Newer
Older
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
Luke Schoen
committed
// This file is part of Parity.
//
// SPDX-License-Identifier: BSD-3-Clause
Luke Schoen
committed
import electron from 'electron';
import settings from 'electron-settings';
Luke Schoen
committed
import { IS_PROD } from '../../constants';
import i18n from '../i18n';
// https://www.npmjs.com/package/auto-launch
import AutoLaunch from 'auto-launch';
import Pino from '../../utils/pino';
// Only use 'auto-launch' library on Linux since Electron API's
// `setLoginItemSettings` is only supported on macOS and Windows
// https://electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows
const fetherAutoLauncher = new AutoLaunch({
name: 'Fether',
path: '/usr/local/bin/fether'
});
Luke Schoen
committed
const { shell } = electron;
Luke Schoen
committed
// Preferences menu
const getPreferences = fetherApp => {
return {
label: i18n.t('menu.file.preferences.languages.submenu_name'),
submenu: [
{
label: i18n.t('menu.file.preferences.languages.english'),
type: 'radio',
checked: settings.get('fether-language') === 'en',
click () {
// Backend menu change language
i18n.changeLanguage('en');
settings.set('fether-language', 'en');
fetherApp.setupMenu(fetherApp);
// Frontend change language
fetherApp.win.webContents.emit('set-language', 'en');
}
},
{
label: i18n.t('menu.file.preferences.languages.german'),
type: 'radio',
checked: settings.get('fether-language') === 'de',
click () {
// Backend menu change language
i18n.changeLanguage('de');
settings.set('fether-language', 'de');
fetherApp.setupMenu(fetherApp);
// Frontend change language
fetherApp.win.webContents.emit('set-language', 'de');
}
}
]
};
};
Luke Schoen
committed
// Create the Application's main menu
// https://github.com/electron/electron/blob/master/docs/api/menu.md#examples
const getMenubarMenuTemplate = fetherApp => {
Luke Schoen
committed
// File menu
const fileTab =
process.platform === 'darwin'
? {
label: i18n.t('menu.file.submenu_name'),
Luke Schoen
committed
submenu: [
{ role: 'about', label: i18n.t('menu.file.about') },
Luke Schoen
committed
{ type: 'separator' },
{
label: i18n.t('menu.file.preferences.submenu_name'),
submenu: [getPreferences(fetherApp)]
},
Luke Schoen
committed
{ type: 'separator' },
{
role: 'services',
label: i18n.t('menu.file.services'),
submenu: []
},
Luke Schoen
committed
{ type: 'separator' },
{ role: 'hide', label: i18n.t('menu.file.hide') },
{ role: 'hideothers', label: i18n.t('menu.file.hide_others') },
{ role: 'unhide', label: i18n.t('menu.file.unhide') },
{ type: 'separator' },
{ role: 'quit', label: i18n.t('menu.file.quit') }
Luke Schoen
committed
]
}
: {
label: i18n.t('menu.file.submenu_name'),
submenu: [{ role: 'quit', label: i18n.t('menu.file.quit') }]
Luke Schoen
committed
};
/* eslint-disable no-sparse-arrays */
const editTabMacOS = {
label: i18n.t('menu.edit.submenu_name'),
{ role: 'undo', label: i18n.t('menu.edit.undo') },
{ role: 'redo', label: i18n.t('menu.edit.redo') },
{ role: 'cut', label: i18n.t('menu.edit.cut') },
{ role: 'copy', label: i18n.t('menu.edit.copy') },
{ role: 'paste', label: i18n.t('menu.edit.paste') },
{ role: 'delete', label: i18n.t('menu.edit.delete') },
{ role: 'selectall', label: i18n.t('menu.edit.select_all') }
]
};
/* eslint-enable no-sparse-arrays */
Luke Schoen
committed
/**
* On win32 we need to use `webContents` to make some of the menu items
* functional (whereas it is not required on Linux and macOS).
* i.e on macOS/Linux `{ role: 'undo' }` suffices to add the Undo menu item,
* whereas on win32 we must use `webContents` as follows:
* `{ label: 'Undo', click: () => fetherApp.win.webContents.undo() }`.
* Since all items in the 'Edit' menu work with `webContents` we will use
* it to prevent code duplication
*/
Luke Schoen
committed
const editTab = {
label: i18n.t('menu.edit.submenu_name'),
Luke Schoen
committed
submenu: [
{
label: i18n.t('menu.edit.undo'),
click: () => fetherApp.win.webContents.undo()
},
{
label: i18n.t('menu.edit.redo'),
click: () => fetherApp.win.webContents.redo()
},
Luke Schoen
committed
{ type: 'separator' },
{
label: i18n.t('menu.edit.cut'),
click: () => fetherApp.win.webContents.cut()
},
{
label: i18n.t('menu.edit.copy'),
click: () => fetherApp.win.webContents.copy()
},
{
label: i18n.t('menu.edit.paste'),
click: () => fetherApp.win.webContents.paste()
},
Luke Schoen
committed
{ type: 'separator' },
{
label: i18n.t('menu.edit.delete'),
click: () => fetherApp.win.webContents.delete()
},
{
label: i18n.t('menu.edit.select_all'),
Luke Schoen
committed
click: () => fetherApp.win.webContents.selectAll()
}
]
};
Luke Schoen
committed
const viewTab = {
label: i18n.t('menu.view.submenu_name'),
submenu: [
{ role: 'reload', label: i18n.t('menu.view.reload') },
{
role: 'toggledevtools',
label: i18n.t('menu.view.toggle_developer_tools')
}
]
Luke Schoen
committed
};
Luke Schoen
committed
/**
* On win32 we need to use `webContents` to make some of the menu items
* functional (whereas it is not required on Linux and macOS).
* Note that some menu items are not available in `webContents`
* (i.e. resetzoom, zoomin, zoomout, togglefullscreen), however they
* add no benefit to users anyway
*/
Luke Schoen
committed
const viewTabWindowsOS = {
label: i18n.t('menu.view.submenu_name'),
Luke Schoen
committed
submenu: [
{
label: i18n.t('menu.view.reload'),
click: () => fetherApp.win.webContents.reload()
},
{
label: i18n.t('menu.view.toggle_developer_tools'),
Luke Schoen
committed
click: () => fetherApp.win.webContents.toggleDevTools()
}
]
};
Luke Schoen
committed
const windowTab = {
Luke Schoen
committed
role: 'window',
label: i18n.t('menu.window.submenu_name'),
submenu: [
{ role: 'minimize', label: i18n.t('menu.window.minimize') },
{ role: 'close', label: i18n.t('menu.window.close') }
]
Luke Schoen
committed
};
const helpTab = {
Luke Schoen
committed
role: 'help',
label: i18n.t('menu.help.submenu_name'),
Luke Schoen
committed
submenu: [
{
label: i18n.t('menu.help.learn_more'),
Luke Schoen
committed
click () {
shell.openExternal('https://parity.io');
}
}
]
Luke Schoen
committed
};
Luke Schoen
committed
Luke Schoen
committed
fileTab,
process.platform === 'darwin' ? editTabMacOS : editTab,
Luke Schoen
committed
process.platform === 'win32' ? viewTabWindowsOS : viewTab,
windowTab,
helpTab
];
Luke Schoen
committed
if (process.platform === 'darwin') {
// Edit menu
template[1].submenu.push(
Luke Schoen
committed
{ type: 'separator' },
Luke Schoen
committed
{
label: i18n.t('menu.edit.speech.submenu_name'),
submenu: [
{
role: 'startspeaking',
label: i18n.t('menu.edit.speech.start_speaking')
},
{
role: 'stopspeaking',
label: i18n.t('menu.edit.speech.stop_speaking')
}
]
Luke Schoen
committed
}
);
}
Luke Schoen
committed
Luke Schoen
committed
if (process.platform === 'darwin') {
// Window menu
template[3].submenu = [
{ role: 'close', label: i18n.t('menu.window.close') },
{ role: 'minimize', label: i18n.t('menu.window.minimize') },
{ role: 'zoom', label: i18n.t('menu.window.zoom') },
Luke Schoen
committed
{ type: 'separator' },
{ role: 'front', label: i18n.t('menu.window.bring_all_to_front') }
Luke Schoen
committed
];
}
Luke Schoen
committed
Luke Schoen
committed
if (fetherApp.options.withTaskbar) {
// Remove Window menu tab when running as taskbar app
template.splice(3, 1);
Luke Schoen
committed
return template;
};
const execName = path.basename(process.execPath);
pino.info('Executable Name: ', execName);
pino.info('Executable Path: ', process.execPath);
const settingsLaunchOnStartup = shouldLaunchOnStartup => {
if (process.platform === 'win32') {
return {
openAtLogin: shouldLaunchOnStartup,
path: process.execPath, // Windows only
args: [
// Windows only
'--processStart',
`${execName}`,
'--process-start-args',
'--hidden'
]
// TODO - configure additional properties
// References:
// - https://electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows
// - https://github.com/electron-archive/grunt-electron-installer/issues/115
};
} else {
return {
openAtLogin: shouldLaunchOnStartup
};
}
};
const getIsLaunchOnStartup = fetherApp => {
return fetherApp.app.getLoginItemSettings().openAtLogin;
let isLaunchOnStartup;
isLaunchOnStartup = settings.get('launch-on-startup');
isLaunchOnStartup = getIsLaunchOnStartup(fetherApp);
}
pino.info('Set Launch on Startup checkbox to: ', isLaunchOnStartup);
return isLaunchOnStartup;
const getContextTrayMenuTemplate = fetherApp => {
if (fetherApp.options.withTaskbar) {
const template = [
{
label: i18n.t('menu.show_hide_fether'),
click () {
if (fetherApp.win.isVisible() && fetherApp.win.isFocused()) {
fetherApp.win.hide();
} else {
fetherApp.win.show();
fetherApp.win.focus();
}
}
}
];
label: i18n.t('menu.view.reload'),
click: () => fetherApp.win.webContents.reload()
});
}
template.push({ role: 'quit', label: i18n.t('menu.file.quit') });
return template;
}
};
const getContextWindowMenuTemplate = fetherApp => {
const template = getMenubarMenuTemplate(fetherApp);
// Set the checkbox value off in the context menu on first launch
let isFirstLaunch = settings.has('launch-on-startup');
const menuItemLaunchOnStartup = {
label: 'Launch On Startup',
type: 'checkbox',
checked: isFirstLaunch ? false : isChecked(fetherApp),
async click () {
if (process.platform === 'linux') {
isLaunchOnStartup = await fetherAutoLauncher.isEnabled();
pino.info('Previous Launch on Startup setting: ', isLaunchOnStartup);
isLaunchOnStartup
? await fetherAutoLauncher.disable()
: await fetherAutoLauncher.enable();
const newSetting = await fetherAutoLauncher.isEnabled();
pino.info('New Launch on Startup setting: ', newSetting);
/**
* Hack since `checked` property is promise and unable to
* assign it to result of resolved promise. Instead we store
* the state using electron-settings. Only issue is that the
* checked value shown in the UI will be incorrect the first
* time the user runs the application, but after the user
* the value and it starts using the electron-settings value
* it will be correct.
*/
settings.set('launch-on-startup', newSetting);
} else {
isLaunchOnStartup = getIsLaunchOnStartup(fetherApp);
fetherApp.app.setLoginItemSettings(
settingsLaunchOnStartup(!isLaunchOnStartup)
);
}
pino.info('Set Launch On Startup setting to: ', !isLaunchOnStartup);
isFirstLaunch = undefined;
if (fetherApp.options.withTaskbar) {
// Remove File and Help menus in taskbar mode for window context menu
template.shift();
template.pop();
template.push({
label: i18n.t('menu.file.preferences.submenu_name'),
submenu: [getPreferences(fetherApp)]
template.push({
role: 'help',
label: i18n.t('menu.help.submenu_name'),
submenu: [
{
label: i18n.t('menu.help.learn_more'),
click () {
shell.openExternal('https://parity.io');
}
Luke Schoen
committed
}
]
});
template.push({ type: 'separator' });
if (process.platform === 'darwin') {
template[3].submenu.push({
role: 'about',
label: i18n.t('menu.file.about')
});
template.push({ role: 'quit', label: i18n.t('menu.file.quit') });
Luke Schoen
committed
}
Luke Schoen
committed
return template;
};
export {
getContextTrayMenuTemplate,
getContextWindowMenuTemplate,
getMenubarMenuTemplate
};