Skip to content

Commit

Permalink
refactor: extract tray management into a new class
Browse files Browse the repository at this point in the history
  • Loading branch information
jamaljsr committed Jun 18, 2024
1 parent 4bb7d71 commit 0cdf731
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 149 deletions.
121 changes: 121 additions & 0 deletions electron/trayManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { app, BrowserWindow, Menu, nativeImage, nativeTheme, Tray } from 'electron';
import { join } from 'path';
import { APP_ROOT } from './constants';

const TRAY_ICONS_ROOT = join(APP_ROOT, 'assets', 'icons', 'tray');

export default class TrayManager {
mainWindow: BrowserWindow;
tray: Tray;

/** The current system theme */
get theme(): 'light' | 'dark' {
return nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
}

/** The name of the menu icon file based on the platform and theme */
get menuIconName(): string {
switch (process.platform) {
case 'darwin':
return '16x16Template.png';
case 'win32':
return `16x16icon-${this.theme}.png`;
case 'linux':
return `96x96icon-${this.theme}.png`;
default:
return `96x96icon-${this.theme}.png`;
}
}

constructor(mainWindow: BrowserWindow) {
this.mainWindow = mainWindow;
const theme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
const trayIcon =
process.platform === 'darwin'
? join(TRAY_ICONS_ROOT, '16x16Template.png')
: join(TRAY_ICONS_ROOT, `1024x1024-${theme}.png`);
const nativeImageFromPath = nativeImage.createFromPath(trayIcon);
nativeImageFromPath.setTemplateImage(true);
this.tray = new Tray(nativeImageFromPath);

// initial creation of tray menu
this.updateTrayIcons();

this.tray.on('click', () => {
// show the window when the user clicks on the tray icon
this.handleOnShowClick();
});

nativeTheme.on('updated', () => {
// re-create tray context menu when system theme changes
this.updateTrayIcons();
});
}

/**
* Gets the full path to the menu icon icon based on platform and theme
*/
getIconPath(iconDir: 'quit' | 'minimize' | 'show') {
const imagePath = join(TRAY_ICONS_ROOT, iconDir, this.menuIconName);
const image = nativeImage.createFromPath(imagePath);
image.setTemplateImage(true);
return image;
}

/**
* Updates the tray context menu icons based on the current theme
*/
updateTrayIcons() {
const contextMenu = Menu.buildFromTemplate([
{
label: 'Minimize Window',
click: this.handleOnHideClick,
icon: this.getIconPath('minimize'),
},
{
label: 'Show Window',
click: this.handleOnShowClick,
icon: this.getIconPath('show'),
},
{
type: 'separator',
},
{
label: 'Quit Polar',
click: this.handleQuitClick,
icon: this.getIconPath('quit'),
},
]);

this.tray.setContextMenu(contextMenu);
}

/**
* Hides the main window
*/
handleOnHideClick = () => {
app.dock?.hide();
this.mainWindow.setSkipTaskbar(true);
this.mainWindow.hide();
};

/**
* Shows the main window
*/
handleOnShowClick = () => {
app.dock?.show();
this.mainWindow.setSkipTaskbar(false);
this.mainWindow.show();
};

/**
* Closes all windows and quits the app
*/
handleQuitClick = () => {
app.quit();
};

destroy() {
this.tray.destroy();
}
}
156 changes: 7 additions & 149 deletions electron/windowManager.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
import {
app,
BrowserWindow,
ipcMain,
Menu,
nativeImage,
nativeTheme,
Tray,
} from 'electron';
import { app, BrowserWindow, ipcMain, Menu } from 'electron';
import { warn } from 'electron-log';
import windowState from 'electron-window-state';
import { join } from 'path';
Expand All @@ -15,10 +7,11 @@ import { appMenuTemplate } from './appMenu';
import { APP_ROOT, BASE_URL, IS_DEV } from './constants';
import { clearLndProxyCache, initLndProxy } from './lnd/lndProxyServer';
import { initTapdProxy } from './tapd/tapdProxyServer';
import TrayManager from './trayManager';

