mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat: recently added assets page (#28272)
* feat(server): add ordering date option to time buckets * feat(web): add recently added page * feat(server): recently created assets in explore data * feat(web): recently added in explore tab * fix: recently added assets ordering * fix(server): failing bucket test * feat(web): improve recently added preview * chore: update e2e explore/timeline tests * chore: rename and refactor timeline ordering dates * fix(web): invalid timeline option * feat(mobile): recently added page * fix(server): sync tests * fix(mobile): resync assets to get uploadedAt column * chore: rename assetorderby enum * chore(mobile): formatting * minor fixes * stylings --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
+3368
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ class RemoteAsset extends BaseAsset {
|
||||
final AssetVisibility visibility;
|
||||
final String ownerId;
|
||||
final String? stackId;
|
||||
final DateTime? uploadedAt;
|
||||
|
||||
const RemoteAsset({
|
||||
required this.id,
|
||||
@@ -20,6 +21,7 @@ class RemoteAsset extends BaseAsset {
|
||||
required super.type,
|
||||
required super.createdAt,
|
||||
required super.updatedAt,
|
||||
this.uploadedAt,
|
||||
super.width,
|
||||
super.height,
|
||||
super.durationMs,
|
||||
@@ -55,6 +57,7 @@ class RemoteAsset extends BaseAsset {
|
||||
type: $type,
|
||||
createdAt: $createdAt,
|
||||
updatedAt: $updatedAt,
|
||||
uploadedAt: ${uploadedAt ?? "<NA>"},
|
||||
width: ${width ?? "<NA>"},
|
||||
height: ${height ?? "<NA>"},
|
||||
durationMs: ${durationMs ?? "<NA>"},
|
||||
@@ -82,7 +85,8 @@ class RemoteAsset extends BaseAsset {
|
||||
ownerId == other.ownerId &&
|
||||
thumbHash == other.thumbHash &&
|
||||
visibility == other.visibility &&
|
||||
stackId == other.stackId;
|
||||
stackId == other.stackId &&
|
||||
uploadedAt == other.uploadedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -93,7 +97,8 @@ class RemoteAsset extends BaseAsset {
|
||||
localId.hashCode ^
|
||||
thumbHash.hashCode ^
|
||||
visibility.hashCode ^
|
||||
stackId.hashCode;
|
||||
stackId.hashCode ^
|
||||
uploadedAt.hashCode;
|
||||
|
||||
RemoteAsset copyWith({
|
||||
String? id,
|
||||
@@ -104,6 +109,7 @@ class RemoteAsset extends BaseAsset {
|
||||
AssetType? type,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? uploadedAt,
|
||||
int? width,
|
||||
int? height,
|
||||
int? durationMs,
|
||||
@@ -123,6 +129,7 @@ class RemoteAsset extends BaseAsset {
|
||||
type: type ?? this.type,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
uploadedAt: uploadedAt ?? this.uploadedAt,
|
||||
width: width ?? this.width,
|
||||
height: height ?? this.height,
|
||||
durationMs: durationMs ?? this.durationMs,
|
||||
@@ -148,6 +155,7 @@ class RemoteAssetExif extends RemoteAsset {
|
||||
required super.type,
|
||||
required super.createdAt,
|
||||
required super.updatedAt,
|
||||
super.uploadedAt,
|
||||
super.width,
|
||||
super.height,
|
||||
super.durationMs,
|
||||
@@ -184,6 +192,7 @@ class RemoteAssetExif extends RemoteAsset {
|
||||
AssetType? type,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? uploadedAt,
|
||||
int? width,
|
||||
int? height,
|
||||
int? durationMs,
|
||||
@@ -204,6 +213,7 @@ class RemoteAssetExif extends RemoteAsset {
|
||||
type: type ?? this.type,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
uploadedAt: uploadedAt ?? this.uploadedAt,
|
||||
width: width ?? this.width,
|
||||
height: height ?? this.height,
|
||||
durationMs: durationMs ?? this.durationMs,
|
||||
|
||||
@@ -2,6 +2,8 @@ enum GroupAssetsBy { day, month, auto, none }
|
||||
|
||||
enum HeaderType { none, month, day, monthAndDay }
|
||||
|
||||
enum SortAssetsBy { taken, uploaded }
|
||||
|
||||
class Bucket {
|
||||
final int assetCount;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ enum SyncMigrationTask {
|
||||
v20260128_ResetExifV1, // EXIF table has incorrect width and height information.
|
||||
v20260128_CopyExifWidthHeightToAsset, // Asset table has incorrect width and height for video ratio calculations.
|
||||
v20260128_ResetAssetV1, // Asset v2.5.0 has width and height information that were edited assets.
|
||||
v20260597_ResetAssetV1AssetV2, // Assets didn't include the uploadedAt column.
|
||||
}
|
||||
|
||||
class SyncStreamService {
|
||||
@@ -132,6 +133,13 @@ class SyncStreamService {
|
||||
migrations.add(SyncMigrationTask.v20260128_CopyExifWidthHeightToAsset.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!migrations.contains(SyncMigrationTask.v20260597_ResetAssetV1AssetV2.name) &&
|
||||
semVer > const SemVer(major: 2, minor: 7, patch: 5)) {
|
||||
_logger.info("Running pre-sync task: v20260597_ResetAssetV1AssetV2");
|
||||
await _syncApiRepository.deleteSyncAck([SyncEntityType.assetV1, SyncEntityType.assetV2]);
|
||||
migrations.add(SyncMigrationTask.v20260597_ResetAssetV1AssetV2.name);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _runPostSyncTasks(List<String> migrations) async {
|
||||
|
||||
@@ -35,6 +35,7 @@ enum TimelineOrigin {
|
||||
deepLink,
|
||||
albumActivities,
|
||||
folder,
|
||||
recentlyAdded,
|
||||
}
|
||||
|
||||
class TimelineFactory {
|
||||
@@ -61,6 +62,8 @@ class TimelineFactory {
|
||||
|
||||
TimelineService remoteAssets(String userId) => TimelineService(_timelineRepository.remote(userId, groupBy));
|
||||
|
||||
TimelineService recentlyAdded(String userId) => TimelineService(_timelineRepository.recentlyAdded(userId, groupBy));
|
||||
|
||||
TimelineService favorite(String userId) => TimelineService(_timelineRepository.favorite(userId, groupBy));
|
||||
|
||||
TimelineService trash(String userId) => TimelineService(_timelineRepository.trash(userId, groupBy));
|
||||
|
||||
@@ -11,6 +11,7 @@ extension DTOToAsset on api.AssetResponseDto {
|
||||
checksum: checksum,
|
||||
createdAt: fileCreatedAt,
|
||||
updatedAt: updatedAt,
|
||||
uploadedAt: createdAt,
|
||||
ownerId: ownerId,
|
||||
visibility: visibility.toAssetVisibility(),
|
||||
durationMs: duration,
|
||||
@@ -33,6 +34,7 @@ extension DTOToAsset on api.AssetResponseDto {
|
||||
checksum: checksum,
|
||||
createdAt: fileCreatedAt,
|
||||
updatedAt: updatedAt,
|
||||
uploadedAt: createdAt,
|
||||
ownerId: ownerId,
|
||||
visibility: visibility.toAssetVisibility(),
|
||||
durationMs: duration,
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'local_asset.entity.dart';
|
||||
import 'local_album.entity.dart';
|
||||
import 'local_album_asset.entity.dart';
|
||||
|
||||
mergedAsset:
|
||||
mergedAsset:
|
||||
SELECT
|
||||
rae.id as remote_id,
|
||||
(SELECT lae.id FROM local_asset_entity lae WHERE lae.checksum = rae.checksum LIMIT 1) as local_id,
|
||||
@@ -27,7 +27,8 @@ SELECT
|
||||
NULL as longitude,
|
||||
NULL as adjustmentTime,
|
||||
rae.is_edited,
|
||||
0 as playback_style
|
||||
0 as playback_style,
|
||||
rae.uploaded_at
|
||||
FROM
|
||||
remote_asset_entity rae
|
||||
LEFT JOIN
|
||||
@@ -65,7 +66,8 @@ SELECT
|
||||
lae.longitude,
|
||||
lae.adjustment_time,
|
||||
0 as is_edited,
|
||||
lae.playback_style
|
||||
lae.playback_style,
|
||||
NULL as uploaded_at
|
||||
FROM
|
||||
local_asset_entity lae
|
||||
WHERE NOT EXISTS (
|
||||
|
||||
+4
-1
@@ -29,7 +29,7 @@ class MergedAssetDrift extends i1.ModularAccessor {
|
||||
);
|
||||
$arrayStartIndex += generatedlimit.amountOfVariables;
|
||||
return customSelect(
|
||||
'SELECT rae.id AS remote_id, (SELECT lae.id FROM local_asset_entity AS lae WHERE lae.checksum = rae.checksum LIMIT 1) AS local_id, rae.name, rae.type, rae.created_at AS created_at, rae.updated_at, rae.width, rae.height, rae.duration_ms, rae.is_favorite, rae.thumb_hash, rae.checksum, rae.owner_id, rae.live_photo_video_id, 0 AS orientation, rae.stack_id, NULL AS i_cloud_id, NULL AS latitude, NULL AS longitude, NULL AS adjustmentTime, rae.is_edited, 0 AS playback_style FROM remote_asset_entity AS rae LEFT JOIN stack_entity AS se ON rae.stack_id = se.id WHERE rae.deleted_at IS NULL AND rae.visibility = 0 AND rae.owner_id IN ($expandeduserIds) AND(rae.stack_id IS NULL OR rae.id = se.primary_asset_id)UNION ALL SELECT NULL AS remote_id, lae.id AS local_id, lae.name, lae.type, lae.created_at AS created_at, lae.updated_at, lae.width, lae.height, lae.duration_ms, lae.is_favorite, NULL AS thumb_hash, lae.checksum, NULL AS owner_id, NULL AS live_photo_video_id, lae.orientation, NULL AS stack_id, lae.i_cloud_id, lae.latitude, lae.longitude, lae.adjustment_time, 0 AS is_edited, lae.playback_style FROM local_asset_entity AS lae WHERE NOT EXISTS (SELECT 1 FROM remote_asset_entity AS rae WHERE rae.checksum = lae.checksum AND rae.owner_id IN ($expandeduserIds)) AND EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 0) AND NOT EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 2) ORDER BY created_at DESC ${generatedlimit.sql}',
|
||||
'SELECT rae.id AS remote_id, (SELECT lae.id FROM local_asset_entity AS lae WHERE lae.checksum = rae.checksum LIMIT 1) AS local_id, rae.name, rae.type, rae.created_at AS created_at, rae.updated_at, rae.width, rae.height, rae.duration_ms, rae.is_favorite, rae.thumb_hash, rae.checksum, rae.owner_id, rae.live_photo_video_id, 0 AS orientation, rae.stack_id, NULL AS i_cloud_id, NULL AS latitude, NULL AS longitude, NULL AS adjustmentTime, rae.is_edited, 0 AS playback_style, rae.uploaded_at FROM remote_asset_entity AS rae LEFT JOIN stack_entity AS se ON rae.stack_id = se.id WHERE rae.deleted_at IS NULL AND rae.visibility = 0 AND rae.owner_id IN ($expandeduserIds) AND(rae.stack_id IS NULL OR rae.id = se.primary_asset_id)UNION ALL SELECT NULL AS remote_id, lae.id AS local_id, lae.name, lae.type, lae.created_at AS created_at, lae.updated_at, lae.width, lae.height, lae.duration_ms, lae.is_favorite, NULL AS thumb_hash, lae.checksum, NULL AS owner_id, NULL AS live_photo_video_id, lae.orientation, NULL AS stack_id, lae.i_cloud_id, lae.latitude, lae.longitude, lae.adjustment_time, 0 AS is_edited, lae.playback_style, NULL AS uploaded_at FROM local_asset_entity AS lae WHERE NOT EXISTS (SELECT 1 FROM remote_asset_entity AS rae WHERE rae.checksum = lae.checksum AND rae.owner_id IN ($expandeduserIds)) AND EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 0) AND NOT EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 2) ORDER BY created_at DESC ${generatedlimit.sql}',
|
||||
variables: [
|
||||
for (var $ in userIds) i0.Variable<String>($),
|
||||
...generatedlimit.introducedVariables,
|
||||
@@ -68,6 +68,7 @@ class MergedAssetDrift extends i1.ModularAccessor {
|
||||
adjustmentTime: row.readNullable<DateTime>('adjustmentTime'),
|
||||
isEdited: row.read<bool>('is_edited'),
|
||||
playbackStyle: row.read<int>('playback_style'),
|
||||
uploadedAt: row.readNullable<DateTime>('uploaded_at'),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -141,6 +142,7 @@ class MergedAssetResult {
|
||||
final DateTime? adjustmentTime;
|
||||
final bool isEdited;
|
||||
final int playbackStyle;
|
||||
final DateTime? uploadedAt;
|
||||
MergedAssetResult({
|
||||
this.remoteId,
|
||||
this.localId,
|
||||
@@ -164,6 +166,7 @@ class MergedAssetResult {
|
||||
this.adjustmentTime,
|
||||
required this.isEdited,
|
||||
required this.playbackStyle,
|
||||
this.uploadedAt,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ class RemoteAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin
|
||||
|
||||
DateTimeColumn get deletedAt => dateTime().nullable()();
|
||||
|
||||
DateTimeColumn get uploadedAt => dateTime().nullable()();
|
||||
|
||||
TextColumn get livePhotoVideoId => text().nullable()();
|
||||
|
||||
IntColumn get visibility => intEnum<AssetVisibility>()();
|
||||
@@ -66,6 +68,7 @@ extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData {
|
||||
type: type,
|
||||
createdAt: createdAt,
|
||||
updatedAt: updatedAt,
|
||||
uploadedAt: uploadedAt,
|
||||
durationMs: durationMs,
|
||||
isFavorite: isFavorite,
|
||||
height: height,
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef $$RemoteAssetEntityTableCreateCompanionBuilder =
|
||||
i0.Value<DateTime?> localDateTime,
|
||||
i0.Value<String?> thumbHash,
|
||||
i0.Value<DateTime?> deletedAt,
|
||||
i0.Value<DateTime?> uploadedAt,
|
||||
i0.Value<String?> livePhotoVideoId,
|
||||
required i2.AssetVisibility visibility,
|
||||
i0.Value<String?> stackId,
|
||||
@@ -49,6 +50,7 @@ typedef $$RemoteAssetEntityTableUpdateCompanionBuilder =
|
||||
i0.Value<DateTime?> localDateTime,
|
||||
i0.Value<String?> thumbHash,
|
||||
i0.Value<DateTime?> deletedAt,
|
||||
i0.Value<DateTime?> uploadedAt,
|
||||
i0.Value<String?> livePhotoVideoId,
|
||||
i0.Value<i2.AssetVisibility> visibility,
|
||||
i0.Value<String?> stackId,
|
||||
@@ -177,6 +179,11 @@ class $$RemoteAssetEntityTableFilterComposer
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<DateTime> get uploadedAt => $composableBuilder(
|
||||
column: $table.uploadedAt,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<String> get livePhotoVideoId => $composableBuilder(
|
||||
column: $table.livePhotoVideoId,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
@@ -305,6 +312,11 @@ class $$RemoteAssetEntityTableOrderingComposer
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<DateTime> get uploadedAt => $composableBuilder(
|
||||
column: $table.uploadedAt,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<String> get livePhotoVideoId => $composableBuilder(
|
||||
column: $table.livePhotoVideoId,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
@@ -412,6 +424,11 @@ class $$RemoteAssetEntityTableAnnotationComposer
|
||||
i0.GeneratedColumn<DateTime> get deletedAt =>
|
||||
$composableBuilder(column: $table.deletedAt, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<DateTime> get uploadedAt => $composableBuilder(
|
||||
column: $table.uploadedAt,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
i0.GeneratedColumn<String> get livePhotoVideoId => $composableBuilder(
|
||||
column: $table.livePhotoVideoId,
|
||||
builder: (column) => column,
|
||||
@@ -507,6 +524,7 @@ class $$RemoteAssetEntityTableTableManager
|
||||
i0.Value<DateTime?> localDateTime = const i0.Value.absent(),
|
||||
i0.Value<String?> thumbHash = const i0.Value.absent(),
|
||||
i0.Value<DateTime?> deletedAt = const i0.Value.absent(),
|
||||
i0.Value<DateTime?> uploadedAt = const i0.Value.absent(),
|
||||
i0.Value<String?> livePhotoVideoId = const i0.Value.absent(),
|
||||
i0.Value<i2.AssetVisibility> visibility =
|
||||
const i0.Value.absent(),
|
||||
@@ -528,6 +546,7 @@ class $$RemoteAssetEntityTableTableManager
|
||||
localDateTime: localDateTime,
|
||||
thumbHash: thumbHash,
|
||||
deletedAt: deletedAt,
|
||||
uploadedAt: uploadedAt,
|
||||
livePhotoVideoId: livePhotoVideoId,
|
||||
visibility: visibility,
|
||||
stackId: stackId,
|
||||
@@ -550,6 +569,7 @@ class $$RemoteAssetEntityTableTableManager
|
||||
i0.Value<DateTime?> localDateTime = const i0.Value.absent(),
|
||||
i0.Value<String?> thumbHash = const i0.Value.absent(),
|
||||
i0.Value<DateTime?> deletedAt = const i0.Value.absent(),
|
||||
i0.Value<DateTime?> uploadedAt = const i0.Value.absent(),
|
||||
i0.Value<String?> livePhotoVideoId = const i0.Value.absent(),
|
||||
required i2.AssetVisibility visibility,
|
||||
i0.Value<String?> stackId = const i0.Value.absent(),
|
||||
@@ -570,6 +590,7 @@ class $$RemoteAssetEntityTableTableManager
|
||||
localDateTime: localDateTime,
|
||||
thumbHash: thumbHash,
|
||||
deletedAt: deletedAt,
|
||||
uploadedAt: uploadedAt,
|
||||
livePhotoVideoId: livePhotoVideoId,
|
||||
visibility: visibility,
|
||||
stackId: stackId,
|
||||
@@ -818,6 +839,18 @@ class $RemoteAssetEntityTable extends i3.RemoteAssetEntity
|
||||
type: i0.DriftSqlType.dateTime,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const i0.VerificationMeta _uploadedAtMeta = const i0.VerificationMeta(
|
||||
'uploadedAt',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<DateTime> uploadedAt =
|
||||
i0.GeneratedColumn<DateTime>(
|
||||
'uploaded_at',
|
||||
aliasedName,
|
||||
true,
|
||||
type: i0.DriftSqlType.dateTime,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const i0.VerificationMeta _livePhotoVideoIdMeta =
|
||||
const i0.VerificationMeta('livePhotoVideoId');
|
||||
@override
|
||||
@@ -894,6 +927,7 @@ class $RemoteAssetEntityTable extends i3.RemoteAssetEntity
|
||||
localDateTime,
|
||||
thumbHash,
|
||||
deletedAt,
|
||||
uploadedAt,
|
||||
livePhotoVideoId,
|
||||
visibility,
|
||||
stackId,
|
||||
@@ -998,6 +1032,12 @@ class $RemoteAssetEntityTable extends i3.RemoteAssetEntity
|
||||
deletedAt.isAcceptableOrUnknown(data['deleted_at']!, _deletedAtMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('uploaded_at')) {
|
||||
context.handle(
|
||||
_uploadedAtMeta,
|
||||
uploadedAt.isAcceptableOrUnknown(data['uploaded_at']!, _uploadedAtMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('live_photo_video_id')) {
|
||||
context.handle(
|
||||
_livePhotoVideoIdMeta,
|
||||
@@ -1095,6 +1135,10 @@ class $RemoteAssetEntityTable extends i3.RemoteAssetEntity
|
||||
i0.DriftSqlType.dateTime,
|
||||
data['${effectivePrefix}deleted_at'],
|
||||
),
|
||||
uploadedAt: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.dateTime,
|
||||
data['${effectivePrefix}uploaded_at'],
|
||||
),
|
||||
livePhotoVideoId: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}live_photo_video_id'],
|
||||
@@ -1153,6 +1197,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
final DateTime? localDateTime;
|
||||
final String? thumbHash;
|
||||
final DateTime? deletedAt;
|
||||
final DateTime? uploadedAt;
|
||||
final String? livePhotoVideoId;
|
||||
final i2.AssetVisibility visibility;
|
||||
final String? stackId;
|
||||
@@ -1173,6 +1218,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
this.localDateTime,
|
||||
this.thumbHash,
|
||||
this.deletedAt,
|
||||
this.uploadedAt,
|
||||
this.livePhotoVideoId,
|
||||
required this.visibility,
|
||||
this.stackId,
|
||||
@@ -1212,6 +1258,9 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
if (!nullToAbsent || deletedAt != null) {
|
||||
map['deleted_at'] = i0.Variable<DateTime>(deletedAt);
|
||||
}
|
||||
if (!nullToAbsent || uploadedAt != null) {
|
||||
map['uploaded_at'] = i0.Variable<DateTime>(uploadedAt);
|
||||
}
|
||||
if (!nullToAbsent || livePhotoVideoId != null) {
|
||||
map['live_photo_video_id'] = i0.Variable<String>(livePhotoVideoId);
|
||||
}
|
||||
@@ -1252,6 +1301,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
localDateTime: serializer.fromJson<DateTime?>(json['localDateTime']),
|
||||
thumbHash: serializer.fromJson<String?>(json['thumbHash']),
|
||||
deletedAt: serializer.fromJson<DateTime?>(json['deletedAt']),
|
||||
uploadedAt: serializer.fromJson<DateTime?>(json['uploadedAt']),
|
||||
livePhotoVideoId: serializer.fromJson<String?>(json['livePhotoVideoId']),
|
||||
visibility: i1.$RemoteAssetEntityTable.$convertervisibility.fromJson(
|
||||
serializer.fromJson<int>(json['visibility']),
|
||||
@@ -1281,6 +1331,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
'localDateTime': serializer.toJson<DateTime?>(localDateTime),
|
||||
'thumbHash': serializer.toJson<String?>(thumbHash),
|
||||
'deletedAt': serializer.toJson<DateTime?>(deletedAt),
|
||||
'uploadedAt': serializer.toJson<DateTime?>(uploadedAt),
|
||||
'livePhotoVideoId': serializer.toJson<String?>(livePhotoVideoId),
|
||||
'visibility': serializer.toJson<int>(
|
||||
i1.$RemoteAssetEntityTable.$convertervisibility.toJson(visibility),
|
||||
@@ -1306,6 +1357,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
i0.Value<DateTime?> localDateTime = const i0.Value.absent(),
|
||||
i0.Value<String?> thumbHash = const i0.Value.absent(),
|
||||
i0.Value<DateTime?> deletedAt = const i0.Value.absent(),
|
||||
i0.Value<DateTime?> uploadedAt = const i0.Value.absent(),
|
||||
i0.Value<String?> livePhotoVideoId = const i0.Value.absent(),
|
||||
i2.AssetVisibility? visibility,
|
||||
i0.Value<String?> stackId = const i0.Value.absent(),
|
||||
@@ -1328,6 +1380,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
: this.localDateTime,
|
||||
thumbHash: thumbHash.present ? thumbHash.value : this.thumbHash,
|
||||
deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt,
|
||||
uploadedAt: uploadedAt.present ? uploadedAt.value : this.uploadedAt,
|
||||
livePhotoVideoId: livePhotoVideoId.present
|
||||
? livePhotoVideoId.value
|
||||
: this.livePhotoVideoId,
|
||||
@@ -1358,6 +1411,9 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
: this.localDateTime,
|
||||
thumbHash: data.thumbHash.present ? data.thumbHash.value : this.thumbHash,
|
||||
deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt,
|
||||
uploadedAt: data.uploadedAt.present
|
||||
? data.uploadedAt.value
|
||||
: this.uploadedAt,
|
||||
livePhotoVideoId: data.livePhotoVideoId.present
|
||||
? data.livePhotoVideoId.value
|
||||
: this.livePhotoVideoId,
|
||||
@@ -1387,6 +1443,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
..write('localDateTime: $localDateTime, ')
|
||||
..write('thumbHash: $thumbHash, ')
|
||||
..write('deletedAt: $deletedAt, ')
|
||||
..write('uploadedAt: $uploadedAt, ')
|
||||
..write('livePhotoVideoId: $livePhotoVideoId, ')
|
||||
..write('visibility: $visibility, ')
|
||||
..write('stackId: $stackId, ')
|
||||
@@ -1412,6 +1469,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
localDateTime,
|
||||
thumbHash,
|
||||
deletedAt,
|
||||
uploadedAt,
|
||||
livePhotoVideoId,
|
||||
visibility,
|
||||
stackId,
|
||||
@@ -1436,6 +1494,7 @@ class RemoteAssetEntityData extends i0.DataClass
|
||||
other.localDateTime == this.localDateTime &&
|
||||
other.thumbHash == this.thumbHash &&
|
||||
other.deletedAt == this.deletedAt &&
|
||||
other.uploadedAt == this.uploadedAt &&
|
||||
other.livePhotoVideoId == this.livePhotoVideoId &&
|
||||
other.visibility == this.visibility &&
|
||||
other.stackId == this.stackId &&
|
||||
@@ -1459,6 +1518,7 @@ class RemoteAssetEntityCompanion
|
||||
final i0.Value<DateTime?> localDateTime;
|
||||
final i0.Value<String?> thumbHash;
|
||||
final i0.Value<DateTime?> deletedAt;
|
||||
final i0.Value<DateTime?> uploadedAt;
|
||||
final i0.Value<String?> livePhotoVideoId;
|
||||
final i0.Value<i2.AssetVisibility> visibility;
|
||||
final i0.Value<String?> stackId;
|
||||
@@ -1479,6 +1539,7 @@ class RemoteAssetEntityCompanion
|
||||
this.localDateTime = const i0.Value.absent(),
|
||||
this.thumbHash = const i0.Value.absent(),
|
||||
this.deletedAt = const i0.Value.absent(),
|
||||
this.uploadedAt = const i0.Value.absent(),
|
||||
this.livePhotoVideoId = const i0.Value.absent(),
|
||||
this.visibility = const i0.Value.absent(),
|
||||
this.stackId = const i0.Value.absent(),
|
||||
@@ -1500,6 +1561,7 @@ class RemoteAssetEntityCompanion
|
||||
this.localDateTime = const i0.Value.absent(),
|
||||
this.thumbHash = const i0.Value.absent(),
|
||||
this.deletedAt = const i0.Value.absent(),
|
||||
this.uploadedAt = const i0.Value.absent(),
|
||||
this.livePhotoVideoId = const i0.Value.absent(),
|
||||
required i2.AssetVisibility visibility,
|
||||
this.stackId = const i0.Value.absent(),
|
||||
@@ -1526,6 +1588,7 @@ class RemoteAssetEntityCompanion
|
||||
i0.Expression<DateTime>? localDateTime,
|
||||
i0.Expression<String>? thumbHash,
|
||||
i0.Expression<DateTime>? deletedAt,
|
||||
i0.Expression<DateTime>? uploadedAt,
|
||||
i0.Expression<String>? livePhotoVideoId,
|
||||
i0.Expression<int>? visibility,
|
||||
i0.Expression<String>? stackId,
|
||||
@@ -1547,6 +1610,7 @@ class RemoteAssetEntityCompanion
|
||||
if (localDateTime != null) 'local_date_time': localDateTime,
|
||||
if (thumbHash != null) 'thumb_hash': thumbHash,
|
||||
if (deletedAt != null) 'deleted_at': deletedAt,
|
||||
if (uploadedAt != null) 'uploaded_at': uploadedAt,
|
||||
if (livePhotoVideoId != null) 'live_photo_video_id': livePhotoVideoId,
|
||||
if (visibility != null) 'visibility': visibility,
|
||||
if (stackId != null) 'stack_id': stackId,
|
||||
@@ -1570,6 +1634,7 @@ class RemoteAssetEntityCompanion
|
||||
i0.Value<DateTime?>? localDateTime,
|
||||
i0.Value<String?>? thumbHash,
|
||||
i0.Value<DateTime?>? deletedAt,
|
||||
i0.Value<DateTime?>? uploadedAt,
|
||||
i0.Value<String?>? livePhotoVideoId,
|
||||
i0.Value<i2.AssetVisibility>? visibility,
|
||||
i0.Value<String?>? stackId,
|
||||
@@ -1591,6 +1656,7 @@ class RemoteAssetEntityCompanion
|
||||
localDateTime: localDateTime ?? this.localDateTime,
|
||||
thumbHash: thumbHash ?? this.thumbHash,
|
||||
deletedAt: deletedAt ?? this.deletedAt,
|
||||
uploadedAt: uploadedAt ?? this.uploadedAt,
|
||||
livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId,
|
||||
visibility: visibility ?? this.visibility,
|
||||
stackId: stackId ?? this.stackId,
|
||||
@@ -1646,6 +1712,9 @@ class RemoteAssetEntityCompanion
|
||||
if (deletedAt.present) {
|
||||
map['deleted_at'] = i0.Variable<DateTime>(deletedAt.value);
|
||||
}
|
||||
if (uploadedAt.present) {
|
||||
map['uploaded_at'] = i0.Variable<DateTime>(uploadedAt.value);
|
||||
}
|
||||
if (livePhotoVideoId.present) {
|
||||
map['live_photo_video_id'] = i0.Variable<String>(livePhotoVideoId.value);
|
||||
}
|
||||
@@ -1683,6 +1752,7 @@ class RemoteAssetEntityCompanion
|
||||
..write('localDateTime: $localDateTime, ')
|
||||
..write('thumbHash: $thumbHash, ')
|
||||
..write('deletedAt: $deletedAt, ')
|
||||
..write('uploadedAt: $uploadedAt, ')
|
||||
..write('livePhotoVideoId: $livePhotoVideoId, ')
|
||||
..write('visibility: $visibility, ')
|
||||
..write('stackId: $stackId, ')
|
||||
|
||||
@@ -98,7 +98,7 @@ class Drift extends $Drift {
|
||||
}
|
||||
|
||||
@override
|
||||
int get schemaVersion => 25;
|
||||
int get schemaVersion => 26;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
@@ -267,6 +267,9 @@ class Drift extends $Drift {
|
||||
from24To25: (m, v25) async {
|
||||
await m.createTable(v25.metadata);
|
||||
},
|
||||
from25To26: (m, v26) async {
|
||||
await m.addColumn(v26.remoteAssetEntity, v26.remoteAssetEntity.uploadedAt);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -12943,6 +12943,602 @@ i1.GeneratedColumn<String> _column_211(String aliasedName) =>
|
||||
type: i1.DriftSqlType.string,
|
||||
$customConstraints: 'NOT NULL',
|
||||
);
|
||||
|
||||
final class Schema26 extends i0.VersionedSchema {
|
||||
Schema26({required super.database}) : super(version: 26);
|
||||
@override
|
||||
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||
userEntity,
|
||||
remoteAssetEntity,
|
||||
stackEntity,
|
||||
localAssetEntity,
|
||||
remoteAlbumEntity,
|
||||
localAlbumEntity,
|
||||
localAlbumAssetEntity,
|
||||
idxLocalAlbumAssetAlbumAsset,
|
||||
idxLocalAssetChecksum,
|
||||
idxLocalAssetCloudId,
|
||||
idxStackPrimaryAssetId,
|
||||
idxRemoteAssetOwnerChecksum,
|
||||
uQRemoteAssetsOwnerChecksum,
|
||||
uQRemoteAssetsOwnerLibraryChecksum,
|
||||
idxRemoteAssetChecksum,
|
||||
idxRemoteAssetStackId,
|
||||
idxRemoteAssetLocalDateTimeDay,
|
||||
idxRemoteAssetLocalDateTimeMonth,
|
||||
authUserEntity,
|
||||
userMetadataEntity,
|
||||
partnerEntity,
|
||||
remoteExifEntity,
|
||||
remoteAlbumAssetEntity,
|
||||
remoteAlbumUserEntity,
|
||||
remoteAssetCloudIdEntity,
|
||||
memoryEntity,
|
||||
memoryAssetEntity,
|
||||
personEntity,
|
||||
assetFaceEntity,
|
||||
storeEntity,
|
||||
trashedLocalAssetEntity,
|
||||
assetEditEntity,
|
||||
metadata,
|
||||
idxPartnerSharedWithId,
|
||||
idxLatLng,
|
||||
idxRemoteAlbumAssetAlbumAsset,
|
||||
idxRemoteAssetCloudId,
|
||||
idxPersonOwnerId,
|
||||
idxAssetFacePersonId,
|
||||
idxAssetFaceAssetId,
|
||||
idxTrashedLocalAssetChecksum,
|
||||
idxTrashedLocalAssetAlbum,
|
||||
idxAssetEditAssetId,
|
||||
];
|
||||
late final Shape33 userEntity = Shape33(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_108,
|
||||
_column_109,
|
||||
_column_110,
|
||||
_column_111,
|
||||
_column_112,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape50 remoteAssetEntity = Shape50(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_108,
|
||||
_column_113,
|
||||
_column_114,
|
||||
_column_115,
|
||||
_column_116,
|
||||
_column_117,
|
||||
_column_118,
|
||||
_column_107,
|
||||
_column_119,
|
||||
_column_120,
|
||||
_column_121,
|
||||
_column_122,
|
||||
_column_123,
|
||||
_column_124,
|
||||
_column_212,
|
||||
_column_125,
|
||||
_column_126,
|
||||
_column_127,
|
||||
_column_128,
|
||||
_column_129,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape35 stackEntity = Shape35(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'stack_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_114,
|
||||
_column_115,
|
||||
_column_121,
|
||||
_column_130,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape36 localAssetEntity = Shape36(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'local_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_108,
|
||||
_column_113,
|
||||
_column_114,
|
||||
_column_115,
|
||||
_column_116,
|
||||
_column_117,
|
||||
_column_118,
|
||||
_column_107,
|
||||
_column_131,
|
||||
_column_120,
|
||||
_column_132,
|
||||
_column_133,
|
||||
_column_134,
|
||||
_column_135,
|
||||
_column_136,
|
||||
_column_137,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape48 remoteAlbumEntity = Shape48(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_album_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_108,
|
||||
_column_138,
|
||||
_column_114,
|
||||
_column_115,
|
||||
_column_139,
|
||||
_column_140,
|
||||
_column_141,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape38 localAlbumEntity = Shape38(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'local_album_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_108,
|
||||
_column_115,
|
||||
_column_142,
|
||||
_column_143,
|
||||
_column_144,
|
||||
_column_145,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape39 localAlbumAssetEntity = Shape39(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'local_album_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(asset_id, album_id)'],
|
||||
columns: [_column_146, _column_147, _column_145],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
final i1.Index idxLocalAlbumAssetAlbumAsset = i1.Index(
|
||||
'idx_local_album_asset_album_asset',
|
||||
'CREATE INDEX IF NOT EXISTS idx_local_album_asset_album_asset ON local_album_asset_entity (album_id, asset_id)',
|
||||
);
|
||||
final i1.Index idxLocalAssetChecksum = i1.Index(
|
||||
'idx_local_asset_checksum',
|
||||
'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)',
|
||||
);
|
||||
final i1.Index idxLocalAssetCloudId = i1.Index(
|
||||
'idx_local_asset_cloud_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_local_asset_cloud_id ON local_asset_entity (i_cloud_id)',
|
||||
);
|
||||
final i1.Index idxStackPrimaryAssetId = i1.Index(
|
||||
'idx_stack_primary_asset_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_stack_primary_asset_id ON stack_entity (primary_asset_id)',
|
||||
);
|
||||
final i1.Index idxRemoteAssetOwnerChecksum = i1.Index(
|
||||
'idx_remote_asset_owner_checksum',
|
||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)',
|
||||
);
|
||||
final i1.Index uQRemoteAssetsOwnerChecksum = i1.Index(
|
||||
'UQ_remote_assets_owner_checksum',
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)',
|
||||
);
|
||||
final i1.Index uQRemoteAssetsOwnerLibraryChecksum = i1.Index(
|
||||
'UQ_remote_assets_owner_library_checksum',
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)',
|
||||
);
|
||||
final i1.Index idxRemoteAssetChecksum = i1.Index(
|
||||
'idx_remote_asset_checksum',
|
||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)',
|
||||
);
|
||||
final i1.Index idxRemoteAssetStackId = i1.Index(
|
||||
'idx_remote_asset_stack_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_stack_id ON remote_asset_entity (stack_id)',
|
||||
);
|
||||
final i1.Index idxRemoteAssetLocalDateTimeDay = i1.Index(
|
||||
'idx_remote_asset_local_date_time_day',
|
||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_local_date_time_day ON remote_asset_entity (STRFTIME(\'%Y-%m-%d\', local_date_time))',
|
||||
);
|
||||
final i1.Index idxRemoteAssetLocalDateTimeMonth = i1.Index(
|
||||
'idx_remote_asset_local_date_time_month',
|
||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_local_date_time_month ON remote_asset_entity (STRFTIME(\'%Y-%m\', local_date_time))',
|
||||
);
|
||||
late final Shape40 authUserEntity = Shape40(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'auth_user_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_108,
|
||||
_column_109,
|
||||
_column_148,
|
||||
_column_110,
|
||||
_column_111,
|
||||
_column_149,
|
||||
_column_150,
|
||||
_column_151,
|
||||
_column_152,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape4 userMetadataEntity = Shape4(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_metadata_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(user_id, "key")'],
|
||||
columns: [_column_153, _column_154, _column_155],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape41 partnerEntity = Shape41(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'partner_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(shared_by_id, shared_with_id)'],
|
||||
columns: [_column_156, _column_157, _column_158],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape42 remoteExifEntity = Shape42(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_exif_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(asset_id)'],
|
||||
columns: [
|
||||
_column_159,
|
||||
_column_160,
|
||||
_column_161,
|
||||
_column_162,
|
||||
_column_163,
|
||||
_column_164,
|
||||
_column_117,
|
||||
_column_116,
|
||||
_column_165,
|
||||
_column_166,
|
||||
_column_167,
|
||||
_column_168,
|
||||
_column_135,
|
||||
_column_136,
|
||||
_column_169,
|
||||
_column_170,
|
||||
_column_171,
|
||||
_column_172,
|
||||
_column_173,
|
||||
_column_174,
|
||||
_column_175,
|
||||
_column_176,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape7 remoteAlbumAssetEntity = Shape7(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_album_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(asset_id, album_id)'],
|
||||
columns: [_column_159, _column_177],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape10 remoteAlbumUserEntity = Shape10(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_album_user_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(album_id, user_id)'],
|
||||
columns: [_column_177, _column_153, _column_178],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape43 remoteAssetCloudIdEntity = Shape43(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_asset_cloud_id_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(asset_id)'],
|
||||
columns: [
|
||||
_column_159,
|
||||
_column_179,
|
||||
_column_180,
|
||||
_column_134,
|
||||
_column_135,
|
||||
_column_136,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape44 memoryEntity = Shape44(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'memory_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_114,
|
||||
_column_115,
|
||||
_column_124,
|
||||
_column_121,
|
||||
_column_113,
|
||||
_column_181,
|
||||
_column_182,
|
||||
_column_183,
|
||||
_column_184,
|
||||
_column_185,
|
||||
_column_186,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape12 memoryAssetEntity = Shape12(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'memory_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(asset_id, memory_id)'],
|
||||
columns: [_column_159, _column_187],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape45 personEntity = Shape45(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'person_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_114,
|
||||
_column_115,
|
||||
_column_121,
|
||||
_column_108,
|
||||
_column_188,
|
||||
_column_189,
|
||||
_column_190,
|
||||
_column_191,
|
||||
_column_192,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape46 assetFaceEntity = Shape46(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'asset_face_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_159,
|
||||
_column_193,
|
||||
_column_194,
|
||||
_column_195,
|
||||
_column_196,
|
||||
_column_197,
|
||||
_column_198,
|
||||
_column_199,
|
||||
_column_200,
|
||||
_column_201,
|
||||
_column_124,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape18 storeEntity = Shape18(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'store_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [_column_202, _column_203, _column_204],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape47 trashedLocalAssetEntity = Shape47(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'trashed_local_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id, album_id)'],
|
||||
columns: [
|
||||
_column_108,
|
||||
_column_113,
|
||||
_column_114,
|
||||
_column_115,
|
||||
_column_116,
|
||||
_column_117,
|
||||
_column_118,
|
||||
_column_107,
|
||||
_column_205,
|
||||
_column_131,
|
||||
_column_120,
|
||||
_column_132,
|
||||
_column_206,
|
||||
_column_137,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape32 assetEditEntity = Shape32(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'asset_edit_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY(id)'],
|
||||
columns: [
|
||||
_column_107,
|
||||
_column_159,
|
||||
_column_207,
|
||||
_column_208,
|
||||
_column_209,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
late final Shape49 metadata = Shape49(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'metadata',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: ['PRIMARY KEY("key")'],
|
||||
columns: [_column_210, _column_211, _column_115],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null,
|
||||
);
|
||||
final i1.Index idxPartnerSharedWithId = i1.Index(
|
||||
'idx_partner_shared_with_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_partner_shared_with_id ON partner_entity (shared_with_id)',
|
||||
);
|
||||
final i1.Index idxLatLng = i1.Index(
|
||||
'idx_lat_lng',
|
||||
'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)',
|
||||
);
|
||||
final i1.Index idxRemoteAlbumAssetAlbumAsset = i1.Index(
|
||||
'idx_remote_album_asset_album_asset',
|
||||
'CREATE INDEX IF NOT EXISTS idx_remote_album_asset_album_asset ON remote_album_asset_entity (album_id, asset_id)',
|
||||
);
|
||||
final i1.Index idxRemoteAssetCloudId = i1.Index(
|
||||
'idx_remote_asset_cloud_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_cloud_id ON remote_asset_cloud_id_entity (cloud_id)',
|
||||
);
|
||||
final i1.Index idxPersonOwnerId = i1.Index(
|
||||
'idx_person_owner_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_person_owner_id ON person_entity (owner_id)',
|
||||
);
|
||||
final i1.Index idxAssetFacePersonId = i1.Index(
|
||||
'idx_asset_face_person_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_asset_face_person_id ON asset_face_entity (person_id)',
|
||||
);
|
||||
final i1.Index idxAssetFaceAssetId = i1.Index(
|
||||
'idx_asset_face_asset_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_asset_face_asset_id ON asset_face_entity (asset_id)',
|
||||
);
|
||||
final i1.Index idxTrashedLocalAssetChecksum = i1.Index(
|
||||
'idx_trashed_local_asset_checksum',
|
||||
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
||||
);
|
||||
final i1.Index idxTrashedLocalAssetAlbum = i1.Index(
|
||||
'idx_trashed_local_asset_album',
|
||||
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)',
|
||||
);
|
||||
final i1.Index idxAssetEditAssetId = i1.Index(
|
||||
'idx_asset_edit_asset_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_asset_edit_asset_id ON asset_edit_entity (asset_id)',
|
||||
);
|
||||
}
|
||||
|
||||
class Shape50 extends i0.VersionedTable {
|
||||
Shape50({required super.source, required super.alias}) : super.aliased();
|
||||
i1.GeneratedColumn<String> get name =>
|
||||
columnsByName['name']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<int> get type =>
|
||||
columnsByName['type']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<String> get createdAt =>
|
||||
columnsByName['created_at']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get updatedAt =>
|
||||
columnsByName['updated_at']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<int> get width =>
|
||||
columnsByName['width']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<int> get height =>
|
||||
columnsByName['height']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<int> get durationMs =>
|
||||
columnsByName['duration_ms']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<String> get id =>
|
||||
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get checksum =>
|
||||
columnsByName['checksum']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<int> get isFavorite =>
|
||||
columnsByName['is_favorite']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<String> get ownerId =>
|
||||
columnsByName['owner_id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get localDateTime =>
|
||||
columnsByName['local_date_time']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get thumbHash =>
|
||||
columnsByName['thumb_hash']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get deletedAt =>
|
||||
columnsByName['deleted_at']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get uploadedAt =>
|
||||
columnsByName['uploaded_at']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get livePhotoVideoId =>
|
||||
columnsByName['live_photo_video_id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<int> get visibility =>
|
||||
columnsByName['visibility']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<String> get stackId =>
|
||||
columnsByName['stack_id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get libraryId =>
|
||||
columnsByName['library_id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<int> get isEdited =>
|
||||
columnsByName['is_edited']! as i1.GeneratedColumn<int>;
|
||||
}
|
||||
|
||||
i1.GeneratedColumn<String> _column_212(String aliasedName) =>
|
||||
i1.GeneratedColumn<String>(
|
||||
'uploaded_at',
|
||||
aliasedName,
|
||||
true,
|
||||
type: i1.DriftSqlType.string,
|
||||
$customConstraints: 'NULL',
|
||||
);
|
||||
i0.MigrationStepWithVersion migrationSteps({
|
||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||
@@ -12968,6 +13564,7 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||
required Future<void> Function(i1.Migrator m, Schema23 schema) from22To23,
|
||||
required Future<void> Function(i1.Migrator m, Schema24 schema) from23To24,
|
||||
required Future<void> Function(i1.Migrator m, Schema25 schema) from24To25,
|
||||
required Future<void> Function(i1.Migrator m, Schema26 schema) from25To26,
|
||||
}) {
|
||||
return (currentVersion, database) async {
|
||||
switch (currentVersion) {
|
||||
@@ -13091,6 +13688,11 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||
final migrator = i1.Migrator(database, schema);
|
||||
await from24To25(migrator, schema);
|
||||
return 25;
|
||||
case 25:
|
||||
final schema = Schema26(database: database);
|
||||
final migrator = i1.Migrator(database, schema);
|
||||
await from25To26(migrator, schema);
|
||||
return 26;
|
||||
default:
|
||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||
}
|
||||
@@ -13122,6 +13724,7 @@ i1.OnUpgrade stepByStep({
|
||||
required Future<void> Function(i1.Migrator m, Schema23 schema) from22To23,
|
||||
required Future<void> Function(i1.Migrator m, Schema24 schema) from23To24,
|
||||
required Future<void> Function(i1.Migrator m, Schema25 schema) from24To25,
|
||||
required Future<void> Function(i1.Migrator m, Schema26 schema) from25To26,
|
||||
}) => i0.VersionedSchema.stepByStepHelper(
|
||||
step: migrationSteps(
|
||||
from1To2: from1To2,
|
||||
@@ -13148,5 +13751,6 @@ i1.OnUpgrade stepByStep({
|
||||
from22To23: from22To23,
|
||||
from23To24: from23To24,
|
||||
from24To25: from24To25,
|
||||
from25To26: from25To26,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -191,6 +191,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||
type: Value(asset.type.toAssetType()),
|
||||
createdAt: Value.absentIfNull(asset.fileCreatedAt),
|
||||
updatedAt: Value.absentIfNull(asset.fileModifiedAt),
|
||||
uploadedAt: Value(asset.createdAt),
|
||||
durationMs: Value(asset.duration?.toDuration()?.inMilliseconds ?? 0),
|
||||
checksum: Value(asset.checksum),
|
||||
isFavorite: Value(asset.isFavorite),
|
||||
@@ -229,6 +230,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||
type: Value(asset.type.toAssetType()),
|
||||
createdAt: Value.absentIfNull(asset.fileCreatedAt),
|
||||
updatedAt: Value.absentIfNull(asset.fileModifiedAt),
|
||||
uploadedAt: Value(asset.createdAt),
|
||||
durationMs: Value(asset.duration),
|
||||
checksum: Value(asset.checksum),
|
||||
isFavorite: Value(asset.isFavorite),
|
||||
|
||||
@@ -79,6 +79,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||
type: row.type,
|
||||
createdAt: row.createdAt,
|
||||
updatedAt: row.updatedAt,
|
||||
uploadedAt: row.uploadedAt,
|
||||
thumbHash: row.thumbHash,
|
||||
width: row.width,
|
||||
height: row.height,
|
||||
@@ -317,6 +318,17 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||
origin: TimelineOrigin.remoteAssets,
|
||||
);
|
||||
|
||||
TimelineQuery recentlyAdded(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder(
|
||||
filter: (row) =>
|
||||
row.uploadedAt.isNotNull() &
|
||||
row.deletedAt.isNull() &
|
||||
row.ownerId.equals(userId) &
|
||||
(row.visibility.equalsValue(AssetVisibility.timeline) | row.visibility.equalsValue(AssetVisibility.archive)),
|
||||
origin: TimelineOrigin.recentlyAdded,
|
||||
groupBy: groupBy,
|
||||
sortBy: SortAssetsBy.uploaded,
|
||||
);
|
||||
|
||||
TimelineQuery favorite(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder(
|
||||
filter: (row) =>
|
||||
row.deletedAt.isNull() &
|
||||
@@ -597,9 +609,10 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||
required TimelineOrigin origin,
|
||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
||||
bool joinLocal = false,
|
||||
SortAssetsBy sortBy = SortAssetsBy.taken,
|
||||
}) {
|
||||
return (
|
||||
bucketSource: () => _watchRemoteBucket(filter: filter, groupBy: groupBy),
|
||||
bucketSource: () => _watchRemoteBucket(filter: filter, groupBy: groupBy, sortBy: sortBy),
|
||||
assetSource: (offset, count) =>
|
||||
_getRemoteAssets(filter: filter, offset: offset, count: count, joinLocal: joinLocal),
|
||||
origin: origin,
|
||||
@@ -609,6 +622,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||
Stream<List<Bucket>> _watchRemoteBucket({
|
||||
required Expression<bool> Function($RemoteAssetEntityTable row) filter,
|
||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
||||
SortAssetsBy sortBy = SortAssetsBy.taken,
|
||||
}) {
|
||||
if (groupBy == GroupAssetsBy.none) {
|
||||
final query = _db.remoteAssetEntity.count(where: filter);
|
||||
@@ -616,7 +630,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||
}
|
||||
|
||||
final assetCountExp = _db.remoteAssetEntity.id.count();
|
||||
final dateExp = _db.remoteAssetEntity.effectiveCreatedAt(groupBy);
|
||||
final dateExp = _db.remoteAssetEntity.effectiveCreatedAt(groupBy, sortBy: sortBy);
|
||||
|
||||
final query = _db.remoteAssetEntity.selectOnly()
|
||||
..addColumns([assetCountExp, dateExp])
|
||||
@@ -692,8 +706,13 @@ extension on Expression<DateTime> {
|
||||
}
|
||||
|
||||
extension on $RemoteAssetEntityTable {
|
||||
Expression<String> effectiveCreatedAt(GroupAssetsBy groupBy) =>
|
||||
coalesce([localDateTime.dateFmt(groupBy), createdAt.dateFmt(groupBy, toLocal: true)]);
|
||||
Expression<String> effectiveCreatedAt(GroupAssetsBy groupBy, {SortAssetsBy sortBy = SortAssetsBy.taken}) {
|
||||
if (sortBy == SortAssetsBy.uploaded) {
|
||||
return uploadedAt.dateFmt(groupBy, toLocal: true);
|
||||
}
|
||||
|
||||
return coalesce([localDateTime.dateFmt(groupBy), createdAt.dateFmt(groupBy, toLocal: true)]);
|
||||
}
|
||||
}
|
||||
|
||||
extension on String {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftRecentlyAddedPage extends StatelessWidget {
|
||||
const DriftRecentlyAddedPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ProviderScope(
|
||||
overrides: [
|
||||
timelineServiceProvider.overrideWith((ref) {
|
||||
final user = ref.watch(currentUserProvider);
|
||||
if (user == null) {
|
||||
throw Exception('User must be logged in to access recently taken');
|
||||
}
|
||||
|
||||
final timelineService = ref.watch(timelineFactoryProvider).recentlyAdded(user.id);
|
||||
ref.onDispose(timelineService.dispose);
|
||||
return timelineService;
|
||||
}),
|
||||
],
|
||||
child: Timeline(appBar: MesmerizingSliverAppBar(title: 'recently_added'.t())),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/search/search_filter.model.dart';
|
||||
import 'package:immich_mobile/presentation/pages/search/paginated_search.provider.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart';
|
||||
@@ -879,6 +880,12 @@ class _QuickLinkList extends StatelessWidget {
|
||||
isTop: true,
|
||||
onTap: () => context.pushRoute(const DriftRecentlyTakenRoute()),
|
||||
),
|
||||
_QuickLink(
|
||||
title: context.t.recently_added,
|
||||
icon: Icons.upload_outlined,
|
||||
isTop: true,
|
||||
onTap: () => context.pushRoute(const DriftRecentlyAddedRoute()),
|
||||
),
|
||||
_QuickLink(
|
||||
title: 'videos'.t(context: context),
|
||||
icon: Icons.play_circle_outline_rounded,
|
||||
|
||||
@@ -58,6 +58,7 @@ import 'package:immich_mobile/presentation/pages/drift_person.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_place.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_place_detail.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_recently_taken.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_recently_added.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_remote_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_trash.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_user_selection.page.dart';
|
||||
@@ -168,6 +169,7 @@ class AppRouter extends RootStackRouter {
|
||||
AutoRoute(page: DriftAssetSelectionTimelineRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftPartnerDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftRecentlyTakenRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftRecentlyAddedRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftLocalAlbumsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftCreateAlbumRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftPlaceRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
|
||||
@@ -1047,6 +1047,22 @@ class DriftPlaceRouteArgs {
|
||||
int get hashCode => key.hashCode ^ currentLocation.hashCode;
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [DriftRecentlyAddedPage]
|
||||
class DriftRecentlyAddedRoute extends PageRouteInfo<void> {
|
||||
const DriftRecentlyAddedRoute({List<PageRouteInfo>? children})
|
||||
: super(DriftRecentlyAddedRoute.name, initialChildren: children);
|
||||
|
||||
static const String name = 'DriftRecentlyAddedRoute';
|
||||
|
||||
static PageInfo page = PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const DriftRecentlyAddedPage();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [DriftRecentlyTakenPage]
|
||||
class DriftRecentlyTakenRoute extends PageRouteInfo<void> {
|
||||
|
||||
@@ -329,7 +329,7 @@ class ForegroundUploadService {
|
||||
'fileCreatedAt': asset.createdAt.toUtc().toIso8601String(),
|
||||
'fileModifiedAt': asset.updatedAt.toUtc().toIso8601String(),
|
||||
'isFavorite': asset.isFavorite.toString(),
|
||||
'duration': asset.duration.toString(),
|
||||
'duration': (asset.durationMs ?? 0).toString(),
|
||||
};
|
||||
|
||||
// Upload live photo video first if available
|
||||
|
||||
Generated
+1
@@ -375,6 +375,7 @@ Class | Method | HTTP request | Description
|
||||
- [AssetMetadataUpsertItemDto](doc//AssetMetadataUpsertItemDto.md)
|
||||
- [AssetOcrResponseDto](doc//AssetOcrResponseDto.md)
|
||||
- [AssetOrder](doc//AssetOrder.md)
|
||||
- [AssetOrderBy](doc//AssetOrderBy.md)
|
||||
- [AssetRejectReason](doc//AssetRejectReason.md)
|
||||
- [AssetResponseDto](doc//AssetResponseDto.md)
|
||||
- [AssetStackResponseDto](doc//AssetStackResponseDto.md)
|
||||
|
||||
Generated
+1
@@ -123,6 +123,7 @@ part 'model/asset_metadata_upsert_dto.dart';
|
||||
part 'model/asset_metadata_upsert_item_dto.dart';
|
||||
part 'model/asset_ocr_response_dto.dart';
|
||||
part 'model/asset_order.dart';
|
||||
part 'model/asset_order_by.dart';
|
||||
part 'model/asset_reject_reason.dart';
|
||||
part 'model/asset_response_dto.dart';
|
||||
part 'model/asset_stack_response_dto.dart';
|
||||
|
||||
Generated
+24
-6
@@ -44,6 +44,9 @@ class TimelineApi {
|
||||
/// * [AssetOrder] order:
|
||||
/// Sort order for assets within time buckets (ASC for oldest first, DESC for newest first)
|
||||
///
|
||||
/// * [AssetOrderBy] orderBy:
|
||||
/// Date to group and order assets by (takenAt for date taken, createdAt for date added to Immich)
|
||||
///
|
||||
/// * [String] personId:
|
||||
/// Filter assets containing a specific person (face recognition)
|
||||
///
|
||||
@@ -66,7 +69,7 @@ class TimelineApi {
|
||||
///
|
||||
/// * [bool] withStacked:
|
||||
/// Include stacked assets in the response. When true, only primary assets from stacks are returned.
|
||||
Future<Response> getTimeBucketWithHttpInfo(String timeBucket, { String? albumId, String? bbox, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async {
|
||||
Future<Response> getTimeBucketWithHttpInfo(String timeBucket, { String? albumId, String? bbox, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, AssetOrderBy? orderBy, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/timeline/bucket';
|
||||
|
||||
@@ -95,6 +98,9 @@ class TimelineApi {
|
||||
if (order != null) {
|
||||
queryParams.addAll(_queryParams('', 'order', order));
|
||||
}
|
||||
if (orderBy != null) {
|
||||
queryParams.addAll(_queryParams('', 'orderBy', orderBy));
|
||||
}
|
||||
if (personId != null) {
|
||||
queryParams.addAll(_queryParams('', 'personId', personId));
|
||||
}
|
||||
@@ -161,6 +167,9 @@ class TimelineApi {
|
||||
/// * [AssetOrder] order:
|
||||
/// Sort order for assets within time buckets (ASC for oldest first, DESC for newest first)
|
||||
///
|
||||
/// * [AssetOrderBy] orderBy:
|
||||
/// Date to group and order assets by (takenAt for date taken, createdAt for date added to Immich)
|
||||
///
|
||||
/// * [String] personId:
|
||||
/// Filter assets containing a specific person (face recognition)
|
||||
///
|
||||
@@ -183,8 +192,8 @@ class TimelineApi {
|
||||
///
|
||||
/// * [bool] withStacked:
|
||||
/// Include stacked assets in the response. When true, only primary assets from stacks are returned.
|
||||
Future<TimeBucketAssetResponseDto?> getTimeBucket(String timeBucket, { String? albumId, String? bbox, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async {
|
||||
final response = await getTimeBucketWithHttpInfo(timeBucket, albumId: albumId, bbox: bbox, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, personId: personId, slug: slug, tagId: tagId, userId: userId, visibility: visibility, withCoordinates: withCoordinates, withPartners: withPartners, withStacked: withStacked, );
|
||||
Future<TimeBucketAssetResponseDto?> getTimeBucket(String timeBucket, { String? albumId, String? bbox, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, AssetOrderBy? orderBy, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async {
|
||||
final response = await getTimeBucketWithHttpInfo(timeBucket, albumId: albumId, bbox: bbox, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, orderBy: orderBy, personId: personId, slug: slug, tagId: tagId, userId: userId, visibility: visibility, withCoordinates: withCoordinates, withPartners: withPartners, withStacked: withStacked, );
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
@@ -223,6 +232,9 @@ class TimelineApi {
|
||||
/// * [AssetOrder] order:
|
||||
/// Sort order for assets within time buckets (ASC for oldest first, DESC for newest first)
|
||||
///
|
||||
/// * [AssetOrderBy] orderBy:
|
||||
/// Date to group and order assets by (takenAt for date taken, createdAt for date added to Immich)
|
||||
///
|
||||
/// * [String] personId:
|
||||
/// Filter assets containing a specific person (face recognition)
|
||||
///
|
||||
@@ -245,7 +257,7 @@ class TimelineApi {
|
||||
///
|
||||
/// * [bool] withStacked:
|
||||
/// Include stacked assets in the response. When true, only primary assets from stacks are returned.
|
||||
Future<Response> getTimeBucketsWithHttpInfo({ String? albumId, String? bbox, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async {
|
||||
Future<Response> getTimeBucketsWithHttpInfo({ String? albumId, String? bbox, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, AssetOrderBy? orderBy, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/timeline/buckets';
|
||||
|
||||
@@ -274,6 +286,9 @@ class TimelineApi {
|
||||
if (order != null) {
|
||||
queryParams.addAll(_queryParams('', 'order', order));
|
||||
}
|
||||
if (orderBy != null) {
|
||||
queryParams.addAll(_queryParams('', 'orderBy', orderBy));
|
||||
}
|
||||
if (personId != null) {
|
||||
queryParams.addAll(_queryParams('', 'personId', personId));
|
||||
}
|
||||
@@ -336,6 +351,9 @@ class TimelineApi {
|
||||
/// * [AssetOrder] order:
|
||||
/// Sort order for assets within time buckets (ASC for oldest first, DESC for newest first)
|
||||
///
|
||||
/// * [AssetOrderBy] orderBy:
|
||||
/// Date to group and order assets by (takenAt for date taken, createdAt for date added to Immich)
|
||||
///
|
||||
/// * [String] personId:
|
||||
/// Filter assets containing a specific person (face recognition)
|
||||
///
|
||||
@@ -358,8 +376,8 @@ class TimelineApi {
|
||||
///
|
||||
/// * [bool] withStacked:
|
||||
/// Include stacked assets in the response. When true, only primary assets from stacks are returned.
|
||||
Future<List<TimeBucketsResponseDto>?> getTimeBuckets({ String? albumId, String? bbox, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async {
|
||||
final response = await getTimeBucketsWithHttpInfo( albumId: albumId, bbox: bbox, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, personId: personId, slug: slug, tagId: tagId, userId: userId, visibility: visibility, withCoordinates: withCoordinates, withPartners: withPartners, withStacked: withStacked, );
|
||||
Future<List<TimeBucketsResponseDto>?> getTimeBuckets({ String? albumId, String? bbox, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, AssetOrderBy? orderBy, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async {
|
||||
final response = await getTimeBucketsWithHttpInfo( albumId: albumId, bbox: bbox, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, orderBy: orderBy, personId: personId, slug: slug, tagId: tagId, userId: userId, visibility: visibility, withCoordinates: withCoordinates, withPartners: withPartners, withStacked: withStacked, );
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
|
||||
Generated
+2
@@ -292,6 +292,8 @@ class ApiClient {
|
||||
return AssetOcrResponseDto.fromJson(value);
|
||||
case 'AssetOrder':
|
||||
return AssetOrderTypeTransformer().decode(value);
|
||||
case 'AssetOrderBy':
|
||||
return AssetOrderByTypeTransformer().decode(value);
|
||||
case 'AssetRejectReason':
|
||||
return AssetRejectReasonTypeTransformer().decode(value);
|
||||
case 'AssetResponseDto':
|
||||
|
||||
Generated
+3
@@ -76,6 +76,9 @@ String parameterToString(dynamic value) {
|
||||
if (value is AssetOrder) {
|
||||
return AssetOrderTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is AssetOrderBy) {
|
||||
return AssetOrderByTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is AssetRejectReason) {
|
||||
return AssetRejectReasonTypeTransformer().encode(value).toString();
|
||||
}
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
/// Asset sorting property
|
||||
class AssetOrderBy {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetOrderBy._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const takenAt = AssetOrderBy._(r'takenAt');
|
||||
static const createdAt = AssetOrderBy._(r'createdAt');
|
||||
|
||||
/// List of all possible values in this [enum][AssetOrderBy].
|
||||
static const values = <AssetOrderBy>[
|
||||
takenAt,
|
||||
createdAt,
|
||||
];
|
||||
|
||||
static AssetOrderBy? fromJson(dynamic value) => AssetOrderByTypeTransformer().decode(value);
|
||||
|
||||
static List<AssetOrderBy> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetOrderBy>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = AssetOrderBy.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [AssetOrderBy] to String,
|
||||
/// and [decode] dynamic data back to [AssetOrderBy].
|
||||
class AssetOrderByTypeTransformer {
|
||||
factory AssetOrderByTypeTransformer() => _instance ??= const AssetOrderByTypeTransformer._();
|
||||
|
||||
const AssetOrderByTypeTransformer._();
|
||||
|
||||
String encode(AssetOrderBy data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetOrderBy.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetOrderBy? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'takenAt': return AssetOrderBy.takenAt;
|
||||
case r'createdAt': return AssetOrderBy.createdAt;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetOrderByTypeTransformer] instance.
|
||||
static AssetOrderByTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
+16
-1
@@ -14,6 +14,7 @@ class SyncAssetV1 {
|
||||
/// Returns a new [SyncAssetV1] instance.
|
||||
SyncAssetV1({
|
||||
required this.checksum,
|
||||
required this.createdAt,
|
||||
required this.deletedAt,
|
||||
required this.duration,
|
||||
required this.fileCreatedAt,
|
||||
@@ -37,6 +38,9 @@ class SyncAssetV1 {
|
||||
/// Checksum
|
||||
String checksum;
|
||||
|
||||
/// Uploaded to Immich at
|
||||
DateTime? createdAt;
|
||||
|
||||
/// Deleted at
|
||||
DateTime? deletedAt;
|
||||
|
||||
@@ -98,6 +102,7 @@ class SyncAssetV1 {
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SyncAssetV1 &&
|
||||
other.checksum == checksum &&
|
||||
other.createdAt == createdAt &&
|
||||
other.deletedAt == deletedAt &&
|
||||
other.duration == duration &&
|
||||
other.fileCreatedAt == fileCreatedAt &&
|
||||
@@ -121,6 +126,7 @@ class SyncAssetV1 {
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(checksum.hashCode) +
|
||||
(createdAt == null ? 0 : createdAt!.hashCode) +
|
||||
(deletedAt == null ? 0 : deletedAt!.hashCode) +
|
||||
(duration == null ? 0 : duration!.hashCode) +
|
||||
(fileCreatedAt == null ? 0 : fileCreatedAt!.hashCode) +
|
||||
@@ -141,11 +147,18 @@ class SyncAssetV1 {
|
||||
(width == null ? 0 : width!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'SyncAssetV1[checksum=$checksum, deletedAt=$deletedAt, duration=$duration, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, height=$height, id=$id, isEdited=$isEdited, isFavorite=$isFavorite, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, ownerId=$ownerId, stackId=$stackId, thumbhash=$thumbhash, type=$type, visibility=$visibility, width=$width]';
|
||||
String toString() => 'SyncAssetV1[checksum=$checksum, createdAt=$createdAt, deletedAt=$deletedAt, duration=$duration, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, height=$height, id=$id, isEdited=$isEdited, isFavorite=$isFavorite, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, ownerId=$ownerId, stackId=$stackId, thumbhash=$thumbhash, type=$type, visibility=$visibility, width=$width]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'checksum'] = this.checksum;
|
||||
if (this.createdAt != null) {
|
||||
json[r'createdAt'] = _isEpochMarker(r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/')
|
||||
? this.createdAt!.millisecondsSinceEpoch
|
||||
: this.createdAt!.toUtc().toIso8601String();
|
||||
} else {
|
||||
// json[r'createdAt'] = null;
|
||||
}
|
||||
if (this.deletedAt != null) {
|
||||
json[r'deletedAt'] = _isEpochMarker(r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/')
|
||||
? this.deletedAt!.millisecondsSinceEpoch
|
||||
@@ -229,6 +242,7 @@ class SyncAssetV1 {
|
||||
|
||||
return SyncAssetV1(
|
||||
checksum: mapValueOfType<String>(json, r'checksum')!,
|
||||
createdAt: mapDateTime(json, r'createdAt', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
|
||||
deletedAt: mapDateTime(json, r'deletedAt', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
|
||||
duration: mapValueOfType<String>(json, r'duration'),
|
||||
fileCreatedAt: mapDateTime(json, r'fileCreatedAt', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
|
||||
@@ -295,6 +309,7 @@ class SyncAssetV1 {
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'checksum',
|
||||
'createdAt',
|
||||
'deletedAt',
|
||||
'duration',
|
||||
'fileCreatedAt',
|
||||
|
||||
+16
-1
@@ -14,6 +14,7 @@ class SyncAssetV2 {
|
||||
/// Returns a new [SyncAssetV2] instance.
|
||||
SyncAssetV2({
|
||||
required this.checksum,
|
||||
required this.createdAt,
|
||||
required this.deletedAt,
|
||||
required this.duration,
|
||||
required this.fileCreatedAt,
|
||||
@@ -37,6 +38,9 @@ class SyncAssetV2 {
|
||||
/// Checksum
|
||||
String checksum;
|
||||
|
||||
/// Uploaded to Immich at
|
||||
DateTime? createdAt;
|
||||
|
||||
/// Deleted at
|
||||
DateTime? deletedAt;
|
||||
|
||||
@@ -101,6 +105,7 @@ class SyncAssetV2 {
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SyncAssetV2 &&
|
||||
other.checksum == checksum &&
|
||||
other.createdAt == createdAt &&
|
||||
other.deletedAt == deletedAt &&
|
||||
other.duration == duration &&
|
||||
other.fileCreatedAt == fileCreatedAt &&
|
||||
@@ -124,6 +129,7 @@ class SyncAssetV2 {
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(checksum.hashCode) +
|
||||
(createdAt == null ? 0 : createdAt!.hashCode) +
|
||||
(deletedAt == null ? 0 : deletedAt!.hashCode) +
|
||||
(duration == null ? 0 : duration!.hashCode) +
|
||||
(fileCreatedAt == null ? 0 : fileCreatedAt!.hashCode) +
|
||||
@@ -144,11 +150,18 @@ class SyncAssetV2 {
|
||||
(width == null ? 0 : width!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'SyncAssetV2[checksum=$checksum, deletedAt=$deletedAt, duration=$duration, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, height=$height, id=$id, isEdited=$isEdited, isFavorite=$isFavorite, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, ownerId=$ownerId, stackId=$stackId, thumbhash=$thumbhash, type=$type, visibility=$visibility, width=$width]';
|
||||
String toString() => 'SyncAssetV2[checksum=$checksum, createdAt=$createdAt, deletedAt=$deletedAt, duration=$duration, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, height=$height, id=$id, isEdited=$isEdited, isFavorite=$isFavorite, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, ownerId=$ownerId, stackId=$stackId, thumbhash=$thumbhash, type=$type, visibility=$visibility, width=$width]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'checksum'] = this.checksum;
|
||||
if (this.createdAt != null) {
|
||||
json[r'createdAt'] = _isEpochMarker(r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/')
|
||||
? this.createdAt!.millisecondsSinceEpoch
|
||||
: this.createdAt!.toUtc().toIso8601String();
|
||||
} else {
|
||||
// json[r'createdAt'] = null;
|
||||
}
|
||||
if (this.deletedAt != null) {
|
||||
json[r'deletedAt'] = _isEpochMarker(r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/')
|
||||
? this.deletedAt!.millisecondsSinceEpoch
|
||||
@@ -232,6 +245,7 @@ class SyncAssetV2 {
|
||||
|
||||
return SyncAssetV2(
|
||||
checksum: mapValueOfType<String>(json, r'checksum')!,
|
||||
createdAt: mapDateTime(json, r'createdAt', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
|
||||
deletedAt: mapDateTime(json, r'deletedAt', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
|
||||
duration: mapValueOfType<int>(json, r'duration'),
|
||||
fileCreatedAt: mapDateTime(json, r'fileCreatedAt', r'/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/'),
|
||||
@@ -298,6 +312,7 @@ class SyncAssetV2 {
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'checksum',
|
||||
'createdAt',
|
||||
'deletedAt',
|
||||
'duration',
|
||||
'fileCreatedAt',
|
||||
|
||||
+12
-1
@@ -15,6 +15,7 @@ class TimeBucketAssetResponseDto {
|
||||
TimeBucketAssetResponseDto({
|
||||
this.city = const [],
|
||||
this.country = const [],
|
||||
this.createdAt = const [],
|
||||
this.duration = const [],
|
||||
this.fileCreatedAt = const [],
|
||||
this.id = const [],
|
||||
@@ -39,6 +40,9 @@ class TimeBucketAssetResponseDto {
|
||||
/// Array of country names extracted from EXIF GPS data
|
||||
List<String?> country;
|
||||
|
||||
/// Array of UTC timestamps when each asset was originally uploaded to Immich
|
||||
List<String> createdAt;
|
||||
|
||||
/// Array of video/gif durations in milliseconds (null for static images)
|
||||
List<int?> duration;
|
||||
|
||||
@@ -91,6 +95,7 @@ class TimeBucketAssetResponseDto {
|
||||
bool operator ==(Object other) => identical(this, other) || other is TimeBucketAssetResponseDto &&
|
||||
_deepEquality.equals(other.city, city) &&
|
||||
_deepEquality.equals(other.country, country) &&
|
||||
_deepEquality.equals(other.createdAt, createdAt) &&
|
||||
_deepEquality.equals(other.duration, duration) &&
|
||||
_deepEquality.equals(other.fileCreatedAt, fileCreatedAt) &&
|
||||
_deepEquality.equals(other.id, id) &&
|
||||
@@ -113,6 +118,7 @@ class TimeBucketAssetResponseDto {
|
||||
// ignore: unnecessary_parenthesis
|
||||
(city.hashCode) +
|
||||
(country.hashCode) +
|
||||
(createdAt.hashCode) +
|
||||
(duration.hashCode) +
|
||||
(fileCreatedAt.hashCode) +
|
||||
(id.hashCode) +
|
||||
@@ -131,12 +137,13 @@ class TimeBucketAssetResponseDto {
|
||||
(visibility.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'TimeBucketAssetResponseDto[city=$city, country=$country, duration=$duration, fileCreatedAt=$fileCreatedAt, id=$id, isFavorite=$isFavorite, isImage=$isImage, isTrashed=$isTrashed, latitude=$latitude, livePhotoVideoId=$livePhotoVideoId, localOffsetHours=$localOffsetHours, longitude=$longitude, ownerId=$ownerId, projectionType=$projectionType, ratio=$ratio, stack=$stack, thumbhash=$thumbhash, visibility=$visibility]';
|
||||
String toString() => 'TimeBucketAssetResponseDto[city=$city, country=$country, createdAt=$createdAt, duration=$duration, fileCreatedAt=$fileCreatedAt, id=$id, isFavorite=$isFavorite, isImage=$isImage, isTrashed=$isTrashed, latitude=$latitude, livePhotoVideoId=$livePhotoVideoId, localOffsetHours=$localOffsetHours, longitude=$longitude, ownerId=$ownerId, projectionType=$projectionType, ratio=$ratio, stack=$stack, thumbhash=$thumbhash, visibility=$visibility]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'city'] = this.city;
|
||||
json[r'country'] = this.country;
|
||||
json[r'createdAt'] = this.createdAt;
|
||||
json[r'duration'] = this.duration;
|
||||
json[r'fileCreatedAt'] = this.fileCreatedAt;
|
||||
json[r'id'] = this.id;
|
||||
@@ -171,6 +178,9 @@ class TimeBucketAssetResponseDto {
|
||||
country: json[r'country'] is Iterable
|
||||
? (json[r'country'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
createdAt: json[r'createdAt'] is Iterable
|
||||
? (json[r'createdAt'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
duration: json[r'duration'] is Iterable
|
||||
? (json[r'duration'] as Iterable).cast<int>().toList(growable: false)
|
||||
: const [],
|
||||
@@ -268,6 +278,7 @@ class TimeBucketAssetResponseDto {
|
||||
static const requiredKeys = <String>{
|
||||
'city',
|
||||
'country',
|
||||
'createdAt',
|
||||
'duration',
|
||||
'fileCreatedAt',
|
||||
'id',
|
||||
|
||||
@@ -34,6 +34,7 @@ SyncAssetV1 _createAsset({
|
||||
isFavorite: false,
|
||||
fileCreatedAt: DateTime(2024, 1, 1),
|
||||
fileModifiedAt: DateTime(2024, 1, 1),
|
||||
createdAt: DateTime(2024, 1, 1),
|
||||
localDateTime: DateTime(2024, 1, 1),
|
||||
visibility: AssetVisibility.timeline,
|
||||
width: width,
|
||||
|
||||
+4
@@ -29,6 +29,7 @@ import 'schema_v22.dart' as v22;
|
||||
import 'schema_v23.dart' as v23;
|
||||
import 'schema_v24.dart' as v24;
|
||||
import 'schema_v25.dart' as v25;
|
||||
import 'schema_v26.dart' as v26;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
@@ -84,6 +85,8 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
return v24.DatabaseAtV24(db);
|
||||
case 25:
|
||||
return v25.DatabaseAtV25(db);
|
||||
case 26:
|
||||
return v26.DatabaseAtV26(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
@@ -115,5 +118,6 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
];
|
||||
}
|
||||
|
||||
+9384
File diff suppressed because it is too large
Load Diff
+1
@@ -115,6 +115,7 @@ abstract final class SyncStreamStub {
|
||||
duration: '0',
|
||||
fileCreatedAt: DateTime(2025),
|
||||
fileModifiedAt: DateTime(2025, 1, 2),
|
||||
createdAt: DateTime(2025, 1, 2),
|
||||
id: id,
|
||||
isFavorite: false,
|
||||
libraryId: null,
|
||||
|
||||
@@ -38,6 +38,7 @@ void main() {
|
||||
visibility: AssetVisibility.timeline,
|
||||
createdAt: Value(createdAt),
|
||||
updatedAt: Value(createdAt),
|
||||
uploadedAt: Value(createdAt),
|
||||
localDateTime: const Value(null),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -58,6 +58,7 @@ abstract final class TestUtils {
|
||||
type: domain.AssetType.image,
|
||||
createdAt: DateTime(2024, 1, 1),
|
||||
updatedAt: DateTime(2024, 1, 1),
|
||||
uploadedAt: DateTime(2024, 1, 1),
|
||||
durationMs: 0,
|
||||
isFavorite: false,
|
||||
width: width,
|
||||
|
||||
@@ -35,6 +35,7 @@ RemoteAsset createRemoteAsset({
|
||||
AssetType type = AssetType.image,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? uploadedAt,
|
||||
bool isFavorite = false,
|
||||
}) {
|
||||
return RemoteAsset(
|
||||
@@ -46,6 +47,7 @@ RemoteAsset createRemoteAsset({
|
||||
ownerId: 'owner-id',
|
||||
createdAt: createdAt ?? DateTime.now(),
|
||||
updatedAt: updatedAt ?? DateTime.now(),
|
||||
uploadedAt: uploadedAt ?? DateTime.now(),
|
||||
isFavorite: isFavorite,
|
||||
isEdited: false,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user