Attempt to resolve auto update issues.

This commit is contained in:
Patrick Fic
2025-04-10 11:29:22 -07:00
parent 078b717328
commit 7e2c068e52
5 changed files with 136 additions and 21 deletions

6
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "bodyshop-desktop",
"version": "0.0.1-alpha.3",
"version": "0.0.1-alpha.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "bodyshop-desktop",
"version": "0.0.1-alpha.3",
"version": "0.0.1-alpha.0",
"hasInstallScript": true,
"dependencies": {
"@apollo/client": "^3.13.6",
@@ -14,6 +14,7 @@
"@electron-toolkit/utils": "^4.0.0",
"@sentry/electron": "^6.5.0",
"@sentry/vite-plugin": "^3.3.1",
"dayjs": "^1.11.13",
"electron-log": "^5.3.3",
"electron-store": "^8.2.0",
"electron-updater": "^6.6.2",
@@ -6774,7 +6775,6 @@
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"dev": true,
"license": "MIT"
},
"node_modules/dbffile": {

View File

@@ -1,6 +1,6 @@
{
"name": "bodyshop-desktop",
"version": "0.0.1-alpha.1",
"version": "0.0.1-alpha.0",
"description": "Shop Management System Partner",
"main": "./out/main/index.js",
"author": "Convenient Brands, LLC",
@@ -29,6 +29,7 @@
"@electron-toolkit/utils": "^4.0.0",
"@sentry/electron": "^6.5.0",
"@sentry/vite-plugin": "^3.3.1",
"dayjs": "^1.11.13",
"electron-log": "^5.3.3",
"electron-store": "^8.2.0",
"electron-updater": "^6.6.2",

View File

@@ -22,6 +22,7 @@ import ipcTypes from "../util/ipcTypes.json";
import ImportJob from "./decoder/decoder";
import LocalServer from "./http-server/http-server";
import store from "./store/store";
import { getMainWindow } from "./util/toRenderer";
import { GetAllEnvFiles } from "./watcher/watcher";
Sentry.init({
@@ -373,17 +374,17 @@ app.whenReady().then(async () => {
//Check for app updates.
autoUpdater.logger = log;
// if (import.meta.env.DEV) {
// // Useful for some dev/debugging tasks, but download can
// // not be validated becuase dev app is not signed
// autoUpdater.channel = "alpha";
// autoUpdater.updateConfigPath = path.join(
// __dirname,
// "../../dev-app-update.yml",
// );
// autoUpdater.forceDevUpdateConfig = true;
// //autoUpdater.autoDownload = false;
// }
if (import.meta.env.DEV) {
// Useful for some dev/debugging tasks, but download can
// not be validated becuase dev app is not signed
autoUpdater.channel = "alpha";
autoUpdater.updateConfigPath = path.join(
__dirname,
"../../dev-app-update.yml",
);
autoUpdater.forceDevUpdateConfig = true;
//autoUpdater.autoDownload = false;
}
autoUpdater.on("checking-for-update", () => {
log.info("Checking for update...");
@@ -439,7 +440,8 @@ app.on("window-all-closed", () => {
}
});
app.on("before-quit", () => {
app.on("before-quit", (props) => {
console.log(props);
preQuitMethods();
});
@@ -447,14 +449,17 @@ app.on("before-quit", () => {
ipcMain.on(ipcTypes.toMain.updates.apply, () => {
log.info("Applying update from renderer.");
preQuitMethods();
autoUpdater.quitAndInstall();
setImmediate(() => {
app.removeAllListeners("window-all-closed");
const mainWindow = getMainWindow();
if (mainWindow) mainWindow.close();
autoUpdater.quitAndInstall(false);
});
});
function preQuitMethods(): void {
localServer.stop();
const currentSetting = store.get("app.openOnStartup") as boolean;
store.set("app.openOnStartup", !currentSetting);
log.info("Open on startup set to", !currentSetting);
if (!import.meta.env.DEV) {
app.setLoginItemSettings({
enabled: true, //This is a windows only command. Updates the task manager and registry.

View File

@@ -5,12 +5,13 @@ import {
selectUpdateAvailable,
} from "@renderer/redux/app.slice";
import { useAppSelector } from "@renderer/redux/reduxHooks";
import { Affix, Button, Card, Progress } from "antd";
import { Affix, Button, Card, Progress, Space, Statistic } from "antd";
import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json";
const UpdateAvailable: React.FC = () => {
const { t } = useTranslation();
const isUpdateAvailable = useAppSelector(selectUpdateAvailable);
const updateSpeed = useAppSelector(selectAppUpdateSpeed);
const updateProgress = useAppSelector(selectAppUpdateProgress);
@@ -39,7 +40,17 @@ const UpdateAvailable: React.FC = () => {
/>
{!isUpdateComplete && formatSpeed(updateSpeed)}
{isUpdateComplete && (
<Space>
<Button onClick={handleApply}>{t("updates.apply")}</Button>
<Statistic.Countdown
title="Auto update in:"
format="mm:ss"
value={Date.now() + 10 * 1000}
onFinish={(): void =>
window.electron.ipcRenderer.send(ipcTypes.toMain.updates.apply)
}
/>
</Space>
)}
</Card>
</Affix>

View File

@@ -0,0 +1,98 @@
import React from "react";
const useCountDown = (
timeToCount = 60 * 1000,
interval = 1000,
): [
number,
{
start: (ttc?: number) => void;
pause: () => void;
resume: () => void;
reset: () => void;
},
] => {
const [timeLeft, setTimeLeft] = React.useState(0);
const timer = React.useRef({});
const run = (ts) => {
if (!timer.current.started) {
timer.current.started = ts;
timer.current.lastInterval = ts;
}
const localInterval = Math.min(
interval,
timer.current.timeLeft || Infinity,
);
if (ts - timer.current.lastInterval >= localInterval) {
timer.current.lastInterval += localInterval;
setTimeLeft((timeLeft) => {
timer.current.timeLeft = timeLeft - localInterval;
return timer.current.timeLeft;
});
}
if (ts - timer.current.started < timer.current.timeToCount) {
timer.current.requestId = window.requestAnimationFrame(run);
} else {
timer.current = {};
setTimeLeft(0);
}
};
const start = React.useCallback(
(ttc) => {
window.cancelAnimationFrame(timer.current.requestId);
const newTimeToCount = ttc !== undefined ? ttc : timeToCount;
timer.current.started = null;
timer.current.lastInterval = null;
timer.current.timeToCount = newTimeToCount;
timer.current.requestId = window.requestAnimationFrame(run);
setTimeLeft(newTimeToCount);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[],
);
const pause = React.useCallback(() => {
window.cancelAnimationFrame(timer.current.requestId);
timer.current.started = null;
timer.current.lastInterval = null;
timer.current.timeToCount = timer.current.timeLeft;
}, []);
const resume = React.useCallback(
() => {
if (!timer.current.started && timer.current.timeLeft > 0) {
window.cancelAnimationFrame(timer.current.requestId);
timer.current.requestId = window.requestAnimationFrame(run);
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[],
);
const reset = React.useCallback(() => {
if (timer.current.timeLeft) {
window.cancelAnimationFrame(timer.current.requestId);
timer.current = {};
setTimeLeft(0);
}
}, []);
const actions = React.useMemo(
() => ({ start, pause, resume, reset }), // eslint-disable-next-line react-hooks/exhaustive-deps
[],
);
React.useEffect(() => {
return () => window.cancelAnimationFrame(timer.current.requestId);
}, []);
return [timeLeft, actions];
};
export default useCountDown;