Minor app fixes and improvements.

This commit is contained in:
Patrick FIc
2025-04-01 17:23:41 -07:00
parent e4f204bf38
commit 20f2963330
8 changed files with 92 additions and 63 deletions

View File

@@ -60,7 +60,6 @@ workflows:
deploy_and_build: deploy_and_build:
jobs: jobs:
- partner-win-build - partner-win-build
# - partner-mac-build: filters:
# filters: branches:
# branches: only: main
# only: main

View File

@@ -148,17 +148,23 @@ export default class LocalServer {
public start(): void { public start(): void {
try { try {
this.server = this.app.listen(this.PORT, (error: Error | undefined) => { this.server = http.createServer(this.app);
if (error) {
this.server.on("error", (error: NodeJS.ErrnoException) => {
if (error.code === "EADDRINUSE") {
log.error( log.error(
`[HTTP Server] Error starting server: ${errorTypeCheck(error)}`, `[HTTP Server] Port ${this.PORT} is already in use. Please use a different port.`,
); );
} else { } else {
log.info( log.error(`[HTTP Server] Server error: ${error.message}`);
`[HTTP Server] Local HTTP server running on port ${this.PORT}`,
);
} }
}); });
this.server.listen(this.PORT, () => {
log.info(
`[HTTP Server] Local HTTP server running on port ${this.PORT}`,
);
});
} catch (error: unknown) { } catch (error: unknown) {
log.error("[HTTP Server] Error starting server", errorTypeCheck(error)); log.error("[HTTP Server] Error starting server", errorTypeCheck(error));
} }

View File

@@ -26,6 +26,8 @@ const isMac = process.platform === "darwin";
let isAppQuitting = false; //Needed on Mac as an override to allow us to fully quit the app. let isAppQuitting = false; //Needed on Mac as an override to allow us to fully quit the app.
// Initialize the server // Initialize the server
const localServer = new LocalServer(); const localServer = new LocalServer();
const gotTheLock = app.requestSingleInstanceLock();
function createWindow(): void { function createWindow(): void {
// Create the browser window. // Create the browser window.
const { width, height, x, y } = store.get("app.windowBounds") as { const { width, height, x, y } = store.get("app.windowBounds") as {
@@ -45,6 +47,7 @@ function createWindow(): void {
minHeight: 400, minHeight: 400,
//autoHideMenuBar: true, //autoHideMenuBar: true,
...(process.platform === "linux" ? { icon } : {}), ...(process.platform === "linux" ? { icon } : {}),
title: "Shop Partner",
webPreferences: { webPreferences: {
preload: join(__dirname, "../preload/index.js"), preload: join(__dirname, "../preload/index.js"),
sandbox: false, sandbox: false,
@@ -260,6 +263,9 @@ function createWindow(): void {
} }
} }
if (!gotTheLock) {
app.quit(); // Quit the app if another instance is already running
}
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
@@ -274,6 +280,12 @@ app.whenReady().then(async () => {
optimizer.watchWindowShortcuts(window); optimizer.watchWindowShortcuts(window);
}); });
// Add this event handler for second instance
app.on("second-instance", () => {
// Someone tried to run a second instance, we should focus our window
openMainWindow();
});
//Dynamically load ipcMain handlers once ready. //Dynamically load ipcMain handlers once ready.
try { try {
// Replace 'path/to/your/file' with the actual path to your file // Replace 'path/to/your/file' with the actual path to your file
@@ -365,6 +377,14 @@ app.on("window-all-closed", () => {
app.on("before-quit", () => { app.on("before-quit", () => {
localServer.stop(); localServer.stop();
const currentSetting = store.get("app.openOnStartup") as boolean;
store.set("app.openOnStartup", !currentSetting);
log.info("Open on startup set to", !currentSetting);
app.setLoginItemSettings({
enabled: true, //This is a windows only command. Updates the task manager and registry.
openAtLogin: !currentSetting,
});
isAppQuitting = true; isAppQuitting = true;
}); });

View File

@@ -45,8 +45,10 @@ const ipcMainHandleAuthStateChanged = async (
const convCo = activeBodyshop.bodyshops[0].convenient_company; const convCo = activeBodyshop.bodyshops[0].convenient_company;
if (convCo === "alpha") { if (convCo === "alpha") {
autoUpdater.channel = "alpha"; autoUpdater.channel = "alpha";
log.debug("Setting update channel to ALPHA channel.");
} else if (convCo === "beta") { } else if (convCo === "beta") {
autoUpdater.channel = "beta"; autoUpdater.channel = "beta";
log.debug("Setting update channel to BETA channel.");
} }
} catch (error) { } catch (error) {
log.error( log.error(

View File

@@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Electron</title> <title>Shop Partner</title>
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<!-- <meta <!-- <meta
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"

View File

@@ -97,7 +97,7 @@ const SettingsWatcher: React.FC = () => {
> >
<Card title={t("settings.labels.watcherstatus")}> <Card title={t("settings.labels.watcherstatus")}>
<Row> <Row>
<Col span={12}> <Col md={12} xs={24}>
{isWatcherStarted ? ( {isWatcherStarted ? (
<Button onClick={handleStop}> <Button onClick={handleStop}>
{t("settings.actions.stopwatcher")} {t("settings.actions.stopwatcher")}
@@ -108,7 +108,7 @@ const SettingsWatcher: React.FC = () => {
</Button> </Button>
)} )}
</Col> </Col>
<Col span={12}> <Col md={12} xs={24}>
<Space direction="vertical" wrap> <Space direction="vertical" wrap>
<Switch <Switch
checked={!pollingState.enabled} checked={!pollingState.enabled}

View File

@@ -3,7 +3,7 @@ import { Card, Typography } from "antd";
import { JSX, useEffect, useState } from "react"; import { JSX, useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json"; import ipcTypes from "../../../../util/ipcTypes.json";
import _ from "lodash";
const Welcome = (): JSX.Element => { const Welcome = (): JSX.Element => {
const { t } = useTranslation(); const { t } = useTranslation();
const [shopName, setShopName] = useState<string | null>(null); const [shopName, setShopName] = useState<string | null>(null);
@@ -18,12 +18,14 @@ const Welcome = (): JSX.Element => {
return ( return (
<> <>
<Card> <Typography.Title level={4}>
<Typography.Title level={3}> {t("auth.labels.welcome", {
{t("auth.labels.welcome", { name: auth.currentUser?.displayName })} name: _.isEmpty(auth.currentUser?.displayName)
</Typography.Title> ? auth.currentUser?.email
<Typography.Paragraph>{shopName || ""}</Typography.Paragraph> : `${auth.currentUser?.displayName} (${auth.currentUser?.email})`.trim(),
</Card> })}
</Typography.Title>
<Typography.Paragraph>{shopName || ""}</Typography.Paragraph>
</> </>
); );
}; };

View File

@@ -1,45 +1,45 @@
{ {
"translation": { "translation": {
"auth": { "auth": {
"labels": { "labels": {
"welcome": "Welcome {{name}}" "welcome": "Hi {{name}}"
}, },
"login": { "login": {
"error": "The username and password combination provided is not valid.", "error": "The username and password combination provided is not valid.",
"login": "Log In", "login": "Log In",
"resetpassword": "Reset Password" "resetpassword": "Reset Password"
} }
}, },
"errors": { "errors": {
"errorboundary": "Uh oh - we've hit an error.", "errorboundary": "Uh oh - we've hit an error.",
"notificationtitle": "Error Encountered" "notificationtitle": "Error Encountered"
}, },
"navigation": { "navigation": {
"home": "Home", "home": "Home",
"settings": "Settings", "settings": "Settings",
"signout": "Sign Out" "signout": "Sign Out"
}, },
"settings": { "settings": {
"actions": { "actions": {
"addpath": "Add path", "addpath": "Add path",
"startwatcher": "Start Watcher", "startwatcher": "Start Watcher",
"stopwatcher": "Stop Watcher\n" "stopwatcher": "Stop Watcher\n"
}, },
"labels": { "labels": {
"pollinginterval": "Polling Interval (ms)", "pollinginterval": "Polling Interval (ms)",
"started": "Started", "started": "Started",
"stopped": "Stopped", "stopped": "Stopped",
"watchedpaths": "Watched Paths", "watchedpaths": "Watched Paths",
"watchermodepolling": "Polling", "watchermodepolling": "Polling",
"watchermoderealtime": "Real Time", "watchermoderealtime": "Real Time",
"watcherstatus": "Watcher Status" "watcherstatus": "Watcher Status"
} }
}, },
"updates": { "updates": {
"apply": "Apply Update", "apply": "Apply Update",
"available": "An update is available.", "available": "An update is available.",
"download": "Download Update", "download": "Download Update",
"downloading": "An update is downloading." "downloading": "An update is downloading."
} }
} }
} }