fix: clear the mail search with back instead of leaving the app

This commit is contained in:
Linus Rath
2026-10-15 02:35:21 +02:00
parent 512a28c494
commit 46d30169b2
3 changed files with 48 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
import { describe, it, expect } from 'vitest';
import { listBackStep } from '../list-back';
describe('listBackStep', () => {
it('ends selection mode first', () => {
expect(listBackStep({ selecting: true, searching: true })).toBe('clear-selection');
});
it('clears an open search instead of leaving the app', () => {
expect(listBackStep({ selecting: false, searching: true })).toBe('clear-search');
});
it('leaves only from a plain list', () => {
expect(listBackStep({ selecting: false, searching: false })).toBe('leave');
});
});
+14
View File
@@ -0,0 +1,14 @@
/** What Android back does on a list screen (mail, contacts). */
export type ListBackStep = 'clear-selection' | 'clear-search' | 'leave';
/**
* Back works through the list's own layers first: selection mode ends, then
* an open search (and on mail its filters) clears. Only a plain list lets
* back `leave`: on the mail root that closes the app, on another tab it goes
* back to Mail. A search used to exit the app straight away.
*/
export function listBackStep(state: { selecting: boolean; searching: boolean }): ListBackStep {
if (state.selecting) return 'clear-selection';
if (state.searching) return 'clear-search';
return 'leave';
}
+18
View File
@@ -31,6 +31,8 @@ import {
} from '../stores/email-store';
import { useSettingsStore, type SwipeAction, type SwipeMode } from '../stores/settings-store';
import { useKeywordsStore, type KeywordDef } from '../stores/keywords-store';
import { useBackWhileFocused } from '../lib/use-back-while-focused';
import { listBackStep } from '../lib/list-back';
import { useLocaleStore } from '../stores/locale-store';
import { useSearchHistoryStore } from '../stores/search-history-store';
import { useContactsStore } from '../stores/contacts-store';
@@ -885,6 +887,22 @@ export default function EmailListScreen({
(filters.keyword ? 1 : 0) +
(filters.folder && filters.folder !== 'current' ? 1 : 0);
const hasActiveSearchOrFilter = Boolean(storeSearchQuery) || activeFilterCount > 0;
// Back first leaves the selection, then the search and filters; only then
// does it leave the app (it used to exit with a search still open).
const backStep = listBackStep({
selecting: selectionMode,
searching: hasActiveSearchOrFilter || searchInput.length > 0,
});
const handleBack = React.useCallback(() => {
if (backStep === 'clear-selection') {
clearSelection();
} else if (backStep === 'clear-search') {
setSearchInput('');
clearSearchAndFilters();
}
}, [backStep, clearSelection, clearSearchAndFilters]);
useBackWhileFocused(backStep !== 'leave', handleBack);
const folderScope = effectiveFolderScope(storeSearchQuery, filters);
// Accounts an "All folders" list could not reach (#1082).
const unreachedAccounts = spansAccounts({ searchQuery: storeSearchQuery, filters })