diff --git a/mobile/openapi/lib/api/assets_api.dart b/mobile/openapi/lib/api/assets_api.dart index 06965e1f8b..db6a2e78a3 100644 --- a/mobile/openapi/lib/api/assets_api.dart +++ b/mobile/openapi/lib/api/assets_api.dart @@ -542,7 +542,9 @@ class AssetsApi { /// * [String] key: /// /// * [String] duration: - Future replaceAssetWithHttpInfo(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, }) async { + /// + /// * [String] filename: + Future replaceAssetWithHttpInfo(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, String? filename, }) async { // ignore: prefer_const_declarations final apiPath = r'/assets/{id}/original' .replaceAll('{id}', id); @@ -587,6 +589,10 @@ class AssetsApi { hasFields = true; mp.fields[r'fileModifiedAt'] = parameterToString(fileModifiedAt); } + if (filename != null) { + hasFields = true; + mp.fields[r'filename'] = parameterToString(filename); + } if (hasFields) { postBody = mp; } @@ -623,8 +629,10 @@ class AssetsApi { /// * [String] key: /// /// * [String] duration: - Future replaceAsset(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, }) async { - final response = await replaceAssetWithHttpInfo(id, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, duration: duration, ); + /// + /// * [String] filename: + Future replaceAsset(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, String? filename, }) async { + final response = await replaceAssetWithHttpInfo(id, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, duration: duration, filename: filename, ); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } @@ -788,6 +796,8 @@ class AssetsApi { /// /// * [String] duration: /// + /// * [String] filename: + /// /// * [bool] isFavorite: /// /// * [String] livePhotoVideoId: @@ -795,7 +805,7 @@ class AssetsApi { /// * [MultipartFile] sidecarData: /// /// * [AssetVisibility] visibility: - Future uploadAssetWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isFavorite, String? livePhotoVideoId, MultipartFile? sidecarData, AssetVisibility? visibility, }) async { + Future uploadAssetWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, MultipartFile? sidecarData, AssetVisibility? visibility, }) async { // ignore: prefer_const_declarations final apiPath = r'/assets'; @@ -843,6 +853,10 @@ class AssetsApi { hasFields = true; mp.fields[r'fileModifiedAt'] = parameterToString(fileModifiedAt); } + if (filename != null) { + hasFields = true; + mp.fields[r'filename'] = parameterToString(filename); + } if (isFavorite != null) { hasFields = true; mp.fields[r'isFavorite'] = parameterToString(isFavorite); @@ -894,6 +908,8 @@ class AssetsApi { /// /// * [String] duration: /// + /// * [String] filename: + /// /// * [bool] isFavorite: /// /// * [String] livePhotoVideoId: @@ -901,8 +917,8 @@ class AssetsApi { /// * [MultipartFile] sidecarData: /// /// * [AssetVisibility] visibility: - Future uploadAsset(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isFavorite, String? livePhotoVideoId, MultipartFile? sidecarData, AssetVisibility? visibility, }) async { - final response = await uploadAssetWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, xImmichChecksum: xImmichChecksum, duration: duration, isFavorite: isFavorite, livePhotoVideoId: livePhotoVideoId, sidecarData: sidecarData, visibility: visibility, ); + Future uploadAsset(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, MultipartFile? sidecarData, AssetVisibility? visibility, }) async { + final response = await uploadAssetWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, xImmichChecksum: xImmichChecksum, duration: duration, filename: filename, isFavorite: isFavorite, livePhotoVideoId: livePhotoVideoId, sidecarData: sidecarData, visibility: visibility, ); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 8318756295..4ef9ad0bd8 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -9401,6 +9401,9 @@ "format": "date-time", "type": "string" }, + "filename": { + "type": "string" + }, "isFavorite": { "type": "boolean" }, @@ -9451,6 +9454,9 @@ "fileModifiedAt": { "format": "date-time", "type": "string" + }, + "filename": { + "type": "string" } }, "required": [ diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 8dced80394..e9dccc9cc6 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -444,6 +444,7 @@ export type AssetMediaCreateDto = { duration?: string; fileCreatedAt: string; fileModifiedAt: string; + filename?: string; isFavorite?: boolean; livePhotoVideoId?: string; sidecarData?: Blob; @@ -510,6 +511,7 @@ export type AssetMediaReplaceDto = { duration?: string; fileCreatedAt: string; fileModifiedAt: string; + filename?: string; }; export type SignUpDto = { email: string; diff --git a/server/src/dtos/asset-media.dto.ts b/server/src/dtos/asset-media.dto.ts index a647b4515f..92e1302864 100644 --- a/server/src/dtos/asset-media.dto.ts +++ b/server/src/dtos/asset-media.dto.ts @@ -46,6 +46,10 @@ class AssetMediaBase { @IsString() duration?: string; + @Optional() + @IsString() + filename?: string; + // The properties below are added to correctly generate the API docs // and client SDKs. Validation should be handled in the controller. @ApiProperty({ type: 'string', format: 'binary' }) diff --git a/server/src/services/asset-media.service.ts b/server/src/services/asset-media.service.ts index 87d617ede6..b56641947d 100644 --- a/server/src/services/asset-media.service.ts +++ b/server/src/services/asset-media.service.ts @@ -418,7 +418,7 @@ export class AssetMediaService extends BaseService { duration: dto.duration || null, visibility: dto.visibility ?? AssetVisibility.TIMELINE, livePhotoVideoId: dto.livePhotoVideoId, - originalFileName: file.originalName, + originalFileName: dto.filename || file.originalName, sidecarPath: sidecarFile?.originalPath, });