import 'package:signals/signals.dart'; import '../../database/database.dart'; import '../../mews/document.dart'; /// Which sites the reader subscribes to (spec 6). The posts themselves live in /// the database, so an unread post survives a restart; only the set of /// addresses is held here, because that is what the chrome watches. class SubscriptionsController { SubscriptionsController(this._db); final MewsDatabase _db; final subscribedUrls = signal({}); Future load() async { final rows = await _db.allSubscriptions(); subscribedUrls.value = rows.map((row) => row.url).toSet(); } bool isSubscribed(String url) => subscribedUrls.value.contains(url); Future toggle(MewsPage page) async { if (isSubscribed(page.url)) { await remove(page.url); return; } await _db.addSubscription(page.url, page.title, page.atomFeedHref); subscribedUrls.value = {...subscribedUrls.value, page.url}; // The posts already on the page are the site's back catalogue, not news, // so they are stored read and only later posts are flagged. await _db.addEntries(page.url, page.entries, read: true); } Future remove(String siteUrl) async { await _db.removeSubscription(siteUrl); subscribedUrls.value = {...subscribedUrls.value}..remove(siteUrl); } /// Records the posts on a subscribed page the reader just opened, and /// returns the ones that are new. Does nothing for a site not subscribed to. Future> refreshSite(MewsPage page) async { if (!isSubscribed(page.url)) return const []; await _db.describeSubscription(page.url, title: page.title, atomHref: page.atomFeedHref); final fresh = await _db.addEntries(page.url, page.entries); await _db.touchSubscription(page.url, DateTime.now()); return fresh; } }