feat(server): read-write external assets (#9235)

* refactor: remove isReadOnly and isExternal usages

* chore: open api

* fix: linting

* remove mobile isReadOnly dependency

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Jason Rasmussen
2024-05-03 15:34:57 -04:00
committed by GitHub
parent d26ac431b8
commit 5b87abb021
57 changed files with 181 additions and 603 deletions
-11
View File
@@ -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,
}""";
}
+40 -95
View File
@@ -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<P>(
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<Asset, Asset, QFilterCondition> {
});
}
QueryBuilder<Asset, Asset, QAfterFilterCondition> isReadOnlyEqualTo(
bool value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'isReadOnly',
value: value,
));
});
}
QueryBuilder<Asset, Asset, QAfterFilterCondition> isTrashedEqualTo(
bool value) {
return QueryBuilder.apply(this, (query) {
@@ -2527,18 +2508,6 @@ extension AssetQuerySortBy on QueryBuilder<Asset, Asset, QSortBy> {
});
}
QueryBuilder<Asset, Asset, QAfterSortBy> sortByIsReadOnly() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isReadOnly', Sort.asc);
});
}
QueryBuilder<Asset, Asset, QAfterSortBy> sortByIsReadOnlyDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isReadOnly', Sort.desc);
});
}
QueryBuilder<Asset, Asset, QAfterSortBy> sortByIsTrashed() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isTrashed', Sort.asc);
@@ -2793,18 +2762,6 @@ extension AssetQuerySortThenBy on QueryBuilder<Asset, Asset, QSortThenBy> {
});
}
QueryBuilder<Asset, Asset, QAfterSortBy> thenByIsReadOnly() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isReadOnly', Sort.asc);
});
}
QueryBuilder<Asset, Asset, QAfterSortBy> thenByIsReadOnlyDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isReadOnly', Sort.desc);
});
}
QueryBuilder<Asset, Asset, QAfterSortBy> thenByIsTrashed() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isTrashed', Sort.asc);
@@ -2995,12 +2952,6 @@ extension AssetQueryWhereDistinct on QueryBuilder<Asset, Asset, QDistinct> {
});
}
QueryBuilder<Asset, Asset, QDistinct> distinctByIsReadOnly() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'isReadOnly');
});
}
QueryBuilder<Asset, Asset, QDistinct> distinctByIsTrashed() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'isTrashed');
@@ -3136,12 +3087,6 @@ extension AssetQueryProperty on QueryBuilder<Asset, Asset, QQueryProperty> {
});
}
QueryBuilder<Asset, bool, QQueryOperations> isReadOnlyProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'isReadOnly');
});
}
QueryBuilder<Asset, bool, QQueryOperations> isTrashedProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'isTrashed');
@@ -71,19 +71,6 @@ extension AssetListExtension on Iterable<Asset> {
return this;
}
/// Returns the assets that are present on a file system which has write permission
/// This filters out assets on readOnly external library to which we cannot perform any write operation
Iterable<Asset> writableOnly({
void Function()? errorCallback,
}) {
final bool onlyWritable = every((e) => !e.isReadOnly);
if (!onlyWritable) {
if (errorCallback != null) errorCallback();
return where((a) => !a.isReadOnly);
}
return this;
}
/// Filters out offline assets and returns those that are still accessible by the Immich server
Iterable<Asset> nonOfflineOnly({
void Function()? errorCallback,
@@ -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<bool> onDelete(bool force) async {
final isDeleted = await ref.read(assetProvider.notifier).deleteAssets(
{asset},
@@ -42,7 +42,7 @@ class ExifBottomSheet extends HookConsumerWidget {
fontSize: 14,
),
),
if (asset.isRemote && !asset.isReadOnly)
if (asset.isRemote)
IconButton(
onPressed: () => handleEditDateTime(
ref,
@@ -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),
+20 -20
View File
@@ -63,6 +63,12 @@ abstract class _$AppRouter extends RootStackRouter {
child: const AllPeoplePage(),
);
},
AllPlacesRoute.name: (routeData) {
return AutoRoutePage<dynamic>(
routeData: routeData,
child: const AllPlacesPage(),
);
},
AllVideosRoute.name: (routeData) {
return AutoRoutePage<dynamic>(
routeData: routeData,
@@ -138,12 +144,6 @@ abstract class _$AppRouter extends RootStackRouter {
),
);
},
AllPlacesRoute.name: (routeData) {
return AutoRoutePage<dynamic>(
routeData: routeData,
child: const AllPlacesPage(),
);
},
FailedBackupStatusRoute.name: (routeData) {
return AutoRoutePage<dynamic>(
routeData: routeData,
@@ -525,6 +525,20 @@ class AllPeopleRoute extends PageRouteInfo<void> {
static const PageInfo<void> page = PageInfo<void>(name);
}
/// generated route for
/// [AllPlacesPage]
class AllPlacesRoute extends PageRouteInfo<void> {
const AllPlacesRoute({List<PageRouteInfo>? children})
: super(
AllPlacesRoute.name,
initialChildren: children,
);
static const String name = 'AllPlacesRoute';
static const PageInfo<void> page = PageInfo<void>(name);
}
/// generated route for
/// [AllVideosPage]
class AllVideosRoute extends PageRouteInfo<void> {
@@ -752,20 +766,6 @@ class CreateAlbumRouteArgs {
}
}
/// generated route for
/// [AllPlacesPage]
class AllPlacesRoute extends PageRouteInfo<void> {
const AllPlacesRoute({List<PageRouteInfo>? children})
: super(
AllPlacesRoute.name,
initialChildren: children,
);
static const String name = 'CuratedLocationRoute';
static const PageInfo<void> page = PageInfo<void>(name);
}
/// generated route for
/// [FailedBackupStatusPage]
class FailedBackupStatusRoute extends PageRouteInfo<void> {
@@ -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());
}
+2 -4
View File
@@ -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]
+2 -2
View File
@@ -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]
-2
View File
@@ -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]
-2
View File
@@ -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]
+3 -11
View File
@@ -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<Response> uploadFileWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isReadOnly, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async {
Future<Response> uploadFileWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async {
// ignore: prefer_const_declarations
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<AssetFileUploadResponseDto?> uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isReadOnly, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async {
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<AssetFileUploadResponseDto?> uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isOffline, bool? isVisible, String? libraryId, MultipartFile? livePhotoData, MultipartFile? sidecarData, }) async {
final response = await uploadFileWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, xImmichChecksum: xImmichChecksum, duration: duration, isArchived: isArchived, isFavorite: isFavorite, isOffline: isOffline, isVisible: isVisible, libraryId: libraryId, livePhotoData: livePhotoData, sidecarData: sidecarData, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
+30 -10
View File
@@ -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<bool>(json, r'hasMetadata')!,
id: mapValueOfType<String>(json, r'id')!,
isArchived: mapValueOfType<bool>(json, r'isArchived')!,
isExternal: mapValueOfType<bool>(json, r'isExternal')!,
isExternal: mapValueOfType<bool>(json, r'isExternal'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite')!,
isOffline: mapValueOfType<bool>(json, r'isOffline')!,
isReadOnly: mapValueOfType<bool>(json, r'isReadOnly')!,
isReadOnly: mapValueOfType<bool>(json, r'isReadOnly'),
isTrashed: mapValueOfType<bool>(json, r'isTrashed')!,
libraryId: mapValueOfType<String>(json, r'libraryId')!,
livePhotoVideoId: mapValueOfType<String>(json, r'livePhotoVideoId'),
@@ -365,10 +387,8 @@ class AssetResponseDto {
'hasMetadata',
'id',
'isArchived',
'isExternal',
'isFavorite',
'isOffline',
'isReadOnly',
'isTrashed',
'libraryId',
'localDateTime',
+1 -35
View File
@@ -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<String, dynamic> toJson() {
final json = <String, dynamic>{};
@@ -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<String>(json, r'id'),
isArchived: mapValueOfType<bool>(json, r'isArchived'),
isEncoded: mapValueOfType<bool>(json, r'isEncoded'),
isExternal: mapValueOfType<bool>(json, r'isExternal'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isMotion: mapValueOfType<bool>(json, r'isMotion'),
isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'),
isOffline: mapValueOfType<bool>(json, r'isOffline'),
isReadOnly: mapValueOfType<bool>(json, r'isReadOnly'),
isVisible: mapValueOfType<bool>(json, r'isVisible'),
lensModel: mapValueOfType<String>(json, r'lensModel'),
libraryId: mapValueOfType<String>(json, r'libraryId'),
+1 -35
View File
@@ -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<String, dynamic> toJson() {
final json = <String, dynamic>{};
@@ -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<String>(json, r'deviceId'),
isArchived: mapValueOfType<bool>(json, r'isArchived'),
isEncoded: mapValueOfType<bool>(json, r'isEncoded'),
isExternal: mapValueOfType<bool>(json, r'isExternal'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isMotion: mapValueOfType<bool>(json, r'isMotion'),
isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'),
isOffline: mapValueOfType<bool>(json, r'isOffline'),
isReadOnly: mapValueOfType<bool>(json, r'isReadOnly'),
isVisible: mapValueOfType<bool>(json, r'isVisible'),
lensModel: mapValueOfType<String>(json, r'lensModel'),
libraryId: mapValueOfType<String>(json, r'libraryId'),
+1 -1
View File
@@ -105,7 +105,7 @@ void main() {
// TODO
});
//Future<AssetFileUploadResponseDto> uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String key, String xImmichChecksum, String duration, bool isArchived, bool isFavorite, bool isOffline, bool isReadOnly, bool isVisible, String libraryId, MultipartFile livePhotoData, MultipartFile sidecarData }) async
//Future<AssetFileUploadResponseDto> uploadFile(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String key, String xImmichChecksum, String duration, bool isArchived, bool isFavorite, bool isOffline, bool isVisible, String libraryId, MultipartFile livePhotoData, MultipartFile sidecarData }) async
test('test uploadFile', () async {
// TODO
});
+2
View File
@@ -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
-10
View File
@@ -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
-10
View File
@@ -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