You've already forked immich
							
							
				mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 00:18:28 +02:00 
			
		
		
		
	fix: live photo uploads (#4167)
* fix: live photo uploads * fix: format --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
		| @@ -19,11 +19,14 @@ export interface AssetOwnerCheck extends AssetCheck { | ||||
|   ownerId: string; | ||||
| } | ||||
|  | ||||
| export type AssetCreate = Omit< | ||||
|   AssetEntity, | ||||
|   'id' | 'createdAt' | 'updatedAt' | 'owner' | 'livePhotoVideoId' | 'library' | ||||
| >; | ||||
|  | ||||
| export interface IAssetRepository { | ||||
|   get(id: string): Promise<AssetEntity | null>; | ||||
|   create( | ||||
|     asset: Omit<AssetEntity, 'id' | 'createdAt' | 'updatedAt' | 'ownerId' | 'libraryId' | 'livePhotoVideoId'>, | ||||
|   ): Promise<AssetEntity>; | ||||
|   create(asset: AssetCreate): Promise<AssetEntity>; | ||||
|   remove(asset: AssetEntity): Promise<void>; | ||||
|   getAllByUserId(userId: string, dto: AssetSearchDto): Promise<AssetEntity[]>; | ||||
|   getAllByDeviceId(userId: string, deviceId: string): Promise<string[]>; | ||||
| @@ -151,9 +154,7 @@ export class AssetRepository implements IAssetRepository { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   create( | ||||
|     asset: Omit<AssetEntity, 'id' | 'createdAt' | 'updatedAt' | 'ownerId' | 'livePhotoVideoId'>, | ||||
|   ): Promise<AssetEntity> { | ||||
|   create(asset: AssetCreate): Promise<AssetEntity> { | ||||
|     return this.assetRepository.save(asset); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { AuthUserDto, IJobRepository, JobName, mimeTypes, UploadFile } from '@app/domain'; | ||||
| import { AssetEntity, LibraryEntity, UserEntity } from '@app/infra/entities'; | ||||
| import { AssetEntity } from '@app/infra/entities'; | ||||
| import { parse } from 'node:path'; | ||||
| import { IAssetRepository } from './asset-repository'; | ||||
| import { CreateAssetDto, ImportAssetDto } from './dto/create-asset.dto'; | ||||
| @@ -12,14 +12,14 @@ export class AssetCore { | ||||
|  | ||||
|   async create( | ||||
|     authUser: AuthUserDto, | ||||
|     dto: CreateAssetDto | ImportAssetDto, | ||||
|     dto: (CreateAssetDto | ImportAssetDto) & { libraryId: string }, | ||||
|     file: UploadFile, | ||||
|     livePhotoAssetId?: string, | ||||
|     sidecarPath?: string, | ||||
|   ): Promise<AssetEntity> { | ||||
|     const asset = await this.repository.create({ | ||||
|       owner: { id: authUser.id } as UserEntity, | ||||
|       library: { id: dto.libraryId } as LibraryEntity, | ||||
|       ownerId: authUser.id, | ||||
|       libraryId: dto.libraryId, | ||||
|  | ||||
|       checksum: file.checksum, | ||||
|       originalPath: file.originalPath, | ||||
|   | ||||
| @@ -90,22 +90,19 @@ export class AssetService { | ||||
|     let livePhotoAsset: AssetEntity | null = null; | ||||
|  | ||||
|     try { | ||||
|       const libraryId = await this.getLibraryId(authUser, dto.libraryId); | ||||
|       if (livePhotoFile) { | ||||
|         const livePhotoDto = { ...dto, assetType: AssetType.VIDEO, isVisible: false }; | ||||
|         const livePhotoDto = { ...dto, assetType: AssetType.VIDEO, isVisible: false, libraryId }; | ||||
|         livePhotoAsset = await this.assetCore.create(authUser, livePhotoDto, livePhotoFile); | ||||
|       } | ||||
|  | ||||
|       if (!dto.libraryId) { | ||||
|         // No library given, fall back to default upload library | ||||
|         const defaultUploadLibrary = await this.libraryRepository.getDefaultUploadLibrary(authUser.id); | ||||
|  | ||||
|         if (!defaultUploadLibrary) { | ||||
|           throw new InternalServerErrorException('Cannot find default upload library for user ' + authUser.id); | ||||
|         } | ||||
|         dto.libraryId = defaultUploadLibrary.id; | ||||
|       } | ||||
|  | ||||
|       const asset = await this.assetCore.create(authUser, dto, file, livePhotoAsset?.id, sidecarFile?.originalPath); | ||||
|       const asset = await this.assetCore.create( | ||||
|         authUser, | ||||
|         { ...dto, libraryId }, | ||||
|         file, | ||||
|         livePhotoAsset?.id, | ||||
|         sidecarFile?.originalPath, | ||||
|       ); | ||||
|  | ||||
|       return { id: asset.id, duplicate: false }; | ||||
|     } catch (error: any) { | ||||
| @@ -164,7 +161,8 @@ export class AssetService { | ||||
|     }; | ||||
|  | ||||
|     try { | ||||
|       const asset = await this.assetCore.create(authUser, dto, assetFile, undefined, dto.sidecarPath); | ||||
|       const libraryId = await this.getLibraryId(authUser, dto.libraryId); | ||||
|       const asset = await this.assetCore.create(authUser, { ...dto, libraryId }, assetFile, undefined, dto.sidecarPath); | ||||
|       return { id: asset.id, duplicate: false }; | ||||
|     } catch (error: QueryFailedError | Error | any) { | ||||
|       // handle duplicates with a success response | ||||
| @@ -505,4 +503,25 @@ export class AssetService { | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   private async getLibraryId(authUser: AuthUserDto, libraryId?: string) { | ||||
|     if (libraryId) { | ||||
|       return libraryId; | ||||
|     } | ||||
|  | ||||
|     let library = await this.libraryRepository.getDefaultUploadLibrary(authUser.id); | ||||
|     if (!library) { | ||||
|       library = await this.libraryRepository.create({ | ||||
|         ownerId: authUser.id, | ||||
|         name: 'Default Library', | ||||
|         assets: [], | ||||
|         type: LibraryType.UPLOAD, | ||||
|         importPaths: [], | ||||
|         exclusionPatterns: [], | ||||
|         isVisible: true, | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     return library.id; | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user