fix(ux): navigate back after deleting all search results (#85)
When the user searches in a mailbox, selects all results, and deletes them, re-evaluate the search. If no results remain and there is a previous screen in the navigation stack, pop back to it instead of clearing the search and showing the regular inbox. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
ef3fb72f4e
commit
122358c9a2
@@ -503,7 +503,11 @@ class _EmailListScreenState extends ConsumerState<EmailListScreen> {
|
||||
.searchEmails(widget.accountId, widget.mailboxPath, searchQuery);
|
||||
if (!mounted) return;
|
||||
if (remaining.isEmpty) {
|
||||
_searchController.clear();
|
||||
if (context.canPop()) {
|
||||
context.pop();
|
||||
} else {
|
||||
_searchController.clear();
|
||||
}
|
||||
} else {
|
||||
setState(() => _searchResults = remaining);
|
||||
}
|
||||
|
||||
@@ -3,9 +3,30 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:sharedinbox/core/models/email.dart';
|
||||
import 'package:sharedinbox/di.dart';
|
||||
import 'package:sharedinbox/ui/screens/email_list_screen.dart';
|
||||
import 'package:sharedinbox/ui/screens/mailbox_list_screen.dart';
|
||||
|
||||
import 'helpers.dart';
|
||||
|
||||
// A fake email repository whose search results can be changed mid-test.
|
||||
class _MutableFakeEmailRepository extends FakeEmailRepository {
|
||||
List<Email> _results;
|
||||
|
||||
_MutableFakeEmailRepository(List<Email> initial)
|
||||
: _results = List.of(initial),
|
||||
super();
|
||||
|
||||
void setSearchResults(List<Email> results) => _results = results;
|
||||
|
||||
@override
|
||||
Future<List<Email>> searchEmails(
|
||||
String accountId,
|
||||
String mailboxPath,
|
||||
String query,
|
||||
) async =>
|
||||
_results;
|
||||
}
|
||||
|
||||
final _kDate = DateTime(2024, 6);
|
||||
|
||||
void main() {
|
||||
@@ -405,6 +426,66 @@ void main() {
|
||||
expect(find.text('Result email'), findsWidgets);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'deleting all search results pops back to previous screen',
|
||||
(tester) async {
|
||||
final email = testEmail(subject: 'Needle');
|
||||
final repo = _MutableFakeEmailRepository([email]);
|
||||
|
||||
// Start at the mailbox list so the email list is pushed on top of it,
|
||||
// making context.canPop() == true inside EmailListScreen.
|
||||
await tester.pumpWidget(
|
||||
buildApp(
|
||||
initialLocation: '/accounts/acc-1/mailboxes',
|
||||
overrides: [
|
||||
accountRepositoryProvider.overrideWithValue(
|
||||
FakeAccountRepository([kTestAccount]),
|
||||
),
|
||||
mailboxRepositoryProvider.overrideWithValue(
|
||||
FakeMailboxRepository([kTestMailbox]),
|
||||
),
|
||||
emailRepositoryProvider.overrideWithValue(repo),
|
||||
],
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(MailboxListScreen), findsOneWidget);
|
||||
|
||||
// Navigate into INBOX (pushes EmailListScreen onto the stack).
|
||||
await tester.tap(find.text('INBOX'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(EmailListScreen), findsOneWidget);
|
||||
|
||||
// Search for the email.
|
||||
await tester.enterText(find.byType(TextField), 'Needle');
|
||||
await tester.testTextInput.receiveAction(TextInputAction.search);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 'Needle' also appears in the SearchBar input, so match at least one.
|
||||
expect(find.text('Needle'), findsAtLeastNWidgets(1));
|
||||
|
||||
// Long-press the sender name (unique to the email tile) to enter
|
||||
// selection mode.
|
||||
await tester.longPress(find.text('Bob'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byIcon(Icons.select_all));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// After deletion the search re-runs and finds nothing.
|
||||
repo.setSearchResults([]);
|
||||
|
||||
await tester.tap(find.byIcon(Icons.delete));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Should have popped back to the mailbox list.
|
||||
expect(find.byType(EmailListScreen), findsNothing);
|
||||
expect(find.byType(MailboxListScreen), findsOneWidget);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('shows preview snippet when email has preview', (tester) async {
|
||||
final email = Email(
|
||||
id: 'acc-1:99',
|
||||
|
||||
Reference in New Issue
Block a user