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
113 lines
3.3 KiB
Dart
113 lines
3.3 KiB
Dart
import 'package:sqflite/sqflite.dart';
|
|
import 'package:worldhopper/database/database.dart';
|
|
import 'package:worldhopper/database/tables/publications_table.dart';
|
|
import 'package:worldhopper/models/publication.dart';
|
|
|
|
/// Repository for publication cache operations
|
|
class PublicationRepository {
|
|
final DatabaseHelper _dbHelper;
|
|
|
|
PublicationRepository(this._dbHelper);
|
|
|
|
/// Get publication by server and entry ID
|
|
Future<Publication?> getPublication(String serverId, String entryId) async {
|
|
final db = await _dbHelper.database;
|
|
final results = await db.query(
|
|
PublicationsTable.tableName,
|
|
where: 'server_id = ? AND entry_id = ?',
|
|
whereArgs: [serverId, entryId],
|
|
);
|
|
|
|
if (results.isEmpty) return null;
|
|
return Publication.fromDatabase(results.first);
|
|
}
|
|
|
|
/// Get publication by cache ID
|
|
Future<Publication?> getPublicationById(String id) async {
|
|
final db = await _dbHelper.database;
|
|
final results = await db.query(
|
|
PublicationsTable.tableName,
|
|
where: 'id = ?',
|
|
whereArgs: [id],
|
|
);
|
|
|
|
if (results.isEmpty) return null;
|
|
return Publication.fromDatabase(results.first);
|
|
}
|
|
|
|
/// Save or update publication
|
|
Future<void> savePublication(Publication publication) async {
|
|
final db = await _dbHelper.database;
|
|
await db.insert(
|
|
PublicationsTable.tableName,
|
|
publication.toDatabase(),
|
|
conflictAlgorithm: ConflictAlgorithm.replace,
|
|
);
|
|
}
|
|
|
|
/// Update last accessed timestamp
|
|
Future<void> updateLastAccessed(String id) async {
|
|
final db = await _dbHelper.database;
|
|
await db.update(
|
|
PublicationsTable.tableName,
|
|
{'last_accessed_at': DateTime.now().millisecondsSinceEpoch},
|
|
where: 'id = ?',
|
|
whereArgs: [id],
|
|
);
|
|
}
|
|
|
|
/// Get publications for a server
|
|
Future<List<Publication>> getPublicationsByServer(String serverId) async {
|
|
final db = await _dbHelper.database;
|
|
final results = await db.query(
|
|
PublicationsTable.tableName,
|
|
where: 'server_id = ?',
|
|
whereArgs: [serverId],
|
|
orderBy: 'last_accessed_at DESC',
|
|
);
|
|
|
|
return results.map((row) => Publication.fromDatabase(row)).toList();
|
|
}
|
|
|
|
/// Get stale publications (not accessed recently and old)
|
|
Future<List<Publication>> getStalePublications({
|
|
int notAccessedDays = 60,
|
|
int olderThanDays = 30,
|
|
}) async {
|
|
final db = await _dbHelper.database;
|
|
final notAccessedDate = DateTime.now()
|
|
.subtract(Duration(days: notAccessedDays))
|
|
.millisecondsSinceEpoch;
|
|
final olderThanDate = DateTime.now()
|
|
.subtract(Duration(days: olderThanDays))
|
|
.millisecondsSinceEpoch;
|
|
|
|
final results = await db.query(
|
|
PublicationsTable.tableName,
|
|
where: 'last_accessed_at < ? AND last_cached_at < ?',
|
|
whereArgs: [notAccessedDate, olderThanDate],
|
|
);
|
|
|
|
return results.map((row) => Publication.fromDatabase(row)).toList();
|
|
}
|
|
|
|
/// Delete publication
|
|
Future<void> deletePublication(String id) async {
|
|
final db = await _dbHelper.database;
|
|
await db.delete(
|
|
PublicationsTable.tableName,
|
|
where: 'id = ?',
|
|
whereArgs: [id],
|
|
);
|
|
}
|
|
|
|
/// Delete publications for a server
|
|
Future<void> deletePublicationsByServer(String serverId) async {
|
|
final db = await _dbHelper.database;
|
|
await db.delete(
|
|
PublicationsTable.tableName,
|
|
where: 'server_id = ?',
|
|
whereArgs: [serverId],
|
|
);
|
|
}
|
|
}
|