codeburn/app/renderer/hooks/useUpdateStatus.ts
iamtoruk 8fc9e303b9 feat(app): update-available notifications
Checks the GitHub releases for newer desktop-v tags once per launch
and every 24h (15s timeout, no identifying headers, offline = silent
retry). A dismissible banner and a Settings About row surface the
newer version and link the release page; dismissal persists per
version so each release nags at most once. No auto-install: unsigned
builds cannot, by platform constraint; the checker only notifies.

App 364/364 (+24), typechecks + build green.
2026-07-17 04:58:13 -07:00

30 lines
1.3 KiB
TypeScript

import { useEffect, useState } from 'react'
import { codeburn } from '../lib/ipc'
import type { UpdateStatus } from '../lib/types'
/**
* Reads the main-process update-availability status once on mount and stays live
* via the push event. Returns null until the first read resolves, or when the
* bridge predates the feature (an older preload, or a test mock) — both degrade
* to "no update", so callers can treat null as "nothing to show".
*/
export function useUpdateStatus(): UpdateStatus | null {
const [status, setStatus] = useState<UpdateStatus | null>(null)
useEffect(() => {
if (typeof codeburn.getUpdateStatus !== 'function') return
let active = true
codeburn.getUpdateStatus().then(next => { if (active) setStatus(next) }).catch(() => { /* offline — no nudge */ })
const unsubscribe = typeof codeburn.onUpdateStatus === 'function'
? codeburn.onUpdateStatus(next => { if (active) setStatus(next) })
: undefined
return () => { active = false; unsubscribe?.() }
}, [])
return status
}
/** GitHub release page for a desktop tag — the Download target (no site #get
* anchor exists). https-only, so it passes the openExternal allowlist. */
export function releasePageUrl(tag: string): string {
return `https://github.com/getagentseal/codeburn/releases/tag/${tag}`
}