gui/modules/desktop/electron/libs/auto-updater.ts
Neil 84339660c9
#587 enable force updating (#591)
Co-authored-by: neil molina <neil@neils-MacBook-Pro.local>
2023-05-11 12:13:18 +08:00

125 lines
3.6 KiB
TypeScript

import { type AppUpdater, autoUpdater } from "electron-updater";
import log from "./logger";
import { MainWindowNotifier } from "./types";
import { getTeaPath } from "./tea-dir";
import path from "path";
import fs from "fs";
type AutoUpdateStatus = {
status: "up-to-date" | "available" | "ready";
version?: string;
};
autoUpdater.logger = log;
let mainWindowNotifier: MainWindowNotifier | null = null;
let initalized = false;
let isUpdating = false;
// keep the last status to resend to the window when it's opened becuase the store is destroyed when the window is closed
let lastStatus: AutoUpdateStatus = { status: "up-to-date" };
export const getUpdater = () => autoUpdater;
export function checkUpdater(notifier: MainWindowNotifier): AppUpdater {
try {
mainWindowNotifier = notifier;
checkForUpdates();
if (!initalized) {
initalized = true;
setInterval(() => {
checkForUpdates();
}, 1000 * 60 * 30); // check for updates every 30 minutes
}
setPublishURL();
} catch (error) {
log.error(error);
}
return autoUpdater;
}
const checkForUpdates = async () => {
if (isUpdating) {
log.info("Update is already in progress");
return;
}
isUpdating = true;
try {
const result = await autoUpdater.checkForUpdatesAndNotify();
if (!result?.downloadPromise) {
isUpdating = false;
} else {
const files = await result.downloadPromise;
log.info("Successfully downloaded update files:", files);
// DO NOT RESET isUpdating here because the user still needs to click to install it
// and we don't want to accidentally start another update and overwrite the file
}
} catch (err) {
log.error("Error checking for updates:", err);
isUpdating = false;
}
};
// The auto update runs in the background so the window might not be open when the status changes
// When the update store gets created as part of the window it will request the latest status.
export function getAutoUpdateStatus() {
return lastStatus;
}
function sendStatusToWindow(status: AutoUpdateStatus) {
lastStatus = status;
if (mainWindowNotifier) {
mainWindowNotifier("app-update-status", status);
}
}
autoUpdater.on("checking-for-update", () => {
log.info("checking for tea gui update");
});
autoUpdater.on("update-available", (info) => {
log.info("update-available", info);
sendStatusToWindow({ status: "available" });
});
autoUpdater.on("update-not-available", () => {
log.info("no update for tea gui");
sendStatusToWindow({ status: "up-to-date" });
});
autoUpdater.on("error", (err) => {
log.error("auto update:", err);
});
autoUpdater.on("download-progress", (progressObj) => {
let log_message = "Download speed: " + progressObj.bytesPerSecond;
log_message = log_message + " - Downloaded " + progressObj.percent + "%";
log_message = log_message + " (" + progressObj.transferred + "/" + progressObj.total + ")";
log.info("tea gui:", log_message);
});
autoUpdater.on("update-downloaded", (info) => {
log.info("update-downloaded");
sendStatusToWindow({ status: "ready", version: info.version });
});
export const isDev = () => fs.existsSync(path.join(getTeaPath(), "tea.xyz/gui/dev"));
export const isForceUpdate = () =>
fs.existsSync(path.join(getTeaPath(), "tea.xyz/gui/force-auto-update"));
async function setPublishURL() {
try {
const folder = isForceUpdate() ? "auto-update-test" : isDev() ? "dev" : "release";
const feedUrl = `https://gui.tea.xyz/${folder}`;
log.info(`feedUrl$: ${feedUrl}`);
autoUpdater.setFeedURL(feedUrl);
} catch (error) {
log.error(error);
}
}