mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2025-12-21 10:29:30 +00:00
feat: enhance library selection UI with refresh functionality and error handling
This commit is contained in:
parent
90111551d0
commit
6ce4537985
3 changed files with 96 additions and 38 deletions
|
|
@ -24,6 +24,7 @@ Future<Library?> currentLibrary(Ref ref, String id) async {
|
||||||
_logger.warning('No library found in the list of libraries');
|
_logger.warning('No library found in the list of libraries');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
_logger.fine('Fetched library: ${library}');
|
||||||
return library.library;
|
return library.library;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,6 +38,7 @@ class Libraries extends _$Libraries {
|
||||||
_logger.warning('Failed to fetch libraries');
|
_logger.warning('Failed to fetch libraries');
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
_logger.fine('Fetched ${libraries.length} libraries');
|
||||||
return libraries;
|
return libraries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ part of 'library_provider.dart';
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$currentLibraryHash() => r'f37904b8b43c88a523696d1ed7acf871c3e3326f';
|
String _$currentLibraryHash() => r'1b41abb16566d91cd5961973e45bccaad7c49c9a';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|
@ -157,7 +157,7 @@ class _CurrentLibraryProviderElement
|
||||||
String get id => (origin as CurrentLibraryProvider).id;
|
String get id => (origin as CurrentLibraryProvider).id;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$librariesHash() => r'a79954d0b68a8265859c577e36d5596620a72843';
|
String _$librariesHash() => r'a57828f3b875d56db6c5815d051eca93695aefe2';
|
||||||
|
|
||||||
/// See also [Libraries].
|
/// See also [Libraries].
|
||||||
@ProviderFor(Libraries)
|
@ProviderFor(Libraries)
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,14 @@ void showLibrarySwitcher(
|
||||||
child: Scrollbar(child: content),
|
child: Scrollbar(child: content),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
// Invalidate the provider to trigger a refetch
|
||||||
|
ref.invalidate(librariesProvider);
|
||||||
|
Navigator.pop(dialogContext);
|
||||||
|
},
|
||||||
|
child: const Text('Refresh'),
|
||||||
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(dialogContext),
|
onPressed: () => Navigator.pop(dialogContext),
|
||||||
child: const Text('Cancel'),
|
child: const Text('Cancel'),
|
||||||
|
|
@ -110,6 +118,15 @@ void showLibrarySwitcher(
|
||||||
// Allow the list to take remaining space and scroll
|
// Allow the list to take remaining space and scroll
|
||||||
child: Scrollbar(child: content),
|
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 {
|
class _LibrarySelectionContent extends ConsumerWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
// Get the current library ID from the settings
|
final librariesAsyncValue = ref.watch(librariesProvider);
|
||||||
final currentLibraryId = ref.watch(
|
final currentLibraryId = ref.watch(
|
||||||
apiSettingsProvider.select(
|
apiSettingsProvider.select((settings) => settings.activeLibraryId),
|
||||||
(settings) => settings.activeLibraryId,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
// Get the list of libraries from the settings
|
final errorColor = Theme.of(context).colorScheme.error;
|
||||||
final libraries = ref.watch(librariesProvider).valueOrNull ??
|
return librariesAsyncValue.when(
|
||||||
[]; // Use null-aware operator to handle null case
|
// --- Loading State ---
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
|
||||||
// If no libraries are available, show a message
|
// --- Error State ---
|
||||||
if (libraries.isEmpty) {
|
error: (error, stackTrace) => Center(
|
||||||
return const Center(
|
child: Padding(
|
||||||
child: Text('No libraries available'),
|
padding: const EdgeInsets.all(16.0),
|
||||||
);
|
child: Column(
|
||||||
}
|
mainAxisSize: MainAxisSize.min,
|
||||||
return ListView.builder(
|
children: [
|
||||||
shrinkWrap: true, // Important for Dialog/BottomSheet sizing
|
Icon(Icons.error_outline, color: errorColor),
|
||||||
itemCount: libraries.length,
|
const SizedBox(height: 10),
|
||||||
itemBuilder: (context, index) {
|
Text(
|
||||||
final library = libraries[index];
|
'Error loading libraries: $error',
|
||||||
final bool isSelected = library.id == currentLibraryId;
|
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(
|
// --- Data State ---
|
||||||
title: Text(library.name),
|
data: (libraries) {
|
||||||
leading: Icon(AbsIcons.getIconByName(library.icon)),
|
// Handle case where data loaded successfully but is empty
|
||||||
selected: isSelected,
|
if (libraries.isEmpty) {
|
||||||
trailing: isSelected ? const Icon(Icons.check) : null,
|
return const Center(
|
||||||
onTap: () {
|
child: Padding(
|
||||||
appLogger
|
padding: EdgeInsets.all(16.0),
|
||||||
.info('Selected library: ${library.name} (ID: ${library.id})');
|
child: Text('No libraries available.'),
|
||||||
// Get current settings state
|
),
|
||||||
final currentSettings = ref.read(apiSettingsProvider);
|
);
|
||||||
// Update the active library ID
|
}
|
||||||
ref.read(apiSettingsProvider.notifier).updateState(
|
|
||||||
currentSettings.copyWith(activeLibraryId: library.id),
|
// Build the list if libraries are available
|
||||||
);
|
return Scrollbar(
|
||||||
// Close the dialog/bottom sheet
|
// Add scrollbar for potentially long lists
|
||||||
Navigator.pop(context);
|
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);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue