fix(learn): Archived and Recently deleted fold during a search

A search opened both sections whatever they were set to, so a tap on
their headers did nothing while one was under way. A search still opens
them, so their matches show, and a tap now folds them until the search
ends, which brings them back as they were left before it.

Whats-New: While searching the library, Archived and Recently deleted fold again when tapped.
Whats-New-De: Beim Suchen in der Bibliothek lassen sich Archiviert und Zuletzt gelöscht wieder einklappen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-11 15:44:51 +01:00
commit 3ee29de391
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
2 changed files with 62 additions and 6 deletions

View file

@ -494,6 +494,20 @@ class _GridState() extends State<_Grid> {
var _archiveOpen = false; var _archiveOpen = false;
var _deletedOpen = true; var _deletedOpen = true;
/// Whether the sections are open during a search: each search opens
/// them, so their matches show, and a tap folds them until it ends.
var _archiveOpenInSearch = true;
var _deletedOpenInSearch = true;
@override
void didUpdateWidget(_Grid oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.query.isEmpty && widget.query.isNotEmpty) {
_archiveOpenInSearch = true;
_deletedOpenInSearch = true;
}
}
static const _spacing = 12.0; static const _spacing = 12.0;
// As many columns as fit cards up to 400 dp wide; every card as tall, so // As many columns as fit cards up to 400 dp wide; every card as tall, so
@ -594,10 +608,11 @@ class _GridState() extends State<_Grid> {
for (final studyset in widget.deleted) for (final studyset in widget.deleted)
if (listed(studyset)) studyset, if (listed(studyset)) studyset,
]; ];
// A search opens the sections, so their matches show; closing the // A search opens the sections, so their matches show, and a tap folds
// search brings them back as the person left them. // them for the rest of it; closing the search brings them back as the
final archiveOpen = searching || _archiveOpen; // person left them.
final deletedOpen = searching || _deletedOpen; final archiveOpen = searching ? _archiveOpenInSearch : _archiveOpen;
final deletedOpen = searching ? _deletedOpenInSearch : _deletedOpen;
// Pulled down, the library syncs. // Pulled down, the library syncs.
return AppRefreshIndicator( return AppRefreshIndicator(
onRefresh: () => _syncNow(context), onRefresh: () => _syncNow(context),
@ -655,7 +670,13 @@ class _GridState() extends State<_Grid> {
label: l10n.libraryArchivedSection, label: l10n.libraryArchivedSection,
count: archived.length, count: archived.length,
open: archiveOpen, open: archiveOpen,
onToggle: () => setState(() => _archiveOpen = !_archiveOpen), onToggle: () => setState(() {
if (searching) {
_archiveOpenInSearch = !_archiveOpenInSearch;
} else {
_archiveOpen = !_archiveOpen;
}
}),
), ),
), ),
if (archiveOpen) if (archiveOpen)
@ -680,7 +701,13 @@ class _GridState() extends State<_Grid> {
label: l10n.libraryDeletedSection, label: l10n.libraryDeletedSection,
count: deleted.length, count: deleted.length,
open: deletedOpen, open: deletedOpen,
onToggle: () => setState(() => _deletedOpen = !_deletedOpen), onToggle: () => setState(() {
if (searching) {
_deletedOpenInSearch = !_deletedOpenInSearch;
} else {
_deletedOpen = !_deletedOpen;
}
}),
), ),
), ),
if (deletedOpen) ...[ if (deletedOpen) ...[

View file

@ -683,6 +683,35 @@ void main() {
expect(find.text('Kanji'), findsNothing, reason: 'the archive is closed'); expect(find.text('Kanji'), findsNothing, reason: 'the archive is closed');
}); });
testWidgets('a search opens the archive, which a tap folds for the rest '
'of the search', (tester) async {
stored(
'kanji',
'Kanji',
secondaryTitle: 'Japanese',
archivedAt: DateTime.utc(2026, 10),
);
await showLibrary(tester);
await tester.tap(find.byTooltip('Search'));
await tester.pumpAndSettle();
await tester.enterText(find.byType(TextField), 'kan');
await tester.pumpAndSettle();
expect(find.text('Kanji'), findsOneWidget);
await tester.tap(find.text('Archived'));
await tester.pumpAndSettle();
expect(find.text('Kanji'), findsNothing);
await tester.enterText(find.byType(TextField), 'kanj');
await tester.pumpAndSettle();
expect(find.text('Kanji'), findsNothing, reason: 'still folded');
await tester.tap(find.text('Archived'));
await tester.pumpAndSettle();
expect(find.text('Kanji'), findsOneWidget);
});
testWidgets('a search lists titles starting with what is typed first, then ' testWidgets('a search lists titles starting with what is typed first, then '
'those holding it as a word, then secondary titles, whatever was changed ' 'those holding it as a word, then secondary titles, whatever was changed '
'last', (tester) async { 'last', (tester) async {