mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2025-12-31 07:19:31 +00:00
feat: implement library view with Authors, Genres, and Series browsing
This commit implements a comprehensive library browsing feature: - Add LibraryBrowserProvider with providers for authors, genres, and series data - Create LibraryAuthorsPage with grid view of authors including images and book counts - Create LibraryGenresPage with list view of all genres - Create LibrarySeriesPage with list view of series and book counts - Update LibraryBrowserPage navigation to route to the new views - Add routes for /browser/authors, /browser/genres, and /browser/series - Replace "Not Implemented" toasts with functional navigation The implementation uses the Audiobookshelf API via shelfsdk to fetch: - Authors list with metadata (getAuthors) - Genres from library filter data (getFilterData) - Series with pagination support (getSeries) All views follow Material Design 3 patterns and include proper loading/error states.
This commit is contained in:
parent
07aea41c6e
commit
53027bf74c
7 changed files with 485 additions and 5 deletions
79
lib/api/library_browser_provider.dart
Normal file
79
lib/api/library_browser_provider.dart
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart' show Ref;
|
||||
import 'package:logging/logging.dart' show Logger;
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:shelfsdk/audiobookshelf_api.dart'
|
||||
show Author, GetLibrarysSeriesResponse, LibraryFilterData;
|
||||
import 'package:vaani/api/api_provider.dart' show authenticatedApiProvider;
|
||||
import 'package:vaani/api/library_provider.dart' show currentLibraryProvider;
|
||||
|
||||
part 'library_browser_provider.g.dart';
|
||||
|
||||
final _logger = Logger('LibraryBrowserProvider');
|
||||
|
||||
/// Provider for fetching all authors in the current library
|
||||
@riverpod
|
||||
Future<List<Author>> libraryAuthors(Ref ref) async {
|
||||
final api = ref.watch(authenticatedApiProvider);
|
||||
final currentLibrary = await ref.watch(currentLibraryProvider.future);
|
||||
|
||||
if (currentLibrary == null) {
|
||||
_logger.warning('No current library found');
|
||||
return [];
|
||||
}
|
||||
|
||||
final authors = await api.libraries.getAuthors(libraryId: currentLibrary.id);
|
||||
|
||||
if (authors == null) {
|
||||
_logger.warning('Failed to fetch authors for library ${currentLibrary.id}');
|
||||
return [];
|
||||
}
|
||||
|
||||
_logger.fine('Fetched ${authors.length} authors');
|
||||
return authors;
|
||||
}
|
||||
|
||||
/// Provider for fetching all genres in the current library
|
||||
@riverpod
|
||||
Future<List<String>> libraryGenres(Ref ref) async {
|
||||
final api = ref.watch(authenticatedApiProvider);
|
||||
final currentLibrary = await ref.watch(currentLibraryProvider.future);
|
||||
|
||||
if (currentLibrary == null) {
|
||||
_logger.warning('No current library found');
|
||||
return [];
|
||||
}
|
||||
|
||||
final filterData = await api.libraries.getFilterData(libraryId: currentLibrary.id);
|
||||
|
||||
if (filterData == null) {
|
||||
_logger.warning('Failed to fetch filter data for library ${currentLibrary.id}');
|
||||
return [];
|
||||
}
|
||||
|
||||
_logger.fine('Fetched ${filterData.genres.length} genres');
|
||||
return filterData.genres;
|
||||
}
|
||||
|
||||
/// Provider for fetching all series in the current library
|
||||
@riverpod
|
||||
Future<GetLibrarysSeriesResponse?> librarySeries(Ref ref, {int page = 0, int limit = 50}) async {
|
||||
final api = ref.watch(authenticatedApiProvider);
|
||||
final currentLibrary = await ref.watch(currentLibraryProvider.future);
|
||||
|
||||
if (currentLibrary == null) {
|
||||
_logger.warning('No current library found');
|
||||
return null;
|
||||
}
|
||||
|
||||
final series = await api.libraries.getSeries(
|
||||
libraryId: currentLibrary.id,
|
||||
);
|
||||
|
||||
if (series == null) {
|
||||
_logger.warning('Failed to fetch series for library ${currentLibrary.id}');
|
||||
return null;
|
||||
}
|
||||
|
||||
_logger.fine('Fetched ${series.results.length} series (${series.total} total)');
|
||||
return series;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue