subtracks/lib/app/lists.dart
Bart Ribbers 686e0a2dba chore: upgrade to Flutter 3.24.5
At the time of writing the latest Flutter version.
2024-12-10 21:30:53 +01:00

138 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import '../services/sync_service.dart';
import 'items.dart';
import 'snackbars.dart';
class PagedListQueryView<T> extends HookConsumerWidget {
final PagingController<int, T> pagingController;
final bool refreshSyncAll;
final bool fabPadding;
final bool useSliver;
final Widget Function(BuildContext context, T item, int index) itemBuilder;
const PagedListQueryView({
super.key,
required this.pagingController,
this.refreshSyncAll = false,
this.fabPadding = true,
this.useSliver = false,
required this.itemBuilder,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final builderDelegate = PagedChildBuilderDelegate<T>(
itemBuilder: (context, item, index) => itemBuilder(context, item, index),
noMoreItemsIndicatorBuilder:
fabPadding ? (context) => const FabPadding() : null,
);
final listView = useSliver
? PagedSliverList<int, T>(
pagingController: pagingController,
builderDelegate: builderDelegate,
)
: PagedListView<int, T>(
pagingController: pagingController,
builderDelegate: builderDelegate,
);
if (refreshSyncAll) {
return SyncAllRefresh(child: listView);
} else {
return listView;
}
}
}
enum GridSize {
small,
large,
}
class PagedGridQueryView<T> extends HookConsumerWidget {
final PagingController<int, T> pagingController;
final bool refreshSyncAll;
final bool fabPadding;
final GridSize size;
final Widget Function(BuildContext context, T item, int index, GridSize size)
itemBuilder;
const PagedGridQueryView({
super.key,
required this.pagingController,
this.refreshSyncAll = false,
this.fabPadding = true,
this.size = GridSize.small,
required this.itemBuilder,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
SliverGridDelegate gridDelegate;
double spacing;
if (size == GridSize.small) {
spacing = 4;
gridDelegate = SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: spacing,
crossAxisSpacing: spacing,
);
} else {
spacing = 12;
gridDelegate = SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: spacing,
crossAxisSpacing: spacing,
);
}
final listView = PagedGridView<int, T>(
padding: MediaQuery.of(context).padding + EdgeInsets.all(spacing),
pagingController: pagingController,
builderDelegate: PagedChildBuilderDelegate(
itemBuilder: (context, item, index) =>
itemBuilder(context, item, index, size),
noMoreItemsIndicatorBuilder:
fabPadding ? (context) => const FabPadding() : null,
),
gridDelegate: gridDelegate,
showNoMoreItemsIndicatorAsGridChild: false,
);
if (refreshSyncAll) {
return SyncAllRefresh(child: listView);
} else {
return listView;
}
}
}
class SyncAllRefresh extends HookConsumerWidget {
final Widget child;
const SyncAllRefresh({
super.key,
required this.child,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
return RefreshIndicator(
onRefresh: () async {
try {
await ref.read(syncServiceProvider.notifier).syncAll();
} catch (e) {
if (!context.mounted) return;
showErrorSnackbar(context, e.toString());
}
},
child: child,
);
}
}