From 154e6191048c76fb126cba2586ca827f574d9e3d Mon Sep 17 00:00:00 2001 From: Bruins <18346124519@163.com> Date: Mon, 26 Apr 2021 23:44:46 +0930 Subject: [PATCH 01/16] - Issue #2: Update preferences with 'Show app in the notification area' --- source/app/service-providers/assets/get-config-template.ts | 3 ++- .../app/service-providers/assets/types.config-provider.d.ts | 1 + source/win-preferences/schema/advanced.js | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/source/app/service-providers/assets/get-config-template.ts b/source/app/service-providers/assets/get-config-template.ts index 5bf10fb3d9..844cde4b7c 100644 --- a/source/app/service-providers/assets/get-config-template.ts +++ b/source/app/service-providers/assets/get-config-template.ts @@ -211,7 +211,8 @@ export default function getConfigTemplate (): ConfigOptions { }, system: { deleteOnFail: false, // Whether to delete files if trashing them fails - avoidNewTabs: true // Whether to avoid opening new tabs for documents if possible + avoidNewTabs: true, // Whether to avoid opening new tabs for documents if possible + showInNotification: false }, checkForBeta: false, // Should the user be notified of beta releases? uuid: uuid4() // The app's unique anonymous identifier diff --git a/source/app/service-providers/assets/types.config-provider.d.ts b/source/app/service-providers/assets/types.config-provider.d.ts index 9090d3e9d9..cbc4587587 100644 --- a/source/app/service-providers/assets/types.config-provider.d.ts +++ b/source/app/service-providers/assets/types.config-provider.d.ts @@ -144,6 +144,7 @@ interface ConfigOptions { system: { deleteOnFail: boolean avoidNewTabs: boolean + showInNotification: boolean } checkForBeta: boolean uuid: string diff --git a/source/win-preferences/schema/advanced.js b/source/win-preferences/schema/advanced.js index c6dc0b161d..2ff6cb2fa2 100644 --- a/source/win-preferences/schema/advanced.js +++ b/source/win-preferences/schema/advanced.js @@ -35,6 +35,11 @@ export default { type: 'checkbox', label: trans('dialog.preferences.delete_on_fail'), model: 'system.deleteOnFail' + }, + { + type: 'checkbox', + label: 'Show app in the notification area', + model: 'system.showInNotification' } ], [ From 1db8ac0b278c1bb15fb67d56ec980aa8d6dce6ae Mon Sep 17 00:00:00 2001 From: Bruins <18346124519@163.com> Date: Mon, 26 Apr 2021 23:45:24 +0930 Subject: [PATCH 02/16] - Issue #4: Add a tray to MacOS - Issue #7: Add show Zettlr window event to MacOS/Linux --- source/main/assets/icons/black_white_128.png | Bin 0 -> 670 bytes source/main/modules/window-manager/index.ts | 149 ++++++++++++------- 2 files changed, 98 insertions(+), 51 deletions(-) create mode 100644 source/main/assets/icons/black_white_128.png diff --git a/source/main/assets/icons/black_white_128.png b/source/main/assets/icons/black_white_128.png new file mode 100644 index 0000000000000000000000000000000000000000..2e1b2a83a0e1d440634da56714ff642113ab7239 GIT binary patch literal 670 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&F%}28J2BoosZ$T+cnA1|xB_X0 zh6aY2X+T;V$N&OHMxe<5|NqaOJJ;9O_wL=hxVX4|`}VC{x2~?P&eqOWM^D$+&+p#7 zdwF?z^XAQym6K)QWMc>oo#;KG5~y9WB*-tAfr<4$8{;7spfSiGlsT2f>N(JgJDx6% zAr*7p-o9OSNI`%#K)~>;&{og<|Nocz?*0{^5XonJ*yoDn`!$x~qKl z1&iqCkFyvJ&DQ_-?cr|G2(mxAJF+q2zX^NsSHE@kEaB^%?szgaegFAce+PrT=JW-V zS#!)R9k$s|DPF+);TFTkI%bIj3>gQwHP{Rq80X1t$meL7!8ak0mvKX24MT{nvcg*X zrsIW-1@iOx8{VZeDJ-AQUEuZW_pXCH4aJx0SIYRZ%Un2po>}4BWX9?wd(ncW-+~#R z)F~;vte?vM;Jdxtfr$&}vpjgQoFU>DCqo~51CzpghY*KL_0!l5bQy#jF7&hV++x`F zubOp3&LI(?_$9Upzut=&WHH~^=EyAZz>#6X;T_8uTJN(;KJb-R_}`jxhV}iShMAL- zN)Jr=XH>I-sUW+FnZfV%!sVrB8P@urzR41C;A@$^PXp_Lf9aQn7?ifKGH|SARJ32| z#<8M7=T*b6eD606xAxEa!FZ72RYRQg0z2kS)(aU|{N?9Z@g|-9&ue)ThSF*V`vv>v ziyK_~zW!bBDgWGt54ZoSI{bZFR(oK2PVM#7zi|~@pU&Icwi->J^KX-`-cAmC*3{i^ z{2v{P)jzm8?z7;oH`}6jy?%CO{qIPfY0uA?v)FFAVlk&a8|undefined - private _beforeMainWindowCloseCallback: Function|null + private _persistTimeout: ReturnType | undefined + private _beforeMainWindowCloseCallback: Function | null - constructor () { + constructor() { this._mainWindow = null this._qlWindows = [] this._printWindow = null @@ -110,7 +116,7 @@ export default class WindowManager { } else { callingWindow.maximize() } - // fall through + // fall through case 'get-maximised-status': event.reply('window-controls', { command: 'get-maximised-status', @@ -176,7 +182,7 @@ export default class WindowManager { /** * Loads persisted window position data from disk */ - async loadData (): Promise { + async loadData(): Promise { try { const data = await fs.readFile(this._configFile, 'utf8') this._windowState = JSON.parse(data) as WindowPosition[] @@ -191,14 +197,14 @@ export default class WindowManager { * * @param {Function} callback The callback that will be called. Must return boolean. */ - onBeforeMainWindowClose (callback: () => boolean): void { + onBeforeMainWindowClose(callback: () => boolean): void { this._beforeMainWindowCloseCallback = callback } /** * Programmatically closes the main window if it is open. */ - closeMainWindow (): void { + closeMainWindow(): void { if (this._mainWindow !== null) { this._mainWindow.close() } @@ -207,18 +213,50 @@ export default class WindowManager { /** * Shuts down the window manager and performs final operations */ - shutdown (): void { + shutdown(): void { this._persistWindowPositions() } /** * Listens to events on the main window */ - private _hookMainWindow (): void { + private _hookMainWindow(): void { if (this._mainWindow === null) { return } + this._mainWindow.on('show', async () => { + // issue : Add tray to MacOS #4 + // If Zettlr is running AND the Show app in the notification area is true, + // the tray icon will be visible (regardless if Zettlr window(s) are visible or not). + // Zettlr can take a while a load. Only show the tray when the Zettlr window is ready. + // Do not add the actions (event handlers) to tray click and tray menu. See separate issue. + if (process.platform == 'darwin') { + if (tray == null) { + let basepath = app.getAppPath() + let image = await nativeImage.createThumbnailFromPath(basepath + '/source/main/assets/icons/black_white_128.png', { width: 16, height: 16 }) + tray = new Tray(image) + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show zettlr', + click: () => { + this.showAnyWindow() + }, + type: 'normal' + }, + { label: '', type: 'separator' }, + { + label: 'Quit', + click: () => { + app.quit() + }, type: 'normal' + } + ]) + tray.setContextMenu(contextMenu) + } + } + }) + // Listens to events from the window this._mainWindow.on('close', (event) => { // The user has requested the window to be closed -> first close @@ -271,7 +309,7 @@ export default class WindowManager { * * @param {BrowserWindow} win The window to make visible */ - private _makeVisible (win: BrowserWindow): void { + private _makeVisible(win: BrowserWindow): void { if (win.isMinimized()) { // Maximise and move on top win.maximize() @@ -289,7 +327,7 @@ export default class WindowManager { /** * Persists the window positions to disk */ - private _persistWindowPositions (): void { + private _persistWindowPositions(): void { if (this._fileLock) { if (this._persistTimeout !== undefined) { clearTimeout(this._persistTimeout) @@ -324,7 +362,7 @@ export default class WindowManager { * * @return {WindowPosition} A sanitised WindowPosition */ - private _retrieveWindowPosition (type: string, defaultSize: Rect|null, predicate?: Record): WindowPosition { + private _retrieveWindowPosition(type: string, defaultSize: Rect | null, predicate?: Record): WindowPosition { let windowConfiguration = this._windowState.find(state => { if (state.windowType !== type) { return false @@ -408,7 +446,7 @@ export default class WindowManager { * @param {BrowserWindow} window The window to hook * @param {WindowPosition} conf The configuration to update */ - private _hookWindowResize (window: BrowserWindow, conf: WindowPosition): void { + private _hookWindowResize(window: BrowserWindow, conf: WindowPosition): void { const callback = (): void => { let newBounds = window.getBounds() // The configuration object will be edited in place. @@ -462,7 +500,7 @@ export default class WindowManager { /** * Shows the main window */ - showMainWindow (): void { + showMainWindow(): void { if (this._mainWindow === null) { const display = screen.getPrimaryDisplay() const windowConfiguration = this._retrieveWindowPosition('main', { @@ -483,7 +521,7 @@ export default class WindowManager { /** * Shows any window. If none are open, the main window will be opened and shown. */ - showAnyWindow (): void { + showAnyWindow(): void { const windows = BrowserWindow.getAllWindows() if (windows.length === 0) { this.showMainWindow() @@ -497,7 +535,7 @@ export default class WindowManager { * * @param {MDFileDescriptor} file The file to display in the Quicklook */ - showQuicklookWindow (file: MDFileDescriptor): void { + showQuicklookWindow(file: MDFileDescriptor): void { // Opens a new Quicklook. It's called new because there can be multiple // Quicklook windows. @@ -534,7 +572,7 @@ export default class WindowManager { /** * Displays the log window */ - showLogWindow (): void { + showLogWindow(): void { if (this._logWindow === null) { const conf = this._retrieveWindowPosition('log', null) this._logWindow = createLogWindow(conf) @@ -552,7 +590,7 @@ export default class WindowManager { /** * Displays the defaults window */ - showDefaultsWindow (): void { + showDefaultsWindow(): void { if (this._defaultsWindow === null) { const conf = this._retrieveWindowPosition('log', null) this._defaultsWindow = createDefaultsWindow(conf) @@ -570,7 +608,7 @@ export default class WindowManager { /** * Shows the statistics window */ - showStatsWindow (): void { + showStatsWindow(): void { if (this._statsWindow === null) { const conf = this._retrieveWindowPosition('stats', null) this._statsWindow = createStatsWindow(conf) @@ -587,10 +625,19 @@ export default class WindowManager { /** * Shows the preferences window */ - showPreferences (): void { + showPreferences(): void { if (this._preferences === null) { - const conf = this._retrieveWindowPosition('preferences', null) - this._preferences = createPreferencesWindow(conf) + // const conf = this._retrieveWindowPosition('preferences', null) + let conf: WindowPosition = { + windowType: 'preferences', + lastDisplayId: 69734662, + top: 279.5, + left: 448, + width: 896, + height: 513, + isMaximised: false + } + this._preferences = createPreferencesWindow(conf); this._hookWindowResize(this._preferences, conf) // Dereference the window as soon as it is closed @@ -605,7 +652,7 @@ export default class WindowManager { /** * Shows the custom CSS window */ - showCustomCSS (): void { + showCustomCSS(): void { if (this._customCSS === null) { const display = screen.getPrimaryDisplay() const conf = this._retrieveWindowPosition('custom-css', { @@ -629,7 +676,7 @@ export default class WindowManager { /** * Shows the custom CSS window */ - showAboutWindow (): void { + showAboutWindow(): void { if (this._aboutWindow === null) { const display = screen.getPrimaryDisplay() const conf = this._retrieveWindowPosition('about', { @@ -653,7 +700,7 @@ export default class WindowManager { /** * Shows the tag manager window */ - showTagManager (): void { + showTagManager(): void { if (this._tagManager === null) { const conf = this._retrieveWindowPosition('tag-manager', null) this._tagManager = createTagManagerWindow(conf) @@ -671,7 +718,7 @@ export default class WindowManager { /** * Shows the paste image modal and, after closing, returns */ - async showPasteImageModal (startPath: string): Promise { + async showPasteImageModal(startPath: string): Promise { return await new Promise((resolve, reject) => { if (this._mainWindow === null) { return reject(new Error('[Window Manager] A paste image modal was requested, but there was no main window open.')) @@ -693,7 +740,7 @@ export default class WindowManager { }) } - showErrorMessage (title: string, message: string, contents?: string): void { + showErrorMessage(title: string, message: string, contents?: string): void { if (this._mainWindow === null) { global.log.error('[Application] Could not display error message, because the main window was not open!', message) return @@ -718,7 +765,7 @@ export default class WindowManager { * * @param {string} filePath The file to load */ - showPrintWindow (filePath: string): void { + showPrintWindow(filePath: string): void { if (this._printWindow === null) { const conf = this._retrieveWindowPosition('print', null) this._printWindow = createPrintWindow(filePath, conf) @@ -746,7 +793,7 @@ export default class WindowManager { * * @param {boolean} modificationState Whether to indicate a modification */ - setModified (modificationState: boolean): void { + setModified(modificationState: boolean): void { if (this._mainWindow !== null && process.platform === 'darwin') { this._mainWindow.setDocumentEdited(modificationState) } @@ -757,7 +804,7 @@ export default class WindowManager { * * @return {BrowserWindow|null} The main window */ - getMainWindow (): BrowserWindow|null { + getMainWindow(): BrowserWindow | null { return this._mainWindow } @@ -770,7 +817,7 @@ export default class WindowManager { * @param {string} filename The filename to be displayed. * @return {boolean} True if the file should be replaced */ - async shouldReplaceFile (filename: string): Promise { + async shouldReplaceFile(filename: string): Promise { if (this._mainWindow === null) { // If the main window is not open, there is no sense in showing this // box, as the file is not really "open". It will be shown once a new @@ -787,7 +834,7 @@ export default class WindowManager { * @param {string} filename The filename that should be contained in the message * @return {boolean} Resolves with true if the file should be overwritten */ - async shouldOverwriteFile (filename: string): Promise { + async shouldOverwriteFile(filename: string): Promise { return await shouldOverwriteFileDialog(this._mainWindow, filename) } @@ -798,7 +845,7 @@ export default class WindowManager { * * @return {Promise} Returns the message box results */ - async askSaveChanges (): Promise { + async askSaveChanges(): Promise { return await askSaveChanges(this._mainWindow) } @@ -806,7 +853,7 @@ export default class WindowManager { * Show the dialog for choosing a directory * @return {string[]} An array containing all selected paths. */ - async askDir (win?: BrowserWindow|null): Promise { + async askDir(win?: BrowserWindow | null): Promise { if (win != null) { return await askDirectoryDialog(win) } else { @@ -823,7 +870,7 @@ export default class WindowManager { * * @return {string[]} An array containing all selected files. */ - async askFile (filters: FileFilter[]|null = null, multiSel: boolean = false, win?: BrowserWindow|null): Promise { + async askFile(filters: FileFilter[] | null = null, multiSel: boolean = false, win?: BrowserWindow | null): Promise { if (win != null) { return await askFileDialog(win, filters, multiSel) } else { @@ -835,7 +882,7 @@ export default class WindowManager { * This function prompts the user with information. * @param {any} options Necessary informations for displaying the prompt */ - prompt (options: any): void { + prompt(options: any): void { promptDialog(this._mainWindow, options) } @@ -844,10 +891,10 @@ export default class WindowManager { * @param {MDFileDescriptor|DirDescriptor} descriptor The corresponding descriptor * @return {boolean} True if user wishes to remove it. */ - async confirmRemove (descriptor: MDFileDescriptor|CodeFileDescriptor|DirDescriptor): Promise { + async confirmRemove(descriptor: MDFileDescriptor | CodeFileDescriptor | DirDescriptor): Promise { const options: MessageBoxOptions = { type: 'warning', - buttons: [ 'Ok', trans('system.error.cancel_remove') ], + buttons: ['Ok', trans('system.error.cancel_remove')], defaultId: 0, cancelId: 1, title: trans('system.error.remove_title'), From 342e2c3bd70a2eef558fe694247dec67de2903df Mon Sep 17 00:00:00 2001 From: Invited User iuk5bytl Date: Wed, 28 Apr 2021 13:01:16 +0930 Subject: [PATCH 03/16] -Issue #1: Update preferences with 'Leave app running in the notification area' -Issue #2: Update preferences with'Show app in the notification area' --- source/app/service-providers/assets/get-config-template.ts | 2 +- .../app/service-providers/assets/types.config-provider.d.ts | 2 +- source/win-preferences/schema/advanced.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/app/service-providers/assets/get-config-template.ts b/source/app/service-providers/assets/get-config-template.ts index 844cde4b7c..62753d3efc 100644 --- a/source/app/service-providers/assets/get-config-template.ts +++ b/source/app/service-providers/assets/get-config-template.ts @@ -212,7 +212,7 @@ export default function getConfigTemplate (): ConfigOptions { system: { deleteOnFail: false, // Whether to delete files if trashing them fails avoidNewTabs: true, // Whether to avoid opening new tabs for documents if possible - showInNotification: false + displayInNotification: false }, checkForBeta: false, // Should the user be notified of beta releases? uuid: uuid4() // The app's unique anonymous identifier diff --git a/source/app/service-providers/assets/types.config-provider.d.ts b/source/app/service-providers/assets/types.config-provider.d.ts index cbc4587587..d0331089fc 100644 --- a/source/app/service-providers/assets/types.config-provider.d.ts +++ b/source/app/service-providers/assets/types.config-provider.d.ts @@ -144,7 +144,7 @@ interface ConfigOptions { system: { deleteOnFail: boolean avoidNewTabs: boolean - showInNotification: boolean + displayInNotification: boolean } checkForBeta: boolean uuid: string diff --git a/source/win-preferences/schema/advanced.js b/source/win-preferences/schema/advanced.js index 2ff6cb2fa2..fa0836d751 100644 --- a/source/win-preferences/schema/advanced.js +++ b/source/win-preferences/schema/advanced.js @@ -38,8 +38,8 @@ export default { }, { type: 'checkbox', - label: 'Show app in the notification area', - model: 'system.showInNotification' + label: process.platform === 'darwin'? 'Show app in the notification area' : 'leave app running in the notification area', + model: 'system.displayInNotification' } ], [ From 0afb9fe6ce267f4bab36fb4e53a593c0aa7c5d5e Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <18346124519@163.com> Date: Wed, 28 Apr 2021 13:01:16 +0930 Subject: [PATCH 04/16] -Issue #1: Update preferences with 'Leave app running in the notification area' -Issue #2: Update preferences with'Show app in the notification area' --- source/app/service-providers/assets/get-config-template.ts | 2 +- .../app/service-providers/assets/types.config-provider.d.ts | 2 +- source/win-preferences/schema/advanced.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/app/service-providers/assets/get-config-template.ts b/source/app/service-providers/assets/get-config-template.ts index 844cde4b7c..62753d3efc 100644 --- a/source/app/service-providers/assets/get-config-template.ts +++ b/source/app/service-providers/assets/get-config-template.ts @@ -212,7 +212,7 @@ export default function getConfigTemplate (): ConfigOptions { system: { deleteOnFail: false, // Whether to delete files if trashing them fails avoidNewTabs: true, // Whether to avoid opening new tabs for documents if possible - showInNotification: false + displayInNotification: false }, checkForBeta: false, // Should the user be notified of beta releases? uuid: uuid4() // The app's unique anonymous identifier diff --git a/source/app/service-providers/assets/types.config-provider.d.ts b/source/app/service-providers/assets/types.config-provider.d.ts index cbc4587587..d0331089fc 100644 --- a/source/app/service-providers/assets/types.config-provider.d.ts +++ b/source/app/service-providers/assets/types.config-provider.d.ts @@ -144,7 +144,7 @@ interface ConfigOptions { system: { deleteOnFail: boolean avoidNewTabs: boolean - showInNotification: boolean + displayInNotification: boolean } checkForBeta: boolean uuid: string diff --git a/source/win-preferences/schema/advanced.js b/source/win-preferences/schema/advanced.js index 2ff6cb2fa2..fa0836d751 100644 --- a/source/win-preferences/schema/advanced.js +++ b/source/win-preferences/schema/advanced.js @@ -38,8 +38,8 @@ export default { }, { type: 'checkbox', - label: 'Show app in the notification area', - model: 'system.showInNotification' + label: process.platform === 'darwin'? 'Show app in the notification area' : 'leave app running in the notification area', + model: 'system.displayInNotification' } ], [ From 7ae6dabd0aec6b0cc198909ed4dd9d660ae68448 Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <18346124519@163.com> Date: Fri, 30 Apr 2021 22:20:58 +0930 Subject: [PATCH 05/16] Issue #9: Change titlebar x to close window and not quit --- source/main/modules/window-manager/index.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index 27b5f90ea0..8354f952ec 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -127,7 +127,17 @@ export default class WindowManager { callingWindow.minimize() break case 'win-close': - callingWindow.close() + if (process.platform !== 'darwin') { + const showInNotification = Boolean(global.config.get('system.showInNotification')) + if (showInNotification) { + callingWindow.hide() + } + else { + callingWindow.close() + } + } else { + callingWindow.close() + } break // Convenience APIs for the renderers to execute these commands case 'cut': From 3f06d2c8eb6d65caf58dc8890cef126a55e7650b Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <18346124519@163.com> Date: Fri, 30 Apr 2021 22:28:40 +0930 Subject: [PATCH 06/16] Issue #28 : Add tooltip message to guide user to understand the basic function of tray --- source/main/modules/window-manager/index.ts | 32 +++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index 8354f952ec..8c9126f40c 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -236,11 +236,6 @@ export default class WindowManager { } this._mainWindow.on('show', async () => { - // issue : Add tray to MacOS #4 - // If Zettlr is running AND the Show app in the notification area is true, - // the tray icon will be visible (regardless if Zettlr window(s) are visible or not). - // Zettlr can take a while a load. Only show the tray when the Zettlr window is ready. - // Do not add the actions (event handlers) to tray click and tray menu. See separate issue. if (process.platform == 'darwin') { if (tray == null) { let basepath = app.getAppPath() @@ -262,6 +257,33 @@ export default class WindowManager { }, type: 'normal' } ]) + tray.setToolTip('This is zettlr tray. \n click show Zettlr button to display app \n click quit to quit app') + tray.setContextMenu(contextMenu) + } + } else { + if (tray == null) { + tray = new Tray(app.getAppPath() + '\/source\/main\/assets\/icons\/128x128.png') + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show Zettlr', + click: () => { + // Add show Zettlr window event to Windows #6 + this.showMainWindow() + }, + type: 'normal' + }, + { label: '', type: 'separator' }, + { + label: 'Quit', + click: () => { + // Add quit event to tray #8 + // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. + app.quit() + }, + type: 'normal' + } + ]) + tray.setToolTip('This is zettlr tray. \n click show Zettlr button to display app \n click quit to quit app') tray.setContextMenu(contextMenu) } } From 07fe78ca3b7eba1ef2e09e542f51379667f1ab5c Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <18346124519@163.com> Date: Fri, 30 Apr 2021 22:43:29 +0930 Subject: [PATCH 07/16] - Fix issue according to @cskeogh comments --- source/main/modules/window-manager/index.ts | 34 ++++++++++----------- source/win-preferences/schema/advanced.js | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index 8c9126f40c..b699c89594 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -63,24 +63,24 @@ interface QuicklookRecord { } export default class WindowManager { - private _mainWindow: BrowserWindow | null + private _mainWindow: BrowserWindow|null private readonly _qlWindows: QuicklookRecord[] - private _printWindow: BrowserWindow | null - private _logWindow: BrowserWindow | null - private _statsWindow: BrowserWindow | null - private _defaultsWindow: BrowserWindow | null - private _preferences: BrowserWindow | null - private _customCSS: BrowserWindow | null - private _aboutWindow: BrowserWindow | null - private _tagManager: BrowserWindow | null - private _pasteImageModal: BrowserWindow | null - private _errorModal: BrowserWindow | null - private _printWindowFile: string | undefined + private _printWindow: BrowserWindow|null + private _logWindow: BrowserWindow|null + private _statsWindow: BrowserWindow|null + private _defaultsWindow: BrowserWindow|null + private _preferences: BrowserWindow|null + private _customCSS: BrowserWindow|null + private _aboutWindow: BrowserWindow|null + private _tagManager: BrowserWindow|null + private _pasteImageModal: BrowserWindow|null + private _errorModal: BrowserWindow|null + private _printWindowFile: string|undefined private _windowState: WindowPosition[] private readonly _configFile: string private _fileLock: boolean - private _persistTimeout: ReturnType | undefined - private _beforeMainWindowCloseCallback: Function | null + private _persistTimeout: ReturnType|undefined + private _beforeMainWindowCloseCallback: Function|null constructor() { this._mainWindow = null @@ -239,11 +239,11 @@ export default class WindowManager { if (process.platform == 'darwin') { if (tray == null) { let basepath = app.getAppPath() - let image = await nativeImage.createThumbnailFromPath(basepath + '/source/main/assets/icons/black_white_128.png', { width: 16, height: 16 }) + let image = await nativeImage.createThumbnailFromPath(path.join(__dirname, 'assets/icons/128x128.png'), { width: 16, height: 16 }) tray = new Tray(image) const contextMenu = Menu.buildFromTemplate([ { - label: 'Show zettlr', + label: 'Show Zettlr', click: () => { this.showAnyWindow() }, @@ -262,7 +262,7 @@ export default class WindowManager { } } else { if (tray == null) { - tray = new Tray(app.getAppPath() + '\/source\/main\/assets\/icons\/128x128.png') + tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) const contextMenu = Menu.buildFromTemplate([ { label: 'Show Zettlr', diff --git a/source/win-preferences/schema/advanced.js b/source/win-preferences/schema/advanced.js index fa0836d751..23bc7ab03c 100644 --- a/source/win-preferences/schema/advanced.js +++ b/source/win-preferences/schema/advanced.js @@ -38,7 +38,7 @@ export default { }, { type: 'checkbox', - label: process.platform === 'darwin'? 'Show app in the notification area' : 'leave app running in the notification area', + label: process.platform === 'darwin'? 'Show app in the notification area' : 'Leave app running in the notification area', model: 'system.displayInNotification' } ], From 97e4a8b806096edc0ac6d489c5862600c05ed883 Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <> Date: Tue, 4 May 2021 11:01:06 +0930 Subject: [PATCH 08/16] - part 2: fix issue according to @cskeogh comments --- .../service-providers/appearance-provider.ts | 6 +- source/main/modules/window-manager/index.ts | 118 +++++++++--------- source/win-preferences/schema/advanced.js | 4 +- 3 files changed, 61 insertions(+), 67 deletions(-) diff --git a/source/app/service-providers/appearance-provider.ts b/source/app/service-providers/appearance-provider.ts index a95c88bb37..526e4702f3 100644 --- a/source/app/service-providers/appearance-provider.ts +++ b/source/app/service-providers/appearance-provider.ts @@ -121,9 +121,9 @@ export default class AppearanceProvider extends EventEmitter { // Calculate the contrast before returning const dark = '33333333' const light = 'eeeeeeee' - const r = parseInt(accentColor.substring(0, 2), 16); // hexToR - const g = parseInt(accentColor.substring(2, 4), 16); // hexToG - const b = parseInt(accentColor.substring(4, 6), 16); // hexToB + const r = parseInt(accentColor.substring(0, 2), 16) // hexToR + const g = parseInt(accentColor.substring(2, 4), 16) // hexToG + const b = parseInt(accentColor.substring(4, 6), 16) // hexToB const ratio = (r * 0.299) + (g * 0.587) + (b * 0.114) const threshold = 186 // NOTE: We can adapt this later on return { diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index b699c89594..cdde2fe3ad 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -54,9 +54,6 @@ import { WindowPosition } from './types.d' import askFileDialog from './dialog/ask-file' // import dragIcon from '../../assets/dragicon.png' -// issue : Add tray to MacOS #4 -let tray: Tray | null = null - interface QuicklookRecord { path: string win: BrowserWindow @@ -82,7 +79,10 @@ export default class WindowManager { private _persistTimeout: ReturnType|undefined private _beforeMainWindowCloseCallback: Function|null - constructor() { + // Add tray to MacOS + private _tray: Tray | null + + constructor () { this._mainWindow = null this._qlWindows = [] this._printWindow = null @@ -100,6 +100,7 @@ export default class WindowManager { this._configFile = path.join(app.getPath('userData'), 'window_state.json') this._fileLock = false this._beforeMainWindowCloseCallback = null + this._tray = null // Listen to window control commands ipcMain.on('window-controls', (event, message) => { @@ -131,8 +132,7 @@ export default class WindowManager { const showInNotification = Boolean(global.config.get('system.showInNotification')) if (showInNotification) { callingWindow.hide() - } - else { + } else { callingWindow.close() } } else { @@ -192,7 +192,7 @@ export default class WindowManager { /** * Loads persisted window position data from disk */ - async loadData(): Promise { + async loadData (): Promise { try { const data = await fs.readFile(this._configFile, 'utf8') this._windowState = JSON.parse(data) as WindowPosition[] @@ -207,14 +207,14 @@ export default class WindowManager { * * @param {Function} callback The callback that will be called. Must return boolean. */ - onBeforeMainWindowClose(callback: () => boolean): void { + onBeforeMainWindowClose (callback: () => boolean): void { this._beforeMainWindowCloseCallback = callback } /** * Programmatically closes the main window if it is open. */ - closeMainWindow(): void { + closeMainWindow (): void { if (this._mainWindow !== null) { this._mainWindow.close() } @@ -223,24 +223,26 @@ export default class WindowManager { /** * Shuts down the window manager and performs final operations */ - shutdown(): void { + shutdown (): void { this._persistWindowPositions() } /** * Listens to events on the main window */ - private _hookMainWindow(): void { + private _hookMainWindow (): void { if (this._mainWindow === null) { return } this._mainWindow.on('show', async () => { - if (process.platform == 'darwin') { - if (tray == null) { + if (process.platform === 'darwin') { + if (this._tray == null) { let basepath = app.getAppPath() - let image = await nativeImage.createThumbnailFromPath(path.join(__dirname, 'assets/icons/128x128.png'), { width: 16, height: 16 }) - tray = new Tray(image) + let image = await nativeImage.createThumbnailFromPath(basepath + '/source/main/assets/icons/black_white_128.png', { width: 16, height: 16 }) + this._tray = new Tray(image) + + // this._tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) const contextMenu = Menu.buildFromTemplate([ { label: 'Show Zettlr', @@ -254,20 +256,21 @@ export default class WindowManager { label: 'Quit', click: () => { app.quit() - }, type: 'normal' + }, + type: 'normal' } ]) - tray.setToolTip('This is zettlr tray. \n click show Zettlr button to display app \n click quit to quit app') - tray.setContextMenu(contextMenu) + this._tray.setToolTip('This is Zettlr tray. \n click show Zettlr button to display app \n click quit to quit app') + this._tray.setContextMenu(contextMenu) } } else { - if (tray == null) { - tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) + if (this._tray == null) { + this._tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) const contextMenu = Menu.buildFromTemplate([ { label: 'Show Zettlr', click: () => { - // Add show Zettlr window event to Windows #6 + // Add show Zettlr window event to Windows this.showMainWindow() }, type: 'normal' @@ -276,15 +279,15 @@ export default class WindowManager { { label: 'Quit', click: () => { - // Add quit event to tray #8 + // Add quit event to tray // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. app.quit() }, type: 'normal' } ]) - tray.setToolTip('This is zettlr tray. \n click show Zettlr button to display app \n click quit to quit app') - tray.setContextMenu(contextMenu) + this._tray.setToolTip('This is zettlr tray. \n click show Zettlr button to display app \n click quit to quit app') + this._tray.setContextMenu(contextMenu) } } }) @@ -341,7 +344,7 @@ export default class WindowManager { * * @param {BrowserWindow} win The window to make visible */ - private _makeVisible(win: BrowserWindow): void { + private _makeVisible (win: BrowserWindow): void { if (win.isMinimized()) { // Maximise and move on top win.maximize() @@ -359,7 +362,7 @@ export default class WindowManager { /** * Persists the window positions to disk */ - private _persistWindowPositions(): void { + private _persistWindowPositions (): void { if (this._fileLock) { if (this._persistTimeout !== undefined) { clearTimeout(this._persistTimeout) @@ -394,7 +397,7 @@ export default class WindowManager { * * @return {WindowPosition} A sanitised WindowPosition */ - private _retrieveWindowPosition(type: string, defaultSize: Rect | null, predicate?: Record): WindowPosition { + private _retrieveWindowPosition (type: string, defaultSize: Rect | null, predicate?: Record): WindowPosition { let windowConfiguration = this._windowState.find(state => { if (state.windowType !== type) { return false @@ -478,7 +481,7 @@ export default class WindowManager { * @param {BrowserWindow} window The window to hook * @param {WindowPosition} conf The configuration to update */ - private _hookWindowResize(window: BrowserWindow, conf: WindowPosition): void { + private _hookWindowResize (window: BrowserWindow, conf: WindowPosition): void { const callback = (): void => { let newBounds = window.getBounds() // The configuration object will be edited in place. @@ -532,7 +535,7 @@ export default class WindowManager { /** * Shows the main window */ - showMainWindow(): void { + showMainWindow (): void { if (this._mainWindow === null) { const display = screen.getPrimaryDisplay() const windowConfiguration = this._retrieveWindowPosition('main', { @@ -553,7 +556,7 @@ export default class WindowManager { /** * Shows any window. If none are open, the main window will be opened and shown. */ - showAnyWindow(): void { + showAnyWindow (): void { const windows = BrowserWindow.getAllWindows() if (windows.length === 0) { this.showMainWindow() @@ -567,7 +570,7 @@ export default class WindowManager { * * @param {MDFileDescriptor} file The file to display in the Quicklook */ - showQuicklookWindow(file: MDFileDescriptor): void { + showQuicklookWindow (file: MDFileDescriptor): void { // Opens a new Quicklook. It's called new because there can be multiple // Quicklook windows. @@ -604,7 +607,7 @@ export default class WindowManager { /** * Displays the log window */ - showLogWindow(): void { + showLogWindow (): void { if (this._logWindow === null) { const conf = this._retrieveWindowPosition('log', null) this._logWindow = createLogWindow(conf) @@ -622,7 +625,7 @@ export default class WindowManager { /** * Displays the defaults window */ - showDefaultsWindow(): void { + showDefaultsWindow (): void { if (this._defaultsWindow === null) { const conf = this._retrieveWindowPosition('log', null) this._defaultsWindow = createDefaultsWindow(conf) @@ -640,7 +643,7 @@ export default class WindowManager { /** * Shows the statistics window */ - showStatsWindow(): void { + showStatsWindow (): void { if (this._statsWindow === null) { const conf = this._retrieveWindowPosition('stats', null) this._statsWindow = createStatsWindow(conf) @@ -657,19 +660,10 @@ export default class WindowManager { /** * Shows the preferences window */ - showPreferences(): void { + showPreferences (): void { if (this._preferences === null) { - // const conf = this._retrieveWindowPosition('preferences', null) - let conf: WindowPosition = { - windowType: 'preferences', - lastDisplayId: 69734662, - top: 279.5, - left: 448, - width: 896, - height: 513, - isMaximised: false - } - this._preferences = createPreferencesWindow(conf); + const conf = this._retrieveWindowPosition('preferences', null) + this._preferences = createPreferencesWindow(conf) this._hookWindowResize(this._preferences, conf) // Dereference the window as soon as it is closed @@ -684,7 +678,7 @@ export default class WindowManager { /** * Shows the custom CSS window */ - showCustomCSS(): void { + showCustomCSS (): void { if (this._customCSS === null) { const display = screen.getPrimaryDisplay() const conf = this._retrieveWindowPosition('custom-css', { @@ -708,7 +702,7 @@ export default class WindowManager { /** * Shows the custom CSS window */ - showAboutWindow(): void { + showAboutWindow (): void { if (this._aboutWindow === null) { const display = screen.getPrimaryDisplay() const conf = this._retrieveWindowPosition('about', { @@ -732,7 +726,7 @@ export default class WindowManager { /** * Shows the tag manager window */ - showTagManager(): void { + showTagManager (): void { if (this._tagManager === null) { const conf = this._retrieveWindowPosition('tag-manager', null) this._tagManager = createTagManagerWindow(conf) @@ -750,7 +744,7 @@ export default class WindowManager { /** * Shows the paste image modal and, after closing, returns */ - async showPasteImageModal(startPath: string): Promise { + async showPasteImageModal (startPath: string): Promise { return await new Promise((resolve, reject) => { if (this._mainWindow === null) { return reject(new Error('[Window Manager] A paste image modal was requested, but there was no main window open.')) @@ -772,7 +766,7 @@ export default class WindowManager { }) } - showErrorMessage(title: string, message: string, contents?: string): void { + showErrorMessage (title: string, message: string, contents?: string): void { if (this._mainWindow === null) { global.log.error('[Application] Could not display error message, because the main window was not open!', message) return @@ -797,7 +791,7 @@ export default class WindowManager { * * @param {string} filePath The file to load */ - showPrintWindow(filePath: string): void { + showPrintWindow (filePath: string): void { if (this._printWindow === null) { const conf = this._retrieveWindowPosition('print', null) this._printWindow = createPrintWindow(filePath, conf) @@ -825,7 +819,7 @@ export default class WindowManager { * * @param {boolean} modificationState Whether to indicate a modification */ - setModified(modificationState: boolean): void { + setModified (modificationState: boolean): void { if (this._mainWindow !== null && process.platform === 'darwin') { this._mainWindow.setDocumentEdited(modificationState) } @@ -836,7 +830,7 @@ export default class WindowManager { * * @return {BrowserWindow|null} The main window */ - getMainWindow(): BrowserWindow | null { + getMainWindow (): BrowserWindow | null { return this._mainWindow } @@ -849,7 +843,7 @@ export default class WindowManager { * @param {string} filename The filename to be displayed. * @return {boolean} True if the file should be replaced */ - async shouldReplaceFile(filename: string): Promise { + async shouldReplaceFile (filename: string): Promise { if (this._mainWindow === null) { // If the main window is not open, there is no sense in showing this // box, as the file is not really "open". It will be shown once a new @@ -866,7 +860,7 @@ export default class WindowManager { * @param {string} filename The filename that should be contained in the message * @return {boolean} Resolves with true if the file should be overwritten */ - async shouldOverwriteFile(filename: string): Promise { + async shouldOverwriteFile (filename: string): Promise { return await shouldOverwriteFileDialog(this._mainWindow, filename) } @@ -877,7 +871,7 @@ export default class WindowManager { * * @return {Promise} Returns the message box results */ - async askSaveChanges(): Promise { + async askSaveChanges (): Promise { return await askSaveChanges(this._mainWindow) } @@ -885,7 +879,7 @@ export default class WindowManager { * Show the dialog for choosing a directory * @return {string[]} An array containing all selected paths. */ - async askDir(win?: BrowserWindow | null): Promise { + async askDir (win?: BrowserWindow | null): Promise { if (win != null) { return await askDirectoryDialog(win) } else { @@ -902,7 +896,7 @@ export default class WindowManager { * * @return {string[]} An array containing all selected files. */ - async askFile(filters: FileFilter[] | null = null, multiSel: boolean = false, win?: BrowserWindow | null): Promise { + async askFile (filters: FileFilter[] | null = null, multiSel: boolean = false, win?: BrowserWindow | null): Promise { if (win != null) { return await askFileDialog(win, filters, multiSel) } else { @@ -914,7 +908,7 @@ export default class WindowManager { * This function prompts the user with information. * @param {any} options Necessary informations for displaying the prompt */ - prompt(options: any): void { + prompt (options: any): void { promptDialog(this._mainWindow, options) } @@ -923,10 +917,10 @@ export default class WindowManager { * @param {MDFileDescriptor|DirDescriptor} descriptor The corresponding descriptor * @return {boolean} True if user wishes to remove it. */ - async confirmRemove(descriptor: MDFileDescriptor | CodeFileDescriptor | DirDescriptor): Promise { + async confirmRemove (descriptor: MDFileDescriptor | CodeFileDescriptor | DirDescriptor): Promise { const options: MessageBoxOptions = { type: 'warning', - buttons: ['Ok', trans('system.error.cancel_remove')], + buttons: [ 'Ok', trans('system.error.cancel_remove') ], defaultId: 0, cancelId: 1, title: trans('system.error.remove_title'), diff --git a/source/win-preferences/schema/advanced.js b/source/win-preferences/schema/advanced.js index 23bc7ab03c..ef6a31a977 100644 --- a/source/win-preferences/schema/advanced.js +++ b/source/win-preferences/schema/advanced.js @@ -37,8 +37,8 @@ export default { model: 'system.deleteOnFail' }, { - type: 'checkbox', - label: process.platform === 'darwin'? 'Show app in the notification area' : 'Leave app running in the notification area', + type: 'checkbox', + label: process.platform === 'darwin' ? 'Show app in the notification area' : 'Leave app running in the notification area', model: 'system.displayInNotification' } ], From d390c4a58d2bc4929e71526f6bac98a30b432eb3 Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <> Date: Tue, 4 May 2021 11:21:30 +0930 Subject: [PATCH 09/16] - keep leaveAppRunning --- source/app/service-providers/assets/get-config-template.ts | 2 +- source/app/service-providers/assets/types.config-provider.d.ts | 2 +- source/win-preferences/schema/advanced.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/app/service-providers/assets/get-config-template.ts b/source/app/service-providers/assets/get-config-template.ts index 62753d3efc..bee7a58a3b 100644 --- a/source/app/service-providers/assets/get-config-template.ts +++ b/source/app/service-providers/assets/get-config-template.ts @@ -212,7 +212,7 @@ export default function getConfigTemplate (): ConfigOptions { system: { deleteOnFail: false, // Whether to delete files if trashing them fails avoidNewTabs: true, // Whether to avoid opening new tabs for documents if possible - displayInNotification: false + leaveAppRunning: false }, checkForBeta: false, // Should the user be notified of beta releases? uuid: uuid4() // The app's unique anonymous identifier diff --git a/source/app/service-providers/assets/types.config-provider.d.ts b/source/app/service-providers/assets/types.config-provider.d.ts index d0331089fc..bab9a4988e 100644 --- a/source/app/service-providers/assets/types.config-provider.d.ts +++ b/source/app/service-providers/assets/types.config-provider.d.ts @@ -144,7 +144,7 @@ interface ConfigOptions { system: { deleteOnFail: boolean avoidNewTabs: boolean - displayInNotification: boolean + leaveAppRunning: boolean } checkForBeta: boolean uuid: string diff --git a/source/win-preferences/schema/advanced.js b/source/win-preferences/schema/advanced.js index ef6a31a977..e87f8391a7 100644 --- a/source/win-preferences/schema/advanced.js +++ b/source/win-preferences/schema/advanced.js @@ -39,7 +39,7 @@ export default { { type: 'checkbox', label: process.platform === 'darwin' ? 'Show app in the notification area' : 'Leave app running in the notification area', - model: 'system.displayInNotification' + model: 'system.leaveAppRunning' } ], [ From cb54f2093219ac1d2982962f455aa95e07eb7f20 Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <> Date: Thu, 6 May 2021 09:51:20 +0930 Subject: [PATCH 10/16] part 3: fix issue according to @cskeogh comments --- .../assets/get-config-template.ts | 4 +- .../assets/types.config-provider.d.ts | 2 +- source/main/modules/window-manager/index.ts | 117 +++++++++--------- 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/source/app/service-providers/assets/get-config-template.ts b/source/app/service-providers/assets/get-config-template.ts index bee7a58a3b..4f917ef324 100644 --- a/source/app/service-providers/assets/get-config-template.ts +++ b/source/app/service-providers/assets/get-config-template.ts @@ -211,8 +211,8 @@ export default function getConfigTemplate (): ConfigOptions { }, system: { deleteOnFail: false, // Whether to delete files if trashing them fails - avoidNewTabs: true, // Whether to avoid opening new tabs for documents if possible - leaveAppRunning: false + leaveAppRunning: false, // Whether to leave app running in the notification area (tray) + avoidNewTabs: true // Whether to avoid opening new tabs for documents if possible }, checkForBeta: false, // Should the user be notified of beta releases? uuid: uuid4() // The app's unique anonymous identifier diff --git a/source/app/service-providers/assets/types.config-provider.d.ts b/source/app/service-providers/assets/types.config-provider.d.ts index bab9a4988e..6ca631b267 100644 --- a/source/app/service-providers/assets/types.config-provider.d.ts +++ b/source/app/service-providers/assets/types.config-provider.d.ts @@ -143,8 +143,8 @@ interface ConfigOptions { } system: { deleteOnFail: boolean - avoidNewTabs: boolean leaveAppRunning: boolean + avoidNewTabs: boolean } checkForBeta: boolean uuid: string diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index cdde2fe3ad..5eff7aa864 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -129,8 +129,8 @@ export default class WindowManager { break case 'win-close': if (process.platform !== 'darwin') { - const showInNotification = Boolean(global.config.get('system.showInNotification')) - if (showInNotification) { + const leaveAppRunning = Boolean(global.config.get('system.leaveAppRunning')) + if (leaveAppRunning) { callingWindow.hide() } else { callingWindow.close() @@ -235,59 +235,60 @@ export default class WindowManager { return } - this._mainWindow.on('show', async () => { - if (process.platform === 'darwin') { - if (this._tray == null) { - let basepath = app.getAppPath() - let image = await nativeImage.createThumbnailFromPath(basepath + '/source/main/assets/icons/black_white_128.png', { width: 16, height: 16 }) - this._tray = new Tray(image) - - // this._tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Show Zettlr', - click: () => { - this.showAnyWindow() + this._mainWindow.on('show', () => { + const leaveAppRunning = Boolean(global.config.get('system.leaveAppRunning')) + if (leaveAppRunning) { + if (process.platform === 'darwin') { + if (this._tray == null) { + let basepath = app.getAppPath() + this._tray = new Tray(path.join(__dirname, './assets/icons/128x128.png')) + + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show Zettlr', + click: () => { + this.showAnyWindow() + }, + type: 'normal' }, - type: 'normal' - }, - { label: '', type: 'separator' }, - { - label: 'Quit', - click: () => { - app.quit() - }, - type: 'normal' - } - ]) - this._tray.setToolTip('This is Zettlr tray. \n click show Zettlr button to display app \n click quit to quit app') - this._tray.setContextMenu(contextMenu) - } - } else { - if (this._tray == null) { - this._tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Show Zettlr', - click: () => { - // Add show Zettlr window event to Windows - this.showMainWindow() - }, - type: 'normal' - }, - { label: '', type: 'separator' }, - { - label: 'Quit', - click: () => { - // Add quit event to tray - // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. - app.quit() + { label: '', type: 'separator' }, + { + label: 'Quit', + click: () => { + app.quit() + }, + type: 'normal' + } + ]) + this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') + this._tray.setContextMenu(contextMenu) + } + } else { + if (this._tray == null) { + this._tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show Zettlr', + click: () => { + // Add show Zettlr window event to Windows + this.showMainWindow() + }, + type: 'normal' }, - type: 'normal' - } - ]) - this._tray.setToolTip('This is zettlr tray. \n click show Zettlr button to display app \n click quit to quit app') - this._tray.setContextMenu(contextMenu) + { label: '', type: 'separator' }, + { + label: 'Quit', + click: () => { + // Add quit event to tray + // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. + app.quit() + }, + type: 'normal' + } + ]) + this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') + this._tray.setContextMenu(contextMenu) + } } } }) @@ -397,7 +398,7 @@ export default class WindowManager { * * @return {WindowPosition} A sanitised WindowPosition */ - private _retrieveWindowPosition (type: string, defaultSize: Rect | null, predicate?: Record): WindowPosition { + private _retrieveWindowPosition (type: string, defaultSize: Rect|null, predicate?: Record): WindowPosition { let windowConfiguration = this._windowState.find(state => { if (state.windowType !== type) { return false @@ -830,7 +831,7 @@ export default class WindowManager { * * @return {BrowserWindow|null} The main window */ - getMainWindow (): BrowserWindow | null { + getMainWindow (): BrowserWindow|null { return this._mainWindow } @@ -879,7 +880,7 @@ export default class WindowManager { * Show the dialog for choosing a directory * @return {string[]} An array containing all selected paths. */ - async askDir (win?: BrowserWindow | null): Promise { + async askDir (win?: BrowserWindow|null): Promise { if (win != null) { return await askDirectoryDialog(win) } else { @@ -896,7 +897,7 @@ export default class WindowManager { * * @return {string[]} An array containing all selected files. */ - async askFile (filters: FileFilter[] | null = null, multiSel: boolean = false, win?: BrowserWindow | null): Promise { + async askFile (filters: FileFilter[]|null = null, multiSel: boolean = false, win?: BrowserWindow|null): Promise { if (win != null) { return await askFileDialog(win, filters, multiSel) } else { @@ -917,7 +918,7 @@ export default class WindowManager { * @param {MDFileDescriptor|DirDescriptor} descriptor The corresponding descriptor * @return {boolean} True if user wishes to remove it. */ - async confirmRemove (descriptor: MDFileDescriptor | CodeFileDescriptor | DirDescriptor): Promise { + async confirmRemove (descriptor: MDFileDescriptor|CodeFileDescriptor|DirDescriptor): Promise { const options: MessageBoxOptions = { type: 'warning', buttons: [ 'Ok', trans('system.error.cancel_remove') ], From b804eb2ebdfe90e1c93a929c4b343c4f22d764ab Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <> Date: Sat, 8 May 2021 17:36:58 +0930 Subject: [PATCH 11/16] - part 4: fix issue according to @cskeogh comments --- source/main/assets/icons/22x22_white.png | Bin 0 -> 475 bytes source/main/assets/icons/black_white_128.png | Bin 670 -> 0 bytes source/main/assets/icons/icon.ico | Bin 0 -> 67646 bytes source/main/modules/window-manager/index.ts | 38 +++++++++++++++---- 4 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 source/main/assets/icons/22x22_white.png delete mode 100644 source/main/assets/icons/black_white_128.png create mode 100644 source/main/assets/icons/icon.ico diff --git a/source/main/assets/icons/22x22_white.png b/source/main/assets/icons/22x22_white.png new file mode 100644 index 0000000000000000000000000000000000000000..02338cd19447e43b861dc63de7bebde8fbfdacef GIT binary patch literal 475 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H3?x5i&EW)6jKx9jPK-BC>eK@{oCO|{#S9GG z!XV7ZFl&wkP;gOzPlzj!{!aw>@#i-Ys{a4^_m>!D|Nj4jD+98A{zWkyDEs^GAGiXG zHE%_Lt~4tN@(X5QG)&HwfAD|0=f);g4(5e3Sj1M&;ZnMAl%I1~c+kJElb(u)y#DK^ z?w+sJ)Tg~f@S)YLsqOPCyf!z8E{uE?xANJ_r=e1B*d6B{I+3>E zV$RlsJ1)OHns7&+$NhoLGS5Smt1{Tmy__Rx literal 0 HcmV?d00001 diff --git a/source/main/assets/icons/black_white_128.png b/source/main/assets/icons/black_white_128.png deleted file mode 100644 index 2e1b2a83a0e1d440634da56714ff642113ab7239..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 670 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 literal 0 HcmV?d00001 diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index 5eff7aa864..cc1095a52c 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -25,8 +25,7 @@ import { MessageBoxOptions, MessageBoxReturnValue, Menu, - Tray, - nativeImage + Tray } from 'electron' import { promises as fs } from 'fs' import path from 'path' @@ -131,12 +130,12 @@ export default class WindowManager { if (process.platform !== 'darwin') { const leaveAppRunning = Boolean(global.config.get('system.leaveAppRunning')) if (leaveAppRunning) { - callingWindow.hide() + this._mainWindow?.hide() } else { - callingWindow.close() + this._mainWindow?.close() } } else { - callingWindow.close() + this._mainWindow?.close() } break // Convenience APIs for the renderers to execute these commands @@ -240,8 +239,7 @@ export default class WindowManager { if (leaveAppRunning) { if (process.platform === 'darwin') { if (this._tray == null) { - let basepath = app.getAppPath() - this._tray = new Tray(path.join(__dirname, './assets/icons/128x128.png')) + this._tray = new Tray(path.join(__dirname, './assets/icons/22x22_white.png')) const contextMenu = Menu.buildFromTemplate([ { @@ -263,6 +261,32 @@ export default class WindowManager { this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') this._tray.setContextMenu(contextMenu) } + } else if (process.platform === 'win32') { + if (this._tray == null) { + this._tray = new Tray(path.join(__dirname, 'assets/icons/icon.ico')) + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show Zettlr', + click: () => { + // Add show Zettlr window event to Windows + this.showMainWindow() + }, + type: 'normal' + }, + { label: '', type: 'separator' }, + { + label: 'Quit', + click: () => { + // Add quit event to tray + // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. + app.quit() + }, + type: 'normal' + } + ]) + this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') + this._tray.setContextMenu(contextMenu) + } } else { if (this._tray == null) { this._tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) From 80cc57016514163d8f4035c195ada46a2872dc51 Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <> Date: Mon, 10 May 2021 22:50:42 +0930 Subject: [PATCH 12/16] - part 5: fix issue according to @cskeogh comments --- .../icons/png}/22x22_white.png | Bin .../service-providers/appearance-provider.ts | 6 +++--- source/main/assets/icons/icon.ico | Bin 67646 -> 0 bytes source/main/modules/window-manager/index.ts | 2 +- webpack.main.config.js | 4 +++- 5 files changed, 7 insertions(+), 5 deletions(-) rename {source/main/assets/icons => resources/icons/png}/22x22_white.png (100%) delete mode 100644 source/main/assets/icons/icon.ico diff --git a/source/main/assets/icons/22x22_white.png b/resources/icons/png/22x22_white.png similarity index 100% rename from source/main/assets/icons/22x22_white.png rename to resources/icons/png/22x22_white.png diff --git a/source/app/service-providers/appearance-provider.ts b/source/app/service-providers/appearance-provider.ts index 526e4702f3..a95c88bb37 100644 --- a/source/app/service-providers/appearance-provider.ts +++ b/source/app/service-providers/appearance-provider.ts @@ -121,9 +121,9 @@ export default class AppearanceProvider extends EventEmitter { // Calculate the contrast before returning const dark = '33333333' const light = 'eeeeeeee' - const r = parseInt(accentColor.substring(0, 2), 16) // hexToR - const g = parseInt(accentColor.substring(2, 4), 16) // hexToG - const b = parseInt(accentColor.substring(4, 6), 16) // hexToB + const r = parseInt(accentColor.substring(0, 2), 16); // hexToR + const g = parseInt(accentColor.substring(2, 4), 16); // hexToG + const b = parseInt(accentColor.substring(4, 6), 16); // hexToB const ratio = (r * 0.299) + (g * 0.587) + (b * 0.114) const threshold = 186 // NOTE: We can adapt this later on return { diff --git a/source/main/assets/icons/icon.ico b/source/main/assets/icons/icon.ico deleted file mode 100644 index 8dd6e1d7525467ac123dfb0cd397e73139bd436e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67646 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 diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index cc1095a52c..b1089625fa 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -239,7 +239,7 @@ export default class WindowManager { if (leaveAppRunning) { if (process.platform === 'darwin') { if (this._tray == null) { - this._tray = new Tray(path.join(__dirname, './assets/icons/22x22_white.png')) + this._tray = new Tray(path.join(__dirname, './assets/icons/png/22x22_white.png')) const contextMenu = Menu.buildFromTemplate([ { diff --git a/webpack.main.config.js b/webpack.main.config.js index 3d7d53102b..8a4947baf1 100644 --- a/webpack.main.config.js +++ b/webpack.main.config.js @@ -17,7 +17,9 @@ module.exports = { { from: 'source/app/service-providers/assets/defaults', to: 'assets/defaults' }, { from: 'source/main/modules/export/assets/export.tpl.htm', to: 'assets' }, { from: 'source/main/modules/export/assets/template.revealjs.htm', to: 'assets' }, - { from: 'source/main/modules/export/assets/revealjs-styles', to: 'assets/revealjs-styles' } + { from: 'source/main/modules/export/assets/revealjs-styles', to: 'assets/revealjs-styles' }, + { from: 'source/main/modules/window-manager/assets/icons', to: 'assets/icons' }, + { from: 'resources/icons/png', to: 'assets/icons/png' } ] }) ], From 80ee145402b5090b6f004e926f80ca0f6051860b Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <> Date: Tue, 11 May 2021 10:28:18 +0930 Subject: [PATCH 13/16] - part 6: fix issue according to @cskeogh comments --- source/main/modules/window-manager/index.ts | 158 ++++++++++---------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index b1089625fa..7a1bdd3ecb 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -226,6 +226,86 @@ export default class WindowManager { this._persistWindowPositions() } + private _addTray(){ + if (process.platform === 'darwin') { + if (this._tray == null) { + this._tray = new Tray(path.join(__dirname, './assets/icons/png/22x22_white.png')) + + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show Zettlr', + click: () => { + this.showAnyWindow() + }, + type: 'normal' + }, + { label: '', type: 'separator' }, + { + label: 'Quit', + click: () => { + app.quit() + }, + type: 'normal' + } + ]) + this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') + this._tray.setContextMenu(contextMenu) + } + } else if (process.platform === 'win32') { + if (this._tray == null) { + this._tray = new Tray(path.join(__dirname, 'assets/icons/icon.ico')) + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show Zettlr', + click: () => { + // Add show Zettlr window event to Windows + this.showMainWindow() + }, + type: 'normal' + }, + { label: '', type: 'separator' }, + { + label: 'Quit', + click: () => { + // Add quit event to tray + // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. + app.quit() + }, + type: 'normal' + } + ]) + this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') + this._tray.setContextMenu(contextMenu) + } + } else { + if (this._tray == null) { + this._tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) + const contextMenu = Menu.buildFromTemplate([ + { + label: 'Show Zettlr', + click: () => { + // Add show Zettlr window event to Windows + this.showMainWindow() + }, + type: 'normal' + }, + { label: '', type: 'separator' }, + { + label: 'Quit', + click: () => { + // Add quit event to tray + // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. + app.quit() + }, + type: 'normal' + } + ]) + this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') + this._tray.setContextMenu(contextMenu) + } + } + } + /** * Listens to events on the main window */ @@ -237,83 +317,7 @@ export default class WindowManager { this._mainWindow.on('show', () => { const leaveAppRunning = Boolean(global.config.get('system.leaveAppRunning')) if (leaveAppRunning) { - if (process.platform === 'darwin') { - if (this._tray == null) { - this._tray = new Tray(path.join(__dirname, './assets/icons/png/22x22_white.png')) - - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Show Zettlr', - click: () => { - this.showAnyWindow() - }, - type: 'normal' - }, - { label: '', type: 'separator' }, - { - label: 'Quit', - click: () => { - app.quit() - }, - type: 'normal' - } - ]) - this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') - this._tray.setContextMenu(contextMenu) - } - } else if (process.platform === 'win32') { - if (this._tray == null) { - this._tray = new Tray(path.join(__dirname, 'assets/icons/icon.ico')) - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Show Zettlr', - click: () => { - // Add show Zettlr window event to Windows - this.showMainWindow() - }, - type: 'normal' - }, - { label: '', type: 'separator' }, - { - label: 'Quit', - click: () => { - // Add quit event to tray - // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. - app.quit() - }, - type: 'normal' - } - ]) - this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') - this._tray.setContextMenu(contextMenu) - } - } else { - if (this._tray == null) { - this._tray = new Tray(path.join(__dirname, 'assets/icons/128x128.png')) - const contextMenu = Menu.buildFromTemplate([ - { - label: 'Show Zettlr', - click: () => { - // Add show Zettlr window event to Windows - this.showMainWindow() - }, - type: 'normal' - }, - { label: '', type: 'separator' }, - { - label: 'Quit', - click: () => { - // Add quit event to tray - // On Windows, left or right click the tray icon ➔ Quit will quit Zettlr. Same function as File ➔ Quit. - app.quit() - }, - type: 'normal' - } - ]) - this._tray.setToolTip('This is the Zettlr tray. \n Select Show Zettlr to show the Zettlr app. \n Select Quit to quit the Zettlr app.') - this._tray.setContextMenu(contextMenu) - } - } + this._addTray() } }) From 676cd0dc938c13b8bb612263c2a6849ffe753b68 Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <48038877+WeiqinYang1994@users.noreply.github.com> Date: Tue, 11 May 2021 13:08:56 +0930 Subject: [PATCH 14/16] - part 7 : fix issue according to @cskeogh comments --- source/main/modules/window-manager/index.ts | 10 ---------- webpack.main.config.js | 1 - 2 files changed, 11 deletions(-) diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index 01693fd412..27c44514d8 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -125,16 +125,6 @@ export default class WindowManager { callingWindow.minimize() break case 'win-close': - if (process.platform !== 'darwin') { - const leaveAppRunning = Boolean(global.config.get('system.leaveAppRunning')) - if (leaveAppRunning) { - this._mainWindow?.hide() - } else { - this._mainWindow?.close() - } - } else { - this._mainWindow?.close() - } break // Convenience APIs for the renderers to execute these commands case 'cut': diff --git a/webpack.main.config.js b/webpack.main.config.js index 8a4947baf1..8d3932717c 100644 --- a/webpack.main.config.js +++ b/webpack.main.config.js @@ -18,7 +18,6 @@ module.exports = { { from: 'source/main/modules/export/assets/export.tpl.htm', to: 'assets' }, { from: 'source/main/modules/export/assets/template.revealjs.htm', to: 'assets' }, { from: 'source/main/modules/export/assets/revealjs-styles', to: 'assets/revealjs-styles' }, - { from: 'source/main/modules/window-manager/assets/icons', to: 'assets/icons' }, { from: 'resources/icons/png', to: 'assets/icons/png' } ] }) From be62f16dd9cd83516ad1dee71ad9919b559b7f5c Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <48038877+WeiqinYang1994@users.noreply.github.com> Date: Tue, 11 May 2021 13:27:08 +0930 Subject: [PATCH 15/16] - part 8 : fix issue according to @cskeogh comments --- source/main/modules/window-manager/index.ts | 1 + webpack.main.config.js | 1 + 2 files changed, 2 insertions(+) diff --git a/source/main/modules/window-manager/index.ts b/source/main/modules/window-manager/index.ts index 27c44514d8..23292ca8b4 100644 --- a/source/main/modules/window-manager/index.ts +++ b/source/main/modules/window-manager/index.ts @@ -125,6 +125,7 @@ export default class WindowManager { callingWindow.minimize() break case 'win-close': + callingWindow.close() break // Convenience APIs for the renderers to execute these commands case 'cut': diff --git a/webpack.main.config.js b/webpack.main.config.js index 8d3932717c..981322768e 100644 --- a/webpack.main.config.js +++ b/webpack.main.config.js @@ -18,6 +18,7 @@ module.exports = { { from: 'source/main/modules/export/assets/export.tpl.htm', to: 'assets' }, { from: 'source/main/modules/export/assets/template.revealjs.htm', to: 'assets' }, { from: 'source/main/modules/export/assets/revealjs-styles', to: 'assets/revealjs-styles' }, + { from: 'resources/icons/icon.ico', to: 'assets/icons' }, { from: 'resources/icons/png', to: 'assets/icons/png' } ] }) From 9f0f9a1e8a1b1e85ae82e4315659510f5fb4d105 Mon Sep 17 00:00:00 2001 From: WeiqinYang1994 <48038877+WeiqinYang1994@users.noreply.github.com> Date: Tue, 11 May 2021 15:48:53 +0930 Subject: [PATCH 16/16] - part 9 : fix issue according to @cskeogh comments --- resources/icons/png/22x22_white.png | Bin 475 -> 794 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/icons/png/22x22_white.png b/resources/icons/png/22x22_white.png index 02338cd19447e43b861dc63de7bebde8fbfdacef..b83151e0da4bae08d549fcbdf16555211d98b5ea 100644 GIT binary patch delta 760 zcmVB%WisVG(Z-&um&c=Y8S`D@zLTIq|qb7bJe< zy6o~B=aRz$&x{z^^gMBdSS)q1+{LVHsKnF6QAO1#U&y(vaNgpqR_m;NPyWJiL0idi zoz@5vSV9shh<}h#M+H?_h|#W*Vj@lFaS#8n<4=)GCRYWF91EyHh2;3b|KN9T&EnLg zn-q=%ffw8U7zKj6K&xTf-^aGyIsyF8z?IhV*P6iWC+Urj7Ci#`w}Ff6jwbH`mpj1F zlP(#OBl&3w#Uk*2M&FbN25y1Sn%lSbIZhvdEcI&n1}r!@1jb5~z3%bu-tNBrThs2} z4-TDje@hrC(EtDd24YJ`L;wH)0002_L%WeJ8Gi?KNlirue zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{008nyL_t(I%k7o1P69y?hW{~F zfSTAqsEmYC?I=vJgd4i+%9Vjle#2DVdQbT(dR$5|73!#*cW)qi-9AVwc_*XkS zyMNzK{>fyee>quM61bC;mK@2=tp8IY+4FE+QoAI-2(9=^(yg~OkkoSPPf2|Gun9&-PvBzIAW*RjB> zLYzjMci^L7#}ar0UV$-i77FeFGj{7SXhEbM+$7ydx^~tzB;C8aUuKrXv?zBK&qJEG q3wkc;(uEH(tIb@+&%o*5`IeK@{oCO|{#S9GG z!XV7ZFl&wkP;gOzPlzj!{!aw>@#i-Ys{a4^_m>!D|Nj4jD+98A{zWkyDEs^GAGiXG zHE%_Lt~4tN@(X5QG)&HwfAD|0=f);g4(5e3Sj1M&;ZnMAl%I1~c+kJElb(u)y#DK^ z?w+sJ)Tg~f@S)YLsqOPCyf!z8E{uE?xANJ_r=e1B*d6B{I+3>E zV$RlsJ1)OHns7&+$NhoLGS5Smt1{Tmy__Rx