mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-08 16:14:32 +00:00
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.
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { useState } from 'react'
|
|
|
|
import { releasePageUrl, useUpdateStatus } from '../hooks/useUpdateStatus'
|
|
import { codeburn } from '../lib/ipc'
|
|
|
|
const DISMISS_KEY = 'codeburn.updateDismissed'
|
|
|
|
function readDismissed(): string | null {
|
|
try { return globalThis.localStorage?.getItem(DISMISS_KEY) ?? null } catch { return null }
|
|
}
|
|
|
|
/**
|
|
* Subtle, dismissible "update available" nudge, in the budget-banner visual
|
|
* language. Dismiss persists per release tag (codeburn.updateDismissed), so the
|
|
* same version never nags twice but the next release shows fresh. Download opens
|
|
* the release page via the https-only openExternal bridge. Never auto-installs.
|
|
*/
|
|
export function UpdateBanner() {
|
|
const status = useUpdateStatus()
|
|
const [dismissedTag, setDismissedTag] = useState<string | null>(readDismissed)
|
|
|
|
if (!status || !status.updateAvailable || !status.tag) return null
|
|
if (dismissedTag === status.tag) return null
|
|
|
|
const tag = status.tag
|
|
const dismiss = () => {
|
|
try { globalThis.localStorage?.setItem(DISMISS_KEY, tag) } catch { /* storage can be unavailable */ }
|
|
setDismissedTag(tag)
|
|
}
|
|
|
|
return (
|
|
<div role="status" className="update-banner">
|
|
<span>
|
|
Update available: CodeBurn {status.latestVersion} ·{' '}
|
|
<button type="button" className="set-text-button" onClick={() => { void codeburn.openExternal(releasePageUrl(tag)) }}>Download</button>
|
|
</span>
|
|
<button type="button" className="set-text-button" onClick={dismiss}>Dismiss</button>
|
|
</div>
|
|
)
|
|
}
|