Skip to content

Commit 20e7c74

Browse files
gsxdsmclaude
andauthored
Fix event endpoint persistence (#831)
* Changes from fix/event-hook-endpoint * fix: Allow empty eventHooks/ntfyEndpoints to reconcile from server Remove the `length > 0` guards in fast-hydrate reconciliation that prevented intentional empty-array clears from syncing across clients. Server-side wipe protection (`__allowEmpty*` escape hatches) already ensures empty arrays in the server are intentional. Addresses PR #831 review feedback from CodeRabbit and Gemini. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent dd7108a commit 20e7c74

3 files changed

Lines changed: 26 additions & 6 deletions

File tree

apps/ui/src/lib/http-api-client.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2763,6 +2763,21 @@ export class HttpApiClient implements ElectronAPI {
27632763
headers?: Record<string, string>;
27642764
enabled?: boolean;
27652765
}>;
2766+
eventHooks?: Array<{
2767+
id: string;
2768+
trigger: string;
2769+
enabled: boolean;
2770+
action: Record<string, unknown>;
2771+
name?: string;
2772+
}>;
2773+
ntfyEndpoints?: Array<{
2774+
id: string;
2775+
name: string;
2776+
serverUrl: string;
2777+
topic: string;
2778+
authType: string;
2779+
enabled: boolean;
2780+
}>;
27662781
};
27672782
error?: string;
27682783
}> => this.get('/api/settings/global'),

apps/ui/src/routes/__root.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -600,10 +600,7 @@ function RootLayoutContent() {
600600
// so updating them won't cause a visible re-render flash.
601601
const serverHooks = (finalSettings as GlobalSettings).eventHooks ?? [];
602602
const currentHooks = useAppStore.getState().eventHooks;
603-
if (
604-
JSON.stringify(serverHooks) !== JSON.stringify(currentHooks) &&
605-
serverHooks.length > 0
606-
) {
603+
if (JSON.stringify(serverHooks) !== JSON.stringify(currentHooks)) {
607604
logger.info(
608605
`[FAST_HYDRATE] Reconciling eventHooks from server (server=${serverHooks.length}, store=${currentHooks.length})`
609606
);

apps/ui/src/store/app-store.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,11 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
15061506
set({ eventHooks: hooks });
15071507
try {
15081508
const httpApi = getHttpApiClient();
1509-
await httpApi.settings.updateGlobal({ eventHooks: hooks });
1509+
await httpApi.settings.updateGlobal({
1510+
eventHooks: hooks,
1511+
// Signal the server that an empty array is intentional (not a wipe from stale state)
1512+
...(hooks.length === 0 ? { __allowEmptyEventHooks: true } : {}),
1513+
});
15101514
} catch (error) {
15111515
logger.error('Failed to sync event hooks:', error);
15121516
}
@@ -1517,7 +1521,11 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
15171521
set({ ntfyEndpoints: endpoints });
15181522
try {
15191523
const httpApi = getHttpApiClient();
1520-
await httpApi.settings.updateGlobal({ ntfyEndpoints: endpoints });
1524+
await httpApi.settings.updateGlobal({
1525+
ntfyEndpoints: endpoints,
1526+
// Signal the server that an empty array is intentional (not a wipe from stale state)
1527+
...(endpoints.length === 0 ? { __allowEmptyNtfyEndpoints: true } : {}),
1528+
});
15211529
} catch (error) {
15221530
logger.error('Failed to sync ntfy endpoints:', error);
15231531
}

0 commit comments

Comments
 (0)