feature(mobile): Hardening synchronization mechanism + Pull to refresh (#2085)

* fix(mobile): allow syncing duplicate local IDs

* enable to run isar unit tests on CI

* serialize sync operations, add pull to refresh on timeline

---------

Co-authored-by: Fynn Petersen-Frey <zoodyy@users.noreply.github.com>
This commit is contained in:
Fynn Petersen-Frey 2023-03-27 04:35:52 +02:00 committed by GitHub
parent 1a94530935
commit cae37657e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 653 additions and 249 deletions

View file

@ -17,10 +17,12 @@ class ImmichAssetGrid extends HookConsumerWidget {
final bool selectionActive;
final List<Asset> assets;
final RenderList? renderList;
final Future<void> Function()? onRefresh;
const ImmichAssetGrid({
super.key,
required this.assets,
this.onRefresh,
this.renderList,
this.assetsPerRow,
this.showStorageIndicator,
@ -62,11 +64,12 @@ class ImmichAssetGrid extends HookConsumerWidget {
enabled: enableHeroAnimations.value,
child: ImmichAssetGridView(
allAssets: assets,
assetsPerRow: assetsPerRow
?? settings.getSetting(AppSettingsEnum.tilesPerRow),
onRefresh: onRefresh,
assetsPerRow: assetsPerRow ??
settings.getSetting(AppSettingsEnum.tilesPerRow),
listener: listener,
showStorageIndicator: showStorageIndicator
?? settings.getSetting(AppSettingsEnum.storageIndicator),
showStorageIndicator: showStorageIndicator ??
settings.getSetting(AppSettingsEnum.storageIndicator),
renderList: renderList!,
margin: margin,
selectionActive: selectionActive,
@ -76,26 +79,25 @@ class ImmichAssetGrid extends HookConsumerWidget {
}
return renderListFuture.when(
data: (renderList) =>
WillPopScope(
onWillPop: onWillPop,
child: HeroMode(
enabled: enableHeroAnimations.value,
child: ImmichAssetGridView(
allAssets: assets,
assetsPerRow: assetsPerRow
?? settings.getSetting(AppSettingsEnum.tilesPerRow),
listener: listener,
showStorageIndicator: showStorageIndicator
?? settings.getSetting(AppSettingsEnum.storageIndicator),
renderList: renderList,
margin: margin,
selectionActive: selectionActive,
),
data: (renderList) => WillPopScope(
onWillPop: onWillPop,
child: HeroMode(
enabled: enableHeroAnimations.value,
child: ImmichAssetGridView(
allAssets: assets,
onRefresh: onRefresh,
assetsPerRow: assetsPerRow ??
settings.getSetting(AppSettingsEnum.tilesPerRow),
listener: listener,
showStorageIndicator: showStorageIndicator ??
settings.getSetting(AppSettingsEnum.storageIndicator),
renderList: renderList,
margin: margin,
selectionActive: selectionActive,
),
),
error: (err, stack) =>
Center(child: Text("$err")),
),
error: (err, stack) => Center(child: Text("$err")),
loading: () => const Center(
child: ImmichLoadingIndicator(),
),

View file

@ -199,21 +199,23 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
addRepaintBoundaries: true,
);
if (!useDragScrolling) {
return listWidget;
}
final child = useDragScrolling
? DraggableScrollbar.semicircle(
scrollStateListener: dragScrolling,
itemPositionsListener: _itemPositionsListener,
controller: _itemScrollController,
backgroundColor: Theme.of(context).hintColor,
labelTextBuilder: _labelBuilder,
labelConstraints: const BoxConstraints(maxHeight: 28),
scrollbarAnimationDuration: const Duration(seconds: 1),
scrollbarTimeToFade: const Duration(seconds: 4),
child: listWidget,
)
: listWidget;
return DraggableScrollbar.semicircle(
scrollStateListener: dragScrolling,
itemPositionsListener: _itemPositionsListener,
controller: _itemScrollController,
backgroundColor: Theme.of(context).hintColor,
labelTextBuilder: _labelBuilder,
labelConstraints: const BoxConstraints(maxHeight: 28),
scrollbarAnimationDuration: const Duration(seconds: 1),
scrollbarTimeToFade: const Duration(seconds: 4),
child: listWidget,
);
return widget.onRefresh == null
? child
: RefreshIndicator(onRefresh: widget.onRefresh!, child: child);
}
@override
@ -248,7 +250,7 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
}
void _scrollToTop() {
// for some reason, this is necessary as well in order
// for some reason, this is necessary as well in order
// to correctly reposition the drag thumb scroll bar
_itemScrollController.jumpTo(
index: 0,
@ -281,6 +283,7 @@ class ImmichAssetGridView extends StatefulWidget {
final ImmichAssetGridSelectionListener? listener;
final bool selectionActive;
final List<Asset> allAssets;
final Future<void> Function()? onRefresh;
const ImmichAssetGridView({
super.key,
@ -291,6 +294,7 @@ class ImmichAssetGridView extends StatefulWidget {
this.listener,
this.margin = 5.0,
this.selectionActive = false,
this.onRefresh,
});
@override