From 6898e385e8ebbf6fc7a33430e83172d5f6ff8517 Mon Sep 17 00:00:00 2001 From: vjrj Date: Sat, 11 Jul 2026 14:05:31 +0200 Subject: [PATCH] =?UTF-8?q?polish(detail):=20TODO=20review=20=E2=80=94=20c?= =?UTF-8?q?alendar=20intro,=20drop=20abundance,=20collapse=20seed-saving?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the owner's TODO.org review of the shipped features: - Crop calendar now says the months are YOUR notes: a hint line in the editor (cropCalendar.editorHint) and a caption under the 'this month' screen (calendar.selfNote) — it read as if the app knew when to sow. - Dropped the 'how much I have' (abundance) input + display: it competed with the lot quantity as a second 'how much'. Removed from the lot sheet and the lot summary; the DB column + backup/CSV/catalog plumbing stay dormant (no destructive migration). offer_status carries 'do I share'. - Seed-saving guidance moved into a collapsed expander (detail.seedSaving) — reference facts about the species shouldn't sit open among the grower's own records; opt-in depth, per progressive disclosure. - Condition checks already live behind the collapsed 'advanced' expander (seed lots only) — left as the discreet power-user surface. Tests: dropped the obsolete abundance→share nudge test; the seed-saving section test now expands before asserting. analyze clean; suites green. --- apps/app_seeds/lib/i18n/ast.i18n.json | 2 + apps/app_seeds/lib/i18n/en.i18n.json | 2 + apps/app_seeds/lib/i18n/es.i18n.json | 2 + apps/app_seeds/lib/i18n/pt.i18n.json | 2 + apps/app_seeds/lib/i18n/strings.g.dart | 4 +- apps/app_seeds/lib/i18n/strings_ast.g.dart | 4 + apps/app_seeds/lib/i18n/strings_en.g.dart | 8 ++ apps/app_seeds/lib/i18n/strings_es.g.dart | 4 + apps/app_seeds/lib/i18n/strings_pt.g.dart | 4 + apps/app_seeds/lib/ui/calendar_screen.dart | 7 ++ .../lib/ui/variety_detail_screen.dart | 116 +++++------------- .../test/ui/seed_saving_section_test.dart | 8 ++ apps/app_seeds/test/ui/share_flow_test.dart | 34 ----- 13 files changed, 73 insertions(+), 124 deletions(-) diff --git a/apps/app_seeds/lib/i18n/ast.i18n.json b/apps/app_seeds/lib/i18n/ast.i18n.json index 1d2feba..e94ee39 100644 --- a/apps/app_seeds/lib/i18n/ast.i18n.json +++ b/apps/app_seeds/lib/i18n/ast.i18n.json @@ -30,6 +30,7 @@ "calendar": { "title": "Esti mes", "filterChip": "Esti mes", + "selfNote": "Lo qu'anotasti nes tos variedaes.", "nothing": "Nada anotao pa {month}." }, "app": { @@ -342,6 +343,7 @@ "flowering": "Floriamientu", "fruiting": "Fructificación", "seedHarvest": "Coyecha de simiente", + "editorHint": "Anota tú los meses típicos d'esta variedá na to zona — son notes tuyes.", "unset": "—" }, "needsReproduction": { diff --git a/apps/app_seeds/lib/i18n/en.i18n.json b/apps/app_seeds/lib/i18n/en.i18n.json index 3d4f76a..b6182e1 100644 --- a/apps/app_seeds/lib/i18n/en.i18n.json +++ b/apps/app_seeds/lib/i18n/en.i18n.json @@ -30,6 +30,7 @@ "calendar": { "title": "This month", "filterChip": "This month", + "selfNote": "What you've noted in your varieties.", "nothing": "Nothing noted for {month}." }, "app": { @@ -343,6 +344,7 @@ "flowering": "Flowering", "fruiting": "Fruiting", "seedHarvest": "Seed harvest", + "editorHint": "Note the months typical for this variety in your area — these are your own notes.", "unset": "—" }, "needsReproduction": { diff --git a/apps/app_seeds/lib/i18n/es.i18n.json b/apps/app_seeds/lib/i18n/es.i18n.json index a7529de..c7ce0ca 100644 --- a/apps/app_seeds/lib/i18n/es.i18n.json +++ b/apps/app_seeds/lib/i18n/es.i18n.json @@ -30,6 +30,7 @@ "calendar": { "title": "Este mes", "filterChip": "Este mes", + "selfNote": "Lo que has anotado en tus variedades.", "nothing": "Nada anotado para {month}." }, "app": { @@ -342,6 +343,7 @@ "flowering": "Floración", "fruiting": "Fructificación", "seedHarvest": "Cosecha de semilla", + "editorHint": "Anota tú los meses típicos de esta variedad en tu zona — son tus propias notas.", "unset": "—" }, "needsReproduction": { diff --git a/apps/app_seeds/lib/i18n/pt.i18n.json b/apps/app_seeds/lib/i18n/pt.i18n.json index 1bd4334..c514e1d 100644 --- a/apps/app_seeds/lib/i18n/pt.i18n.json +++ b/apps/app_seeds/lib/i18n/pt.i18n.json @@ -30,6 +30,7 @@ "calendar": { "title": "Este mês", "filterChip": "Este mês", + "selfNote": "O que anotaste nas tuas variedades.", "nothing": "Nada anotado para {month}." }, "app": { @@ -339,6 +340,7 @@ "flowering": "Floração", "fruiting": "Frutificação", "seedHarvest": "Colheita de semente", + "editorHint": "Anota tu os meses típicos desta variedade na tua zona — são as tuas notas.", "unset": "—" }, "needsReproduction": { diff --git a/apps/app_seeds/lib/i18n/strings.g.dart b/apps/app_seeds/lib/i18n/strings.g.dart index 14f6883..ae8dd2a 100644 --- a/apps/app_seeds/lib/i18n/strings.g.dart +++ b/apps/app_seeds/lib/i18n/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 4 -/// Strings: 2008 (502 per locale) +/// Strings: 2016 (504 per locale) /// -/// Built on 2026-07-11 at 11:29 UTC +/// Built on 2026-07-11 at 12:07 UTC // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/apps/app_seeds/lib/i18n/strings_ast.g.dart b/apps/app_seeds/lib/i18n/strings_ast.g.dart index 8f6b5b8..f7b6490 100644 --- a/apps/app_seeds/lib/i18n/strings_ast.g.dart +++ b/apps/app_seeds/lib/i18n/strings_ast.g.dart @@ -129,6 +129,7 @@ class _Translations$calendar$ast extends Translations$calendar$en { // Translations @override String get title => 'Esti mes'; @override String get filterChip => 'Esti mes'; + @override String get selfNote => 'Lo qu\'anotasti nes tos variedaes.'; @override String nothing({required Object month}) => 'Nada anotao pa ${month}.'; } @@ -602,6 +603,7 @@ class _Translations$cropCalendar$ast extends Translations$cropCalendar$en { @override String get flowering => 'Floriamientu'; @override String get fruiting => 'Fructificación'; @override String get seedHarvest => 'Coyecha de simiente'; + @override String get editorHint => 'Anota tú los meses típicos d\'esta variedá na to zona — son notes tuyes.'; @override String get unset => '—'; } @@ -1320,6 +1322,7 @@ extension on TranslationsAst { 'seedSaving.sourcePrefix' => 'Fonte', 'calendar.title' => 'Esti mes', 'calendar.filterChip' => 'Esti mes', + 'calendar.selfNote' => 'Lo qu\'anotasti nes tos variedaes.', 'calendar.nothing' => ({required Object month}) => 'Nada anotao pa ${month}.', 'app.title' => 'Tanemaki', 'bootstrap.failed' => 'Tanemaki nun pudo aniciar', @@ -1566,6 +1569,7 @@ extension on TranslationsAst { 'cropCalendar.flowering' => 'Floriamientu', 'cropCalendar.fruiting' => 'Fructificación', 'cropCalendar.seedHarvest' => 'Coyecha de simiente', + 'cropCalendar.editorHint' => 'Anota tú los meses típicos d\'esta variedá na to zona — son notes tuyes.', 'cropCalendar.unset' => '—', 'needsReproduction.label' => 'Reproducir esta temporada', 'needsReproduction.hint' => 'Cultívala enantes de que s\'acabe la simiente', diff --git a/apps/app_seeds/lib/i18n/strings_en.g.dart b/apps/app_seeds/lib/i18n/strings_en.g.dart index 66c4933..d7ee735 100644 --- a/apps/app_seeds/lib/i18n/strings_en.g.dart +++ b/apps/app_seeds/lib/i18n/strings_en.g.dart @@ -187,6 +187,9 @@ class Translations$calendar$en { /// en: 'This month' String get filterChip => 'This month'; + /// en: 'What you've noted in your varieties.' + String get selfNote => 'What you\'ve noted in your varieties.'; + /// en: 'Nothing noted for {month}.' String nothing({required Object month}) => 'Nothing noted for ${month}.'; } @@ -1113,6 +1116,9 @@ class Translations$cropCalendar$en { /// en: 'Seed harvest' String get seedHarvest => 'Seed harvest'; + /// en: 'Note the months typical for this variety in your area — these are your own notes.' + String get editorHint => 'Note the months typical for this variety in your area — these are your own notes.'; + /// en: '—' String get unset => '—'; } @@ -2311,6 +2317,7 @@ extension on Translations { 'seedSaving.sourcePrefix' => 'Source', 'calendar.title' => 'This month', 'calendar.filterChip' => 'This month', + 'calendar.selfNote' => 'What you\'ve noted in your varieties.', 'calendar.nothing' => ({required Object month}) => 'Nothing noted for ${month}.', 'app.title' => 'Tanemaki', 'bootstrap.failed' => 'Tanemaki couldn\'t start', @@ -2558,6 +2565,7 @@ extension on Translations { 'cropCalendar.flowering' => 'Flowering', 'cropCalendar.fruiting' => 'Fruiting', 'cropCalendar.seedHarvest' => 'Seed harvest', + 'cropCalendar.editorHint' => 'Note the months typical for this variety in your area — these are your own notes.', 'cropCalendar.unset' => '—', 'needsReproduction.label' => 'To regrow this season', 'needsReproduction.hint' => 'Grow it out before the seed runs out', diff --git a/apps/app_seeds/lib/i18n/strings_es.g.dart b/apps/app_seeds/lib/i18n/strings_es.g.dart index 3fa19c7..0ecc6a3 100644 --- a/apps/app_seeds/lib/i18n/strings_es.g.dart +++ b/apps/app_seeds/lib/i18n/strings_es.g.dart @@ -129,6 +129,7 @@ class _Translations$calendar$es extends Translations$calendar$en { // Translations @override String get title => 'Este mes'; @override String get filterChip => 'Este mes'; + @override String get selfNote => 'Lo que has anotado en tus variedades.'; @override String nothing({required Object month}) => 'Nada anotado para ${month}.'; } @@ -602,6 +603,7 @@ class _Translations$cropCalendar$es extends Translations$cropCalendar$en { @override String get flowering => 'Floración'; @override String get fruiting => 'Fructificación'; @override String get seedHarvest => 'Cosecha de semilla'; + @override String get editorHint => 'Anota tú los meses típicos de esta variedad en tu zona — son tus propias notas.'; @override String get unset => '—'; } @@ -1322,6 +1324,7 @@ extension on TranslationsEs { 'seedSaving.sourcePrefix' => 'Fuente', 'calendar.title' => 'Este mes', 'calendar.filterChip' => 'Este mes', + 'calendar.selfNote' => 'Lo que has anotado en tus variedades.', 'calendar.nothing' => ({required Object month}) => 'Nada anotado para ${month}.', 'app.title' => 'Tanemaki', 'bootstrap.failed' => 'Tanemaki no pudo arrancar', @@ -1568,6 +1571,7 @@ extension on TranslationsEs { 'cropCalendar.flowering' => 'Floración', 'cropCalendar.fruiting' => 'Fructificación', 'cropCalendar.seedHarvest' => 'Cosecha de semilla', + 'cropCalendar.editorHint' => 'Anota tú los meses típicos de esta variedad en tu zona — son tus propias notas.', 'cropCalendar.unset' => '—', 'needsReproduction.label' => 'Reproducir esta temporada', 'needsReproduction.hint' => 'Cultívala antes de que se acabe la semilla', diff --git a/apps/app_seeds/lib/i18n/strings_pt.g.dart b/apps/app_seeds/lib/i18n/strings_pt.g.dart index 7ce472d..589644e 100644 --- a/apps/app_seeds/lib/i18n/strings_pt.g.dart +++ b/apps/app_seeds/lib/i18n/strings_pt.g.dart @@ -129,6 +129,7 @@ class _Translations$calendar$pt extends Translations$calendar$en { // Translations @override String get title => 'Este mês'; @override String get filterChip => 'Este mês'; + @override String get selfNote => 'O que anotaste nas tuas variedades.'; @override String nothing({required Object month}) => 'Nada anotado para ${month}.'; } @@ -599,6 +600,7 @@ class _Translations$cropCalendar$pt extends Translations$cropCalendar$en { @override String get flowering => 'Floração'; @override String get fruiting => 'Frutificação'; @override String get seedHarvest => 'Colheita de semente'; + @override String get editorHint => 'Anota tu os meses típicos desta variedade na tua zona — são as tuas notas.'; @override String get unset => '—'; } @@ -1319,6 +1321,7 @@ extension on TranslationsPt { 'seedSaving.sourcePrefix' => 'Fonte', 'calendar.title' => 'Este mês', 'calendar.filterChip' => 'Este mês', + 'calendar.selfNote' => 'O que anotaste nas tuas variedades.', 'calendar.nothing' => ({required Object month}) => 'Nada anotado para ${month}.', 'app.title' => 'Tanemaki', 'bootstrap.failed' => 'O Tanemaki não conseguiu iniciar', @@ -1562,6 +1565,7 @@ extension on TranslationsPt { 'cropCalendar.flowering' => 'Floração', 'cropCalendar.fruiting' => 'Frutificação', 'cropCalendar.seedHarvest' => 'Colheita de semente', + 'cropCalendar.editorHint' => 'Anota tu os meses típicos desta variedade na tua zona — são as tuas notas.', 'cropCalendar.unset' => '—', 'needsReproduction.label' => 'Reproduzir nesta época', 'needsReproduction.hint' => 'Cultiva-a antes que a semente acabe', diff --git a/apps/app_seeds/lib/ui/calendar_screen.dart b/apps/app_seeds/lib/ui/calendar_screen.dart index ef05f1c..d01df9e 100644 --- a/apps/app_seeds/lib/ui/calendar_screen.dart +++ b/apps/app_seeds/lib/ui/calendar_screen.dart @@ -71,6 +71,13 @@ class _CalendarScreenState extends State { month: _month, onSelect: (m) => setState(() => _month = m), ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(16, 0, 16, 8), + child: Text( + t.calendar.selfNote, + style: const TextStyle(color: seedMuted, fontSize: 12), + ), + ), const Divider(height: 1), Expanded( child: StreamBuilder>( diff --git a/apps/app_seeds/lib/ui/variety_detail_screen.dart b/apps/app_seeds/lib/ui/variety_detail_screen.dart index 3478bf9..1b1c270 100644 --- a/apps/app_seeds/lib/ui/variety_detail_screen.dart +++ b/apps/app_seeds/lib/ui/variety_detail_screen.dart @@ -147,9 +147,22 @@ class _DetailView extends StatelessWidget { scientificName: detail.scientificName, family: detail.family ?? detail.category, ) case final guide? when guide.hasAny) ...[ - const SizedBox(height: 16), - _SectionTitle(t.seedSaving.title), - _SeedSavingView(guide: guide), + const SizedBox(height: 8), + // Reference data (facts about the species, not the grower's own + // records) — collapsed by default so it's opt-in depth, not noise. + ExpansionTile( + key: const Key('detail.seedSaving'), + tilePadding: EdgeInsets.zero, + childrenPadding: const EdgeInsets.only(bottom: 8), + leading: const Icon(Icons.spa_outlined, color: seedGreen), + title: Text(t.seedSaving.title), + children: [ + Align( + alignment: AlignmentDirectional.centerStart, + child: _SeedSavingView(guide: guide), + ), + ], + ), ], if (_referenceLinks(context, detail) case final references when references.isNotEmpty) ...[ @@ -234,10 +247,7 @@ String _lotSubtitle(Translations t, VarietyLot lot) { harvestDateLabel(t, year: lot.harvestYear!, month: lot.harvestMonth) else t.detail.noYear, - if (lot.quantity != null) - quantityDisplay(t, lot.quantity!) - else if (lot.abundance != null) - abundanceLabel(t, lot.abundance!), + if (lot.quantity != null) quantityDisplay(t, lot.quantity!), if (lot.presentation != null) presentationLabel(t, lot.presentation!), if (lot.offerStatus != OfferStatus.private) shareStatusLabel(t, lot.offerStatus), @@ -879,6 +889,17 @@ class _EditVarietySheetState extends State<_EditVarietySheet> { title: Text(t.cropCalendar.title), onExpansionChanged: (v) => _calendarOpen = v, children: [ + Align( + alignment: AlignmentDirectional.centerStart, + child: Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Text( + t.cropCalendar.editorHint, + style: const TextStyle( + color: seedMuted, fontSize: 12), + ), + ), + ), _MonthMultiSelect( label: t.cropCalendar.sow, mask: _sowMonths, @@ -1176,14 +1197,6 @@ class _DifficultyChip extends StatelessWidget { } } -/// Human label for a coarse-abundance level. -String abundanceLabel(Translations t, Abundance a) => switch (a) { - Abundance.plentyToShare => t.abundance.plentyToShare, - Abundance.enoughToShare => t.abundance.enoughToShare, - Abundance.enoughForMe => t.abundance.enoughForMe, - Abundance.runningLow => t.abundance.runningLow, -}; - /// Human label for how (whether) a lot is offered to others. String shareStatusLabel(Translations t, OfferStatus s) => switch (s) { OfferStatus.private => t.share.private, @@ -1210,32 +1223,6 @@ String desiccantLabel(Translations t, DesiccantState d) => switch (d) { DesiccantState.fresh => t.desiccant.fresh, }; -/// Single-select chips for the coarse-abundance level; tapping the current one -/// clears it (null). -class _AbundanceSelector extends StatelessWidget { - const _AbundanceSelector({required this.value, required this.onChanged}); - - final Abundance? value; - final ValueChanged onChanged; - - @override - Widget build(BuildContext context) { - final t = context.t; - return Wrap( - spacing: 8, - runSpacing: 4, - children: [ - for (final a in Abundance.values) - ChoiceChip( - key: Key('abundance.${a.name}'), - label: Text(abundanceLabel(t, a)), - selected: value == a, - onSelected: (sel) => onChanged(sel ? a : null), - ), - ], - ); - } -} /// Single-select chips for the share terms. Gift and swap come first and sale /// last, never preselected — the gift is first-class, the sale a choice @@ -1464,12 +1451,10 @@ Future _showLotSheet( final originPlaceCtrl = TextEditingController( text: existing?.originPlace ?? '', ); - var selectedAbundance = existing?.abundance; var selectedPreservation = existing?.preservationFormat; var selectedShare = existing?.offerStatus ?? OfferStatus.private; var showOrigin = existing?.originName != null || existing?.originPlace != null; - var showAbundance = existing?.abundance != null; var showShare = selectedShare != OfferStatus.private; final existingPrice = existing?.priceAmount; final priceAmountCtrl = TextEditingController( @@ -1585,17 +1570,6 @@ Future _showLotSheet( label: Text(t.provenance.section), onPressed: () => setState(() => showOrigin = true), ), - if (!showAbundance) - ActionChip( - key: const Key('lot.addAbundance'), - avatar: const Icon( - Icons.inventory_2_outlined, - size: 18, - ), - label: Text(t.abundance.add), - onPressed: () => - setState(() => showAbundance = true), - ), if (!showShare) ActionChip( key: const Key('lot.addShare'), @@ -1636,27 +1610,6 @@ Future _showLotSheet( ), ), ], - if (showAbundance) ...[ - const SizedBox(height: 16), - Text( - t.abundance.title, - style: Theme.of(sheetContext).textTheme.labelLarge, - ), - const SizedBox(height: 8), - _AbundanceSelector( - value: selectedAbundance, - onChanged: (a) => setState(() { - selectedAbundance = a; - // The bridge from "how much" to "do you share it": - // declaring plenty reveals the sharing choice. A - // nudge, never a change of the choice itself. - if (a == Abundance.plentyToShare || - a == Abundance.enoughToShare) { - showShare = true; - } - }), - ), - ], if (showShare) ...[ const SizedBox(height: 16), Text( @@ -1668,17 +1621,6 @@ Future _showLotSheet( value: selectedShare, onChanged: (s) => setState(() => selectedShare = s), ), - if (selectedShare == OfferStatus.private && - (selectedAbundance == Abundance.plentyToShare || - selectedAbundance == Abundance.enoughToShare)) - Padding( - padding: const EdgeInsets.only(top: 6), - child: Text( - t.share.nudge, - key: const Key('share.nudge'), - style: Theme.of(sheetContext).textTheme.bodySmall, - ), - ), // Price only when selling — informational, agreed and // paid off-app. Empty amount = "to be agreed". if (selectedShare == OfferStatus.sell) ...[ @@ -1786,7 +1728,6 @@ Future _showLotSheet( presentation: selectedPresentation, originName: originName, originPlace: originPlace, - abundance: selectedAbundance, preservationFormat: selectedPreservation, offerStatus: selectedShare, priceAmount: priceAmount, @@ -1801,7 +1742,6 @@ Future _showLotSheet( presentation: selectedPresentation, originName: originName, originPlace: originPlace, - abundance: selectedAbundance, preservationFormat: selectedPreservation, offerStatus: selectedShare, priceAmount: priceAmount, diff --git a/apps/app_seeds/test/ui/seed_saving_section_test.dart b/apps/app_seeds/test/ui/seed_saving_section_test.dart index 015a0a9..a80f7d1 100644 --- a/apps/app_seeds/test/ui/seed_saving_section_test.dart +++ b/apps/app_seeds/test/ui/seed_saving_section_test.dart @@ -1,3 +1,4 @@ +import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tane/data/seed_saving_catalog.dart'; import 'package:tane/db/database.dart'; @@ -36,7 +37,14 @@ void main() { testWidgets('shows the seed-saving section for a known family', (tester) async { await pumpDetailFor(tester, 'Solanaceae'); + // The section is a collapsed expander — its title shows, its body doesn't + // until opened. expect(find.text('Saving its seed'), findsOneWidget); + expect(find.textContaining('Self-pollinating'), findsNothing); + + await tester.tap(find.byKey(const Key('detail.seedSaving'))); + await tester.pumpAndSettle(); + // The pollination line is a Text.rich (label + value), so match the run. expect(find.textContaining('Self-pollinating'), findsOneWidget); expect(find.text('Easy'), findsOneWidget); // the difficulty pill diff --git a/apps/app_seeds/test/ui/share_flow_test.dart b/apps/app_seeds/test/ui/share_flow_test.dart index f0c1a69..3618249 100644 --- a/apps/app_seeds/test/ui/share_flow_test.dart +++ b/apps/app_seeds/test/ui/share_flow_test.dart @@ -47,40 +47,6 @@ void main() { await disposeTree(tester); }); - testWidgets('declaring plenty reveals the share choice with a nudge', ( - tester, - ) async { - final repo = newTestRepository(db); - final id = await repo.addQuickVariety(label: 'Maize'); - - await tester.pumpWidget( - wrapDetail( - repository: repo, - varietyId: id, - species: newTestSpeciesRepository(db), - ), - ); - await tester.pumpAndSettle(); - - await tester.tap(find.byKey(const Key('detail.addLot'))); - await tester.pumpAndSettle(); - - // Reveal abundance and declare plenty. - await tester.ensureVisible(find.byKey(const Key('lot.addAbundance'))); - await tester.tap(find.byKey(const Key('lot.addAbundance'))); - await tester.pumpAndSettle(); - await tester.ensureVisible( - find.byKey(const Key('abundance.plentyToShare')), - ); - await tester.tap(find.byKey(const Key('abundance.plentyToShare'))); - await tester.pumpAndSettle(); - - // The share section reveals itself, still private, with a soft nudge. - expect(find.byKey(const Key('share.private')), findsOneWidget); - expect(find.byKey(const Key('share.nudge')), findsOneWidget); - await disposeTree(tester); - }); - testWidgets('the sharing filter narrows the list to what I share', ( tester, ) async {