From 606e6bcca2e190c25c25931333c9fa04ff25edb9 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Wed, 19 Mar 2025 15:35:12 +0800 Subject: [PATCH 01/16] Click the icon to show the window --- src/services/window.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/window.ts b/src/services/window.ts index c43e56415..8b5697609 100644 --- a/src/services/window.ts +++ b/src/services/window.ts @@ -162,7 +162,7 @@ async function createMainWindow(app: App) { if (mainWindow.isMinimized()) { mainWindow.restore(); } - + mainWindow.show(); mainWindow.focus(); } }); From be2064fbf04a329947128d6201b2a1030a2c1ff2 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Fri, 21 Mar 2025 11:08:33 +0800 Subject: [PATCH 02/16] Fix tray exception when multiple windows --- .../tray/new-windowTemplate-inverted.png | Bin 0 -> 348 bytes .../new-windowTemplate-inverted@1.25x.png | Bin 0 -> 427 bytes .../tray/new-windowTemplate-inverted@1.5x.png | Bin 0 -> 514 bytes .../tray/new-windowTemplate-inverted@2x.png | Bin 0 -> 649 bytes images/app-icons/tray/new-windowTemplate.png | Bin 0 -> 331 bytes .../tray/new-windowTemplate@1.25x.png | Bin 0 -> 409 bytes .../tray/new-windowTemplate@1.5x.png | Bin 0 -> 481 bytes .../app-icons/tray/new-windowTemplate@2x.png | Bin 0 -> 626 bytes src/services/tray.ts | 155 +++++++++++++----- src/services/window.ts | 48 +++++- translations/en/server.json | 3 +- 11 files changed, 156 insertions(+), 50 deletions(-) create mode 100644 images/app-icons/tray/new-windowTemplate-inverted.png create mode 100644 images/app-icons/tray/new-windowTemplate-inverted@1.25x.png create mode 100644 images/app-icons/tray/new-windowTemplate-inverted@1.5x.png create mode 100644 images/app-icons/tray/new-windowTemplate-inverted@2x.png create mode 100644 images/app-icons/tray/new-windowTemplate.png create mode 100644 images/app-icons/tray/new-windowTemplate@1.25x.png create mode 100644 images/app-icons/tray/new-windowTemplate@1.5x.png create mode 100644 images/app-icons/tray/new-windowTemplate@2x.png diff --git a/images/app-icons/tray/new-windowTemplate-inverted.png b/images/app-icons/tray/new-windowTemplate-inverted.png new file mode 100644 index 0000000000000000000000000000000000000000..b587fe0bbfbc27183bf610e90242885d6edcb539 GIT binary patch literal 348 zcmV-i0i*tjP)wJ0!)A#1C)P64hFae?vR9} zsWxA?lKKn;yaA8SN(0dgpaagLAp+FEGjR1!0_T3y*DKdw0b^jtdR!yh#`cM1_ZdWx zF40@y*l9mGSZ7gQLjJ$sPH|@a2>4v*Uk-dz4Lkq`z`oD*x@IdghAZzUzz6VZSpcV* z&#w}e2?uk_z4h}f@G=HZ0S~y4Kd<@A;XNq zvlTPTtvPZtTQ;*{%@$R|CdW4IT>@|lern+n_^4S^pEC{2i(^PwDq$bE_@%-fpf8Rg zp+`%^4#!G-=5feGunX*Io>gsd6>DDE0&uKS+yf6) zLedHcOJD-%0W)&52TTSg)+Pj)0?vVrpjPX0v|U$W8pPUC)CHb2y1;2bn8q9~a%`aE zl)wvcqV+>P&qjzEgl@a&{&n;Td3Rrd=iq8MU=ElKOzUXx_kC1zSR2zEjPrG5QV=Uk7I#7QCMUX*sx&164rKoLIVdN@8W_rScD0NW{V)pkOHy&{Ax~v=(ag57>yEptWf&6HqJ# zg)~Vt`F3|~-hsnr*S$C&8CZ7r?Cg2pnK@S%Lf|Mz-XeEX!V6slJWw@FOgJLOAp%Yx zGGJ~BBpmPuDD@mHfhf2JJOh>!A4OcuCa?;8ikL2h;5FeK@EJHYWxM+UTm`-Z&g)D9 za8cj~hIPsd={_T@0QkBM1l>z(C<%=(V)!;Mh-aSZNMrx2Zg&~D z-zN}x;3M!M@#=Sg2Yn;qqQ2!oks#U@(%Cx{mj<}#2rl#pT7`7>CNMg-r%FbB!YaUV zk=PkaC?5$P^TumE-!#4*hPudDw^|kO3h+oWKStS*k;#~@15X560*`?kdd{XrAc8Lg zFMwm_I5OZlaA7D3Kj7R;U>;ZpPAjoE={S(=4X|Kxei8z4l_!9AN~Io{F>_`ly9B%k zPMZIcctOku>%c3$UooL|O|^tKi>gu)h;FqFyfyM&L!d2pgs}uN8ChOiMP@?lVoUCz zR@mmoP&*04f@B+*=(1yCyrFE!9ibuSPs|P;+LgQkypUhtH5E+!wh!FV_BU?$x}*=7t=&-Er(cg#}RM##+Auw}7X>d9wn$J9~z3 zp?90ID^$r#G(`a0|dv={SIuH?T5BXe^clcf+IL8!~yi z0VbL3%)Hre{==R!&Zi6@IKw5-1!7|NWN$T4d4Lia3*cBbTLC-)&t{wo{T!YEbX;m* zz(Tgz5dKbO$C`b}z(5+O*TAjPep9eU z9Mclg`Ti=!ne-dr=Rg0fWlRO|3iN?1$%Wop0fHg~U;wOuPw^5MCO&^k*tj0d#V^wD zlfWAb?g6fWkviOHxpEiiLEl=wA0Dv;zExwiJy#QFk}JJ!RZ^KAQ!m+zN(Y9MgKPBq d*fdT$=N-zgNZA9LKn?%^002ovPDHLkV1mqFi_`!B literal 0 HcmV?d00001 diff --git a/images/app-icons/tray/new-windowTemplate@1.25x.png b/images/app-icons/tray/new-windowTemplate@1.25x.png new file mode 100644 index 0000000000000000000000000000000000000000..b52f2158d5ac4d95dfbd4cbf82f7cc5dafa810c5 GIT binary patch literal 409 zcmV;K0cQS*P)YU6vlt|=2o$~IQRe+2VMMw?mD=ZqV#!O-FyfYItkJT5Yz`ya1`7{L`0+@P2%!h zJ;o;5=m#eW=YPI)a^v_!0(j~n15&GS{2eY{9FPNBl6;H;(f0y4vvDiHP!4ru2rOeb zTNH}V zC@713Sc%C}^PG+F{Z_dQi4yDpyLwKl0z!o?cD4Ws1egL&fepjeI?xB2zwOW)T~i%(fqO|8I5r7=F-Is&Y@pZ4fJfj+_I=$?Ml?0B z(+-9GYv~h;(|rOS%xVN+4wyAVYbo~2KCYD<4hOQoNRY1RmjbJ?q64mgZD3Olao^6B zWX}}u1J6q06@Lj_+sXgy0bBJ8NY!oRdMKZy>=*D3C!%bA!HCNs00000NkvXXu0mjf DAmOSF literal 0 HcmV?d00001 diff --git a/images/app-icons/tray/new-windowTemplate@1.5x.png b/images/app-icons/tray/new-windowTemplate@1.5x.png new file mode 100644 index 0000000000000000000000000000000000000000..61172b73248887298524200e378fcb76181deecc GIT binary patch literal 481 zcmV<70UrK|P)Inm;DAry7I+LT zsR6A(Xj6KZ&ILjZIFKcqjyZ7X0c>F2TyFW=5TGetE(8Fm06)MfkP6HdRO)3Lz?*at z19(e%z<0^pPvQu)8A9HYEDKCdB6-cIP&wwc~1J0v86X+R8SF;F!x9}uN#I|_e3#9-O(H`(5#Z!?3o`HIFk+lH4 z`F9H2ZeT%Iy!+@a3jyp0w=ybz4d7TZL#-Q8VKh3s1Yk3o#3Ty256!cH=aVtbNVKK! zw$X#mRP=0+JO=11iCmP7%|OPN3McoPxY4w=naWH*cl6M^z*w{^UMG@GrK1H@!$=tc zm%vM2Mh11Nw_@J`ufUZqlEhuB>g#xPaG=>oMqe(dXLP=C*fRgU>6<@(Lrl(h?r+O4 XxGJCsS42yu00000NkvXXu0mjfzoF4= literal 0 HcmV?d00001 diff --git a/images/app-icons/tray/new-windowTemplate@2x.png b/images/app-icons/tray/new-windowTemplate@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a1ced05691f3434a8bfe412c9fed279be3363737 GIT binary patch literal 626 zcmV-&0*(ENP)=L;ko_j#}VOz-U)xX(EIvFk1(0 z3vd4ga--`QKwzu_FM!34k0KcJ5m*C0SP)J>SAlP0PIBx6SESQ90VshbU;#KXsJk3! z?@Q8E0?tQbAkjG$69~Sb<2Vp~Mf#;0T~jd}S3a^R1=fK*AuT$vyZ}~!hr^S;Lf}2{ zu4C&DfJb!z0Q5BHfox30VUJ$bWQ=m7IIB_0M-{D1d)5ZfS#7W5o^hJkd4V`+3&^)r zo+z?k>AP=oyKI^wZPRK^ithqX#B*&nYeK1l={E38N^{^Ta7W+iqyPlvi@*jjWsV~S zUII6of^ZGaJqPB1ZQ!CBOQJoF#Cr{#Gd;f(0Kv)&z+2#!_4 zA8Z3#`oC#P>pHM25U#56v;`2->L>8V@P8QqRlTEZ3m{dH`5`M(Q(Ai!y(3s(8XZYh zVEPE+MAi;8EDcOHzkt(CI4L)V8Wd+MC)hZ9`GEvZY;3g`EAf=`nN5+0KTdg z#NOM}(5jUc`vS)+-0hnmYHh_DA3IG5A M07*qoM6N<$f^Iq!cK`qY literal 0 HcmV?d00001 diff --git a/src/services/tray.ts b/src/services/tray.ts index c35e2c823..ab1dc0af0 100644 --- a/src/services/tray.ts +++ b/src/services/tray.ts @@ -1,4 +1,4 @@ -import { Menu, Tray } from "electron"; +import { Menu, Tray, BrowserWindow } from "electron"; import path from "path"; import windowService from "./window.js"; import optionService from "./options.js"; @@ -17,7 +17,7 @@ import cls from "./cls.js"; let tray: Tray; // `mainWindow.isVisible` doesn't work with `mainWindow.show` and `mainWindow.hide` - it returns `false` when the window // is minimized -let isVisible = true; +let windowVisibilityMap: Record = {};; // Dictionary for storing window ID and its visibility status function getTrayIconPath() { let name: string; @@ -37,53 +37,87 @@ function getIconPath(name: string) { return path.join(path.dirname(fileURLToPath(import.meta.url)), "../..", "images", "app-icons", "tray", `${name}Template${suffix}.png`); } -function registerVisibilityListener() { - const mainWindow = windowService.getMainWindow(); - if (!mainWindow) { +function registerVisibilityListener(window: BrowserWindow) { + if (!window) { return; } // They need to be registered before the tray updater is registered - mainWindow.on("show", () => { - isVisible = true; + window.on("show", () => { + windowVisibilityMap[window.id] = true; updateTrayMenu(); }); - mainWindow.on("hide", () => { - isVisible = false; + window.on("hide", () => { + windowVisibilityMap[window.id] = false; updateTrayMenu(); }); - mainWindow.on("minimize", updateTrayMenu); - mainWindow.on("maximize", updateTrayMenu); - if (!isMac) { - // macOS uses template icons which work great on dark & light themes. - nativeTheme.on("updated", updateTrayMenu); - } - ipcMain.on("reload-tray", updateTrayMenu); - i18next.on("languageChanged", updateTrayMenu); + window.on("minimize", updateTrayMenu); + window.on("maximize", updateTrayMenu); } -function updateTrayMenu() { - const mainWindow = windowService.getMainWindow(); - if (!mainWindow) { +function getWindowTitle(window: BrowserWindow | null) { + if (!window) { return; } + const title = window.getTitle(); + const titleWithoutAppName = title.replace(/\s-\s[^-]+$/, ''); // Remove the name of the app - function ensureVisible() { - if (mainWindow) { - mainWindow.show(); - mainWindow.focus(); + // Limit title maximum length to 17 + if (titleWithoutAppName.length > 20) { + return titleWithoutAppName.substring(0, 17) + '...'; + } + + return titleWithoutAppName; +} + +function updateWindowVisibilityMap(allWindows: BrowserWindow[]) { + const currentWindowIds: number[] = allWindows.map(window => window.id); + + // Deleting closed windows from windowVisibilityMap + for (const [id, visibility] of Object.entries(windowVisibilityMap)) { + const windowId = Number(id); + if (!currentWindowIds.includes(windowId)) { + delete windowVisibilityMap[windowId]; + } + } + + // Iterate through allWindows to make sure the ID of each window exists in windowVisibilityMap + allWindows.forEach(window => { + const windowId = window.id; + if (!(windowId in windowVisibilityMap)) { + // If it does not exist, it is the newly created window + windowVisibilityMap[windowId] = true; + registerVisibilityListener(window); + } + }); +} + + +function updateTrayMenu() { + const lastFocusedWindow = windowService.getLastFocusedWindow(); + const allWindows = windowService.getAllWindows(); + updateWindowVisibilityMap(allWindows); + + function ensureVisible(win: BrowserWindow) { + if (win) { + win.show(); + win.focus(); } } function triggerKeyboardAction(actionName: KeyboardActionNames) { - mainWindow?.webContents.send("globalShortcut", actionName); - ensureVisible(); + if (lastFocusedWindow){ + lastFocusedWindow.webContents.send("globalShortcut", actionName); + ensureVisible(lastFocusedWindow); + } } function openInSameTab(note: BNote | BRecentNote) { - mainWindow?.webContents.send("openInSameTab", note.noteId); - ensureVisible(); + if (lastFocusedWindow){ + lastFocusedWindow.webContents.send("openInSameTab", note.noteId); + ensureVisible(lastFocusedWindow); + } } function buildBookmarksMenu() { @@ -144,20 +178,44 @@ function updateTrayMenu() { return menuItems; } - const contextMenu = Menu.buildFromTemplate([ - { - label: t("tray.show-windows"), + const windowVisibilityMenuItems: Electron.MenuItemConstructorOptions[] = []; + + // Only call getWindowTitle if windowVisibilityMap has more than one window + const showTitle = Object.keys(windowVisibilityMap).length > 1; + + for (const idStr in windowVisibilityMap) { + const id = parseInt(idStr, 10); // Get the ID of the window and make sure it is a number + const isVisible = windowVisibilityMap[id]; + const win = allWindows.find(w => w.id === id); + if (!win) { + continue; + } + windowVisibilityMenuItems.push({ + label: showTitle ? `${t("tray.show-windows")}: ${getWindowTitle(win)}` : t("tray.show-windows"), type: "checkbox", checked: isVisible, click: () => { if (isVisible) { - mainWindow.hide(); + win.hide(); + windowVisibilityMap[id] = false; } else { - ensureVisible(); + ensureVisible(win); + windowVisibilityMap[id] = true; } } - }, + }); + } + + + const contextMenu = Menu.buildFromTemplate([ + ...windowVisibilityMenuItems, { type: "separator" }, + { + label: t("tray.open_new_window"), + type: "normal", + icon: getIconPath("new-window"), + click: () => triggerKeyboardAction("openNewWindow") + }, { label: t("tray.new-note"), type: "normal", @@ -188,7 +246,10 @@ function updateTrayMenu() { type: "normal", icon: getIconPath("close"), click: () => { - mainWindow.close(); + const windows = BrowserWindow.getAllWindows(); + windows.forEach(window => { + window.close(); + }); } } ]); @@ -197,16 +258,18 @@ function updateTrayMenu() { } function changeVisibility() { - const window = windowService.getMainWindow(); - if (!window) { + const lastFocusedWindow = windowService.getLastFocusedWindow(); + + if (!lastFocusedWindow) { return; } - if (isVisible) { - window.hide(); + // If the window is visible, hide it + if (windowVisibilityMap[lastFocusedWindow.id]) { + lastFocusedWindow.hide(); } else { - window.show(); - window.focus(); + lastFocusedWindow.show(); + lastFocusedWindow.focus(); } } @@ -221,9 +284,15 @@ function createTray() { tray.on("click", changeVisibility); updateTrayMenu(); - registerVisibilityListener(); + if (!isMac) { + // macOS uses template icons which work great on dark & light themes. + nativeTheme.on("updated", updateTrayMenu); + } + ipcMain.on("reload-tray", updateTrayMenu); + i18next.on("languageChanged", updateTrayMenu); } export default { - createTray + createTray, + updateTrayMenu }; diff --git a/src/services/window.ts b/src/services/window.ts index 8b5697609..12c125b6d 100644 --- a/src/services/window.ts +++ b/src/services/window.ts @@ -11,6 +11,7 @@ import remoteMain from "@electron/remote/main/index.js"; import { BrowserWindow, shell, type App, type BrowserWindowConstructorOptions, type WebContents } from "electron"; import { dialog, ipcMain } from "electron"; import { formatDownloadTitle, isDev, isMac, isWindows } from "./utils.js"; +import tray from "./tray.js"; import { fileURLToPath } from "url"; import { dirname } from "path"; @@ -19,6 +20,26 @@ import { t } from "i18next"; // Prevent the window being garbage collected let mainWindow: BrowserWindow | null; let setupWindow: BrowserWindow | null; +let allWindows: BrowserWindow[] = []; // // Used to store all windows, sorted by the order of focus. + +function trackWindowFocus(win: BrowserWindow) { + // We need to get the last focused window from allWindows. If the last window is closed, we return the previous window. + // Therefore, we need to push the window into the allWindows array every time it gets focused. + win.on("focus", () => { + allWindows = allWindows.filter(w => !w.isDestroyed() && w !== win); + allWindows.push(win); + if (!optionService.getOptionBool("disableTray")) { + tray.updateTrayMenu(); + } + }); + + win.on("closed", () => { + allWindows = allWindows.filter(w => !w.isDestroyed()); + if (!optionService.getOptionBool("disableTray")) { + tray.updateTrayMenu(); + } + }); +} async function createExtraWindow(extraWindowHash: string) { const spellcheckEnabled = optionService.getOptionBool("spellCheckEnabled"); @@ -42,6 +63,8 @@ async function createExtraWindow(extraWindowHash: string) { win.loadURL(`http://127.0.0.1:${port}/?extraWindow=1${extraWindowHash}`); configureWebContents(win.webContents, spellcheckEnabled); + + trackWindowFocus(win); } ipcMain.on("create-extra-window", (event, arg) => { @@ -154,18 +177,21 @@ async function createMainWindow(app: App) { configureWebContents(mainWindow.webContents, spellcheckEnabled); app.on("second-instance", (event, commandLine) => { + const lastFocusedWindow = getLastFocusedWindow(); if (commandLine.includes("--new-window")) { createExtraWindow(""); - } else if (mainWindow) { + } else if (lastFocusedWindow) { // Someone tried to run a second instance, we should focus our window. // see www.ts "requestSingleInstanceLock" for the rest of this logic with explanation - if (mainWindow.isMinimized()) { - mainWindow.restore(); + if (lastFocusedWindow.isMinimized()) { + lastFocusedWindow.restore(); } - mainWindow.show(); - mainWindow.focus(); + lastFocusedWindow.show(); + lastFocusedWindow.focus(); } }); + + trackWindowFocus(mainWindow); } function getWindowExtraOpts() { @@ -296,10 +322,20 @@ function getMainWindow() { return mainWindow; } +function getLastFocusedWindow() { + return allWindows.length > 0 ? allWindows[allWindows.length - 1] : null; +} + +function getAllWindows(){ + return allWindows; +} + export default { createMainWindow, createSetupWindow, closeSetupWindow, registerGlobalShortcuts, - getMainWindow + getMainWindow, + getLastFocusedWindow, + getAllWindows }; diff --git a/translations/en/server.json b/translations/en/server.json index f25927fd6..6267a0060 100644 --- a/translations/en/server.json +++ b/translations/en/server.json @@ -272,7 +272,8 @@ "bookmarks": "Bookmarks", "today": "Open today's journal note", "new-note": "New note", - "show-windows": "Show windows" + "show-windows": "Show windows", + "open_new_window": "Open new window" }, "migration": { "old_version": "Direct migration from your current version is not supported. Please upgrade to the latest v0.60.4 first and only then to this version.", From da59dd2ecefdccbbb8bf37fd235024cda333c8d8 Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Fri, 21 Mar 2025 13:56:21 +0800 Subject: [PATCH 03/16] Add Chinese translation --- translations/cn/server.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/translations/cn/server.json b/translations/cn/server.json index 619bb0c7a..aaaceb7e2 100644 --- a/translations/cn/server.json +++ b/translations/cn/server.json @@ -271,7 +271,8 @@ "bookmarks": "书签", "today": "打开今天的日记笔记", "new-note": "新建笔记", - "show-windows": "显示窗口" + "show-windows": "显示窗口", + "open_new_window": "打开新窗口" }, "migration": { "old_version": "由您当前版本的直接迁移不被支持。请先升级到最新的 v0.60.4 然后再到这个版本。", From 87c70cb46e8efcb722bc8c51f93d2e5ae0c31b2c Mon Sep 17 00:00:00 2001 From: SiriusXT <1160925501@qq.com> Date: Sun, 23 Mar 2025 10:44:01 +0800 Subject: [PATCH 04/16] Fixed focusing on old windows when opening new windows from tray --- src/services/tray.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/services/tray.ts b/src/services/tray.ts index ab1dc0af0..2933e49fc 100644 --- a/src/services/tray.ts +++ b/src/services/tray.ts @@ -106,6 +106,12 @@ function updateTrayMenu() { } } + function openNewWindow() { + if (lastFocusedWindow){ + lastFocusedWindow.webContents.send("globalShortcut", "openNewWindow"); + } + } + function triggerKeyboardAction(actionName: KeyboardActionNames) { if (lastFocusedWindow){ lastFocusedWindow.webContents.send("globalShortcut", actionName); @@ -214,7 +220,7 @@ function updateTrayMenu() { label: t("tray.open_new_window"), type: "normal", icon: getIconPath("new-window"), - click: () => triggerKeyboardAction("openNewWindow") + click: () => openNewWindow() }, { label: t("tray.new-note"), From 9b96cb61cc453a39c01e5a15eba2f2d2a2de7274 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 02:59:03 +0000 Subject: [PATCH 05/16] chore(deps): update electron-forge monorepo to v7.8.0 --- package-lock.json | 243 +++++++++++++++++++++++----------------------- package.json | 16 +-- 2 files changed, 130 insertions(+), 129 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24b1755ef..dbd375048 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,14 +100,14 @@ "trilium": "src/main.js" }, "devDependencies": { - "@electron-forge/cli": "7.7.0", - "@electron-forge/maker-deb": "7.7.0", - "@electron-forge/maker-dmg": "7.7.0", - "@electron-forge/maker-flatpak": "7.7.0", - "@electron-forge/maker-rpm": "7.7.0", - "@electron-forge/maker-squirrel": "7.7.0", - "@electron-forge/maker-zip": "7.7.0", - "@electron-forge/plugin-auto-unpack-natives": "7.7.0", + "@electron-forge/cli": "7.8.0", + "@electron-forge/maker-deb": "7.8.0", + "@electron-forge/maker-dmg": "7.8.0", + "@electron-forge/maker-flatpak": "7.8.0", + "@electron-forge/maker-rpm": "7.8.0", + "@electron-forge/maker-squirrel": "7.8.0", + "@electron-forge/maker-zip": "7.8.0", + "@electron-forge/plugin-auto-unpack-natives": "7.8.0", "@electron/rebuild": "3.7.1", "@eslint/js": "9.23.0", "@fullcalendar/core": "6.1.15", @@ -569,9 +569,9 @@ } }, "node_modules/@electron-forge/cli": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.7.0.tgz", - "integrity": "sha512-QfnjghmlHMb7dyArR5cbPA+MP9ff/ulWZi6R/a5MkHlKyhrysRfjzDtZDsmkEv9mGQgRwylssgXrZrKHGlxFkw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.8.0.tgz", + "integrity": "sha512-XZ+Hg7pxeE9pgrahqcpMlND+VH0l0UTZLyO5wkI+YfanNyBQksB2mw24XeEtCA6x8F2IaEYdIGgijmPF6qpjzA==", "dev": true, "funding": [ { @@ -585,15 +585,16 @@ ], "license": "MIT", "dependencies": { - "@electron-forge/core": "7.7.0", - "@electron-forge/core-utils": "7.7.0", - "@electron-forge/shared-types": "7.7.0", + "@electron-forge/core": "7.8.0", + "@electron-forge/core-utils": "7.8.0", + "@electron-forge/shared-types": "7.8.0", "@electron/get": "^3.0.0", "chalk": "^4.0.0", "commander": "^11.1.0", "debug": "^4.3.1", "fs-extra": "^10.0.0", "listr2": "^7.0.2", + "log-symbols": "^4.0.0", "semver": "^7.2.1" }, "bin": { @@ -634,9 +635,9 @@ } }, "node_modules/@electron-forge/core": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/core/-/core-7.7.0.tgz", - "integrity": "sha512-BWhg1Zw1bhpDuZowGH3lXDiL9zZBsYFNjtqyMqmkjcEm5xf9Dzs8mpRpNjtkpf3jit3LB4PNGMLj3c8ix0h4vQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/core/-/core-7.8.0.tgz", + "integrity": "sha512-7byf660ECZND+irOhGxvpmRXjk1bMrsTWh5J2AZMEvaXI8tub9OrZY9VSbi5fcDt0lpHPKmgVk7NRf/ZjJ+beQ==", "dev": true, "funding": [ { @@ -650,17 +651,17 @@ ], "license": "MIT", "dependencies": { - "@electron-forge/core-utils": "7.7.0", - "@electron-forge/maker-base": "7.7.0", - "@electron-forge/plugin-base": "7.7.0", - "@electron-forge/publisher-base": "7.7.0", - "@electron-forge/shared-types": "7.7.0", - "@electron-forge/template-base": "7.7.0", - "@electron-forge/template-vite": "7.7.0", - "@electron-forge/template-vite-typescript": "7.7.0", - "@electron-forge/template-webpack": "7.7.0", - "@electron-forge/template-webpack-typescript": "7.7.0", - "@electron-forge/tracer": "7.7.0", + "@electron-forge/core-utils": "7.8.0", + "@electron-forge/maker-base": "7.8.0", + "@electron-forge/plugin-base": "7.8.0", + "@electron-forge/publisher-base": "7.8.0", + "@electron-forge/shared-types": "7.8.0", + "@electron-forge/template-base": "7.8.0", + "@electron-forge/template-vite": "7.8.0", + "@electron-forge/template-vite-typescript": "7.8.0", + "@electron-forge/template-webpack": "7.8.0", + "@electron-forge/template-webpack-typescript": "7.8.0", + "@electron-forge/tracer": "7.8.0", "@electron/get": "^3.0.0", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", @@ -689,13 +690,13 @@ } }, "node_modules/@electron-forge/core-utils": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/core-utils/-/core-utils-7.7.0.tgz", - "integrity": "sha512-kgOkiLzqnySkcpt26rBg8AoZsI1ID3f6s/dQlzfRJisWZTKTu4ryiMcaC0F07DVjaYFnEl9SQ86IvkTcyS97mQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/core-utils/-/core-utils-7.8.0.tgz", + "integrity": "sha512-ZioRzqkXVOGuwkfvXN/FPZxcssJ9AkOZx6RvxomQn90F77G2KfEbw4ZwAxVTQ+jWNUzydTic5qavWle++Y5IeA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.7.0", + "@electron-forge/shared-types": "7.8.0", "@electron/rebuild": "^3.7.0", "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", @@ -766,13 +767,13 @@ } }, "node_modules/@electron-forge/maker-base": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-base/-/maker-base-7.7.0.tgz", - "integrity": "sha512-9u+mmBLBAUHuH0+IGw94EGVTDD4CPKX05h5pp5/PIaijy16ss5dymK4vEp3s2XJMFlza2PsCgLLYBgDcAE2Dqg==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-base/-/maker-base-7.8.0.tgz", + "integrity": "sha512-yGRvz70w+NnKO7PhzNFRgYM+x6kxYFgpbChJIQBs3WChd9bGjL+MZLrwYqmxOFLpWNwRAJ6PEi4E/8U5GgV6AQ==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.7.0", + "@electron-forge/shared-types": "7.8.0", "fs-extra": "^10.0.0", "which": "^2.0.2" }, @@ -809,14 +810,14 @@ } }, "node_modules/@electron-forge/maker-deb": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-deb/-/maker-deb-7.7.0.tgz", - "integrity": "sha512-yMT0TWpCwXaC9+AYpSr9PBIhcZR297wdJUk5PnEnIROsvOW2y1sh7ny7YdHXTxkvhWdbqY8sLQruL3BE+CyE8w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-deb/-/maker-deb-7.8.0.tgz", + "integrity": "sha512-9jjhLm/1IBIo0UuRdELgvBhUkNjK3tHNlUsrqeb8EJwWJZShbPwHYZJj+VbgjQfJFFzhHwBBDJViBXJ/4ePv+g==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.7.0", - "@electron-forge/shared-types": "7.7.0" + "@electron-forge/maker-base": "7.8.0", + "@electron-forge/shared-types": "7.8.0" }, "engines": { "node": ">= 16.4.0" @@ -826,14 +827,14 @@ } }, "node_modules/@electron-forge/maker-dmg": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-dmg/-/maker-dmg-7.7.0.tgz", - "integrity": "sha512-Hq4nsY6eOdtigN4RLc9i2SbLEr46J6FfbdU+r39R/EVIJ82WRk7JPrCqbckEM7KY1TjhmrnhPWeviWoGAjbXhA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-dmg/-/maker-dmg-7.8.0.tgz", + "integrity": "sha512-ml6GpHvUyhOapIF1ALEM4zCqXiAf2+t+3FqKnjNtiVbH5fnV2CW//SWWozrvAGTrYGi/6V4s9TL/rIek0BHOPA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.7.0", - "@electron-forge/shared-types": "7.7.0", + "@electron-forge/maker-base": "7.8.0", + "@electron-forge/shared-types": "7.8.0", "fs-extra": "^10.0.0" }, "engines": { @@ -872,14 +873,14 @@ } }, "node_modules/@electron-forge/maker-flatpak": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-flatpak/-/maker-flatpak-7.7.0.tgz", - "integrity": "sha512-WDNmGTulgPe4FEgxq128TI58EtVyS2Fq3loXhfirNuzoXpBtvt0LHK447cmtKHAvZZ+R802uriTcj28L+Iub3A==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-flatpak/-/maker-flatpak-7.8.0.tgz", + "integrity": "sha512-tnOWQLVvNZVO9xWmhUHK4OsQgYUpEIn0DX1M8FkgQCYSDXcPg/CZaZ66zqj/gu1KzGAOWg1m5KlTbITRY5Jmcg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.7.0", - "@electron-forge/shared-types": "7.7.0", + "@electron-forge/maker-base": "7.8.0", + "@electron-forge/shared-types": "7.8.0", "fs-extra": "^10.0.0" }, "engines": { @@ -918,14 +919,14 @@ } }, "node_modules/@electron-forge/maker-rpm": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-rpm/-/maker-rpm-7.7.0.tgz", - "integrity": "sha512-M9cFO6bCnOuA6BwBUUw35FrnWciWeFyLuByO0KOn3zEYeBDqG2fbBgXXS6OKcRHrpnJVTwiLY5S7eviyO1DJzQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-rpm/-/maker-rpm-7.8.0.tgz", + "integrity": "sha512-oTH951NE39LOX2wYMg+C06vBZDWUP/0dsK01PlXEl5e5YfQM5Cifsk3E7BzE6BpZdWRJL3k/ETqpyYeIGNb1jw==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.7.0", - "@electron-forge/shared-types": "7.7.0" + "@electron-forge/maker-base": "7.8.0", + "@electron-forge/shared-types": "7.8.0" }, "engines": { "node": ">= 16.4.0" @@ -935,14 +936,14 @@ } }, "node_modules/@electron-forge/maker-squirrel": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-squirrel/-/maker-squirrel-7.7.0.tgz", - "integrity": "sha512-9Gcq8e6+1MuXGeE7bEpk7VTd86c0riXTsDFKW8OqwVozeBYhoCd6GU59RmI3b7mcAIKOY1cBY97B+/5bnZ8ZYg==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-squirrel/-/maker-squirrel-7.8.0.tgz", + "integrity": "sha512-On8WIyjNtNlWf8NJRRVToighGCCU+wcxytFM0F8Zx/pLszgc01bt7wIarOiAIzuIT9Z8vshAYA0iG1U099jfeA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.7.0", - "@electron-forge/shared-types": "7.7.0", + "@electron-forge/maker-base": "7.8.0", + "@electron-forge/shared-types": "7.8.0", "fs-extra": "^10.0.0" }, "engines": { @@ -981,14 +982,14 @@ } }, "node_modules/@electron-forge/maker-zip": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-zip/-/maker-zip-7.7.0.tgz", - "integrity": "sha512-/rRFiPcojk0hcn+NOfHv2SlMNvghBk1RN0nuLHbbe8r+C0vG4LJV9ee/Y0HhVKkcpapJOQ+MasXJ86fzAp5uAg==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-zip/-/maker-zip-7.8.0.tgz", + "integrity": "sha512-7MLD7GkZdlGecC9GvgBu0sWYt48p3smYvr+YCwlpdH1CTeLmWhvCqeH33a2AB0XI5CY8U8jnkG2jgdTkzr/EQw==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.7.0", - "@electron-forge/shared-types": "7.7.0", + "@electron-forge/maker-base": "7.8.0", + "@electron-forge/shared-types": "7.8.0", "cross-zip": "^4.0.0", "fs-extra": "^10.0.0", "got": "^11.8.5" @@ -1026,53 +1027,53 @@ } }, "node_modules/@electron-forge/plugin-auto-unpack-natives": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.7.0.tgz", - "integrity": "sha512-cYeD4x2oQXUyK4+DtIR6wMxcIHvyPgsJq1diEuBoQ+MFTh+s6DXZl6JvwtI3scD0XieCkzcmUmf8ygzqs124+w==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.8.0.tgz", + "integrity": "sha512-JGal5ltZmbTQ5rNq67OgGC4MJ2zjjFW0fqykHy8X9J8cgaH7SRdKkT4yYZ8jH01IAF1J57FD2zIob1MvcBqjcg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/plugin-base": "7.7.0", - "@electron-forge/shared-types": "7.7.0" + "@electron-forge/plugin-base": "7.8.0", + "@electron-forge/shared-types": "7.8.0" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/plugin-base": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-7.7.0.tgz", - "integrity": "sha512-6wisQ4ZKOWey48wFF+JHzih7AuQuVma5KauwNEju2Dh2ibwDMJmPy0FWVolMSg7XUIMbGKLADGilxX6XRv8qNQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-7.8.0.tgz", + "integrity": "sha512-rDeeChRWIp5rQVo3Uc1q0ncUvA+kWWURW7tMuQjPvy2qVSgX+jIf5krk+T1Dp06+D4YZzEIrkibRaamAaIcR1w==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.7.0" + "@electron-forge/shared-types": "7.8.0" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/publisher-base": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/publisher-base/-/publisher-base-7.7.0.tgz", - "integrity": "sha512-jHKvUc1peBBSl2t5d1x6M3CNyCMyNB+NnTO9LmA1dWFQ3oRDFwromIH5KjRqPJj6l4AyH0/XJogdO7Nn4Eyn6Q==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/publisher-base/-/publisher-base-7.8.0.tgz", + "integrity": "sha512-wrZyptJ0Uqvlh2wYzDZfIu2HgCQ+kdGiBlcucmLY4W+GUqf043O8cbYso3D9NXQxOow55QC/1saCQkgLphprPA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.7.0" + "@electron-forge/shared-types": "7.8.0" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/shared-types": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/shared-types/-/shared-types-7.7.0.tgz", - "integrity": "sha512-1zQsmudkAuHv0HnJtSJY3pvTeuN3fnSa9BR6cbeUlcpOfrnG4OTG03FqerHfyIWaBRVy7jGgif0NhKKE9azKyg==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/shared-types/-/shared-types-7.8.0.tgz", + "integrity": "sha512-Ul+7HPvAZiAirqpZm0vc9YvlkAE+2bcrI10p3t50mEtuxn5VO/mB72NXiEKfWzHm8F31JySIe9bUV6s1MHQcCw==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/tracer": "7.7.0", + "@electron-forge/tracer": "7.8.0", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", "listr2": "^7.0.2" @@ -1082,14 +1083,14 @@ } }, "node_modules/@electron-forge/template-base": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-base/-/template-base-7.7.0.tgz", - "integrity": "sha512-jwnhEHNIyQfbwJ6R8SuZIJApHKBykDr/rSgUF3km9nr2qAUSoUUV7RaJa/uiQJMtvamXenuo5K84C2NzumzS3A==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/template-base/-/template-base-7.8.0.tgz", + "integrity": "sha512-hc8NwoDqEEmZFH/p0p3MK/7xygMmI+cm8Gavoj2Mr2xS7VUUu4r3b5PwIGKvkLfPG34uwsiVwtid2t1rWGF4UA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/core-utils": "7.7.0", - "@electron-forge/shared-types": "7.7.0", + "@electron-forge/core-utils": "7.8.0", + "@electron-forge/shared-types": "7.8.0", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "fs-extra": "^10.0.0", @@ -1128,14 +1129,14 @@ } }, "node_modules/@electron-forge/template-vite": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-vite/-/template-vite-7.7.0.tgz", - "integrity": "sha512-6p+U6FDWrmF7XgSLkrO07OOgJcrrrArbnExSckGJdBnupxmIDf1Y+exwfHHKdxX6/FfkA6JST5nRGjgA5CFqcw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/template-vite/-/template-vite-7.8.0.tgz", + "integrity": "sha512-bf/jd8WzD0gU7Jet+WSi0Lm0SQmseb08WY27ZfJYEs2EVNMiwDfPicgQnOaqP++2yTrXhj1OY/rolZCP9CUyVw==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.7.0", - "@electron-forge/template-base": "7.7.0", + "@electron-forge/shared-types": "7.8.0", + "@electron-forge/template-base": "7.8.0", "fs-extra": "^10.0.0" }, "engines": { @@ -1143,14 +1144,14 @@ } }, "node_modules/@electron-forge/template-vite-typescript": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.7.0.tgz", - "integrity": "sha512-32C/+PF+hIloTdbRx7OutvqnTkkC7BHeQxNw4/zG2TfQ3cjl7JUD6A2UvTUHtv5KHkK2hDw6ZdahPwpJO41YSA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.8.0.tgz", + "integrity": "sha512-kW3CaVxKHUYuVfY+rT3iepeZ69frBRGh3YZOngLY2buCvGIqNEx+VCgrFBRDDbOKGmwQtwO1E9wp2rtC8q6Ztg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.7.0", - "@electron-forge/template-base": "7.7.0", + "@electron-forge/shared-types": "7.8.0", + "@electron-forge/template-base": "7.8.0", "fs-extra": "^10.0.0" }, "engines": { @@ -1214,14 +1215,14 @@ } }, "node_modules/@electron-forge/template-webpack": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack/-/template-webpack-7.7.0.tgz", - "integrity": "sha512-7Hb1wejKqtvPXqhelubUNAh39FtClB/4JDtWzyAsL2iC3XeB5qh6pITz8+nW/rF2qW/JAepc/lnreqKn34P2ig==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack/-/template-webpack-7.8.0.tgz", + "integrity": "sha512-AdLGC6NVgrd7Q0SaaeiwJKmSBjN6C2EHxZgLMy1yxNSpazU9m3DtYQilDjXqmCWfxkeNzdke0NaeDvLgdJSw5A==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.7.0", - "@electron-forge/template-base": "7.7.0", + "@electron-forge/shared-types": "7.8.0", + "@electron-forge/template-base": "7.8.0", "fs-extra": "^10.0.0" }, "engines": { @@ -1229,14 +1230,14 @@ } }, "node_modules/@electron-forge/template-webpack-typescript": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.7.0.tgz", - "integrity": "sha512-w1vRAjGy0MjjdEDYPpZcpkMo2e3z5uEwfJdwVOpBeha7p2WM/Y6go21K+7pSqGp8Xmq4zlE20hq5MEx8Bs8eZg==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.8.0.tgz", + "integrity": "sha512-Pl8l+gv3HzqCfFIMLxlEsoAkNd0VEWeZZ675SYyqs0/kBQUifn0bKNhVE4gUZwKGgQCcG1Gvb23KdVGD3H3XmA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.7.0", - "@electron-forge/template-base": "7.7.0", + "@electron-forge/shared-types": "7.8.0", + "@electron-forge/template-base": "7.8.0", "fs-extra": "^10.0.0" }, "engines": { @@ -1300,9 +1301,9 @@ } }, "node_modules/@electron-forge/tracer": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@electron-forge/tracer/-/tracer-7.7.0.tgz", - "integrity": "sha512-R/JiGFzWhwfVyc6ioT4l5FFChRLS4Z2tWPeQfPcyoemdpzKpI1rvMHti42gzWXFW8GdzkhG0G3ZWfKiF3y3x/Q==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@electron-forge/tracer/-/tracer-7.8.0.tgz", + "integrity": "sha512-t4fIATZEX6/7PJNfyh6tLzKEsNMpO01Nz/rgHWBxeRvjCw5UNul9OOxoM7b43vfFAO9Jv++34oI3VJ09LeVQ2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1313,9 +1314,9 @@ } }, "node_modules/@electron/asar": { - "version": "3.2.17", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.17.tgz", - "integrity": "sha512-OcWImUI686w8LkghQj9R2ynZ2ME693Ek6L1SiaAgqGKzBaTIZw3fHDqN82Rcl+EU1Gm9EgkJ5KLIY/q5DCRbbA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.3.1.tgz", + "integrity": "sha512-WtpC/+34p0skWZiarRjLAyqaAX78DofhDxnREy/V5XHfu1XEXbFCSSMcDQ6hNCPJFaPy8/NnUgYuf9uiCkvKPg==", "dev": true, "license": "MIT", "dependencies": { @@ -1511,9 +1512,9 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.2.tgz", - "integrity": "sha512-KqVlm9WMWq19lBpCXQoThC/Koaiji2zotUDYwZDaZlZZym+FXY9mQW8wN6sUQ93nkVc42f3TQ1S/XN9S1kjM5Q==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.3.tgz", + "integrity": "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -1677,13 +1678,13 @@ } }, "node_modules/@electron/universal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", - "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.2.tgz", + "integrity": "sha512-mqY1szx5/d5YLvfCDWWoJdkSIjIz+NdWN4pN0r78lYiE7De+slLpuF3lVxIT+hlJnwk5sH2wFRMl6/oUgUVO3A==", "dev": true, "license": "MIT", "dependencies": { - "@electron/asar": "^3.2.7", + "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", diff --git a/package.json b/package.json index 2f7f8d0e8..ec3db7f27 100644 --- a/package.json +++ b/package.json @@ -157,14 +157,14 @@ "yauzl": "3.2.0" }, "devDependencies": { - "@electron-forge/cli": "7.7.0", - "@electron-forge/maker-deb": "7.7.0", - "@electron-forge/maker-dmg": "7.7.0", - "@electron-forge/maker-flatpak": "7.7.0", - "@electron-forge/maker-rpm": "7.7.0", - "@electron-forge/maker-squirrel": "7.7.0", - "@electron-forge/maker-zip": "7.7.0", - "@electron-forge/plugin-auto-unpack-natives": "7.7.0", + "@electron-forge/cli": "7.8.0", + "@electron-forge/maker-deb": "7.8.0", + "@electron-forge/maker-dmg": "7.8.0", + "@electron-forge/maker-flatpak": "7.8.0", + "@electron-forge/maker-rpm": "7.8.0", + "@electron-forge/maker-squirrel": "7.8.0", + "@electron-forge/maker-zip": "7.8.0", + "@electron-forge/plugin-auto-unpack-natives": "7.8.0", "@electron/rebuild": "3.7.1", "@eslint/js": "9.23.0", "@fullcalendar/core": "6.1.15", From 269cfc46898111471642f2623e6fcdf2733e69f3 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 25 Mar 2025 10:47:13 +0200 Subject: [PATCH 06/16] feat(ci): trigger on renovate electron forge --- .github/workflows/nightly.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 0ab203be0..184f69c93 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -5,6 +5,9 @@ on: - cron: "0 2 * * *" # run at 2 AM UTC # This can be used to allow manually triggering nightlies from the web interface workflow_dispatch: + push: + branches: + - renovate/electron-forge* pull_request: paths: - .github/actions/build-electron/* From 5ec3d58f6f7d44d02342d93e6802c434c44c03d1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 26 Mar 2025 08:30:56 +0200 Subject: [PATCH 07/16] fix(electron): option does not exist --- electron.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electron.ts b/electron.ts index 6beda97cf..938440947 100644 --- a/electron.ts +++ b/electron.ts @@ -23,7 +23,7 @@ electronDl({ saveAs: true }); // needed for excalidraw export https://github.com/zadam/trilium/issues/4271 electron.app.commandLine.appendSwitch("enable-experimental-web-platform-features"); -electron.app.commandLine.appendSwitch("lang", options.getOption("formattingLocale") ?? "en"); +electron.app.commandLine.appendSwitch("lang", options.getOptionOrNull("formattingLocale") ?? "en"); electron.app.userAgentFallback = `${electron.app.getName()} ${electron.app.getVersion()}`; From b97c28bc135b5a3cff373b6a21aec1f69c3a8fb9 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Wed, 26 Mar 2025 08:10:04 +0100 Subject: [PATCH 08/16] ci: bump to node v22 -> fixes EBADENGINE warning npm warn EBADENGINE Unsupported engine { npm warn EBADENGINE package: 'node-abi@4.2.0', npm warn EBADENGINE required: { node: '>=22.12.0' }, npm warn EBADENGINE current: { node: 'v20.18.1', npm: '10.8.2' } npm warn EBADENGINE } --- .github/actions/build-server/action.yml | 2 +- .github/workflows/dev.yml | 2 +- .github/workflows/main-docker.yml | 2 +- .github/workflows/nightly.yml | 2 +- .github/workflows/release.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/build-server/action.yml b/.github/actions/build-server/action.yml index 7423b8c4a..d296838a2 100644 --- a/.github/actions/build-server/action.yml +++ b/.github/actions/build-server/action.yml @@ -11,7 +11,7 @@ runs: - name: Set up node & dependencies uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: "npm" - name: Install dependencies shell: bash diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 18ff8190b..e7bff39e9 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -26,7 +26,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: "npm" - run: npm ci diff --git a/.github/workflows/main-docker.yml b/.github/workflows/main-docker.yml index 085ae836e..25277d30a 100644 --- a/.github/workflows/main-docker.yml +++ b/.github/workflows/main-docker.yml @@ -45,7 +45,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: "npm" - name: Install npm dependencies diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index f63c9f578..95204f1d3 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -39,7 +39,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: Install dependencies run: npm ci - name: Update nightly version diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4f791bda0..b3f334ec8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,7 +36,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 - name: Run the build uses: ./.github/actions/build-electron with: From 1e713469e797b54b192aa8d2c11d9bc1be466ca0 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Wed, 26 Mar 2025 08:12:22 +0100 Subject: [PATCH 09/16] build(server): bump to latest node v22.14.0 -> fixes EBADENGINE warning npm warn EBADENGINE Unsupported engine { npm warn EBADENGINE package: 'node-abi@4.2.0', npm warn EBADENGINE required: { node: '>=22.12.0' }, npm warn EBADENGINE current: { node: 'v20.18.1', npm: '10.8.2' } npm warn EBADENGINE } --- bin/build-server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/build-server.sh b/bin/build-server.sh index 3af7ec9f5..052a8131b 100755 --- a/bin/build-server.sh +++ b/bin/build-server.sh @@ -21,7 +21,7 @@ fi echo "Selected Arch: $ARCH" # Set Node.js version and architecture-specific filename -NODE_VERSION=20.15.1 +NODE_VERSION=22.14.0 BUILD_DIR="./build" DIST_DIR="./dist" From 0cedd697cc2b5b5116d073d634b46beb24108496 Mon Sep 17 00:00:00 2001 From: --global Date: Wed, 26 Mar 2025 18:41:36 +0200 Subject: [PATCH 10/16] fix(electron): not starting on an empty DB --- src/services/options.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/services/options.ts b/src/services/options.ts index a5516df1a..3d54fde5f 100644 --- a/src/services/options.ts +++ b/src/services/options.ts @@ -25,7 +25,12 @@ function getOptionOrNull(name: OptionNames): string | null { option = becca.getOption(name); } else { // e.g. in initial sync becca is not loaded because DB is not initialized - option = sql.getRow("SELECT * FROM options WHERE name = ?", [name]); + try { + option = sql.getRow("SELECT * FROM options WHERE name = ?", [name]); + } catch (e: unknown) { + // DB is not initialized. + return null; + } } return option ? option.value : null; From c2d917b9262fec812dfdfe79e9adc7d4763edb58 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 26 Mar 2025 18:53:17 +0200 Subject: [PATCH 11/16] style(next): restyle WebKit scrollbars --- src/public/stylesheets/theme-next-dark.css | 7 ++- src/public/stylesheets/theme-next-light.css | 7 ++- src/public/stylesheets/theme-next/forms.css | 58 +++++++++++++++++++++ 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/public/stylesheets/theme-next-dark.css b/src/public/stylesheets/theme-next-dark.css index 87353887b..84a0e0eb9 100644 --- a/src/public/stylesheets/theme-next-dark.css +++ b/src/public/stylesheets/theme-next-dark.css @@ -190,8 +190,11 @@ --right-pane-item-hover-background: #ffffff26; --right-pane-item-hover-color: white; - --scrollbar-border-color: #666; - --scrollbar-background-color: #333; + --scrollbar-thumb-color: #fdfdfd5c; + --scrollbar-thumb-color-hover: #ffffff7d; + --scrollbar-border-color: unset; /* Deprecated */ + --scrollbar-background-color: unset; /* Deprecated */ + --link-color: lightskyblue; --mermaid-theme: dark; diff --git a/src/public/stylesheets/theme-next-light.css b/src/public/stylesheets/theme-next-light.css index 4060daf87..781a34a2b 100644 --- a/src/public/stylesheets/theme-next-light.css +++ b/src/public/stylesheets/theme-next-light.css @@ -189,8 +189,11 @@ --right-pane-item-hover-background: #ececec; --right-pane-item-hover-color: inherit; - --scrollbar-border-color: #ddd; - --scrollbar-background-color: #ddd; + --scrollbar-thumb-color: #0000005c; + --scrollbar-thumb-color-hover: #00000066; + --scrollbar-border-color: unset; /* Deprecated */ + --scrollbar-background-color: unset; /* Deprecated */ + --link-color: blue; --mermaid-theme: default; diff --git a/src/public/stylesheets/theme-next/forms.css b/src/public/stylesheets/theme-next/forms.css index 671a90997..402f332dc 100644 --- a/src/public/stylesheets/theme-next/forms.css +++ b/src/public/stylesheets/theme-next/forms.css @@ -660,3 +660,61 @@ a.tn-link:hover[href^="https://"]:not(.no-arrow)::after, input[type="range"] { background: transparent; } + +/* + * WebKit scrollbars + */ + +:root { + --scrollbar-thickness: 10px; + --scrollbar-thumb-thickness: 3px; + --scrollbar-thumb-hover-thickness: 8px; + --scrollbar-start-end-gap: 8px; +} + +/* Scrollbar's body */ + +::-webkit-scrollbar:vertical { + width: var(--scrollbar-thickness) !important; +} + +::-webkit-scrollbar:horizontal { + height: var(--scrollbar-thickness) !important; +} + +/* Scrollbar's thumb */ + +::-webkit-scrollbar-thumb { + --s-thumb-thickness: var(--scrollbar-thumb-thickness); + --s-thumb-color: var(--scrollbar-thumb-color); + + --s-gradient-angle: 90deg; + --s-gradient-p1: calc((var(--scrollbar-thickness) - var(--s-thumb-thickness)) / 2); + --s-gradient-p2: calc(var(--s-gradient-p1) + var(--s-thumb-thickness)); + + border: none !important; + background: linear-gradient(var(--s-gradient-angle), transparent, transparent var(--s-gradient-p1), + var(--s-thumb-color) 0px, var(--s-thumb-color) var(--s-gradient-p2), + transparent 0) !important; + + border-radius: calc(var(--scrollbar-thickness) / 2) !important; +} + +::-webkit-scrollbar-thumb:horizontal { + --s-gradient-angle: 0deg; +} + +::-webkit-scrollbar-thumb:hover { + --s-thumb-thickness: var(--scrollbar-thumb-hover-thickness); + --s-thumb-color: var(--scrollbar-thumb-color-hover); +} + +/* Scrollbar's increment/decrement buttons (repurposed as a scrollbar start/end gap) */ + +::-webkit-scrollbar-button:vertical { + height: var(--scrollbar-start-end-gap); +} + +::-webkit-scrollbar-button:horizontal { + width: var(--scrollbar-start-end-gap); +} \ No newline at end of file From e85b7f5e79662680c8f39080649419004a491eb8 Mon Sep 17 00:00:00 2001 From: --global Date: Wed, 26 Mar 2025 18:56:28 +0200 Subject: [PATCH 12/16] chore(vscode): add playwright to recommendations --- .vscode/extensions.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 5eb23aafc..1eeb900b2 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "lokalise.i18n-ally", "editorconfig.editorconfig", - "vitest.explorer" + "vitest.explorer", + "ms-playwright.playwright" ] } From 4b9ea651a1c956b83856b1c3be59988ab3d3c9c3 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 26 Mar 2025 19:06:22 +0200 Subject: [PATCH 13/16] style(next): restyle Firefox scrollbars --- src/public/stylesheets/theme-next/forms.css | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/public/stylesheets/theme-next/forms.css b/src/public/stylesheets/theme-next/forms.css index 402f332dc..8dc997fda 100644 --- a/src/public/stylesheets/theme-next/forms.css +++ b/src/public/stylesheets/theme-next/forms.css @@ -717,4 +717,16 @@ input[type="range"] { ::-webkit-scrollbar-button:horizontal { width: var(--scrollbar-start-end-gap); +} + +/* + * Firefox scrollbars + * + * Unsupported features: --scrollbar-thumb-thickness, --scrollbar-thumb-hover-thickness, + * --scrollbar-start-end-gap, --scrollbar-thumb-color-hover. + */ + +:root { + scrollbar-color: var(--scrollbar-thumb-color) transparent; + scrollbar-width: var(--scrollbar-thickness); } \ No newline at end of file From fd0018677c95665f876205e13e757b32fa5b521f Mon Sep 17 00:00:00 2001 From: --global Date: Wed, 26 Mar 2025 19:11:07 +0200 Subject: [PATCH 14/16] test(i18n): add refresh button click after language change --- e2e/i18n.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/e2e/i18n.spec.ts b/e2e/i18n.spec.ts index 21fd1880b..0124f271b 100644 --- a/e2e/i18n.spec.ts +++ b/e2e/i18n.spec.ts @@ -47,6 +47,10 @@ test("User can change language from settings", async ({ page, context }) => { // Select Chinese and ensure the translation is set. await languageCombobox.selectOption("cn"); + + // Press the refresh button. + await app.currentNoteSplit.getByRole("button", { name: "Restart the application" }).click(); + await expect(app.currentNoteSplit).toContainText("一周的第一天", { timeout: 15000 }); await expect(languageCombobox).toHaveValue("cn"); From be9b19d81cd1d8c5cf0acb43fb1a68b27fec4342 Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 26 Mar 2025 19:15:29 +0200 Subject: [PATCH 15/16] style(next): improve CSS formatting --- src/public/stylesheets/theme-next/forms.css | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/public/stylesheets/theme-next/forms.css b/src/public/stylesheets/theme-next/forms.css index 8dc997fda..ecab8bdc1 100644 --- a/src/public/stylesheets/theme-next/forms.css +++ b/src/public/stylesheets/theme-next/forms.css @@ -693,9 +693,10 @@ input[type="range"] { --s-gradient-p2: calc(var(--s-gradient-p1) + var(--s-thumb-thickness)); border: none !important; - background: linear-gradient(var(--s-gradient-angle), transparent, transparent var(--s-gradient-p1), - var(--s-thumb-color) 0px, var(--s-thumb-color) var(--s-gradient-p2), - transparent 0) !important; + background: linear-gradient(var(--s-gradient-angle), + transparent, transparent var(--s-gradient-p1), + var(--s-thumb-color) 0px, var(--s-thumb-color) var(--s-gradient-p2), + transparent 0) !important; border-radius: calc(var(--scrollbar-thickness) / 2) !important; } @@ -705,8 +706,8 @@ input[type="range"] { } ::-webkit-scrollbar-thumb:hover { - --s-thumb-thickness: var(--scrollbar-thumb-hover-thickness); - --s-thumb-color: var(--scrollbar-thumb-color-hover); + --s-thumb-thickness: var(--scrollbar-thumb-hover-thickness); + --s-thumb-color: var(--scrollbar-thumb-color-hover); } /* Scrollbar's increment/decrement buttons (repurposed as a scrollbar start/end gap) */ @@ -723,7 +724,7 @@ input[type="range"] { * Firefox scrollbars * * Unsupported features: --scrollbar-thumb-thickness, --scrollbar-thumb-hover-thickness, - * --scrollbar-start-end-gap, --scrollbar-thumb-color-hover. + * --scrollbar-start-end-gap, --scrollbar-thumb-color-hover. */ :root { From dcd64554ebf37995d692633371c62d7903ce3d1d Mon Sep 17 00:00:00 2001 From: Adorian Doran Date: Wed, 26 Mar 2025 19:33:11 +0200 Subject: [PATCH 16/16] style(next): fix Firefox scrollbar styles overriding WebKit scrollbar styles --- src/public/stylesheets/theme-next/forms.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/public/stylesheets/theme-next/forms.css b/src/public/stylesheets/theme-next/forms.css index ecab8bdc1..16fec7c1e 100644 --- a/src/public/stylesheets/theme-next/forms.css +++ b/src/public/stylesheets/theme-next/forms.css @@ -730,4 +730,13 @@ input[type="range"] { :root { scrollbar-color: var(--scrollbar-thumb-color) transparent; scrollbar-width: var(--scrollbar-thickness); +} + +@supports selector(::-webkit-scrollbar) { + /* Prevent the scrollbar-color and scrollbar-width properties to override the custom styles + * defined using ::-webkit-scrollbar. */ + :root { + scrollbar-color: unset; + scrollbar-width: unset; + } } \ No newline at end of file