mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 10:37:11 -04:00 
			
		
		
		
	feat(server): read-write external assets (#9235)
* refactor: remove isReadOnly and isExternal usages * chore: open api * fix: linting * remove mobile isReadOnly dependency --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
		
							parent
							
								
									d26ac431b8
								
							
						
					
					
						commit
						5b87abb021
					
				| @ -102,7 +102,6 @@ describe('/asset', () => { | |||||||
|       utils.createAsset(user1.accessToken), |       utils.createAsset(user1.accessToken), | ||||||
|       utils.createAsset(user1.accessToken, { |       utils.createAsset(user1.accessToken, { | ||||||
|         isFavorite: true, |         isFavorite: true, | ||||||
|         isReadOnly: true, |  | ||||||
|         fileCreatedAt: yesterday.toISO(), |         fileCreatedAt: yesterday.toISO(), | ||||||
|         fileModifiedAt: yesterday.toISO(), |         fileModifiedAt: yesterday.toISO(), | ||||||
|         assetData: { filename: 'example.mp4' }, |         assetData: { filename: 'example.mp4' }, | ||||||
|  | |||||||
| @ -24,12 +24,12 @@ describe('/search', () => { | |||||||
|   // let assetRidge: AssetFileUploadResponseDto;
 |   // let assetRidge: AssetFileUploadResponseDto;
 | ||||||
|   // let assetPolemonium: AssetFileUploadResponseDto;
 |   // let assetPolemonium: AssetFileUploadResponseDto;
 | ||||||
|   // let assetWood: AssetFileUploadResponseDto;
 |   // let assetWood: AssetFileUploadResponseDto;
 | ||||||
|  |   // let assetGlarus: AssetFileUploadResponseDto;
 | ||||||
|   let assetHeic: AssetFileUploadResponseDto; |   let assetHeic: AssetFileUploadResponseDto; | ||||||
|   let assetRocks: AssetFileUploadResponseDto; |   let assetRocks: AssetFileUploadResponseDto; | ||||||
|   let assetOneJpg6: AssetFileUploadResponseDto; |   let assetOneJpg6: AssetFileUploadResponseDto; | ||||||
|   let assetOneHeic6: AssetFileUploadResponseDto; |   let assetOneHeic6: AssetFileUploadResponseDto; | ||||||
|   let assetOneJpg5: AssetFileUploadResponseDto; |   let assetOneJpg5: AssetFileUploadResponseDto; | ||||||
|   let assetGlarus: AssetFileUploadResponseDto; |  | ||||||
|   let assetSprings: AssetFileUploadResponseDto; |   let assetSprings: AssetFileUploadResponseDto; | ||||||
|   let assetLast: AssetFileUploadResponseDto; |   let assetLast: AssetFileUploadResponseDto; | ||||||
|   let cities: string[]; |   let cities: string[]; | ||||||
| @ -52,11 +52,12 @@ describe('/search', () => { | |||||||
|       { filename: '/formats/motionphoto/Samsung One UI 6.jpg' }, |       { filename: '/formats/motionphoto/Samsung One UI 6.jpg' }, | ||||||
|       { filename: '/formats/motionphoto/Samsung One UI 6.heic' }, |       { filename: '/formats/motionphoto/Samsung One UI 6.heic' }, | ||||||
|       { filename: '/formats/motionphoto/Samsung One UI 5.jpg' }, |       { filename: '/formats/motionphoto/Samsung One UI 5.jpg' }, | ||||||
|       { filename: '/formats/raw/Nikon/D80/glarus.nef', dto: { isReadOnly: true } }, | 
 | ||||||
|       { filename: '/metadata/gps-position/thompson-springs.jpg', dto: { isArchived: true } }, |       { filename: '/metadata/gps-position/thompson-springs.jpg', dto: { isArchived: true } }, | ||||||
| 
 | 
 | ||||||
|       // used for search suggestions
 |       // used for search suggestions
 | ||||||
|       { filename: '/formats/png/density_plot.png' }, |       { filename: '/formats/png/density_plot.png' }, | ||||||
|  |       { filename: '/formats/raw/Nikon/D80/glarus.nef' }, | ||||||
|       { filename: '/formats/raw/Nikon/D700/philadelphia.nef' }, |       { filename: '/formats/raw/Nikon/D700/philadelphia.nef' }, | ||||||
|       { filename: '/albums/nature/orychophragmus_violaceus.jpg' }, |       { filename: '/albums/nature/orychophragmus_violaceus.jpg' }, | ||||||
|       { filename: '/albums/nature/tanners_ridge.jpg' }, |       { filename: '/albums/nature/tanners_ridge.jpg' }, | ||||||
| @ -93,9 +94,9 @@ describe('/search', () => { | |||||||
|       { latitude: 23.133_02, longitude: -82.383_04 }, // havana
 |       { latitude: 23.133_02, longitude: -82.383_04 }, // havana
 | ||||||
|       { latitude: 41.694_11, longitude: 44.833_68 }, // tbilisi
 |       { latitude: 41.694_11, longitude: 44.833_68 }, // tbilisi
 | ||||||
|       { latitude: 31.222_22, longitude: 121.458_06 }, // shanghai
 |       { latitude: 31.222_22, longitude: 121.458_06 }, // shanghai
 | ||||||
|       { latitude: 47.040_57, longitude: 9.068_04 }, // glarus
 |  | ||||||
|       { latitude: 38.9711, longitude: -109.7137 }, // thompson springs
 |       { latitude: 38.9711, longitude: -109.7137 }, // thompson springs
 | ||||||
|       { latitude: 40.714_27, longitude: -74.005_97 }, // new york
 |       { latitude: 40.714_27, longitude: -74.005_97 }, // new york
 | ||||||
|  |       { latitude: 47.040_57, longitude: 9.068_04 }, // glarus
 | ||||||
|       { latitude: 32.771_52, longitude: -89.116_73 }, // philadelphia
 |       { latitude: 32.771_52, longitude: -89.116_73 }, // philadelphia
 | ||||||
|       { latitude: 31.634_16, longitude: -7.999_94 }, // marrakesh
 |       { latitude: 31.634_16, longitude: -7.999_94 }, // marrakesh
 | ||||||
|       { latitude: 38.523_735_4, longitude: -78.488_619_4 }, // tanners ridge
 |       { latitude: 38.523_735_4, longitude: -78.488_619_4 }, // tanners ridge
 | ||||||
| @ -123,9 +124,9 @@ describe('/search', () => { | |||||||
|       assetOneJpg6, |       assetOneJpg6, | ||||||
|       assetOneHeic6, |       assetOneHeic6, | ||||||
|       assetOneJpg5, |       assetOneJpg5, | ||||||
|       assetGlarus, |  | ||||||
|       assetSprings, |       assetSprings, | ||||||
|       assetDensity, |       assetDensity, | ||||||
|  |       // assetGlarus,
 | ||||||
|       // assetPhiladelphia,
 |       // assetPhiladelphia,
 | ||||||
|       // assetOrychophragmus,
 |       // assetOrychophragmus,
 | ||||||
|       // assetRidge,
 |       // assetRidge,
 | ||||||
| @ -190,16 +191,7 @@ describe('/search', () => { | |||||||
|         dto: { size: -1.5 }, |         dto: { size: -1.5 }, | ||||||
|         expected: ['size must not be less than 1', 'size must be an integer number'], |         expected: ['size must not be less than 1', 'size must be an integer number'], | ||||||
|       }, |       }, | ||||||
|       ...[ |       ...['isArchived', 'isFavorite', 'isEncoded', 'isMotion', 'isOffline', 'isVisible'].map((value) => ({ | ||||||
|         'isArchived', |  | ||||||
|         'isFavorite', |  | ||||||
|         'isReadOnly', |  | ||||||
|         'isExternal', |  | ||||||
|         'isEncoded', |  | ||||||
|         'isMotion', |  | ||||||
|         'isOffline', |  | ||||||
|         'isVisible', |  | ||||||
|       ].map((value) => ({ |  | ||||||
|         should: `should reject ${value} not a boolean`, |         should: `should reject ${value} not a boolean`, | ||||||
|         dto: { [value]: 'immich' }, |         dto: { [value]: 'immich' }, | ||||||
|         expected: [`${value} must be a boolean value`], |         expected: [`${value} must be a boolean value`], | ||||||
| @ -255,14 +247,6 @@ describe('/search', () => { | |||||||
|         should: 'should search by isArchived (false)', |         should: 'should search by isArchived (false)', | ||||||
|         deferred: () => ({ dto: { size: 1, isArchived: false }, assets: [assetLast] }), |         deferred: () => ({ dto: { size: 1, isArchived: false }, assets: [assetLast] }), | ||||||
|       }, |       }, | ||||||
|       { |  | ||||||
|         should: 'should search by isReadOnly (true)', |  | ||||||
|         deferred: () => ({ dto: { isReadOnly: true }, assets: [assetGlarus] }), |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         should: 'should search by isReadOnly (false)', |  | ||||||
|         deferred: () => ({ dto: { size: 1, isReadOnly: false }, assets: [assetLast] }), |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         should: 'should search by type (image)', |         should: 'should search by type (image)', | ||||||
|         deferred: () => ({ dto: { size: 1, type: 'IMAGE' }, assets: [assetLast] }), |         deferred: () => ({ dto: { size: 1, type: 'IMAGE' }, assets: [assetLast] }), | ||||||
|  | |||||||
| @ -34,7 +34,6 @@ describe('/timeline', () => { | |||||||
|       utils.createAsset(user.accessToken), |       utils.createAsset(user.accessToken), | ||||||
|       utils.createAsset(user.accessToken, { |       utils.createAsset(user.accessToken, { | ||||||
|         isFavorite: true, |         isFavorite: true, | ||||||
|         isReadOnly: true, |  | ||||||
|         fileCreatedAt: yesterday.toISO(), |         fileCreatedAt: yesterday.toISO(), | ||||||
|         fileModifiedAt: yesterday.toISO(), |         fileModifiedAt: yesterday.toISO(), | ||||||
|         assetData: { filename: 'example.mp4' }, |         assetData: { filename: 'example.mp4' }, | ||||||
|  | |||||||
| @ -32,7 +32,6 @@ class Asset { | |||||||
|         isFavorite = remote.isFavorite, |         isFavorite = remote.isFavorite, | ||||||
|         isArchived = remote.isArchived, |         isArchived = remote.isArchived, | ||||||
|         isTrashed = remote.isTrashed, |         isTrashed = remote.isTrashed, | ||||||
|         isReadOnly = remote.isReadOnly, |  | ||||||
|         isOffline = remote.isOffline, |         isOffline = remote.isOffline, | ||||||
|         // workaround to nullify stackParentId for the parent asset until we refactor the mobile app |         // workaround to nullify stackParentId for the parent asset until we refactor the mobile app | ||||||
|         // stack handling to properly handle it |         // stack handling to properly handle it | ||||||
| @ -55,7 +54,6 @@ class Asset { | |||||||
|         isFavorite = local.isFavorite, |         isFavorite = local.isFavorite, | ||||||
|         isArchived = false, |         isArchived = false, | ||||||
|         isTrashed = false, |         isTrashed = false, | ||||||
|         isReadOnly = false, |  | ||||||
|         isOffline = false, |         isOffline = false, | ||||||
|         stackCount = 0, |         stackCount = 0, | ||||||
|         fileCreatedAt = local.createDateTime { |         fileCreatedAt = local.createDateTime { | ||||||
| @ -90,7 +88,6 @@ class Asset { | |||||||
|     this.isTrashed = false, |     this.isTrashed = false, | ||||||
|     this.stackParentId, |     this.stackParentId, | ||||||
|     this.stackCount = 0, |     this.stackCount = 0, | ||||||
|     this.isReadOnly = false, |  | ||||||
|     this.isOffline = false, |     this.isOffline = false, | ||||||
|     this.thumbhash, |     this.thumbhash, | ||||||
|   }); |   }); | ||||||
| @ -161,8 +158,6 @@ class Asset { | |||||||
| 
 | 
 | ||||||
|   bool isTrashed; |   bool isTrashed; | ||||||
| 
 | 
 | ||||||
|   bool isReadOnly; |  | ||||||
| 
 |  | ||||||
|   bool isOffline; |   bool isOffline; | ||||||
| 
 | 
 | ||||||
|   @ignore |   @ignore | ||||||
| @ -278,7 +273,6 @@ class Asset { | |||||||
|         isFavorite != a.isFavorite || |         isFavorite != a.isFavorite || | ||||||
|         isArchived != a.isArchived || |         isArchived != a.isArchived || | ||||||
|         isTrashed != a.isTrashed || |         isTrashed != a.isTrashed || | ||||||
|         isReadOnly != a.isReadOnly || |  | ||||||
|         isOffline != a.isOffline || |         isOffline != a.isOffline || | ||||||
|         a.exifInfo?.latitude != exifInfo?.latitude || |         a.exifInfo?.latitude != exifInfo?.latitude || | ||||||
|         a.exifInfo?.longitude != exifInfo?.longitude || |         a.exifInfo?.longitude != exifInfo?.longitude || | ||||||
| @ -324,7 +318,6 @@ class Asset { | |||||||
|           isFavorite: isFavorite, |           isFavorite: isFavorite, | ||||||
|           isArchived: isArchived, |           isArchived: isArchived, | ||||||
|           isTrashed: isTrashed, |           isTrashed: isTrashed, | ||||||
|           isReadOnly: isReadOnly, |  | ||||||
|           isOffline: isOffline, |           isOffline: isOffline, | ||||||
|         ); |         ); | ||||||
|       } |       } | ||||||
| @ -345,7 +338,6 @@ class Asset { | |||||||
|           isFavorite: a.isFavorite, |           isFavorite: a.isFavorite, | ||||||
|           isArchived: a.isArchived, |           isArchived: a.isArchived, | ||||||
|           isTrashed: a.isTrashed, |           isTrashed: a.isTrashed, | ||||||
|           isReadOnly: a.isReadOnly, |  | ||||||
|           isOffline: a.isOffline, |           isOffline: a.isOffline, | ||||||
|           exifInfo: a.exifInfo?.copyWith(id: id) ?? exifInfo, |           exifInfo: a.exifInfo?.copyWith(id: id) ?? exifInfo, | ||||||
|           thumbhash: a.thumbhash, |           thumbhash: a.thumbhash, | ||||||
| @ -380,7 +372,6 @@ class Asset { | |||||||
|     bool? isFavorite, |     bool? isFavorite, | ||||||
|     bool? isArchived, |     bool? isArchived, | ||||||
|     bool? isTrashed, |     bool? isTrashed, | ||||||
|     bool? isReadOnly, |  | ||||||
|     bool? isOffline, |     bool? isOffline, | ||||||
|     ExifInfo? exifInfo, |     ExifInfo? exifInfo, | ||||||
|     String? stackParentId, |     String? stackParentId, | ||||||
| @ -405,7 +396,6 @@ class Asset { | |||||||
|         isFavorite: isFavorite ?? this.isFavorite, |         isFavorite: isFavorite ?? this.isFavorite, | ||||||
|         isArchived: isArchived ?? this.isArchived, |         isArchived: isArchived ?? this.isArchived, | ||||||
|         isTrashed: isTrashed ?? this.isTrashed, |         isTrashed: isTrashed ?? this.isTrashed, | ||||||
|         isReadOnly: isReadOnly ?? this.isReadOnly, |  | ||||||
|         isOffline: isOffline ?? this.isOffline, |         isOffline: isOffline ?? this.isOffline, | ||||||
|         exifInfo: exifInfo ?? this.exifInfo, |         exifInfo: exifInfo ?? this.exifInfo, | ||||||
|         stackParentId: stackParentId ?? this.stackParentId, |         stackParentId: stackParentId ?? this.stackParentId, | ||||||
| @ -470,7 +460,6 @@ class Asset { | |||||||
|   "height": ${height ?? "N/A"}, |   "height": ${height ?? "N/A"}, | ||||||
|   "isArchived": $isArchived, |   "isArchived": $isArchived, | ||||||
|   "isTrashed": $isTrashed, |   "isTrashed": $isTrashed, | ||||||
|   "isReadOnly": $isReadOnly, |  | ||||||
|   "isOffline": $isOffline, |   "isOffline": $isOffline, | ||||||
| }"""; | }"""; | ||||||
|   } |   } | ||||||
|  | |||||||
							
								
								
									
										135
									
								
								mobile/lib/entities/asset.entity.g.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										135
									
								
								mobile/lib/entities/asset.entity.g.dart
									
									
									
										generated
									
									
									
								
							| @ -62,64 +62,59 @@ const AssetSchema = CollectionSchema( | |||||||
|       name: r'isOffline', |       name: r'isOffline', | ||||||
|       type: IsarType.bool, |       type: IsarType.bool, | ||||||
|     ), |     ), | ||||||
|     r'isReadOnly': PropertySchema( |  | ||||||
|       id: 9, |  | ||||||
|       name: r'isReadOnly', |  | ||||||
|       type: IsarType.bool, |  | ||||||
|     ), |  | ||||||
|     r'isTrashed': PropertySchema( |     r'isTrashed': PropertySchema( | ||||||
|       id: 10, |       id: 9, | ||||||
|       name: r'isTrashed', |       name: r'isTrashed', | ||||||
|       type: IsarType.bool, |       type: IsarType.bool, | ||||||
|     ), |     ), | ||||||
|     r'livePhotoVideoId': PropertySchema( |     r'livePhotoVideoId': PropertySchema( | ||||||
|       id: 11, |       id: 10, | ||||||
|       name: r'livePhotoVideoId', |       name: r'livePhotoVideoId', | ||||||
|       type: IsarType.string, |       type: IsarType.string, | ||||||
|     ), |     ), | ||||||
|     r'localId': PropertySchema( |     r'localId': PropertySchema( | ||||||
|       id: 12, |       id: 11, | ||||||
|       name: r'localId', |       name: r'localId', | ||||||
|       type: IsarType.string, |       type: IsarType.string, | ||||||
|     ), |     ), | ||||||
|     r'ownerId': PropertySchema( |     r'ownerId': PropertySchema( | ||||||
|       id: 13, |       id: 12, | ||||||
|       name: r'ownerId', |       name: r'ownerId', | ||||||
|       type: IsarType.long, |       type: IsarType.long, | ||||||
|     ), |     ), | ||||||
|     r'remoteId': PropertySchema( |     r'remoteId': PropertySchema( | ||||||
|       id: 14, |       id: 13, | ||||||
|       name: r'remoteId', |       name: r'remoteId', | ||||||
|       type: IsarType.string, |       type: IsarType.string, | ||||||
|     ), |     ), | ||||||
|     r'stackCount': PropertySchema( |     r'stackCount': PropertySchema( | ||||||
|       id: 15, |       id: 14, | ||||||
|       name: r'stackCount', |       name: r'stackCount', | ||||||
|       type: IsarType.long, |       type: IsarType.long, | ||||||
|     ), |     ), | ||||||
|     r'stackParentId': PropertySchema( |     r'stackParentId': PropertySchema( | ||||||
|       id: 16, |       id: 15, | ||||||
|       name: r'stackParentId', |       name: r'stackParentId', | ||||||
|       type: IsarType.string, |       type: IsarType.string, | ||||||
|     ), |     ), | ||||||
|     r'thumbhash': PropertySchema( |     r'thumbhash': PropertySchema( | ||||||
|       id: 17, |       id: 16, | ||||||
|       name: r'thumbhash', |       name: r'thumbhash', | ||||||
|       type: IsarType.string, |       type: IsarType.string, | ||||||
|     ), |     ), | ||||||
|     r'type': PropertySchema( |     r'type': PropertySchema( | ||||||
|       id: 18, |       id: 17, | ||||||
|       name: r'type', |       name: r'type', | ||||||
|       type: IsarType.byte, |       type: IsarType.byte, | ||||||
|       enumMap: _AssettypeEnumValueMap, |       enumMap: _AssettypeEnumValueMap, | ||||||
|     ), |     ), | ||||||
|     r'updatedAt': PropertySchema( |     r'updatedAt': PropertySchema( | ||||||
|       id: 19, |       id: 18, | ||||||
|       name: r'updatedAt', |       name: r'updatedAt', | ||||||
|       type: IsarType.dateTime, |       type: IsarType.dateTime, | ||||||
|     ), |     ), | ||||||
|     r'width': PropertySchema( |     r'width': PropertySchema( | ||||||
|       id: 20, |       id: 19, | ||||||
|       name: r'width', |       name: r'width', | ||||||
|       type: IsarType.int, |       type: IsarType.int, | ||||||
|     ) |     ) | ||||||
| @ -239,18 +234,17 @@ void _assetSerialize( | |||||||
|   writer.writeBool(offsets[6], object.isArchived); |   writer.writeBool(offsets[6], object.isArchived); | ||||||
|   writer.writeBool(offsets[7], object.isFavorite); |   writer.writeBool(offsets[7], object.isFavorite); | ||||||
|   writer.writeBool(offsets[8], object.isOffline); |   writer.writeBool(offsets[8], object.isOffline); | ||||||
|   writer.writeBool(offsets[9], object.isReadOnly); |   writer.writeBool(offsets[9], object.isTrashed); | ||||||
|   writer.writeBool(offsets[10], object.isTrashed); |   writer.writeString(offsets[10], object.livePhotoVideoId); | ||||||
|   writer.writeString(offsets[11], object.livePhotoVideoId); |   writer.writeString(offsets[11], object.localId); | ||||||
|   writer.writeString(offsets[12], object.localId); |   writer.writeLong(offsets[12], object.ownerId); | ||||||
|   writer.writeLong(offsets[13], object.ownerId); |   writer.writeString(offsets[13], object.remoteId); | ||||||
|   writer.writeString(offsets[14], object.remoteId); |   writer.writeLong(offsets[14], object.stackCount); | ||||||
|   writer.writeLong(offsets[15], object.stackCount); |   writer.writeString(offsets[15], object.stackParentId); | ||||||
|   writer.writeString(offsets[16], object.stackParentId); |   writer.writeString(offsets[16], object.thumbhash); | ||||||
|   writer.writeString(offsets[17], object.thumbhash); |   writer.writeByte(offsets[17], object.type.index); | ||||||
|   writer.writeByte(offsets[18], object.type.index); |   writer.writeDateTime(offsets[18], object.updatedAt); | ||||||
|   writer.writeDateTime(offsets[19], object.updatedAt); |   writer.writeInt(offsets[19], object.width); | ||||||
|   writer.writeInt(offsets[20], object.width); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Asset _assetDeserialize( | Asset _assetDeserialize( | ||||||
| @ -270,19 +264,18 @@ Asset _assetDeserialize( | |||||||
|     isArchived: reader.readBoolOrNull(offsets[6]) ?? false, |     isArchived: reader.readBoolOrNull(offsets[6]) ?? false, | ||||||
|     isFavorite: reader.readBoolOrNull(offsets[7]) ?? false, |     isFavorite: reader.readBoolOrNull(offsets[7]) ?? false, | ||||||
|     isOffline: reader.readBoolOrNull(offsets[8]) ?? false, |     isOffline: reader.readBoolOrNull(offsets[8]) ?? false, | ||||||
|     isReadOnly: reader.readBoolOrNull(offsets[9]) ?? false, |     isTrashed: reader.readBoolOrNull(offsets[9]) ?? false, | ||||||
|     isTrashed: reader.readBoolOrNull(offsets[10]) ?? false, |     livePhotoVideoId: reader.readStringOrNull(offsets[10]), | ||||||
|     livePhotoVideoId: reader.readStringOrNull(offsets[11]), |     localId: reader.readStringOrNull(offsets[11]), | ||||||
|     localId: reader.readStringOrNull(offsets[12]), |     ownerId: reader.readLong(offsets[12]), | ||||||
|     ownerId: reader.readLong(offsets[13]), |     remoteId: reader.readStringOrNull(offsets[13]), | ||||||
|     remoteId: reader.readStringOrNull(offsets[14]), |     stackCount: reader.readLongOrNull(offsets[14]), | ||||||
|     stackCount: reader.readLongOrNull(offsets[15]), |     stackParentId: reader.readStringOrNull(offsets[15]), | ||||||
|     stackParentId: reader.readStringOrNull(offsets[16]), |     thumbhash: reader.readStringOrNull(offsets[16]), | ||||||
|     thumbhash: reader.readStringOrNull(offsets[17]), |     type: _AssettypeValueEnumMap[reader.readByteOrNull(offsets[17])] ?? | ||||||
|     type: _AssettypeValueEnumMap[reader.readByteOrNull(offsets[18])] ?? |  | ||||||
|         AssetType.other, |         AssetType.other, | ||||||
|     updatedAt: reader.readDateTime(offsets[19]), |     updatedAt: reader.readDateTime(offsets[18]), | ||||||
|     width: reader.readIntOrNull(offsets[20]), |     width: reader.readIntOrNull(offsets[19]), | ||||||
|   ); |   ); | ||||||
|   return object; |   return object; | ||||||
| } | } | ||||||
| @ -315,27 +308,25 @@ P _assetDeserializeProp<P>( | |||||||
|     case 9: |     case 9: | ||||||
|       return (reader.readBoolOrNull(offset) ?? false) as P; |       return (reader.readBoolOrNull(offset) ?? false) as P; | ||||||
|     case 10: |     case 10: | ||||||
|       return (reader.readBoolOrNull(offset) ?? false) as P; |       return (reader.readStringOrNull(offset)) as P; | ||||||
|     case 11: |     case 11: | ||||||
|       return (reader.readStringOrNull(offset)) as P; |       return (reader.readStringOrNull(offset)) as P; | ||||||
|     case 12: |     case 12: | ||||||
|       return (reader.readStringOrNull(offset)) as P; |  | ||||||
|     case 13: |  | ||||||
|       return (reader.readLong(offset)) as P; |       return (reader.readLong(offset)) as P; | ||||||
|     case 14: |     case 13: | ||||||
|       return (reader.readStringOrNull(offset)) as P; |       return (reader.readStringOrNull(offset)) as P; | ||||||
|     case 15: |     case 14: | ||||||
|       return (reader.readLongOrNull(offset)) as P; |       return (reader.readLongOrNull(offset)) as P; | ||||||
|  |     case 15: | ||||||
|  |       return (reader.readStringOrNull(offset)) as P; | ||||||
|     case 16: |     case 16: | ||||||
|       return (reader.readStringOrNull(offset)) as P; |       return (reader.readStringOrNull(offset)) as P; | ||||||
|     case 17: |     case 17: | ||||||
|       return (reader.readStringOrNull(offset)) as P; |  | ||||||
|     case 18: |  | ||||||
|       return (_AssettypeValueEnumMap[reader.readByteOrNull(offset)] ?? |       return (_AssettypeValueEnumMap[reader.readByteOrNull(offset)] ?? | ||||||
|           AssetType.other) as P; |           AssetType.other) as P; | ||||||
|     case 19: |     case 18: | ||||||
|       return (reader.readDateTime(offset)) as P; |       return (reader.readDateTime(offset)) as P; | ||||||
|     case 20: |     case 19: | ||||||
|       return (reader.readIntOrNull(offset)) as P; |       return (reader.readIntOrNull(offset)) as P; | ||||||
|     default: |     default: | ||||||
|       throw IsarError('Unknown property with id $propertyId'); |       throw IsarError('Unknown property with id $propertyId'); | ||||||
| @ -1366,16 +1357,6 @@ extension AssetQueryFilter on QueryBuilder<Asset, Asset, QFilterCondition> { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   QueryBuilder<Asset, Asset, QAfterFilterCondition> isReadOnlyEqualTo( |  | ||||||
|       bool value) { |  | ||||||
|     return QueryBuilder.apply(this, (query) { |  | ||||||
|       return query.addFilterCondition(FilterCondition.equalTo( |  | ||||||
|         property: r'isReadOnly', |  | ||||||
|         value: value, |  | ||||||
|       )); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   QueryBuilder<Asset, Asset, QAfterFilterCondition> isTrashedEqualTo( |   QueryBuilder<Asset, Asset, QAfterFilterCondition> isTrashedEqualTo( | ||||||
|       bool value) { |       bool value) { | ||||||
|     return QueryBuilder.apply(this, (query) { |     return QueryBuilder.apply(this, (query) { | ||||||
| @ -2527,18 +2508,6 @@ extension AssetQuerySortBy on QueryBuilder<Asset, Asset, QSortBy> { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   QueryBuilder<Asset, Asset, QAfterSortBy> sortByIsReadOnly() { |  | ||||||
|     return QueryBuilder.apply(this, (query) { |  | ||||||
|       return query.addSortBy(r'isReadOnly', Sort.asc); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   QueryBuilder<Asset, Asset, QAfterSortBy> sortByIsReadOnlyDesc() { |  | ||||||
|     return QueryBuilder.apply(this, (query) { |  | ||||||
|       return query.addSortBy(r'isReadOnly', Sort.desc); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   QueryBuilder<Asset, Asset, QAfterSortBy> sortByIsTrashed() { |   QueryBuilder<Asset, Asset, QAfterSortBy> sortByIsTrashed() { | ||||||
|     return QueryBuilder.apply(this, (query) { |     return QueryBuilder.apply(this, (query) { | ||||||
|       return query.addSortBy(r'isTrashed', Sort.asc); |       return query.addSortBy(r'isTrashed', Sort.asc); | ||||||
| @ -2793,18 +2762,6 @@ extension AssetQuerySortThenBy on QueryBuilder<Asset, Asset, QSortThenBy> { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   QueryBuilder<Asset, Asset, QAfterSortBy> thenByIsReadOnly() { |  | ||||||
|     return QueryBuilder.apply(this, (query) { |  | ||||||
|       return query.addSortBy(r'isReadOnly', Sort.asc); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   QueryBuilder<Asset, Asset, QAfterSortBy> thenByIsReadOnlyDesc() { |  | ||||||
|     return QueryBuilder.apply(this, (query) { |  | ||||||
|       return query.addSortBy(r'isReadOnly', Sort.desc); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   QueryBuilder<Asset, Asset, QAfterSortBy> thenByIsTrashed() { |   QueryBuilder<Asset, Asset, QAfterSortBy> thenByIsTrashed() { | ||||||
|     return QueryBuilder.apply(this, (query) { |     return QueryBuilder.apply(this, (query) { | ||||||
|       return query.addSortBy(r'isTrashed', Sort.asc); |       return query.addSortBy(r'isTrashed', Sort.asc); | ||||||
| @ -2995,12 +2952,6 @@ extension AssetQueryWhereDistinct on QueryBuilder<Asset, Asset, QDistinct> { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   QueryBuilder<Asset, Asset, QDistinct> distinctByIsReadOnly() { |  | ||||||
|     return QueryBuilder.apply(this, (query) { |  | ||||||
|       return query.addDistinctBy(r'isReadOnly'); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   QueryBuilder<Asset, Asset, QDistinct> distinctByIsTrashed() { |   QueryBuilder<Asset, Asset, QDistinct> distinctByIsTrashed() { | ||||||
|     return QueryBuilder.apply(this, (query) { |     return QueryBuilder.apply(this, (query) { | ||||||
|       return query.addDistinctBy(r'isTrashed'); |       return query.addDistinctBy(r'isTrashed'); | ||||||
| @ -3136,12 +3087,6 @@ extension AssetQueryProperty on QueryBuilder<Asset, Asset, QQueryProperty> { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   QueryBuilder<Asset, bool, QQueryOperations> isReadOnlyProperty() { |  | ||||||
|     return QueryBuilder.apply(this, (query) { |  | ||||||
|       return query.addPropertyName(r'isReadOnly'); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   QueryBuilder<Asset, bool, QQueryOperations> isTrashedProperty() { |   QueryBuilder<Asset, bool, QQueryOperations> isTrashedProperty() { | ||||||
|     return QueryBuilder.apply(this, (query) { |     return QueryBuilder.apply(this, (query) { | ||||||
|       return query.addPropertyName(r'isTrashed'); |       return query.addPropertyName(r'isTrashed'); | ||||||
|  | |||||||
| @ -71,19 +71,6 @@ extension AssetListExtension on Iterable<Asset> { | |||||||
|     return this; |     return this; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /// Returns the assets that are present on a file system which has write permission |  | ||||||
|   /// This filters out assets on readOnly external library to which we cannot perform any write operation |  | ||||||
|   Iterable<Asset> writableOnly({ |  | ||||||
|     void Function()? errorCallback, |  | ||||||
|   }) { |  | ||||||
|     final bool onlyWritable = every((e) => !e.isReadOnly); |  | ||||||
|     if (!onlyWritable) { |  | ||||||
|       if (errorCallback != null) errorCallback(); |  | ||||||
|       return where((a) => !a.isReadOnly); |  | ||||||
|     } |  | ||||||
|     return this; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   /// Filters out offline assets and returns those that are still accessible by the Immich server |   /// Filters out offline assets and returns those that are still accessible by the Immich server | ||||||
|   Iterable<Asset> nonOfflineOnly({ |   Iterable<Asset> nonOfflineOnly({ | ||||||
|     void Function()? errorCallback, |     void Function()? errorCallback, | ||||||
|  | |||||||
| @ -102,16 +102,6 @@ class BottomGalleryBar extends ConsumerWidget { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void handleDelete() async { |     void handleDelete() async { | ||||||
|       // Cannot delete readOnly / external assets. They are handled through library offline jobs |  | ||||||
|       if (asset.isReadOnly) { |  | ||||||
|         ImmichToast.show( |  | ||||||
|           durationInSecond: 1, |  | ||||||
|           context: context, |  | ||||||
|           msg: 'asset_action_delete_err_read_only'.tr(), |  | ||||||
|           gravity: ToastGravity.BOTTOM, |  | ||||||
|         ); |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
|       Future<bool> onDelete(bool force) async { |       Future<bool> onDelete(bool force) async { | ||||||
|         final isDeleted = await ref.read(assetProvider.notifier).deleteAssets( |         final isDeleted = await ref.read(assetProvider.notifier).deleteAssets( | ||||||
|           {asset}, |           {asset}, | ||||||
|  | |||||||
| @ -42,7 +42,7 @@ class ExifBottomSheet extends HookConsumerWidget { | |||||||
|             fontSize: 14, |             fontSize: 14, | ||||||
|           ), |           ), | ||||||
|         ), |         ), | ||||||
|         if (asset.isRemote && !asset.isReadOnly) |         if (asset.isRemote) | ||||||
|           IconButton( |           IconButton( | ||||||
|             onPressed: () => handleEditDateTime( |             onPressed: () => handleEditDateTime( | ||||||
|               ref, |               ref, | ||||||
|  | |||||||
| @ -24,7 +24,7 @@ class ExifLocation extends StatelessWidget { | |||||||
|     final hasCoordinates = exifInfo?.hasCoordinates ?? false; |     final hasCoordinates = exifInfo?.hasCoordinates ?? false; | ||||||
|     // Guard no lat/lng |     // Guard no lat/lng | ||||||
|     if (!hasCoordinates) { |     if (!hasCoordinates) { | ||||||
|       return asset.isRemote && !asset.isReadOnly |       return asset.isRemote | ||||||
|           ? ListTile( |           ? ListTile( | ||||||
|               minLeadingWidth: 0, |               minLeadingWidth: 0, | ||||||
|               contentPadding: const EdgeInsets.all(0), |               contentPadding: const EdgeInsets.all(0), | ||||||
| @ -57,7 +57,7 @@ class ExifLocation extends StatelessWidget { | |||||||
|                     fontWeight: FontWeight.w600, |                     fontWeight: FontWeight.w600, | ||||||
|                   ), |                   ), | ||||||
|                 ).tr(), |                 ).tr(), | ||||||
|                 if (asset.isRemote && !asset.isReadOnly) |                 if (asset.isRemote) | ||||||
|                   IconButton( |                   IconButton( | ||||||
|                     onPressed: editLocation, |                     onPressed: editLocation, | ||||||
|                     icon: const Icon(Icons.edit_outlined), |                     icon: const Icon(Icons.edit_outlined), | ||||||
|  | |||||||
| @ -63,6 +63,12 @@ abstract class _$AppRouter extends RootStackRouter { | |||||||
|         child: const AllPeoplePage(), |         child: const AllPeoplePage(), | ||||||
|       ); |       ); | ||||||
|     }, |     }, | ||||||
|  |     AllPlacesRoute.name: (routeData) { | ||||||
|  |       return AutoRoutePage<dynamic>( | ||||||
|  |         routeData: routeData, | ||||||
|  |         child: const AllPlacesPage(), | ||||||
|  |       ); | ||||||
|  |     }, | ||||||
|     AllVideosRoute.name: (routeData) { |     AllVideosRoute.name: (routeData) { | ||||||
|       return AutoRoutePage<dynamic>( |       return AutoRoutePage<dynamic>( | ||||||
|         routeData: routeData, |         routeData: routeData, | ||||||
| @ -138,12 +144,6 @@ abstract class _$AppRouter extends RootStackRouter { | |||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|     }, |     }, | ||||||
|     AllPlacesRoute.name: (routeData) { |  | ||||||
|       return AutoRoutePage<dynamic>( |  | ||||||
|         routeData: routeData, |  | ||||||
|         child: const AllPlacesPage(), |  | ||||||
|       ); |  | ||||||
|     }, |  | ||||||
|     FailedBackupStatusRoute.name: (routeData) { |     FailedBackupStatusRoute.name: (routeData) { | ||||||
|       return AutoRoutePage<dynamic>( |       return AutoRoutePage<dynamic>( | ||||||
|         routeData: routeData, |         routeData: routeData, | ||||||
| @ -525,6 +525,20 @@ class AllPeopleRoute extends PageRouteInfo<void> { | |||||||
|   static const PageInfo<void> page = PageInfo<void>(name); |   static const PageInfo<void> page = PageInfo<void>(name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// generated route for | ||||||
|  | /// [AllPlacesPage] | ||||||
|  | class AllPlacesRoute extends PageRouteInfo<void> { | ||||||
|  |   const AllPlacesRoute({List<PageRouteInfo>? children}) | ||||||
|  |       : super( | ||||||
|  |           AllPlacesRoute.name, | ||||||
|  |           initialChildren: children, | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |   static const String name = 'AllPlacesRoute'; | ||||||
|  | 
 | ||||||
|  |   static const PageInfo<void> page = PageInfo<void>(name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [AllVideosPage] | /// [AllVideosPage] | ||||||
| class AllVideosRoute extends PageRouteInfo<void> { | class AllVideosRoute extends PageRouteInfo<void> { | ||||||
| @ -752,20 +766,6 @@ class CreateAlbumRouteArgs { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// generated route for |  | ||||||
| /// [AllPlacesPage] |  | ||||||
| class AllPlacesRoute extends PageRouteInfo<void> { |  | ||||||
|   const AllPlacesRoute({List<PageRouteInfo>? children}) |  | ||||||
|       : super( |  | ||||||
|           AllPlacesRoute.name, |  | ||||||
|           initialChildren: children, |  | ||||||
|         ); |  | ||||||
| 
 |  | ||||||
|   static const String name = 'CuratedLocationRoute'; |  | ||||||
| 
 |  | ||||||
|   static const PageInfo<void> page = PageInfo<void>(name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// generated route for | /// generated route for | ||||||
| /// [FailedBackupStatusPage] | /// [FailedBackupStatusPage] | ||||||
| class FailedBackupStatusRoute extends PageRouteInfo<void> { | class FailedBackupStatusRoute extends PageRouteInfo<void> { | ||||||
|  | |||||||
| @ -184,11 +184,6 @@ class MultiselectGrid extends HookConsumerWidget { | |||||||
|               currentUser, |               currentUser, | ||||||
|               errorCallback: errorBuilder('home_page_delete_err_partner'.tr()), |               errorCallback: errorBuilder('home_page_delete_err_partner'.tr()), | ||||||
|             ) |             ) | ||||||
|             // Cannot delete readOnly / external assets. They are handled through library offline jobs |  | ||||||
|             .writableOnly( |  | ||||||
|               errorCallback: |  | ||||||
|                   errorBuilder('asset_action_delete_err_read_only'.tr()), |  | ||||||
|             ) |  | ||||||
|             .toList(); |             .toList(); | ||||||
|         final isDeleted = await ref |         final isDeleted = await ref | ||||||
|             .read(assetProvider.notifier) |             .read(assetProvider.notifier) | ||||||
| @ -238,13 +233,7 @@ class MultiselectGrid extends HookConsumerWidget { | |||||||
|         final toDelete = ownedRemoteSelection( |         final toDelete = ownedRemoteSelection( | ||||||
|           localErrorMessage: 'home_page_delete_remote_err_local'.tr(), |           localErrorMessage: 'home_page_delete_remote_err_local'.tr(), | ||||||
|           ownerErrorMessage: 'home_page_delete_err_partner'.tr(), |           ownerErrorMessage: 'home_page_delete_err_partner'.tr(), | ||||||
|         ) |         ).toList(); | ||||||
|             // Cannot delete readOnly / external assets. They are handled through library offline jobs |  | ||||||
|             .writableOnly( |  | ||||||
|               errorCallback: |  | ||||||
|                   errorBuilder('asset_action_delete_err_read_only'.tr()), |  | ||||||
|             ) |  | ||||||
|             .toList(); |  | ||||||
| 
 | 
 | ||||||
|         final isDeleted = await ref |         final isDeleted = await ref | ||||||
|             .read(assetProvider.notifier) |             .read(assetProvider.notifier) | ||||||
| @ -372,12 +361,8 @@ class MultiselectGrid extends HookConsumerWidget { | |||||||
|         final remoteAssets = ownedRemoteSelection( |         final remoteAssets = ownedRemoteSelection( | ||||||
|           localErrorMessage: 'home_page_favorite_err_local'.tr(), |           localErrorMessage: 'home_page_favorite_err_local'.tr(), | ||||||
|           ownerErrorMessage: 'home_page_favorite_err_partner'.tr(), |           ownerErrorMessage: 'home_page_favorite_err_partner'.tr(), | ||||||
|         ).writableOnly( |  | ||||||
|           // Assume readOnly assets to be present in a read-only mount. So do not write sidecar |  | ||||||
|           errorCallback: errorBuilder( |  | ||||||
|             'multiselect_grid_edit_date_time_err_read_only'.tr(), |  | ||||||
|           ), |  | ||||||
|         ); |         ); | ||||||
|  | 
 | ||||||
|         if (remoteAssets.isNotEmpty) { |         if (remoteAssets.isNotEmpty) { | ||||||
|           handleEditDateTime(ref, context, remoteAssets.toList()); |           handleEditDateTime(ref, context, remoteAssets.toList()); | ||||||
|         } |         } | ||||||
| @ -391,12 +376,8 @@ class MultiselectGrid extends HookConsumerWidget { | |||||||
|         final remoteAssets = ownedRemoteSelection( |         final remoteAssets = ownedRemoteSelection( | ||||||
|           localErrorMessage: 'home_page_favorite_err_local'.tr(), |           localErrorMessage: 'home_page_favorite_err_local'.tr(), | ||||||
|           ownerErrorMessage: 'home_page_favorite_err_partner'.tr(), |           ownerErrorMessage: 'home_page_favorite_err_partner'.tr(), | ||||||
|         ).writableOnly( |  | ||||||
|           // Assume readOnly assets to be present in a read-only mount. So do not write sidecar |  | ||||||
|           errorCallback: errorBuilder( |  | ||||||
|             'multiselect_grid_edit_gps_err_read_only'.tr(), |  | ||||||
|           ), |  | ||||||
|         ); |         ); | ||||||
|  | 
 | ||||||
|         if (remoteAssets.isNotEmpty) { |         if (remoteAssets.isNotEmpty) { | ||||||
|           handleEditLocation(ref, context, remoteAssets.toList()); |           handleEditLocation(ref, context, remoteAssets.toList()); | ||||||
|         } |         } | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								mobile/openapi/doc/AssetApi.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								mobile/openapi/doc/AssetApi.md
									
									
									
										generated
									
									
									
								
							| @ -955,7 +955,7 @@ void (empty response body) | |||||||
| [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) | ||||||
| 
 | 
 | ||||||
| # **uploadFile** | # **uploadFile** | ||||||
| > AssetFileUploadResponseDto uploadFile(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key, xImmichChecksum, duration, isArchived, isFavorite, isOffline, isReadOnly, isVisible, libraryId, livePhotoData, sidecarData) | > AssetFileUploadResponseDto uploadFile(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key, xImmichChecksum, duration, isArchived, isFavorite, isOffline, isVisible, libraryId, livePhotoData, sidecarData) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -989,14 +989,13 @@ final duration = duration_example; // String | | |||||||
| final isArchived = true; // bool |  | final isArchived = true; // bool |  | ||||||
| final isFavorite = true; // bool |  | final isFavorite = true; // bool |  | ||||||
| final isOffline = true; // bool |  | final isOffline = true; // bool |  | ||||||
| final isReadOnly = true; // bool |  |  | ||||||
| final isVisible = true; // bool |  | final isVisible = true; // bool |  | ||||||
| final libraryId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |  | final libraryId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |  | ||||||
| final livePhotoData = BINARY_DATA_HERE; // MultipartFile |  | final livePhotoData = BINARY_DATA_HERE; // MultipartFile |  | ||||||
| final sidecarData = BINARY_DATA_HERE; // MultipartFile |  | final sidecarData = BINARY_DATA_HERE; // MultipartFile |  | ||||||
| 
 | 
 | ||||||
| try { | try { | ||||||
|     final result = api_instance.uploadFile(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key, xImmichChecksum, duration, isArchived, isFavorite, isOffline, isReadOnly, isVisible, libraryId, livePhotoData, sidecarData); |     final result = api_instance.uploadFile(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key, xImmichChecksum, duration, isArchived, isFavorite, isOffline, isVisible, libraryId, livePhotoData, sidecarData); | ||||||
|     print(result); |     print(result); | ||||||
| } catch (e) { | } catch (e) { | ||||||
|     print('Exception when calling AssetApi->uploadFile: $e\n'); |     print('Exception when calling AssetApi->uploadFile: $e\n'); | ||||||
| @ -1018,7 +1017,6 @@ Name | Type | Description  | Notes | |||||||
|  **isArchived** | **bool**|  | [optional]  |  **isArchived** | **bool**|  | [optional]  | ||||||
|  **isFavorite** | **bool**|  | [optional]  |  **isFavorite** | **bool**|  | [optional]  | ||||||
|  **isOffline** | **bool**|  | [optional]  |  **isOffline** | **bool**|  | [optional]  | ||||||
|  **isReadOnly** | **bool**|  | [optional]  |  | ||||||
|  **isVisible** | **bool**|  | [optional]  |  **isVisible** | **bool**|  | [optional]  | ||||||
|  **libraryId** | **String**|  | [optional]  |  **libraryId** | **String**|  | [optional]  | ||||||
|  **livePhotoData** | **MultipartFile**|  | [optional]  |  **livePhotoData** | **MultipartFile**|  | [optional]  | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								mobile/openapi/doc/AssetResponseDto.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								mobile/openapi/doc/AssetResponseDto.md
									
									
									
										generated
									
									
									
								
							| @ -18,10 +18,10 @@ Name | Type | Description | Notes | |||||||
| **hasMetadata** | **bool** |  |  | **hasMetadata** | **bool** |  |  | ||||||
| **id** | **String** |  |  | **id** | **String** |  |  | ||||||
| **isArchived** | **bool** |  |  | **isArchived** | **bool** |  |  | ||||||
| **isExternal** | **bool** |  |  | **isExternal** | **bool** | This property was deprecated in v1.104.0 | [optional]  | ||||||
| **isFavorite** | **bool** |  |  | **isFavorite** | **bool** |  |  | ||||||
| **isOffline** | **bool** |  |  | **isOffline** | **bool** |  |  | ||||||
| **isReadOnly** | **bool** |  |  | **isReadOnly** | **bool** | This property was deprecated in v1.104.0 | [optional]  | ||||||
| **isTrashed** | **bool** |  |  | **isTrashed** | **bool** |  |  | ||||||
| **libraryId** | **String** |  |  | **libraryId** | **String** |  |  | ||||||
| **livePhotoVideoId** | **String** |  | [optional]  | **livePhotoVideoId** | **String** |  | [optional]  | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								mobile/openapi/doc/MetadataSearchDto.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								mobile/openapi/doc/MetadataSearchDto.md
									
									
									
										generated
									
									
									
								
							| @ -19,12 +19,10 @@ Name | Type | Description | Notes | |||||||
| **id** | **String** |  | [optional]  | **id** | **String** |  | [optional]  | ||||||
| **isArchived** | **bool** |  | [optional]  | **isArchived** | **bool** |  | [optional]  | ||||||
| **isEncoded** | **bool** |  | [optional]  | **isEncoded** | **bool** |  | [optional]  | ||||||
| **isExternal** | **bool** |  | [optional]  |  | ||||||
| **isFavorite** | **bool** |  | [optional]  | **isFavorite** | **bool** |  | [optional]  | ||||||
| **isMotion** | **bool** |  | [optional]  | **isMotion** | **bool** |  | [optional]  | ||||||
| **isNotInAlbum** | **bool** |  | [optional]  | **isNotInAlbum** | **bool** |  | [optional]  | ||||||
| **isOffline** | **bool** |  | [optional]  | **isOffline** | **bool** |  | [optional]  | ||||||
| **isReadOnly** | **bool** |  | [optional]  |  | ||||||
| **isVisible** | **bool** |  | [optional]  | **isVisible** | **bool** |  | [optional]  | ||||||
| **lensModel** | **String** |  | [optional]  | **lensModel** | **String** |  | [optional]  | ||||||
| **libraryId** | **String** |  | [optional]  | **libraryId** | **String** |  | [optional]  | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								mobile/openapi/doc/SmartSearchDto.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								mobile/openapi/doc/SmartSearchDto.md
									
									
									
										generated
									
									
									
								
							| @ -15,12 +15,10 @@ Name | Type | Description | Notes | |||||||
| **deviceId** | **String** |  | [optional]  | **deviceId** | **String** |  | [optional]  | ||||||
| **isArchived** | **bool** |  | [optional]  | **isArchived** | **bool** |  | [optional]  | ||||||
| **isEncoded** | **bool** |  | [optional]  | **isEncoded** | **bool** |  | [optional]  | ||||||
| **isExternal** | **bool** |  | [optional]  |  | ||||||
| **isFavorite** | **bool** |  | [optional]  | **isFavorite** | **bool** |  | [optional]  | ||||||
| **isMotion** | **bool** |  | [optional]  | **isMotion** | **bool** |  | [optional]  | ||||||
| **isNotInAlbum** | **bool** |  | [optional]  | **isNotInAlbum** | **bool** |  | [optional]  | ||||||
| **isOffline** | **bool** |  | [optional]  | **isOffline** | **bool** |  | [optional]  | ||||||
| **isReadOnly** | **bool** |  | [optional]  |  | ||||||
| **isVisible** | **bool** |  | [optional]  | **isVisible** | **bool** |  | [optional]  | ||||||
| **lensModel** | **String** |  | [optional]  | **lensModel** | **String** |  | [optional]  | ||||||
| **libraryId** | **String** |  | [optional]  | **libraryId** | **String** |  | [optional]  | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								mobile/openapi/lib/api/asset_api.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										14
									
								
								mobile/openapi/lib/api/asset_api.dart
									
									
									
										generated
									
									
									
								
							| @ -968,8 +968,6 @@ class AssetApi { | |||||||
|   /// |   /// | ||||||
|   /// * [bool] isOffline: |   /// * [bool] isOffline: | ||||||
|   /// |   /// | ||||||
|   /// * [bool] isReadOnly: |  | ||||||
|   /// |  | ||||||
|   /// * [bool] isVisible: |   /// * [bool] isVisible: | ||||||
|   /// |   /// | ||||||
|   /// * [String] libraryId: |   /// * [String] libraryId: | ||||||
| @ -977,7 +975,7 @@ class AssetApi { | |||||||
|   /// * [MultipartFile] livePhotoData: |   /// * [MultipartFile] livePhotoData: | ||||||
|   /// |   /// | ||||||
|   /// * [MultipartFile] sidecarData: |   /// * [MultipartFile] sidecarData: | ||||||
|   Future<Response> uploadFileWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isReadOnly, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async { |   Future<Response> uploadFileWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async { | ||||||
|     // ignore: prefer_const_declarations |     // ignore: prefer_const_declarations | ||||||
|     final path = r'/asset/upload'; |     final path = r'/asset/upload'; | ||||||
| 
 | 
 | ||||||
| @ -1037,10 +1035,6 @@ class AssetApi { | |||||||
|       hasFields = true; |       hasFields = true; | ||||||
|       mp.fields[r'isOffline'] = parameterToString(isOffline); |       mp.fields[r'isOffline'] = parameterToString(isOffline); | ||||||
|     } |     } | ||||||
|     if (isReadOnly != null) { |  | ||||||
|       hasFields = true; |  | ||||||
|       mp.fields[r'isReadOnly'] = parameterToString(isReadOnly); |  | ||||||
|     } |  | ||||||
|     if (isVisible != null) { |     if (isVisible != null) { | ||||||
|       hasFields = true; |       hasFields = true; | ||||||
|       mp.fields[r'isVisible'] = parameterToString(isVisible); |       mp.fields[r'isVisible'] = parameterToString(isVisible); | ||||||
| @ -1099,8 +1093,6 @@ class AssetApi { | |||||||
|   /// |   /// | ||||||
|   /// * [bool] isOffline: |   /// * [bool] isOffline: | ||||||
|   /// |   /// | ||||||
|   /// * [bool] isReadOnly: |  | ||||||
|   /// |  | ||||||
|   /// * [bool] isVisible: |   /// * [bool] isVisible: | ||||||
|   /// |   /// | ||||||
|   /// * [String] libraryId: |   /// * [String] libraryId: | ||||||
| @ -1108,8 +1100,8 @@ class AssetApi { | |||||||
|   /// * [MultipartFile] livePhotoData: |   /// * [MultipartFile] livePhotoData: | ||||||
|   /// |   /// | ||||||
|   /// * [MultipartFile] sidecarData: |   /// * [MultipartFile] sidecarData: | ||||||
|   Future<AssetFileUploadResponseDto?> uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isReadOnly, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async { |   Future<AssetFileUploadResponseDto?> uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async { | ||||||
|     final response = await uploadFileWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt,  key: key, xImmichChecksum: xImmichChecksum, duration: duration, isArchived: isArchived, isFavorite: isFavorite, isOffline: isOffline, isReadOnly: isReadOnly, isVisible: isVisible, libraryId: libraryId, livePhotoData: livePhotoData, sidecarData: sidecarData, ); |     final response = await uploadFileWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt,  key: key, xImmichChecksum: xImmichChecksum, duration: duration, isArchived: isArchived, isFavorite: isFavorite, isOffline: isOffline, isVisible: isVisible, libraryId: libraryId, livePhotoData: livePhotoData, sidecarData: sidecarData, ); | ||||||
|     if (response.statusCode >= HttpStatus.badRequest) { |     if (response.statusCode >= HttpStatus.badRequest) { | ||||||
|       throw ApiException(response.statusCode, await _decodeBodyBytes(response)); |       throw ApiException(response.statusCode, await _decodeBodyBytes(response)); | ||||||
|     } |     } | ||||||
|  | |||||||
							
								
								
									
										40
									
								
								mobile/openapi/lib/model/asset_response_dto.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										40
									
								
								mobile/openapi/lib/model/asset_response_dto.dart
									
									
									
										generated
									
									
									
								
							| @ -23,10 +23,10 @@ class AssetResponseDto { | |||||||
|     required this.hasMetadata, |     required this.hasMetadata, | ||||||
|     required this.id, |     required this.id, | ||||||
|     required this.isArchived, |     required this.isArchived, | ||||||
|     required this.isExternal, |     this.isExternal, | ||||||
|     required this.isFavorite, |     required this.isFavorite, | ||||||
|     required this.isOffline, |     required this.isOffline, | ||||||
|     required this.isReadOnly, |     this.isReadOnly, | ||||||
|     required this.isTrashed, |     required this.isTrashed, | ||||||
|     required this.libraryId, |     required this.libraryId, | ||||||
|     this.livePhotoVideoId, |     this.livePhotoVideoId, | ||||||
| @ -74,13 +74,27 @@ class AssetResponseDto { | |||||||
| 
 | 
 | ||||||
|   bool isArchived; |   bool isArchived; | ||||||
| 
 | 
 | ||||||
|   bool isExternal; |   /// This property was deprecated in v1.104.0 | ||||||
|  |   /// | ||||||
|  |   /// 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 | ||||||
|  |   /// source code must fall back to having a nullable type. | ||||||
|  |   /// Consider adding a "default:" property in the specification file to hide this note. | ||||||
|  |   /// | ||||||
|  |   bool? isExternal; | ||||||
| 
 | 
 | ||||||
|   bool isFavorite; |   bool isFavorite; | ||||||
| 
 | 
 | ||||||
|   bool isOffline; |   bool isOffline; | ||||||
| 
 | 
 | ||||||
|   bool isReadOnly; |   /// This property was deprecated in v1.104.0 | ||||||
|  |   /// | ||||||
|  |   /// 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 | ||||||
|  |   /// source code must fall back to having a nullable type. | ||||||
|  |   /// Consider adding a "default:" property in the specification file to hide this note. | ||||||
|  |   /// | ||||||
|  |   bool? isReadOnly; | ||||||
| 
 | 
 | ||||||
|   bool isTrashed; |   bool isTrashed; | ||||||
| 
 | 
 | ||||||
| @ -178,10 +192,10 @@ class AssetResponseDto { | |||||||
|     (hasMetadata.hashCode) + |     (hasMetadata.hashCode) + | ||||||
|     (id.hashCode) + |     (id.hashCode) + | ||||||
|     (isArchived.hashCode) + |     (isArchived.hashCode) + | ||||||
|     (isExternal.hashCode) + |     (isExternal == null ? 0 : isExternal!.hashCode) + | ||||||
|     (isFavorite.hashCode) + |     (isFavorite.hashCode) + | ||||||
|     (isOffline.hashCode) + |     (isOffline.hashCode) + | ||||||
|     (isReadOnly.hashCode) + |     (isReadOnly == null ? 0 : isReadOnly!.hashCode) + | ||||||
|     (isTrashed.hashCode) + |     (isTrashed.hashCode) + | ||||||
|     (libraryId.hashCode) + |     (libraryId.hashCode) + | ||||||
|     (livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode) + |     (livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode) + | ||||||
| @ -220,10 +234,18 @@ class AssetResponseDto { | |||||||
|       json[r'hasMetadata'] = this.hasMetadata; |       json[r'hasMetadata'] = this.hasMetadata; | ||||||
|       json[r'id'] = this.id; |       json[r'id'] = this.id; | ||||||
|       json[r'isArchived'] = this.isArchived; |       json[r'isArchived'] = this.isArchived; | ||||||
|  |     if (this.isExternal != null) { | ||||||
|       json[r'isExternal'] = this.isExternal; |       json[r'isExternal'] = this.isExternal; | ||||||
|  |     } else { | ||||||
|  |     //  json[r'isExternal'] = null; | ||||||
|  |     } | ||||||
|       json[r'isFavorite'] = this.isFavorite; |       json[r'isFavorite'] = this.isFavorite; | ||||||
|       json[r'isOffline'] = this.isOffline; |       json[r'isOffline'] = this.isOffline; | ||||||
|  |     if (this.isReadOnly != null) { | ||||||
|       json[r'isReadOnly'] = this.isReadOnly; |       json[r'isReadOnly'] = this.isReadOnly; | ||||||
|  |     } else { | ||||||
|  |     //  json[r'isReadOnly'] = null; | ||||||
|  |     } | ||||||
|       json[r'isTrashed'] = this.isTrashed; |       json[r'isTrashed'] = this.isTrashed; | ||||||
|       json[r'libraryId'] = this.libraryId; |       json[r'libraryId'] = this.libraryId; | ||||||
|     if (this.livePhotoVideoId != null) { |     if (this.livePhotoVideoId != null) { | ||||||
| @ -287,10 +309,10 @@ class AssetResponseDto { | |||||||
|         hasMetadata: mapValueOfType<bool>(json, r'hasMetadata')!, |         hasMetadata: mapValueOfType<bool>(json, r'hasMetadata')!, | ||||||
|         id: mapValueOfType<String>(json, r'id')!, |         id: mapValueOfType<String>(json, r'id')!, | ||||||
|         isArchived: mapValueOfType<bool>(json, r'isArchived')!, |         isArchived: mapValueOfType<bool>(json, r'isArchived')!, | ||||||
|         isExternal: mapValueOfType<bool>(json, r'isExternal')!, |         isExternal: mapValueOfType<bool>(json, r'isExternal'), | ||||||
|         isFavorite: mapValueOfType<bool>(json, r'isFavorite')!, |         isFavorite: mapValueOfType<bool>(json, r'isFavorite')!, | ||||||
|         isOffline: mapValueOfType<bool>(json, r'isOffline')!, |         isOffline: mapValueOfType<bool>(json, r'isOffline')!, | ||||||
|         isReadOnly: mapValueOfType<bool>(json, r'isReadOnly')!, |         isReadOnly: mapValueOfType<bool>(json, r'isReadOnly'), | ||||||
|         isTrashed: mapValueOfType<bool>(json, r'isTrashed')!, |         isTrashed: mapValueOfType<bool>(json, r'isTrashed')!, | ||||||
|         libraryId: mapValueOfType<String>(json, r'libraryId')!, |         libraryId: mapValueOfType<String>(json, r'libraryId')!, | ||||||
|         livePhotoVideoId: mapValueOfType<String>(json, r'livePhotoVideoId'), |         livePhotoVideoId: mapValueOfType<String>(json, r'livePhotoVideoId'), | ||||||
| @ -365,10 +387,8 @@ class AssetResponseDto { | |||||||
|     'hasMetadata', |     'hasMetadata', | ||||||
|     'id', |     'id', | ||||||
|     'isArchived', |     'isArchived', | ||||||
|     'isExternal', |  | ||||||
|     'isFavorite', |     'isFavorite', | ||||||
|     'isOffline', |     'isOffline', | ||||||
|     'isReadOnly', |  | ||||||
|     'isTrashed', |     'isTrashed', | ||||||
|     'libraryId', |     'libraryId', | ||||||
|     'localDateTime', |     'localDateTime', | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								mobile/openapi/lib/model/metadata_search_dto.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										36
									
								
								mobile/openapi/lib/model/metadata_search_dto.dart
									
									
									
										generated
									
									
									
								
							| @ -24,12 +24,10 @@ class MetadataSearchDto { | |||||||
|     this.id, |     this.id, | ||||||
|     this.isArchived, |     this.isArchived, | ||||||
|     this.isEncoded, |     this.isEncoded, | ||||||
|     this.isExternal, |  | ||||||
|     this.isFavorite, |     this.isFavorite, | ||||||
|     this.isMotion, |     this.isMotion, | ||||||
|     this.isNotInAlbum, |     this.isNotInAlbum, | ||||||
|     this.isOffline, |     this.isOffline, | ||||||
|     this.isReadOnly, |  | ||||||
|     this.isVisible, |     this.isVisible, | ||||||
|     this.lensModel, |     this.lensModel, | ||||||
|     this.libraryId, |     this.libraryId, | ||||||
| @ -148,14 +146,6 @@ class MetadataSearchDto { | |||||||
|   /// |   /// | ||||||
|   bool? isEncoded; |   bool? isEncoded; | ||||||
| 
 | 
 | ||||||
|   /// |  | ||||||
|   /// 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 |  | ||||||
|   /// source code must fall back to having a nullable type. |  | ||||||
|   /// Consider adding a "default:" property in the specification file to hide this note. |  | ||||||
|   /// |  | ||||||
|   bool? isExternal; |  | ||||||
| 
 |  | ||||||
|   /// |   /// | ||||||
|   /// Please note: This property should have been non-nullable! Since the specification file |   /// 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 |   /// does not include a default value (using the "default:" property), however, the generated | ||||||
| @ -188,14 +178,6 @@ class MetadataSearchDto { | |||||||
|   /// |   /// | ||||||
|   bool? isOffline; |   bool? isOffline; | ||||||
| 
 | 
 | ||||||
|   /// |  | ||||||
|   /// 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 |  | ||||||
|   /// source code must fall back to having a nullable type. |  | ||||||
|   /// Consider adding a "default:" property in the specification file to hide this note. |  | ||||||
|   /// |  | ||||||
|   bool? isReadOnly; |  | ||||||
| 
 |  | ||||||
|   /// |   /// | ||||||
|   /// Please note: This property should have been non-nullable! Since the specification file |   /// 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 |   /// does not include a default value (using the "default:" property), however, the generated | ||||||
| @ -426,12 +408,10 @@ class MetadataSearchDto { | |||||||
|     other.id == id && |     other.id == id && | ||||||
|     other.isArchived == isArchived && |     other.isArchived == isArchived && | ||||||
|     other.isEncoded == isEncoded && |     other.isEncoded == isEncoded && | ||||||
|     other.isExternal == isExternal && |  | ||||||
|     other.isFavorite == isFavorite && |     other.isFavorite == isFavorite && | ||||||
|     other.isMotion == isMotion && |     other.isMotion == isMotion && | ||||||
|     other.isNotInAlbum == isNotInAlbum && |     other.isNotInAlbum == isNotInAlbum && | ||||||
|     other.isOffline == isOffline && |     other.isOffline == isOffline && | ||||||
|     other.isReadOnly == isReadOnly && |  | ||||||
|     other.isVisible == isVisible && |     other.isVisible == isVisible && | ||||||
|     other.lensModel == lensModel && |     other.lensModel == lensModel && | ||||||
|     other.libraryId == libraryId && |     other.libraryId == libraryId && | ||||||
| @ -475,12 +455,10 @@ class MetadataSearchDto { | |||||||
|     (id == null ? 0 : id!.hashCode) + |     (id == null ? 0 : id!.hashCode) + | ||||||
|     (isArchived == null ? 0 : isArchived!.hashCode) + |     (isArchived == null ? 0 : isArchived!.hashCode) + | ||||||
|     (isEncoded == null ? 0 : isEncoded!.hashCode) + |     (isEncoded == null ? 0 : isEncoded!.hashCode) + | ||||||
|     (isExternal == null ? 0 : isExternal!.hashCode) + |  | ||||||
|     (isFavorite == null ? 0 : isFavorite!.hashCode) + |     (isFavorite == null ? 0 : isFavorite!.hashCode) + | ||||||
|     (isMotion == null ? 0 : isMotion!.hashCode) + |     (isMotion == null ? 0 : isMotion!.hashCode) + | ||||||
|     (isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) + |     (isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) + | ||||||
|     (isOffline == null ? 0 : isOffline!.hashCode) + |     (isOffline == null ? 0 : isOffline!.hashCode) + | ||||||
|     (isReadOnly == null ? 0 : isReadOnly!.hashCode) + |  | ||||||
|     (isVisible == null ? 0 : isVisible!.hashCode) + |     (isVisible == null ? 0 : isVisible!.hashCode) + | ||||||
|     (lensModel == null ? 0 : lensModel!.hashCode) + |     (lensModel == null ? 0 : lensModel!.hashCode) + | ||||||
|     (libraryId == null ? 0 : libraryId!.hashCode) + |     (libraryId == null ? 0 : libraryId!.hashCode) + | ||||||
| @ -511,7 +489,7 @@ class MetadataSearchDto { | |||||||
|     (withStacked == null ? 0 : withStacked!.hashCode); |     (withStacked == null ? 0 : withStacked!.hashCode); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   String toString() => 'MetadataSearchDto[checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isArchived=$isArchived, isEncoded=$isEncoded, isExternal=$isExternal, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, resizePath=$resizePath, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, webpPath=$webpPath, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]'; |   String toString() => 'MetadataSearchDto[checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, resizePath=$resizePath, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, webpPath=$webpPath, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]'; | ||||||
| 
 | 
 | ||||||
|   Map<String, dynamic> toJson() { |   Map<String, dynamic> toJson() { | ||||||
|     final json = <String, dynamic>{}; |     final json = <String, dynamic>{}; | ||||||
| @ -570,11 +548,6 @@ class MetadataSearchDto { | |||||||
|     } else { |     } else { | ||||||
|     //  json[r'isEncoded'] = null; |     //  json[r'isEncoded'] = null; | ||||||
|     } |     } | ||||||
|     if (this.isExternal != null) { |  | ||||||
|       json[r'isExternal'] = this.isExternal; |  | ||||||
|     } else { |  | ||||||
|     //  json[r'isExternal'] = null; |  | ||||||
|     } |  | ||||||
|     if (this.isFavorite != null) { |     if (this.isFavorite != null) { | ||||||
|       json[r'isFavorite'] = this.isFavorite; |       json[r'isFavorite'] = this.isFavorite; | ||||||
|     } else { |     } else { | ||||||
| @ -595,11 +568,6 @@ class MetadataSearchDto { | |||||||
|     } else { |     } else { | ||||||
|     //  json[r'isOffline'] = null; |     //  json[r'isOffline'] = null; | ||||||
|     } |     } | ||||||
|     if (this.isReadOnly != null) { |  | ||||||
|       json[r'isReadOnly'] = this.isReadOnly; |  | ||||||
|     } else { |  | ||||||
|     //  json[r'isReadOnly'] = null; |  | ||||||
|     } |  | ||||||
|     if (this.isVisible != null) { |     if (this.isVisible != null) { | ||||||
|       json[r'isVisible'] = this.isVisible; |       json[r'isVisible'] = this.isVisible; | ||||||
|     } else { |     } else { | ||||||
| @ -754,12 +722,10 @@ class MetadataSearchDto { | |||||||
|         id: mapValueOfType<String>(json, r'id'), |         id: mapValueOfType<String>(json, r'id'), | ||||||
|         isArchived: mapValueOfType<bool>(json, r'isArchived'), |         isArchived: mapValueOfType<bool>(json, r'isArchived'), | ||||||
|         isEncoded: mapValueOfType<bool>(json, r'isEncoded'), |         isEncoded: mapValueOfType<bool>(json, r'isEncoded'), | ||||||
|         isExternal: mapValueOfType<bool>(json, r'isExternal'), |  | ||||||
|         isFavorite: mapValueOfType<bool>(json, r'isFavorite'), |         isFavorite: mapValueOfType<bool>(json, r'isFavorite'), | ||||||
|         isMotion: mapValueOfType<bool>(json, r'isMotion'), |         isMotion: mapValueOfType<bool>(json, r'isMotion'), | ||||||
|         isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'), |         isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'), | ||||||
|         isOffline: mapValueOfType<bool>(json, r'isOffline'), |         isOffline: mapValueOfType<bool>(json, r'isOffline'), | ||||||
|         isReadOnly: mapValueOfType<bool>(json, r'isReadOnly'), |  | ||||||
|         isVisible: mapValueOfType<bool>(json, r'isVisible'), |         isVisible: mapValueOfType<bool>(json, r'isVisible'), | ||||||
|         lensModel: mapValueOfType<String>(json, r'lensModel'), |         lensModel: mapValueOfType<String>(json, r'lensModel'), | ||||||
|         libraryId: mapValueOfType<String>(json, r'libraryId'), |         libraryId: mapValueOfType<String>(json, r'libraryId'), | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								mobile/openapi/lib/model/smart_search_dto.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										36
									
								
								mobile/openapi/lib/model/smart_search_dto.dart
									
									
									
										generated
									
									
									
								
							| @ -20,12 +20,10 @@ class SmartSearchDto { | |||||||
|     this.deviceId, |     this.deviceId, | ||||||
|     this.isArchived, |     this.isArchived, | ||||||
|     this.isEncoded, |     this.isEncoded, | ||||||
|     this.isExternal, |  | ||||||
|     this.isFavorite, |     this.isFavorite, | ||||||
|     this.isMotion, |     this.isMotion, | ||||||
|     this.isNotInAlbum, |     this.isNotInAlbum, | ||||||
|     this.isOffline, |     this.isOffline, | ||||||
|     this.isReadOnly, |  | ||||||
|     this.isVisible, |     this.isVisible, | ||||||
|     this.lensModel, |     this.lensModel, | ||||||
|     this.libraryId, |     this.libraryId, | ||||||
| @ -104,14 +102,6 @@ class SmartSearchDto { | |||||||
|   /// |   /// | ||||||
|   bool? isEncoded; |   bool? isEncoded; | ||||||
| 
 | 
 | ||||||
|   /// |  | ||||||
|   /// 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 |  | ||||||
|   /// source code must fall back to having a nullable type. |  | ||||||
|   /// Consider adding a "default:" property in the specification file to hide this note. |  | ||||||
|   /// |  | ||||||
|   bool? isExternal; |  | ||||||
| 
 |  | ||||||
|   /// |   /// | ||||||
|   /// Please note: This property should have been non-nullable! Since the specification file |   /// 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 |   /// does not include a default value (using the "default:" property), however, the generated | ||||||
| @ -144,14 +134,6 @@ class SmartSearchDto { | |||||||
|   /// |   /// | ||||||
|   bool? isOffline; |   bool? isOffline; | ||||||
| 
 | 
 | ||||||
|   /// |  | ||||||
|   /// 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 |  | ||||||
|   /// source code must fall back to having a nullable type. |  | ||||||
|   /// Consider adding a "default:" property in the specification file to hide this note. |  | ||||||
|   /// |  | ||||||
|   bool? isReadOnly; |  | ||||||
| 
 |  | ||||||
|   /// |   /// | ||||||
|   /// Please note: This property should have been non-nullable! Since the specification file |   /// 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 |   /// does not include a default value (using the "default:" property), however, the generated | ||||||
| @ -306,12 +288,10 @@ class SmartSearchDto { | |||||||
|     other.deviceId == deviceId && |     other.deviceId == deviceId && | ||||||
|     other.isArchived == isArchived && |     other.isArchived == isArchived && | ||||||
|     other.isEncoded == isEncoded && |     other.isEncoded == isEncoded && | ||||||
|     other.isExternal == isExternal && |  | ||||||
|     other.isFavorite == isFavorite && |     other.isFavorite == isFavorite && | ||||||
|     other.isMotion == isMotion && |     other.isMotion == isMotion && | ||||||
|     other.isNotInAlbum == isNotInAlbum && |     other.isNotInAlbum == isNotInAlbum && | ||||||
|     other.isOffline == isOffline && |     other.isOffline == isOffline && | ||||||
|     other.isReadOnly == isReadOnly && |  | ||||||
|     other.isVisible == isVisible && |     other.isVisible == isVisible && | ||||||
|     other.lensModel == lensModel && |     other.lensModel == lensModel && | ||||||
|     other.libraryId == libraryId && |     other.libraryId == libraryId && | ||||||
| @ -343,12 +323,10 @@ class SmartSearchDto { | |||||||
|     (deviceId == null ? 0 : deviceId!.hashCode) + |     (deviceId == null ? 0 : deviceId!.hashCode) + | ||||||
|     (isArchived == null ? 0 : isArchived!.hashCode) + |     (isArchived == null ? 0 : isArchived!.hashCode) + | ||||||
|     (isEncoded == null ? 0 : isEncoded!.hashCode) + |     (isEncoded == null ? 0 : isEncoded!.hashCode) + | ||||||
|     (isExternal == null ? 0 : isExternal!.hashCode) + |  | ||||||
|     (isFavorite == null ? 0 : isFavorite!.hashCode) + |     (isFavorite == null ? 0 : isFavorite!.hashCode) + | ||||||
|     (isMotion == null ? 0 : isMotion!.hashCode) + |     (isMotion == null ? 0 : isMotion!.hashCode) + | ||||||
|     (isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) + |     (isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) + | ||||||
|     (isOffline == null ? 0 : isOffline!.hashCode) + |     (isOffline == null ? 0 : isOffline!.hashCode) + | ||||||
|     (isReadOnly == null ? 0 : isReadOnly!.hashCode) + |  | ||||||
|     (isVisible == null ? 0 : isVisible!.hashCode) + |     (isVisible == null ? 0 : isVisible!.hashCode) + | ||||||
|     (lensModel == null ? 0 : lensModel!.hashCode) + |     (lensModel == null ? 0 : lensModel!.hashCode) + | ||||||
|     (libraryId == null ? 0 : libraryId!.hashCode) + |     (libraryId == null ? 0 : libraryId!.hashCode) + | ||||||
| @ -371,7 +349,7 @@ class SmartSearchDto { | |||||||
|     (withExif == null ? 0 : withExif!.hashCode); |     (withExif == null ? 0 : withExif!.hashCode); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   String toString() => 'SmartSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isExternal=$isExternal, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif]'; |   String toString() => 'SmartSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif]'; | ||||||
| 
 | 
 | ||||||
|   Map<String, dynamic> toJson() { |   Map<String, dynamic> toJson() { | ||||||
|     final json = <String, dynamic>{}; |     final json = <String, dynamic>{}; | ||||||
| @ -410,11 +388,6 @@ class SmartSearchDto { | |||||||
|     } else { |     } else { | ||||||
|     //  json[r'isEncoded'] = null; |     //  json[r'isEncoded'] = null; | ||||||
|     } |     } | ||||||
|     if (this.isExternal != null) { |  | ||||||
|       json[r'isExternal'] = this.isExternal; |  | ||||||
|     } else { |  | ||||||
|     //  json[r'isExternal'] = null; |  | ||||||
|     } |  | ||||||
|     if (this.isFavorite != null) { |     if (this.isFavorite != null) { | ||||||
|       json[r'isFavorite'] = this.isFavorite; |       json[r'isFavorite'] = this.isFavorite; | ||||||
|     } else { |     } else { | ||||||
| @ -435,11 +408,6 @@ class SmartSearchDto { | |||||||
|     } else { |     } else { | ||||||
|     //  json[r'isOffline'] = null; |     //  json[r'isOffline'] = null; | ||||||
|     } |     } | ||||||
|     if (this.isReadOnly != null) { |  | ||||||
|       json[r'isReadOnly'] = this.isReadOnly; |  | ||||||
|     } else { |  | ||||||
|     //  json[r'isReadOnly'] = null; |  | ||||||
|     } |  | ||||||
|     if (this.isVisible != null) { |     if (this.isVisible != null) { | ||||||
|       json[r'isVisible'] = this.isVisible; |       json[r'isVisible'] = this.isVisible; | ||||||
|     } else { |     } else { | ||||||
| @ -546,12 +514,10 @@ class SmartSearchDto { | |||||||
|         deviceId: mapValueOfType<String>(json, r'deviceId'), |         deviceId: mapValueOfType<String>(json, r'deviceId'), | ||||||
|         isArchived: mapValueOfType<bool>(json, r'isArchived'), |         isArchived: mapValueOfType<bool>(json, r'isArchived'), | ||||||
|         isEncoded: mapValueOfType<bool>(json, r'isEncoded'), |         isEncoded: mapValueOfType<bool>(json, r'isEncoded'), | ||||||
|         isExternal: mapValueOfType<bool>(json, r'isExternal'), |  | ||||||
|         isFavorite: mapValueOfType<bool>(json, r'isFavorite'), |         isFavorite: mapValueOfType<bool>(json, r'isFavorite'), | ||||||
|         isMotion: mapValueOfType<bool>(json, r'isMotion'), |         isMotion: mapValueOfType<bool>(json, r'isMotion'), | ||||||
|         isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'), |         isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'), | ||||||
|         isOffline: mapValueOfType<bool>(json, r'isOffline'), |         isOffline: mapValueOfType<bool>(json, r'isOffline'), | ||||||
|         isReadOnly: mapValueOfType<bool>(json, r'isReadOnly'), |  | ||||||
|         isVisible: mapValueOfType<bool>(json, r'isVisible'), |         isVisible: mapValueOfType<bool>(json, r'isVisible'), | ||||||
|         lensModel: mapValueOfType<String>(json, r'lensModel'), |         lensModel: mapValueOfType<String>(json, r'lensModel'), | ||||||
|         libraryId: mapValueOfType<String>(json, r'libraryId'), |         libraryId: mapValueOfType<String>(json, r'libraryId'), | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								mobile/openapi/test/asset_api_test.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								mobile/openapi/test/asset_api_test.dart
									
									
									
										generated
									
									
									
								
							| @ -105,7 +105,7 @@ void main() { | |||||||
|       // TODO |       // TODO | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     //Future<AssetFileUploadResponseDto> uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String key, String xImmichChecksum, String duration, bool isArchived, bool isFavorite, bool isOffline, bool isReadOnly, bool isVisible, String libraryId, MultipartFile livePhotoData, MultipartFile sidecarData }) async |     //Future<AssetFileUploadResponseDto> uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String key, String xImmichChecksum, String duration, bool isArchived, bool isFavorite, bool isOffline, bool isVisible, String libraryId, MultipartFile livePhotoData, MultipartFile sidecarData }) async | ||||||
|     test('test uploadFile', () async { |     test('test uploadFile', () async { | ||||||
|       // TODO |       // TODO | ||||||
|     }); |     }); | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								mobile/openapi/test/asset_response_dto_test.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								mobile/openapi/test/asset_response_dto_test.dart
									
									
									
										generated
									
									
									
								
							| @ -67,6 +67,7 @@ void main() { | |||||||
|       // TODO |       // TODO | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     // This property was deprecated in v1.104.0 | ||||||
|     // bool isExternal |     // bool isExternal | ||||||
|     test('to test the property `isExternal`', () async { |     test('to test the property `isExternal`', () async { | ||||||
|       // TODO |       // TODO | ||||||
| @ -82,6 +83,7 @@ void main() { | |||||||
|       // TODO |       // TODO | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     // This property was deprecated in v1.104.0 | ||||||
|     // bool isReadOnly |     // bool isReadOnly | ||||||
|     test('to test the property `isReadOnly`', () async { |     test('to test the property `isReadOnly`', () async { | ||||||
|       // TODO |       // TODO | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								mobile/openapi/test/metadata_search_dto_test.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								mobile/openapi/test/metadata_search_dto_test.dart
									
									
									
										generated
									
									
									
								
							| @ -71,11 +71,6 @@ void main() { | |||||||
|       // TODO |       // TODO | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     // bool isExternal |  | ||||||
|     test('to test the property `isExternal`', () async { |  | ||||||
|       // TODO |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // bool isFavorite |     // bool isFavorite | ||||||
|     test('to test the property `isFavorite`', () async { |     test('to test the property `isFavorite`', () async { | ||||||
|       // TODO |       // TODO | ||||||
| @ -96,11 +91,6 @@ void main() { | |||||||
|       // TODO |       // TODO | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     // bool isReadOnly |  | ||||||
|     test('to test the property `isReadOnly`', () async { |  | ||||||
|       // TODO |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // bool isVisible |     // bool isVisible | ||||||
|     test('to test the property `isVisible`', () async { |     test('to test the property `isVisible`', () async { | ||||||
|       // TODO |       // TODO | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								mobile/openapi/test/smart_search_dto_test.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								mobile/openapi/test/smart_search_dto_test.dart
									
									
									
										generated
									
									
									
								
							| @ -51,11 +51,6 @@ void main() { | |||||||
|       // TODO |       // TODO | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     // bool isExternal |  | ||||||
|     test('to test the property `isExternal`', () async { |  | ||||||
|       // TODO |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // bool isFavorite |     // bool isFavorite | ||||||
|     test('to test the property `isFavorite`', () async { |     test('to test the property `isFavorite`', () async { | ||||||
|       // TODO |       // TODO | ||||||
| @ -76,11 +71,6 @@ void main() { | |||||||
|       // TODO |       // TODO | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     // bool isReadOnly |  | ||||||
|     test('to test the property `isReadOnly`', () async { |  | ||||||
|       // TODO |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // bool isVisible |     // bool isVisible | ||||||
|     test('to test the property `isVisible`', () async { |     test('to test the property `isVisible`', () async { | ||||||
|       // TODO |       // TODO | ||||||
|  | |||||||
| @ -7297,6 +7297,8 @@ | |||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isExternal": { |           "isExternal": { | ||||||
|  |             "deprecated": true, | ||||||
|  |             "description": "This property was deprecated in v1.104.0", | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isFavorite": { |           "isFavorite": { | ||||||
| @ -7306,6 +7308,8 @@ | |||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isReadOnly": { |           "isReadOnly": { | ||||||
|  |             "deprecated": true, | ||||||
|  |             "description": "This property was deprecated in v1.104.0", | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isTrashed": { |           "isTrashed": { | ||||||
| @ -7388,10 +7392,8 @@ | |||||||
|           "hasMetadata", |           "hasMetadata", | ||||||
|           "id", |           "id", | ||||||
|           "isArchived", |           "isArchived", | ||||||
|           "isExternal", |  | ||||||
|           "isFavorite", |           "isFavorite", | ||||||
|           "isOffline", |           "isOffline", | ||||||
|           "isReadOnly", |  | ||||||
|           "isTrashed", |           "isTrashed", | ||||||
|           "libraryId", |           "libraryId", | ||||||
|           "localDateTime", |           "localDateTime", | ||||||
| @ -7652,9 +7654,6 @@ | |||||||
|           "isOffline": { |           "isOffline": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isReadOnly": { |  | ||||||
|             "type": "boolean" |  | ||||||
|           }, |  | ||||||
|           "isVisible": { |           "isVisible": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
| @ -8599,9 +8598,6 @@ | |||||||
|           "isEncoded": { |           "isEncoded": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isExternal": { |  | ||||||
|             "type": "boolean" |  | ||||||
|           }, |  | ||||||
|           "isFavorite": { |           "isFavorite": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
| @ -8614,9 +8610,6 @@ | |||||||
|           "isOffline": { |           "isOffline": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isReadOnly": { |  | ||||||
|             "type": "boolean" |  | ||||||
|           }, |  | ||||||
|           "isVisible": { |           "isVisible": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
| @ -9821,9 +9814,6 @@ | |||||||
|           "isEncoded": { |           "isEncoded": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isExternal": { |  | ||||||
|             "type": "boolean" |  | ||||||
|           }, |  | ||||||
|           "isFavorite": { |           "isFavorite": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
| @ -9836,9 +9826,6 @@ | |||||||
|           "isOffline": { |           "isOffline": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|           "isReadOnly": { |  | ||||||
|             "type": "boolean" |  | ||||||
|           }, |  | ||||||
|           "isVisible": { |           "isVisible": { | ||||||
|             "type": "boolean" |             "type": "boolean" | ||||||
|           }, |           }, | ||||||
|  | |||||||
| @ -122,10 +122,12 @@ export type AssetResponseDto = { | |||||||
|     hasMetadata: boolean; |     hasMetadata: boolean; | ||||||
|     id: string; |     id: string; | ||||||
|     isArchived: boolean; |     isArchived: boolean; | ||||||
|     isExternal: boolean; |     /** This property was deprecated in v1.104.0 */ | ||||||
|  |     isExternal?: boolean; | ||||||
|     isFavorite: boolean; |     isFavorite: boolean; | ||||||
|     isOffline: boolean; |     isOffline: boolean; | ||||||
|     isReadOnly: boolean; |     /** This property was deprecated in v1.104.0 */ | ||||||
|  |     isReadOnly?: boolean; | ||||||
|     isTrashed: boolean; |     isTrashed: boolean; | ||||||
|     libraryId: string; |     libraryId: string; | ||||||
|     livePhotoVideoId?: string | null; |     livePhotoVideoId?: string | null; | ||||||
| @ -296,7 +298,6 @@ export type CreateAssetDto = { | |||||||
|     isArchived?: boolean; |     isArchived?: boolean; | ||||||
|     isFavorite?: boolean; |     isFavorite?: boolean; | ||||||
|     isOffline?: boolean; |     isOffline?: boolean; | ||||||
|     isReadOnly?: boolean; |  | ||||||
|     isVisible?: boolean; |     isVisible?: boolean; | ||||||
|     libraryId?: string; |     libraryId?: string; | ||||||
|     livePhotoData?: Blob; |     livePhotoData?: Blob; | ||||||
| @ -622,12 +623,10 @@ export type MetadataSearchDto = { | |||||||
|     id?: string; |     id?: string; | ||||||
|     isArchived?: boolean; |     isArchived?: boolean; | ||||||
|     isEncoded?: boolean; |     isEncoded?: boolean; | ||||||
|     isExternal?: boolean; |  | ||||||
|     isFavorite?: boolean; |     isFavorite?: boolean; | ||||||
|     isMotion?: boolean; |     isMotion?: boolean; | ||||||
|     isNotInAlbum?: boolean; |     isNotInAlbum?: boolean; | ||||||
|     isOffline?: boolean; |     isOffline?: boolean; | ||||||
|     isReadOnly?: boolean; |  | ||||||
|     isVisible?: boolean; |     isVisible?: boolean; | ||||||
|     lensModel?: string; |     lensModel?: string; | ||||||
|     libraryId?: string; |     libraryId?: string; | ||||||
| @ -699,12 +698,10 @@ export type SmartSearchDto = { | |||||||
|     deviceId?: string; |     deviceId?: string; | ||||||
|     isArchived?: boolean; |     isArchived?: boolean; | ||||||
|     isEncoded?: boolean; |     isEncoded?: boolean; | ||||||
|     isExternal?: boolean; |  | ||||||
|     isFavorite?: boolean; |     isFavorite?: boolean; | ||||||
|     isMotion?: boolean; |     isMotion?: boolean; | ||||||
|     isNotInAlbum?: boolean; |     isNotInAlbum?: boolean; | ||||||
|     isOffline?: boolean; |     isOffline?: boolean; | ||||||
|     isReadOnly?: boolean; |  | ||||||
|     isVisible?: boolean; |     isVisible?: boolean; | ||||||
|     lensModel?: string; |     lensModel?: string; | ||||||
|     libraryId?: string; |     libraryId?: string; | ||||||
|  | |||||||
| @ -113,6 +113,7 @@ export const DummyValue = { | |||||||
|   PAGINATION: { take: 10, skip: 0 }, |   PAGINATION: { take: 10, skip: 0 }, | ||||||
|   EMAIL: 'user@immich.app', |   EMAIL: 'user@immich.app', | ||||||
|   STRING: 'abcdefghi', |   STRING: 'abcdefghi', | ||||||
|  |   NUMBER: 50, | ||||||
|   BUFFER: Buffer.from('abcdefghi'), |   BUFFER: Buffer.from('abcdefghi'), | ||||||
|   DATE: new Date(), |   DATE: new Date(), | ||||||
|   TIME_BUCKET: '2024-01-01T00:00:00.000Z', |   TIME_BUCKET: '2024-01-01T00:00:00.000Z', | ||||||
|  | |||||||
| @ -36,8 +36,10 @@ export class AssetResponseDto extends SanitizedAssetResponseDto { | |||||||
|   isArchived!: boolean; |   isArchived!: boolean; | ||||||
|   isTrashed!: boolean; |   isTrashed!: boolean; | ||||||
|   isOffline!: boolean; |   isOffline!: boolean; | ||||||
|   isExternal!: boolean; |   @PropertyLifecycle({ deprecatedAt: 'v1.104.0' }) | ||||||
|   isReadOnly!: boolean; |   isExternal?: boolean; | ||||||
|  |   @PropertyLifecycle({ deprecatedAt: 'v1.104.0' }) | ||||||
|  |   isReadOnly?: boolean; | ||||||
|   exifInfo?: ExifResponseDto; |   exifInfo?: ExifResponseDto; | ||||||
|   smartInfo?: SmartInfoResponseDto; |   smartInfo?: SmartInfoResponseDto; | ||||||
|   tags?: TagResponseDto[]; |   tags?: TagResponseDto[]; | ||||||
| @ -124,9 +126,9 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As | |||||||
|           .map((a) => mapAsset(a, { stripMetadata, auth: options.auth })) |           .map((a) => mapAsset(a, { stripMetadata, auth: options.auth })) | ||||||
|       : undefined, |       : undefined, | ||||||
|     stackCount: entity.stack?.assets?.length ?? null, |     stackCount: entity.stack?.assets?.length ?? null, | ||||||
|     isExternal: entity.isExternal, |  | ||||||
|     isOffline: entity.isOffline, |     isOffline: entity.isOffline, | ||||||
|     isReadOnly: entity.isReadOnly, |     isExternal: false, | ||||||
|  |     isReadOnly: false, | ||||||
|     hasMetadata: true, |     hasMetadata: true, | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -97,9 +97,6 @@ export class CreateAssetDto { | |||||||
|   @ValidateBoolean({ optional: true }) |   @ValidateBoolean({ optional: true }) | ||||||
|   isOffline?: boolean; |   isOffline?: boolean; | ||||||
| 
 | 
 | ||||||
|   @ValidateBoolean({ optional: true }) |  | ||||||
|   isReadOnly?: boolean; |  | ||||||
| 
 |  | ||||||
|   // The properties below are added to correctly generate the API docs
 |   // The properties below are added to correctly generate the API docs
 | ||||||
|   // and client SDKs. Validation should be handled in the controller.
 |   // and client SDKs. Validation should be handled in the controller.
 | ||||||
|   @ApiProperty({ type: 'string', format: 'binary' }) |   @ApiProperty({ type: 'string', format: 'binary' }) | ||||||
|  | |||||||
| @ -33,9 +33,6 @@ class BaseSearchDto { | |||||||
|   @ValidateBoolean({ optional: true }) |   @ValidateBoolean({ optional: true }) | ||||||
|   isEncoded?: boolean; |   isEncoded?: boolean; | ||||||
| 
 | 
 | ||||||
|   @ValidateBoolean({ optional: true }) |  | ||||||
|   isExternal?: boolean; |  | ||||||
| 
 |  | ||||||
|   @ValidateBoolean({ optional: true }) |   @ValidateBoolean({ optional: true }) | ||||||
|   isFavorite?: boolean; |   isFavorite?: boolean; | ||||||
| 
 | 
 | ||||||
| @ -45,9 +42,6 @@ class BaseSearchDto { | |||||||
|   @ValidateBoolean({ optional: true }) |   @ValidateBoolean({ optional: true }) | ||||||
|   isOffline?: boolean; |   isOffline?: boolean; | ||||||
| 
 | 
 | ||||||
|   @ValidateBoolean({ optional: true }) |  | ||||||
|   isReadOnly?: boolean; |  | ||||||
| 
 |  | ||||||
|   @ValidateBoolean({ optional: true }) |   @ValidateBoolean({ optional: true }) | ||||||
|   isVisible?: boolean; |   isVisible?: boolean; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -106,9 +106,6 @@ export class AssetEntity { | |||||||
|   @Column({ type: 'boolean', default: false }) |   @Column({ type: 'boolean', default: false }) | ||||||
|   isExternal!: boolean; |   isExternal!: boolean; | ||||||
| 
 | 
 | ||||||
|   @Column({ type: 'boolean', default: false }) |  | ||||||
|   isReadOnly!: boolean; |  | ||||||
| 
 |  | ||||||
|   @Column({ type: 'boolean', default: false }) |   @Column({ type: 'boolean', default: false }) | ||||||
|   isOffline!: boolean; |   isOffline!: boolean; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -108,10 +108,6 @@ export interface IEntityJob extends IBaseJob { | |||||||
|   source?: 'upload' | 'sidecar-write'; |   source?: 'upload' | 'sidecar-write'; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface IAssetDeletionJob extends IEntityJob { |  | ||||||
|   fromExternal?: boolean; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export interface ILibraryFileJob extends IEntityJob { | export interface ILibraryFileJob extends IEntityJob { | ||||||
|   ownerId: string; |   ownerId: string; | ||||||
|   assetPath: string; |   assetPath: string; | ||||||
| @ -225,7 +221,7 @@ export type JobItem = | |||||||
| 
 | 
 | ||||||
|   // Asset Deletion
 |   // Asset Deletion
 | ||||||
|   | { name: JobName.PERSON_CLEANUP; data?: IBaseJob } |   | { name: JobName.PERSON_CLEANUP; data?: IBaseJob } | ||||||
|   | { name: JobName.ASSET_DELETION; data: IAssetDeletionJob } |   | { name: JobName.ASSET_DELETION; data: IEntityJob } | ||||||
|   | { name: JobName.ASSET_DELETION_CHECK; data?: IBaseJob } |   | { name: JobName.ASSET_DELETION_CHECK; data?: IBaseJob } | ||||||
| 
 | 
 | ||||||
|   // Library Management
 |   // Library Management
 | ||||||
|  | |||||||
| @ -56,11 +56,9 @@ export type SearchIdOptions = SearchAssetIDOptions & SearchUserIdOptions; | |||||||
| export interface SearchStatusOptions { | export interface SearchStatusOptions { | ||||||
|   isArchived?: boolean; |   isArchived?: boolean; | ||||||
|   isEncoded?: boolean; |   isEncoded?: boolean; | ||||||
|   isExternal?: boolean; |  | ||||||
|   isFavorite?: boolean; |   isFavorite?: boolean; | ||||||
|   isMotion?: boolean; |   isMotion?: boolean; | ||||||
|   isOffline?: boolean; |   isOffline?: boolean; | ||||||
|   isReadOnly?: boolean; |  | ||||||
|   isVisible?: boolean; |   isVisible?: boolean; | ||||||
|   isNotInAlbum?: boolean; |   isNotInAlbum?: boolean; | ||||||
|   type?: AssetType; |   type?: AssetType; | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								server/src/migrations/1714698592332-RemoveIsReadOnly.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								server/src/migrations/1714698592332-RemoveIsReadOnly.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | import { MigrationInterface, QueryRunner } from "typeorm"; | ||||||
|  | 
 | ||||||
|  | export class RemoveIsReadOnly1714698592332 implements MigrationInterface { | ||||||
|  |     name = 'RemoveIsReadOnly1714698592332' | ||||||
|  | 
 | ||||||
|  |     public async up(queryRunner: QueryRunner): Promise<void> { | ||||||
|  |         await queryRunner.query(`ALTER TABLE "assets" DROP COLUMN "isReadOnly"`); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public async down(queryRunner: QueryRunner): Promise<void> { | ||||||
|  |         await queryRunner.query(`ALTER TABLE "assets" ADD "isReadOnly" boolean NOT NULL DEFAULT false`); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -22,7 +22,6 @@ SELECT | |||||||
|   "entity"."isFavorite" AS "entity_isFavorite", |   "entity"."isFavorite" AS "entity_isFavorite", | ||||||
|   "entity"."isArchived" AS "entity_isArchived", |   "entity"."isArchived" AS "entity_isArchived", | ||||||
|   "entity"."isExternal" AS "entity_isExternal", |   "entity"."isExternal" AS "entity_isExternal", | ||||||
|   "entity"."isReadOnly" AS "entity_isReadOnly", |  | ||||||
|   "entity"."isOffline" AS "entity_isOffline", |   "entity"."isOffline" AS "entity_isOffline", | ||||||
|   "entity"."checksum" AS "entity_checksum", |   "entity"."checksum" AS "entity_checksum", | ||||||
|   "entity"."duration" AS "entity_duration", |   "entity"."duration" AS "entity_duration", | ||||||
| @ -105,7 +104,6 @@ SELECT | |||||||
|   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", |   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", | ||||||
|   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", |   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", | ||||||
|   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", |   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", | ||||||
|   "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", |  | ||||||
|   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", |   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", | ||||||
|   "AssetEntity"."checksum" AS "AssetEntity_checksum", |   "AssetEntity"."checksum" AS "AssetEntity_checksum", | ||||||
|   "AssetEntity"."duration" AS "AssetEntity_duration", |   "AssetEntity"."duration" AS "AssetEntity_duration", | ||||||
| @ -141,7 +139,6 @@ SELECT | |||||||
|   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", |   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", | ||||||
|   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", |   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", | ||||||
|   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", |   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", | ||||||
|   "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", |  | ||||||
|   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", |   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", | ||||||
|   "AssetEntity"."checksum" AS "AssetEntity_checksum", |   "AssetEntity"."checksum" AS "AssetEntity_checksum", | ||||||
|   "AssetEntity"."duration" AS "AssetEntity_duration", |   "AssetEntity"."duration" AS "AssetEntity_duration", | ||||||
| @ -226,7 +223,6 @@ SELECT | |||||||
|   "bd93d5747511a4dad4923546c51365bf1a803774"."isFavorite" AS "bd93d5747511a4dad4923546c51365bf1a803774_isFavorite", |   "bd93d5747511a4dad4923546c51365bf1a803774"."isFavorite" AS "bd93d5747511a4dad4923546c51365bf1a803774_isFavorite", | ||||||
|   "bd93d5747511a4dad4923546c51365bf1a803774"."isArchived" AS "bd93d5747511a4dad4923546c51365bf1a803774_isArchived", |   "bd93d5747511a4dad4923546c51365bf1a803774"."isArchived" AS "bd93d5747511a4dad4923546c51365bf1a803774_isArchived", | ||||||
|   "bd93d5747511a4dad4923546c51365bf1a803774"."isExternal" AS "bd93d5747511a4dad4923546c51365bf1a803774_isExternal", |   "bd93d5747511a4dad4923546c51365bf1a803774"."isExternal" AS "bd93d5747511a4dad4923546c51365bf1a803774_isExternal", | ||||||
|   "bd93d5747511a4dad4923546c51365bf1a803774"."isReadOnly" AS "bd93d5747511a4dad4923546c51365bf1a803774_isReadOnly", |  | ||||||
|   "bd93d5747511a4dad4923546c51365bf1a803774"."isOffline" AS "bd93d5747511a4dad4923546c51365bf1a803774_isOffline", |   "bd93d5747511a4dad4923546c51365bf1a803774"."isOffline" AS "bd93d5747511a4dad4923546c51365bf1a803774_isOffline", | ||||||
|   "bd93d5747511a4dad4923546c51365bf1a803774"."checksum" AS "bd93d5747511a4dad4923546c51365bf1a803774_checksum", |   "bd93d5747511a4dad4923546c51365bf1a803774"."checksum" AS "bd93d5747511a4dad4923546c51365bf1a803774_checksum", | ||||||
|   "bd93d5747511a4dad4923546c51365bf1a803774"."duration" AS "bd93d5747511a4dad4923546c51365bf1a803774_duration", |   "bd93d5747511a4dad4923546c51365bf1a803774"."duration" AS "bd93d5747511a4dad4923546c51365bf1a803774_duration", | ||||||
| @ -308,7 +304,6 @@ FROM | |||||||
|       "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", |       "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", | ||||||
|       "AssetEntity"."isArchived" AS "AssetEntity_isArchived", |       "AssetEntity"."isArchived" AS "AssetEntity_isArchived", | ||||||
|       "AssetEntity"."isExternal" AS "AssetEntity_isExternal", |       "AssetEntity"."isExternal" AS "AssetEntity_isExternal", | ||||||
|       "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", |  | ||||||
|       "AssetEntity"."isOffline" AS "AssetEntity_isOffline", |       "AssetEntity"."isOffline" AS "AssetEntity_isOffline", | ||||||
|       "AssetEntity"."checksum" AS "AssetEntity_checksum", |       "AssetEntity"."checksum" AS "AssetEntity_checksum", | ||||||
|       "AssetEntity"."duration" AS "AssetEntity_duration", |       "AssetEntity"."duration" AS "AssetEntity_duration", | ||||||
| @ -405,7 +400,6 @@ SELECT | |||||||
|   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", |   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", | ||||||
|   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", |   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", | ||||||
|   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", |   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", | ||||||
|   "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", |  | ||||||
|   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", |   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", | ||||||
|   "AssetEntity"."checksum" AS "AssetEntity_checksum", |   "AssetEntity"."checksum" AS "AssetEntity_checksum", | ||||||
|   "AssetEntity"."duration" AS "AssetEntity_duration", |   "AssetEntity"."duration" AS "AssetEntity_duration", | ||||||
| @ -451,7 +445,6 @@ SELECT | |||||||
|   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", |   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", | ||||||
|   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", |   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", | ||||||
|   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", |   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", | ||||||
|   "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", |  | ||||||
|   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", |   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", | ||||||
|   "AssetEntity"."checksum" AS "AssetEntity_checksum", |   "AssetEntity"."checksum" AS "AssetEntity_checksum", | ||||||
|   "AssetEntity"."duration" AS "AssetEntity_duration", |   "AssetEntity"."duration" AS "AssetEntity_duration", | ||||||
| @ -519,7 +512,6 @@ SELECT | |||||||
|   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", |   "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", | ||||||
|   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", |   "AssetEntity"."isArchived" AS "AssetEntity_isArchived", | ||||||
|   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", |   "AssetEntity"."isExternal" AS "AssetEntity_isExternal", | ||||||
|   "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", |  | ||||||
|   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", |   "AssetEntity"."isOffline" AS "AssetEntity_isOffline", | ||||||
|   "AssetEntity"."checksum" AS "AssetEntity_checksum", |   "AssetEntity"."checksum" AS "AssetEntity_checksum", | ||||||
|   "AssetEntity"."duration" AS "AssetEntity_duration", |   "AssetEntity"."duration" AS "AssetEntity_duration", | ||||||
| @ -608,7 +600,6 @@ SELECT | |||||||
|   "asset"."isFavorite" AS "asset_isFavorite", |   "asset"."isFavorite" AS "asset_isFavorite", | ||||||
|   "asset"."isArchived" AS "asset_isArchived", |   "asset"."isArchived" AS "asset_isArchived", | ||||||
|   "asset"."isExternal" AS "asset_isExternal", |   "asset"."isExternal" AS "asset_isExternal", | ||||||
|   "asset"."isReadOnly" AS "asset_isReadOnly", |  | ||||||
|   "asset"."isOffline" AS "asset_isOffline", |   "asset"."isOffline" AS "asset_isOffline", | ||||||
|   "asset"."checksum" AS "asset_checksum", |   "asset"."checksum" AS "asset_checksum", | ||||||
|   "asset"."duration" AS "asset_duration", |   "asset"."duration" AS "asset_duration", | ||||||
| @ -667,7 +658,6 @@ SELECT | |||||||
|   "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", |   "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", | ||||||
|   "stackedAssets"."isArchived" AS "stackedAssets_isArchived", |   "stackedAssets"."isArchived" AS "stackedAssets_isArchived", | ||||||
|   "stackedAssets"."isExternal" AS "stackedAssets_isExternal", |   "stackedAssets"."isExternal" AS "stackedAssets_isExternal", | ||||||
|   "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", |  | ||||||
|   "stackedAssets"."isOffline" AS "stackedAssets_isOffline", |   "stackedAssets"."isOffline" AS "stackedAssets_isOffline", | ||||||
|   "stackedAssets"."checksum" AS "stackedAssets_checksum", |   "stackedAssets"."checksum" AS "stackedAssets_checksum", | ||||||
|   "stackedAssets"."duration" AS "stackedAssets_duration", |   "stackedAssets"."duration" AS "stackedAssets_duration", | ||||||
| @ -784,7 +774,6 @@ SELECT | |||||||
|   "asset"."isFavorite" AS "asset_isFavorite", |   "asset"."isFavorite" AS "asset_isFavorite", | ||||||
|   "asset"."isArchived" AS "asset_isArchived", |   "asset"."isArchived" AS "asset_isArchived", | ||||||
|   "asset"."isExternal" AS "asset_isExternal", |   "asset"."isExternal" AS "asset_isExternal", | ||||||
|   "asset"."isReadOnly" AS "asset_isReadOnly", |  | ||||||
|   "asset"."isOffline" AS "asset_isOffline", |   "asset"."isOffline" AS "asset_isOffline", | ||||||
|   "asset"."checksum" AS "asset_checksum", |   "asset"."checksum" AS "asset_checksum", | ||||||
|   "asset"."duration" AS "asset_duration", |   "asset"."duration" AS "asset_duration", | ||||||
| @ -843,7 +832,6 @@ SELECT | |||||||
|   "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", |   "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", | ||||||
|   "stackedAssets"."isArchived" AS "stackedAssets_isArchived", |   "stackedAssets"."isArchived" AS "stackedAssets_isArchived", | ||||||
|   "stackedAssets"."isExternal" AS "stackedAssets_isExternal", |   "stackedAssets"."isExternal" AS "stackedAssets_isExternal", | ||||||
|   "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", |  | ||||||
|   "stackedAssets"."isOffline" AS "stackedAssets_isOffline", |   "stackedAssets"."isOffline" AS "stackedAssets_isOffline", | ||||||
|   "stackedAssets"."checksum" AS "stackedAssets_checksum", |   "stackedAssets"."checksum" AS "stackedAssets_checksum", | ||||||
|   "stackedAssets"."duration" AS "stackedAssets_duration", |   "stackedAssets"."duration" AS "stackedAssets_duration", | ||||||
| @ -891,7 +879,6 @@ SELECT | |||||||
|   "asset"."isFavorite" AS "asset_isFavorite", |   "asset"."isFavorite" AS "asset_isFavorite", | ||||||
|   "asset"."isArchived" AS "asset_isArchived", |   "asset"."isArchived" AS "asset_isArchived", | ||||||
|   "asset"."isExternal" AS "asset_isExternal", |   "asset"."isExternal" AS "asset_isExternal", | ||||||
|   "asset"."isReadOnly" AS "asset_isReadOnly", |  | ||||||
|   "asset"."isOffline" AS "asset_isOffline", |   "asset"."isOffline" AS "asset_isOffline", | ||||||
|   "asset"."checksum" AS "asset_checksum", |   "asset"."checksum" AS "asset_checksum", | ||||||
|   "asset"."duration" AS "asset_duration", |   "asset"."duration" AS "asset_duration", | ||||||
| @ -950,7 +937,6 @@ SELECT | |||||||
|   "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", |   "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", | ||||||
|   "stackedAssets"."isArchived" AS "stackedAssets_isArchived", |   "stackedAssets"."isArchived" AS "stackedAssets_isArchived", | ||||||
|   "stackedAssets"."isExternal" AS "stackedAssets_isExternal", |   "stackedAssets"."isExternal" AS "stackedAssets_isExternal", | ||||||
|   "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", |  | ||||||
|   "stackedAssets"."isOffline" AS "stackedAssets_isOffline", |   "stackedAssets"."isOffline" AS "stackedAssets_isOffline", | ||||||
|   "stackedAssets"."checksum" AS "stackedAssets_checksum", |   "stackedAssets"."checksum" AS "stackedAssets_checksum", | ||||||
|   "stackedAssets"."duration" AS "stackedAssets_duration", |   "stackedAssets"."duration" AS "stackedAssets_duration", | ||||||
|  | |||||||
| @ -165,7 +165,6 @@ FROM | |||||||
|       "AssetFaceEntity__AssetFaceEntity_asset"."isFavorite" AS "AssetFaceEntity__AssetFaceEntity_asset_isFavorite", |       "AssetFaceEntity__AssetFaceEntity_asset"."isFavorite" AS "AssetFaceEntity__AssetFaceEntity_asset_isFavorite", | ||||||
|       "AssetFaceEntity__AssetFaceEntity_asset"."isArchived" AS "AssetFaceEntity__AssetFaceEntity_asset_isArchived", |       "AssetFaceEntity__AssetFaceEntity_asset"."isArchived" AS "AssetFaceEntity__AssetFaceEntity_asset_isArchived", | ||||||
|       "AssetFaceEntity__AssetFaceEntity_asset"."isExternal" AS "AssetFaceEntity__AssetFaceEntity_asset_isExternal", |       "AssetFaceEntity__AssetFaceEntity_asset"."isExternal" AS "AssetFaceEntity__AssetFaceEntity_asset_isExternal", | ||||||
|       "AssetFaceEntity__AssetFaceEntity_asset"."isReadOnly" AS "AssetFaceEntity__AssetFaceEntity_asset_isReadOnly", |  | ||||||
|       "AssetFaceEntity__AssetFaceEntity_asset"."isOffline" AS "AssetFaceEntity__AssetFaceEntity_asset_isOffline", |       "AssetFaceEntity__AssetFaceEntity_asset"."isOffline" AS "AssetFaceEntity__AssetFaceEntity_asset_isOffline", | ||||||
|       "AssetFaceEntity__AssetFaceEntity_asset"."checksum" AS "AssetFaceEntity__AssetFaceEntity_asset_checksum", |       "AssetFaceEntity__AssetFaceEntity_asset"."checksum" AS "AssetFaceEntity__AssetFaceEntity_asset_checksum", | ||||||
|       "AssetFaceEntity__AssetFaceEntity_asset"."duration" AS "AssetFaceEntity__AssetFaceEntity_asset_duration", |       "AssetFaceEntity__AssetFaceEntity_asset"."duration" AS "AssetFaceEntity__AssetFaceEntity_asset_duration", | ||||||
| @ -263,7 +262,6 @@ FROM | |||||||
|       "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", |       "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", | ||||||
|       "AssetEntity"."isArchived" AS "AssetEntity_isArchived", |       "AssetEntity"."isArchived" AS "AssetEntity_isArchived", | ||||||
|       "AssetEntity"."isExternal" AS "AssetEntity_isExternal", |       "AssetEntity"."isExternal" AS "AssetEntity_isExternal", | ||||||
|       "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", |  | ||||||
|       "AssetEntity"."isOffline" AS "AssetEntity_isOffline", |       "AssetEntity"."isOffline" AS "AssetEntity_isOffline", | ||||||
|       "AssetEntity"."checksum" AS "AssetEntity_checksum", |       "AssetEntity"."checksum" AS "AssetEntity_checksum", | ||||||
|       "AssetEntity"."duration" AS "AssetEntity_duration", |       "AssetEntity"."duration" AS "AssetEntity_duration", | ||||||
| @ -393,7 +391,6 @@ SELECT | |||||||
|   "AssetFaceEntity__AssetFaceEntity_asset"."isFavorite" AS "AssetFaceEntity__AssetFaceEntity_asset_isFavorite", |   "AssetFaceEntity__AssetFaceEntity_asset"."isFavorite" AS "AssetFaceEntity__AssetFaceEntity_asset_isFavorite", | ||||||
|   "AssetFaceEntity__AssetFaceEntity_asset"."isArchived" AS "AssetFaceEntity__AssetFaceEntity_asset_isArchived", |   "AssetFaceEntity__AssetFaceEntity_asset"."isArchived" AS "AssetFaceEntity__AssetFaceEntity_asset_isArchived", | ||||||
|   "AssetFaceEntity__AssetFaceEntity_asset"."isExternal" AS "AssetFaceEntity__AssetFaceEntity_asset_isExternal", |   "AssetFaceEntity__AssetFaceEntity_asset"."isExternal" AS "AssetFaceEntity__AssetFaceEntity_asset_isExternal", | ||||||
|   "AssetFaceEntity__AssetFaceEntity_asset"."isReadOnly" AS "AssetFaceEntity__AssetFaceEntity_asset_isReadOnly", |  | ||||||
|   "AssetFaceEntity__AssetFaceEntity_asset"."isOffline" AS "AssetFaceEntity__AssetFaceEntity_asset_isOffline", |   "AssetFaceEntity__AssetFaceEntity_asset"."isOffline" AS "AssetFaceEntity__AssetFaceEntity_asset_isOffline", | ||||||
|   "AssetFaceEntity__AssetFaceEntity_asset"."checksum" AS "AssetFaceEntity__AssetFaceEntity_asset_checksum", |   "AssetFaceEntity__AssetFaceEntity_asset"."checksum" AS "AssetFaceEntity__AssetFaceEntity_asset_checksum", | ||||||
|   "AssetFaceEntity__AssetFaceEntity_asset"."duration" AS "AssetFaceEntity__AssetFaceEntity_asset_duration", |   "AssetFaceEntity__AssetFaceEntity_asset"."duration" AS "AssetFaceEntity__AssetFaceEntity_asset_duration", | ||||||
|  | |||||||
| @ -27,7 +27,6 @@ FROM | |||||||
|       "asset"."isFavorite" AS "asset_isFavorite", |       "asset"."isFavorite" AS "asset_isFavorite", | ||||||
|       "asset"."isArchived" AS "asset_isArchived", |       "asset"."isArchived" AS "asset_isArchived", | ||||||
|       "asset"."isExternal" AS "asset_isExternal", |       "asset"."isExternal" AS "asset_isExternal", | ||||||
|       "asset"."isReadOnly" AS "asset_isReadOnly", |  | ||||||
|       "asset"."isOffline" AS "asset_isOffline", |       "asset"."isOffline" AS "asset_isOffline", | ||||||
|       "asset"."checksum" AS "asset_checksum", |       "asset"."checksum" AS "asset_checksum", | ||||||
|       "asset"."duration" AS "asset_duration", |       "asset"."duration" AS "asset_duration", | ||||||
| @ -58,7 +57,6 @@ FROM | |||||||
|       "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", |       "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", | ||||||
|       "stackedAssets"."isArchived" AS "stackedAssets_isArchived", |       "stackedAssets"."isArchived" AS "stackedAssets_isArchived", | ||||||
|       "stackedAssets"."isExternal" AS "stackedAssets_isExternal", |       "stackedAssets"."isExternal" AS "stackedAssets_isExternal", | ||||||
|       "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", |  | ||||||
|       "stackedAssets"."isOffline" AS "stackedAssets_isOffline", |       "stackedAssets"."isOffline" AS "stackedAssets_isOffline", | ||||||
|       "stackedAssets"."checksum" AS "stackedAssets_checksum", |       "stackedAssets"."checksum" AS "stackedAssets_checksum", | ||||||
|       "stackedAssets"."duration" AS "stackedAssets_duration", |       "stackedAssets"."duration" AS "stackedAssets_duration", | ||||||
| @ -123,7 +121,6 @@ SELECT | |||||||
|   "asset"."isFavorite" AS "asset_isFavorite", |   "asset"."isFavorite" AS "asset_isFavorite", | ||||||
|   "asset"."isArchived" AS "asset_isArchived", |   "asset"."isArchived" AS "asset_isArchived", | ||||||
|   "asset"."isExternal" AS "asset_isExternal", |   "asset"."isExternal" AS "asset_isExternal", | ||||||
|   "asset"."isReadOnly" AS "asset_isReadOnly", |  | ||||||
|   "asset"."isOffline" AS "asset_isOffline", |   "asset"."isOffline" AS "asset_isOffline", | ||||||
|   "asset"."checksum" AS "asset_checksum", |   "asset"."checksum" AS "asset_checksum", | ||||||
|   "asset"."duration" AS "asset_duration", |   "asset"."duration" AS "asset_duration", | ||||||
| @ -154,7 +151,6 @@ SELECT | |||||||
|   "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", |   "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", | ||||||
|   "stackedAssets"."isArchived" AS "stackedAssets_isArchived", |   "stackedAssets"."isArchived" AS "stackedAssets_isArchived", | ||||||
|   "stackedAssets"."isExternal" AS "stackedAssets_isExternal", |   "stackedAssets"."isExternal" AS "stackedAssets_isExternal", | ||||||
|   "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", |  | ||||||
|   "stackedAssets"."isOffline" AS "stackedAssets_isOffline", |   "stackedAssets"."isOffline" AS "stackedAssets_isOffline", | ||||||
|   "stackedAssets"."checksum" AS "stackedAssets_checksum", |   "stackedAssets"."checksum" AS "stackedAssets_checksum", | ||||||
|   "stackedAssets"."duration" AS "stackedAssets_duration", |   "stackedAssets"."duration" AS "stackedAssets_duration", | ||||||
| @ -333,7 +329,6 @@ SELECT | |||||||
|   "asset"."isFavorite" AS "asset_isFavorite", |   "asset"."isFavorite" AS "asset_isFavorite", | ||||||
|   "asset"."isArchived" AS "asset_isArchived", |   "asset"."isArchived" AS "asset_isArchived", | ||||||
|   "asset"."isExternal" AS "asset_isExternal", |   "asset"."isExternal" AS "asset_isExternal", | ||||||
|   "asset"."isReadOnly" AS "asset_isReadOnly", |  | ||||||
|   "asset"."isOffline" AS "asset_isOffline", |   "asset"."isOffline" AS "asset_isOffline", | ||||||
|   "asset"."checksum" AS "asset_checksum", |   "asset"."checksum" AS "asset_checksum", | ||||||
|   "asset"."duration" AS "asset_duration", |   "asset"."duration" AS "asset_duration", | ||||||
|  | |||||||
| @ -41,7 +41,6 @@ FROM | |||||||
|       "SharedLinkEntity__SharedLinkEntity_assets"."isFavorite" AS "SharedLinkEntity__SharedLinkEntity_assets_isFavorite", |       "SharedLinkEntity__SharedLinkEntity_assets"."isFavorite" AS "SharedLinkEntity__SharedLinkEntity_assets_isFavorite", | ||||||
|       "SharedLinkEntity__SharedLinkEntity_assets"."isArchived" AS "SharedLinkEntity__SharedLinkEntity_assets_isArchived", |       "SharedLinkEntity__SharedLinkEntity_assets"."isArchived" AS "SharedLinkEntity__SharedLinkEntity_assets_isArchived", | ||||||
|       "SharedLinkEntity__SharedLinkEntity_assets"."isExternal" AS "SharedLinkEntity__SharedLinkEntity_assets_isExternal", |       "SharedLinkEntity__SharedLinkEntity_assets"."isExternal" AS "SharedLinkEntity__SharedLinkEntity_assets_isExternal", | ||||||
|       "SharedLinkEntity__SharedLinkEntity_assets"."isReadOnly" AS "SharedLinkEntity__SharedLinkEntity_assets_isReadOnly", |  | ||||||
|       "SharedLinkEntity__SharedLinkEntity_assets"."isOffline" AS "SharedLinkEntity__SharedLinkEntity_assets_isOffline", |       "SharedLinkEntity__SharedLinkEntity_assets"."isOffline" AS "SharedLinkEntity__SharedLinkEntity_assets_isOffline", | ||||||
|       "SharedLinkEntity__SharedLinkEntity_assets"."checksum" AS "SharedLinkEntity__SharedLinkEntity_assets_checksum", |       "SharedLinkEntity__SharedLinkEntity_assets"."checksum" AS "SharedLinkEntity__SharedLinkEntity_assets_checksum", | ||||||
|       "SharedLinkEntity__SharedLinkEntity_assets"."duration" AS "SharedLinkEntity__SharedLinkEntity_assets_duration", |       "SharedLinkEntity__SharedLinkEntity_assets"."duration" AS "SharedLinkEntity__SharedLinkEntity_assets_duration", | ||||||
| @ -108,7 +107,6 @@ FROM | |||||||
|       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isFavorite" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isFavorite", |       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isFavorite" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isFavorite", | ||||||
|       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isArchived" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isArchived", |       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isArchived" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isArchived", | ||||||
|       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isExternal" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isExternal", |       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isExternal" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isExternal", | ||||||
|       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isReadOnly" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isReadOnly", |  | ||||||
|       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isOffline" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isOffline", |       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isOffline" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isOffline", | ||||||
|       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."checksum" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_checksum", |       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."checksum" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_checksum", | ||||||
|       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."duration" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_duration", |       "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."duration" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_duration", | ||||||
| @ -231,7 +229,6 @@ SELECT | |||||||
|   "SharedLinkEntity__SharedLinkEntity_assets"."isFavorite" AS "SharedLinkEntity__SharedLinkEntity_assets_isFavorite", |   "SharedLinkEntity__SharedLinkEntity_assets"."isFavorite" AS "SharedLinkEntity__SharedLinkEntity_assets_isFavorite", | ||||||
|   "SharedLinkEntity__SharedLinkEntity_assets"."isArchived" AS "SharedLinkEntity__SharedLinkEntity_assets_isArchived", |   "SharedLinkEntity__SharedLinkEntity_assets"."isArchived" AS "SharedLinkEntity__SharedLinkEntity_assets_isArchived", | ||||||
|   "SharedLinkEntity__SharedLinkEntity_assets"."isExternal" AS "SharedLinkEntity__SharedLinkEntity_assets_isExternal", |   "SharedLinkEntity__SharedLinkEntity_assets"."isExternal" AS "SharedLinkEntity__SharedLinkEntity_assets_isExternal", | ||||||
|   "SharedLinkEntity__SharedLinkEntity_assets"."isReadOnly" AS "SharedLinkEntity__SharedLinkEntity_assets_isReadOnly", |  | ||||||
|   "SharedLinkEntity__SharedLinkEntity_assets"."isOffline" AS "SharedLinkEntity__SharedLinkEntity_assets_isOffline", |   "SharedLinkEntity__SharedLinkEntity_assets"."isOffline" AS "SharedLinkEntity__SharedLinkEntity_assets_isOffline", | ||||||
|   "SharedLinkEntity__SharedLinkEntity_assets"."checksum" AS "SharedLinkEntity__SharedLinkEntity_assets_checksum", |   "SharedLinkEntity__SharedLinkEntity_assets"."checksum" AS "SharedLinkEntity__SharedLinkEntity_assets_checksum", | ||||||
|   "SharedLinkEntity__SharedLinkEntity_assets"."duration" AS "SharedLinkEntity__SharedLinkEntity_assets_duration", |   "SharedLinkEntity__SharedLinkEntity_assets"."duration" AS "SharedLinkEntity__SharedLinkEntity_assets_duration", | ||||||
|  | |||||||
| @ -151,6 +151,14 @@ GROUP BY | |||||||
| ORDER BY | ORDER BY | ||||||
|   "users"."createdAt" ASC |   "users"."createdAt" ASC | ||||||
| 
 | 
 | ||||||
|  | -- UserRepository.updateUsage | ||||||
|  | UPDATE "users" | ||||||
|  | SET | ||||||
|  |   "quotaUsageInBytes" = "quotaUsageInBytes" + 50, | ||||||
|  |   "updatedAt" = CURRENT_TIMESTAMP | ||||||
|  | WHERE | ||||||
|  |   "id" = $1 | ||||||
|  | 
 | ||||||
| -- UserRepository.syncUsage | -- UserRepository.syncUsage | ||||||
| UPDATE "users" | UPDATE "users" | ||||||
| SET | SET | ||||||
|  | |||||||
| @ -253,7 +253,7 @@ export class AssetRepository implements IAssetRepository { | |||||||
| 
 | 
 | ||||||
|   @Chunked() |   @Chunked() | ||||||
|   async softDeleteAll(ids: string[]): Promise<void> { |   async softDeleteAll(ids: string[]): Promise<void> { | ||||||
|     await this.repository.softDelete({ id: In(ids), isExternal: false }); |     await this.repository.softDelete({ id: In(ids) }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @Chunked() |   @Chunked() | ||||||
|  | |||||||
| @ -112,6 +112,7 @@ export class UserRepository implements IUserRepository { | |||||||
|     return stats; |     return stats; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @GenerateSql({ params: [DummyValue.UUID, DummyValue.NUMBER] }) | ||||||
|   async updateUsage(id: string, delta: number): Promise<void> { |   async updateUsage(id: string, delta: number): Promise<void> { | ||||||
|     await this.userRepository.increment({ id }, 'quotaUsageInBytes', delta); |     await this.userRepository.increment({ id }, 'quotaUsageInBytes', delta); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -295,7 +295,6 @@ export class AssetServiceV1 { | |||||||
|       livePhotoVideo: livePhotoAssetId === null ? null : ({ id: livePhotoAssetId } as AssetEntity), |       livePhotoVideo: livePhotoAssetId === null ? null : ({ id: livePhotoAssetId } as AssetEntity), | ||||||
|       originalFileName: file.originalName, |       originalFileName: file.originalName, | ||||||
|       sidecarPath: sidecarPath || null, |       sidecarPath: sidecarPath || null, | ||||||
|       isReadOnly: dto.isReadOnly ?? false, |  | ||||||
|       isOffline: dto.isOffline ?? false, |       isOffline: dto.isOffline ?? false, | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -685,61 +685,6 @@ describe(AssetService.name, () => { | |||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should only delete generated files for readonly assets', async () => { |  | ||||||
|       assetMock.getById.mockResolvedValue(assetStub.readOnly); |  | ||||||
| 
 |  | ||||||
|       await sut.handleAssetDeletion({ id: assetStub.readOnly.id }); |  | ||||||
| 
 |  | ||||||
|       expect(jobMock.queue.mock.calls).toEqual([ |  | ||||||
|         [ |  | ||||||
|           { |  | ||||||
|             name: JobName.DELETE_FILES, |  | ||||||
|             data: { |  | ||||||
|               files: [ |  | ||||||
|                 assetStub.readOnly.thumbnailPath, |  | ||||||
|                 assetStub.readOnly.previewPath, |  | ||||||
|                 assetStub.readOnly.encodedVideoPath, |  | ||||||
|               ], |  | ||||||
|             }, |  | ||||||
|           }, |  | ||||||
|         ], |  | ||||||
|       ]); |  | ||||||
| 
 |  | ||||||
|       expect(assetMock.remove).toHaveBeenCalledWith(assetStub.readOnly); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should not process assets from external library without fromExternal flag', async () => { |  | ||||||
|       assetMock.getById.mockResolvedValue(assetStub.external); |  | ||||||
| 
 |  | ||||||
|       await sut.handleAssetDeletion({ id: assetStub.external.id }); |  | ||||||
| 
 |  | ||||||
|       expect(jobMock.queue).not.toHaveBeenCalled(); |  | ||||||
|       expect(jobMock.queueAll).not.toHaveBeenCalled(); |  | ||||||
|       expect(assetMock.remove).not.toHaveBeenCalled(); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should process assets from external library with fromExternal flag', async () => { |  | ||||||
|       assetMock.getById.mockResolvedValue(assetStub.external); |  | ||||||
| 
 |  | ||||||
|       await sut.handleAssetDeletion({ id: assetStub.external.id, fromExternal: true }); |  | ||||||
| 
 |  | ||||||
|       expect(assetMock.remove).toHaveBeenCalledWith(assetStub.external); |  | ||||||
|       expect(jobMock.queue.mock.calls).toEqual([ |  | ||||||
|         [ |  | ||||||
|           { |  | ||||||
|             name: JobName.DELETE_FILES, |  | ||||||
|             data: { |  | ||||||
|               files: [ |  | ||||||
|                 assetStub.external.thumbnailPath, |  | ||||||
|                 assetStub.external.previewPath, |  | ||||||
|                 assetStub.external.encodedVideoPath, |  | ||||||
|               ], |  | ||||||
|             }, |  | ||||||
|           }, |  | ||||||
|         ], |  | ||||||
|       ]); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should delete a live photo', async () => { |     it('should delete a live photo', async () => { | ||||||
|       assetMock.getById.mockResolvedValue(assetStub.livePhotoStillAsset); |       assetMock.getById.mockResolvedValue(assetStub.livePhotoStillAsset); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ import { IAssetStackRepository } from 'src/interfaces/asset-stack.interface'; | |||||||
| import { IAssetRepository } from 'src/interfaces/asset.interface'; | import { IAssetRepository } from 'src/interfaces/asset.interface'; | ||||||
| import { ClientEvent, IEventRepository } from 'src/interfaces/event.interface'; | import { ClientEvent, IEventRepository } from 'src/interfaces/event.interface'; | ||||||
| import { | import { | ||||||
|   IAssetDeletionJob, |   IEntityJob, | ||||||
|   IJobRepository, |   IJobRepository, | ||||||
|   ISidecarWriteJob, |   ISidecarWriteJob, | ||||||
|   JOBS_ASSET_PAGINATION_SIZE, |   JOBS_ASSET_PAGINATION_SIZE, | ||||||
| @ -371,8 +371,8 @@ export class AssetService { | |||||||
|     return JobStatus.SUCCESS; |     return JobStatus.SUCCESS; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async handleAssetDeletion(job: IAssetDeletionJob): Promise<JobStatus> { |   async handleAssetDeletion(job: IEntityJob): Promise<JobStatus> { | ||||||
|     const { id, fromExternal } = job; |     const { id } = job; | ||||||
| 
 | 
 | ||||||
|     const asset = await this.assetRepository.getById(id, { |     const asset = await this.assetRepository.getById(id, { | ||||||
|       faces: { |       faces: { | ||||||
| @ -387,11 +387,6 @@ export class AssetService { | |||||||
|       return JobStatus.FAILED; |       return JobStatus.FAILED; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Ignore requests that are not from external library job but is for an external asset
 |  | ||||||
|     if (!fromExternal && (!asset.library || asset.library.type === LibraryType.EXTERNAL)) { |  | ||||||
|       return JobStatus.SKIPPED; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Replace the parent of the stack children with a new asset
 |     // Replace the parent of the stack children with a new asset
 | ||||||
|     if (asset.stack?.primaryAssetId === id) { |     if (asset.stack?.primaryAssetId === id) { | ||||||
|       const stackAssetIds = asset.stack.assets.map((a) => a.id); |       const stackAssetIds = asset.stack.assets.map((a) => a.id); | ||||||
| @ -414,18 +409,15 @@ export class AssetService { | |||||||
| 
 | 
 | ||||||
|     // TODO refactor this to use cascades
 |     // TODO refactor this to use cascades
 | ||||||
|     if (asset.livePhotoVideoId) { |     if (asset.livePhotoVideoId) { | ||||||
|       await this.jobRepository.queue({ |       await this.jobRepository.queue({ name: JobName.ASSET_DELETION, data: { id: asset.livePhotoVideoId } }); | ||||||
|         name: JobName.ASSET_DELETION, |  | ||||||
|         data: { id: asset.livePhotoVideoId, fromExternal }, |  | ||||||
|       }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const files = [asset.thumbnailPath, asset.previewPath, asset.encodedVideoPath]; |     await this.jobRepository.queue({ | ||||||
|     if (!(asset.isExternal || asset.isReadOnly)) { |       name: JobName.DELETE_FILES, | ||||||
|       files.push(asset.sidecarPath, asset.originalPath); |       data: { | ||||||
|     } |         files: [asset.thumbnailPath, asset.previewPath, asset.encodedVideoPath, asset.sidecarPath, asset.originalPath], | ||||||
| 
 |       }, | ||||||
|     await this.jobRepository.queue({ name: JobName.DELETE_FILES, data: { files } }); |     }); | ||||||
| 
 | 
 | ||||||
|     return JobStatus.SUCCESS; |     return JobStatus.SUCCESS; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -368,7 +368,6 @@ describe(LibraryService.name, () => { | |||||||
|             type: AssetType.IMAGE, |             type: AssetType.IMAGE, | ||||||
|             originalFileName: 'photo.jpg', |             originalFileName: 'photo.jpg', | ||||||
|             sidecarPath: null, |             sidecarPath: null, | ||||||
|             isReadOnly: true, |  | ||||||
|             isExternal: true, |             isExternal: true, | ||||||
|           }, |           }, | ||||||
|         ], |         ], | ||||||
| @ -416,7 +415,6 @@ describe(LibraryService.name, () => { | |||||||
|             type: AssetType.IMAGE, |             type: AssetType.IMAGE, | ||||||
|             originalFileName: 'photo.jpg', |             originalFileName: 'photo.jpg', | ||||||
|             sidecarPath: '/data/user1/photo.jpg.xmp', |             sidecarPath: '/data/user1/photo.jpg.xmp', | ||||||
|             isReadOnly: true, |  | ||||||
|             isExternal: true, |             isExternal: true, | ||||||
|           }, |           }, | ||||||
|         ], |         ], | ||||||
| @ -463,7 +461,6 @@ describe(LibraryService.name, () => { | |||||||
|             type: AssetType.VIDEO, |             type: AssetType.VIDEO, | ||||||
|             originalFileName: 'video.mp4', |             originalFileName: 'video.mp4', | ||||||
|             sidecarPath: null, |             sidecarPath: null, | ||||||
|             isReadOnly: true, |  | ||||||
|             isExternal: true, |             isExternal: true, | ||||||
|           }, |           }, | ||||||
|         ], |         ], | ||||||
| @ -1458,10 +1455,7 @@ describe(LibraryService.name, () => { | |||||||
|       await expect(sut.handleOfflineRemoval({ id: libraryStub.externalLibrary1.id })).resolves.toBe(JobStatus.SUCCESS); |       await expect(sut.handleOfflineRemoval({ id: libraryStub.externalLibrary1.id })).resolves.toBe(JobStatus.SUCCESS); | ||||||
| 
 | 
 | ||||||
|       expect(jobMock.queueAll).toHaveBeenCalledWith([ |       expect(jobMock.queueAll).toHaveBeenCalledWith([ | ||||||
|         { |         { name: JobName.ASSET_DELETION, data: { id: assetStub.image1.id } }, | ||||||
|           name: JobName.ASSET_DELETION, |  | ||||||
|           data: { id: assetStub.image1.id, fromExternal: true }, |  | ||||||
|         }, |  | ||||||
|       ]); |       ]); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -387,7 +387,7 @@ export class LibraryService { | |||||||
|     const assetIds = await this.repository.getAssetIds(job.id, true); |     const assetIds = await this.repository.getAssetIds(job.id, true); | ||||||
|     this.logger.debug(`Will delete ${assetIds.length} asset(s) in library ${job.id}`); |     this.logger.debug(`Will delete ${assetIds.length} asset(s) in library ${job.id}`); | ||||||
|     await this.jobRepository.queueAll( |     await this.jobRepository.queueAll( | ||||||
|       assetIds.map((assetId) => ({ name: JobName.ASSET_DELETION, data: { id: assetId, fromExternal: true } })), |       assetIds.map((assetId) => ({ name: JobName.ASSET_DELETION, data: { id: assetId } })), | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     if (assetIds.length === 0) { |     if (assetIds.length === 0) { | ||||||
| @ -503,7 +503,6 @@ export class LibraryService { | |||||||
|         type: assetType, |         type: assetType, | ||||||
|         originalFileName, |         originalFileName, | ||||||
|         sidecarPath, |         sidecarPath, | ||||||
|         isReadOnly: true, |  | ||||||
|         isExternal: true, |         isExternal: true, | ||||||
|       }); |       }); | ||||||
|       assetId = addedAsset.id; |       assetId = addedAsset.id; | ||||||
| @ -580,7 +579,7 @@ export class LibraryService { | |||||||
|     for await (const assets of assetPagination) { |     for await (const assets of assetPagination) { | ||||||
|       this.logger.debug(`Removing ${assets.length} offline assets`); |       this.logger.debug(`Removing ${assets.length} offline assets`); | ||||||
|       await this.jobRepository.queueAll( |       await this.jobRepository.queueAll( | ||||||
|         assets.map((asset) => ({ name: JobName.ASSET_DELETION, data: { id: asset.id, fromExternal: true } })), |         assets.map((asset) => ({ name: JobName.ASSET_DELETION, data: { id: asset.id } })), | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -440,7 +440,6 @@ export class MetadataService { | |||||||
|           originalPath: motionPath, |           originalPath: motionPath, | ||||||
|           originalFileName: asset.originalFileName, |           originalFileName: asset.originalFileName, | ||||||
|           isVisible: false, |           isVisible: false, | ||||||
|           isReadOnly: false, |  | ||||||
|           deviceAssetId: 'NONE', |           deviceAssetId: 'NONE', | ||||||
|           deviceId: 'NONE', |           deviceId: 'NONE', | ||||||
|         }); |         }); | ||||||
|  | |||||||
| @ -558,26 +558,5 @@ describe(StorageTemplateService.name, () => { | |||||||
|       ); |       ); | ||||||
|       expect(assetMock.update).not.toHaveBeenCalled(); |       expect(assetMock.update).not.toHaveBeenCalled(); | ||||||
|     }); |     }); | ||||||
| 
 |  | ||||||
|     it('should not move read-only asset', async () => { |  | ||||||
|       assetMock.getAll.mockResolvedValue({ |  | ||||||
|         items: [ |  | ||||||
|           { |  | ||||||
|             ...assetStub.image, |  | ||||||
|             originalPath: 'upload/library/user-id/2023/2023-02-23/asset-id+1.jpg', |  | ||||||
|             isReadOnly: true, |  | ||||||
|           }, |  | ||||||
|         ], |  | ||||||
|         hasNextPage: false, |  | ||||||
|       }); |  | ||||||
|       userMock.getList.mockResolvedValue([userStub.user1]); |  | ||||||
| 
 |  | ||||||
|       await sut.handleMigration(); |  | ||||||
| 
 |  | ||||||
|       expect(assetMock.getAll).toHaveBeenCalled(); |  | ||||||
|       expect(storageMock.rename).not.toHaveBeenCalled(); |  | ||||||
|       expect(storageMock.copyFile).not.toHaveBeenCalled(); |  | ||||||
|       expect(assetMock.update).not.toHaveBeenCalled(); |  | ||||||
|     }); |  | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -170,7 +170,7 @@ export class StorageTemplateService { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async moveAsset(asset: AssetEntity, metadata: MoveAssetMetadata) { |   async moveAsset(asset: AssetEntity, metadata: MoveAssetMetadata) { | ||||||
|     if (asset.isReadOnly || asset.isExternal || StorageCore.isAndroidMotionPath(asset.originalPath)) { |     if (asset.isExternal || StorageCore.isAndroidMotionPath(asset.originalPath)) { | ||||||
|       // External assets are not affected by storage template
 |       // External assets are not affected by storage template
 | ||||||
|       // TODO: shouldn't this only apply to external assets?
 |       // TODO: shouldn't this only apply to external assets?
 | ||||||
|       return; |       return; | ||||||
|  | |||||||
| @ -67,7 +67,7 @@ export function searchAssetBuilder( | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const status = _.pick(options, ['isExternal', 'isFavorite', 'isOffline', 'isReadOnly', 'isVisible', 'type']); |   const status = _.pick(options, ['isFavorite', 'isOffline', 'isVisible', 'type']); | ||||||
|   const { |   const { | ||||||
|     isArchived, |     isArchived, | ||||||
|     isEncoded, |     isEncoded, | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								server/test/fixtures/asset.stub.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								server/test/fixtures/asset.stub.ts
									
									
									
									
										vendored
									
									
								
							| @ -45,7 +45,6 @@ export const assetStub = { | |||||||
|     sharedLinks: [], |     sharedLinks: [], | ||||||
|     faces: [], |     faces: [], | ||||||
|     sidecarPath: null, |     sidecarPath: null, | ||||||
|     isReadOnly: false, |  | ||||||
|     deletedAt: null, |     deletedAt: null, | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
| @ -82,7 +81,6 @@ export const assetStub = { | |||||||
|     originalFileName: 'IMG_456.jpg', |     originalFileName: 'IMG_456.jpg', | ||||||
|     faces: [], |     faces: [], | ||||||
|     sidecarPath: null, |     sidecarPath: null, | ||||||
|     isReadOnly: false, |  | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
| @ -113,7 +111,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
|     library: libraryStub.uploadLibrary1, |     library: libraryStub.uploadLibrary1, | ||||||
| @ -150,7 +147,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
| @ -195,7 +191,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
| @ -235,7 +230,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: true, |     isExternal: true, | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
| @ -275,7 +269,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
| @ -315,7 +308,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: true, |     isExternal: true, | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
| @ -356,7 +348,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
|     livePhotoVideo: null, |     livePhotoVideo: null, | ||||||
| @ -396,7 +387,6 @@ export const assetStub = { | |||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
|     library: libraryStub.uploadLibrary1, |     library: libraryStub.uploadLibrary1, | ||||||
| @ -436,7 +426,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
| @ -527,7 +516,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-22T05:06:29.716Z'), |     localDateTime: new Date('2023-02-22T05:06:29.716Z'), | ||||||
|     isFavorite: false, |     isFavorite: false, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
| @ -570,7 +558,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
| @ -606,7 +593,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
| @ -643,7 +629,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: true, |  | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
| @ -681,7 +666,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|     isOffline: false, |     isOffline: false, | ||||||
|     libraryId: 'library-id', |     libraryId: 'library-id', | ||||||
| @ -719,7 +703,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: true, |     isExternal: true, | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
| @ -758,7 +741,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     isExternal: true, |     isExternal: true, | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
| @ -797,7 +779,6 @@ export const assetStub = { | |||||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), |     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||||
|     isFavorite: true, |     isFavorite: true, | ||||||
|     isArchived: false, |     isArchived: false, | ||||||
|     isReadOnly: false, |  | ||||||
|     duration: null, |     duration: null, | ||||||
|     isVisible: true, |     isVisible: true, | ||||||
|     isExternal: false, |     isExternal: false, | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								server/test/fixtures/shared-link.stub.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								server/test/fixtures/shared-link.stub.ts
									
									
									
									
										vendored
									
									
								
							| @ -59,7 +59,6 @@ const assetResponse: AssetResponseDto = { | |||||||
|   thumbhash: null, |   thumbhash: null, | ||||||
|   fileModifiedAt: today, |   fileModifiedAt: today, | ||||||
|   isExternal: false, |   isExternal: false, | ||||||
|   isReadOnly: false, |  | ||||||
|   isOffline: false, |   isOffline: false, | ||||||
|   fileCreatedAt: today, |   fileCreatedAt: today, | ||||||
|   localDateTime: today, |   localDateTime: today, | ||||||
| @ -210,7 +209,6 @@ export const sharedLinkStub = { | |||||||
|           isFavorite: false, |           isFavorite: false, | ||||||
|           isArchived: false, |           isArchived: false, | ||||||
|           isExternal: false, |           isExternal: false, | ||||||
|           isReadOnly: false, |  | ||||||
|           isOffline: false, |           isOffline: false, | ||||||
|           libraryId: 'library-id', |           libraryId: 'library-id', | ||||||
|           library: libraryStub.uploadLibrary1, |           library: libraryStub.uploadLibrary1, | ||||||
|  | |||||||
| @ -193,9 +193,7 @@ | |||||||
|     {/if} |     {/if} | ||||||
| 
 | 
 | ||||||
|     {#if isOwner} |     {#if isOwner} | ||||||
|       {#if !asset.isReadOnly || !asset.isExternal} |       <CircleIconButton color="opaque" icon={mdiDeleteOutline} on:click={() => dispatch('delete')} title="Delete" /> | ||||||
|         <CircleIconButton color="opaque" icon={mdiDeleteOutline} on:click={() => dispatch('delete')} title="Delete" /> |  | ||||||
|       {/if} |  | ||||||
|       <div |       <div | ||||||
|         use:clickOutside={{ |         use:clickOutside={{ | ||||||
|           onOutclick: () => (isShowAssetOptions = false), |           onOutclick: () => (isShowAssetOptions = false), | ||||||
|  | |||||||
| @ -308,23 +308,15 @@ | |||||||
|   {/if} |   {/if} | ||||||
| 
 | 
 | ||||||
|   <div class="px-4 py-4"> |   <div class="px-4 py-4"> | ||||||
|     {#if !asset.exifInfo && !asset.isExternal} |     {#if asset.exifInfo} | ||||||
|       <p class="text-sm">NO EXIF INFO AVAILABLE</p> |  | ||||||
|     {:else if !asset.exifInfo && asset.isExternal} |  | ||||||
|       <div class="flex gap-4 py-4"> |  | ||||||
|         <div> |  | ||||||
|           <p class="break-all"> |  | ||||||
|             Metadata not loaded for {asset.originalPath} |  | ||||||
|           </p> |  | ||||||
|         </div> |  | ||||||
|       </div> |  | ||||||
|     {:else} |  | ||||||
|       <div class="flex h-10 w-full items-center justify-between text-sm"> |       <div class="flex h-10 w-full items-center justify-between text-sm"> | ||||||
|         <h2>DETAILS</h2> |         <h2>DETAILS</h2> | ||||||
|       </div> |       </div> | ||||||
|  |     {:else} | ||||||
|  |       <p class="text-sm">NO EXIF INFO AVAILABLE</p> | ||||||
|     {/if} |     {/if} | ||||||
| 
 | 
 | ||||||
|     {#if asset.exifInfo?.dateTimeOriginal && !asset.isReadOnly} |     {#if asset.exifInfo?.dateTimeOriginal} | ||||||
|       {@const assetDateTimeOriginal = DateTime.fromISO(asset.exifInfo.dateTimeOriginal, { |       {@const assetDateTimeOriginal = DateTime.fromISO(asset.exifInfo.dateTimeOriginal, { | ||||||
|         zone: asset.exifInfo.timeZone ?? undefined, |         zone: asset.exifInfo.timeZone ?? undefined, | ||||||
|       })} |       })} | ||||||
| @ -374,7 +366,7 @@ | |||||||
|           </div> |           </div> | ||||||
|         {/if} |         {/if} | ||||||
|       </button> |       </button> | ||||||
|     {:else if !asset.exifInfo?.dateTimeOriginal && !asset.isReadOnly && isOwner} |     {:else if !asset.exifInfo?.dateTimeOriginal && isOwner} | ||||||
|       <div class="flex justify-between place-items-start gap-4 py-4"> |       <div class="flex justify-between place-items-start gap-4 py-4"> | ||||||
|         <div class="flex gap-4"> |         <div class="flex gap-4"> | ||||||
|           <div> |           <div> | ||||||
| @ -385,43 +377,6 @@ | |||||||
|           <Icon path={mdiPencil} size="20" /> |           <Icon path={mdiPencil} size="20" /> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|     {:else if asset.exifInfo?.dateTimeOriginal && asset.isReadOnly} |  | ||||||
|       {@const assetDateTimeOriginal = DateTime.fromISO(asset.exifInfo.dateTimeOriginal, { |  | ||||||
|         zone: asset.exifInfo.timeZone ?? undefined, |  | ||||||
|       })} |  | ||||||
|       <div class="flex justify-between place-items-start gap-4 py-4"> |  | ||||||
|         <div class="flex gap-4"> |  | ||||||
|           <div> |  | ||||||
|             <Icon path={mdiCalendar} size="24" /> |  | ||||||
|           </div> |  | ||||||
| 
 |  | ||||||
|           <div> |  | ||||||
|             <p> |  | ||||||
|               {assetDateTimeOriginal.toLocaleString( |  | ||||||
|                 { |  | ||||||
|                   month: 'short', |  | ||||||
|                   day: 'numeric', |  | ||||||
|                   year: 'numeric', |  | ||||||
|                 }, |  | ||||||
|                 { locale: $locale }, |  | ||||||
|               )} |  | ||||||
|             </p> |  | ||||||
|             <div class="flex gap-2 text-sm"> |  | ||||||
|               <p> |  | ||||||
|                 {assetDateTimeOriginal.toLocaleString( |  | ||||||
|                   { |  | ||||||
|                     weekday: 'short', |  | ||||||
|                     hour: 'numeric', |  | ||||||
|                     minute: '2-digit', |  | ||||||
|                     timeZoneName: 'longOffset', |  | ||||||
|                   }, |  | ||||||
|                   { locale: $locale }, |  | ||||||
|                 )} |  | ||||||
|               </p> |  | ||||||
|             </div> |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|       </div> |  | ||||||
|     {/if} |     {/if} | ||||||
| 
 | 
 | ||||||
|     {#if isShowChangeDate} |     {#if isShowChangeDate} | ||||||
| @ -501,7 +456,7 @@ | |||||||
|       </div> |       </div> | ||||||
|     {/if} |     {/if} | ||||||
| 
 | 
 | ||||||
|     {#if asset.exifInfo?.city && !asset.isReadOnly} |     {#if asset.exifInfo?.city} | ||||||
|       <button |       <button | ||||||
|         type="button" |         type="button" | ||||||
|         class="flex w-full text-left justify-between place-items-start gap-4 py-4" |         class="flex w-full text-left justify-between place-items-start gap-4 py-4" | ||||||
| @ -534,7 +489,7 @@ | |||||||
|           </div> |           </div> | ||||||
|         {/if} |         {/if} | ||||||
|       </button> |       </button> | ||||||
|     {:else if !asset.exifInfo?.city && !asset.isReadOnly && isOwner} |     {:else if !asset.exifInfo?.city && isOwner} | ||||||
|       <button |       <button | ||||||
|         type="button" |         type="button" | ||||||
|         class="flex w-full text-left justify-between place-items-start gap-4 py-4 rounded-lg hover:dark:text-immich-dark-primary hover:text-immich-primary" |         class="flex w-full text-left justify-between place-items-start gap-4 py-4 rounded-lg hover:dark:text-immich-dark-primary hover:text-immich-primary" | ||||||
| @ -552,26 +507,6 @@ | |||||||
|           <Icon path={mdiPencil} size="20" /> |           <Icon path={mdiPencil} size="20" /> | ||||||
|         </div> |         </div> | ||||||
|       </button> |       </button> | ||||||
|     {:else if asset.exifInfo?.city && asset.isReadOnly} |  | ||||||
|       <div class="flex justify-between place-items-start gap-4 py-4"> |  | ||||||
|         <div class="flex gap-4"> |  | ||||||
|           <div><Icon path={mdiMapMarkerOutline} size="24" /></div> |  | ||||||
| 
 |  | ||||||
|           <div> |  | ||||||
|             <p>{asset.exifInfo.city}</p> |  | ||||||
|             {#if asset.exifInfo?.state} |  | ||||||
|               <div class="flex gap-2 text-sm"> |  | ||||||
|                 <p>{asset.exifInfo.state}</p> |  | ||||||
|               </div> |  | ||||||
|             {/if} |  | ||||||
|             {#if asset.exifInfo?.country} |  | ||||||
|               <div class="flex gap-2 text-sm"> |  | ||||||
|                 <p>{asset.exifInfo.country}</p> |  | ||||||
|               </div> |  | ||||||
|             {/if} |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|       </div> |  | ||||||
|     {/if} |     {/if} | ||||||
|     {#if isShowChangeLocation} |     {#if isShowChangeLocation} | ||||||
|       <ChangeLocation |       <ChangeLocation | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ | |||||||
| 
 | 
 | ||||||
|   const handleDelete = async () => { |   const handleDelete = async () => { | ||||||
|     loading = true; |     loading = true; | ||||||
|     const ids = [...getOwnedAssets()].filter((a) => !a.isExternal).map((a) => a.id); |     const ids = [...getOwnedAssets()].map((a) => a.id); | ||||||
|     await deleteAssets(force, onAssetDelete, ids); |     await deleteAssets(force, onAssetDelete, ids); | ||||||
|     clearSelect(); |     clearSelect(); | ||||||
|     isShowConfirmation = false; |     isShowConfirmation = false; | ||||||
|  | |||||||
| @ -47,7 +47,7 @@ | |||||||
| 
 | 
 | ||||||
|   $: timelineY = element?.scrollTop || 0; |   $: timelineY = element?.scrollTop || 0; | ||||||
|   $: isEmpty = $assetStore.initialized && $assetStore.buckets.length === 0; |   $: isEmpty = $assetStore.initialized && $assetStore.buckets.length === 0; | ||||||
|   $: idsSelectedAssets = [...$selectedAssets].filter((a) => !a.isExternal).map((a) => a.id); |   $: idsSelectedAssets = [...$selectedAssets].map(({ id }) => id); | ||||||
| 
 | 
 | ||||||
|   $: { |   $: { | ||||||
|     void assetStore.updateViewport(viewport); |     void assetStore.updateViewport(viewport); | ||||||
|  | |||||||
| @ -258,9 +258,9 @@ export const getAssetType = (type: AssetTypeEnum) => { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export const getSelectedAssets = (assets: Set<AssetResponseDto>, user: UserResponseDto | null): string[] => { | export const getSelectedAssets = (assets: Set<AssetResponseDto>, user: UserResponseDto | null): string[] => { | ||||||
|   const ids = [...assets].filter((a) => !a.isExternal && user && a.ownerId === user.id).map((a) => a.id); |   const ids = [...assets].filter((a) => user && a.ownerId === user.id).map((a) => a.id); | ||||||
| 
 | 
 | ||||||
|   const numberOfIssues = [...assets].filter((a) => a.isExternal || (user && a.ownerId !== user.id)).length; |   const numberOfIssues = [...assets].filter((a) => user && a.ownerId !== user.id).length; | ||||||
|   if (numberOfIssues > 0) { |   if (numberOfIssues > 0) { | ||||||
|     notificationController.show({ |     notificationController.show({ | ||||||
|       message: `Can't change metadata of ${numberOfIssues} asset${numberOfIssues > 1 ? 's' : ''}`, |       message: `Can't change metadata of ${numberOfIssues} asset${numberOfIssues > 1 ? 's' : ''}`, | ||||||
|  | |||||||
| @ -22,9 +22,7 @@ export const assetFactory = Sync.makeFactory<AssetResponseDto>({ | |||||||
|   isTrashed: Sync.each(() => faker.datatype.boolean()), |   isTrashed: Sync.each(() => faker.datatype.boolean()), | ||||||
|   duration: '0:00:00.00000', |   duration: '0:00:00.00000', | ||||||
|   checksum: Sync.each(() => faker.string.alphanumeric(28)), |   checksum: Sync.each(() => faker.string.alphanumeric(28)), | ||||||
|   isExternal: Sync.each(() => faker.datatype.boolean()), |  | ||||||
|   isOffline: Sync.each(() => faker.datatype.boolean()), |   isOffline: Sync.each(() => faker.datatype.boolean()), | ||||||
|   isReadOnly: Sync.each(() => faker.datatype.boolean()), |  | ||||||
|   hasMetadata: Sync.each(() => faker.datatype.boolean()), |   hasMetadata: Sync.each(() => faker.datatype.boolean()), | ||||||
|   stackCount: null, |   stackCount: null, | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user