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
50 lines
1.5 KiB
Dart
50 lines
1.5 KiB
Dart
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
|
|
part 'stream_link.freezed.dart';
|
|
part 'stream_link.g.dart';
|
|
|
|
/// Represents an OPDS-PSE stream link for page-by-page reading
|
|
@freezed
|
|
class StreamLink with _$StreamLink {
|
|
const factory StreamLink({
|
|
/// URL template with {pageNumber} and optionally {maxWidth} placeholders
|
|
/// This should be an absolute URL (resolved against server base URL during parsing)
|
|
required String href,
|
|
|
|
/// Image MIME type (image/jpeg, image/png, image/gif)
|
|
required String type,
|
|
|
|
/// Total number of pages
|
|
required int pageCount,
|
|
|
|
/// Last read page (0-indexed), null if never read
|
|
int? lastRead,
|
|
|
|
/// Last read timestamp
|
|
DateTime? lastReadDate,
|
|
}) = _StreamLink;
|
|
|
|
const StreamLink._();
|
|
|
|
/// Create StreamLink from JSON
|
|
factory StreamLink.fromJson(Map<String, dynamic> json) =>
|
|
_$StreamLinkFromJson(json);
|
|
|
|
/// Check if the URL template supports maxWidth parameter
|
|
bool get supportsMaxWidth => href.contains('{maxWidth}');
|
|
|
|
/// Generate the URL for a specific page
|
|
String getPageUrl(int pageNumber, {int? maxWidth}) {
|
|
var url = href.replaceAll('{pageNumber}', pageNumber.toString());
|
|
|
|
if (supportsMaxWidth && maxWidth != null) {
|
|
url = url.replaceAll('{maxWidth}', maxWidth.toString());
|
|
} else if (supportsMaxWidth) {
|
|
// Remove maxWidth parameter if not provided
|
|
url = url.replaceAll(RegExp(r'[?&]maxWidth=\{maxWidth\}'), '');
|
|
url = url.replaceAll(RegExp(r'[?&]size=\{maxWidth\}'), '');
|
|
}
|
|
|
|
return url;
|
|
}
|
|
}
|