Mulimage 2.0 #1
@@ -90,21 +90,43 @@
|
||||
enabled: open
|
||||
}));
|
||||
|
||||
/**
|
||||
* Some PhotoPrism deployments return `/settings` without the
|
||||
* `ui` / `search` / `maps` keys (older versions, custom edits to
|
||||
* settings.yml). The form's `bind:value={draft.ui!.theme}` etc.
|
||||
* non-null-asserts those sub-objects — when they're missing the
|
||||
* assertion lies and the bind getter throws on the next tick. Force
|
||||
* the shape on every clone so every binding has a real object to
|
||||
* write into, and so `draft.ui` is never null while `draft` is non-
|
||||
* null (template gates only check `draft`).
|
||||
*/
|
||||
function normalize(s: PpSettings): PpSettings {
|
||||
return {
|
||||
...s,
|
||||
ui: s.ui ?? {},
|
||||
search: s.search ?? {},
|
||||
maps: s.maps ?? {}
|
||||
};
|
||||
}
|
||||
|
||||
let draft = $state<PpSettings | null>(null);
|
||||
// Re-clone on each open so reopening the dialog shows the freshest
|
||||
// server state. Eagerly nulling on close used to introduce a window
|
||||
// where Dialog's exit animation kept the form mounted while draft
|
||||
// was already null — and bind:value getters read null, triggering
|
||||
// "$.get(...) is null" / can't access .ui at runtime. Resetting on
|
||||
// open instead avoids that race entirely.
|
||||
$effect(() => {
|
||||
if (settingsQuery.data && draft === null) {
|
||||
draft = structuredClone(settingsQuery.data);
|
||||
if (open && settingsQuery.data) {
|
||||
draft = normalize(structuredClone(settingsQuery.data));
|
||||
}
|
||||
});
|
||||
$effect(() => {
|
||||
if (!open) draft = null;
|
||||
});
|
||||
|
||||
const saveMut = createMutation(() => ({
|
||||
mutationFn: (patch: PpSettings) => saveSettings(patch),
|
||||
onSuccess: (next) => {
|
||||
qc.setQueryData(['settings'], next);
|
||||
draft = structuredClone(next);
|
||||
draft = normalize(structuredClone(next));
|
||||
toast.success('Settings saved');
|
||||
},
|
||||
onError: (err) =>
|
||||
@@ -112,7 +134,7 @@
|
||||
}));
|
||||
|
||||
function resetDraft() {
|
||||
if (settingsQuery.data) draft = structuredClone(settingsQuery.data);
|
||||
if (settingsQuery.data) draft = normalize(structuredClone(settingsQuery.data));
|
||||
}
|
||||
|
||||
const selectClass =
|
||||
|
||||
@@ -126,11 +126,6 @@ function handleMessage(raw: string): void {
|
||||
const eventName = inner.event as string | undefined;
|
||||
const data = (inner.data ?? {}) as Record<string, unknown>;
|
||||
if (!eventName) return;
|
||||
// PhotoPrism's WS protocol isn't a stable contract; log the live shape
|
||||
// at `debug` (hidden by default in DevTools — toggle "Verbose" to see)
|
||||
// so future-us can spot new indexer event names without instrumenting
|
||||
// the entire app.
|
||||
console.debug('[indexer]', eventName, data);
|
||||
switch (eventName) {
|
||||
case 'index.indexing': {
|
||||
// Per-file event during the scan pass. PhotoPrism emits one
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user