fix: add series sequence sorting and debug metadata variants

Series sorting fix:
- Detect SeriesFilter and use 'sequence' sort parameter
- Other filters (author/genre) continue using alphabetical title sort
- Books in series now display in proper sequence order

Series metadata debugging:
- Add logging to show media and metadata variants for each item
- Add bookSeriesFilter metadata variant handlers
- Log extracted title and author for debugging
- This will help identify why series-filtered books show no info

The logging will show what metadata structure the API returns for
series-filtered items so we can properly extract title/author data.
This commit is contained in:
Claude 2025-11-20 21:47:46 +00:00
parent a1844c225c
commit 7d2877c1bb
No known key found for this signature in database

View file

@ -2,12 +2,15 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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:logging/logging.dart';
import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:shelfsdk/audiobookshelf_api.dart';
import 'package:vaani/api/api_provider.dart'; import 'package:vaani/api/api_provider.dart';
import 'package:vaani/api/library_provider.dart'; import 'package:vaani/api/library_provider.dart';
import 'package:vaani/router/router.dart'; import 'package:vaani/router/router.dart';
import 'package:vaani/settings/api_settings_provider.dart'; import 'package:vaani/settings/api_settings_provider.dart';
final _logger = Logger('FilteredLibraryItemsPage');
/// Page that displays library items filtered by author, genre, or series /// Page that displays library items filtered by author, genre, or series
class FilteredLibraryItemsPage extends HookConsumerWidget { class FilteredLibraryItemsPage extends HookConsumerWidget {
const FilteredLibraryItemsPage({ const FilteredLibraryItemsPage({
@ -36,12 +39,17 @@ class FilteredLibraryItemsPage extends HookConsumerWidget {
); );
} }
// Determine sort parameter based on filter type
final sortParam = filter is SeriesFilter
? 'sequence' // Sort by series sequence number
: 'media.metadata.title'; // Sort alphabetically by title
return FutureBuilder<GetLibrarysItemsResponse?>( return FutureBuilder<GetLibrarysItemsResponse?>(
future: api.libraries.getItems( future: api.libraries.getItems(
libraryId: library.id, libraryId: library.id,
parameters: GetLibrarysItemsReqParams( parameters: GetLibrarysItemsReqParams(
filter: filter, filter: filter,
sort: 'media.metadata.title', sort: sortParam,
limit: 100, limit: 100,
), ),
), ),
@ -114,6 +122,9 @@ class LibraryItemCard extends ConsumerWidget {
final apiSettings = ref.watch(apiSettingsProvider); final apiSettings = ref.watch(apiSettingsProvider);
final media = item.media; final media = item.media;
// Log media variant for debugging
_logger.info('Item ${item.id}: Media variant = ${media.variant}');
// Extract book info // Extract book info
String title = ''; String title = '';
String? authorName; String? authorName;
@ -122,6 +133,7 @@ class LibraryItemCard extends ConsumerWidget {
media.mapOrNull( media.mapOrNull(
book: (book) { book: (book) {
final metadata = book.metadata; final metadata = book.metadata;
_logger.info(' Metadata variant = ${metadata.variant}');
metadata.mapOrNull( metadata.mapOrNull(
book: (m) { book: (m) {
title = m.title ?? 'Unknown'; title = m.title ?? 'Unknown';
@ -139,10 +151,18 @@ class LibraryItemCard extends ConsumerWidget {
authorName = m.authors.map((a) => a.name).join(', '); authorName = m.authors.map((a) => a.name).join(', ');
} }
}, },
bookSeriesFilter: (m) {
_logger.info(' Found bookSeriesFilter metadata variant!');
title = m.title ?? 'Unknown';
if (m.authors.isNotEmpty) {
authorName = m.authors.map((a) => a.name).join(', ');
}
},
); );
}, },
bookMinified: (book) { bookMinified: (book) {
final metadata = book.metadata; final metadata = book.metadata;
_logger.info(' Metadata variant = ${metadata.variant}');
metadata.mapOrNull( metadata.mapOrNull(
book: (m) { book: (m) {
title = m.title ?? 'Unknown'; title = m.title ?? 'Unknown';
@ -160,10 +180,18 @@ class LibraryItemCard extends ConsumerWidget {
authorName = m.authors.map((a) => a.name).join(', '); authorName = m.authors.map((a) => a.name).join(', ');
} }
}, },
bookSeriesFilter: (m) {
_logger.info(' Found bookSeriesFilter metadata variant!');
title = m.title ?? 'Unknown';
if (m.authors.isNotEmpty) {
authorName = m.authors.map((a) => a.name).join(', ');
}
},
); );
}, },
bookExpanded: (book) { bookExpanded: (book) {
final metadata = book.metadata; final metadata = book.metadata;
_logger.info(' Metadata variant = ${metadata.variant}');
metadata.mapOrNull( metadata.mapOrNull(
book: (m) { book: (m) {
title = m.title ?? 'Unknown'; title = m.title ?? 'Unknown';
@ -181,10 +209,19 @@ class LibraryItemCard extends ConsumerWidget {
authorName = m.authors.map((a) => a.name).join(', '); authorName = m.authors.map((a) => a.name).join(', ');
} }
}, },
bookSeriesFilter: (m) {
_logger.info(' Found bookSeriesFilter metadata variant!');
title = m.title ?? 'Unknown';
if (m.authors.isNotEmpty) {
authorName = m.authors.map((a) => a.name).join(', ');
}
},
); );
}, },
); );
_logger.info(' Extracted: title="$title", author="$authorName"');
final imageUrl = apiSettings.activeServer != null final imageUrl = apiSettings.activeServer != null
? '${apiSettings.activeServer!.serverUrl}/api/items/${item.id}/cover' ? '${apiSettings.activeServer!.serverUrl}/api/items/${item.id}/cover'
: null; : null;