Rename all OPDS-prefixed models to generic names (Server, Feed, Entry, Link, StreamLink), expand the ServerSoftware interface to cover all server interactions, and implement a full Kavita REST API client that replaces the OPDS delegation. - Rename OPDS* models to generic names across ~60 files - Add database migrations 13 (opds_id → entry_id) and 14 (unify credentials) - Create OPDSServerSoftware wrapping existing OPDS services - Create KavitaApiClient for direct Kavita REST API calls - Create KavitaFeedMapper to convert Kavita JSON to Feed/Entry models - Rewrite KavitaServerSoftware to use native API (no OPDS delegation) - Unify server credentials (remove softwareUsername/softwarePassword) - Simplify add/edit server UI to single auth section - Add test connection button to server add/edit screens - Add progress indicator to PublicationCard using local and server data - Eliminate softwareType branching in reader screens - Add EntryProgress and fetchEntryProgress to ServerSoftware interface - Fix Entry.acquisitionLink crash on empty links - Add 59 new tests covering models, services, and providers
77 lines
2.4 KiB
Dart
77 lines
2.4 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:worldhopper/models/server.dart';
|
|
import 'package:worldhopper/repositories/server_repository.dart';
|
|
|
|
/// Provider for ServerRepository instance
|
|
final serverRepositoryProvider = Provider<ServerRepository>((ref) {
|
|
return ServerRepository();
|
|
});
|
|
|
|
/// Provider for the list of all servers
|
|
final serverListProvider = StreamProvider<List<Server>>((ref) async* {
|
|
final repository = ref.watch(serverRepositoryProvider);
|
|
|
|
// Initial load
|
|
yield await repository.getAllServers();
|
|
|
|
// We'll use a simple polling mechanism for now
|
|
// In a production app, you might want to use a more sophisticated approach
|
|
await for (final _ in Stream.periodic(const Duration(seconds: 1))) {
|
|
yield await repository.getAllServers();
|
|
}
|
|
});
|
|
|
|
/// Provider for a single server by ID
|
|
final serverProvider = FutureProvider.family<Server?, String>((ref, id) async {
|
|
final repository = ref.watch(serverRepositoryProvider);
|
|
return await repository.getServer(id);
|
|
});
|
|
|
|
/// Provider for server count
|
|
final serverCountProvider = FutureProvider<int>((ref) async {
|
|
final repository = ref.watch(serverRepositoryProvider);
|
|
return await repository.getServerCount();
|
|
});
|
|
|
|
/// Notifier for managing server operations
|
|
class ServerNotifier extends StateNotifier<AsyncValue<void>> {
|
|
final ServerRepository _repository;
|
|
|
|
ServerNotifier(this._repository) : super(const AsyncValue.data(null));
|
|
|
|
/// Add a new server
|
|
Future<void> addServer(Server server) async {
|
|
state = const AsyncValue.loading();
|
|
state = await AsyncValue.guard(() async {
|
|
await _repository.addServer(server);
|
|
});
|
|
}
|
|
|
|
/// Update an existing server
|
|
Future<void> updateServer(Server server) async {
|
|
state = const AsyncValue.loading();
|
|
state = await AsyncValue.guard(() async {
|
|
await _repository.updateServer(server);
|
|
});
|
|
}
|
|
|
|
/// Delete a server
|
|
Future<void> deleteServer(String id) async {
|
|
state = const AsyncValue.loading();
|
|
state = await AsyncValue.guard(() async {
|
|
await _repository.deleteServer(id);
|
|
});
|
|
}
|
|
|
|
/// Check if server exists
|
|
Future<bool> serverExists(String url) async {
|
|
return await _repository.serverExists(url);
|
|
}
|
|
}
|
|
|
|
/// Provider for ServerNotifier
|
|
final serverNotifierProvider =
|
|
StateNotifierProvider<ServerNotifier, AsyncValue<void>>((ref) {
|
|
final repository = ref.watch(serverRepositoryProvider);
|
|
return ServerNotifier(repository);
|
|
});
|