Files
webmail/lib/move-recent.ts
T
Linus Rath 4d404929e2 fix: show the message's own folders in Move to, in mail-client order, with recents and a filter
The Move lists (message menu, reader Move button and its phone panel,
selection toolbar, Move dialog) now share one model in lib/move-menu.ts.
In the desktop app the native copy of the menu lost the shared accounts'
headers and every folder's nesting, so Inbox, Sent, Spam and Trash
showed once per account with nothing to tell them apart.

- Only the message's own account at the top; other accounts a move can
  reach are submenus under their names.
- System folders first (Inbox, Sent, Archive, Spam, Trash), then the
  user's folders by name; subfolders nest, as submenus natively.
- The open folder shows greyed instead of missing.
- A Recent group, a filter field on long lists, and "Choose folder…"
  for the dialog, which has the filter too.

Tests changed: the open folder is now shown disabled rather than left
out, the own account of a shared-mailbox message is a submenu, and the
selection toolbar's filter field has its own label.
2026-11-04 05:20:14 +01:00

41 lines
1.3 KiB
TypeScript

/**
* The folders messages were last moved to, per account, most recent first.
* Kept on this device only; the Move lists show the few that still exist.
*/
const KEY = "bulwark.moveRecent.v1";
const KEPT = 8;
type Store = Record<string, string[]>;
function read(): Store {
try {
const raw = typeof localStorage === "undefined" ? null : localStorage.getItem(KEY);
const parsed: unknown = raw ? JSON.parse(raw) : null;
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
const out: Store = {};
for (const [account, ids] of Object.entries(parsed as Record<string, unknown>)) {
if (Array.isArray(ids)) out[account] = ids.filter((id): id is string => typeof id === "string").slice(0, KEPT);
}
return out;
} catch {
return {};
}
}
export function readRecentMoveTargets(accountId: string | undefined): string[] {
if (!accountId) return [];
return read()[accountId] ?? [];
}
export function noteMoveTarget(accountId: string | undefined, mailboxId: string): void {
if (!accountId || !mailboxId) return;
const store = read();
store[accountId] = [mailboxId, ...(store[accountId] ?? []).filter((id) => id !== mailboxId)].slice(0, KEPT);
try {
localStorage.setItem(KEY, JSON.stringify(store));
} catch {
// Storage full or off: the list just has no recents.
}
}