mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
fix(mobile): load local thumbnails in album timeline (#22329)
* join local asset in album query * missed one * formatting
This commit is contained in:
parent
c5fbbee8f6
commit
5116b215a2
3 changed files with 34 additions and 36 deletions
|
|
@ -21,7 +21,7 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LocalAssetEntityDataDomainExtension on LocalAssetEntityData {
|
extension LocalAssetEntityDataDomainExtension on LocalAssetEntityData {
|
||||||
LocalAsset toDto() => LocalAsset(
|
LocalAsset toDto({String? remoteId}) => LocalAsset(
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
checksum: checksum,
|
checksum: checksum,
|
||||||
|
|
@ -32,7 +32,7 @@ extension LocalAssetEntityDataDomainExtension on LocalAssetEntityData {
|
||||||
isFavorite: isFavorite,
|
isFavorite: isFavorite,
|
||||||
height: height,
|
height: height,
|
||||||
width: width,
|
width: width,
|
||||||
remoteId: null,
|
remoteId: remoteId,
|
||||||
orientation: orientation,
|
orientation: orientation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class RemoteAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin
|
||||||
}
|
}
|
||||||
|
|
||||||
extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData {
|
extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData {
|
||||||
RemoteAsset toDto() => RemoteAsset(
|
RemoteAsset toDto({String? localId}) => RemoteAsset(
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
ownerId: ownerId,
|
ownerId: ownerId,
|
||||||
|
|
@ -64,7 +64,7 @@ extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData {
|
||||||
thumbHash: thumbHash,
|
thumbHash: thumbHash,
|
||||||
visibility: visibility,
|
visibility: visibility,
|
||||||
livePhotoVideoId: livePhotoVideoId,
|
livePhotoVideoId: livePhotoVideoId,
|
||||||
localId: null,
|
localId: localId,
|
||||||
stackId: stackId,
|
stackId: stackId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,10 +148,9 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
..orderBy([OrderingTerm.desc(_db.localAssetEntity.createdAt)])
|
..orderBy([OrderingTerm.desc(_db.localAssetEntity.createdAt)])
|
||||||
..limit(count, offset: offset);
|
..limit(count, offset: offset);
|
||||||
|
|
||||||
return query.map((row) {
|
return query
|
||||||
final asset = row.readTable(_db.localAssetEntity).toDto();
|
.map((row) => row.readTable(_db.localAssetEntity).toDto(remoteId: row.read(_db.remoteAssetEntity.id)))
|
||||||
return asset.copyWith(remoteId: row.read(_db.remoteAssetEntity.id));
|
.get();
|
||||||
}).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineQuery remoteAlbum(String albumId, GroupAssetsBy groupBy) => (
|
TimelineQuery remoteAlbum(String albumId, GroupAssetsBy groupBy) => (
|
||||||
|
|
@ -165,17 +164,15 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
.count(where: (row) => row.albumId.equals(albumId))
|
.count(where: (row) => row.albumId.equals(albumId))
|
||||||
.map(_generateBuckets)
|
.map(_generateBuckets)
|
||||||
.watch()
|
.watch()
|
||||||
.map((results) => results.isNotEmpty ? results.first : <Bucket>[])
|
.map((results) => results.isNotEmpty ? results.first : const <Bucket>[])
|
||||||
.handleError((error) {
|
.handleError((error) => const <Bucket>[]);
|
||||||
return [];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId)))
|
return (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId)))
|
||||||
.watch()
|
.watch()
|
||||||
.switchMap((albums) {
|
.switchMap((albums) {
|
||||||
if (albums.isEmpty) {
|
if (albums.isEmpty) {
|
||||||
return Stream.value(<Bucket>[]);
|
return Stream.value(const <Bucket>[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
final album = albums.first;
|
final album = albums.first;
|
||||||
|
|
@ -207,10 +204,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
return TimeBucket(date: timeline, assetCount: assetCount);
|
return TimeBucket(date: timeline, assetCount: assetCount);
|
||||||
}).watch();
|
}).watch();
|
||||||
})
|
})
|
||||||
.handleError((error) {
|
// If there's an error (e.g., album was deleted), return empty buckets
|
||||||
// If there's an error (e.g., album was deleted), return empty buckets
|
.handleError((error) => const <Bucket>[]);
|
||||||
return <Bucket>[];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<BaseAsset>> _getRemoteAlbumBucketAssets(String albumId, {required int offset, required int count}) async {
|
Future<List<BaseAsset>> _getRemoteAlbumBucketAssets(String albumId, {required int offset, required int count}) async {
|
||||||
|
|
@ -218,18 +213,23 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
// If album doesn't exist (was deleted), return empty list
|
// If album doesn't exist (was deleted), return empty list
|
||||||
if (albumData == null) {
|
if (albumData == null) {
|
||||||
return <BaseAsset>[];
|
return const <BaseAsset>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
final isAscending = albumData.order == AlbumAssetOrder.asc;
|
final isAscending = albumData.order == AlbumAssetOrder.asc;
|
||||||
|
|
||||||
final query = _db.remoteAssetEntity.select().join([
|
final query = _db.remoteAssetEntity.select().addColumns([_db.localAssetEntity.id]).join([
|
||||||
innerJoin(
|
innerJoin(
|
||||||
_db.remoteAlbumAssetEntity,
|
_db.remoteAlbumAssetEntity,
|
||||||
_db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id),
|
_db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id),
|
||||||
useColumns: false,
|
useColumns: false,
|
||||||
),
|
),
|
||||||
])..where(_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId));
|
leftOuterJoin(
|
||||||
|
_db.localAssetEntity,
|
||||||
|
_db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum),
|
||||||
|
useColumns: false,
|
||||||
|
),
|
||||||
|
])..where(_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAssetEntity.id.equals(albumId));
|
||||||
|
|
||||||
if (isAscending) {
|
if (isAscending) {
|
||||||
query.orderBy([OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]);
|
query.orderBy([OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]);
|
||||||
|
|
@ -239,12 +239,14 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
|
|
||||||
query.limit(count, offset: offset);
|
query.limit(count, offset: offset);
|
||||||
|
|
||||||
return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get();
|
return query
|
||||||
|
.map((row) => row.readTable(_db.remoteAssetEntity).toDto(localId: row.read(_db.localAssetEntity.id)))
|
||||||
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineQuery fromAssets(List<BaseAsset> assets) => (
|
TimelineQuery fromAssets(List<BaseAsset> assets) => (
|
||||||
bucketSource: () => Stream.value(_generateBuckets(assets.length)),
|
bucketSource: () => Stream.value(_generateBuckets(assets.length)),
|
||||||
assetSource: (offset, count) => Future.value(assets.skip(offset).take(count).toList()),
|
assetSource: (offset, count) => Future.value(assets.skip(offset).take(count).toList(growable: false)),
|
||||||
);
|
);
|
||||||
|
|
||||||
TimelineQuery remote(String ownerId, GroupAssetsBy groupBy) => _remoteQueryBuilder(
|
TimelineQuery remote(String ownerId, GroupAssetsBy groupBy) => _remoteQueryBuilder(
|
||||||
|
|
@ -486,6 +488,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get();
|
return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
TimelineQuery _remoteQueryBuilder({
|
TimelineQuery _remoteQueryBuilder({
|
||||||
required Expression<bool> Function($RemoteAssetEntityTable row) filter,
|
required Expression<bool> Function($RemoteAssetEntityTable row) filter,
|
||||||
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
GroupAssetsBy groupBy = GroupAssetsBy.day,
|
||||||
|
|
@ -523,6 +526,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
}).watch();
|
}).watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
Future<List<BaseAsset>> _getRemoteAssets({
|
Future<List<BaseAsset>> _getRemoteAssets({
|
||||||
required Expression<bool> Function($RemoteAssetEntityTable row) filter,
|
required Expression<bool> Function($RemoteAssetEntityTable row) filter,
|
||||||
required int offset,
|
required int offset,
|
||||||
|
|
@ -543,11 +547,9 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
..orderBy([OrderingTerm.desc(_db.remoteAssetEntity.createdAt)])
|
..orderBy([OrderingTerm.desc(_db.remoteAssetEntity.createdAt)])
|
||||||
..limit(count, offset: offset);
|
..limit(count, offset: offset);
|
||||||
|
|
||||||
return query.map((row) {
|
return query
|
||||||
final asset = row.readTable(_db.remoteAssetEntity).toDto();
|
.map((row) => row.readTable(_db.remoteAssetEntity).toDto(localId: row.read(_db.localAssetEntity.id)))
|
||||||
final localId = row.read(_db.localAssetEntity.id);
|
.get();
|
||||||
return asset.copyWith(localId: localId);
|
|
||||||
}).get();
|
|
||||||
} else {
|
} else {
|
||||||
final query = _db.remoteAssetEntity.select()
|
final query = _db.remoteAssetEntity.select()
|
||||||
..where(filter)
|
..where(filter)
|
||||||
|
|
@ -560,12 +562,12 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Bucket> _generateBuckets(int count) {
|
List<Bucket> _generateBuckets(int count) {
|
||||||
final buckets = List.generate(
|
final buckets = List.filled(
|
||||||
(count / kTimelineNoneSegmentSize).floor(),
|
(count / kTimelineNoneSegmentSize).ceil(),
|
||||||
(_) => const Bucket(assetCount: kTimelineNoneSegmentSize),
|
const Bucket(assetCount: kTimelineNoneSegmentSize),
|
||||||
);
|
);
|
||||||
if (count % kTimelineNoneSegmentSize != 0) {
|
if (count % kTimelineNoneSegmentSize != 0) {
|
||||||
buckets.add(Bucket(assetCount: count % kTimelineNoneSegmentSize));
|
buckets[buckets.length - 1] = Bucket(assetCount: count % kTimelineNoneSegmentSize);
|
||||||
}
|
}
|
||||||
return buckets;
|
return buckets;
|
||||||
}
|
}
|
||||||
|
|
@ -590,10 +592,6 @@ extension on String {
|
||||||
GroupAssetsBy.month => "y-M",
|
GroupAssetsBy.month => "y-M",
|
||||||
GroupAssetsBy.none => throw ArgumentError("GroupAssetsBy.none is not supported for date formatting"),
|
GroupAssetsBy.none => throw ArgumentError("GroupAssetsBy.none is not supported for date formatting"),
|
||||||
};
|
};
|
||||||
try {
|
return DateFormat(format, 'en').parse(this);
|
||||||
return DateFormat(format, 'en').parse(this);
|
|
||||||
} catch (e) {
|
|
||||||
throw FormatException("Invalid date format: $this", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue