fix(mac): prevent updater hang on manual install
Bump to 1.0.20. Disable autoDownload during manual check and fix Squirrel.Mac quitAndInstall race on darwin. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,6 +14,43 @@ import type { LicenseService } from '../license/licenseService';
|
||||
const STARTUP_CHECK_DELAY_MS = 12_000;
|
||||
/** Не дёргать сервер чаще (смена лицензии / повторные emit). */
|
||||
const RE_CHECK_COOLDOWN_MS = 30_000;
|
||||
/** Ручная загрузка из модалки — не зависать бесконечно на «Загрузка…». */
|
||||
const MANUAL_DOWNLOAD_TIMEOUT_MS = 30 * 60 * 1000;
|
||||
|
||||
function withTimeout<T>(promise: Promise<T>, ms: number, code: string): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
const timer = setTimeout(() => reject(new Error(code)), ms);
|
||||
promise.then(
|
||||
(v) => {
|
||||
clearTimeout(timer);
|
||||
resolve(v);
|
||||
},
|
||||
(e: unknown) => {
|
||||
clearTimeout(timer);
|
||||
reject(e instanceof Error ? e : new Error(String(e)));
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* На macOS Squirrel.Mac может уже получить update-downloaded к моменту quitAndInstall.
|
||||
* При autoInstallOnAppQuit=true MacUpdater не вызывает checkForUpdates повторно и зависает.
|
||||
*/
|
||||
function quitAndInstallForPlatform(): void {
|
||||
if (process.platform === 'darwin') {
|
||||
autoUpdater.autoInstallOnAppQuit = false;
|
||||
}
|
||||
autoUpdater.quitAndInstall(false, true);
|
||||
}
|
||||
|
||||
function formatUpdaterError(e: unknown): string {
|
||||
const raw = e instanceof Error ? e.message : String(e);
|
||||
if (raw === 'UPDATE_DOWNLOAD_TIMEOUT') {
|
||||
return 'Превышено время ожидания загрузки обновления';
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
let lastCheckAt = 0;
|
||||
/** Ручная установка: не показывать второй диалог из `update-downloaded`. */
|
||||
@@ -42,6 +79,8 @@ async function runManualUpdaterCheck(licenseService: LicenseService): Promise<Up
|
||||
if (!isLicensedForUpdates(licenseService)) {
|
||||
return { outcome: 'no_license' };
|
||||
}
|
||||
const prevAutoDownload = autoUpdater.autoDownload;
|
||||
autoUpdater.autoDownload = false;
|
||||
try {
|
||||
const result = await autoUpdater.checkForUpdates();
|
||||
if (result && result.isUpdateAvailable && result.updateInfo.version) {
|
||||
@@ -51,6 +90,8 @@ async function runManualUpdaterCheck(licenseService: LicenseService): Promise<Up
|
||||
} catch (e) {
|
||||
const message = e instanceof Error ? e.message : String(e);
|
||||
return { outcome: 'error', message };
|
||||
} finally {
|
||||
autoUpdater.autoDownload = prevAutoDownload;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,15 +99,25 @@ async function runManualDownloadAndRestart(): Promise<UpdaterDownloadResponse> {
|
||||
if (!app.isPackaged) {
|
||||
return { ok: false, message: 'NOT_PACKAGED' };
|
||||
}
|
||||
const prevAutoInstallOnAppQuit = autoUpdater.autoInstallOnAppQuit;
|
||||
try {
|
||||
suppressAutoInstallDialog = true;
|
||||
await autoUpdater.downloadUpdate();
|
||||
autoUpdater.quitAndInstall(false, true);
|
||||
if (process.platform === 'darwin') {
|
||||
autoUpdater.autoInstallOnAppQuit = false;
|
||||
}
|
||||
await withTimeout(
|
||||
autoUpdater.downloadUpdate(),
|
||||
MANUAL_DOWNLOAD_TIMEOUT_MS,
|
||||
'UPDATE_DOWNLOAD_TIMEOUT',
|
||||
);
|
||||
quitAndInstallForPlatform();
|
||||
return { ok: true };
|
||||
} catch (e) {
|
||||
suppressAutoInstallDialog = false;
|
||||
const message = e instanceof Error ? e.message : String(e);
|
||||
return { ok: false, message };
|
||||
if (process.platform === 'darwin') {
|
||||
autoUpdater.autoInstallOnAppQuit = prevAutoInstallOnAppQuit;
|
||||
}
|
||||
return { ok: false, message: formatUpdaterError(e) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +170,7 @@ export function installAutoUpdater(licenseService: LicenseService, register: Reg
|
||||
})
|
||||
.then((r) => {
|
||||
if (r.response === 0) {
|
||||
autoUpdater.quitAndInstall(false, true);
|
||||
quitAndInstallForPlatform();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "TTRPGPlayer",
|
||||
"version": "1.0.18",
|
||||
"version": "1.0.20",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "TTRPGPlayer",
|
||||
"version": "1.0.18",
|
||||
"version": "1.0.20",
|
||||
"hasInstallScript": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TTRPGPlayer",
|
||||
"version": "1.0.19",
|
||||
"version": "1.0.20",
|
||||
"description": "TTRPG Player — редактор и проигрыватель НРИ",
|
||||
"main": "dist/main/index.cjs",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user