refresh lists on source change and sync

This commit is contained in:
austinried 2025-11-22 17:39:57 +09:00
parent 798a907cca
commit b6153ce3b6
5 changed files with 37 additions and 23 deletions

View File

@ -0,0 +1,22 @@
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../state/services.dart';
import '../state/source.dart';
void useOnSourceChange(WidgetRef ref, void Function(int sourceId) callback) {
final sourceId = ref.watch(sourceIdProvider);
useEffect(() {
callback(sourceId);
return;
}, [sourceId]);
}
void useOnSourceSync(WidgetRef ref, void Function() callback) {
final syncService = ref.watch(syncServiceProvider);
useOnListenableChange(syncService, () {
callback();
});
}

View File

@ -1,13 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import '../../sources/models.dart'; import '../../sources/models.dart';
import '../hooks/use_on_source.dart';
import '../hooks/use_paging_controller.dart'; import '../hooks/use_paging_controller.dart';
import '../state/database.dart'; import '../state/database.dart';
import '../state/source.dart';
import 'list_items.dart'; import 'list_items.dart';
const kPageSize = 60; const kPageSize = 60;
@ -18,8 +17,6 @@ class AlbumsGrid extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final db = ref.watch(databaseProvider); final db = ref.watch(databaseProvider);
final sourceId = ref.watch(sourceIdProvider);
final controller = usePagingController<int, Album>( final controller = usePagingController<int, Album>(
getNextPageKey: (state) => getNextPageKey: (state) =>
state.lastPageIsEmpty ? null : state.nextIntPageKey, state.lastPageIsEmpty ? null : state.nextIntPageKey,
@ -29,10 +26,8 @@ class AlbumsGrid extends HookConsumerWidget {
), ),
); );
useEffect(() { useOnSourceChange(ref, (_) => controller.refresh());
controller.refresh(); useOnSourceSync(ref, controller.refresh);
return;
}, [sourceId]);
return PagingListener( return PagingListener(
controller: controller, controller: controller,

View File

@ -1,28 +1,23 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import '../../sources/models.dart'; import '../../database/dao/library_dao.dart';
import '../hooks/use_on_source.dart';
import '../hooks/use_paging_controller.dart'; import '../hooks/use_paging_controller.dart';
import '../state/database.dart'; import '../state/database.dart';
import '../state/source.dart';
import 'list_items.dart'; import 'list_items.dart';
const kPageSize = 30; const kPageSize = 30;
typedef _ArtistItem = ({Artist artist, int? albumCount});
class ArtistsList extends HookConsumerWidget { class ArtistsList extends HookConsumerWidget {
const ArtistsList({super.key}); const ArtistsList({super.key});
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final db = ref.watch(databaseProvider); final db = ref.watch(databaseProvider);
final sourceId = ref.watch(sourceIdProvider); final controller = usePagingController<int, AristListItem>(
final controller = usePagingController<int, _ArtistItem>(
getNextPageKey: (state) => getNextPageKey: (state) =>
state.lastPageIsEmpty ? null : state.nextIntPageKey, state.lastPageIsEmpty ? null : state.nextIntPageKey,
fetchPage: (pageKey) => db.libraryDao.listArtists( fetchPage: (pageKey) => db.libraryDao.listArtists(
@ -31,10 +26,8 @@ class ArtistsList extends HookConsumerWidget {
), ),
); );
useEffect(() { useOnSourceChange(ref, (_) => controller.refresh());
controller.refresh(); useOnSourceSync(ref, controller.refresh);
return;
}, [sourceId]);
return PagingListener( return PagingListener(
controller: controller, controller: controller,
@ -42,7 +35,7 @@ class ArtistsList extends HookConsumerWidget {
return PagedSliverList( return PagedSliverList(
state: state, state: state,
fetchNextPage: fetchNextPage, fetchNextPage: fetchNextPage,
builderDelegate: PagedChildBuilderDelegate<_ArtistItem>( builderDelegate: PagedChildBuilderDelegate<AristListItem>(
itemBuilder: (context, item, index) { itemBuilder: (context, item, index) {
final (:artist, :albumCount) = item; final (:artist, :albumCount) = item;

View File

@ -5,6 +5,8 @@ import '../database.dart';
part 'library_dao.g.dart'; part 'library_dao.g.dart';
typedef AristListItem = ({models.Artist artist, int? albumCount});
@DriftAccessor(include: {'../tables.drift'}) @DriftAccessor(include: {'../tables.drift'})
class LibraryDao extends DatabaseAccessor<SubtracksDatabase> class LibraryDao extends DatabaseAccessor<SubtracksDatabase>
with _$LibraryDaoMixin { with _$LibraryDaoMixin {
@ -25,7 +27,7 @@ class LibraryDao extends DatabaseAccessor<SubtracksDatabase>
return query.get(); return query.get();
} }
Future<List<({models.Artist artist, int albumCount})>> listArtists({ Future<List<AristListItem>> listArtists({
required int limit, required int limit,
required int offset, required int offset,
}) async { }) async {

View File

@ -1,13 +1,14 @@
import 'package:async/async.dart'; import 'package:async/async.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:flutter/foundation.dart';
import '../database/database.dart'; import '../database/database.dart';
import '../sources/music_source.dart'; import '../sources/music_source.dart';
const kSliceSize = 200; const kSliceSize = 200;
class SyncService { class SyncService with ChangeNotifier {
SyncService({ SyncService({
required this.source, required this.source,
required this.db, required this.db,
@ -28,6 +29,7 @@ class SyncService {
syncPlaylistSongs(), syncPlaylistSongs(),
]); ]);
}); });
notifyListeners();
} }
Future<void> syncArtists() async { Future<void> syncArtists() async {