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}
- {: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,
});