diff --git a/ui/src/ui/app.ts b/ui/src/ui/app.ts index 6d104fd9d10..b711f0733ca 100644 --- a/ui/src/ui/app.ts +++ b/ui/src/ui/app.ts @@ -963,7 +963,25 @@ export class OpenClawApp extends LitElement { try { const { getExistingSubscription } = await import("./push-subscription.ts"); const existing = await getExistingSubscription(); - this.webPushSubscribed = existing !== null; + if (existing && this.client) { + // Re-register with the gateway to reconcile local/server state. + // Handles the case where the gateway lost the subscription (e.g. + // state-dir reset) but the browser still has one locally. + const subJson = existing.toJSON(); + if (subJson.endpoint && subJson.keys?.p256dh && subJson.keys?.auth) { + try { + await this.client.request("push.web.subscribe", { + endpoint: subJson.endpoint, + keys: { p256dh: subJson.keys.p256dh, auth: subJson.keys.auth }, + }); + } catch { + // Best-effort — don't block init if gateway is unreachable. + } + } + this.webPushSubscribed = true; + } else { + this.webPushSubscribed = existing !== null; + } } catch { // ignore — just means we can't check } diff --git a/ui/src/ui/views/config.ts b/ui/src/ui/views/config.ts index 9d73fb07904..b4e7e562d46 100644 --- a/ui/src/ui/views/config.ts +++ b/ui/src/ui/views/config.ts @@ -969,16 +969,15 @@ export function renderConfig(props: ConfigProps) { const schemaProps = analysis.schema?.properties ?? {}; const VIRTUAL_SECTIONS = new Set(["__appearance__", "__notifications__"]); - const visibleCategories = SECTION_CATEGORIES.map((cat) => - Object.assign({}, cat, { - sections: cat.sections.filter( - (s) => - ((includeVirtualSections && VIRTUAL_SECTIONS.has(s.key)) || s.key in schemaProps) && - (!include || include.has(s.key)) && - (!exclude || !exclude.has(s.key)), - ), - }), - ).filter((cat) => cat.sections.length > 0); + const visibleCategories = SECTION_CATEGORIES.map((cat) => ({ + ...cat, + sections: cat.sections.filter( + (s) => + ((includeVirtualSections && VIRTUAL_SECTIONS.has(s.key)) || s.key in schemaProps) && + (!include || include.has(s.key)) && + (!exclude || !exclude.has(s.key)), + ), + })).filter((cat) => cat.sections.length > 0); // Catch any schema keys not in our categories const extraSections = Object.keys(schemaProps)