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 561a42cc85..4217e133b8 100644 --- a/mobile/openapi/lib/model/asset_response_dto.dart +++ b/mobile/openapi/lib/model/asset_response_dto.dart @@ -36,7 +36,6 @@ class AssetResponseDto { this.owner, required this.ownerId, this.people = const [], - required this.resized, this.smartInfo, this.stack, this.tags = const [], @@ -112,8 +111,6 @@ class AssetResponseDto { List people; - bool resized; - /// /// Please note: This property should have been non-nullable! Since the specification file /// does not include a default value (using the "default:" property), however, the generated @@ -159,7 +156,6 @@ class AssetResponseDto { other.owner == owner && other.ownerId == ownerId && _deepEquality.equals(other.people, people) && - other.resized == resized && other.smartInfo == smartInfo && other.stack == stack && _deepEquality.equals(other.tags, tags) && @@ -194,7 +190,6 @@ class AssetResponseDto { (owner == null ? 0 : owner!.hashCode) + (ownerId.hashCode) + (people.hashCode) + - (resized.hashCode) + (smartInfo == null ? 0 : smartInfo!.hashCode) + (stack == null ? 0 : stack!.hashCode) + (tags.hashCode) + @@ -204,7 +199,7 @@ class AssetResponseDto { (updatedAt.hashCode); @override - String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duplicateId=$duplicateId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, isFavorite=$isFavorite, isOffline=$isOffline, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalMimeType=$originalMimeType, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, smartInfo=$smartInfo, stack=$stack, tags=$tags, thumbhash=$thumbhash, type=$type, unassignedFaces=$unassignedFaces, updatedAt=$updatedAt]'; + String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duplicateId=$duplicateId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, isFavorite=$isFavorite, isOffline=$isOffline, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalMimeType=$originalMimeType, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, smartInfo=$smartInfo, stack=$stack, tags=$tags, thumbhash=$thumbhash, type=$type, unassignedFaces=$unassignedFaces, updatedAt=$updatedAt]'; Map toJson() { final json = {}; @@ -255,7 +250,6 @@ class AssetResponseDto { } json[r'ownerId'] = this.ownerId; json[r'people'] = this.people; - json[r'resized'] = this.resized; if (this.smartInfo != null) { json[r'smartInfo'] = this.smartInfo; } else { @@ -309,7 +303,6 @@ class AssetResponseDto { owner: UserResponseDto.fromJson(json[r'owner']), ownerId: mapValueOfType(json, r'ownerId')!, people: PersonWithFacesResponseDto.listFromJson(json[r'people']), - resized: mapValueOfType(json, r'resized')!, smartInfo: SmartInfoResponseDto.fromJson(json[r'smartInfo']), stack: AssetStackResponseDto.fromJson(json[r'stack']), tags: TagResponseDto.listFromJson(json[r'tags']), @@ -380,7 +373,6 @@ class AssetResponseDto { 'originalFileName', 'originalPath', 'ownerId', - 'resized', 'thumbhash', 'type', 'updatedAt', diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 02a887370a..2137bf7b11 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -8335,9 +8335,6 @@ }, "type": "array" }, - "resized": { - "type": "boolean" - }, "smartInfo": { "$ref": "#/components/schemas/SmartInfoResponseDto" }, @@ -8390,7 +8387,6 @@ "originalFileName", "originalPath", "ownerId", - "resized", "thumbhash", "type", "updatedAt" diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 9642f4c817..bf0c63c2b8 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -229,7 +229,6 @@ export type AssetResponseDto = { owner?: UserResponseDto; ownerId: string; people?: PersonWithFacesResponseDto[]; - resized: boolean; smartInfo?: SmartInfoResponseDto; stack?: (AssetStackResponseDto) | null; tags?: TagResponseDto[]; diff --git a/server/src/dtos/asset-response.dto.ts b/server/src/dtos/asset-response.dto.ts index 332f258d49..caeae2971a 100644 --- a/server/src/dtos/asset-response.dto.ts +++ b/server/src/dtos/asset-response.dto.ts @@ -14,7 +14,6 @@ import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { AssetType } from 'src/enum'; -import { getAssetFiles } from 'src/utils/asset.util'; import { mimeTypes } from 'src/utils/mime-types'; export class SanitizedAssetResponseDto { @@ -23,7 +22,6 @@ export class SanitizedAssetResponseDto { type!: AssetType; thumbhash!: string | null; originalMimeType?: string; - resized!: boolean; localDateTime!: Date; duration!: string; livePhotoVideoId?: string | null; @@ -112,7 +110,6 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As originalMimeType: mimeTypes.lookup(entity.originalFileName), thumbhash: entity.thumbhash?.toString('base64') ?? null, localDateTime: entity.localDateTime, - resized: !!getAssetFiles(entity.files).previewFile, duration: entity.duration ?? '0:00:00.00000', livePhotoVideoId: entity.livePhotoVideoId, hasMetadata: false, @@ -131,7 +128,6 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As originalPath: entity.originalPath, originalFileName: entity.originalFileName, originalMimeType: mimeTypes.lookup(entity.originalFileName), - resized: !!getAssetFiles(entity.files).previewFile, thumbhash: entity.thumbhash?.toString('base64') ?? null, fileCreatedAt: entity.fileCreatedAt, fileModifiedAt: entity.fileModifiedAt, diff --git a/server/src/queries/asset.repository.sql b/server/src/queries/asset.repository.sql index fd5dc15c0a..b08130b183 100644 --- a/server/src/queries/asset.repository.sql +++ b/server/src/queries/asset.repository.sql @@ -598,12 +598,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", @@ -665,7 +659,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" @@ -692,7 +685,6 @@ SELECT )::timestamptz AS "timeBucket" 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" @@ -744,12 +736,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", @@ -811,7 +797,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" @@ -865,12 +850,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", @@ -932,7 +911,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" @@ -964,7 +942,6 @@ SELECT DISTINCT c.city AS "value" FROM "assets" "asset" - LEFT JOIN "asset_files" "files" ON "files"."assetId" = "asset"."id" INNER JOIN "exif" "e" ON "asset"."id" = e."assetId" INNER JOIN "cities" "c" ON c.city = "e"."city" WHERE @@ -995,7 +972,6 @@ SELECT DISTINCT unnest("si"."tags") AS "value" FROM "assets" "asset" - LEFT JOIN "asset_files" "files" ON "files"."assetId" = "asset"."id" INNER JOIN "smart_info" "si" ON "asset"."id" = si."assetId" INNER JOIN "random_tags" "t" ON "si"."tags" @> 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()),