Skip to content
This repository has been archived by the owner on Jan 19, 2023. It is now read-only.

Update tray menu #2411

Merged
merged 1 commit into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions web/electron/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ export const iconPath = path.join(
app.getAppPath(),
'dist/octant/assets/icons/icon.png'
);

export const greyIconPath = path.join(
app.getAppPath(),
'dist/octant/assets/icons/icon-grey.png'
);
124 changes: 93 additions & 31 deletions web/electron/tray-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,109 @@
*
*/

import { app, BrowserWindow, Menu, Tray, nativeImage, shell } from 'electron';
import { errLogPath, iconPath } from './paths';
import { app, BrowserWindow, Menu, Tray, nativeImage, shell, MenuItem } from 'electron';
import { errLogPath, iconPath, greyIconPath } from './paths';
import * as WebSocket from 'ws';
import * as open from 'open';

export class TrayMenu {
public readonly tray: Tray;
public wsConn : WebSocket;
private menuState : {
contexts: string[],
namespaces: string[],
currentContext: (string | null),
buildInfo: {version: string, commit: string, time: string}
}

constructor(public window: BrowserWindow) {
constructor(public window: BrowserWindow, public websocketUrl: string) {
this.tray = new Tray(this.createNativeImage());
this.tray.setContextMenu(this.createMenu(window));
}
this.wsConn = new WebSocket(this.websocketUrl);
this.menuState = { contexts: [], namespaces: [], currentContext: null,
buildInfo: {version: '', commit: '', time: ''}
}

this.setMenu();
this.startOctantEventListener();
}

createNativeImage(): Electron.NativeImage {
const image = nativeImage.createFromPath(iconPath);
const image = nativeImage.createFromPath(greyIconPath);
image.setTemplateImage(true);
return image.resize({ width: 16, height: 16 });
}

createMenu(win: BrowserWindow): Menu {
const menu = Menu.buildFromTemplate([
{
label: 'Open Octant',
type: 'normal',
click: () => {
win.show();
},
},
{
label: 'View Logs',
type: 'normal',
click: () => {
shell.showItemInFolder(errLogPath);
},
},
{
label: 'Quit',
type: 'normal',
click: () => {
app.quit();
},
},
]);
return menu;
startOctantEventListener() {
this.wsConn.on('message', (msg) => {
const config = JSON.parse(`${msg}`);

switch (config.type) {
case 'event.octant.dev/kubeConfig':
this.menuState.contexts = config.data.contexts.map(c => c.name);
this.menuState.currentContext = config.data.currentContext;
this.setMenu();
break;
case 'event.octant.dev/buildInfo':
this.menuState.buildInfo = config.data;
this.setAboutOptions();
this.setMenu();
break;
}
});
}

setMenu() {
let menu = new Menu();
menu.append(new MenuItem({label: 'Open Octant', type: 'normal', click: () => this.window.show()}));
menu.append(new MenuItem({label: 'View Logs', type: 'normal', click: () => shell.showItemInFolder(errLogPath)}));

menu.append(this.contextSubMenu());
menu.append(this.aboutOctantSubMenu());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just have About Octant menu item here that opens the same modal as when invoked from header. I feel it's important to have consistent interface, plus the version and build strings look wonky showing up in sub-menus like that.

Copy link
Contributor Author

@xtreme-vikram-yadav xtreme-vikram-yadav May 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you are asking makes sense. Opening the same modal in the app window may not work well when there is only tray without any open window. I briefly looked into showing a native about panel to show this information but decided to use menu item as not all the provided options are supported across different OSes. But thanks to your comment, I tried it with a work around which shows the info properly. I have updated the implementation, it is not how about panels options are meant to be used but it works for now.
octant-about-native

menu.append(this.openIssueMenuItem());
menu.append(this.octantDocsMenuItem());

menu.append(new MenuItem({label: 'Quit', type: 'normal', click: () => app.quit()}))
this.tray.setContextMenu(menu);
}

contextSubMenu() : MenuItem {
let contextMenu = new Menu();
const cItems = this.menuState.contexts.forEach((context) => {
contextMenu.append(new MenuItem({
label: context,
type: 'checkbox',
checked: context === this.menuState.currentContext,
click: () => { this.wsConn.send(JSON.stringify({
type: 'action.octant.dev/setContext',
payload: { requestedContext: context }
})) }
}));
});


return new MenuItem({label: 'Contexts', type: 'submenu', submenu: contextMenu});
}

aboutOctantSubMenu() : MenuItem {
return new MenuItem({label: 'About Octant', role: 'about'});
}

openIssueMenuItem() : MenuItem {
const newIssueLink = 'https://github.com/vmware-tanzu/octant/issues/new/choose';
return new MenuItem({label: 'Open an Issue/Provide Feedback', type: 'normal', click: () => open(newIssueLink)});
}

octantDocsMenuItem() : MenuItem {
const docsLink = 'https://octant.dev/';
return new MenuItem({label: 'Octant Documentation', type: 'normal', click: () => open(docsLink)});
}

setAboutOptions() : void {
app.setAboutPanelOptions({
applicationName: 'Octant',
applicationVersion: `Version: ${this.menuState.buildInfo.version}\nCommit: ${this.menuState.buildInfo.commit}\nBuilt: ${this.menuState.buildInfo.time}`,
website: 'https://octant.dev',
iconPath: iconPath
})
}
}
5 changes: 3 additions & 2 deletions web/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,13 @@ try {
w.webContents.send('port-message', port);
});

tray = new TrayMenu(win);
const websocketUrl = `ws://localhost:${port}/api/v1/stream`
tray = new TrayMenu(win, websocketUrl);

// In event of a black background issue: https://github.com/electron/electron/issues/15947
// setTimeout(createWindow, 400);
session.defaultSession.webRequest.onBeforeSendHeaders(
{ urls: ['ws://localhost:' + port + '/api/v1/stream'] },
{ urls: [websocketUrl] },
(details, callback) => {
details.requestHeaders['Origin'] = null;
callback({ cancel: false, requestHeaders: details.requestHeaders });
Expand Down
76 changes: 63 additions & 13 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"lodash-es": "^4.17.15",
"monaco-editor": "^0.21.2",
"ngx-highlightjs": "^4.1.2",
"open": "^8.0.7",
"overlayscrollbars-ngx": "^0.2.2",
"rxjs": "^6.6.3",
"serialize-javascript": "^5.0.1",
Expand Down
Binary file added web/src/assets/icons/icon-grey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.