mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
Cmd/Ctrl+K or the search control at the end of the top bar opens a combobox over a client-side index built from the lists the navigation already renders: pages, Insights pages, every Settings section and card (deep-linked by a new anchor prop on SettingsCardHeader), the Appearance sub-pages, module switches and a few actions. Entries follow the module map, the Coach capability, the admin role and a shared record's grant; inside somebody else's record no cards, switches or backup are offered. Ranking is prefix, then word start, then substring, then a small edit distance, then subsequence, with a short multilingual synonym list. The empty state shows recent places (per account, in localStorage) and the main actions. The palette is its own lazily loaded chunk; the top bar shows a search field where it has room and a magnifier otherwise. The module switch mutation moves into a shared hook used by the Modules hub and the palette.
50 lines
1.4 KiB
TypeScript
50 lines
1.4 KiB
TypeScript
/**
|
|
* The places a person last opened from the palette, per account and per
|
|
* browser: a convenience for the empty palette, nothing more. Storage can be
|
|
* missing, full or refused (a private window, a blocked site); every access
|
|
* is wrapped, and the palette works the same without it.
|
|
*/
|
|
|
|
const PREFIX = "healthlog-palette-recent:";
|
|
export const RECENT_LIMIT = 5;
|
|
|
|
function storage(): Storage | null {
|
|
try {
|
|
return typeof window === "undefined" ? null : window.localStorage;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** The ids, newest first, for `account`. */
|
|
export function readRecent(account: string | null | undefined): string[] {
|
|
if (!account) return [];
|
|
try {
|
|
const raw = storage()?.getItem(PREFIX + account);
|
|
if (!raw) return [];
|
|
const parsed: unknown = JSON.parse(raw);
|
|
return Array.isArray(parsed)
|
|
? parsed.filter((id): id is string => typeof id === "string")
|
|
: [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/** Put `id` first, keeping the list short and without repeats. */
|
|
export function pushRecent(
|
|
account: string | null | undefined,
|
|
id: string,
|
|
): void {
|
|
if (!account) return;
|
|
try {
|
|
const next = [id, ...readRecent(account).filter((x) => x !== id)].slice(
|
|
0,
|
|
RECENT_LIMIT,
|
|
);
|
|
storage()?.setItem(PREFIX + account, JSON.stringify(next));
|
|
} catch {
|
|
// A refused write only costs the next empty state its history.
|
|
}
|
|
}
|