Twitch-VOD-Manager/src/renderer-updates.ts

217 lines
7.0 KiB
TypeScript

let updateCheckInProgress = false;
let updateDownloadInProgress = false;
let manualUpdateCheckPending = false;
let latestUpdateVersion = '';
function notifyUpdate(message: string, type: 'info' | 'warn' = 'info'): void {
const toastFn = (window as unknown as { showAppToast?: (msg: string, kind?: 'info' | 'warn') => void }).showAppToast;
if (typeof toastFn === 'function') {
toastFn(message, type);
} else if (type === 'warn') {
alert(message);
}
}
function setCheckButtonCheckingState(enabled: boolean): void {
const btn = byId<HTMLButtonElement>('checkUpdateBtn');
btn.disabled = enabled;
btn.textContent = enabled ? UI_TEXT.updates.checking : UI_TEXT.static.checkUpdates;
}
function showUpdateBanner(): void {
byId('updateBanner').style.display = 'flex';
}
function setDownloadPendingUi(): void {
showUpdateBanner();
const button = byId<HTMLButtonElement>('updateButton');
button.textContent = UI_TEXT.updates.downloading;
button.disabled = true;
byId('updateProgress').style.display = 'block';
const bar = byId('updateProgressBar');
bar.classList.add('downloading');
bar.style.width = '30%';
}
function setDownloadReadyUi(version: string): void {
showUpdateBanner();
updateReady = true;
updateDownloadInProgress = false;
latestUpdateVersion = version || latestUpdateVersion;
const bar = byId('updateProgressBar');
bar.classList.remove('downloading');
bar.style.width = '100%';
byId('updateText').textContent = `Version ${latestUpdateVersion || '?'} ${UI_TEXT.updates.ready}`;
const button = byId<HTMLButtonElement>('updateButton');
button.textContent = UI_TEXT.updates.installNow;
button.disabled = false;
}
async function checkUpdateSilent(): Promise<void> {
try {
await window.api.checkUpdate();
} catch {
// ignore silent updater errors
}
}
async function checkUpdate(): Promise<void> {
manualUpdateCheckPending = true;
setCheckButtonCheckingState(true);
try {
const result = await window.api.checkUpdate();
if (result?.error) {
manualUpdateCheckPending = false;
updateCheckInProgress = false;
setCheckButtonCheckingState(false);
notifyUpdate(UI_TEXT.updates.checkFailed, 'warn');
return;
}
const skippedReason = result?.skipped;
if (skippedReason === 'ready-to-install') {
manualUpdateCheckPending = false;
updateCheckInProgress = false;
setCheckButtonCheckingState(false);
notifyUpdate(UI_TEXT.updates.readyToInstall, 'info');
return;
}
if (skippedReason === 'in-progress' || skippedReason === 'throttled') {
manualUpdateCheckPending = false;
updateCheckInProgress = false;
setCheckButtonCheckingState(false);
notifyUpdate(UI_TEXT.updates.checkInProgress, 'info');
return;
}
manualUpdateCheckPending = false;
updateCheckInProgress = false;
setCheckButtonCheckingState(false);
window.setTimeout(() => {
if (!updateReady && byId('updateBanner').style.display !== 'flex') {
notifyUpdate(UI_TEXT.updates.latest, 'info');
}
}, 2500);
} catch {
manualUpdateCheckPending = false;
updateCheckInProgress = false;
setCheckButtonCheckingState(false);
notifyUpdate(UI_TEXT.updates.checkFailed, 'warn');
}
}
function downloadUpdate(): void {
if (updateReady) {
void window.api.installUpdate();
return;
}
if (updateDownloadInProgress) {
notifyUpdate(UI_TEXT.updates.downloadInProgress, 'info');
return;
}
updateDownloadInProgress = true;
setDownloadPendingUi();
void window.api.downloadUpdate().then((result) => {
if (result?.error) {
updateDownloadInProgress = false;
const button = byId<HTMLButtonElement>('updateButton');
button.textContent = UI_TEXT.updates.downloadNow;
button.disabled = false;
byId('updateProgressBar').classList.remove('downloading');
notifyUpdate(UI_TEXT.updates.downloadFailed, 'warn');
return;
}
if (result?.skipped === 'ready-to-install') {
setDownloadReadyUi(latestUpdateVersion);
return;
}
if (result?.skipped === 'in-progress') {
notifyUpdate(UI_TEXT.updates.downloadInProgress, 'info');
}
}).catch(() => {
updateDownloadInProgress = false;
const button = byId<HTMLButtonElement>('updateButton');
button.textContent = UI_TEXT.updates.downloadNow;
button.disabled = false;
byId('updateProgressBar').classList.remove('downloading');
notifyUpdate(UI_TEXT.updates.downloadFailed, 'warn');
});
}
window.api.onUpdateChecking(() => {
updateCheckInProgress = true;
if (manualUpdateCheckPending) {
setCheckButtonCheckingState(true);
}
});
window.api.onUpdateAvailable((info: UpdateInfo) => {
updateCheckInProgress = false;
updateReady = false;
updateDownloadInProgress = true;
manualUpdateCheckPending = false;
latestUpdateVersion = info.version;
setCheckButtonCheckingState(false);
showUpdateBanner();
byId('updateText').textContent = `Version ${info.version} ${UI_TEXT.updates.available}`;
byId('updateButton').textContent = UI_TEXT.updates.downloading;
byId<HTMLButtonElement>('updateButton').disabled = true;
byId('updateProgress').style.display = 'block';
byId('updateProgressBar').classList.add('downloading');
});
window.api.onUpdateNotAvailable(() => {
updateCheckInProgress = false;
setCheckButtonCheckingState(false);
if (manualUpdateCheckPending) {
notifyUpdate(UI_TEXT.updates.latest, 'info');
}
manualUpdateCheckPending = false;
});
window.api.onUpdateDownloadProgress((progress: UpdateDownloadProgress) => {
updateDownloadInProgress = true;
const bar = byId('updateProgressBar');
bar.classList.remove('downloading');
bar.style.width = progress.percent + '%';
const mb = (progress.transferred / 1024 / 1024).toFixed(1);
const totalMb = (progress.total / 1024 / 1024).toFixed(1);
byId('updateText').textContent = `${UI_TEXT.updates.downloadLabel}: ${mb} / ${totalMb} MB (${progress.percent.toFixed(0)}%)`;
});
window.api.onUpdateDownloaded((info: UpdateInfo) => {
setDownloadReadyUi(info.version);
});
window.api.onUpdateError(() => {
updateCheckInProgress = false;
const wasDownloading = updateDownloadInProgress;
updateDownloadInProgress = false;
manualUpdateCheckPending = false;
setCheckButtonCheckingState(false);
const button = byId<HTMLButtonElement>('updateButton');
if (!updateReady) {
button.textContent = UI_TEXT.updates.downloadNow;
button.disabled = false;
byId('updateProgressBar').classList.remove('downloading');
}
notifyUpdate(wasDownloading ? UI_TEXT.updates.downloadFailed : UI_TEXT.updates.checkFailed, 'warn');
});