blob: afac220a8f6b774690b93e1651b42da0dbea611f [file] [log] [blame]
/**
*
* Copyright (c) 2020 Silicon Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Menu for ZAP UI
*
* @module JS API: Menu for ZAP UI
*/
const { dialog, Menu, shell } = require('electron')
const uiJs = require('./ui-util')
const about = require('./about')
const commonUrl = require('../../src-shared/common-url.js')
const browserApi = require('./browser-api.js')
const rendApi = require('../../src-shared/rend-api.js')
const newConfiguration = 'New Configuration'
let menuIsShown = true
const template = (httpPort) => [
{
role: 'fileMenu',
submenu: [
{
label: newConfiguration + '...',
accelerator: 'CmdOrCtrl+N',
httpPort: httpPort,
click(menuItem, browserWindow, event) {
uiJs.openNewConfiguration(menuItem.httpPort)
}
},
{
label: 'Open File...',
accelerator: 'CmdOrCtrl+O',
httpPort: httpPort,
click(menuItem, browserWindow, event) {
doOpen(browserWindow, menuItem.httpPort)
}
},
{
label: 'Save',
accelerator: 'CmdOrCtrl+S',
click(menuItem, browserWindow, event) {
doSave(browserWindow)
}
},
{
label: 'Save As...',
click(menuItem, browserWindow, event) {
doSaveAs(browserWindow)
}
},
{
type: 'separator'
},
{
role: 'close'
},
{
type: 'separator'
},
{
role: 'quit'
}
]
},
{
role: 'editMenu'
},
{
role: 'viewMenu',
submenu: [
{
label: 'Dark theme',
click(menuItem, browserWindow, event) {
browserApi.execRendererApi(
browserWindow,
rendApi.id.setDarkTheme,
true
)
}
},
{
label: 'Light theme',
click(menuItem, browserWindow, event) {
browserApi.execRendererApi(
browserWindow,
rendApi.id.setDarkTheme,
false
)
}
},
{ type: 'separator' },
{
label: 'Navigate back ...',
click(menuItem, browserWindow, event) {
browserWindow.webContents.goBack()
}
},
{
label: 'Navigate forward ...',
click(menuItem, browserWindow, event) {
browserWindow.webContents.goForward()
}
},
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
},
{
role: 'windowMenu'
},
{
label: 'Help',
submenu: [
{
label: 'Documentation',
click(menuItem, browserWindow, event) {
shell.openExternal(commonUrl.documentationUrl)
}
},
{
label: 'User and session information',
click(menuItem, browserWindow, event) {
getUserSessionInfoMessage(browserWindow)
.then((msg) => {
dialog.showMessageBox(browserWindow, {
title: 'User and session information',
message: msg,
buttons: ['Dismiss']
})
})
.catch((err) => uiJs.showErrorMessage('Session info', err))
}
},
{
label: 'Renderer API information',
click(menuItem, browserWindow, event) {
browserApi.getRendererApiInformation(browserWindow).then((msg) => {
dialog.showMessageBox(browserWindow, {
title: 'Renderer API information',
message: msg,
buttons: ['Dismiss']
})
})
}
},
{
type: 'separator'
},
{
label: 'Start progress',
click(menuItem, browserWindow) {
browserApi.execRendererApi(
browserWindow,
rendApi.id.progressStart,
'Test progress indication.'
)
}
},
{
label: 'End progress',
click(menuItem, browserWindow) {
browserApi.execRendererApi(browserWindow, rendApi.id.progressEnd)
}
},
{
label: 'Show debug navigation bar',
click(menuItem, browserWindow) {
browserApi.execRendererApi(browserWindow, rendApi.id.debugNavBarOn)
}
},
{
label: 'Hide debug navigation bar',
click(menuItem, browserWindow) {
browserApi.execRendererApi(browserWindow, rendApi.id.debugNavBarOff)
}
},
{
label: 'About',
httpPort: httpPort,
click(menuItem, browserWindow, event) {
about.createOrShowAboutWindow(browserWindow, menuItem.httpPort)
}
}
]
}
]
/**
* Get the user session information details in a string.
*
* @param {*} browserWindow
* @returns string
*/
async function getUserSessionInfoMessage(browserWindow) {
let userKey = await browserApi.getUserKeyFromBrowserWindow(browserWindow)
let sessionUuidMap =
await browserApi.getSessionUuidFromBrowserWindow(browserWindow)
let sessionUuidText = ''
for (const [key, value] of sessionUuidMap) {
sessionUuidText += ` ${key} => ${value}\n`
}
return `
Browser user key: ${userKey}
Browser session UUID:
${sessionUuidText}
`
}
/**
* Perform a file->open operation.
*
* @param {*} menuItem
* @param {*} browserWindow
* @param {*} event
*/
function doOpen(browserWindow, httpPort) {
browserApi
.execRendererApi(
browserWindow,
rendApi.id.getStorageItem,
rendApi.storageKey.fileSave
)
.then((filePath) => {
let opts = {
title: 'Select ZAP or ISC file to load.',
properties: ['openFile', 'multiSelections']
}
if (filePath != null) {
opts.defaultPath = filePath
}
return dialog.showOpenDialog(browserWindow, opts)
})
.then((result) => {
if (!result.canceled) {
fileOpen(result.filePaths, httpPort)
browserApi.execRendererApi(
browserWindow,
rendApi.id.setStorageItem,
rendApi.storageKey.fileSave,
result.filePaths[0]
)
}
})
.catch((err) => uiJs.showErrorMessage('Open file', err))
}
/**
* Perform a save, defering to save as if file is not yet selected.
*
* @param {*} browserWindow
*/
function doSave(browserWindow) {
if (browserWindow.getTitle().includes(newConfiguration)) {
doSaveAs(browserWindow)
} else {
fileSave(browserWindow, null)
}
}
/**
* Perform save as.
*
* @param {*} menuItem
* @param {*} browserWindow
* @param {*} event
*/
function doSaveAs(browserWindow) {
browserApi
.execRendererApi(
browserWindow,
rendApi.id.getStorageItem,
rendApi.storageKey.fileSave
)
.then((filePath) => {
let opts = {
filters: [
{ name: 'ZAP Config', extensions: ['zap'] },
{ name: 'All Files', extensions: ['*'] }
]
}
if (filePath != null) {
opts.defaultPath = filePath
}
return dialog.showSaveDialog(opts)
})
.then((result) => {
if (!result.canceled) {
if (process.platform == 'win32') {
result.filePath = result.filePath.replace(/\\/g, '\\\\')
}
fileSave(browserWindow, result.filePath)
return result.filePath
} else {
return null
}
})
.then((filePath) => {
if (filePath != null) {
browserWindow.setTitle(filePath)
browserApi.execRendererApi(
browserWindow,
rendApi.id.setStorageItem,
rendApi.storageKey.fileSave,
filePath
)
}
})
.catch((err) => uiJs.showErrorMessage('Save file', err))
}
/**
* perform the save.
*
* @param {*} db
* @param {*} browserWindow
* @param {*} filePath
* @returns Promise of saving.
*/
function fileSave(browserWindow, filePath) {
browserApi.execRendererApi(browserWindow, rendApi.id.save, filePath)
}
/**
* Perform the do open action, possibly reading in multiple files.
*
* @param {*} db
* @param {*} filePaths
*/
function fileOpen(filePaths, httpPort) {
filePaths.forEach((filePath) => {
uiJs.openFileConfiguration(filePath, httpPort)
})
}
/**
* Show the menu.
*
* @param {*} httpPort
*/
function showMenu(httpPort) {
const menu = Menu.buildFromTemplate(template(httpPort))
Menu.setApplicationMenu(menu)
}
/**
* Hide the menu.
*
* @param {*} httpPort
*/
function hideMenu(httpPort) {
Menu.setApplicationMenu(null)
}
/**
* Toggling of menu
*
* @param {*} port
*/
function toggleMenu(httpPort) {
menuIsShown = !menuIsShown
if (!menuIsShown) {
hideMenu(httpPort)
} else {
showMenu(httpPort)
}
}
/**
* Initial menu show.
*
* @param {*} httpPort
*/
function initMenu(httpPort) {
menuIsShown = true
showMenu(httpPort)
}
exports.toggleMenu = toggleMenu
exports.initMenu = initMenu
exports.newConfiguration = newConfiguration