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
54 lines
1.6 KiB
Dart
54 lines
1.6 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:worldhopper/models/entry.dart';
|
|
import 'package:worldhopper/providers/feed_provider.dart';
|
|
|
|
// Request object for resolving the next entry in a series feed
|
|
class NextInSeriesRequest {
|
|
final String serverId;
|
|
final String feedUrl;
|
|
final String currentEntryId;
|
|
|
|
const NextInSeriesRequest({
|
|
required this.serverId,
|
|
required this.feedUrl,
|
|
required this.currentEntryId,
|
|
});
|
|
|
|
@override
|
|
bool operator ==(Object other) =>
|
|
identical(this, other) ||
|
|
other is NextInSeriesRequest &&
|
|
runtimeType == other.runtimeType &&
|
|
serverId == other.serverId &&
|
|
feedUrl == other.feedUrl &&
|
|
currentEntryId == other.currentEntryId;
|
|
|
|
@override
|
|
int get hashCode =>
|
|
serverId.hashCode ^ feedUrl.hashCode ^ currentEntryId.hashCode;
|
|
}
|
|
|
|
/// Provider that fetches a feed and returns the next entry after the current one.
|
|
/// Returns null if the current entry is the last in the feed or not found.
|
|
final nextInSeriesProvider = FutureProvider.family<Entry?, NextInSeriesRequest>(
|
|
(ref, request) async {
|
|
final repository = ref.watch(feedRepositoryProvider);
|
|
final feed = await repository.fetchFeed(
|
|
request.serverId,
|
|
request.feedUrl,
|
|
);
|
|
|
|
final entries = feed.entries;
|
|
for (var i = 0; i < entries.length; i++) {
|
|
if (entries[i].id == request.currentEntryId) {
|
|
if (i + 1 < entries.length) {
|
|
return entries[i + 1];
|
|
}
|
|
// TODO: If this is the last entry on a paginated page,
|
|
// fetch feed.nextLink to find the next entry.
|
|
return null;
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
);
|