feat(mobile): lazy loading of assets (#2413)

This commit is contained in:
Fynn Petersen-Frey 2023-05-17 19:36:02 +02:00 committed by GitHub
parent 93863b0629
commit 0dde76bbbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 1494 additions and 2328 deletions

View file

@ -1,46 +1,25 @@
import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/archive/providers/archive_asset_provider.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/providers/asset.provider.dart';
import 'package:immich_mobile/shared/providers/db.provider.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
import 'package:immich_mobile/shared/ui/immich_toast.dart';
import 'package:isar/isar.dart';
class ArchivePage extends HookConsumerWidget {
const ArchivePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final User me = Store.get(StoreKey.currentUser);
final query = ref
.watch(dbProvider)
.assets
.filter()
.ownerIdEqualTo(me.isarId)
.isArchivedEqualTo(true);
final stream = query.watch();
final archivedAssets = useState<List<Asset>>([]);
final archivedAssets = ref.watch(archiveProvider);
final selectionEnabledHook = useState(false);
final selection = useState(<Asset>{});
useEffect(
() {
query.findAll().then((value) => archivedAssets.value = value);
final subscription = stream.listen((e) {
archivedAssets.value = e;
});
// Cancel the subscription when the widget is disposed
return subscription.cancel;
},
[],
);
final processing = useState(false);
void selectionListener(
bool multiselect,
@ -50,7 +29,7 @@ class ArchivePage extends HookConsumerWidget {
selection.value = selectedAssets;
}
AppBar buildAppBar() {
AppBar buildAppBar(String count) {
return AppBar(
leading: IconButton(
onPressed: () => AutoRouter.of(context).pop(),
@ -60,7 +39,7 @@ class ArchivePage extends HookConsumerWidget {
automaticallyImplyLeading: false,
title: const Text(
'archive_page_title',
).tr(args: [archivedAssets.value.length.toString()]),
).tr(args: [count]),
);
}
@ -84,24 +63,34 @@ class ArchivePage extends HookConsumerWidget {
'control_bottom_app_bar_unarchive'.tr(),
style: const TextStyle(fontSize: 14),
),
onTap: () {
if (selection.value.isNotEmpty) {
ref
.watch(assetProvider.notifier)
.toggleArchive(selection.value, false);
onTap: processing.value
? null
: () async {
processing.value = true;
try {
if (selection.value.isNotEmpty) {
await ref
.watch(assetProvider.notifier)
.toggleArchive(
selection.value.toList(),
false,
);
final assetOrAssets =
selection.value.length > 1 ? 'assets' : 'asset';
ImmichToast.show(
context: context,
msg:
'Moved ${selection.value.length} $assetOrAssets to library',
gravity: ToastGravity.CENTER,
);
}
selectionEnabledHook.value = false;
},
final assetOrAssets = selection.value.length > 1
? 'assets'
: 'asset';
ImmichToast.show(
context: context,
msg:
'Moved ${selection.value.length} $assetOrAssets to library',
gravity: ToastGravity.CENTER,
);
}
} finally {
processing.value = false;
selectionEnabledHook.value = false;
}
},
)
],
),
@ -111,22 +100,34 @@ class ArchivePage extends HookConsumerWidget {
);
}
return Scaffold(
appBar: buildAppBar(),
body: archivedAssets.value.isEmpty
? Center(
child: Text('archive_page_no_archived_assets'.tr()),
)
: Stack(
children: [
ImmichAssetGrid(
assets: archivedAssets.value,
listener: selectionListener,
selectionActive: selectionEnabledHook.value,
),
if (selectionEnabledHook.value) buildBottomBar()
],
),
return archivedAssets.when(
loading: () => Scaffold(
appBar: buildAppBar("?"),
body: const Center(child: CircularProgressIndicator()),
),
error: (error, stackTrace) => Scaffold(
appBar: buildAppBar("Error"),
body: Center(child: Text(error.toString())),
),
data: (data) => Scaffold(
appBar: buildAppBar(data.totalAssets.toString()),
body: data.isEmpty
? Center(
child: Text('archive_page_no_archived_assets'.tr()),
)
: Stack(
children: [
ImmichAssetGrid(
renderList: data,
listener: selectionListener,
selectionActive: selectionEnabledHook.value,
),
if (selectionEnabledHook.value) buildBottomBar(),
if (processing.value)
const Center(child: ImmichLoadingIndicator())
],
),
),
);
}
}