feat: store subscription posts with a read mark and split the library controller

This commit is contained in:
randogoth 2026-10-11 13:12:48 +03:00
parent b311b9f7dd
commit 953ae798eb
15 changed files with 1787 additions and 386 deletions

View file

@ -28,7 +28,6 @@ class _ReaderScreenState extends State<ReaderScreen> {
/// scrolls down, back on any upward scroll.
bool _chromeVisible = true;
bool _showBrokenText = false;
final _reportedNewPosts = <String>{};
final _checkedSubscriptions = <String>{};
@override
@ -151,7 +150,6 @@ class _ReaderScreenState extends State<ReaderScreen> {
final fontScale = settings.fontScale.value;
final variant = settings.variant.value;
final visited = deps.browser.visitedUrls.value;
_maybeReportNewPosts(context, page);
final palette = paletteFor(
pageVariant: page.variant,
@ -251,32 +249,15 @@ class _ReaderScreenState extends State<ReaderScreen> {
);
}
/// Revalidates a subscribed page once per page load so new entries surface
/// (spec 6.1). The library controller no-ops for unsubscribed pages.
/// Records the posts of a subscribed page once per page load, so what is new
/// shows up on the subscriptions and posts pages (spec 6.1). The controller
/// no-ops for a page the reader is not subscribed to.
void _checkSubscription(BuildContext context, MewsPage page) {
if (_checkedSubscriptions.contains(page.url)) return;
_checkedSubscriptions.add(page.url);
final deps = AppScope.of(context).deps;
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) deps.library.refreshSubscription(page);
});
}
/// Shows the new-posts snackbar once per site after the refresh reports
/// entries the reader has not seen.
void _maybeReportNewPosts(BuildContext context, MewsPage page) {
final scope = AppScope.of(context);
final fresh = scope.deps.library.newEntries.value[page.url];
if (fresh == null || fresh.isEmpty || _reportedNewPosts.contains(page.url)) return;
_reportedNewPosts.add(page.url);
final strings = scope.strings;
final message = fresh.length == 1
? strings.t('new-posts-one')
: strings.t('new-posts-many', {'count': fresh.length});
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
if (mounted) deps.subscriptions.refreshSite(page);
});
}
}