feat: search, filter and act on items from the library pages

This commit is contained in:
randogoth 2026-10-11 13:25:57 +03:00
parent 1b426ccd8b
commit 5cd053c8a9
11 changed files with 401 additions and 43 deletions

View file

@ -1,6 +1,7 @@
import '../../database/database.dart';
import '../../l10n/strings.dart';
import '../../mews/document.dart';
import 'mews_urls.dart';
import 'page_blocks.dart';
Future<MewsPage> buildSubscriptionsPage(
@ -8,7 +9,8 @@ Future<MewsPage> buildSubscriptionsPage(
required MewsDatabase db,
required Strings strings,
}) async {
final sites = await db.allSubscriptions();
final query = url.queryParameters['q'] ?? '';
final sites = await db.allSubscriptions(query: query);
final unread = await db.unreadCounts();
final title = strings.t('subscriptions-title');
@ -17,28 +19,53 @@ Future<MewsPage> buildSubscriptionsPage(
title: title,
body: [
...chrome(title: title, current: url, strings: strings),
searchForm(
action: MewsUrls.subscriptions,
label: strings.t('subscriptions-search-label'),
submitLabel: strings.t('action-search'),
query: query,
),
if (query.isNotEmpty)
ParagraphBlock([
MewsLink(MewsUrls.page(url, {'q': null}),
[MewsText(strings.t('action-clear-search'))]),
]),
if (sites.isEmpty)
ParagraphBlock([MewsText(strings.t('subscriptions-empty'))])
ParagraphBlock([
MewsText(strings.t(query.isEmpty
? 'subscriptions-empty'
: 'subscriptions-no-matches')),
])
else
itemList([
for (final site in sites)
itemRow(
href: site.url,
label: site.title ?? site.url,
date: dayText(site.createdAt),
note: _unreadNote(strings, unread[site.url] ?? 0),
note: _checkedNote(strings, site, unread[site.url] ?? 0),
actions: [
action(
MewsUrls.action('refresh-subscription', {'url': site.url}),
strings.t('action-refresh')),
action(MewsUrls.action('unsubscribe', {'url': site.url}),
strings.t('action-unsubscribe')),
],
),
]),
],
);
}
/// The unread count for a site, or null when it has nothing unread, so the
/// row carries no second line.
String? _unreadNote(Strings strings, int count) {
if (count == 0) return null;
return countText(strings, count,
none: 'count-unread-none',
one: 'count-unread-one',
many: 'count-unread-many');
/// What the reader needs to know about a site: what is waiting, or when it was
/// last looked at. Each is a whole message of its own.
String _checkedNote(Strings strings, Subscription site, int unread) {
if (unread > 0) {
return countText(strings, unread,
none: 'count-unread-none',
one: 'count-unread-one',
many: 'count-unread-many');
}
final checkedAt = site.lastCheckedAt;
if (checkedAt == null) return strings.t('subscriptions-never-checked');
return strings.t('subscriptions-checked', {'date': dayText(checkedAt)});
}