diff --git a/e2e/src/api/specs/asset.e2e-spec.ts b/e2e/src/api/specs/asset.e2e-spec.ts index 30febc777d..050fa9b1e2 100644 --- a/e2e/src/api/specs/asset.e2e-spec.ts +++ b/e2e/src/api/specs/asset.e2e-spec.ts @@ -102,7 +102,6 @@ describe('/asset', () => { utils.createAsset(user1.accessToken), utils.createAsset(user1.accessToken, { isFavorite: true, - isReadOnly: true, fileCreatedAt: yesterday.toISO(), fileModifiedAt: yesterday.toISO(), assetData: { filename: 'example.mp4' }, diff --git a/e2e/src/api/specs/search.e2e-spec.ts b/e2e/src/api/specs/search.e2e-spec.ts index be6268babf..c7e2c3c218 100644 --- a/e2e/src/api/specs/search.e2e-spec.ts +++ b/e2e/src/api/specs/search.e2e-spec.ts @@ -24,12 +24,12 @@ describe('/search', () => { // let assetRidge: AssetFileUploadResponseDto; // let assetPolemonium: AssetFileUploadResponseDto; // let assetWood: AssetFileUploadResponseDto; + // let assetGlarus: AssetFileUploadResponseDto; let assetHeic: AssetFileUploadResponseDto; let assetRocks: AssetFileUploadResponseDto; let assetOneJpg6: AssetFileUploadResponseDto; let assetOneHeic6: AssetFileUploadResponseDto; let assetOneJpg5: AssetFileUploadResponseDto; - let assetGlarus: AssetFileUploadResponseDto; let assetSprings: AssetFileUploadResponseDto; let assetLast: AssetFileUploadResponseDto; let cities: string[]; @@ -52,11 +52,12 @@ describe('/search', () => { { filename: '/formats/motionphoto/Samsung One UI 6.jpg' }, { filename: '/formats/motionphoto/Samsung One UI 6.heic' }, { 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 } }, // used for search suggestions { filename: '/formats/png/density_plot.png' }, + { filename: '/formats/raw/Nikon/D80/glarus.nef' }, { filename: '/formats/raw/Nikon/D700/philadelphia.nef' }, { filename: '/albums/nature/orychophragmus_violaceus.jpg' }, { filename: '/albums/nature/tanners_ridge.jpg' }, @@ -93,9 +94,9 @@ describe('/search', () => { { latitude: 23.133_02, longitude: -82.383_04 }, // havana { latitude: 41.694_11, longitude: 44.833_68 }, // tbilisi { 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: 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: 31.634_16, longitude: -7.999_94 }, // marrakesh { latitude: 38.523_735_4, longitude: -78.488_619_4 }, // tanners ridge @@ -123,9 +124,9 @@ describe('/search', () => { assetOneJpg6, assetOneHeic6, assetOneJpg5, - assetGlarus, assetSprings, assetDensity, + // assetGlarus, // assetPhiladelphia, // assetOrychophragmus, // assetRidge, @@ -190,16 +191,7 @@ describe('/search', () => { dto: { size: -1.5 }, expected: ['size must not be less than 1', 'size must be an integer number'], }, - ...[ - 'isArchived', - 'isFavorite', - 'isReadOnly', - 'isExternal', - 'isEncoded', - 'isMotion', - 'isOffline', - 'isVisible', - ].map((value) => ({ + ...['isArchived', 'isFavorite', 'isEncoded', 'isMotion', 'isOffline', 'isVisible'].map((value) => ({ should: `should reject ${value} not a boolean`, dto: { [value]: 'immich' }, expected: [`${value} must be a boolean value`], @@ -255,14 +247,6 @@ describe('/search', () => { should: 'should search by isArchived (false)', 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)', deferred: () => ({ dto: { size: 1, type: 'IMAGE' }, assets: [assetLast] }), diff --git a/e2e/src/api/specs/timeline.e2e-spec.ts b/e2e/src/api/specs/timeline.e2e-spec.ts index 84daa19f44..af71d0e088 100644 --- a/e2e/src/api/specs/timeline.e2e-spec.ts +++ b/e2e/src/api/specs/timeline.e2e-spec.ts @@ -34,7 +34,6 @@ describe('/timeline', () => { utils.createAsset(user.accessToken), utils.createAsset(user.accessToken, { isFavorite: true, - isReadOnly: true, fileCreatedAt: yesterday.toISO(), fileModifiedAt: yesterday.toISO(), assetData: { filename: 'example.mp4' }, diff --git a/mobile/lib/entities/asset.entity.dart b/mobile/lib/entities/asset.entity.dart index a5849e9812..3f8c1fa74c 100644 --- a/mobile/lib/entities/asset.entity.dart +++ b/mobile/lib/entities/asset.entity.dart @@ -32,7 +32,6 @@ class Asset { isFavorite = remote.isFavorite, isArchived = remote.isArchived, isTrashed = remote.isTrashed, - isReadOnly = remote.isReadOnly, isOffline = remote.isOffline, // workaround to nullify stackParentId for the parent asset until we refactor the mobile app // stack handling to properly handle it @@ -55,7 +54,6 @@ class Asset { isFavorite = local.isFavorite, isArchived = false, isTrashed = false, - isReadOnly = false, isOffline = false, stackCount = 0, fileCreatedAt = local.createDateTime { @@ -90,7 +88,6 @@ class Asset { this.isTrashed = false, this.stackParentId, this.stackCount = 0, - this.isReadOnly = false, this.isOffline = false, this.thumbhash, }); @@ -161,8 +158,6 @@ class Asset { bool isTrashed; - bool isReadOnly; - bool isOffline; @ignore @@ -278,7 +273,6 @@ class Asset { isFavorite != a.isFavorite || isArchived != a.isArchived || isTrashed != a.isTrashed || - isReadOnly != a.isReadOnly || isOffline != a.isOffline || a.exifInfo?.latitude != exifInfo?.latitude || a.exifInfo?.longitude != exifInfo?.longitude || @@ -324,7 +318,6 @@ class Asset { isFavorite: isFavorite, isArchived: isArchived, isTrashed: isTrashed, - isReadOnly: isReadOnly, isOffline: isOffline, ); } @@ -345,7 +338,6 @@ class Asset { isFavorite: a.isFavorite, isArchived: a.isArchived, isTrashed: a.isTrashed, - isReadOnly: a.isReadOnly, isOffline: a.isOffline, exifInfo: a.exifInfo?.copyWith(id: id) ?? exifInfo, thumbhash: a.thumbhash, @@ -380,7 +372,6 @@ class Asset { bool? isFavorite, bool? isArchived, bool? isTrashed, - bool? isReadOnly, bool? isOffline, ExifInfo? exifInfo, String? stackParentId, @@ -405,7 +396,6 @@ class Asset { isFavorite: isFavorite ?? this.isFavorite, isArchived: isArchived ?? this.isArchived, isTrashed: isTrashed ?? this.isTrashed, - isReadOnly: isReadOnly ?? this.isReadOnly, isOffline: isOffline ?? this.isOffline, exifInfo: exifInfo ?? this.exifInfo, stackParentId: stackParentId ?? this.stackParentId, @@ -470,7 +460,6 @@ class Asset { "height": ${height ?? "N/A"}, "isArchived": $isArchived, "isTrashed": $isTrashed, - "isReadOnly": $isReadOnly, "isOffline": $isOffline, }"""; } diff --git a/mobile/lib/entities/asset.entity.g.dart b/mobile/lib/entities/asset.entity.g.dart index 00cb80a1af..099e15eef1 100644 --- a/mobile/lib/entities/asset.entity.g.dart +++ b/mobile/lib/entities/asset.entity.g.dart @@ -62,64 +62,59 @@ const AssetSchema = CollectionSchema( name: r'isOffline', type: IsarType.bool, ), - r'isReadOnly': PropertySchema( - id: 9, - name: r'isReadOnly', - type: IsarType.bool, - ), r'isTrashed': PropertySchema( - id: 10, + id: 9, name: r'isTrashed', type: IsarType.bool, ), r'livePhotoVideoId': PropertySchema( - id: 11, + id: 10, name: r'livePhotoVideoId', type: IsarType.string, ), r'localId': PropertySchema( - id: 12, + id: 11, name: r'localId', type: IsarType.string, ), r'ownerId': PropertySchema( - id: 13, + id: 12, name: r'ownerId', type: IsarType.long, ), r'remoteId': PropertySchema( - id: 14, + id: 13, name: r'remoteId', type: IsarType.string, ), r'stackCount': PropertySchema( - id: 15, + id: 14, name: r'stackCount', type: IsarType.long, ), r'stackParentId': PropertySchema( - id: 16, + id: 15, name: r'stackParentId', type: IsarType.string, ), r'thumbhash': PropertySchema( - id: 17, + id: 16, name: r'thumbhash', type: IsarType.string, ), r'type': PropertySchema( - id: 18, + id: 17, name: r'type', type: IsarType.byte, enumMap: _AssettypeEnumValueMap, ), r'updatedAt': PropertySchema( - id: 19, + id: 18, name: r'updatedAt', type: IsarType.dateTime, ), r'width': PropertySchema( - id: 20, + id: 19, name: r'width', type: IsarType.int, ) @@ -239,18 +234,17 @@ void _assetSerialize( writer.writeBool(offsets[6], object.isArchived); writer.writeBool(offsets[7], object.isFavorite); writer.writeBool(offsets[8], object.isOffline); - writer.writeBool(offsets[9], object.isReadOnly); - writer.writeBool(offsets[10], object.isTrashed); - writer.writeString(offsets[11], object.livePhotoVideoId); - writer.writeString(offsets[12], object.localId); - writer.writeLong(offsets[13], object.ownerId); - writer.writeString(offsets[14], object.remoteId); - writer.writeLong(offsets[15], object.stackCount); - writer.writeString(offsets[16], object.stackParentId); - writer.writeString(offsets[17], object.thumbhash); - writer.writeByte(offsets[18], object.type.index); - writer.writeDateTime(offsets[19], object.updatedAt); - writer.writeInt(offsets[20], object.width); + writer.writeBool(offsets[9], object.isTrashed); + writer.writeString(offsets[10], object.livePhotoVideoId); + writer.writeString(offsets[11], object.localId); + writer.writeLong(offsets[12], object.ownerId); + writer.writeString(offsets[13], object.remoteId); + writer.writeLong(offsets[14], object.stackCount); + writer.writeString(offsets[15], object.stackParentId); + writer.writeString(offsets[16], object.thumbhash); + writer.writeByte(offsets[17], object.type.index); + writer.writeDateTime(offsets[18], object.updatedAt); + writer.writeInt(offsets[19], object.width); } Asset _assetDeserialize( @@ -270,19 +264,18 @@ Asset _assetDeserialize( isArchived: reader.readBoolOrNull(offsets[6]) ?? false, isFavorite: reader.readBoolOrNull(offsets[7]) ?? false, isOffline: reader.readBoolOrNull(offsets[8]) ?? false, - isReadOnly: reader.readBoolOrNull(offsets[9]) ?? false, - isTrashed: reader.readBoolOrNull(offsets[10]) ?? false, - livePhotoVideoId: reader.readStringOrNull(offsets[11]), - localId: reader.readStringOrNull(offsets[12]), - ownerId: reader.readLong(offsets[13]), - remoteId: reader.readStringOrNull(offsets[14]), - stackCount: reader.readLongOrNull(offsets[15]), - stackParentId: reader.readStringOrNull(offsets[16]), - thumbhash: reader.readStringOrNull(offsets[17]), - type: _AssettypeValueEnumMap[reader.readByteOrNull(offsets[18])] ?? + isTrashed: reader.readBoolOrNull(offsets[9]) ?? false, + livePhotoVideoId: reader.readStringOrNull(offsets[10]), + localId: reader.readStringOrNull(offsets[11]), + ownerId: reader.readLong(offsets[12]), + remoteId: reader.readStringOrNull(offsets[13]), + stackCount: reader.readLongOrNull(offsets[14]), + stackParentId: reader.readStringOrNull(offsets[15]), + thumbhash: reader.readStringOrNull(offsets[16]), + type: _AssettypeValueEnumMap[reader.readByteOrNull(offsets[17])] ?? AssetType.other, - updatedAt: reader.readDateTime(offsets[19]), - width: reader.readIntOrNull(offsets[20]), + updatedAt: reader.readDateTime(offsets[18]), + width: reader.readIntOrNull(offsets[19]), ); return object; } @@ -315,27 +308,25 @@ P _assetDeserializeProp

( case 9: return (reader.readBoolOrNull(offset) ?? false) as P; case 10: - return (reader.readBoolOrNull(offset) ?? false) as P; + return (reader.readStringOrNull(offset)) as P; case 11: return (reader.readStringOrNull(offset)) as P; case 12: - return (reader.readStringOrNull(offset)) as P; - case 13: return (reader.readLong(offset)) as P; - case 14: + case 13: return (reader.readStringOrNull(offset)) as P; - case 15: + case 14: return (reader.readLongOrNull(offset)) as P; + case 15: + return (reader.readStringOrNull(offset)) as P; case 16: return (reader.readStringOrNull(offset)) as P; case 17: - return (reader.readStringOrNull(offset)) as P; - case 18: return (_AssettypeValueEnumMap[reader.readByteOrNull(offset)] ?? AssetType.other) as P; - case 19: + case 18: return (reader.readDateTime(offset)) as P; - case 20: + case 19: return (reader.readIntOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); @@ -1366,16 +1357,6 @@ extension AssetQueryFilter on QueryBuilder { }); } - QueryBuilder isReadOnlyEqualTo( - bool value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'isReadOnly', - value: value, - )); - }); - } - QueryBuilder isTrashedEqualTo( bool value) { return QueryBuilder.apply(this, (query) { @@ -2527,18 +2508,6 @@ extension AssetQuerySortBy on QueryBuilder { }); } - QueryBuilder sortByIsReadOnly() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isReadOnly', Sort.asc); - }); - } - - QueryBuilder sortByIsReadOnlyDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isReadOnly', Sort.desc); - }); - } - QueryBuilder sortByIsTrashed() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'isTrashed', Sort.asc); @@ -2793,18 +2762,6 @@ extension AssetQuerySortThenBy on QueryBuilder { }); } - QueryBuilder thenByIsReadOnly() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isReadOnly', Sort.asc); - }); - } - - QueryBuilder thenByIsReadOnlyDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isReadOnly', Sort.desc); - }); - } - QueryBuilder thenByIsTrashed() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'isTrashed', Sort.asc); @@ -2995,12 +2952,6 @@ extension AssetQueryWhereDistinct on QueryBuilder { }); } - QueryBuilder distinctByIsReadOnly() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'isReadOnly'); - }); - } - QueryBuilder distinctByIsTrashed() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'isTrashed'); @@ -3136,12 +3087,6 @@ extension AssetQueryProperty on QueryBuilder { }); } - QueryBuilder isReadOnlyProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'isReadOnly'); - }); - } - QueryBuilder isTrashedProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'isTrashed'); diff --git a/mobile/lib/extensions/collection_extensions.dart b/mobile/lib/extensions/collection_extensions.dart index 8e79394340..769bec472b 100644 --- a/mobile/lib/extensions/collection_extensions.dart +++ b/mobile/lib/extensions/collection_extensions.dart @@ -71,19 +71,6 @@ extension AssetListExtension on Iterable { 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 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 Iterable nonOfflineOnly({ void Function()? errorCallback, diff --git a/mobile/lib/modules/asset_viewer/ui/bottom_gallery_bar.dart b/mobile/lib/modules/asset_viewer/ui/bottom_gallery_bar.dart index 7178939e7e..9d44288157 100644 --- a/mobile/lib/modules/asset_viewer/ui/bottom_gallery_bar.dart +++ b/mobile/lib/modules/asset_viewer/ui/bottom_gallery_bar.dart @@ -102,16 +102,6 @@ class BottomGalleryBar extends ConsumerWidget { } 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 onDelete(bool force) async { final isDeleted = await ref.read(assetProvider.notifier).deleteAssets( {asset}, diff --git a/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_bottom_sheet.dart b/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_bottom_sheet.dart index d9dedf6d6a..34b11ebd2c 100644 --- a/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_bottom_sheet.dart +++ b/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_bottom_sheet.dart @@ -42,7 +42,7 @@ class ExifBottomSheet extends HookConsumerWidget { fontSize: 14, ), ), - if (asset.isRemote && !asset.isReadOnly) + if (asset.isRemote) IconButton( onPressed: () => handleEditDateTime( ref, diff --git a/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_location.dart b/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_location.dart index 6acfb2efa0..300b445b2a 100644 --- a/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_location.dart +++ b/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_location.dart @@ -24,7 +24,7 @@ class ExifLocation extends StatelessWidget { final hasCoordinates = exifInfo?.hasCoordinates ?? false; // Guard no lat/lng if (!hasCoordinates) { - return asset.isRemote && !asset.isReadOnly + return asset.isRemote ? ListTile( minLeadingWidth: 0, contentPadding: const EdgeInsets.all(0), @@ -57,7 +57,7 @@ class ExifLocation extends StatelessWidget { fontWeight: FontWeight.w600, ), ).tr(), - if (asset.isRemote && !asset.isReadOnly) + if (asset.isRemote) IconButton( onPressed: editLocation, icon: const Icon(Icons.edit_outlined), diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart index 2b0baff086..f17d296128 100644 --- a/mobile/lib/routing/router.gr.dart +++ b/mobile/lib/routing/router.gr.dart @@ -63,6 +63,12 @@ abstract class _$AppRouter extends RootStackRouter { child: const AllPeoplePage(), ); }, + AllPlacesRoute.name: (routeData) { + return AutoRoutePage( + routeData: routeData, + child: const AllPlacesPage(), + ); + }, AllVideosRoute.name: (routeData) { return AutoRoutePage( routeData: routeData, @@ -138,12 +144,6 @@ abstract class _$AppRouter extends RootStackRouter { ), ); }, - AllPlacesRoute.name: (routeData) { - return AutoRoutePage( - routeData: routeData, - child: const AllPlacesPage(), - ); - }, FailedBackupStatusRoute.name: (routeData) { return AutoRoutePage( routeData: routeData, @@ -525,6 +525,20 @@ class AllPeopleRoute extends PageRouteInfo { static const PageInfo page = PageInfo(name); } +/// generated route for +/// [AllPlacesPage] +class AllPlacesRoute extends PageRouteInfo { + const AllPlacesRoute({List? children}) + : super( + AllPlacesRoute.name, + initialChildren: children, + ); + + static const String name = 'AllPlacesRoute'; + + static const PageInfo page = PageInfo(name); +} + /// generated route for /// [AllVideosPage] class AllVideosRoute extends PageRouteInfo { @@ -752,20 +766,6 @@ class CreateAlbumRouteArgs { } } -/// generated route for -/// [AllPlacesPage] -class AllPlacesRoute extends PageRouteInfo { - const AllPlacesRoute({List? children}) - : super( - AllPlacesRoute.name, - initialChildren: children, - ); - - static const String name = 'CuratedLocationRoute'; - - static const PageInfo page = PageInfo(name); -} - /// generated route for /// [FailedBackupStatusPage] class FailedBackupStatusRoute extends PageRouteInfo { diff --git a/mobile/lib/shared/ui/asset_grid/multiselect_grid.dart b/mobile/lib/shared/ui/asset_grid/multiselect_grid.dart index 77548042ff..cf9420b554 100644 --- a/mobile/lib/shared/ui/asset_grid/multiselect_grid.dart +++ b/mobile/lib/shared/ui/asset_grid/multiselect_grid.dart @@ -184,11 +184,6 @@ class MultiselectGrid extends HookConsumerWidget { currentUser, 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(); final isDeleted = await ref .read(assetProvider.notifier) @@ -238,13 +233,7 @@ class MultiselectGrid extends HookConsumerWidget { final toDelete = ownedRemoteSelection( localErrorMessage: 'home_page_delete_remote_err_local'.tr(), ownerErrorMessage: '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 .read(assetProvider.notifier) @@ -372,12 +361,8 @@ class MultiselectGrid extends HookConsumerWidget { final remoteAssets = ownedRemoteSelection( localErrorMessage: 'home_page_favorite_err_local'.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) { handleEditDateTime(ref, context, remoteAssets.toList()); } @@ -391,12 +376,8 @@ class MultiselectGrid extends HookConsumerWidget { final remoteAssets = ownedRemoteSelection( localErrorMessage: 'home_page_favorite_err_local'.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) { handleEditLocation(ref, context, remoteAssets.toList()); } diff --git a/mobile/openapi/doc/AssetApi.md b/mobile/openapi/doc/AssetApi.md index 5c2af2594b..d710ef926a 100644 --- a/mobile/openapi/doc/AssetApi.md +++ b/mobile/openapi/doc/AssetApi.md @@ -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) # **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 isFavorite = true; // bool | final isOffline = true; // bool | -final isReadOnly = true; // bool | final isVisible = true; // bool | final libraryId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | final livePhotoData = BINARY_DATA_HERE; // MultipartFile | final sidecarData = BINARY_DATA_HERE; // MultipartFile | 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); } catch (e) { print('Exception when calling AssetApi->uploadFile: $e\n'); @@ -1018,7 +1017,6 @@ Name | Type | Description | Notes **isArchived** | **bool**| | [optional] **isFavorite** | **bool**| | [optional] **isOffline** | **bool**| | [optional] - **isReadOnly** | **bool**| | [optional] **isVisible** | **bool**| | [optional] **libraryId** | **String**| | [optional] **livePhotoData** | **MultipartFile**| | [optional] diff --git a/mobile/openapi/doc/AssetResponseDto.md b/mobile/openapi/doc/AssetResponseDto.md index 7c79f74183..98290b3745 100644 --- a/mobile/openapi/doc/AssetResponseDto.md +++ b/mobile/openapi/doc/AssetResponseDto.md @@ -18,10 +18,10 @@ Name | Type | Description | Notes **hasMetadata** | **bool** | | **id** | **String** | | **isArchived** | **bool** | | -**isExternal** | **bool** | | +**isExternal** | **bool** | This property was deprecated in v1.104.0 | [optional] **isFavorite** | **bool** | | **isOffline** | **bool** | | -**isReadOnly** | **bool** | | +**isReadOnly** | **bool** | This property was deprecated in v1.104.0 | [optional] **isTrashed** | **bool** | | **libraryId** | **String** | | **livePhotoVideoId** | **String** | | [optional] diff --git a/mobile/openapi/doc/MetadataSearchDto.md b/mobile/openapi/doc/MetadataSearchDto.md index d9448bd7f7..d6eb2c34be 100644 --- a/mobile/openapi/doc/MetadataSearchDto.md +++ b/mobile/openapi/doc/MetadataSearchDto.md @@ -19,12 +19,10 @@ Name | Type | Description | Notes **id** | **String** | | [optional] **isArchived** | **bool** | | [optional] **isEncoded** | **bool** | | [optional] -**isExternal** | **bool** | | [optional] **isFavorite** | **bool** | | [optional] **isMotion** | **bool** | | [optional] **isNotInAlbum** | **bool** | | [optional] **isOffline** | **bool** | | [optional] -**isReadOnly** | **bool** | | [optional] **isVisible** | **bool** | | [optional] **lensModel** | **String** | | [optional] **libraryId** | **String** | | [optional] diff --git a/mobile/openapi/doc/SmartSearchDto.md b/mobile/openapi/doc/SmartSearchDto.md index d5f4c40256..145b3b0264 100644 --- a/mobile/openapi/doc/SmartSearchDto.md +++ b/mobile/openapi/doc/SmartSearchDto.md @@ -15,12 +15,10 @@ Name | Type | Description | Notes **deviceId** | **String** | | [optional] **isArchived** | **bool** | | [optional] **isEncoded** | **bool** | | [optional] -**isExternal** | **bool** | | [optional] **isFavorite** | **bool** | | [optional] **isMotion** | **bool** | | [optional] **isNotInAlbum** | **bool** | | [optional] **isOffline** | **bool** | | [optional] -**isReadOnly** | **bool** | | [optional] **isVisible** | **bool** | | [optional] **lensModel** | **String** | | [optional] **libraryId** | **String** | | [optional] diff --git a/mobile/openapi/lib/api/asset_api.dart b/mobile/openapi/lib/api/asset_api.dart index 93b0e98bab..6515046869 100644 --- a/mobile/openapi/lib/api/asset_api.dart +++ b/mobile/openapi/lib/api/asset_api.dart @@ -968,8 +968,6 @@ class AssetApi { /// /// * [bool] isOffline: /// - /// * [bool] isReadOnly: - /// /// * [bool] isVisible: /// /// * [String] libraryId: @@ -977,7 +975,7 @@ class AssetApi { /// * [MultipartFile] livePhotoData: /// /// * [MultipartFile] sidecarData: - Future 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 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 final path = r'/asset/upload'; @@ -1037,10 +1035,6 @@ class AssetApi { hasFields = true; mp.fields[r'isOffline'] = parameterToString(isOffline); } - if (isReadOnly != null) { - hasFields = true; - mp.fields[r'isReadOnly'] = parameterToString(isReadOnly); - } if (isVisible != null) { hasFields = true; mp.fields[r'isVisible'] = parameterToString(isVisible); @@ -1099,8 +1093,6 @@ class AssetApi { /// /// * [bool] isOffline: /// - /// * [bool] isReadOnly: - /// /// * [bool] isVisible: /// /// * [String] libraryId: @@ -1108,8 +1100,8 @@ class AssetApi { /// * [MultipartFile] livePhotoData: /// /// * [MultipartFile] sidecarData: - Future 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 { - 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, ); + Future 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, isVisible: isVisible, libraryId: libraryId, livePhotoData: livePhotoData, sidecarData: sidecarData, ); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } diff --git a/mobile/openapi/lib/model/asset_response_dto.dart b/mobile/openapi/lib/model/asset_response_dto.dart index bbda5ba604..6ba7f27d60 100644 --- a/mobile/openapi/lib/model/asset_response_dto.dart +++ b/mobile/openapi/lib/model/asset_response_dto.dart @@ -23,10 +23,10 @@ class AssetResponseDto { required this.hasMetadata, required this.id, required this.isArchived, - required this.isExternal, + this.isExternal, required this.isFavorite, required this.isOffline, - required this.isReadOnly, + this.isReadOnly, required this.isTrashed, required this.libraryId, this.livePhotoVideoId, @@ -74,13 +74,27 @@ class AssetResponseDto { 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 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; @@ -178,10 +192,10 @@ class AssetResponseDto { (hasMetadata.hashCode) + (id.hashCode) + (isArchived.hashCode) + - (isExternal.hashCode) + + (isExternal == null ? 0 : isExternal!.hashCode) + (isFavorite.hashCode) + (isOffline.hashCode) + - (isReadOnly.hashCode) + + (isReadOnly == null ? 0 : isReadOnly!.hashCode) + (isTrashed.hashCode) + (libraryId.hashCode) + (livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode) + @@ -220,10 +234,18 @@ class AssetResponseDto { json[r'hasMetadata'] = this.hasMetadata; json[r'id'] = this.id; json[r'isArchived'] = this.isArchived; + if (this.isExternal != null) { json[r'isExternal'] = this.isExternal; + } else { + // json[r'isExternal'] = null; + } json[r'isFavorite'] = this.isFavorite; json[r'isOffline'] = this.isOffline; + if (this.isReadOnly != null) { json[r'isReadOnly'] = this.isReadOnly; + } else { + // json[r'isReadOnly'] = null; + } json[r'isTrashed'] = this.isTrashed; json[r'libraryId'] = this.libraryId; if (this.livePhotoVideoId != null) { @@ -287,10 +309,10 @@ class AssetResponseDto { hasMetadata: mapValueOfType(json, r'hasMetadata')!, id: mapValueOfType(json, r'id')!, isArchived: mapValueOfType(json, r'isArchived')!, - isExternal: mapValueOfType(json, r'isExternal')!, + isExternal: mapValueOfType(json, r'isExternal'), isFavorite: mapValueOfType(json, r'isFavorite')!, isOffline: mapValueOfType(json, r'isOffline')!, - isReadOnly: mapValueOfType(json, r'isReadOnly')!, + isReadOnly: mapValueOfType(json, r'isReadOnly'), isTrashed: mapValueOfType(json, r'isTrashed')!, libraryId: mapValueOfType(json, r'libraryId')!, livePhotoVideoId: mapValueOfType(json, r'livePhotoVideoId'), @@ -365,10 +387,8 @@ class AssetResponseDto { 'hasMetadata', 'id', 'isArchived', - 'isExternal', 'isFavorite', 'isOffline', - 'isReadOnly', 'isTrashed', 'libraryId', 'localDateTime', diff --git a/mobile/openapi/lib/model/metadata_search_dto.dart b/mobile/openapi/lib/model/metadata_search_dto.dart index 61bf44ae12..6ef3ffcfcd 100644 --- a/mobile/openapi/lib/model/metadata_search_dto.dart +++ b/mobile/openapi/lib/model/metadata_search_dto.dart @@ -24,12 +24,10 @@ class MetadataSearchDto { this.id, this.isArchived, this.isEncoded, - this.isExternal, this.isFavorite, this.isMotion, this.isNotInAlbum, this.isOffline, - this.isReadOnly, this.isVisible, this.lensModel, this.libraryId, @@ -148,14 +146,6 @@ class MetadataSearchDto { /// 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 /// does not include a default value (using the "default:" property), however, the generated @@ -188,14 +178,6 @@ class MetadataSearchDto { /// 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 /// does not include a default value (using the "default:" property), however, the generated @@ -426,12 +408,10 @@ class MetadataSearchDto { other.id == id && other.isArchived == isArchived && other.isEncoded == isEncoded && - other.isExternal == isExternal && other.isFavorite == isFavorite && other.isMotion == isMotion && other.isNotInAlbum == isNotInAlbum && other.isOffline == isOffline && - other.isReadOnly == isReadOnly && other.isVisible == isVisible && other.lensModel == lensModel && other.libraryId == libraryId && @@ -475,12 +455,10 @@ class MetadataSearchDto { (id == null ? 0 : id!.hashCode) + (isArchived == null ? 0 : isArchived!.hashCode) + (isEncoded == null ? 0 : isEncoded!.hashCode) + - (isExternal == null ? 0 : isExternal!.hashCode) + (isFavorite == null ? 0 : isFavorite!.hashCode) + (isMotion == null ? 0 : isMotion!.hashCode) + (isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) + (isOffline == null ? 0 : isOffline!.hashCode) + - (isReadOnly == null ? 0 : isReadOnly!.hashCode) + (isVisible == null ? 0 : isVisible!.hashCode) + (lensModel == null ? 0 : lensModel!.hashCode) + (libraryId == null ? 0 : libraryId!.hashCode) + @@ -511,7 +489,7 @@ class MetadataSearchDto { (withStacked == null ? 0 : withStacked!.hashCode); @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 toJson() { final json = {}; @@ -570,11 +548,6 @@ class MetadataSearchDto { } else { // json[r'isEncoded'] = null; } - if (this.isExternal != null) { - json[r'isExternal'] = this.isExternal; - } else { - // json[r'isExternal'] = null; - } if (this.isFavorite != null) { json[r'isFavorite'] = this.isFavorite; } else { @@ -595,11 +568,6 @@ class MetadataSearchDto { } else { // json[r'isOffline'] = null; } - if (this.isReadOnly != null) { - json[r'isReadOnly'] = this.isReadOnly; - } else { - // json[r'isReadOnly'] = null; - } if (this.isVisible != null) { json[r'isVisible'] = this.isVisible; } else { @@ -754,12 +722,10 @@ class MetadataSearchDto { id: mapValueOfType(json, r'id'), isArchived: mapValueOfType(json, r'isArchived'), isEncoded: mapValueOfType(json, r'isEncoded'), - isExternal: mapValueOfType(json, r'isExternal'), isFavorite: mapValueOfType(json, r'isFavorite'), isMotion: mapValueOfType(json, r'isMotion'), isNotInAlbum: mapValueOfType(json, r'isNotInAlbum'), isOffline: mapValueOfType(json, r'isOffline'), - isReadOnly: mapValueOfType(json, r'isReadOnly'), isVisible: mapValueOfType(json, r'isVisible'), lensModel: mapValueOfType(json, r'lensModel'), libraryId: mapValueOfType(json, r'libraryId'), diff --git a/mobile/openapi/lib/model/smart_search_dto.dart b/mobile/openapi/lib/model/smart_search_dto.dart index f24595fa1b..6b9b17e352 100644 --- a/mobile/openapi/lib/model/smart_search_dto.dart +++ b/mobile/openapi/lib/model/smart_search_dto.dart @@ -20,12 +20,10 @@ class SmartSearchDto { this.deviceId, this.isArchived, this.isEncoded, - this.isExternal, this.isFavorite, this.isMotion, this.isNotInAlbum, this.isOffline, - this.isReadOnly, this.isVisible, this.lensModel, this.libraryId, @@ -104,14 +102,6 @@ class SmartSearchDto { /// 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 /// does not include a default value (using the "default:" property), however, the generated @@ -144,14 +134,6 @@ class SmartSearchDto { /// 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 /// does not include a default value (using the "default:" property), however, the generated @@ -306,12 +288,10 @@ class SmartSearchDto { other.deviceId == deviceId && other.isArchived == isArchived && other.isEncoded == isEncoded && - other.isExternal == isExternal && other.isFavorite == isFavorite && other.isMotion == isMotion && other.isNotInAlbum == isNotInAlbum && other.isOffline == isOffline && - other.isReadOnly == isReadOnly && other.isVisible == isVisible && other.lensModel == lensModel && other.libraryId == libraryId && @@ -343,12 +323,10 @@ class SmartSearchDto { (deviceId == null ? 0 : deviceId!.hashCode) + (isArchived == null ? 0 : isArchived!.hashCode) + (isEncoded == null ? 0 : isEncoded!.hashCode) + - (isExternal == null ? 0 : isExternal!.hashCode) + (isFavorite == null ? 0 : isFavorite!.hashCode) + (isMotion == null ? 0 : isMotion!.hashCode) + (isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) + (isOffline == null ? 0 : isOffline!.hashCode) + - (isReadOnly == null ? 0 : isReadOnly!.hashCode) + (isVisible == null ? 0 : isVisible!.hashCode) + (lensModel == null ? 0 : lensModel!.hashCode) + (libraryId == null ? 0 : libraryId!.hashCode) + @@ -371,7 +349,7 @@ class SmartSearchDto { (withExif == null ? 0 : withExif!.hashCode); @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 toJson() { final json = {}; @@ -410,11 +388,6 @@ class SmartSearchDto { } else { // json[r'isEncoded'] = null; } - if (this.isExternal != null) { - json[r'isExternal'] = this.isExternal; - } else { - // json[r'isExternal'] = null; - } if (this.isFavorite != null) { json[r'isFavorite'] = this.isFavorite; } else { @@ -435,11 +408,6 @@ class SmartSearchDto { } else { // json[r'isOffline'] = null; } - if (this.isReadOnly != null) { - json[r'isReadOnly'] = this.isReadOnly; - } else { - // json[r'isReadOnly'] = null; - } if (this.isVisible != null) { json[r'isVisible'] = this.isVisible; } else { @@ -546,12 +514,10 @@ class SmartSearchDto { deviceId: mapValueOfType(json, r'deviceId'), isArchived: mapValueOfType(json, r'isArchived'), isEncoded: mapValueOfType(json, r'isEncoded'), - isExternal: mapValueOfType(json, r'isExternal'), isFavorite: mapValueOfType(json, r'isFavorite'), isMotion: mapValueOfType(json, r'isMotion'), isNotInAlbum: mapValueOfType(json, r'isNotInAlbum'), isOffline: mapValueOfType(json, r'isOffline'), - isReadOnly: mapValueOfType(json, r'isReadOnly'), isVisible: mapValueOfType(json, r'isVisible'), lensModel: mapValueOfType(json, r'lensModel'), libraryId: mapValueOfType(json, r'libraryId'), diff --git a/mobile/openapi/test/asset_api_test.dart b/mobile/openapi/test/asset_api_test.dart index 1f6f4e6923..0a278daa32 100644 --- a/mobile/openapi/test/asset_api_test.dart +++ b/mobile/openapi/test/asset_api_test.dart @@ -105,7 +105,7 @@ void main() { // TODO }); - //Future 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 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 { // TODO }); diff --git a/mobile/openapi/test/asset_response_dto_test.dart b/mobile/openapi/test/asset_response_dto_test.dart index b8a64b6a24..fa12bc9f15 100644 --- a/mobile/openapi/test/asset_response_dto_test.dart +++ b/mobile/openapi/test/asset_response_dto_test.dart @@ -67,6 +67,7 @@ void main() { // TODO }); + // This property was deprecated in v1.104.0 // bool isExternal test('to test the property `isExternal`', () async { // TODO @@ -82,6 +83,7 @@ void main() { // TODO }); + // This property was deprecated in v1.104.0 // bool isReadOnly test('to test the property `isReadOnly`', () async { // TODO diff --git a/mobile/openapi/test/metadata_search_dto_test.dart b/mobile/openapi/test/metadata_search_dto_test.dart index 8037f08c67..c630fec9a5 100644 --- a/mobile/openapi/test/metadata_search_dto_test.dart +++ b/mobile/openapi/test/metadata_search_dto_test.dart @@ -71,11 +71,6 @@ void main() { // TODO }); - // bool isExternal - test('to test the property `isExternal`', () async { - // TODO - }); - // bool isFavorite test('to test the property `isFavorite`', () async { // TODO @@ -96,11 +91,6 @@ void main() { // TODO }); - // bool isReadOnly - test('to test the property `isReadOnly`', () async { - // TODO - }); - // bool isVisible test('to test the property `isVisible`', () async { // TODO diff --git a/mobile/openapi/test/smart_search_dto_test.dart b/mobile/openapi/test/smart_search_dto_test.dart index 5263f7bb6a..6ad95107ba 100644 --- a/mobile/openapi/test/smart_search_dto_test.dart +++ b/mobile/openapi/test/smart_search_dto_test.dart @@ -51,11 +51,6 @@ void main() { // TODO }); - // bool isExternal - test('to test the property `isExternal`', () async { - // TODO - }); - // bool isFavorite test('to test the property `isFavorite`', () async { // TODO @@ -76,11 +71,6 @@ void main() { // TODO }); - // bool isReadOnly - test('to test the property `isReadOnly`', () async { - // TODO - }); - // bool isVisible test('to test the property `isVisible`', () async { // TODO diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 31ca9b2937..ae6a3dfb06 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -7297,6 +7297,8 @@ "type": "boolean" }, "isExternal": { + "deprecated": true, + "description": "This property was deprecated in v1.104.0", "type": "boolean" }, "isFavorite": { @@ -7306,6 +7308,8 @@ "type": "boolean" }, "isReadOnly": { + "deprecated": true, + "description": "This property was deprecated in v1.104.0", "type": "boolean" }, "isTrashed": { @@ -7388,10 +7392,8 @@ "hasMetadata", "id", "isArchived", - "isExternal", "isFavorite", "isOffline", - "isReadOnly", "isTrashed", "libraryId", "localDateTime", @@ -7652,9 +7654,6 @@ "isOffline": { "type": "boolean" }, - "isReadOnly": { - "type": "boolean" - }, "isVisible": { "type": "boolean" }, @@ -8599,9 +8598,6 @@ "isEncoded": { "type": "boolean" }, - "isExternal": { - "type": "boolean" - }, "isFavorite": { "type": "boolean" }, @@ -8614,9 +8610,6 @@ "isOffline": { "type": "boolean" }, - "isReadOnly": { - "type": "boolean" - }, "isVisible": { "type": "boolean" }, @@ -9821,9 +9814,6 @@ "isEncoded": { "type": "boolean" }, - "isExternal": { - "type": "boolean" - }, "isFavorite": { "type": "boolean" }, @@ -9836,9 +9826,6 @@ "isOffline": { "type": "boolean" }, - "isReadOnly": { - "type": "boolean" - }, "isVisible": { "type": "boolean" }, diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index fee15d0fbc..903d8e048d 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -122,10 +122,12 @@ export type AssetResponseDto = { hasMetadata: boolean; id: string; isArchived: boolean; - isExternal: boolean; + /** This property was deprecated in v1.104.0 */ + isExternal?: boolean; isFavorite: boolean; isOffline: boolean; - isReadOnly: boolean; + /** This property was deprecated in v1.104.0 */ + isReadOnly?: boolean; isTrashed: boolean; libraryId: string; livePhotoVideoId?: string | null; @@ -296,7 +298,6 @@ export type CreateAssetDto = { isArchived?: boolean; isFavorite?: boolean; isOffline?: boolean; - isReadOnly?: boolean; isVisible?: boolean; libraryId?: string; livePhotoData?: Blob; @@ -622,12 +623,10 @@ export type MetadataSearchDto = { id?: string; isArchived?: boolean; isEncoded?: boolean; - isExternal?: boolean; isFavorite?: boolean; isMotion?: boolean; isNotInAlbum?: boolean; isOffline?: boolean; - isReadOnly?: boolean; isVisible?: boolean; lensModel?: string; libraryId?: string; @@ -699,12 +698,10 @@ export type SmartSearchDto = { deviceId?: string; isArchived?: boolean; isEncoded?: boolean; - isExternal?: boolean; isFavorite?: boolean; isMotion?: boolean; isNotInAlbum?: boolean; isOffline?: boolean; - isReadOnly?: boolean; isVisible?: boolean; lensModel?: string; libraryId?: string; diff --git a/server/src/decorators.ts b/server/src/decorators.ts index 9f80ab68a5..e1966013b1 100644 --- a/server/src/decorators.ts +++ b/server/src/decorators.ts @@ -113,6 +113,7 @@ export const DummyValue = { PAGINATION: { take: 10, skip: 0 }, EMAIL: 'user@immich.app', STRING: 'abcdefghi', + NUMBER: 50, BUFFER: Buffer.from('abcdefghi'), DATE: new Date(), TIME_BUCKET: '2024-01-01T00:00:00.000Z', diff --git a/server/src/dtos/asset-response.dto.ts b/server/src/dtos/asset-response.dto.ts index d094511bfb..f6ce8271ed 100644 --- a/server/src/dtos/asset-response.dto.ts +++ b/server/src/dtos/asset-response.dto.ts @@ -36,8 +36,10 @@ export class AssetResponseDto extends SanitizedAssetResponseDto { isArchived!: boolean; isTrashed!: boolean; isOffline!: boolean; - isExternal!: boolean; - isReadOnly!: boolean; + @PropertyLifecycle({ deprecatedAt: 'v1.104.0' }) + isExternal?: boolean; + @PropertyLifecycle({ deprecatedAt: 'v1.104.0' }) + isReadOnly?: boolean; exifInfo?: ExifResponseDto; smartInfo?: SmartInfoResponseDto; tags?: TagResponseDto[]; @@ -124,9 +126,9 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As .map((a) => mapAsset(a, { stripMetadata, auth: options.auth })) : undefined, stackCount: entity.stack?.assets?.length ?? null, - isExternal: entity.isExternal, isOffline: entity.isOffline, - isReadOnly: entity.isReadOnly, + isExternal: false, + isReadOnly: false, hasMetadata: true, }; } diff --git a/server/src/dtos/asset-v1.dto.ts b/server/src/dtos/asset-v1.dto.ts index 5cac6fbe65..131d28ca4a 100644 --- a/server/src/dtos/asset-v1.dto.ts +++ b/server/src/dtos/asset-v1.dto.ts @@ -97,9 +97,6 @@ export class CreateAssetDto { @ValidateBoolean({ optional: true }) isOffline?: boolean; - @ValidateBoolean({ optional: true }) - isReadOnly?: boolean; - // The properties below are added to correctly generate the API docs // and client SDKs. Validation should be handled in the controller. @ApiProperty({ type: 'string', format: 'binary' }) diff --git a/server/src/dtos/search.dto.ts b/server/src/dtos/search.dto.ts index 0eb2aae749..31d4195e7a 100644 --- a/server/src/dtos/search.dto.ts +++ b/server/src/dtos/search.dto.ts @@ -33,9 +33,6 @@ class BaseSearchDto { @ValidateBoolean({ optional: true }) isEncoded?: boolean; - @ValidateBoolean({ optional: true }) - isExternal?: boolean; - @ValidateBoolean({ optional: true }) isFavorite?: boolean; @@ -45,9 +42,6 @@ class BaseSearchDto { @ValidateBoolean({ optional: true }) isOffline?: boolean; - @ValidateBoolean({ optional: true }) - isReadOnly?: boolean; - @ValidateBoolean({ optional: true }) isVisible?: boolean; diff --git a/server/src/entities/asset.entity.ts b/server/src/entities/asset.entity.ts index c977560bea..1181b42da9 100644 --- a/server/src/entities/asset.entity.ts +++ b/server/src/entities/asset.entity.ts @@ -106,9 +106,6 @@ export class AssetEntity { @Column({ type: 'boolean', default: false }) isExternal!: boolean; - @Column({ type: 'boolean', default: false }) - isReadOnly!: boolean; - @Column({ type: 'boolean', default: false }) isOffline!: boolean; diff --git a/server/src/interfaces/job.interface.ts b/server/src/interfaces/job.interface.ts index a4c5a60459..0deb6d7266 100644 --- a/server/src/interfaces/job.interface.ts +++ b/server/src/interfaces/job.interface.ts @@ -108,10 +108,6 @@ export interface IEntityJob extends IBaseJob { source?: 'upload' | 'sidecar-write'; } -export interface IAssetDeletionJob extends IEntityJob { - fromExternal?: boolean; -} - export interface ILibraryFileJob extends IEntityJob { ownerId: string; assetPath: string; @@ -225,7 +221,7 @@ export type JobItem = // Asset Deletion | { 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 } // Library Management diff --git a/server/src/interfaces/search.interface.ts b/server/src/interfaces/search.interface.ts index 14c70631d6..56dbe1da4b 100644 --- a/server/src/interfaces/search.interface.ts +++ b/server/src/interfaces/search.interface.ts @@ -56,11 +56,9 @@ export type SearchIdOptions = SearchAssetIDOptions & SearchUserIdOptions; export interface SearchStatusOptions { isArchived?: boolean; isEncoded?: boolean; - isExternal?: boolean; isFavorite?: boolean; isMotion?: boolean; isOffline?: boolean; - isReadOnly?: boolean; isVisible?: boolean; isNotInAlbum?: boolean; type?: AssetType; diff --git a/server/src/migrations/1714698592332-RemoveIsReadOnly.ts b/server/src/migrations/1714698592332-RemoveIsReadOnly.ts new file mode 100644 index 0000000000..bc56f8dac7 --- /dev/null +++ b/server/src/migrations/1714698592332-RemoveIsReadOnly.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class RemoveIsReadOnly1714698592332 implements MigrationInterface { + name = 'RemoveIsReadOnly1714698592332' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "assets" DROP COLUMN "isReadOnly"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "assets" ADD "isReadOnly" boolean NOT NULL DEFAULT false`); + } + +} diff --git a/server/src/queries/asset.repository.sql b/server/src/queries/asset.repository.sql index 8e8e55e6e3..de97757f17 100644 --- a/server/src/queries/asset.repository.sql +++ b/server/src/queries/asset.repository.sql @@ -22,7 +22,6 @@ SELECT "entity"."isFavorite" AS "entity_isFavorite", "entity"."isArchived" AS "entity_isArchived", "entity"."isExternal" AS "entity_isExternal", - "entity"."isReadOnly" AS "entity_isReadOnly", "entity"."isOffline" AS "entity_isOffline", "entity"."checksum" AS "entity_checksum", "entity"."duration" AS "entity_duration", @@ -105,7 +104,6 @@ SELECT "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", "AssetEntity"."isArchived" AS "AssetEntity_isArchived", "AssetEntity"."isExternal" AS "AssetEntity_isExternal", - "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", "AssetEntity"."isOffline" AS "AssetEntity_isOffline", "AssetEntity"."checksum" AS "AssetEntity_checksum", "AssetEntity"."duration" AS "AssetEntity_duration", @@ -141,7 +139,6 @@ SELECT "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", "AssetEntity"."isArchived" AS "AssetEntity_isArchived", "AssetEntity"."isExternal" AS "AssetEntity_isExternal", - "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", "AssetEntity"."isOffline" AS "AssetEntity_isOffline", "AssetEntity"."checksum" AS "AssetEntity_checksum", "AssetEntity"."duration" AS "AssetEntity_duration", @@ -226,7 +223,6 @@ SELECT "bd93d5747511a4dad4923546c51365bf1a803774"."isFavorite" AS "bd93d5747511a4dad4923546c51365bf1a803774_isFavorite", "bd93d5747511a4dad4923546c51365bf1a803774"."isArchived" AS "bd93d5747511a4dad4923546c51365bf1a803774_isArchived", "bd93d5747511a4dad4923546c51365bf1a803774"."isExternal" AS "bd93d5747511a4dad4923546c51365bf1a803774_isExternal", - "bd93d5747511a4dad4923546c51365bf1a803774"."isReadOnly" AS "bd93d5747511a4dad4923546c51365bf1a803774_isReadOnly", "bd93d5747511a4dad4923546c51365bf1a803774"."isOffline" AS "bd93d5747511a4dad4923546c51365bf1a803774_isOffline", "bd93d5747511a4dad4923546c51365bf1a803774"."checksum" AS "bd93d5747511a4dad4923546c51365bf1a803774_checksum", "bd93d5747511a4dad4923546c51365bf1a803774"."duration" AS "bd93d5747511a4dad4923546c51365bf1a803774_duration", @@ -308,7 +304,6 @@ FROM "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", "AssetEntity"."isArchived" AS "AssetEntity_isArchived", "AssetEntity"."isExternal" AS "AssetEntity_isExternal", - "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", "AssetEntity"."isOffline" AS "AssetEntity_isOffline", "AssetEntity"."checksum" AS "AssetEntity_checksum", "AssetEntity"."duration" AS "AssetEntity_duration", @@ -405,7 +400,6 @@ SELECT "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", "AssetEntity"."isArchived" AS "AssetEntity_isArchived", "AssetEntity"."isExternal" AS "AssetEntity_isExternal", - "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", "AssetEntity"."isOffline" AS "AssetEntity_isOffline", "AssetEntity"."checksum" AS "AssetEntity_checksum", "AssetEntity"."duration" AS "AssetEntity_duration", @@ -451,7 +445,6 @@ SELECT "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", "AssetEntity"."isArchived" AS "AssetEntity_isArchived", "AssetEntity"."isExternal" AS "AssetEntity_isExternal", - "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", "AssetEntity"."isOffline" AS "AssetEntity_isOffline", "AssetEntity"."checksum" AS "AssetEntity_checksum", "AssetEntity"."duration" AS "AssetEntity_duration", @@ -519,7 +512,6 @@ SELECT "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", "AssetEntity"."isArchived" AS "AssetEntity_isArchived", "AssetEntity"."isExternal" AS "AssetEntity_isExternal", - "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", "AssetEntity"."isOffline" AS "AssetEntity_isOffline", "AssetEntity"."checksum" AS "AssetEntity_checksum", "AssetEntity"."duration" AS "AssetEntity_duration", @@ -608,7 +600,6 @@ SELECT "asset"."isFavorite" AS "asset_isFavorite", "asset"."isArchived" AS "asset_isArchived", "asset"."isExternal" AS "asset_isExternal", - "asset"."isReadOnly" AS "asset_isReadOnly", "asset"."isOffline" AS "asset_isOffline", "asset"."checksum" AS "asset_checksum", "asset"."duration" AS "asset_duration", @@ -667,7 +658,6 @@ SELECT "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", "stackedAssets"."isArchived" AS "stackedAssets_isArchived", "stackedAssets"."isExternal" AS "stackedAssets_isExternal", - "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", "stackedAssets"."isOffline" AS "stackedAssets_isOffline", "stackedAssets"."checksum" AS "stackedAssets_checksum", "stackedAssets"."duration" AS "stackedAssets_duration", @@ -784,7 +774,6 @@ SELECT "asset"."isFavorite" AS "asset_isFavorite", "asset"."isArchived" AS "asset_isArchived", "asset"."isExternal" AS "asset_isExternal", - "asset"."isReadOnly" AS "asset_isReadOnly", "asset"."isOffline" AS "asset_isOffline", "asset"."checksum" AS "asset_checksum", "asset"."duration" AS "asset_duration", @@ -843,7 +832,6 @@ SELECT "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", "stackedAssets"."isArchived" AS "stackedAssets_isArchived", "stackedAssets"."isExternal" AS "stackedAssets_isExternal", - "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", "stackedAssets"."isOffline" AS "stackedAssets_isOffline", "stackedAssets"."checksum" AS "stackedAssets_checksum", "stackedAssets"."duration" AS "stackedAssets_duration", @@ -891,7 +879,6 @@ SELECT "asset"."isFavorite" AS "asset_isFavorite", "asset"."isArchived" AS "asset_isArchived", "asset"."isExternal" AS "asset_isExternal", - "asset"."isReadOnly" AS "asset_isReadOnly", "asset"."isOffline" AS "asset_isOffline", "asset"."checksum" AS "asset_checksum", "asset"."duration" AS "asset_duration", @@ -950,7 +937,6 @@ SELECT "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", "stackedAssets"."isArchived" AS "stackedAssets_isArchived", "stackedAssets"."isExternal" AS "stackedAssets_isExternal", - "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", "stackedAssets"."isOffline" AS "stackedAssets_isOffline", "stackedAssets"."checksum" AS "stackedAssets_checksum", "stackedAssets"."duration" AS "stackedAssets_duration", diff --git a/server/src/queries/person.repository.sql b/server/src/queries/person.repository.sql index 1cde746d8b..6b7739aed3 100644 --- a/server/src/queries/person.repository.sql +++ b/server/src/queries/person.repository.sql @@ -165,7 +165,6 @@ FROM "AssetFaceEntity__AssetFaceEntity_asset"."isFavorite" AS "AssetFaceEntity__AssetFaceEntity_asset_isFavorite", "AssetFaceEntity__AssetFaceEntity_asset"."isArchived" AS "AssetFaceEntity__AssetFaceEntity_asset_isArchived", "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"."checksum" AS "AssetFaceEntity__AssetFaceEntity_asset_checksum", "AssetFaceEntity__AssetFaceEntity_asset"."duration" AS "AssetFaceEntity__AssetFaceEntity_asset_duration", @@ -263,7 +262,6 @@ FROM "AssetEntity"."isFavorite" AS "AssetEntity_isFavorite", "AssetEntity"."isArchived" AS "AssetEntity_isArchived", "AssetEntity"."isExternal" AS "AssetEntity_isExternal", - "AssetEntity"."isReadOnly" AS "AssetEntity_isReadOnly", "AssetEntity"."isOffline" AS "AssetEntity_isOffline", "AssetEntity"."checksum" AS "AssetEntity_checksum", "AssetEntity"."duration" AS "AssetEntity_duration", @@ -393,7 +391,6 @@ SELECT "AssetFaceEntity__AssetFaceEntity_asset"."isFavorite" AS "AssetFaceEntity__AssetFaceEntity_asset_isFavorite", "AssetFaceEntity__AssetFaceEntity_asset"."isArchived" AS "AssetFaceEntity__AssetFaceEntity_asset_isArchived", "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"."checksum" AS "AssetFaceEntity__AssetFaceEntity_asset_checksum", "AssetFaceEntity__AssetFaceEntity_asset"."duration" AS "AssetFaceEntity__AssetFaceEntity_asset_duration", diff --git a/server/src/queries/search.repository.sql b/server/src/queries/search.repository.sql index 3e83d72384..e75cd3322a 100644 --- a/server/src/queries/search.repository.sql +++ b/server/src/queries/search.repository.sql @@ -27,7 +27,6 @@ FROM "asset"."isFavorite" AS "asset_isFavorite", "asset"."isArchived" AS "asset_isArchived", "asset"."isExternal" AS "asset_isExternal", - "asset"."isReadOnly" AS "asset_isReadOnly", "asset"."isOffline" AS "asset_isOffline", "asset"."checksum" AS "asset_checksum", "asset"."duration" AS "asset_duration", @@ -58,7 +57,6 @@ FROM "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", "stackedAssets"."isArchived" AS "stackedAssets_isArchived", "stackedAssets"."isExternal" AS "stackedAssets_isExternal", - "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", "stackedAssets"."isOffline" AS "stackedAssets_isOffline", "stackedAssets"."checksum" AS "stackedAssets_checksum", "stackedAssets"."duration" AS "stackedAssets_duration", @@ -123,7 +121,6 @@ SELECT "asset"."isFavorite" AS "asset_isFavorite", "asset"."isArchived" AS "asset_isArchived", "asset"."isExternal" AS "asset_isExternal", - "asset"."isReadOnly" AS "asset_isReadOnly", "asset"."isOffline" AS "asset_isOffline", "asset"."checksum" AS "asset_checksum", "asset"."duration" AS "asset_duration", @@ -154,7 +151,6 @@ SELECT "stackedAssets"."isFavorite" AS "stackedAssets_isFavorite", "stackedAssets"."isArchived" AS "stackedAssets_isArchived", "stackedAssets"."isExternal" AS "stackedAssets_isExternal", - "stackedAssets"."isReadOnly" AS "stackedAssets_isReadOnly", "stackedAssets"."isOffline" AS "stackedAssets_isOffline", "stackedAssets"."checksum" AS "stackedAssets_checksum", "stackedAssets"."duration" AS "stackedAssets_duration", @@ -333,7 +329,6 @@ SELECT "asset"."isFavorite" AS "asset_isFavorite", "asset"."isArchived" AS "asset_isArchived", "asset"."isExternal" AS "asset_isExternal", - "asset"."isReadOnly" AS "asset_isReadOnly", "asset"."isOffline" AS "asset_isOffline", "asset"."checksum" AS "asset_checksum", "asset"."duration" AS "asset_duration", diff --git a/server/src/queries/shared.link.repository.sql b/server/src/queries/shared.link.repository.sql index 78581b8ba1..ae416696ee 100644 --- a/server/src/queries/shared.link.repository.sql +++ b/server/src/queries/shared.link.repository.sql @@ -41,7 +41,6 @@ FROM "SharedLinkEntity__SharedLinkEntity_assets"."isFavorite" AS "SharedLinkEntity__SharedLinkEntity_assets_isFavorite", "SharedLinkEntity__SharedLinkEntity_assets"."isArchived" AS "SharedLinkEntity__SharedLinkEntity_assets_isArchived", "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"."checksum" AS "SharedLinkEntity__SharedLinkEntity_assets_checksum", "SharedLinkEntity__SharedLinkEntity_assets"."duration" AS "SharedLinkEntity__SharedLinkEntity_assets_duration", @@ -108,7 +107,6 @@ FROM "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isFavorite" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isFavorite", "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isArchived" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isArchived", "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isExternal" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isExternal", - "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isReadOnly" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isReadOnly", "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."isOffline" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_isOffline", "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."checksum" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_checksum", "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."duration" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_duration", @@ -231,7 +229,6 @@ SELECT "SharedLinkEntity__SharedLinkEntity_assets"."isFavorite" AS "SharedLinkEntity__SharedLinkEntity_assets_isFavorite", "SharedLinkEntity__SharedLinkEntity_assets"."isArchived" AS "SharedLinkEntity__SharedLinkEntity_assets_isArchived", "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"."checksum" AS "SharedLinkEntity__SharedLinkEntity_assets_checksum", "SharedLinkEntity__SharedLinkEntity_assets"."duration" AS "SharedLinkEntity__SharedLinkEntity_assets_duration", diff --git a/server/src/queries/user.repository.sql b/server/src/queries/user.repository.sql index 581ebe2277..30464da786 100644 --- a/server/src/queries/user.repository.sql +++ b/server/src/queries/user.repository.sql @@ -151,6 +151,14 @@ GROUP BY ORDER BY "users"."createdAt" ASC +-- UserRepository.updateUsage +UPDATE "users" +SET + "quotaUsageInBytes" = "quotaUsageInBytes" + 50, + "updatedAt" = CURRENT_TIMESTAMP +WHERE + "id" = $1 + -- UserRepository.syncUsage UPDATE "users" SET diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index 7618996fb1..88e23be437 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -253,7 +253,7 @@ export class AssetRepository implements IAssetRepository { @Chunked() async softDeleteAll(ids: string[]): Promise { - await this.repository.softDelete({ id: In(ids), isExternal: false }); + await this.repository.softDelete({ id: In(ids) }); } @Chunked() diff --git a/server/src/repositories/user.repository.ts b/server/src/repositories/user.repository.ts index 95341d7c1c..4f62732e7b 100644 --- a/server/src/repositories/user.repository.ts +++ b/server/src/repositories/user.repository.ts @@ -112,6 +112,7 @@ export class UserRepository implements IUserRepository { return stats; } + @GenerateSql({ params: [DummyValue.UUID, DummyValue.NUMBER] }) async updateUsage(id: string, delta: number): Promise { await this.userRepository.increment({ id }, 'quotaUsageInBytes', delta); } diff --git a/server/src/services/asset-v1.service.ts b/server/src/services/asset-v1.service.ts index 22b2618541..9667730fb3 100644 --- a/server/src/services/asset-v1.service.ts +++ b/server/src/services/asset-v1.service.ts @@ -295,7 +295,6 @@ export class AssetServiceV1 { livePhotoVideo: livePhotoAssetId === null ? null : ({ id: livePhotoAssetId } as AssetEntity), originalFileName: file.originalName, sidecarPath: sidecarPath || null, - isReadOnly: dto.isReadOnly ?? false, isOffline: dto.isOffline ?? false, }); diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index 27a7eeb88d..5a61f70da8 100755 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -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 () => { assetMock.getById.mockResolvedValue(assetStub.livePhotoStillAsset); diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index afb167f902..2e5c11b1ec 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -33,7 +33,7 @@ import { IAssetStackRepository } from 'src/interfaces/asset-stack.interface'; import { IAssetRepository } from 'src/interfaces/asset.interface'; import { ClientEvent, IEventRepository } from 'src/interfaces/event.interface'; import { - IAssetDeletionJob, + IEntityJob, IJobRepository, ISidecarWriteJob, JOBS_ASSET_PAGINATION_SIZE, @@ -371,8 +371,8 @@ export class AssetService { return JobStatus.SUCCESS; } - async handleAssetDeletion(job: IAssetDeletionJob): Promise { - const { id, fromExternal } = job; + async handleAssetDeletion(job: IEntityJob): Promise { + const { id } = job; const asset = await this.assetRepository.getById(id, { faces: { @@ -387,11 +387,6 @@ export class AssetService { 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 if (asset.stack?.primaryAssetId === id) { const stackAssetIds = asset.stack.assets.map((a) => a.id); @@ -414,18 +409,15 @@ export class AssetService { // TODO refactor this to use cascades if (asset.livePhotoVideoId) { - await this.jobRepository.queue({ - name: JobName.ASSET_DELETION, - data: { id: asset.livePhotoVideoId, fromExternal }, - }); + await this.jobRepository.queue({ name: JobName.ASSET_DELETION, data: { id: asset.livePhotoVideoId } }); } - const files = [asset.thumbnailPath, asset.previewPath, asset.encodedVideoPath]; - if (!(asset.isExternal || asset.isReadOnly)) { - files.push(asset.sidecarPath, asset.originalPath); - } - - await this.jobRepository.queue({ name: JobName.DELETE_FILES, data: { files } }); + await this.jobRepository.queue({ + name: JobName.DELETE_FILES, + data: { + files: [asset.thumbnailPath, asset.previewPath, asset.encodedVideoPath, asset.sidecarPath, asset.originalPath], + }, + }); return JobStatus.SUCCESS; } diff --git a/server/src/services/library.service.spec.ts b/server/src/services/library.service.spec.ts index 2122b03208..59f2c5a1d3 100644 --- a/server/src/services/library.service.spec.ts +++ b/server/src/services/library.service.spec.ts @@ -368,7 +368,6 @@ describe(LibraryService.name, () => { type: AssetType.IMAGE, originalFileName: 'photo.jpg', sidecarPath: null, - isReadOnly: true, isExternal: true, }, ], @@ -416,7 +415,6 @@ describe(LibraryService.name, () => { type: AssetType.IMAGE, originalFileName: 'photo.jpg', sidecarPath: '/data/user1/photo.jpg.xmp', - isReadOnly: true, isExternal: true, }, ], @@ -463,7 +461,6 @@ describe(LibraryService.name, () => { type: AssetType.VIDEO, originalFileName: 'video.mp4', sidecarPath: null, - isReadOnly: true, isExternal: true, }, ], @@ -1458,10 +1455,7 @@ describe(LibraryService.name, () => { await expect(sut.handleOfflineRemoval({ id: libraryStub.externalLibrary1.id })).resolves.toBe(JobStatus.SUCCESS); expect(jobMock.queueAll).toHaveBeenCalledWith([ - { - name: JobName.ASSET_DELETION, - data: { id: assetStub.image1.id, fromExternal: true }, - }, + { name: JobName.ASSET_DELETION, data: { id: assetStub.image1.id } }, ]); }); }); diff --git a/server/src/services/library.service.ts b/server/src/services/library.service.ts index 00909e9837..a0d9b70d65 100644 --- a/server/src/services/library.service.ts +++ b/server/src/services/library.service.ts @@ -387,7 +387,7 @@ export class LibraryService { const assetIds = await this.repository.getAssetIds(job.id, true); this.logger.debug(`Will delete ${assetIds.length} asset(s) in library ${job.id}`); 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) { @@ -503,7 +503,6 @@ export class LibraryService { type: assetType, originalFileName, sidecarPath, - isReadOnly: true, isExternal: true, }); assetId = addedAsset.id; @@ -580,7 +579,7 @@ export class LibraryService { for await (const assets of assetPagination) { this.logger.debug(`Removing ${assets.length} offline assets`); 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 } })), ); } diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index e28f1cd474..4b013fb663 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -440,7 +440,6 @@ export class MetadataService { originalPath: motionPath, originalFileName: asset.originalFileName, isVisible: false, - isReadOnly: false, deviceAssetId: 'NONE', deviceId: 'NONE', }); diff --git a/server/src/services/storage-template.service.spec.ts b/server/src/services/storage-template.service.spec.ts index 952b656546..0ee0204357 100644 --- a/server/src/services/storage-template.service.spec.ts +++ b/server/src/services/storage-template.service.spec.ts @@ -558,26 +558,5 @@ describe(StorageTemplateService.name, () => { ); 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(); - }); }); }); diff --git a/server/src/services/storage-template.service.ts b/server/src/services/storage-template.service.ts index 835f5ea7d7..1a3c61a4b8 100644 --- a/server/src/services/storage-template.service.ts +++ b/server/src/services/storage-template.service.ts @@ -170,7 +170,7 @@ export class StorageTemplateService { } 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 // TODO: shouldn't this only apply to external assets? return; diff --git a/server/src/utils/database.ts b/server/src/utils/database.ts index be0eb8fa66..65456e8192 100644 --- a/server/src/utils/database.ts +++ b/server/src/utils/database.ts @@ -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 { isArchived, isEncoded, diff --git a/server/test/fixtures/asset.stub.ts b/server/test/fixtures/asset.stub.ts index 9bd3edbaaf..2491406785 100644 --- a/server/test/fixtures/asset.stub.ts +++ b/server/test/fixtures/asset.stub.ts @@ -45,7 +45,6 @@ export const assetStub = { sharedLinks: [], faces: [], sidecarPath: null, - isReadOnly: false, deletedAt: null, isOffline: false, isExternal: false, @@ -82,7 +81,6 @@ export const assetStub = { originalFileName: 'IMG_456.jpg', faces: [], sidecarPath: null, - isReadOnly: false, isOffline: false, isExternal: false, libraryId: 'library-id', @@ -113,7 +111,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isOffline: false, libraryId: 'library-id', library: libraryStub.uploadLibrary1, @@ -150,7 +147,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, duration: null, isVisible: true, isExternal: false, @@ -195,7 +191,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, duration: null, isVisible: true, isExternal: false, @@ -235,7 +230,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: true, duration: null, isVisible: true, @@ -275,7 +269,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: false, duration: null, isVisible: true, @@ -315,7 +308,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: true, duration: null, isVisible: true, @@ -356,7 +348,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, duration: null, isVisible: true, livePhotoVideo: null, @@ -396,7 +387,6 @@ export const assetStub = { isFavorite: true, isArchived: false, isExternal: false, - isReadOnly: false, isOffline: false, libraryId: 'library-id', library: libraryStub.uploadLibrary1, @@ -436,7 +426,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: false, isOffline: false, libraryId: 'library-id', @@ -527,7 +516,6 @@ export const assetStub = { localDateTime: new Date('2023-02-22T05:06:29.716Z'), isFavorite: false, isArchived: false, - isReadOnly: false, isExternal: false, isOffline: false, libraryId: 'library-id', @@ -570,7 +558,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: false, isOffline: false, libraryId: 'library-id', @@ -606,7 +593,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: false, isOffline: false, libraryId: 'library-id', @@ -643,7 +629,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: true, isExternal: false, isOffline: false, libraryId: 'library-id', @@ -681,7 +666,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: false, isOffline: false, libraryId: 'library-id', @@ -719,7 +703,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: true, duration: null, isVisible: true, @@ -758,7 +741,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, isExternal: true, duration: null, isVisible: true, @@ -797,7 +779,6 @@ export const assetStub = { localDateTime: new Date('2023-02-23T05:06:29.716Z'), isFavorite: true, isArchived: false, - isReadOnly: false, duration: null, isVisible: true, isExternal: false, diff --git a/server/test/fixtures/shared-link.stub.ts b/server/test/fixtures/shared-link.stub.ts index aa785a2413..94f39a6978 100644 --- a/server/test/fixtures/shared-link.stub.ts +++ b/server/test/fixtures/shared-link.stub.ts @@ -59,7 +59,6 @@ const assetResponse: AssetResponseDto = { thumbhash: null, fileModifiedAt: today, isExternal: false, - isReadOnly: false, isOffline: false, fileCreatedAt: today, localDateTime: today, @@ -210,7 +209,6 @@ export const sharedLinkStub = { isFavorite: false, isArchived: false, isExternal: false, - isReadOnly: false, isOffline: false, libraryId: 'library-id', library: libraryStub.uploadLibrary1, diff --git a/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte b/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte index 6e6dcbd92f..3ad17b1eed 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte @@ -193,9 +193,7 @@ {/if} {#if isOwner} - {#if !asset.isReadOnly || !asset.isExternal} - dispatch('delete')} title="Delete" /> - {/if} + dispatch('delete')} title="Delete" />

(isShowAssetOptions = false), diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte index d3f977f762..893cd047ab 100644 --- a/web/src/lib/components/asset-viewer/detail-panel.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel.svelte @@ -308,23 +308,15 @@ {/if}
- {#if !asset.exifInfo && !asset.isExternal} -

NO EXIF INFO AVAILABLE

- {:else if !asset.exifInfo && asset.isExternal} -
-
-

- Metadata not loaded for {asset.originalPath} -

-
-
- {:else} + {#if asset.exifInfo}

DETAILS

+ {:else} +

NO EXIF INFO AVAILABLE

{/if} - {#if asset.exifInfo?.dateTimeOriginal && !asset.isReadOnly} + {#if asset.exifInfo?.dateTimeOriginal} {@const assetDateTimeOriginal = DateTime.fromISO(asset.exifInfo.dateTimeOriginal, { zone: asset.exifInfo.timeZone ?? undefined, })} @@ -374,7 +366,7 @@
{/if} - {:else if !asset.exifInfo?.dateTimeOriginal && !asset.isReadOnly && isOwner} + {:else if !asset.exifInfo?.dateTimeOriginal && isOwner}
@@ -385,43 +377,6 @@
- {:else if asset.exifInfo?.dateTimeOriginal && asset.isReadOnly} - {@const assetDateTimeOriginal = DateTime.fromISO(asset.exifInfo.dateTimeOriginal, { - zone: asset.exifInfo.timeZone ?? undefined, - })} -
-
-
- -
- -
-

- {assetDateTimeOriginal.toLocaleString( - { - month: 'short', - day: 'numeric', - year: 'numeric', - }, - { locale: $locale }, - )} -

-
-

- {assetDateTimeOriginal.toLocaleString( - { - weekday: 'short', - hour: 'numeric', - minute: '2-digit', - timeZoneName: 'longOffset', - }, - { locale: $locale }, - )} -

-
-
-
-
{/if} {#if isShowChangeDate} @@ -501,7 +456,7 @@
{/if} - {#if asset.exifInfo?.city && !asset.isReadOnly} + {#if asset.exifInfo?.city} - {:else if !asset.exifInfo?.city && !asset.isReadOnly && isOwner} + {:else if !asset.exifInfo?.city && isOwner}
- {:else if asset.exifInfo?.city && asset.isReadOnly} -
-
-
- -
-

{asset.exifInfo.city}

- {#if asset.exifInfo?.state} -
-

{asset.exifInfo.state}

-
- {/if} - {#if asset.exifInfo?.country} -
-

{asset.exifInfo.country}

-
- {/if} -
-
-
{/if} {#if isShowChangeLocation} { 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); clearSelect(); isShowConfirmation = false; diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte index 920e833a9e..7771cfbb4b 100644 --- a/web/src/lib/components/photos-page/asset-grid.svelte +++ b/web/src/lib/components/photos-page/asset-grid.svelte @@ -47,7 +47,7 @@ $: timelineY = element?.scrollTop || 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); diff --git a/web/src/lib/utils/asset-utils.ts b/web/src/lib/utils/asset-utils.ts index 50337fb06b..efa292d74c 100644 --- a/web/src/lib/utils/asset-utils.ts +++ b/web/src/lib/utils/asset-utils.ts @@ -258,9 +258,9 @@ export const getAssetType = (type: AssetTypeEnum) => { }; export const getSelectedAssets = (assets: Set, 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) { notificationController.show({ message: `Can't change metadata of ${numberOfIssues} asset${numberOfIssues > 1 ? 's' : ''}`, diff --git a/web/src/test-data/factories/asset-factory.ts b/web/src/test-data/factories/asset-factory.ts index 32cb723c02..6b1e1a6ce3 100644 --- a/web/src/test-data/factories/asset-factory.ts +++ b/web/src/test-data/factories/asset-factory.ts @@ -22,9 +22,7 @@ export const assetFactory = Sync.makeFactory({ isTrashed: Sync.each(() => faker.datatype.boolean()), duration: '0:00:00.00000', checksum: Sync.each(() => faker.string.alphanumeric(28)), - isExternal: Sync.each(() => faker.datatype.boolean()), isOffline: Sync.each(() => faker.datatype.boolean()), - isReadOnly: Sync.each(() => faker.datatype.boolean()), hasMetadata: Sync.each(() => faker.datatype.boolean()), stackCount: null, });