From d386f6ca5f86ff43c29a0f3c31a8843028ff78a6 Mon Sep 17 00:00:00 2001 From: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Date: Mon, 16 Feb 2026 15:16:08 +0100 Subject: [PATCH 1/2] fix(web): clear unsaved asset description when changing asset --- .../detail-panel-description.spec.ts | 65 +++++++++++++++++++ .../detail-panel-description.svelte | 7 +- 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 web/src/lib/components/asset-viewer/detail-panel-description.spec.ts diff --git a/web/src/lib/components/asset-viewer/detail-panel-description.spec.ts b/web/src/lib/components/asset-viewer/detail-panel-description.spec.ts new file mode 100644 index 0000000000000..3175bd819463d --- /dev/null +++ b/web/src/lib/components/asset-viewer/detail-panel-description.spec.ts @@ -0,0 +1,65 @@ +import { assetFactory } from '@test-data/factories/asset-factory'; +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/svelte'; +import userEvent from '@testing-library/user-event'; +import DetailPanelDescription from './detail-panel-description.svelte'; + +describe('DetailPanelDescription', () => { + it('clears unsaved draft on asset change', async () => { + const user = userEvent.setup(); + + const assetA = assetFactory.build({ + id: 'asset-a', + exifInfo: { description: '' }, + }); + const assetB = assetFactory.build({ + id: 'asset-b', + exifInfo: { description: '' }, + }); + + const { rerender } = render(DetailPanelDescription, { + props: { + asset: assetA, + isOwner: true, + }, + }); + + const textarea = screen.getByTestId('autogrow-textarea') as HTMLTextAreaElement; + await user.type(textarea, 'unsaved draft'); + expect(textarea).toHaveValue('unsaved draft'); + + await rerender({ + asset: assetB, + isOwner: true, + }); + + expect(screen.getByTestId('autogrow-textarea')).toHaveValue(''); + }); + + it('updates description on asset switch', async () => { + const assetA = assetFactory.build({ + id: 'asset-a', + exifInfo: { description: 'first description' }, + }); + const assetB = assetFactory.build({ + id: 'asset-b', + exifInfo: { description: 'second description' }, + }); + + const { rerender } = render(DetailPanelDescription, { + props: { + asset: assetA, + isOwner: true, + }, + }); + + expect(screen.getByTestId('autogrow-textarea')).toHaveValue('first description'); + + await rerender({ + asset: assetB, + isOwner: true, + }); + + expect(screen.getByTestId('autogrow-textarea')).toHaveValue('second description'); + }); +}); diff --git a/web/src/lib/components/asset-viewer/detail-panel-description.svelte b/web/src/lib/components/asset-viewer/detail-panel-description.svelte index bc3929f3dd4b5..7af9a438def2e 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-description.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-description.svelte @@ -14,7 +14,12 @@ let { asset, isOwner }: Props = $props(); let currentDescription = $derived(asset.exifInfo?.description ?? ''); - let description = $derived(currentDescription); + let description = $state(''); + + $effect.pre(() => { + void asset.id; + description = currentDescription; + }); const handleFocusOut = async () => { if (description === currentDescription) { From 80a04be3052bd340c0bb5648b24464eb2a3ed013 Mon Sep 17 00:00:00 2001 From: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Date: Mon, 16 Feb 2026 16:09:37 +0100 Subject: [PATCH 2/2] remove unneeded $derived --- .../asset-viewer/detail-panel-description.svelte | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/web/src/lib/components/asset-viewer/detail-panel-description.svelte b/web/src/lib/components/asset-viewer/detail-panel-description.svelte index 7af9a438def2e..9aeb7855b6045 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-description.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-description.svelte @@ -13,15 +13,10 @@ let { asset, isOwner }: Props = $props(); - let currentDescription = $derived(asset.exifInfo?.description ?? ''); - let description = $state(''); - - $effect.pre(() => { - void asset.id; - description = currentDescription; - }); + let description = $derived(asset.exifInfo?.description ?? ''); const handleFocusOut = async () => { + const currentDescription = asset.exifInfo?.description ?? ''; if (description === currentDescription) { return; }