diff --git a/src/lib/components/CardAdd.svelte b/src/lib/components/CardAdd.svelte index 7ddaff4..5a86fa5 100644 --- a/src/lib/components/CardAdd.svelte +++ b/src/lib/components/CardAdd.svelte @@ -113,7 +113,7 @@ export async function show_local_image(){ } const result = await response.json(); - uploaded_image_filename = result.unhashedFilename; + uploaded_image_filename = result.filename; upload_error = ""; } catch (error: any) { diff --git a/src/routes/[recipeLang=recipeLang]/edit/[name]/+page.server.ts b/src/routes/[recipeLang=recipeLang]/edit/[name]/+page.server.ts index b0da09e..5569b9f 100644 --- a/src/routes/[recipeLang=recipeLang]/edit/[name]/+page.server.ts +++ b/src/routes/[recipeLang=recipeLang]/edit/[name]/+page.server.ts @@ -4,7 +4,7 @@ import { Recipe } from '$models/Recipe'; import { dbConnect } from '$utils/db'; import { invalidateRecipeCaches } from '$lib/server/cache'; import { IMAGE_DIR } from '$env/static/private'; -import { rename, access } from 'fs/promises'; +import { rename, access, unlink } from 'fs/promises'; import { join } from 'path'; import { constants } from 'fs'; import { @@ -14,6 +14,43 @@ import { detectChangedFields } from '$utils/recipeFormHelpers'; +/** + * Delete recipe image files from all directories (full, thumb, placeholder) + * Handles both hashed and unhashed versions for backward compatibility + */ +async function deleteRecipeImage(filename: string): Promise { + if (!filename) return; + + const imageDirectories = ['full', 'thumb', 'placeholder']; + + // Extract basename to handle both hashed and unhashed versions + const basename = filename + .replace(/\.[a-f0-9]{8}\.webp$/, '') // Remove hash if present + .replace(/\.webp$/, ''); // Remove extension + + const unhashedFilename = basename + '.webp'; + + for (const dir of imageDirectories) { + // Delete hashed version (if it's the hashed filename that was passed in) + if (filename !== unhashedFilename) { + try { + await unlink(join(IMAGE_DIR, 'rezepte', dir, filename)); + console.log(`Deleted hashed image: ${dir}/${filename}`); + } catch (err) { + console.warn(`Could not delete hashed image ${dir}/${filename}:`, err); + } + } + + // Delete unhashed version + try { + await unlink(join(IMAGE_DIR, 'rezepte', dir, unhashedFilename)); + console.log(`Deleted unhashed image: ${dir}/${unhashedFilename}`); + } catch (err) { + console.warn(`Could not delete unhashed image ${dir}/${unhashedFilename}:`, err); + } + } +} + export const load: PageServerLoad = async ({ fetch, params, locals}) => { // Edit is German-only - redirect to German version if (params.recipeLang === 'recipes') { @@ -79,7 +116,11 @@ export const actions = { const existingImagePath = formData.get('existing_image_path')?.toString(); if (uploadedImage) { - // New image uploaded - use it + // New image uploaded - delete old image files and use new one + if (existingImagePath && existingImagePath !== uploadedImage) { + await deleteRecipeImage(existingImagePath); + } + recipeData.images = [{ mediapath: uploadedImage, alt: existingImagePath ? (recipeData.images?.[0]?.alt || '') : '',