Update MkUploaderDialog.vue

This commit is contained in:
syuilo 2025-05-30 19:03:12 +09:00
parent 12a3000a64
commit 02255efa4f
1 changed files with 21 additions and 13 deletions

View File

@ -297,9 +297,9 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
icon: 'ti ti-sparkles', icon: 'ti ti-sparkles',
text: i18n.ts._imageEffector.title, text: i18n.ts._imageEffector.title,
action: async () => { action: async () => {
const img = await getImageElement(item.file); const imgElementCtx = await getImageElement(item.file);
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkImageEffectorDialog.vue')), { const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkImageEffectorDialog.vue')), {
image: img, image: imgElementCtx.img,
}, { }, {
ok: (file) => { ok: (file) => {
URL.revokeObjectURL(item.thumbnail); URL.revokeObjectURL(item.thumbnail);
@ -314,7 +314,7 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
}); });
}, },
closed: () => { closed: () => {
URL.revokeObjectURL(img.src); imgElementCtx.dispose();
dispose(); dispose();
}, },
}); });
@ -353,16 +353,16 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
icon: 'ti ti-plus', icon: 'ti ti-plus',
text: i18n.ts.add, text: i18n.ts.add,
action: async () => { action: async () => {
const img = await getImageElement(item.file); const imgElementCtx = await getImageElement(item.file);
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), { const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), {
image: img, image: imgElementCtx.img,
}, { }, {
ok: (preset) => { ok: (preset) => {
prefer.commit('watermarkPresets', [...prefer.s.watermarkPresets, preset]); prefer.commit('watermarkPresets', [...prefer.s.watermarkPresets, preset]);
changeWatermarkPreset(preset.id); changeWatermarkPreset(preset.id);
}, },
closed: () => { closed: () => {
URL.revokeObjectURL(img.src); imgElementCtx.dispose();
dispose(); dispose();
}, },
}); });
@ -515,12 +515,20 @@ async function chooseFile(ev: MouseEvent) {
} }
} }
function getImageElement(file: Blob | File): Promise<HTMLImageElement> { /**
* 使用後は dispose() でメモリの解放を忘れないように
*/
function getImageElement(file: Blob | File): Promise<{ img: HTMLImageElement, dispose: () => void }> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const img = new Image(); const img = new Image();
img.onload = () => { img.onload = () => {
resolve(img); resolve({
img: markRaw(img),
dispose: () => {
URL.revokeObjectURL(img.src);
},
});
}; };
img.onerror = (error) => { img.onerror = (error) => {
@ -535,7 +543,7 @@ async function preprocess(item: (typeof items)['value'][number]): Promise<void>
item.preprocessing = true; item.preprocessing = true;
let file: Blob | File = item.file; let file: Blob | File = item.file;
const img = await getImageElement(file); const imgElementCtx = await getImageElement(file);
const needsWatermark = item.watermarkPresetId != null && WATERMARK_SUPPORTED_TYPES.includes(file.type); const needsWatermark = item.watermarkPresetId != null && WATERMARK_SUPPORTED_TYPES.includes(file.type);
const preset = prefer.s.watermarkPresets.find(p => p.id === item.watermarkPresetId); const preset = prefer.s.watermarkPresets.find(p => p.id === item.watermarkPresetId);
@ -543,9 +551,9 @@ async function preprocess(item: (typeof items)['value'][number]): Promise<void>
const canvas = window.document.createElement('canvas'); const canvas = window.document.createElement('canvas');
const renderer = new WatermarkRenderer({ const renderer = new WatermarkRenderer({
canvas: canvas, canvas: canvas,
renderWidth: img.width, renderWidth: imgElementCtx.img.width,
renderHeight: img.height, renderHeight: imgElementCtx.img.height,
image: img, image: imgElementCtx.img,
}); });
await renderer.setLayers(preset.layers); await renderer.setLayers(preset.layers);
@ -596,7 +604,7 @@ async function preprocess(item: (typeof items)['value'][number]): Promise<void>
item.preprocessedFile = markRaw(file); item.preprocessedFile = markRaw(file);
item.preprocessing = false; item.preprocessing = false;
URL.revokeObjectURL(img.src); imgElementCtx.dispose();
} }
function initializeFile(file: File) { function initializeFile(file: File) {