diff --git a/package-lock.json b/package-lock.json
index af2975e..34a9b01 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -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": {
diff --git a/package.json b/package.json
index 25ad6a7..95e84a6 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/main/index.ts b/src/main/index.ts
index 0727488..d6a5c48 100644
--- a/src/main/index.ts
+++ b/src/main/index.ts
@@ -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.
diff --git a/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx b/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx
index a20a549..7c8011b 100644
--- a/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx
+++ b/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx
@@ -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 && (
-
+
+
+
+ window.electron.ipcRenderer.send(ipcTypes.toMain.updates.apply)
+ }
+ />
+
)}
diff --git a/src/renderer/src/util/countdownHook.ts b/src/renderer/src/util/countdownHook.ts
new file mode 100644
index 0000000..5b2acd9
--- /dev/null
+++ b/src/renderer/src/util/countdownHook.ts
@@ -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;