class WindowManager {
mainWindow: BrowserWindow | null = null;
tray: Tray | null = null;
trayManager: TrayManager | null = null;

start() {
app.on('ready', async () => {
Expand Down Expand Up @@ -56,8 +49,8 @@ class WindowManager {
});

// create App system tray icon with context menus
if (!this.tray) {
this.createAppTray();
if (!this.trayManager) {
this.trayManager = new TrayManager(this.mainWindow);
}

this.mainWindow.setMenuBarVisibility(false);
Expand Down Expand Up @@ -99,12 +92,12 @@ class WindowManager {

onMainClosed() {
this.mainWindow = null;
this.tray?.destroy();
this.trayManager?.destroy();
app.quit();
}

onAllClosed() {
this.tray?.destroy();
this.trayManager?.destroy();
app.quit();
}

Expand All @@ -123,141 +116,6 @@ class WindowManager {
this.createMainWindow();
}
}

TRAY_ICONS_ROOT: string[] = [APP_ROOT, 'assets', 'icons', 'tray'];

/**
* select `light` or `dark` icon based on host OS
* system theme
* @param path
* @returns
*/
iconSelector = (path: 'quit' | 'minimize' | 'show') => {
console.log('nativeTheme.shouldUseDarkColors', nativeTheme.shouldUseDarkColors);
if (nativeTheme.shouldUseDarkColors) {
let iconName;
switch (process.platform) {
case 'darwin':
iconName = '16x16Template.png';
break;
case 'win32':
iconName = '16x16icon-dark.png';
break;
case 'linux':
iconName = '96x96icon-dark.png';
break;
default:
iconName = '96x96icon-dark.png';
break;
}
const imagePath = join(...this.TRAY_ICONS_ROOT, path, iconName);
const nativeImageFromPath = nativeImage.createFromPath(imagePath);
nativeImageFromPath.setTemplateImage(true);
return nativeImageFromPath;
}

if (!nativeTheme.shouldUseDarkColors) {
let iconName;
switch (process.platform) {
case 'darwin':
iconName = '16x16Template.png';
break;
case 'win32':
iconName = '16x16icon-light.png';
break;
case 'linux':
iconName = '96x96icon-light.png';
break;
default:
iconName = '96x96icon-light.png';
break;
}
const imagePath = join(...this.TRAY_ICONS_ROOT, path, iconName);
const nativeImageFromPath = nativeImage.createFromPath(imagePath);
nativeImageFromPath.setTemplateImage(true);
return nativeImageFromPath;
}
};

/**
* `hides` polar windows
*/
handleOnHideClick = () => {
app.dock?.hide();
this.mainWindow?.setSkipTaskbar(true);
this.mainWindow?.hide();
};

/**
* `shows` polar window
*/
handleOnShowClick = () => {
app.dock?.show();
this.mainWindow?.setSkipTaskbar(false);
this.mainWindow?.show();
};

/**
* closes all windows and quits the app
*/
handleQuitClick = () => {
app.quit();
};

updateTrayIcons(tray: Tray | null) {
const contextMenu = Menu.buildFromTemplate([
{
label: 'Minimize Window',
click: this.handleOnHideClick,
icon: this.iconSelector('minimize'),
},
{
label: 'Show Window',
click: this.handleOnShowClick,
icon: this.iconSelector('show'),
},
{
type: 'separator',
},
{
label: 'Quit Polar',
click: this.handleQuitClick,
icon: this.iconSelector('quit'),
},
]);

tray?.setContextMenu(contextMenu);
}

/**
* Creates App tray icon with a menu of options
* to `Hide/Show` the app window
* and also `quite` the running app instance
* @returns void
*/
createAppTray() {
const theme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
const trayIcon =
process.platform === 'darwin'
? join(...this.TRAY_ICONS_ROOT, '16x16Template.png')
: join(...this.TRAY_ICONS_ROOT, `1024x1024-${theme}.png`);
const nativeImageFromPath = nativeImage.createFromPath(trayIcon as string);
nativeImageFromPath.setTemplateImage(true);
this.tray = new Tray(nativeImageFromPath);

// initial creation of tray menu
this.updateTrayIcons(this.tray);

this.tray.on('click', () => {
// show the window when the user clicks on the tray icon
this.handleOnShowClick();
});

nativeTheme.on('updated', () => {
// re-create tray context menu when system theme changes
this.updateTrayIcons(this?.tray);
});
}
}

export default WindowManager;

0 comments on commit 0cdf731

Please sign in to comment.