From e01d24c94e89731fa4a02c5bb77f256735d9dd6f Mon Sep 17 00:00:00 2001 From: viktor44 Date: Mon, 11 Nov 2024 01:22:19 +0100 Subject: [PATCH 1/9] Tray icon --- packages/app/electron-builder.yml | 2 + packages/app/src/app-main.js | 49 ++++++++++++++++++- .../services/browser-window/interface.ts | 4 ++ .../services/services/browser-window/main.ts | 3 +- .../services/browser-window/manager.ts | 6 +++ packages/app/src/utils/process.ts | 1 + .../src/windows/utils/GenericWindowManager.ts | 4 ++ .../src/windows/utils/MainWindowManager.ts | 13 ++++- 8 files changed, 79 insertions(+), 3 deletions(-) diff --git a/packages/app/electron-builder.yml b/packages/app/electron-builder.yml index 1586e8d3..b85bc13e 100644 --- a/packages/app/electron-builder.yml +++ b/packages/app/electron-builder.yml @@ -64,6 +64,8 @@ extraResources: to: '.env.production' - from: 'build/icon_512x512.png' to: 'icon.png' + - from: 'build/icon.ico' + to: 'icon.ico' files: - '!**/*.map' diff --git a/packages/app/src/app-main.js b/packages/app/src/app-main.js index ed9eca12..0496d424 100644 --- a/packages/app/src/app-main.js +++ b/packages/app/src/app-main.js @@ -1,7 +1,11 @@ +import * as path from 'path'; import { EventEmitter } from 'events'; import { parse } from 'url'; -import { app, session, webContents } from 'electron'; +import { app, webContents, BrowserWindow, Menu, Tray } from 'electron'; import log from 'electron-log'; + +import { isWindows } from './utils/process'; +import { isPackaged } from './utils/env'; import services from './services/servicesManager'; import { observer } from './services/lib/helpers'; import { handleError } from './services/api/helpers'; @@ -9,6 +13,7 @@ import { start } from './webui/webUIHandler'; import { enhanceSession } from './session'; export default class BrowserXAppMain extends EventEmitter { + init() { this.initAppLifeCycle(); this.initProcessManagerAnalytics().catch(handleError()); @@ -40,9 +45,51 @@ export default class BrowserXAppMain extends EventEmitter { return services.processManager.addObserver(observer({ onWillKillProcess })); } + getTrayIcon() { + let result = undefined; + + if (isWindows) { + result = isPackaged + ? path.resolve(process.resourcesPath, 'icon.ico') + : path.resolve(__dirname, '../build/icon.ico'); + } + else { + result = isPackaged + ? path.resolve(process.resourcesPath, 'icon.png') + : path.resolve(__dirname, '../build/icon_512x512.png'); + } + + return result; + } + initWebUIHandler() { + const trayIcon = this.getTrayIcon(); app.on('ready', () => { start(); + + const tray = new Tray(trayIcon); + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Open', + type: 'normal', + click: () => { + BrowserWindow.getAllWindows() + .reverse() + .forEach(win => { + win.show(); + }); + }, + }, + { + label: 'Exit', + type: 'normal', + click: () => { + app.quit() + } + }, + ]); + tray.setToolTip('Station'); + tray.setContextMenu(contextMenu); }); } } diff --git a/packages/app/src/services/services/browser-window/interface.ts b/packages/app/src/services/services/browser-window/interface.ts index 0f39f018..e660d2c7 100644 --- a/packages/app/src/services/services/browser-window/interface.ts +++ b/packages/app/src/services/services/browser-window/interface.ts @@ -84,6 +84,8 @@ export class BrowserWindowServiceObserver extends ServiceBase implements RPC.Int onContextMenu(params: Electron.ContextMenuParams): void {} // @ts-ignore onNewNotification(notificationId: string, props: NotificationProps): void {} + // @ts-ignore + onMinimize(): void {} } @service('browser-window') @@ -111,4 +113,6 @@ export class BrowserWindowManagerService extends ServiceBase implements RPC.Inte setProvider(provider: RPC.Node): Promise {} // @ts-ignore hideMainMenu(hide: boolean): Promise {} + // @ts-ignore + hideAllWindows(): Promise {} } diff --git a/packages/app/src/services/services/browser-window/main.ts b/packages/app/src/services/services/browser-window/main.ts index 966fcb62..408d1fd0 100644 --- a/packages/app/src/services/services/browser-window/main.ts +++ b/packages/app/src/services/services/browser-window/main.ts @@ -1,4 +1,4 @@ -import { BrowserWindow, ipcMain, screen, webContents, WebContents, WebPreferences, app } from 'electron'; +import { BrowserWindow, ipcMain, screen } from 'electron'; import * as remoteMain from '@electron/remote/main'; import * as windowStateKeeper from 'electron-window-state'; import { fromEvent } from 'rxjs'; @@ -162,6 +162,7 @@ export class BrowserWindowServiceImpl extends BrowserWindowService implements RP this.onAny('closed', obs.onClosed), this.onAny('enter-full-screen', obs.onEnterFullScreen), this.onAny('leave-full-screen', obs.onLeaveFullScreen), + this.onAny('minimize', obs.onMinimize), this.onAnyWebContents('did-finish-load', obs.onDidFinishLoad), this.onReadyToShow(obs.onReadyToShow), this.onContextMenu(obs.onContextMenu), diff --git a/packages/app/src/services/services/browser-window/manager.ts b/packages/app/src/services/services/browser-window/manager.ts index 3b67f7f9..1fead8c4 100644 --- a/packages/app/src/services/services/browser-window/manager.ts +++ b/packages/app/src/services/services/browser-window/manager.ts @@ -114,4 +114,10 @@ export class BrowserWindowManagerServiceImpl extends BrowserWindowManagerService }); await this.provider.setHideMainMenu(hide); } + + async hideAllWindows() { + BrowserWindow.getAllWindows().forEach((bw) => { + bw.hide(); + }); + } } diff --git a/packages/app/src/utils/process.ts b/packages/app/src/utils/process.ts index 81efa74d..21b5671d 100644 --- a/packages/app/src/utils/process.ts +++ b/packages/app/src/utils/process.ts @@ -1,5 +1,6 @@ export const isDarwin = process.platform === 'darwin'; export const isLinux = process.platform === 'linux'; +export const isWindows = process.platform === 'win32'; export const fullPlatform = isDarwin ? `${process.platform}_${process.arch}` : process.platform; diff --git a/packages/app/src/windows/utils/GenericWindowManager.ts b/packages/app/src/windows/utils/GenericWindowManager.ts index 2bc4d891..04bd9579 100644 --- a/packages/app/src/windows/utils/GenericWindowManager.ts +++ b/packages/app/src/windows/utils/GenericWindowManager.ts @@ -1,5 +1,6 @@ import { EventEmitter } from 'events'; import { Action, Store } from 'redux'; + import { changeAppFocusState } from '../../app/duck'; import { NotificationProps } from '../../notification-center/types'; import { handleError } from '../../services/api/helpers'; @@ -152,6 +153,9 @@ export default class GenericWindowManager extends EventEmitter { webContentsId, }); }, + onMinimize() { + self.emit('minimize'); + } }, 'gwm' ) diff --git a/packages/app/src/windows/utils/MainWindowManager.ts b/packages/app/src/windows/utils/MainWindowManager.ts index 2518bba2..4df7e030 100644 --- a/packages/app/src/windows/utils/MainWindowManager.ts +++ b/packages/app/src/windows/utils/MainWindowManager.ts @@ -1,9 +1,14 @@ +import log from 'electron-log'; + import { getUrlToLoad } from '../../utils/dev'; import { isDarwin } from '../../utils/process'; import { getResourceIconPath } from '../../utils/resources'; import { windowCreated } from '../duck'; import GenericWindowManager from './GenericWindowManager'; +// import { mainServices } from '../../services/renderer' +import services from '../../services/servicesManager'; + export default class MainWindowManager extends GenericWindowManager { static instance: MainWindowManager; @@ -15,7 +20,9 @@ export default class MainWindowManager extends GenericWindowManager { } async create() { - if (this.isCreated()) return this.window; + if (this.isCreated()) { + return this.window; + } await super.create({ show: false, @@ -25,6 +32,10 @@ export default class MainWindowManager extends GenericWindowManager { savePosition: 'main-window', }); + this.on('minimize', () => { + services.browserWindow.hideAllWindows(); + }); + await super.load(); return this.window!; From 11bbfddb088917dce7130ff7b8c2d079daf55d37 Mon Sep 17 00:00:00 2001 From: viktor44 Date: Wed, 13 Nov 2024 23:27:36 +0100 Subject: [PATCH 2/9] 3.3.0-b1 --- package.json | 2 +- packages/app/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index afc1c03d..1db3d749 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "station-project", "private": true, "productName": "Station", - "version": "3.2.0-b3", + "version": "3.3.0-b1", "description": "Station", "homepage": "https://getstation.com", "author": { diff --git a/packages/app/package.json b/packages/app/package.json index 029e40dd..2657267e 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,7 +1,7 @@ { "name": "station-desktop-app", "productName": "Station", - "version": "3.2.0-b3", + "version": "3.3.0-b1", "description": "Station", "homepage": "https://getstation.com", "author": { From 2a93a1613e4abff5d1dc99c60de53a84318a1341 Mon Sep 17 00:00:00 2001 From: viktor44 Date: Fri, 15 Nov 2024 01:23:35 +0100 Subject: [PATCH 3/9] Minimize to tray settings --- packages/app/codegen-local.yml | 7 ++ packages/app/src/app-main.js | 17 ++-- packages/app/src/app-worker.ts | 6 +- packages/app/src/app/duck.js | 13 +++ packages/app/src/app/resolvers.ts | 12 ++- packages/app/src/app/sagas.js | 22 +++++ packages/app/src/app/selectors.ts | 3 + packages/app/src/app/types.ts | 2 + packages/app/src/database/model.ts | 4 + packages/app/src/graphql/schema.graphql | 4 + packages/app/src/persistence/local.backend.ts | 2 + .../20241113000000-add-minimize-to-tray.js | 11 +++ .../services/electron-app/interface.ts | 15 +++- .../services/services/electron-app/main.ts | 25 +++++- .../services/services/electron-app/worker.ts | 26 ++++++ .../SettingsMinimizeToTray.tsx | 89 +++++++++++++++++++ .../SettingsMinimizeToTray/queries@local.gql | 8 ++ .../components/SettingsPanelGeneral.tsx | 3 + 18 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 packages/app/src/persistence/umzug-runs/20241113000000-add-minimize-to-tray.js create mode 100644 packages/app/src/services/services/electron-app/worker.ts create mode 100644 packages/app/src/settings/components/SettingsMinimizeToTray/SettingsMinimizeToTray.tsx create mode 100644 packages/app/src/settings/components/SettingsMinimizeToTray/queries@local.gql diff --git a/packages/app/codegen-local.yml b/packages/app/codegen-local.yml index bd508443..9f672511 100644 --- a/packages/app/codegen-local.yml +++ b/packages/app/codegen-local.yml @@ -30,6 +30,13 @@ generates: - typescript-operations - typescript-react-apollo + ./src/settings/components/SettingsMinimizeToTray/queries@local.gql.generated.tsx: + documents: ./src/settings/components/SettingsMinimizeToTray/queries@local.gql + plugins: + - typescript + - typescript-operations + - typescript-react-apollo + ./src/settings/components/SettingsDownloads/queries@local.gql.generated.tsx: documents: ./src/settings/components/SettingsDownloads/queries@local.gql plugins: diff --git a/packages/app/src/app-main.js b/packages/app/src/app-main.js index 0496d424..ed8b9220 100644 --- a/packages/app/src/app-main.js +++ b/packages/app/src/app-main.js @@ -1,10 +1,10 @@ import * as path from 'path'; import { EventEmitter } from 'events'; import { parse } from 'url'; -import { app, webContents, BrowserWindow, Menu, Tray } from 'electron'; +import { app, webContents, BrowserWindow, Menu, Tray, nativeImage } from 'electron'; import log from 'electron-log'; -import { isWindows } from './utils/process'; +import { isDarwin, isWindows } from './utils/process'; import { isPackaged } from './utils/env'; import services from './services/servicesManager'; import { observer } from './services/lib/helpers'; @@ -49,14 +49,15 @@ export default class BrowserXAppMain extends EventEmitter { let result = undefined; if (isWindows) { - result = isPackaged - ? path.resolve(process.resourcesPath, 'icon.ico') - : path.resolve(__dirname, '../build/icon.ico'); + result = nativeImage.createFromPath(path.resolve(__dirname, './static/icon-app.png')); + result.setTemplateImage(true); } else { - result = isPackaged - ? path.resolve(process.resourcesPath, 'icon.png') - : path.resolve(__dirname, '../build/icon_512x512.png'); + // result = isPackaged + // ? path.resolve(process.resourcesPath, 'icon.png') + // : path.resolve(__dirname, '../build/icon_512x512.png'); + result = nativeImage.createFromPath(path.resolve(__dirname, './static/icon-app.png')); + result.setTemplateImage(true); } return result; diff --git a/packages/app/src/app-worker.ts b/packages/app/src/app-worker.ts index 73382f89..9013529e 100644 --- a/packages/app/src/app-worker.ts +++ b/packages/app/src/app-worker.ts @@ -58,6 +58,7 @@ import MainWindowManager from './windows/utils/MainWindowManager'; import URLRouter from './urlrouter/URLRouter'; import { closeCurrentTab } from './tabs/duck'; import { BrowserWindowManagerProviderServiceImpl } from './services/services/browser-window/worker'; +import { ElectronAppServiceProviderServiceImpl } from './services/services/electron-app/worker'; export class BrowserXAppWorker { public store: StationStoreWorker; @@ -342,13 +343,16 @@ export class BrowserXAppWorker { } private async initAppLifeCycle() { + services.electronApp.setProvider(new ElectronAppServiceProviderServiceImpl(this.store)) // Don't wrap this in this.store.ready() // because we want the window to be created as soon as possible await this.mainWindowManager.create(); const onActivate = async () => { const isReady = await services.electronApp.isReady(); - if (!isReady) return; + if (!isReady) { + return; + } // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. await this.mainWindowManager.create(); diff --git a/packages/app/src/app/duck.js b/packages/app/src/app/duck.js index cc3a20d0..ed7958fd 100644 --- a/packages/app/src/app/duck.js +++ b/packages/app/src/app/duck.js @@ -12,6 +12,8 @@ export const SET_AUTO_LAUNCH_ENABLED = 'browserX/app/SET_AUTO_LAUNCH_ENABLED'; export const ENABLE_AUTO_LAUNCH = 'browserX/app/ENABLE_AUTO_LAUNCH'; export const SET_HIDE_MAIN_MENU = 'browserX/app/SET_HIDE_MAIN_MENU'; export const HIDE_MAIN_MENU = 'browserX/app/HIDE_MAIN_MENU'; +export const SET_MINIMIZE_TO_TRAY = 'browserX/app/SET_MINIMIZE_TO_TRAY'; +export const MINIMIZE_TO_TRAY = 'browserX/app/MINIMIZE_TO_TRAY'; export const INCLUDE_BETA_IN_UPDATES = 'browserX/app/INCLUDE_BETA_IN_UPDATES'; export const SET_INCLUDES_BETA_IN_UPDATES = 'browserX/app/SET_INCLUDES_BETA_IN_UPDATES'; export const SET_FULL_SCREEN_STATE = 'browserX/app/SET_FULL_SCREEN_STATE'; @@ -58,6 +60,14 @@ export const hideMainMenu = (hide) => ({ type: HIDE_MAIN_MENU, hide }); +export const setMinimizeToTray = (enabled) => ({ + type: SET_MINIMIZE_TO_TRAY, enabled +}); + +export const minimizeToTray = (enable) => ({ + type: MINIMIZE_TO_TRAY, enable +}); + export const includeBetaInUpdates = (include = true) => ({ type: INCLUDE_BETA_IN_UPDATES, include }); @@ -151,6 +161,9 @@ export default function app(state = new Map(), action) { case SET_HIDE_MAIN_MENU: return state.set('hideMainMenu', action.hide); + case SET_MINIMIZE_TO_TRAY: + return state.set('minimizeToTray', action.enabled); + case SET_INCLUDES_BETA_IN_UPDATES: return state.set('includesBetaInUpdates', action.included); diff --git a/packages/app/src/app/resolvers.ts b/packages/app/src/app/resolvers.ts index 2793dfce..de63af94 100644 --- a/packages/app/src/app/resolvers.ts +++ b/packages/app/src/app/resolvers.ts @@ -5,9 +5,9 @@ import { distinctUntilChanged, map } from 'rxjs/operators'; import { subscribeStore } from '../utils/observable'; import { Resolvers } from '../graphql/resolvers-types.generated'; -import { getAppAutoLaunchEnabledStatus, getAppHideMainMenuStatus, getPromptDownloadEnabled } from './selectors'; +import { getAppAutoLaunchEnabledStatus, getAppHideMainMenuStatus, getAppMinimizeToTrayStatus, getPromptDownloadEnabled } from './selectors'; import { getStationStatus } from '../app/selectors'; -import { enableAutoLaunch, hideMainMenu, togglePromptDownload } from './duck'; +import { enableAutoLaunch, hideMainMenu, minimizeToTray, togglePromptDownload } from './duck'; const resolvers: Resolvers = { Query: { @@ -19,6 +19,10 @@ const resolvers: Resolvers = { return subscribeStore(context.store, getAppHideMainMenuStatus) .pipe(map(Boolean), distinctUntilChanged()); }, + minimizeToTray: (_obj, _args, context) => { + return subscribeStore(context.store, getAppMinimizeToTrayStatus) + .pipe(map(Boolean), distinctUntilChanged()); + }, promptDownloadEnabled: (_obj, _args, context) => { return subscribeStore(context.store, getPromptDownloadEnabled) .pipe(map(Boolean), distinctUntilChanged()); @@ -40,6 +44,10 @@ const resolvers: Resolvers = { context.store.dispatch(hideMainMenu(args.hide)); return true; }, + setMinimizeToTray: (_obj, args, context) => { + context.store.dispatch(minimizeToTray(args.enabled)); + return true; + }, setPromptDownload: (_obj, args, context) => { context.store.dispatch(togglePromptDownload(args.enabled)); return true; diff --git a/packages/app/src/app/sagas.js b/packages/app/src/app/sagas.js index d15d76d4..406c80ad 100644 --- a/packages/app/src/app/sagas.js +++ b/packages/app/src/app/sagas.js @@ -26,6 +26,7 @@ import { CHANGE_APP_FOCUS_STATE, ENABLE_AUTO_LAUNCH, enableAutoLaunch, HIDE_MAIN_MENU, hideMainMenu, + MINIMIZE_TO_TRAY, minimizeToTray, INCLUDE_BETA_IN_UPDATES, keyboardLayoutChanged, OPEN_PROCESS_MANAGER, @@ -45,6 +46,7 @@ import { getWindow } from '../windows/selectors'; import { getAppAutoLaunchEnabledStatus, getAppHideMainMenuStatus, + getAppMinimizeToTrayStatus, getPromptDownloadEnabled, isFullyReady, isKbdShortcutsOverlayVisible @@ -101,6 +103,24 @@ function* sagaHideMainMenu({ hide }) { yield call([services.browserWindow, services.browserWindow.hideMainMenu], hide); } +function* sagaSyncMinimizeToTray() { + let isEnabled = yield select(getAppMinimizeToTrayStatus); + if (typeof isEnabled === 'undefined') { + isEnabled = false; + } + + yield put(minimizeToTray(isEnabled)); +} + +function* sagaMinimizeToTray({ enable }) { + if (enable) { + yield call([services.electronApp, services.electronApp.showTrayIcon]); + } + else { + yield call([services.electronApp, services.electronApp.hideTrayIcon]); + } +} + function* sagaTogglePromptDownload({ promptDownload }) { yield call( [services.download, services.download.setShouldShowPromptPathOnDownload], @@ -271,9 +291,11 @@ export default function* main(bxApp) { takeEveryWitness(READY, sagaPrepareQuit, bxApp), takeEveryWitness(REHYDRATION_COMPLETE, sagaSyncAutoLaunch), takeEveryWitness(REHYDRATION_COMPLETE, sagaSyncHideMainMenu), + takeEveryWitness(REHYDRATION_COMPLETE, sagaSyncMinimizeToTray), takeEveryWitness(REHYDRATION_COMPLETE, sagaSyncPromptDownload), takeEveryWitness(ENABLE_AUTO_LAUNCH, sagaEnableAutoLaunch), takeEveryWitness(HIDE_MAIN_MENU, sagaHideMainMenu), + takeEveryWitness(MINIMIZE_TO_TRAY, sagaMinimizeToTray), takeEveryWitness(TOGGLE_PROMPT_DOWNLOAD, sagaTogglePromptDownload), takeEveryWitness(INCLUDE_BETA_IN_UPDATES, sagaIncludeBetaInUpdates), takeEveryWitness(TOGGLE_MAXIMIZE, sagaSendToggleMaximize), diff --git a/packages/app/src/app/selectors.ts b/packages/app/src/app/selectors.ts index 75f4b055..89d99960 100644 --- a/packages/app/src/app/selectors.ts +++ b/packages/app/src/app/selectors.ts @@ -20,6 +20,9 @@ export const getAppAutoLaunchEnabledStatus = (state: StationState): boolean | un export const getAppHideMainMenuStatus = (state: StationState): boolean | undefined => getStationStatus(state).get('hideMainMenu'); +export const getAppMinimizeToTrayStatus = (state: StationState): boolean | undefined => + getStationStatus(state).get('minimizeToTray'); + export const areBetaIncludedInUpdates = (state: StationState): boolean => state.getIn(['app', 'includesBetaInUpdates'], false); diff --git a/packages/app/src/app/types.ts b/packages/app/src/app/types.ts index db72f6d6..e1df91a7 100644 --- a/packages/app/src/app/types.ts +++ b/packages/app/src/app/types.ts @@ -1,11 +1,13 @@ import { RecursiveImmutableMap } from '../types'; +// Global application properties export type StationApp = { appName: string, appVersion: string, includesBetaInUpdates: boolean, autoLaunchEnabled: boolean, hideMainMenu: boolean, + minimizeToTray: boolean, isFullScreen: boolean, defaultDownloadFolder: string, downloadFolder: string, diff --git a/packages/app/src/database/model.ts b/packages/app/src/database/model.ts index 002f1ddc..4c4ce96b 100644 --- a/packages/app/src/database/model.ts +++ b/packages/app/src/database/model.ts @@ -20,6 +20,10 @@ export const App = db.define( type: Sequelize.BOOLEAN, defaultValue: false, }, + minimizeToTray: { + type: Sequelize.BOOLEAN, + defaultValue: false, + }, downloadFolder: { type: Sequelize.STRING, }, diff --git a/packages/app/src/graphql/schema.graphql b/packages/app/src/graphql/schema.graphql index ab5306ae..bd6c1310 100644 --- a/packages/app/src/graphql/schema.graphql +++ b/packages/app/src/graphql/schema.graphql @@ -3,6 +3,8 @@ type Query { autoLaunchEnabled: Boolean, """ Hide main menu (Windows, Linux) """ hideMainMenu: Boolean, + """ Minimize application to tray icon """ + minimizeToTray: Boolean, promptDownloadEnabled: Boolean, @@ -49,6 +51,8 @@ type Mutation { """ Will set the value of hideMainMenu property. """ setHideMainMenu(hide: Boolean!): Boolean, + setMinimizeToTray(enabled: Boolean!): Boolean, + setPromptDownload(enabled: Boolean!):Boolean """Trigger an action to check for updates""" diff --git a/packages/app/src/persistence/local.backend.ts b/packages/app/src/persistence/local.backend.ts index 81696231..c5eb6c6d 100644 --- a/packages/app/src/persistence/local.backend.ts +++ b/packages/app/src/persistence/local.backend.ts @@ -181,6 +181,7 @@ export class AppProxy extends SingletonProxyMixin({ version: state.get('version'), autoLaunchEnabled: state.get('autoLaunchEnabled'), hideMainMenu: state.get('hideMainMenu'), + minimizeToTray: state.get('minimizeToTray'), downloadFolder: state.get('downloadFolder'), promptDownload: state.get('promptDownload'), }), @@ -188,6 +189,7 @@ export class AppProxy extends SingletonProxyMixin({ version: obj.version, autoLaunchEnabled: obj.autoLaunchEnabled, hideMainMenu: obj.hideMainMenu, + minimizeToTray: obj.minimizeToTray, downloadFolder: obj.downloadFolder, promptDownload: Boolean(obj.promptDownload), }), diff --git a/packages/app/src/persistence/umzug-runs/20241113000000-add-minimize-to-tray.js b/packages/app/src/persistence/umzug-runs/20241113000000-add-minimize-to-tray.js new file mode 100644 index 00000000..120b92f4 --- /dev/null +++ b/packages/app/src/persistence/umzug-runs/20241113000000-add-minimize-to-tray.js @@ -0,0 +1,11 @@ +/* eslint-disable no-unused-vars */ + +export default { + up(query, DataTypes) { + return query.addColumn('app', 'minimizeToTray', DataTypes.BOOLEAN); + }, + + down(query, DataTypes) { + return query.removeColumn('app', 'minimizeToTray'); + } +}; diff --git a/packages/app/src/services/services/electron-app/interface.ts b/packages/app/src/services/services/electron-app/interface.ts index c71755dc..4ca5b147 100644 --- a/packages/app/src/services/services/electron-app/interface.ts +++ b/packages/app/src/services/services/electron-app/interface.ts @@ -25,9 +25,14 @@ export class ElectronAppService extends ServiceBase implements RPC.Interface {} // @ts-ignore getAppMetadata(): Promise {} - + // @ts-ignore + showTrayIcon(): Promise {} + // @ts-ignore + hideTrayIcon(): Promise {} // @ts-ignore addObserver(obs: RPC.ObserverNode): Promise {} + // @ts-ignore + setProvider(provider: RPC.Node): Promise {} } @service('electron-app') @@ -41,3 +46,11 @@ export interface AppMetadata { name: string, version: string, } + +@service('browser-window') +export class ElectronAppServiceProviderService extends ServiceBase implements RPC.Interface { + // @ts-ignore + showTrayIcon(): Promise {} + // @ts-ignore + hideTrayIcon(): Promise {} +} diff --git a/packages/app/src/services/services/electron-app/main.ts b/packages/app/src/services/services/electron-app/main.ts index 3953a62d..6404dd74 100644 --- a/packages/app/src/services/services/electron-app/main.ts +++ b/packages/app/src/services/services/electron-app/main.ts @@ -4,7 +4,7 @@ import * as globalTunnel from 'global-tunnel-ng'; import { fromEvent, Subject, Subscription } from 'rxjs'; import { ServiceSubscription } from '../../lib/class'; import { RPC } from '../../lib/types'; -import { ElectronAppService, ElectronAppServiceObserver } from './interface'; +import { ElectronAppService, ElectronAppServiceObserver, ElectronAppServiceProviderService } from './interface'; import { ElectronAppPath } from './types'; const RESUME_QUIT_RECOVERY_DELAY = 5000; @@ -34,6 +34,7 @@ function initProxyResolver() { export class ElectronAppServiceImpl extends ElectronAppService implements RPC.Interface { private prepareQuitSubject: Subject; private appCanQuit: boolean; + private provider?: RPC.Node; constructor(uuid?: string) { super(uuid, { ready: false }); @@ -128,6 +129,24 @@ export class ElectronAppServiceImpl extends ElectronAppService implements RPC.In return new ServiceSubscription(subscriptions, obs); } + async showTrayIcon() { + if (!this.provider) { + log.info('missing provider service'); + // throw new Error('missing provider service'); + } + log.info('showTrayIcon'); + await this.provider?.showTrayIcon(); + } + + async hideTrayIcon() { + if (!this.provider) { + log.info('missing provider service'); + // throw new Error('missing provider service'); + } + log.info('hideTrayIcon'); + await this.provider?.hideTrayIcon(); + } + private initPrepareQuit() { app.on('before-quit', (event) => { if (!this.appCanQuit) { @@ -137,4 +156,8 @@ export class ElectronAppServiceImpl extends ElectronAppService implements RPC.In } }); } + + async setProvider(provider: RPC.Node) { + this.provider = provider; + } } diff --git a/packages/app/src/services/services/electron-app/worker.ts b/packages/app/src/services/services/electron-app/worker.ts new file mode 100644 index 00000000..3276294c --- /dev/null +++ b/packages/app/src/services/services/electron-app/worker.ts @@ -0,0 +1,26 @@ +import log from 'electron-log'; + +// @ts-ignore: no declaration file +import { setMinimizeToTray } from '../../../app/duck'; +import { StationStoreWorker } from '../../../types'; +import { RPC } from '../../lib/types'; +import { ElectronAppServiceProviderService } from './interface'; + +export class ElectronAppServiceProviderServiceImpl extends ElectronAppServiceProviderService implements RPC.Interface { + store: StationStoreWorker; + + constructor(store: StationStoreWorker, uuid?: string) { + super(uuid); + this.store = store; + } + + async showTrayIcon() { + log.info('Provider showTrayIcon'); + this.store.dispatch(setMinimizeToTray(true)); + } + + async hideTrayIcon() { + log.info('Provider hideTrayIcon'); + this.store.dispatch(setMinimizeToTray(false)); + } +} diff --git a/packages/app/src/settings/components/SettingsMinimizeToTray/SettingsMinimizeToTray.tsx b/packages/app/src/settings/components/SettingsMinimizeToTray/SettingsMinimizeToTray.tsx new file mode 100644 index 00000000..88f45342 --- /dev/null +++ b/packages/app/src/settings/components/SettingsMinimizeToTray/SettingsMinimizeToTray.tsx @@ -0,0 +1,89 @@ +import { Switcher } from '@getstation/theme'; +import * as React from 'react'; +// @ts-ignore: no declaration file +import injectSheet from 'react-jss'; +import { compose } from 'redux'; +import { withGetMinimizeToTrayStatus, withEnableMinimizeToTray } from './queries@local.gql.generated'; + +export interface Classes { + container: string, + item: string, + title: string, + settingName: string, + checkbox: string, + label: string, +} + +export interface Props { + classes?: Classes + isMinimizeToTray: boolean, + onMinimizeToTray: (enabled: boolean) => any + loading: boolean, +} + +const styles = { + container: { + maxWidth: '600px', + paddingTop: '10px', + paddingBottom: '10px', + }, + item: { + }, + settingName: { + marginBottom: 8, + textTransform: 'uppercase', + fontSize: 14, + fontWeight: 'bold', + }, + checkbox: { + '-webkit-appearance': 'checkbox', + marginRight: 10, + marginBottom: 20, + borderRadius: 2, + width: 14, + height: 14, + }, + label: { + }, +}; + +@injectSheet(styles) +class SettingsMinimizeToTray extends React.Component { + render() { + const { classes, loading, isMinimizeToTray } = this.props; + + const handleSwitcherChange = (e: React.ChangeEvent) => + this.props.onMinimizeToTray(e.target.checked); + return ( +
+
+

TRAY ICON

+ +
+ Minimize application to tray +
+
+
+ ); + } +} + +const connect = compose( + withGetMinimizeToTrayStatus({ + props: ({ data }) => ({ + loading: !data || data.loading, + isMinimizeToTray: !!data && Boolean(data.minimizeToTray), + }), + }), + withEnableMinimizeToTray({ + props: ({ mutate }) => ({ + onMinimizeToTray: (enabled: boolean) => mutate && mutate({ variables: { enabled } }), + }), + }), +); + +export default connect(SettingsMinimizeToTray); diff --git a/packages/app/src/settings/components/SettingsMinimizeToTray/queries@local.gql b/packages/app/src/settings/components/SettingsMinimizeToTray/queries@local.gql new file mode 100644 index 00000000..bca419bd --- /dev/null +++ b/packages/app/src/settings/components/SettingsMinimizeToTray/queries@local.gql @@ -0,0 +1,8 @@ + query GetMinimizeToTrayStatus @live @local { + minimizeToTray + } + + mutation EnableMinimizeToTray($enabled: Boolean!) @local{ + setMinimizeToTray(enabled: $enabled) + } + \ No newline at end of file diff --git a/packages/app/src/settings/components/SettingsPanelGeneral.tsx b/packages/app/src/settings/components/SettingsPanelGeneral.tsx index f62b4736..8bbadf6d 100644 --- a/packages/app/src/settings/components/SettingsPanelGeneral.tsx +++ b/packages/app/src/settings/components/SettingsPanelGeneral.tsx @@ -17,6 +17,7 @@ import SettingsDownloadFolder from './SettingsDownloads/SettingsDownloadFolder'; import SettingsOpenSourceInfo from './SettingsOpenSourceInfo'; import SettingsUpdatesButton from './SettingsUpdatesButton/SettingsUpdatesButton'; import SettingsHideMainMenu from './SettingsHideMainMenu/SettingsHideMainMenu'; +import SettingsMinimizeToTray from './SettingsMinimizeToTray/SettingsMinimizeToTray'; import { isDarwin } from '../../utils/process'; export interface Classes { @@ -82,6 +83,8 @@ class SettingsPanelGeneralImpl extends React.PureComponent { { !isDarwin && } + + Date: Sat, 16 Nov 2024 18:24:05 +0100 Subject: [PATCH 4/9] Minimize to tray --- packages/app/electron-builder.yml | 6 +- packages/app/src/app-main.js | 46 ------------- .../services/services/electron-app/main.ts | 65 ++++++++++++++++--- .../services/services/electron-app/worker.ts | 4 -- 4 files changed, 58 insertions(+), 63 deletions(-) diff --git a/packages/app/electron-builder.yml b/packages/app/electron-builder.yml index b85bc13e..de30666d 100644 --- a/packages/app/electron-builder.yml +++ b/packages/app/electron-builder.yml @@ -62,10 +62,8 @@ linux: extraResources: - from: '../../.env.production' to: '.env.production' - - from: 'build/icon_512x512.png' - to: 'icon.png' - - from: 'build/icon.ico' - to: 'icon.ico' + - from: 'src/static/icon-app.png' + to: 'icon-app.png' files: - '!**/*.map' diff --git a/packages/app/src/app-main.js b/packages/app/src/app-main.js index ed8b9220..df3da3fb 100644 --- a/packages/app/src/app-main.js +++ b/packages/app/src/app-main.js @@ -1,11 +1,8 @@ -import * as path from 'path'; import { EventEmitter } from 'events'; import { parse } from 'url'; import { app, webContents, BrowserWindow, Menu, Tray, nativeImage } from 'electron'; import log from 'electron-log'; -import { isDarwin, isWindows } from './utils/process'; -import { isPackaged } from './utils/env'; import services from './services/servicesManager'; import { observer } from './services/lib/helpers'; import { handleError } from './services/api/helpers'; @@ -45,52 +42,9 @@ export default class BrowserXAppMain extends EventEmitter { return services.processManager.addObserver(observer({ onWillKillProcess })); } - getTrayIcon() { - let result = undefined; - - if (isWindows) { - result = nativeImage.createFromPath(path.resolve(__dirname, './static/icon-app.png')); - result.setTemplateImage(true); - } - else { - // result = isPackaged - // ? path.resolve(process.resourcesPath, 'icon.png') - // : path.resolve(__dirname, '../build/icon_512x512.png'); - result = nativeImage.createFromPath(path.resolve(__dirname, './static/icon-app.png')); - result.setTemplateImage(true); - } - - return result; - } - initWebUIHandler() { - const trayIcon = this.getTrayIcon(); app.on('ready', () => { start(); - - const tray = new Tray(trayIcon); - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Open', - type: 'normal', - click: () => { - BrowserWindow.getAllWindows() - .reverse() - .forEach(win => { - win.show(); - }); - }, - }, - { - label: 'Exit', - type: 'normal', - click: () => { - app.quit() - } - }, - ]); - tray.setToolTip('Station'); - tray.setContextMenu(contextMenu); }); } } diff --git a/packages/app/src/services/services/electron-app/main.ts b/packages/app/src/services/services/electron-app/main.ts index 6404dd74..45875e1b 100644 --- a/packages/app/src/services/services/electron-app/main.ts +++ b/packages/app/src/services/services/electron-app/main.ts @@ -1,7 +1,11 @@ -import { app, session } from 'electron'; +import * as path from 'path'; +import { BrowserWindow, Menu, Tray, app, nativeImage, session } from 'electron'; import log from 'electron-log'; import * as globalTunnel from 'global-tunnel-ng'; import { fromEvent, Subject, Subscription } from 'rxjs'; + +// import { isDarwin, isWindows } from '../../../utils/process'; +import { isPackaged } from '../../../utils/env'; import { ServiceSubscription } from '../../lib/class'; import { RPC } from '../../lib/types'; import { ElectronAppService, ElectronAppServiceObserver, ElectronAppServiceProviderService } from './interface'; @@ -35,6 +39,7 @@ export class ElectronAppServiceImpl extends ElectronAppService implements RPC.In private prepareQuitSubject: Subject; private appCanQuit: boolean; private provider?: RPC.Node; + private tray?: Tray; constructor(uuid?: string) { super(uuid, { ready: false }); @@ -131,20 +136,21 @@ export class ElectronAppServiceImpl extends ElectronAppService implements RPC.In async showTrayIcon() { if (!this.provider) { - log.info('missing provider service'); - // throw new Error('missing provider service'); + throw new Error('missing provider service'); } - log.info('showTrayIcon'); - await this.provider?.showTrayIcon(); + this.tray = this.createTray(); + await this.provider.showTrayIcon(); } async hideTrayIcon() { if (!this.provider) { - log.info('missing provider service'); - // throw new Error('missing provider service'); + throw new Error('missing provider service'); + } + if (this.tray) { + this.tray.destroy(); + this.tray = undefined; } - log.info('hideTrayIcon'); - await this.provider?.hideTrayIcon(); + await this.provider.hideTrayIcon(); } private initPrepareQuit() { @@ -160,4 +166,45 @@ export class ElectronAppServiceImpl extends ElectronAppService implements RPC.In async setProvider(provider: RPC.Node) { this.provider = provider; } + + getTrayIcon() { + const result = nativeImage.createFromPath( + isPackaged + ? path.resolve(process.resourcesPath, 'icon-app.png') + : path.resolve(__dirname, '../../../static/icon-app.png') + ); + result.setTemplateImage(true); + + return result; + } + + createTray() { + const tray = new Tray(this.getTrayIcon()); + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Open', + type: 'normal', + click: () => { + BrowserWindow.getAllWindows() + .reverse() + .forEach(win => { + if (win.webContents.id !== 1) { + win.show(); + } + }); + }, + }, + { + label: 'Exit', + type: 'normal', + click: () => { + app.quit() + } + }, + ]); + tray.setToolTip('Station'); + tray.setContextMenu(contextMenu); + + return tray; + } } diff --git a/packages/app/src/services/services/electron-app/worker.ts b/packages/app/src/services/services/electron-app/worker.ts index 3276294c..03b65605 100644 --- a/packages/app/src/services/services/electron-app/worker.ts +++ b/packages/app/src/services/services/electron-app/worker.ts @@ -1,5 +1,3 @@ -import log from 'electron-log'; - // @ts-ignore: no declaration file import { setMinimizeToTray } from '../../../app/duck'; import { StationStoreWorker } from '../../../types'; @@ -15,12 +13,10 @@ export class ElectronAppServiceProviderServiceImpl extends ElectronAppServicePro } async showTrayIcon() { - log.info('Provider showTrayIcon'); this.store.dispatch(setMinimizeToTray(true)); } async hideTrayIcon() { - log.info('Provider hideTrayIcon'); this.store.dispatch(setMinimizeToTray(false)); } } From e8320408cf388d011488834346febbe3db796bdd Mon Sep 17 00:00:00 2001 From: viktor44 Date: Sat, 16 Nov 2024 18:28:51 +0100 Subject: [PATCH 5/9] Minimize to tray --- packages/app/src/services/services/electron-app/main.ts | 1 - packages/app/src/windows/utils/MainWindowManager.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/packages/app/src/services/services/electron-app/main.ts b/packages/app/src/services/services/electron-app/main.ts index 45875e1b..20b4bbd6 100644 --- a/packages/app/src/services/services/electron-app/main.ts +++ b/packages/app/src/services/services/electron-app/main.ts @@ -4,7 +4,6 @@ import log from 'electron-log'; import * as globalTunnel from 'global-tunnel-ng'; import { fromEvent, Subject, Subscription } from 'rxjs'; -// import { isDarwin, isWindows } from '../../../utils/process'; import { isPackaged } from '../../../utils/env'; import { ServiceSubscription } from '../../lib/class'; import { RPC } from '../../lib/types'; diff --git a/packages/app/src/windows/utils/MainWindowManager.ts b/packages/app/src/windows/utils/MainWindowManager.ts index 4df7e030..3a933323 100644 --- a/packages/app/src/windows/utils/MainWindowManager.ts +++ b/packages/app/src/windows/utils/MainWindowManager.ts @@ -1,12 +1,8 @@ -import log from 'electron-log'; - import { getUrlToLoad } from '../../utils/dev'; import { isDarwin } from '../../utils/process'; import { getResourceIconPath } from '../../utils/resources'; import { windowCreated } from '../duck'; import GenericWindowManager from './GenericWindowManager'; - -// import { mainServices } from '../../services/renderer' import services from '../../services/servicesManager'; export default class MainWindowManager extends GenericWindowManager { From b8f8ea89ecc15ad2f716b3e8d90433888cffbaba Mon Sep 17 00:00:00 2001 From: viktor44 Date: Sat, 16 Nov 2024 18:45:19 +0100 Subject: [PATCH 6/9] Minimize to tray --- .../services/services/electron-app/main.ts | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/app/src/services/services/electron-app/main.ts b/packages/app/src/services/services/electron-app/main.ts index 20b4bbd6..39e86b59 100644 --- a/packages/app/src/services/services/electron-app/main.ts +++ b/packages/app/src/services/services/electron-app/main.ts @@ -166,7 +166,7 @@ export class ElectronAppServiceImpl extends ElectronAppService implements RPC.In this.provider = provider; } - getTrayIcon() { + private getTrayIcon() { const result = nativeImage.createFromPath( isPackaged ? path.resolve(process.resourcesPath, 'icon-app.png') @@ -177,20 +177,23 @@ export class ElectronAppServiceImpl extends ElectronAppService implements RPC.In return result; } - createTray() { - const tray = new Tray(this.getTrayIcon()); + private showAllWindows() { + BrowserWindow.getAllWindows() + .reverse() + .forEach(win => { + if (win.webContents.id !== 1) { + win.show(); + } + }); + } + + private createTray() { const contextMenu = Menu.buildFromTemplate([ { label: 'Open', type: 'normal', click: () => { - BrowserWindow.getAllWindows() - .reverse() - .forEach(win => { - if (win.webContents.id !== 1) { - win.show(); - } - }); + this.showAllWindows(); }, }, { @@ -201,9 +204,11 @@ export class ElectronAppServiceImpl extends ElectronAppService implements RPC.In } }, ]); + + const tray = new Tray(this.getTrayIcon()); + tray.addListener('double-click', () => this.showAllWindows()); tray.setToolTip('Station'); tray.setContextMenu(contextMenu); - return tray; } } From a3f1ab7fdb141d5c44fa5ece921380900b296740 Mon Sep 17 00:00:00 2001 From: viktor44 Date: Sat, 16 Nov 2024 20:29:21 +0100 Subject: [PATCH 7/9] Minimize to tray --- packages/app/src/settings/components/SettingsPanelGeneral.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/src/settings/components/SettingsPanelGeneral.tsx b/packages/app/src/settings/components/SettingsPanelGeneral.tsx index 8bbadf6d..1354c34e 100644 --- a/packages/app/src/settings/components/SettingsPanelGeneral.tsx +++ b/packages/app/src/settings/components/SettingsPanelGeneral.tsx @@ -18,7 +18,7 @@ import SettingsOpenSourceInfo from './SettingsOpenSourceInfo'; import SettingsUpdatesButton from './SettingsUpdatesButton/SettingsUpdatesButton'; import SettingsHideMainMenu from './SettingsHideMainMenu/SettingsHideMainMenu'; import SettingsMinimizeToTray from './SettingsMinimizeToTray/SettingsMinimizeToTray'; -import { isDarwin } from '../../utils/process'; +import { isDarwin, isWindows } from '../../utils/process'; export interface Classes { container: string, @@ -83,7 +83,7 @@ class SettingsPanelGeneralImpl extends React.PureComponent { { !isDarwin && } - + { isWindows && } Date: Sat, 16 Nov 2024 22:05:43 +0100 Subject: [PATCH 8/9] electron-process-manager update --- packages/app/package.json | 2 +- yarn.lock | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/app/package.json b/packages/app/package.json index 2657267e..a3cf8139 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -69,7 +69,7 @@ "electron-chrome-extension": "https://github.com/viktor44/electron-chrome-extension/releases/download/v6.0.3/release.tar.gz", "electron-debug": "^3.2.0", "electron-log": "^2.2.14", - "electron-process-manager": "https://github.com/viktor44/electron-process-manager/releases/download/v1.1.0/release.tar.gz", + "electron-process-manager": "^1.2.0", "electron-updater": "^6.2.1", "electron-window-state": "5.0.3", "emoji-js": "^3.4.1", diff --git a/yarn.lock b/yarn.lock index 31f02840..b3cc6fd0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2809,6 +2809,18 @@ __metadata: languageName: node linkType: hard +"@getstation/electron-process-reporter@npm:^2.0.0": + version: 2.0.0 + resolution: "@getstation/electron-process-reporter@npm:2.0.0" + dependencies: + memoizee: "npm:^0.4.17" + pidtree: "npm:^0.6.0" + pidusage: "npm:3.0.2" + rxjs: "npm:^6.6.7" + checksum: 10c0/af4afd13f81104efe1ee14fdb4a86bea8ed8c8aae8514e9794948b3440e479b2977226817201c3261cc4f2f5e6c58544858867e990943dfc95d5cb8c33b9496d + languageName: node + linkType: hard + "@getstation/fetch-favicon@npm:^0.0.4-rc.2": version: 0.0.4-rc.2 resolution: "@getstation/fetch-favicon@npm:0.0.4-rc.2" @@ -14070,24 +14082,12 @@ __metadata: languageName: node linkType: hard -"electron-process-manager@https://github.com/viktor44/electron-process-manager/releases/download/v1.1.0/release.tar.gz": - version: 1.1.0 - resolution: "electron-process-manager@https://github.com/viktor44/electron-process-manager/releases/download/v1.1.0/release.tar.gz" - dependencies: - electron-process-reporter: "https://github.com/viktor44/electron-process-reporter/releases/download/v1.5.0/release.tar.gz" - checksum: 10c0/7bff2d2e3b19fe73599c7bd514709b460939b5e8c1819b3cbe8541422d9cfc197779f539f504e8f3718545dad092f1de9bc4b1371bd9b254fc76a6f4ede853f5 - languageName: node - linkType: hard - -"electron-process-reporter@https://github.com/viktor44/electron-process-reporter/releases/download/v1.5.0/release.tar.gz": - version: 1.5.0 - resolution: "electron-process-reporter@https://github.com/viktor44/electron-process-reporter/releases/download/v1.5.0/release.tar.gz" +"electron-process-manager@npm:^1.2.0": + version: 1.2.0 + resolution: "electron-process-manager@npm:1.2.0" dependencies: - memoizee: "npm:^0.4.17" - pidtree: "npm:^0.6.0" - pidusage: "npm:3.0.2" - rxjs: "npm:^6.6.7" - checksum: 10c0/5bdabfd46f3026af71df4128f13d2d395788931afa7dab23370252c6b3f4d417f3b561db72f136db606096bb531076a22e237019ec94486301d3668b015fcd25 + "@getstation/electron-process-reporter": "npm:^2.0.0" + checksum: 10c0/1e6baeac7e28ddbdd04b109420a9f61e9f002e54ecb0afc007fa3441e5b29f40c86e547849743e76949063b7c13416407712b782a6084190e8bd1897c794128d languageName: node linkType: hard @@ -29387,7 +29387,7 @@ __metadata: electron-debug: "npm:^3.2.0" electron-log: "npm:^2.2.14" electron-mocha: "npm:^12.1.0" - electron-process-manager: "https://github.com/viktor44/electron-process-manager/releases/download/v1.1.0/release.tar.gz" + electron-process-manager: "npm:^1.2.0" electron-updater: "npm:^6.2.1" electron-webpack: "npm:^2.8.2" electron-window-state: "npm:5.0.3" From e584f4fce23a617175c1c003b8d0163df073d6a5 Mon Sep 17 00:00:00 2001 From: viktor44 Date: Sat, 16 Nov 2024 22:34:02 +0100 Subject: [PATCH 9/9] test fix --- packages/app/test/jest/persistence/test-app.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/app/test/jest/persistence/test-app.ts b/packages/app/test/jest/persistence/test-app.ts index 2fd8976f..7c6980f4 100644 --- a/packages/app/test/jest/persistence/test-app.ts +++ b/packages/app/test/jest/persistence/test-app.ts @@ -7,6 +7,7 @@ const appData = Immutable.Map({ version: 1, autoLaunchEnabled: true, hideMainMenu: true, + minimizeToTray: false, downloadFolder: '/any/path', promptDownload: false }); @@ -15,6 +16,7 @@ const appData2 = Immutable.Map({ version: 2, autoLaunchEnabled: true, hideMainMenu: true, + minimizeToTray: false, downloadFolder: '/any/path', promptDownload: true }); @@ -24,6 +26,7 @@ const wrongData = Immutable.Map({ unaivalableProp: true, autoLaunchEnabled: true, hideMainMenu: true, + minimizeToTray: false, downloadFolder: '/any/path', promptDownload: false }); @@ -36,6 +39,7 @@ const correctedData = { version: 1, autoLaunchEnabled: true, hideMainMenu: true, + minimizeToTray: false, downloadFolder: '/any/path', promptDownload: false };