1
0
mirror of https://github.com/immich-app/immich.git synced 2025-07-16 07:24:40 +02:00

feat(mobile): sqlite timeline (#19197)

* wip: timeline

* more segment extensions

* added scrubber

* refactor: timeline state

* more refactors

* fix scrubber segments

* added remote thumb & thumbhash provider

* feat: merged view

* scrub / merged asset fixes

* rename stuff & add tile indicators

* fix local album timeline query

* ignore hidden assets during sync

* ignore recovered assets during sync

* old scrubber

* add video indicator

* handle groupBy

* handle partner inTimeline

* show duration

* reduce widget nesting in thumb tile

* merge main

* chore: extend cacheExtent

* ignore touch events on scrub label when not visible

* scrub label ignore events and hide immediately

* auto reload on sync

* refactor image providers

* throttle db updates

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
shenlong
2025-06-16 20:37:45 +05:30
committed by GitHub
parent 7347f64958
commit bcda2c6e22
50 changed files with 2921 additions and 59 deletions

View File

@ -11,6 +11,7 @@ enum AssetVisibility {
class Asset extends BaseAsset {
final String id;
final String? localId;
final String? thumbHash;
final AssetVisibility visibility;
const Asset({
@ -25,9 +26,14 @@ class Asset extends BaseAsset {
super.height,
super.durationInSeconds,
super.isFavorite = false,
this.thumbHash,
this.visibility = AssetVisibility.timeline,
});
@override
AssetState get storage =>
localId == null ? AssetState.remote : AssetState.merged;
@override
String toString() {
return '''Asset {
@ -41,6 +47,7 @@ class Asset extends BaseAsset {
durationInSeconds: ${durationInSeconds ?? "<NA>"},
localId: ${localId ?? "<NA>"},
isFavorite: $isFavorite,
thumbHash: ${thumbHash ?? "<NA>"},
visibility: $visibility,
}''';
}
@ -52,10 +59,15 @@ class Asset extends BaseAsset {
return super == other &&
id == other.id &&
localId == other.localId &&
thumbHash == other.thumbHash &&
visibility == other.visibility;
}
@override
int get hashCode =>
super.hashCode ^ id.hashCode ^ localId.hashCode ^ visibility.hashCode;
super.hashCode ^
id.hashCode ^
localId.hashCode ^
thumbHash.hashCode ^
visibility.hashCode;
}

View File

@ -9,6 +9,12 @@ enum AssetType {
audio,
}
enum AssetState {
local,
remote,
merged,
}
sealed class BaseAsset {
final String name;
final String? checksum;
@ -32,6 +38,10 @@ sealed class BaseAsset {
this.isFavorite = false,
});
bool get isImage => type == AssetType.image;
bool get isVideo => type == AssetType.video;
AssetState get storage;
@override
String toString() {
return '''BaseAsset {

View File

@ -18,6 +18,10 @@ class LocalAsset extends BaseAsset {
super.isFavorite = false,
});
@override
AssetState get storage =>
remoteId == null ? AssetState.local : AssetState.merged;
@override
String toString() {
return '''LocalAsset {

View File

@ -0,0 +1,12 @@
import 'package:immich_mobile/domain/models/store.model.dart';
enum Setting<T> {
tilesPerRow<int>(StoreKey.tilesPerRow, 4),
groupAssetsBy<int>(StoreKey.groupAssetsBy, 0),
showStorageIndicator<bool>(StoreKey.storageIndicator, true);
const Setting(this.storeKey, this.defaultValue);
final StoreKey<T> storeKey;
final T defaultValue;
}

View File

@ -0,0 +1,40 @@
enum GroupAssetsBy {
day,
month,
none;
}
enum HeaderType {
none,
month,
day,
monthAndDay;
}
class Bucket {
final int assetCount;
const Bucket({required this.assetCount});
@override
bool operator ==(covariant Bucket other) {
return assetCount == other.assetCount;
}
@override
int get hashCode => assetCount.hashCode;
}
class TimeBucket extends Bucket {
final DateTime date;
const TimeBucket({required this.date, required super.assetCount});
@override
bool operator ==(covariant TimeBucket other) {
return super == other && date == other.date;
}
@override
int get hashCode => super.hashCode ^ date.hashCode;
}