feat: tag bookmarks and sites, and browse the library by tag

This commit is contained in:
randogoth 2026-10-11 13:32:00 +03:00
parent 5cd053c8a9
commit b0b86ef5b1
13 changed files with 445 additions and 21 deletions

View file

@ -59,7 +59,8 @@ void main() {
db = MewsDatabase.test(NativeDatabase.memory());
strings = Strings();
strings.loadSource(File('locales/en-US/main.ftl').readAsStringSync());
deps = AppDependencies(database: db, strings: strings);
deps = AppDependencies(
database: db, fetch: FakeFetch(const {}), strings: strings);
});
tearDown(() async {
@ -530,6 +531,63 @@ void main() {
expect(deps.bookmarks.isBookmarked('https://a.example/retro.html'), isFalse);
});
testWidgets('tags are made by using them and filter the list',
(tester) async {
await pumpApp(tester);
await deps.bookmarks.load();
await deps.bookmarks.toggle('https://a.example/retro.html', 'Retro gear');
await deps.bookmarks.toggle('https://b.example/signal.html', 'Signal bars');
// Nothing is tagged yet.
await deps.browser.open(MewsUrls.tags);
await tester.pumpAndSettle();
expect(find.textContaining('Tags you add'), findsOneWidget);
// Tagging reaches the item from its own row.
await deps.browser.open(MewsUrls.bookmarks);
await tester.pumpAndSettle();
await tapRun(tester, 'Edit tags');
expect(find.textContaining('Tags for'), findsWidgets);
// Adding a tag that does not exist yet is how one is made.
await tester.enterText(find.byType(TextFormField), 'phones');
await tester.tap(find.widgetWithText(FilledButton, 'Add tag'));
await tester.pumpAndSettle();
expect(find.textContaining('On this item'), findsOneWidget);
expect(await deps.db.tagCounts(), contains('phones'));
// An empty submit does nothing.
await tester.enterText(find.byType(TextFormField), ' ');
await tester.tap(find.widgetWithText(FilledButton, 'Add tag'));
await tester.pumpAndSettle();
expect((await deps.db.tagCounts()).keys, ['phones']);
// The tag now shows on the row and narrows the list when followed.
await deps.browser.open(MewsUrls.bookmarks);
await tester.pumpAndSettle();
await tapRun(tester, 'phones');
expect(deps.browser.currentPage.value?.url, 'mews:bookmarks?tag=phones');
expect(find.textContaining('Showing bookmarks tagged phones'), findsOneWidget);
expect(find.textContaining('Signal bars'), findsNothing);
await tapRun(tester, 'Show all bookmarks');
expect(deps.browser.currentPage.value?.url, MewsUrls.bookmarks);
expect(find.textContaining('Signal bars'), findsOneWidget);
// The index counts what carries the tag.
await deps.browser.open(MewsUrls.tags);
await tester.pumpAndSettle();
expect(find.textContaining('1 bookmark'), findsOneWidget);
// Deleting it everywhere leaves no trace, because a tag only exists while
// something carries it.
await tapRun(tester, 'Delete this tag everywhere');
expect(find.textContaining('Tags you add'), findsOneWidget);
expect(await deps.db.tagCounts(), isEmpty);
expect(await deps.db.tagsOf(TagKind.bookmark, 'https://a.example/retro.html'),
isEmpty);
});
testWidgets('clearing history takes a second step', (tester) async {
await pumpApp(tester);
await deps.db.recordVisit('https://a.example/one.html', 'Page one');