Files
immich-folio/app/admin/components/sameDraft.ts

32 lines
1.3 KiB
TypeScript
Raw Normal View History

2026-10-02 18:14:23 +02:00
/**
* Whether an editor's state is still what was last loaded or saved (QA A-19).
*
* The editors set a dirty flag on every edit, so typing a value back to what
* it was left "Unsaved changes" up, the leave guard armed and the draft
* stored. Comparing against the saved state fixes that, but not by plain
* JSON: an edit that is undone does not always undo its shape. The settings
* form creates the parent object of a path it writes (`contact: {}`), and a
* key that is deleted and typed again moves to the end of its object. So the
* comparison ignores key order, `undefined` and empty objects — none of which
* reaches the YAML that is written.
*/
function canonical(value: unknown): unknown {
if (Array.isArray(value)) return value.map(canonical);
if (value && typeof value === 'object') {
const out: Record<string, unknown> = {};
for (const key of Object.keys(value).sort()) {
const c = canonical((value as Record<string, unknown>)[key]);
if (c === undefined) continue;
if (c && typeof c === 'object' && !Array.isArray(c) && Object.keys(c).length === 0) continue;
out[key] = c;
}
return out;
}
return value;
}
export function sameDraft(a: unknown, b: unknown): boolean {
return JSON.stringify(canonical(a)) === JSON.stringify(canonical(b));
}