Add tray icons.

This commit is contained in:
Patrick Fic
2025-03-25 15:55:54 -07:00
parent f5fd6960ef
commit c7aa51f202
5 changed files with 101 additions and 70 deletions

View File

@@ -17,7 +17,7 @@
"postinstall": "electron-builder install-app-deps", "postinstall": "electron-builder install-app-deps",
"build:unpack": "npm run build && electron-builder --dir", "build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win", "build:win": "npm run build && electron-builder --win",
"build:mac": "electron-vite build && electron-builder --mac --publish always", "build:mac": "electron-vite build && electron-builder --mac",
"build:linux": "electron-vite build && electron-builder --linux" "build:linux": "electron-vite build && electron-builder --linux"
}, },
"dependencies": { "dependencies": {

BIN
resources/diamond.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

View File

@@ -1,5 +1,5 @@
import { electronApp, is, optimizer } from "@electron-toolkit/utils"; import { electronApp, is, optimizer } from "@electron-toolkit/utils";
import { app, BrowserWindow, Menu, shell } from "electron"; import { app, BrowserWindow, Menu, shell, nativeImage, Tray } from "electron";
import log from "electron-log/main"; import log from "electron-log/main";
import { autoUpdater } from "electron-updater"; import { autoUpdater } from "electron-updater";
import path, { join } from "path"; import path, { join } from "path";
@@ -8,10 +8,11 @@ import ErrorTypeCheck from "../util/errorTypeCheck";
import ipcTypes from "../util/ipcTypes.json"; import ipcTypes from "../util/ipcTypes.json";
import client from "./graphql/graphql-client"; import client from "./graphql/graphql-client";
import store from "./store/store"; import store from "./store/store";
import { createPublicKey } from "crypto"; import appIcon from "../../resources/diamond.png?asset";
log.initialize(); log.initialize();
const isMac = process.platform === "darwin"; const isMac = process.platform === "darwin";
var isAppQuitting = false; //Needed on Mac as an override to allow us to fully quit the app.
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 {
@@ -128,8 +129,6 @@ function createWindow(): void {
], ],
}, },
...(import.meta.env.DEV
? [
{ {
label: "Development", label: "Development",
submenu: [ submenu: [
@@ -161,9 +160,7 @@ function createWindow(): void {
{ {
label: "Log the Store", label: "Log the Store",
click: (): void => { click: (): void => {
log.debug( log.debug("Store Contents" + JSON.stringify(store.store, null, 4));
"Store Contents" + JSON.stringify(store.store, null, 4),
);
}, },
}, },
{ {
@@ -188,8 +185,6 @@ function createWindow(): void {
}, },
], ],
}, },
]
: []),
]; ];
const menu: Electron.Menu = Menu.buildFromTemplate(template); const menu: Electron.Menu = Menu.buildFromTemplate(template);
@@ -210,6 +205,13 @@ function createWindow(): void {
mainWindow.show(); mainWindow.show();
}); });
mainWindow.on("close", (event: Electron.Event) => {
if (!isAppQuitting) {
event.preventDefault(); // Prevent the window from closing
mainWindow.hide();
}
});
mainWindow.webContents.setWindowOpenHandler((details) => { mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url); shell.openExternal(details.url);
return { action: "deny" }; return { action: "deny" };
@@ -255,6 +257,26 @@ app.whenReady().then(async () => {
...ErrorTypeCheck(error), ...ErrorTypeCheck(error),
}); });
} }
//Create Tray
const trayicon = nativeImage.createFromPath(appIcon);
const tray = new Tray(trayicon.resize({ width: 16 }));
const contextMenu = Menu.buildFromTemplate([
{
label: "Show App",
click: (): void => {
openMainWindow();
},
},
{
label: "Quit",
click: (): void => {
app.quit(); // actually quit the app.
},
},
]);
tray.setContextMenu(contextMenu);
//Check for app updates. //Check for app updates.
@@ -300,9 +322,7 @@ app.whenReady().then(async () => {
createWindow(); createWindow();
app.on("activate", function () { app.on("activate", function () {
// On macOS it's common to re-create a window in the app when the openMainWindow();
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
}); });
}); });
@@ -311,9 +331,19 @@ app.whenReady().then(async () => {
// explicitly with Cmd + Q. // explicitly with Cmd + Q.
app.on("window-all-closed", () => { app.on("window-all-closed", () => {
if (process.platform !== "darwin") { if (process.platform !== "darwin") {
app.quit(); app.quit(); //Disable the quit.
} }
}); });
// In this file you can include the rest of your app's specific main process app.on("before-quit", () => {
// code. You can also put them in separate files and require them here. isAppQuitting = true;
});
function openMainWindow(): void {
const mainWindow = BrowserWindow.getAllWindows()[0];
if (mainWindow) {
mainWindow.show();
} else {
createWindow();
}
}

View File

@@ -10,10 +10,10 @@ const NavigationHeader: React.FC = () => {
const isWatcherStarted = useAppSelector(selectWatcherStatus); const isWatcherStarted = useAppSelector(selectWatcherStatus);
const menuItems: MenuItemType[] = [ const menuItems: MenuItemType[] = [
{ label: <NavLink to="/">{t("navigation.home")}</NavLink>, key: "home" }, { label: <NavLink to="/">{t("navigation.home")}</NavLink>, key: "home" },
{ // {
label: <NavLink to="/settings">{t("navigation.settings")}</NavLink>, // label: <NavLink to="/settings">{t("navigation.settings")}</NavLink>,
key: "settings", // key: "settings",
}, // },
]; ];
return ( return (
<Badge.Ribbon <Badge.Ribbon

View File

@@ -6,7 +6,8 @@
"src/preload/**/*", "src/preload/**/*",
"src/util/**/*", "src/util/**/*",
"src/interfaces/**/*", "src/interfaces/**/*",
"tests/index.spec.ts" "tests/index.spec.ts",
"/resources/**/*"
], ],
"compilerOptions": { "compilerOptions": {
"resolveJsonModule": true, "resolveJsonModule": true,