From 7fbf50a75e567ed4a9c5243532499efd383576ce Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Thu, 22 Aug 2024 23:24:49 -0400 Subject: [PATCH] fix: remove `asset.resized` (#11983) fix: remove resized --- e2e/src/api/specs/asset.e2e-spec.ts | 10 ---- .../openapi/lib/model/asset_response_dto.dart | Bin 13366 -> 13135 bytes open-api/immich-openapi-specs.json | 4 -- open-api/typescript-sdk/src/fetch-client.ts | 1 - server/src/dtos/asset-response.dto.ts | 4 -- server/src/queries/asset.repository.sql | 45 ------------------ server/src/repositories/asset.repository.ts | 5 +- server/test/fixtures/shared-link.stub.ts | 2 - .../asset-viewer/asset-viewer.svelte | 21 +++----- .../asset-viewer/photo-viewer.svelte | 10 ++-- .../lib/components/assets/broken-asset.svelte | 25 ++++++++++ .../assets/thumbnail/image-thumbnail.svelte | 16 +++---- .../assets/thumbnail/thumbnail.svelte | 23 ++++----- .../covers/__tests__/share-cover.spec.ts | 6 ++- .../covers/asset-cover.svelte | 25 ++++++---- .../covers/share-cover.svelte | 4 +- .../sharedlinks-page/shared-link-card.svelte | 2 +- web/src/test-data/factories/asset-factory.ts | 1 - 18 files changed, 77 insertions(+), 127 deletions(-) create mode 100644 web/src/lib/components/assets/broken-asset.svelte diff --git a/e2e/src/api/specs/asset.e2e-spec.ts b/e2e/src/api/specs/asset.e2e-spec.ts index 99b33dfed8..82ce17865a 100644 --- a/e2e/src/api/specs/asset.e2e-spec.ts +++ b/e2e/src/api/specs/asset.e2e-spec.ts @@ -843,7 +843,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: '8bit-sRGB.avif', - resized: true, exifInfo: { description: '', exifImageHeight: 1080, @@ -859,7 +858,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: 'el_torcal_rocks.jpg', - resized: true, exifInfo: { dateTimeOriginal: '2012-08-05T11:39:59.000Z', exifImageWidth: 512, @@ -883,7 +881,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: '8bit-sRGB.jxl', - resized: true, exifInfo: { description: '', exifImageHeight: 1080, @@ -899,7 +896,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: 'IMG_2682.heic', - resized: true, fileCreatedAt: '2019-03-21T16:04:22.348Z', exifInfo: { dateTimeOriginal: '2019-03-21T16:04:22.348Z', @@ -924,7 +920,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: 'density_plot.png', - resized: true, exifInfo: { exifImageWidth: 800, exifImageHeight: 800, @@ -939,7 +934,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: 'glarus.nef', - resized: true, fileCreatedAt: '2010-07-20T17:27:12.000Z', exifInfo: { make: 'NIKON CORPORATION', @@ -961,7 +955,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: 'philadelphia.nef', - resized: true, fileCreatedAt: '2016-09-22T22:10:29.060Z', exifInfo: { make: 'NIKON CORPORATION', @@ -984,7 +977,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: '4_3.rw2', - resized: true, fileCreatedAt: '2018-05-10T08:42:37.842Z', exifInfo: { make: 'Panasonic', @@ -1008,7 +1000,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: '12bit-compressed-(3_2).arw', - resized: true, fileCreatedAt: '2016-09-27T10:51:44.000Z', exifInfo: { make: 'SONY', @@ -1033,7 +1024,6 @@ describe('/asset', () => { expected: { type: AssetTypeEnum.Image, originalFileName: '14bit-uncompressed-(3_2).arw', - resized: true, fileCreatedAt: '2016-01-08T14:08:01.000Z', exifInfo: { make: 'SONY', diff --git a/mobile/openapi/lib/model/asset_response_dto.dart b/mobile/openapi/lib/model/asset_response_dto.dart index 561a42cc852cfa7375c2bc5a0ca475bde8a7d4e7..4217e133b8c3462575ae7c8e92f4af406115e266 100644 GIT binary patch delta 51 zcmV-30L=fkXwPP_1_ZMq1WO0AwFzATv)T;U1hdi+fCRH^7F+|f*%@F5vtS{J39}+A J)CiLWG%*H~64L+x delta 179 zcmX?~wk=}=8_VQ*EPU)msl}O9sVSRS0@-^$` zM0~QKi121Mu^46ns5)B}nC=A0Bz8pwg{ ARRAY[t.tag] WHERE @@ -1038,12 +1014,6 @@ SELECT "asset"."sidecarPath" AS "asset_sidecarPath", "asset"."stackId" AS "asset_stackId", "asset"."duplicateId" AS "asset_duplicateId", - "files"."id" AS "files_id", - "files"."assetId" AS "files_assetId", - "files"."createdAt" AS "files_createdAt", - "files"."updatedAt" AS "files_updatedAt", - "files"."type" AS "files_type", - "files"."path" AS "files_path", "exifInfo"."assetId" AS "exifInfo_assetId", "exifInfo"."description" AS "exifInfo_description", "exifInfo"."exifImageWidth" AS "exifInfo_exifImageWidth", @@ -1078,7 +1048,6 @@ SELECT "stack"."primaryAssetId" AS "stack_primaryAssetId" FROM "assets" "asset" - LEFT JOIN "asset_files" "files" ON "files"."assetId" = "asset"."id" LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "asset"."id" LEFT JOIN "asset_stack" "stack" ON "stack"."id" = "asset"."stackId" WHERE @@ -1120,12 +1089,6 @@ SELECT "asset"."sidecarPath" AS "asset_sidecarPath", "asset"."stackId" AS "asset_stackId", "asset"."duplicateId" AS "asset_duplicateId", - "files"."id" AS "files_id", - "files"."assetId" AS "files_assetId", - "files"."createdAt" AS "files_createdAt", - "files"."updatedAt" AS "files_updatedAt", - "files"."type" AS "files_type", - "files"."path" AS "files_path", "exifInfo"."assetId" AS "exifInfo_assetId", "exifInfo"."description" AS "exifInfo_description", "exifInfo"."exifImageWidth" AS "exifInfo_exifImageWidth", @@ -1160,7 +1123,6 @@ SELECT "stack"."primaryAssetId" AS "stack_primaryAssetId" FROM "assets" "asset" - LEFT JOIN "asset_files" "files" ON "files"."assetId" = "asset"."id" LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "asset"."id" LEFT JOIN "asset_stack" "stack" ON "stack"."id" = "asset"."stackId" WHERE @@ -1197,12 +1159,6 @@ SELECT "asset"."sidecarPath" AS "asset_sidecarPath", "asset"."stackId" AS "asset_stackId", "asset"."duplicateId" AS "asset_duplicateId", - "files"."id" AS "files_id", - "files"."assetId" AS "files_assetId", - "files"."createdAt" AS "files_createdAt", - "files"."updatedAt" AS "files_updatedAt", - "files"."type" AS "files_type", - "files"."path" AS "files_path", "exifInfo"."assetId" AS "exifInfo_assetId", "exifInfo"."description" AS "exifInfo_description", "exifInfo"."exifImageWidth" AS "exifInfo_exifImageWidth", @@ -1264,7 +1220,6 @@ SELECT "stackedAssets"."duplicateId" AS "stackedAssets_duplicateId" FROM "assets" "asset" - LEFT JOIN "asset_files" "files" ON "files"."assetId" = "asset"."id" LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "asset"."id" LEFT JOIN "asset_stack" "stack" ON "stack"."id" = "asset"."stackId" LEFT JOIN "assets" "stackedAssets" ON "stackedAssets"."stackId" = "stack"."id" diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index 50ed724f9f..b95db5f3a8 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -710,10 +710,7 @@ export class AssetRepository implements IAssetRepository { } private getBuilder(options: AssetBuilderOptions) { - const builder = this.repository - .createQueryBuilder('asset') - .where('asset.isVisible = true') - .leftJoinAndSelect('asset.files', 'files'); + const builder = this.repository.createQueryBuilder('asset').where('asset.isVisible = true'); if (options.assetType !== undefined) { builder.andWhere('asset.type = :assetType', { assetType: options.assetType }); diff --git a/server/test/fixtures/shared-link.stub.ts b/server/test/fixtures/shared-link.stub.ts index 9ea252b5f7..54898d8693 100644 --- a/server/test/fixtures/shared-link.stub.ts +++ b/server/test/fixtures/shared-link.stub.ts @@ -54,7 +54,6 @@ const assetResponse: AssetResponseDto = { originalMimeType: 'image/jpeg', originalPath: 'fake_path/jpeg', originalFileName: 'asset_1.jpeg', - resized: false, thumbhash: null, fileModifiedAt: today, isOffline: false, @@ -82,7 +81,6 @@ const assetResponseWithoutMetadata = { id: 'id_1', type: AssetType.VIDEO, originalMimeType: 'image/jpeg', - resized: false, thumbhash: null, localDateTime: today, duration: '0:00:00.00000', diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte index 3ed955848b..4e98546069 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte @@ -4,9 +4,9 @@ import MotionPhotoAction from '$lib/components/asset-viewer/actions/motion-photo-action.svelte'; import NextAssetAction from '$lib/components/asset-viewer/actions/next-asset-action.svelte'; import PreviousAssetAction from '$lib/components/asset-viewer/actions/previous-asset-action.svelte'; - import Icon from '$lib/components/elements/icon.svelte'; import { AssetAction, ProjectionType } from '$lib/constants'; import { updateNumberOfComments } from '$lib/stores/activity.store'; + import { closeEditorCofirm } from '$lib/stores/asset-editor.store'; import { assetViewingStore } from '$lib/stores/asset-viewing.store'; import type { AssetStore } from '$lib/stores/assets.store'; import { isShowDetail } from '$lib/stores/preferences.store'; @@ -25,14 +25,13 @@ getActivities, getActivityStatistics, getAllAlbums, + getStack, runAssetJobs, type ActivityResponseDto, type AlbumResponseDto, type AssetResponseDto, - getStack, type StackResponseDto, } from '@immich/sdk'; - import { mdiImageBrokenVariant } from '@mdi/js'; import { createEventDispatcher, onDestroy, onMount } from 'svelte'; import { t } from 'svelte-i18n'; import { fly } from 'svelte/transition'; @@ -42,13 +41,13 @@ import ActivityViewer from './activity-viewer.svelte'; import AssetViewerNavBar from './asset-viewer-nav-bar.svelte'; import DetailPanel from './detail-panel.svelte'; + import CropArea from './editor/crop-tool/crop-area.svelte'; + import EditorPanel from './editor/editor-panel.svelte'; import PanoramaViewer from './panorama-viewer.svelte'; import PhotoViewer from './photo-viewer.svelte'; import SlideshowBar from './slideshow-bar.svelte'; import VideoViewer from './video-wrapper-viewer.svelte'; - import EditorPanel from './editor/editor-panel.svelte'; - import CropArea from './editor/crop-tool/crop-area.svelte'; - import { closeEditorCofirm } from '$lib/stores/asset-editor.store'; + export let assetStore: AssetStore | null = null; export let asset: AssetResponseDto; export let preloadAssets: AssetResponseDto[] = []; @@ -481,15 +480,7 @@ {/key} {:else} {#key asset.id} - {#if !asset.resized} -
-
- -
-
- {:else if asset.type === AssetTypeEnum.Image} + {#if asset.type === AssetTypeEnum.Image} {#if shouldPlayMotionPhoto && asset.livePhotoVideoId} import { shortcuts } from '$lib/actions/shortcut'; + import { zoomImageAction, zoomed } from '$lib/actions/zoom-image'; + import BrokenAsset from '$lib/components/assets/broken-asset.svelte'; import { photoViewer } from '$lib/stores/assets.store'; import { boundingBoxesArray } from '$lib/stores/people.store'; import { alwaysLoadOriginalFile } from '$lib/stores/preferences.store'; @@ -9,15 +11,13 @@ import { isWebCompatibleImage } from '$lib/utils/asset-utils'; import { getBoundingBox } from '$lib/utils/people-utils'; import { getAltText } from '$lib/utils/thumbnail-util'; - import { AssetTypeEnum, type AssetResponseDto, AssetMediaSize, type SharedLinkResponseDto } from '@immich/sdk'; - import { zoomImageAction, zoomed } from '$lib/actions/zoom-image'; + import { AssetMediaSize, AssetTypeEnum, type AssetResponseDto, type SharedLinkResponseDto } from '@immich/sdk'; import { canCopyImagesToClipboard, copyImageToClipboard } from 'copy-image-clipboard'; import { onDestroy, onMount } from 'svelte'; - + import { t } from 'svelte-i18n'; import { fade } from 'svelte/transition'; import LoadingSpinner from '../shared-components/loading-spinner.svelte'; import { NotificationType, notificationController } from '../shared-components/notification/notification'; - import { t } from 'svelte-i18n'; export let asset: AssetResponseDto; export let preloadAssets: AssetResponseDto[] | undefined = undefined; @@ -137,7 +137,7 @@ ]} /> {#if imageError} -
{$t('error_loading_image')}
+ {/if} diff --git a/web/src/lib/components/assets/broken-asset.svelte b/web/src/lib/components/assets/broken-asset.svelte new file mode 100644 index 0000000000..216a8f6f84 --- /dev/null +++ b/web/src/lib/components/assets/broken-asset.svelte @@ -0,0 +1,25 @@ + + +
+
+ + {#if !noMessage} +
{$t('error_loading_image')}
+ {/if} +
+
+ +
+
+
diff --git a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte index e03dd35653..38f2ff4dbb 100644 --- a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte @@ -1,12 +1,12 @@ {#if errored} -
- -
+ +
{$t('error_loading_image')}
+
{:else} {/if} - {#if asset.resized} - (loaded = true)} - /> - {:else} -
- -
- {/if} + (loaded = true)} + /> {#if asset.type === AssetTypeEnum.Video}
diff --git a/web/src/lib/components/sharedlinks-page/covers/__tests__/share-cover.spec.ts b/web/src/lib/components/sharedlinks-page/covers/__tests__/share-cover.spec.ts index 1f1fa65cf8..2952498b1a 100644 --- a/web/src/lib/components/sharedlinks-page/covers/__tests__/share-cover.spec.ts +++ b/web/src/lib/components/sharedlinks-page/covers/__tests__/share-cover.spec.ts @@ -47,13 +47,15 @@ describe('ShareCover component', () => { expect(img.className).toBe('z-0 rounded-xl object-cover aspect-square text'); }); - it('renders fallback image when asset is not resized', () => { - const link = sharedLinkFactory.build({ assets: [assetFactory.build({ resized: false })] }); + it.skip('renders fallback image when asset is not resized', () => { + const link = sharedLinkFactory.build({ assets: [assetFactory.build()] }); render(ShareCover, { link: link, preload: false, }); + // TODO emit image error event and check if fallback image is rendered + const img = screen.getByTestId('album-image'); expect(img.alt).toBe('unnamed_share'); }); diff --git a/web/src/lib/components/sharedlinks-page/covers/asset-cover.svelte b/web/src/lib/components/sharedlinks-page/covers/asset-cover.svelte index b8335be6b0..69c11e079c 100644 --- a/web/src/lib/components/sharedlinks-page/covers/asset-cover.svelte +++ b/web/src/lib/components/sharedlinks-page/covers/asset-cover.svelte @@ -1,16 +1,25 @@ - +{#if isBroken} + +{:else} + (isBroken = true)} + class="z-0 rounded-xl object-cover aspect-square {className}" + data-testid="album-image" + draggable="false" + loading={preload ? 'eager' : 'lazy'} + {src} + /> +{/if} diff --git a/web/src/lib/components/sharedlinks-page/covers/share-cover.svelte b/web/src/lib/components/sharedlinks-page/covers/share-cover.svelte index 3a21a60989..09f32d7dac 100644 --- a/web/src/lib/components/sharedlinks-page/covers/share-cover.svelte +++ b/web/src/lib/components/sharedlinks-page/covers/share-cover.svelte @@ -12,10 +12,10 @@ export { className as class }; -
+
{#if link?.album} - {:else if link.assets[0]?.resized} + {:else if link.assets[0]} - +
diff --git a/web/src/test-data/factories/asset-factory.ts b/web/src/test-data/factories/asset-factory.ts index 5f31b8af44..700b98c180 100644 --- a/web/src/test-data/factories/asset-factory.ts +++ b/web/src/test-data/factories/asset-factory.ts @@ -12,7 +12,6 @@ export const assetFactory = Sync.makeFactory({ originalPath: Sync.each(() => faker.system.filePath()), originalFileName: Sync.each(() => faker.system.fileName()), originalMimeType: Sync.each(() => faker.system.mimeType()), - resized: true, thumbhash: Sync.each(() => faker.string.alphanumeric(28)), fileCreatedAt: Sync.each(() => faker.date.past().toISOString()), fileModifiedAt: Sync.each(() => faker.date.past().toISOString()),