diff --git a/lib/api/library_provider.dart b/lib/api/library_provider.dart index a138a7a..7c796a0 100644 --- a/lib/api/library_provider.dart +++ b/lib/api/library_provider.dart @@ -24,6 +24,7 @@ Future currentLibrary(Ref ref, String id) async { _logger.warning('No library found in the list of libraries'); return null; } + _logger.fine('Fetched library: ${library}'); return library.library; } @@ -37,6 +38,7 @@ class Libraries extends _$Libraries { _logger.warning('Failed to fetch libraries'); return []; } + _logger.fine('Fetched ${libraries.length} libraries'); return libraries; } } diff --git a/lib/api/library_provider.g.dart b/lib/api/library_provider.g.dart index 3161d34..bf9dc6b 100644 --- a/lib/api/library_provider.g.dart +++ b/lib/api/library_provider.g.dart @@ -6,7 +6,7 @@ part of 'library_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$currentLibraryHash() => r'f37904b8b43c88a523696d1ed7acf871c3e3326f'; +String _$currentLibraryHash() => r'1b41abb16566d91cd5961973e45bccaad7c49c9a'; /// Copied from Dart SDK class _SystemHash { @@ -157,7 +157,7 @@ class _CurrentLibraryProviderElement String get id => (origin as CurrentLibraryProvider).id; } -String _$librariesHash() => r'a79954d0b68a8265859c577e36d5596620a72843'; +String _$librariesHash() => r'a57828f3b875d56db6c5815d051eca93695aefe2'; /// See also [Libraries]. @ProviderFor(Libraries) diff --git a/lib/features/you/view/widgets/library_switch_chip.dart b/lib/features/you/view/widgets/library_switch_chip.dart index c4ed4d0..1463b8f 100644 --- a/lib/features/you/view/widgets/library_switch_chip.dart +++ b/lib/features/you/view/widgets/library_switch_chip.dart @@ -77,6 +77,14 @@ void showLibrarySwitcher( child: Scrollbar(child: content), ), actions: [ + TextButton( + onPressed: () { + // Invalidate the provider to trigger a refetch + ref.invalidate(librariesProvider); + Navigator.pop(dialogContext); + }, + child: const Text('Refresh'), + ), TextButton( onPressed: () => Navigator.pop(dialogContext), child: const Text('Cancel'), @@ -110,6 +118,15 @@ void showLibrarySwitcher( // Allow the list to take remaining space and scroll child: Scrollbar(child: content), ), + const SizedBox(height: 10), + ElevatedButton.icon( + icon: const Icon(Icons.refresh), + label: const Text('Refresh'), + onPressed: () { + // Invalidate the provider to trigger a refetch + ref.invalidate(librariesProvider); + }, + ), ], ), ), @@ -121,46 +138,85 @@ void showLibrarySwitcher( class _LibrarySelectionContent extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - // Get the current library ID from the settings + final librariesAsyncValue = ref.watch(librariesProvider); final currentLibraryId = ref.watch( - apiSettingsProvider.select( - (settings) => settings.activeLibraryId, - ), + apiSettingsProvider.select((settings) => settings.activeLibraryId), ); - // Get the list of libraries from the settings - final libraries = ref.watch(librariesProvider).valueOrNull ?? - []; // Use null-aware operator to handle null case + final errorColor = Theme.of(context).colorScheme.error; + return librariesAsyncValue.when( + // --- Loading State --- + loading: () => const Center(child: CircularProgressIndicator()), - // If no libraries are available, show a message - if (libraries.isEmpty) { - return const Center( - child: Text('No libraries available'), - ); - } - return ListView.builder( - shrinkWrap: true, // Important for Dialog/BottomSheet sizing - itemCount: libraries.length, - itemBuilder: (context, index) { - final library = libraries[index]; - final bool isSelected = library.id == currentLibraryId; + // --- Error State --- + error: (error, stackTrace) => Center( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.error_outline, color: errorColor), + const SizedBox(height: 10), + Text( + 'Error loading libraries: $error', + textAlign: TextAlign.center, + style: TextStyle(color: errorColor), + ), + const SizedBox(height: 16), + ElevatedButton.icon( + icon: const Icon(Icons.refresh), + label: const Text('Retry'), + onPressed: () { + // Invalidate the provider to trigger a refetch + ref.invalidate(librariesProvider); + }, + ), + ], + ), + ), + ), - return ListTile( - title: Text(library.name), - leading: Icon(AbsIcons.getIconByName(library.icon)), - selected: isSelected, - trailing: isSelected ? const Icon(Icons.check) : null, - onTap: () { - appLogger - .info('Selected library: ${library.name} (ID: ${library.id})'); - // Get current settings state - final currentSettings = ref.read(apiSettingsProvider); - // Update the active library ID - ref.read(apiSettingsProvider.notifier).updateState( - currentSettings.copyWith(activeLibraryId: library.id), - ); - // Close the dialog/bottom sheet - Navigator.pop(context); - }, + // --- Data State --- + data: (libraries) { + // Handle case where data loaded successfully but is empty + if (libraries.isEmpty) { + return const Center( + child: Padding( + padding: EdgeInsets.all(16.0), + child: Text('No libraries available.'), + ), + ); + } + + // Build the list if libraries are available + return Scrollbar( + // Add scrollbar for potentially long lists + child: ListView.builder( + shrinkWrap: true, // Important for Dialog/BottomSheet sizing + itemCount: libraries.length, + itemBuilder: (context, index) { + final library = libraries[index]; + final bool isSelected = library.id == currentLibraryId; + + return ListTile( + title: Text(library.name), + leading: Icon(AbsIcons.getIconByName(library.icon)), + selected: isSelected, + trailing: isSelected ? const Icon(Icons.check) : null, + onTap: () { + appLogger.info( + 'Selected library: ${library.name} (ID: ${library.id})'); + // Get current settings state + final currentSettings = ref.read(apiSettingsProvider); + // Update the active library ID + ref.read(apiSettingsProvider.notifier).updateState( + currentSettings.copyWith(activeLibraryId: library.id), + ); + // Close the dialog/bottom sheet + Navigator.pop(context); + }, + ); + }, + ), ); }, );