feat(settings): explicit Save/Discard for preferences with dirty tracking
Settings-page prefs (theme/scheme/dark-mode/list-view/perf/hints/font + the
notification settings) were each auto-saved to the server on every toggle via
fire-and-forget savePrefs().catch(() => {}) — silent on failure, and no
positive confirmation on success, so the user had zero feedback either way.
Make them a draft instead: changes apply locally for instant preview but
persist only on an explicit Save (or revert on Discard). App owns the live
draft + the last-saved baseline, computes dirty, and exposes a controller to
the panel. The panel shows a Save/Discard bar with 'Saving…' → 'Settings
saved' (auto-clearing) / 'Couldn't save' feedback. Leaving the page with
unsaved changes prompts a confirm (in-app nav + browser Back), and a
beforeunload guards reload/close. savePrefs is now idempotent so the Save
survives a transient gateway blip; failures surface via the connection-lost
status. Language & sidebar layout stay instant (edited outside this page).
New i18n keys settings.save.* / settings.unsaved.* in EN/HU/DE.
This commit is contained in:
parent
d61e844f6b
commit
4a1a025353
6 changed files with 336 additions and 120 deletions
|
|
@ -464,8 +464,9 @@ export const api = {
|
|||
videoDetail: (id: string): Promise<VideoDetail> => req(`/api/videos/${id}`),
|
||||
pauseSync: () => req("/api/sync/pause", { method: "POST" }),
|
||||
resumeSync: () => req("/api/sync/resume", { method: "POST" }),
|
||||
// Overwriting preferences is idempotent, so let it retry on a transient gateway blip.
|
||||
savePrefs: (p: Record<string, any>) =>
|
||||
req("/api/me/preferences", { method: "PUT", body: JSON.stringify(p) }),
|
||||
req("/api/me/preferences", { method: "PUT", body: JSON.stringify(p) }, { idempotent: true }),
|
||||
|
||||
// --- channel manager ---
|
||||
myStatus: (): Promise<MyStatus> => req("/api/sync/my-status"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue