Files
Psychotoxical-psysonic/src/components/AppUpdater.tsx
T
Psychotoxical 95468fb137 refactor: remove Tauri auto-updater, replace with simple GitHub-check modal
Remove tauri-plugin-updater, relaunch_after_update command, generate-update-
manifest.js, the generate-manifest CI job, and all signing/upload steps for
.sig files and latest.json. The updater plugin, its pubkey and endpoint config
in tauri.conf.json, and the updater:default capability are all gone.

Replace AppUpdater.tsx with a lightweight component that:
- Fetches https://api.github.com/repos/Psychotoxical/psysonic/releases/latest
  after a 4 s delay (no install, no download, no progress bar)
- Shows a dismissible toast with two buttons:
  GitHub → releases/latest
  Website → https://psysonic.psychotoxic.eu/#downloads

i18n: remove updaterInstall/Downloading/Installing/Download/ExperimentalHint
keys from all 7 locales; add updaterWebsite; update updaterVersion wording.

CI: remove generate-manifest job and all .sig signing/upload steps from
build-macos-windows. Also remove TAURI_SIGNING_PRIVATE_KEY env vars (no
longer needed). Release now just builds and uploads the installable binaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:42:52 +02:00

73 lines
2.5 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { open } from '@tauri-apps/plugin-shell';
import { RefreshCw, X } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { version as currentVersion } from '../../package.json';
// Semver comparison: returns true if `a` is newer than `b`
function isNewer(a: string, b: string): boolean {
const pa = a.replace(/^[^0-9]*/, '').split('.').map(Number);
const pb = b.replace(/^[^0-9]*/, '').split('.').map(Number);
for (let i = 0; i < 3; i++) {
if ((pa[i] ?? 0) > (pb[i] ?? 0)) return true;
if ((pa[i] ?? 0) < (pb[i] ?? 0)) return false;
}
return false;
}
export default function AppUpdater() {
const { t } = useTranslation();
const [newVersion, setNewVersion] = useState<string | null>(null);
const [dismissed, setDismissed] = useState(false);
useEffect(() => {
let cancelled = false;
const timer = setTimeout(async () => {
if (cancelled) return;
try {
const res = await fetch('https://api.github.com/repos/Psychotoxical/psysonic/releases/latest');
if (!res.ok || cancelled) return;
const data = await res.json();
const tag: string = data.tag_name ?? '';
if (!cancelled && tag && isNewer(tag, currentVersion)) {
setNewVersion(tag.replace(/^[^0-9]*/, ''));
}
} catch {
// No network or rate-limited — stay idle
}
}, 4000);
return () => { cancelled = true; clearTimeout(timer); };
}, []);
if (!newVersion || dismissed) return null;
return createPortal(
<div className="app-updater-toast">
<div className="app-updater-header">
<RefreshCw size={13} />
<span className="app-updater-label">{t('common.updaterAvailable')}</span>
<button className="app-updater-dismiss" onClick={() => setDismissed(true)} aria-label="Dismiss">
<X size={12} />
</button>
</div>
<div className="app-updater-version">{t('common.updaterVersion', { version: newVersion })}</div>
<div className="app-updater-actions">
<button
className="app-updater-btn-primary"
onClick={() => open('https://github.com/Psychotoxical/psysonic/releases/latest')}
>
GitHub
</button>
<button
className="app-updater-btn-secondary"
onClick={() => open('https://psysonic.psychotoxic.eu/#downloads')}
>
{t('common.updaterWebsite')}
</button>
</div>
</div>,
document.body
);
}