import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:worldhopper/l10n/app_localizations.dart'; import 'package:worldhopper/config/constants.dart'; import 'package:worldhopper/helpers/snackbar_helper.dart'; import 'package:worldhopper/providers/server_provider.dart'; import 'package:worldhopper/providers/connectivity_provider.dart'; import 'package:worldhopper/widgets/server_card.dart'; import 'package:worldhopper/widgets/worldhopper_app_bar.dart'; /// Screen displaying the list of configured OPDS servers class ServerListScreen extends ConsumerWidget { const ServerListScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context); final serversAsync = ref.watch(serverListProvider); return Scaffold( appBar: WorldhopperAppBar( title: Text(l10n.serverListTitle), ), body: serversAsync.when( data: (servers) { if (servers.isEmpty) { return _buildEmptyState(context, l10n); } return RefreshIndicator( onRefresh: () async { ref.invalidate(serverListProvider); }, child: ListView.builder( padding: const EdgeInsets.all(16), itemCount: servers.length, itemBuilder: (context, index) { final server = servers[index]; return ServerCard( server: server, onTap: () { // Check connectivity before browsing server final connectivityState = ref.read(connectivityStateProvider); final isOnline = connectivityState.whenOrNull( data: (online) => online, ) ?? true; if (!isOnline) { // Block navigation when offline context.showInfoSnackBar( l10n.serverListOffline, duration: const Duration(seconds: 3), ); return; } // Navigate to library browser context.push('/browse/${server.id}'); }, onEdit: () { context.push( '${AppConstants.routeEditServer}/${server.id}', ); }, onDelete: () async { final confirmed = await _confirmDelete(context, l10n, server.name); if (confirmed) { await ref .read(serverNotifierProvider.notifier) .deleteServer(server.id); if (context.mounted) { context .showInfoSnackBar(l10n.serverDeleted(server.name)); } } }, ); }, ), ); }, loading: () => const Center(child: CircularProgressIndicator()), error: (error, stack) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 48, color: Colors.red), const SizedBox(height: 16), Text(l10n.serverListErrorLoading(error.toString())), const SizedBox(height: 16), ElevatedButton( onPressed: () => ref.invalidate(serverListProvider), child: Text(l10n.serverListRetry), ), ], ), ), ), floatingActionButton: FloatingActionButton.extended( onPressed: () { context.push(AppConstants.routeAddServer); }, icon: const Icon(Icons.add), label: Text(l10n.serverListAddServer), ), ); } Widget _buildEmptyState(BuildContext context, AppLocalizations l10n) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.cloud_off, size: 100, color: Theme.of(context).colorScheme.secondary.withValues(alpha: 0.5), ), const SizedBox(height: 24), Text( l10n.serverListEmpty, style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox(height: 8), Padding( padding: const EdgeInsets.symmetric(horizontal: 32), child: Text( l10n.serverListEmptySubtitle, textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context) .colorScheme .onSurface .withValues(alpha: 0.7), ), ), ), ], ), ); } Future _confirmDelete( BuildContext context, AppLocalizations l10n, String serverName) async { final result = await showDialog( context: context, builder: (context) => AlertDialog( title: Text(l10n.serverDeleteTitle), content: Text(l10n.serverDeleteConfirmation(serverName)), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: Text(l10n.commonCancel), ), FilledButton( onPressed: () => Navigator.of(context).pop(true), style: FilledButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.error, ), child: Text(l10n.commonDelete), ), ], ), ); return result ?? false; } }