From a1a62b00a06a3b93dd91377c8f2b1e070b7994d0 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 11 Apr 2023 05:23:39 -0500 Subject: [PATCH] feat(server): add originalFileName to asset table (#2231) --- mobile/openapi/doc/AssetResponseDto.md | Bin 1225 -> 1265 bytes mobile/openapi/doc/ExifResponseDto.md | Bin 1272 -> 1228 bytes .../openapi/lib/model/asset_response_dto.dart | Bin 9638 -> 9982 bytes .../openapi/lib/model/exif_response_dto.dart | Bin 10513 -> 10165 bytes .../openapi/test/asset_response_dto_test.dart | Bin 2512 -> 2629 bytes .../openapi/test/exif_response_dto_test.dart | Bin 2510 -> 2407 bytes .../immich/src/api-v1/asset/asset.core.ts | 2 + .../src/api-v1/asset/dto/create-exif.dto.ts | 3 - .../src/modules/download/download.service.ts | 4 +- .../metadata-extraction.processor.ts | 9 +-- server/immich-openapi-specs.json | 9 ++- .../asset/response-dto/asset-response.dto.ts | 3 + .../asset/response-dto/exif-response.dto.ts | 2 - .../storage-template.service.ts | 4 +- server/libs/domain/test/fixtures.ts | 7 +- .../libs/infra/src/entities/asset.entity.ts | 3 + server/libs/infra/src/entities/exif.entity.ts | 4 -- ...4628393-AddOriginalFileNameToAssetTable.ts | 30 +++++++++ ...1159594469-RemoveImageNameFromEXIFTable.ts | 62 ++++++++++++++++++ .../src/repositories/typesense.repository.ts | 6 +- .../src/typesense-schemas/asset.schema.ts | 4 +- web/src/api/open-api/api.ts | 12 ++-- .../asset-viewer/detail-panel.svelte | 2 +- .../assets/thumbnail/thumbnail.svelte | 2 +- 24 files changed, 127 insertions(+), 41 deletions(-) create mode 100644 server/libs/infra/src/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts create mode 100644 server/libs/infra/src/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts diff --git a/mobile/openapi/doc/AssetResponseDto.md b/mobile/openapi/doc/AssetResponseDto.md index 44754a6c4d5042f6c3286c42e310f039b759d2c8..0c8bb3363e8a55c4e3febb444a26e81a162a8652 100644 GIT binary patch delta 29 lcmX@f`H^$O7RJdF7&$oHGILV>5_3~0?_-qMyoFJe833qk3Q+(6 delta 12 Tcmey!d6IL(7RJqY7)6-@C3ghc diff --git a/mobile/openapi/doc/ExifResponseDto.md b/mobile/openapi/doc/ExifResponseDto.md index 7c40bc742aeb7ec5e5a9c86951af3a65accffefb..1fb483d6350897dca6e5a7c5324d84cab52245ec 100644 GIT binary patch delta 12 Tcmeytd4_XCIOFDK#!_YgBDw^Q delta 26 hcmX@Z`Ga#qI3s6fZen_>Ut(_Rx0;Dxk@vZsue0U{ygERj{?i zRO!z7hDiWjHq)$ diff --git a/mobile/openapi/lib/model/exif_response_dto.dart b/mobile/openapi/lib/model/exif_response_dto.dart index 071d8caf70cd8218388ecb36609aaa7b7116925c..0c3ec07461d5717fb6779a4e8d60ceaa42cb2bee 100644 GIT binary patch delta 54 zcmV-60LlN6QngR8z5$c#0SS|@5CyZ~0dfJeXagz&v$q8>1G5_mvjel_3_b&sJ`oAC MuMmR_vvD1u3p$DuasU7T delta 238 zcmdn$KQU;-K1R;W+{E-$zr@_s&6^p!83lt&iZb)k?G@m{lLMKBH~TQlFp0s16l`q~ z@|z=B?V06K2(j$|gVL65Tw5V>7b|T%oNBoVnSP$AKB)kjVxDlG1QV r^;iX4g_4ZSVm+A9qazS{54a??@EK^tkA*Tec diff --git a/mobile/openapi/test/exif_response_dto_test.dart b/mobile/openapi/test/exif_response_dto_test.dart index 63623cd4fefbd20232c11b90911f828225b654b8..138bff96161f9087d280a05cf4273ed18f3ac0e0 100644 GIT binary patch delta 16 YcmX>n{9I_mZ>Gr?n0YtnGsm+506@$Jg#Z8m delta 41 tcmaDZbWV7~Z>GuiOzfPQxrynieu=rMlMk{fu|YVK1K5o>|7Xfz0{}=Q4*CE9 diff --git a/server/apps/immich/src/api-v1/asset/asset.core.ts b/server/apps/immich/src/api-v1/asset/asset.core.ts index 0798d82f74..14261b001e 100644 --- a/server/apps/immich/src/api-v1/asset/asset.core.ts +++ b/server/apps/immich/src/api-v1/asset/asset.core.ts @@ -2,6 +2,7 @@ import { AuthUserDto, IJobRepository, JobName } from '@app/domain'; import { AssetEntity, UserEntity } from '@app/infra/entities'; import { IAssetRepository } from './asset-repository'; import { CreateAssetDto, UploadFile } from './dto/create-asset.dto'; +import { parse } from 'node:path'; export class AssetCore { constructor(private repository: IAssetRepository, private jobRepository: IJobRepository) {} @@ -35,6 +36,7 @@ export class AssetCore { encodedVideoPath: null, tags: [], sharedLinks: [], + originalFileName: parse(file.originalName).name, }); await this.jobRepository.queue({ name: JobName.ASSET_UPLOADED, data: { asset, fileName: file.originalName } }); diff --git a/server/apps/immich/src/api-v1/asset/dto/create-exif.dto.ts b/server/apps/immich/src/api-v1/asset/dto/create-exif.dto.ts index 16a7d6f226..c2594c47ba 100644 --- a/server/apps/immich/src/api-v1/asset/dto/create-exif.dto.ts +++ b/server/apps/immich/src/api-v1/asset/dto/create-exif.dto.ts @@ -10,9 +10,6 @@ export class CreateExifDto { @IsOptional() model?: string; - @IsOptional() - imageName?: string; - @IsOptional() exifImageWidth?: number; diff --git a/server/apps/immich/src/modules/download/download.service.ts b/server/apps/immich/src/modules/download/download.service.ts index d5e800578b..c11377407c 100644 --- a/server/apps/immich/src/modules/download/download.service.ts +++ b/server/apps/immich/src/modules/download/download.service.ts @@ -28,8 +28,8 @@ export class DownloadService { let fileCount = 0; let complete = true; - for (const { id, originalPath, exifInfo } of assets) { - const name = `${exifInfo?.imageName || id}${extname(originalPath)}`; + for (const { originalPath, exifInfo, originalFileName } of assets) { + const name = `${originalFileName}${extname(originalPath)}`; archive.file(originalPath, { name }); totalSize += Number(exifInfo?.fileSizeInByte || 0); fileCount++; diff --git a/server/apps/microservices/src/processors/metadata-extraction.processor.ts b/server/apps/microservices/src/processors/metadata-extraction.processor.ts index 43e1ac98d8..5874a231d6 100644 --- a/server/apps/microservices/src/processors/metadata-extraction.processor.ts +++ b/server/apps/microservices/src/processors/metadata-extraction.processor.ts @@ -1,6 +1,5 @@ import { AssetCore, - getFileNameWithoutExtension, IAssetRepository, IAssetUploadedJob, IBaseJob, @@ -21,7 +20,6 @@ import { ExifDateTime, exiftool, Tags } from 'exiftool-vendored'; import ffmpeg, { FfprobeData } from 'fluent-ffmpeg'; import { Duration } from 'luxon'; import fs from 'node:fs'; -import path from 'path'; import sharp from 'sharp'; import { Repository } from 'typeorm/repository/Repository'; import { promisify } from 'util'; @@ -79,7 +77,7 @@ export class MetadataExtractionProcessor { : await this.assetRepository.getWithout(WithoutProperty.EXIF); for (const asset of assets) { - const fileName = asset.exifInfo?.imageName ?? getFileNameWithoutExtension(asset.originalPath); + const fileName = asset.originalFileName; const name = asset.type === AssetType.VIDEO ? JobName.EXTRACT_VIDEO_METADATA : JobName.EXIF_EXTRACTION; await this.jobRepository.queue({ name, data: { asset, fileName } }); } @@ -92,7 +90,6 @@ export class MetadataExtractionProcessor { async extractExifInfo(job: Job) { try { let asset = job.data.asset; - const fileName = job.data.fileName; const exifData = await exiftool.read(asset.originalPath).catch((e) => { this.logger.warn(`The exifData parsing failed due to: ${e} on file ${asset.originalPath}`); return null; @@ -126,7 +123,6 @@ export class MetadataExtractionProcessor { const newExif = new ExifEntity(); newExif.assetId = asset.id; - newExif.imageName = path.parse(fileName).name; newExif.fileSizeInByte = fileSizeInBytes; newExif.make = exifData?.Make || null; newExif.model = exifData?.Model || null; @@ -191,7 +187,6 @@ export class MetadataExtractionProcessor { @Process({ name: JobName.EXTRACT_VIDEO_METADATA, concurrency: 2 }) async extractVideoMetadata(job: Job) { let asset = job.data.asset; - const fileName = job.data.fileName; if (!asset.isVisible) { return; @@ -219,7 +214,6 @@ export class MetadataExtractionProcessor { const newExif = new ExifEntity(); newExif.assetId = asset.id; newExif.description = ''; - newExif.imageName = path.parse(fileName).name || null; newExif.fileSizeInByte = data.format.size || null; newExif.dateTimeOriginal = fileCreatedAt ? new Date(fileCreatedAt) : null; newExif.modifyDate = null; @@ -242,7 +236,6 @@ export class MetadataExtractionProcessor { if (photoAsset) { await this.assetCore.save({ id: photoAsset.id, livePhotoVideoId: asset.id }); await this.assetCore.save({ id: asset.id, isVisible: false }); - newExif.imageName = (photoAsset.exifInfo as ExifEntity).imageName; } } diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index 7318739e24..c699528caa 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -3548,11 +3548,6 @@ "nullable": true, "default": null }, - "imageName": { - "type": "string", - "nullable": true, - "default": null - }, "exifImageWidth": { "type": "number", "nullable": true, @@ -3712,6 +3707,9 @@ "originalPath": { "type": "string" }, + "originalFileName": { + "type": "string" + }, "resizePath": { "type": "string", "nullable": true @@ -3767,6 +3765,7 @@ "ownerId", "deviceId", "originalPath", + "originalFileName", "resizePath", "fileCreatedAt", "fileModifiedAt", diff --git a/server/libs/domain/src/asset/response-dto/asset-response.dto.ts b/server/libs/domain/src/asset/response-dto/asset-response.dto.ts index d057dabad2..041aef5829 100644 --- a/server/libs/domain/src/asset/response-dto/asset-response.dto.ts +++ b/server/libs/domain/src/asset/response-dto/asset-response.dto.ts @@ -13,6 +13,7 @@ export class AssetResponseDto { @ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType }) type!: AssetType; originalPath!: string; + originalFileName!: string; resizePath!: string | null; fileCreatedAt!: string; fileModifiedAt!: string; @@ -36,6 +37,7 @@ export function mapAsset(entity: AssetEntity): AssetResponseDto { deviceId: entity.deviceId, type: entity.type, originalPath: entity.originalPath, + originalFileName: entity.originalFileName, resizePath: entity.resizePath, fileCreatedAt: entity.fileCreatedAt, fileModifiedAt: entity.fileModifiedAt, @@ -60,6 +62,7 @@ export function mapAssetWithoutExif(entity: AssetEntity): AssetResponseDto { deviceId: entity.deviceId, type: entity.type, originalPath: entity.originalPath, + originalFileName: entity.originalFileName, resizePath: entity.resizePath, fileCreatedAt: entity.fileCreatedAt, fileModifiedAt: entity.fileModifiedAt, diff --git a/server/libs/domain/src/asset/response-dto/exif-response.dto.ts b/server/libs/domain/src/asset/response-dto/exif-response.dto.ts index 83961a1960..cac1d24686 100644 --- a/server/libs/domain/src/asset/response-dto/exif-response.dto.ts +++ b/server/libs/domain/src/asset/response-dto/exif-response.dto.ts @@ -4,7 +4,6 @@ import { ApiProperty } from '@nestjs/swagger'; export class ExifResponseDto { make?: string | null = null; model?: string | null = null; - imageName?: string | null = null; exifImageWidth?: number | null = null; exifImageHeight?: number | null = null; @@ -30,7 +29,6 @@ export function mapExif(entity: ExifEntity): ExifResponseDto { return { make: entity.make, model: entity.model, - imageName: entity.imageName, exifImageWidth: entity.exifImageWidth, exifImageHeight: entity.exifImageHeight, fileSizeInByte: entity.fileSizeInByte ? parseInt(entity.fileSizeInByte.toString()) : null, diff --git a/server/libs/domain/src/storage-template/storage-template.service.ts b/server/libs/domain/src/storage-template/storage-template.service.ts index b6df125c18..ff188d29e1 100644 --- a/server/libs/domain/src/storage-template/storage-template.service.ts +++ b/server/libs/domain/src/storage-template/storage-template.service.ts @@ -26,7 +26,7 @@ export class StorageTemplateService { const { asset } = data; try { - const filename = asset.exifInfo?.imageName || asset.id; + const filename = asset.originalFileName || asset.id; await this.moveAsset(asset, filename); // move motion part of live photo @@ -56,7 +56,7 @@ export class StorageTemplateService { for (const asset of assets) { const livePhotoParentAsset = livePhotoMap[asset.id]; // TODO: remove livePhoto specific stuff once upload is fixed - const filename = asset.exifInfo?.imageName || livePhotoParentAsset?.exifInfo?.imageName || asset.id; + const filename = asset.originalFileName || livePhotoParentAsset?.originalFileName || asset.id; await this.moveAsset(asset, filename); } diff --git a/server/libs/domain/test/fixtures.ts b/server/libs/domain/test/fixtures.ts index af5ca08ec5..00bcfee90e 100644 --- a/server/libs/domain/test/fixtures.ts +++ b/server/libs/domain/test/fixtures.ts @@ -118,6 +118,7 @@ export const fileStub = { export const assetEntityStub = { noResizePath: Object.freeze({ id: 'asset-id', + originalFileName: 'asset_1.jpeg', deviceAssetId: 'device-asset-id', fileModifiedAt: '2023-02-23T05:06:29.716Z', fileCreatedAt: '2023-02-23T05:06:29.716Z', @@ -163,9 +164,11 @@ export const assetEntityStub = { livePhotoVideoId: null, tags: [], sharedLinks: [], + originalFileName: 'asset-id.ext', }), video: Object.freeze({ id: 'asset-id', + originalFileName: 'asset-id.ext', deviceAssetId: 'device-asset-id', fileModifiedAt: '2023-02-23T05:06:29.716Z', fileCreatedAt: '2023-02-23T05:06:29.716Z', @@ -320,7 +323,6 @@ export const albumStub = { const assetInfo: ExifResponseDto = { make: 'camera-make', model: 'camera-model', - imageName: 'fancy-image', exifImageWidth: 500, exifImageHeight: 500, fileSizeInByte: 100, @@ -347,6 +349,7 @@ const assetResponse: AssetResponseDto = { deviceId: 'device_id_1', type: AssetType.VIDEO, originalPath: 'fake_path/jpeg', + originalFileName: 'asset_1.jpeg', resizePath: '', fileModifiedAt: today.toISOString(), fileCreatedAt: today.toISOString(), @@ -602,6 +605,7 @@ export const sharedLinkStub = { isVisible: true, livePhotoVideo: null, livePhotoVideoId: null, + originalFileName: 'asset_1.jpeg', exifInfo: { livePhotoCID: null, assetId: 'id_1', @@ -620,7 +624,6 @@ export const sharedLinkStub = { country: 'country', make: 'camera-make', model: 'camera-model', - imageName: 'fancy-image', lensModel: 'fancy', fNumber: 100, focalLength: 100, diff --git a/server/libs/infra/src/entities/asset.entity.ts b/server/libs/infra/src/entities/asset.entity.ts index ba83e62542..f47e0fec39 100644 --- a/server/libs/infra/src/entities/asset.entity.ts +++ b/server/libs/infra/src/entities/asset.entity.ts @@ -87,6 +87,9 @@ export class AssetEntity { @Column({ nullable: true }) livePhotoVideoId!: string | null; + @Column({ type: 'varchar' }) + originalFileName!: string; + @OneToOne(() => ExifEntity, (exifEntity) => exifEntity.asset) exifInfo?: ExifEntity; diff --git a/server/libs/infra/src/entities/exif.entity.ts b/server/libs/infra/src/entities/exif.entity.ts index 00b57f9e28..d4abd6e6d7 100644 --- a/server/libs/infra/src/entities/exif.entity.ts +++ b/server/libs/infra/src/entities/exif.entity.ts @@ -63,9 +63,6 @@ export class ExifEntity { @Column({ type: 'varchar', nullable: true }) model!: string | null; - @Column({ type: 'varchar', nullable: true }) - imageName!: string | null; - @Column({ type: 'varchar', nullable: true }) lensModel!: string | null; @@ -94,7 +91,6 @@ export class ExifEntity { COALESCE(model, '') || ' ' || COALESCE(orientation, '') || ' ' || COALESCE("lensModel", '') || ' ' || - COALESCE("imageName", '') || ' ' || COALESCE("city", '') || ' ' || COALESCE("state", '') || ' ' || COALESCE("country", ''))`, diff --git a/server/libs/infra/src/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts b/server/libs/infra/src/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts new file mode 100644 index 0000000000..7c547108b5 --- /dev/null +++ b/server/libs/infra/src/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts @@ -0,0 +1,30 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddOriginalFileNameToAssetTable1681144628393 implements MigrationInterface { + name = 'AddOriginalFileNameToAssetTable1681144628393'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "assets" ADD "originalFileName" character varying`); + + await queryRunner.query(` + UPDATE assets a + SET "originalFileName" = ( + select e."imageName" + from exif e + where e."assetId" = a.id + ) + `); + + await queryRunner.query(` + UPDATE assets a + SET "originalFileName" = a.id + where a."originalFileName" IS NULL or a."originalFileName" = '' + `); + + await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "originalFileName" SET NOT NULL`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "assets" DROP COLUMN "originalFileName"`); + } +} diff --git a/server/libs/infra/src/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts b/server/libs/infra/src/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts new file mode 100644 index 0000000000..87bf2a62e6 --- /dev/null +++ b/server/libs/infra/src/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts @@ -0,0 +1,62 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RemoveImageNameFromEXIFTable1681159594469 implements MigrationInterface { + name = 'RemoveImageNameFromEXIFTable1681159594469'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "exif" DROP COLUMN IF EXISTS "exifTextSearchableColumn"`); + await queryRunner.query( + `DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "database" = $3 AND "schema" = $4 AND "table" = $5`, + ['GENERATED_COLUMN', 'exifTextSearchableColumn', 'immich', 'public', 'exif'], + ); + await queryRunner.query(`ALTER TABLE "exif" ADD "exifTextSearchableColumn" tsvector GENERATED ALWAYS AS (TO_TSVECTOR('english', + COALESCE(make, '') || ' ' || + COALESCE(model, '') || ' ' || + COALESCE(orientation, '') || ' ' || + COALESCE("lensModel", '') || ' ' || + COALESCE("city", '') || ' ' || + COALESCE("state", '') || ' ' || + COALESCE("country", ''))) STORED NOT NULL`); + await queryRunner.query( + `INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES ($1, $2, $3, $4, $5, $6)`, + [ + 'immich', + 'public', + 'exif', + 'GENERATED_COLUMN', + 'exifTextSearchableColumn', + "TO_TSVECTOR('english',\n COALESCE(make, '') || ' ' ||\n COALESCE(model, '') || ' ' ||\n COALESCE(orientation, '') || ' ' ||\n COALESCE(\"lensModel\", '') || ' ' ||\n COALESCE(\"city\", '') || ' ' ||\n COALESCE(\"state\", '') || ' ' ||\n COALESCE(\"country\", ''))", + ], + ); + await queryRunner.query(`ALTER TABLE "exif" DROP COLUMN "imageName"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "database" = $3 AND "schema" = $4 AND "table" = $5`, + ['GENERATED_COLUMN', 'exifTextSearchableColumn', 'immich', 'public', 'exif'], + ); + await queryRunner.query(`ALTER TABLE "exif" DROP COLUMN "exifTextSearchableColumn"`); + await queryRunner.query( + `INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES ($1, $2, $3, $4, $5, $6)`, + [ + 'immich', + 'public', + 'exif', + 'GENERATED_COLUMN', + 'exifTextSearchableColumn', + "TO_TSVECTOR('english',\n COALESCE(make, '') || ' ' ||\n COALESCE(model, '') || ' ' ||\n COALESCE(orientation, '') || ' ' ||\n COALESCE(\"lensModel\", '') || ' ' ||\n COALESCE(\"imageName\", '') || ' ' ||\n COALESCE(\"city\", '') || ' ' ||\n COALESCE(\"state\", '') || ' ' ||\n COALESCE(\"country\", ''))", + ], + ); + await queryRunner.query(`ALTER TABLE "exif" ADD "exifTextSearchableColumn" tsvector GENERATED ALWAYS AS (TO_TSVECTOR('english', + COALESCE(make, '') || ' ' || + COALESCE(model, '') || ' ' || + COALESCE(orientation, '') || ' ' || + COALESCE("lensModel", '') || ' ' || + COALESCE("imageName", '') || ' ' || + COALESCE("city", '') || ' ' || + COALESCE("state", '') || ' ' || + COALESCE("country", ''))) STORED NOT NULL`); + await queryRunner.query(`ALTER TABLE "exif" ADD "imageName" character varying`); + } +} diff --git a/server/libs/infra/src/repositories/typesense.repository.ts b/server/libs/infra/src/repositories/typesense.repository.ts index 6e3a2115f8..d4682ee27f 100644 --- a/server/libs/infra/src/repositories/typesense.repository.ts +++ b/server/libs/infra/src/repositories/typesense.repository.ts @@ -144,7 +144,7 @@ export class TypesenseRepository implements ISearchRepository { const { facet_counts: facets } = await asset$.search({ ...common, - query_by: 'exifInfo.imageName', + query_by: 'originalFileName', facet_by: 'exifInfo.city,smartInfo.objects', max_facet_values: 12, }); @@ -157,7 +157,7 @@ export class TypesenseRepository implements ISearchRepository { mergeMap((count) => { const config = { ...common, - query_by: 'exifInfo.imageName', + query_by: 'originalFileName', filter_by: [ this.buildFilterBy('ownerId', userId, true), this.buildFilterBy(facet.field_name, count.value, true), @@ -230,7 +230,7 @@ export class TypesenseRepository implements ISearchRepository { .search({ q: query, query_by: [ - 'exifInfo.imageName', + 'originalFileName', 'exifInfo.country', 'exifInfo.state', 'exifInfo.city', diff --git a/server/libs/infra/src/typesense-schemas/asset.schema.ts b/server/libs/infra/src/typesense-schemas/asset.schema.ts index 28a61cf097..04636d4f67 100644 --- a/server/libs/infra/src/typesense-schemas/asset.schema.ts +++ b/server/libs/infra/src/typesense-schemas/asset.schema.ts @@ -1,6 +1,6 @@ import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections'; -export const assetSchemaVersion = 3; +export const assetSchemaVersion = 4; export const assetSchema: CollectionCreateSchema = { name: `assets-v${assetSchemaVersion}`, fields: [ @@ -13,6 +13,7 @@ export const assetSchema: CollectionCreateSchema = { { name: 'fileCreatedAt', type: 'string', facet: false, sort: true }, { name: 'fileModifiedAt', type: 'string', facet: false, sort: true }, { name: 'isFavorite', type: 'bool', facet: true }, + { name: 'originalFileName', type: 'string', facet: false, optional: true }, // { name: 'checksum', type: 'string', facet: true }, // { name: 'tags', type: 'string[]', facet: true, optional: true }, @@ -21,7 +22,6 @@ export const assetSchema: CollectionCreateSchema = { { name: 'exifInfo.country', type: 'string', facet: true, optional: true }, { name: 'exifInfo.state', type: 'string', facet: true, optional: true }, { name: 'exifInfo.description', type: 'string', facet: false, optional: true }, - { name: 'exifInfo.imageName', type: 'string', facet: false, optional: true }, { name: 'exifInfo.make', type: 'string', facet: true, optional: true }, { name: 'exifInfo.model', type: 'string', facet: true, optional: true }, { name: 'exifInfo.orientation', type: 'string', optional: true }, diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index b1e38dae25..f92dd2328e 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -476,6 +476,12 @@ export interface AssetResponseDto { * @memberof AssetResponseDto */ 'originalPath': string; + /** + * + * @type {string} + * @memberof AssetResponseDto + */ + 'originalFileName': string; /** * * @type {string} @@ -1100,12 +1106,6 @@ export interface ExifResponseDto { * @memberof ExifResponseDto */ 'model'?: string | null; - /** - * - * @type {string} - * @memberof ExifResponseDto - */ - 'imageName'?: string | null; /** * * @type {number} diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte index 9ab4d99a1b..d0dd9a8661 100644 --- a/web/src/lib/components/asset-viewer/detail-panel.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel.svelte @@ -96,7 +96,7 @@
-

{`${asset.exifInfo.imageName}.${asset.originalPath.split('.')[1]}` || ''}

+

{`${asset.originalFileName}.${asset.originalPath.split('.')[1]}` || ''}

{#if asset.exifInfo.exifImageHeight && asset.exifInfo.exifImageWidth} {#if getMegapixel(asset.exifInfo.exifImageHeight, asset.exifInfo.exifImageWidth)} diff --git a/web/src/lib/components/assets/thumbnail/thumbnail.svelte b/web/src/lib/components/assets/thumbnail/thumbnail.svelte index c4239f9849..39a17faa19 100644 --- a/web/src/lib/components/assets/thumbnail/thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/thumbnail.svelte @@ -116,7 +116,7 @@