From 1251d9208caadce626fd0706dfd34ba3e022fb2a Mon Sep 17 00:00:00 2001 From: haoyuren <13851610112@163.com> Date: Tue, 18 Aug 2026 20:30:17 +0800 Subject: Add in-app update check with one-click installer download On launch the home page checks the latest GitHub release; when a newer version exists a bottom-right card offers Download (streams the right installer for the platform into ~/Downloads and opens it), Later, or Skip this version (remembered). Unsigned app rules out silent auto-update on macOS, so installation stays a manual replace. Co-Authored-By: Claude Fable 5 --- src/renderer/src/App.css | 46 +++++++++++++++++++++++++ src/renderer/src/App.tsx | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) (limited to 'src/renderer') diff --git a/src/renderer/src/App.css b/src/renderer/src/App.css index d790a14..40867c4 100644 --- a/src/renderer/src/App.css +++ b/src/renderer/src/App.css @@ -1090,6 +1090,52 @@ html, body, #root { color: var(--text-primary); } +/* ── Update toast (bottom-right card on the home page) ─────────── */ + +.update-toast { + position: fixed; + bottom: 16px; + right: 16px; + z-index: 1000; + width: 320px; + padding: 14px 16px; + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: var(--shadow-md); + font-size: 13px; + color: var(--text-primary); +} + +.update-toast-title { + font-weight: 600; + margin-bottom: 10px; + display: flex; + align-items: baseline; + gap: 8px; +} + +.update-toast-link { + border: none; + background: none; + padding: 0; + font-size: 12px; + color: var(--accent-blue); + cursor: pointer; + text-decoration: underline; +} + +.update-toast-body { + color: var(--text-secondary); + margin-bottom: 10px; +} + +.update-toast-actions { + display: flex; + gap: 8px; + flex-wrap: wrap; +} + /* ── Projects Page ──────────────────────────────────────────── */ .projects-page { diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 3aa68e2..f3f9f79 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -39,6 +39,94 @@ export const remoteCursors = new Map() // the list window opens each project in its own window via ?projectId=) const initialProjectId = new URLSearchParams(window.location.search).get('projectId') +/** Update-available card (home renderer only). Checks GitHub Releases once + * per launch; "Skip this version" is remembered in localStorage. */ +function UpdateToast() { + const [info, setInfo] = useState<{ + version: string + releaseUrl: string + assetName?: string + assetUrl?: string + assetSize?: number + } | null>(null) + const [phase, setPhase] = useState<'idle' | 'downloading' | 'done' | 'error'>('idle') + + useEffect(() => { + window.api.updateCheck().then((r) => { + if (!r.available || !r.version) return + if (localStorage.getItem('lattex-skip-version') === r.version) return + setInfo({ + version: r.version, + releaseUrl: r.releaseUrl || 'https://github.com/YurenHao0426/lattex/releases', + assetName: r.assetName, + assetUrl: r.assetUrl, + assetSize: r.assetSize + }) + }).catch(() => {}) + }, []) + + if (!info) return null + + const sizeMb = info.assetSize ? ` (${(info.assetSize / 1024 / 1024).toFixed(0)} MB)` : '' + + const download = async () => { + if (!info.assetUrl || !info.assetName) { + // No installer for this platform in the release — open the page + window.api.openExternal(info.releaseUrl) + return + } + setPhase('downloading') + const r = await window.api.updateDownload(info.assetUrl, info.assetName) + setPhase(r.success ? 'done' : 'error') + } + + return ( +
+
+ Update available: v{info.version} + +
+ {phase === 'done' ? ( +
+ Installer opened — quit LatteX and replace the app to finish updating. +
+ ) : phase === 'error' ? ( +
+ Download failed — you can get it from the releases page instead. +
+ ) : ( +
+ + + +
+ )} + {(phase === 'done' || phase === 'error') && ( +
+ + {phase === 'error' && ( + + )} +
+ )} +
+ ) +} + /** Browser-style tab strip: persistent home tab + one tab per open project. * Rendered by the home renderer only, in the top TAB_BAR_HEIGHT (38px) strip * that project views never cover. Hidden entirely when no project is open. */ @@ -657,6 +745,7 @@ export default function App() {
+ ) -- cgit v1.2.3