feat: store subscription posts with a read mark and split the library controller
This commit is contained in:
parent
b311b9f7dd
commit
953ae798eb
15 changed files with 1787 additions and 386 deletions
|
|
@ -2,7 +2,9 @@ import 'package:drift/drift.dart' show Value;
|
|||
import 'package:drift/native.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:mews/application/controllers/bookmarks_controller.dart';
|
||||
import 'package:mews/application/controllers/reader_settings_controller.dart';
|
||||
import 'package:mews/application/controllers/subscriptions_controller.dart';
|
||||
import 'package:mews/database/database.dart';
|
||||
import 'package:mews/mews/document.dart';
|
||||
|
||||
|
|
@ -45,44 +47,89 @@ void main() {
|
|||
});
|
||||
|
||||
test('bookmarks toggle and persist', () async {
|
||||
final library = LibraryController(db);
|
||||
await library.load();
|
||||
await library.toggleBookmark('https://example.com/', 'Example');
|
||||
expect(library.isBookmarked('https://example.com/'), isTrue);
|
||||
final bookmarks = BookmarksController(db);
|
||||
await bookmarks.load();
|
||||
await bookmarks.toggle('https://example.com/', 'Example');
|
||||
expect(bookmarks.isBookmarked('https://example.com/'), isTrue);
|
||||
|
||||
final reloaded = LibraryController(db);
|
||||
final reloaded = BookmarksController(db);
|
||||
await reloaded.load();
|
||||
expect(reloaded.isBookmarked('https://example.com/'), isTrue);
|
||||
|
||||
await reloaded.toggleBookmark('https://example.com/', 'Example');
|
||||
await reloaded.toggle('https://example.com/', 'Example');
|
||||
expect(reloaded.isBookmarked('https://example.com/'), isFalse);
|
||||
});
|
||||
|
||||
test('subscription refresh reports only unseen entries', () async {
|
||||
final library = LibraryController(db);
|
||||
await library.load();
|
||||
test('subscribing takes on the back catalogue without flagging it', () async {
|
||||
final subscriptions = SubscriptionsController(db);
|
||||
await subscriptions.load();
|
||||
|
||||
final firstPost = MewsEntry(
|
||||
url: 'https://example.com/a.html', date: DateTime(2026, 9, 21), title: 'First post');
|
||||
await library.toggleSubscription(
|
||||
'https://example.com/', 'Example', [firstPost]);
|
||||
expect(library.isSubscribed('https://example.com/'), isTrue);
|
||||
url: 'https://example.com/a.html',
|
||||
date: DateTime(2026, 9, 21),
|
||||
title: 'First post');
|
||||
await subscriptions.toggle(_page('https://example.com/', [firstPost]));
|
||||
expect(subscriptions.isSubscribed('https://example.com/'), isTrue);
|
||||
|
||||
// Nothing new yet.
|
||||
await library.refreshSubscription(_page('https://example.com/', [firstPost]));
|
||||
expect(library.newEntries.value['https://example.com/'], isNull);
|
||||
// The post was stored, but read, so nothing is waiting for the reader.
|
||||
expect(await db.unreadCount(), 0);
|
||||
|
||||
// A new post appears.
|
||||
// Opening the page again finds nothing new.
|
||||
expect(await subscriptions.refreshSite(_page('https://example.com/', [firstPost])),
|
||||
isEmpty);
|
||||
|
||||
// A later post is new, and stays unread until the reader opens it.
|
||||
final newPost = MewsEntry(
|
||||
url: 'https://example.com/b.html', date: DateTime(2026, 10, 8), title: 'Second post');
|
||||
await library.refreshSubscription(_page('https://example.com/', [newPost, firstPost]));
|
||||
final fresh = library.newEntries.value['https://example.com/']!;
|
||||
expect(fresh, hasLength(1));
|
||||
expect(fresh.single.url, 'https://example.com/b.html');
|
||||
url: 'https://example.com/b.html',
|
||||
date: DateTime(2026, 10, 8),
|
||||
title: 'Second post');
|
||||
final fresh = await subscriptions
|
||||
.refreshSite(_page('https://example.com/', [newPost, firstPost]));
|
||||
expect(fresh.map((e) => e.url), ['https://example.com/b.html']);
|
||||
expect(await db.unreadCount(siteUrl: 'https://example.com/'), 1);
|
||||
|
||||
// The refresh stored it; a repeat refresh reports nothing.
|
||||
await library.refreshSubscription(_page('https://example.com/', [newPost, firstPost]));
|
||||
expect(library.newEntries.value['https://example.com/'], isNull);
|
||||
// Finding it a second time does not report it again.
|
||||
expect(
|
||||
await subscriptions
|
||||
.refreshSite(_page('https://example.com/', [newPost, firstPost])),
|
||||
isEmpty);
|
||||
expect(await db.unreadCount(), 1);
|
||||
});
|
||||
|
||||
test('unread posts survive a restart', () async {
|
||||
final subscriptions = SubscriptionsController(db);
|
||||
await subscriptions.load();
|
||||
await subscriptions.toggle(_page('https://example.com/', const []));
|
||||
await subscriptions.refreshSite(_page('https://example.com/', [
|
||||
MewsEntry(
|
||||
url: 'https://example.com/a.html',
|
||||
date: DateTime(2026, 9, 21),
|
||||
title: 'First post'),
|
||||
]));
|
||||
|
||||
// A fresh controller over the same database sees the same unread post,
|
||||
// which the old in-memory count could not do.
|
||||
final restarted = SubscriptionsController(db);
|
||||
await restarted.load();
|
||||
expect(restarted.isSubscribed('https://example.com/'), isTrue);
|
||||
expect(await db.unreadCount(), 1);
|
||||
});
|
||||
|
||||
test('leaving a site takes its posts with it', () async {
|
||||
final subscriptions = SubscriptionsController(db);
|
||||
await subscriptions.load();
|
||||
await subscriptions.toggle(_page('https://example.com/', const []));
|
||||
await subscriptions.refreshSite(_page('https://example.com/', [
|
||||
MewsEntry(
|
||||
url: 'https://example.com/a.html',
|
||||
date: DateTime(2026, 9, 21),
|
||||
title: 'First post'),
|
||||
]));
|
||||
expect(await db.unreadCount(), 1);
|
||||
|
||||
await subscriptions.remove('https://example.com/');
|
||||
expect(subscriptions.isSubscribed('https://example.com/'), isFalse);
|
||||
expect(await db.unreadCount(), 0);
|
||||
});
|
||||
|
||||
test('caches pages for offline reopening', () async {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue