
* Add developer mode manager, implement browser-only mode * Add indicator when developer mode is enabled * Add switch to disable notification storage * Add setting to disable the user activity monitor * Add switchOff method for easily creating switches to disable/enable functionality, added setting to disable context menu * Add setting to force legacy API * Add force new API to remove any support for legacy mode, fix i18n * Fix lint * Use one call to `push`
470 lines
18 KiB
TypeScript
470 lines
18 KiB
TypeScript
// Copyright (c) 2015-2016 Yuya Ochiai
|
|
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
'use strict';
|
|
|
|
import type {MenuItemConstructorOptions, MenuItem, BrowserWindow} from 'electron';
|
|
import {app, ipcMain, Menu, session, shell, clipboard} from 'electron';
|
|
import log from 'electron-log';
|
|
|
|
import ServerViewState from 'app/serverViewState';
|
|
import {OPEN_SERVERS_DROPDOWN, SHOW_NEW_SERVER_MODAL} from 'common/communication';
|
|
import type {Config} from 'common/config';
|
|
import ServerManager from 'common/servers/serverManager';
|
|
import {t} from 'common/utils/util';
|
|
import {getViewDisplayName} from 'common/views/View';
|
|
import type {ViewType} from 'common/views/View';
|
|
import type {UpdateManager} from 'main/autoUpdater';
|
|
import DeveloperMode from 'main/developerMode';
|
|
import Diagnostics from 'main/diagnostics';
|
|
import downloadsManager from 'main/downloadsManager';
|
|
import {localizeMessage} from 'main/i18nManager';
|
|
import {getLocalPreload} from 'main/utils';
|
|
import ModalManager from 'main/views/modalManager';
|
|
import ViewManager from 'main/views/viewManager';
|
|
import CallsWidgetWindow from 'main/windows/callsWidgetWindow';
|
|
import MainWindow from 'main/windows/mainWindow';
|
|
|
|
export function createTemplate(config: Config, updateManager: UpdateManager) {
|
|
const separatorItem: MenuItemConstructorOptions = {
|
|
type: 'separator',
|
|
};
|
|
|
|
const isMac = process.platform === 'darwin';
|
|
const appName = app.name;
|
|
const firstMenuName = isMac ? '&' + appName : localizeMessage('main.menus.app.file', '&File');
|
|
const template = [];
|
|
|
|
const settingsLabel = isMac ? localizeMessage('main.menus.app.file.preferences', 'Preferences...') : localizeMessage('main.menus.app.file.settings', 'Settings...');
|
|
|
|
let platformAppMenu = [];
|
|
if (isMac) {
|
|
platformAppMenu.push(
|
|
{
|
|
label: localizeMessage('main.menus.app.file.about', 'About {appName}', {appName}),
|
|
role: 'about',
|
|
},
|
|
);
|
|
platformAppMenu.push(separatorItem);
|
|
}
|
|
platformAppMenu.push({
|
|
label: settingsLabel,
|
|
accelerator: 'CmdOrCtrl+,',
|
|
click() {
|
|
const mainWindow = MainWindow.get();
|
|
if (!mainWindow) {
|
|
return;
|
|
}
|
|
|
|
ModalManager.addModal(
|
|
'settingsModal',
|
|
'mattermost-desktop://renderer/settings.html',
|
|
getLocalPreload('internalAPI.js'),
|
|
null,
|
|
mainWindow,
|
|
);
|
|
},
|
|
});
|
|
|
|
if (config.enableServerManagement === true && ServerManager.hasServers()) {
|
|
platformAppMenu.push({
|
|
label: localizeMessage('main.menus.app.file.signInToAnotherServer', 'Sign in to Another Server'),
|
|
click() {
|
|
ipcMain.emit(SHOW_NEW_SERVER_MODAL);
|
|
},
|
|
});
|
|
}
|
|
|
|
if (isMac) {
|
|
platformAppMenu = platformAppMenu.concat([
|
|
separatorItem, {
|
|
role: 'hide',
|
|
label: localizeMessage('main.menus.app.file.hide', 'Hide {appName}', {appName}),
|
|
}, {
|
|
role: 'hideOthers',
|
|
label: localizeMessage('main.menus.app.file.hideOthers', 'Hide Others'),
|
|
}, {
|
|
role: 'unhide',
|
|
label: localizeMessage('main.menus.app.file.unhide', 'Show All'),
|
|
}, separatorItem, {
|
|
role: 'quit',
|
|
label: localizeMessage('main.menus.app.file.quit', 'Quit {appName}', {appName}),
|
|
}]);
|
|
} else {
|
|
platformAppMenu = platformAppMenu.concat([
|
|
separatorItem, {
|
|
role: 'quit',
|
|
label: localizeMessage('main.menus.app.file.exit', 'Exit'),
|
|
accelerator: 'CmdOrCtrl+Q',
|
|
}]);
|
|
}
|
|
|
|
template.push({
|
|
id: 'file',
|
|
label: firstMenuName,
|
|
submenu: [
|
|
...platformAppMenu,
|
|
],
|
|
});
|
|
template.push({
|
|
id: 'edit',
|
|
label: localizeMessage('main.menus.app.edit', '&Edit'),
|
|
submenu: [{
|
|
role: 'undo',
|
|
label: localizeMessage('main.menus.app.edit.undo', 'Undo'),
|
|
accelerator: 'CmdOrCtrl+Z',
|
|
}, {
|
|
role: 'Redo',
|
|
label: localizeMessage('main.menus.app.edit.redo', 'Redo'),
|
|
accelerator: 'CmdOrCtrl+SHIFT+Z',
|
|
}, separatorItem, {
|
|
role: 'cut',
|
|
label: localizeMessage('main.menus.app.edit.cut', 'Cut'),
|
|
accelerator: 'CmdOrCtrl+X',
|
|
}, {
|
|
role: 'copy',
|
|
label: localizeMessage('main.menus.app.edit.copy', 'Copy'),
|
|
accelerator: 'CmdOrCtrl+C',
|
|
}, {
|
|
role: 'paste',
|
|
label: localizeMessage('main.menus.app.edit.paste', 'Paste'),
|
|
accelerator: 'CmdOrCtrl+V',
|
|
}, {
|
|
role: 'pasteAndMatchStyle',
|
|
label: localizeMessage('main.menus.app.edit.pasteAndMatchStyle', 'Paste and Match Style'),
|
|
accelerator: 'CmdOrCtrl+SHIFT+V',
|
|
}, {
|
|
role: 'selectall',
|
|
label: localizeMessage('main.menus.app.edit.selectAll', 'Select All'),
|
|
accelerator: 'CmdOrCtrl+A',
|
|
}],
|
|
});
|
|
|
|
const devToolsSubMenu: Electron.MenuItemConstructorOptions[] = [
|
|
{
|
|
label: localizeMessage('main.menus.app.view.devToolsAppWrapper', 'Developer Tools for Application Wrapper'),
|
|
accelerator: (() => {
|
|
if (process.platform === 'darwin') {
|
|
return 'Alt+Command+I';
|
|
}
|
|
return 'Ctrl+Shift+I';
|
|
})(),
|
|
click(item: Electron.MenuItem, focusedWindow?: BrowserWindow) {
|
|
if (focusedWindow) {
|
|
// toggledevtools opens it in the last known position, so sometimes it goes below the browserview
|
|
if (focusedWindow.webContents.isDevToolsOpened()) {
|
|
focusedWindow.webContents.closeDevTools();
|
|
} else {
|
|
focusedWindow.webContents.openDevTools({mode: 'detach'});
|
|
}
|
|
}
|
|
},
|
|
},
|
|
{
|
|
label: localizeMessage('main.menus.app.view.devToolsCurrentServer', 'Developer Tools for Current Server'),
|
|
click() {
|
|
ViewManager.getCurrentView()?.openDevTools();
|
|
},
|
|
},
|
|
];
|
|
|
|
if (CallsWidgetWindow.isOpen()) {
|
|
devToolsSubMenu.push({
|
|
label: localizeMessage('main.menus.app.view.devToolsCurrentCallWidget', 'Developer Tools for Call Widget'),
|
|
click() {
|
|
CallsWidgetWindow.openDevTools();
|
|
},
|
|
});
|
|
}
|
|
|
|
if (DeveloperMode.enabled()) {
|
|
devToolsSubMenu.push(...[
|
|
separatorItem,
|
|
{
|
|
label: localizeMessage('main.menus.app.view.developerModeBrowserOnly', 'Browser Only Mode'),
|
|
type: 'checkbox' as const,
|
|
checked: DeveloperMode.get('browserOnly'),
|
|
click() {
|
|
DeveloperMode.toggle('browserOnly');
|
|
},
|
|
},
|
|
{
|
|
label: localizeMessage('main.menus.app.view.developerModeDisableNotificationStorage', 'Disable Notification Storage'),
|
|
type: 'checkbox' as const,
|
|
checked: DeveloperMode.get('disableNotificationStorage'),
|
|
click() {
|
|
DeveloperMode.toggle('disableNotificationStorage');
|
|
},
|
|
},
|
|
{
|
|
label: localizeMessage('main.menus.app.view.developerModeDisableUserActivityMonitor', 'Disable User Activity Monitor'),
|
|
type: 'checkbox' as const,
|
|
checked: DeveloperMode.get('disableUserActivityMonitor'),
|
|
click() {
|
|
DeveloperMode.toggle('disableUserActivityMonitor');
|
|
},
|
|
},
|
|
{
|
|
label: localizeMessage('main.menus.app.view.developerModeDisableContextMenu', 'Disable Context Menu'),
|
|
type: 'checkbox' as const,
|
|
checked: DeveloperMode.get('disableContextMenu'),
|
|
click() {
|
|
DeveloperMode.toggle('disableContextMenu');
|
|
},
|
|
},
|
|
{
|
|
label: localizeMessage('main.menus.app.view.developerModeForceLegacyAPI', 'Force Legacy API'),
|
|
type: 'checkbox' as const,
|
|
checked: DeveloperMode.get('forceLegacyAPI'),
|
|
click() {
|
|
DeveloperMode.toggle('forceLegacyAPI');
|
|
},
|
|
},
|
|
{
|
|
label: localizeMessage('main.menus.app.view.developerModeForceNewAPI', 'Force New API'),
|
|
type: 'checkbox' as const,
|
|
checked: DeveloperMode.get('forceNewAPI'),
|
|
click() {
|
|
DeveloperMode.toggle('forceNewAPI');
|
|
},
|
|
},
|
|
]);
|
|
}
|
|
|
|
const viewSubMenu = [{
|
|
label: localizeMessage('main.menus.app.view.find', 'Find..'),
|
|
accelerator: 'CmdOrCtrl+F',
|
|
click() {
|
|
ViewManager.sendToFind();
|
|
},
|
|
}, {
|
|
label: localizeMessage('main.menus.app.view.reload', 'Reload'),
|
|
accelerator: 'CmdOrCtrl+R',
|
|
click() {
|
|
ViewManager.reload();
|
|
},
|
|
}, {
|
|
label: localizeMessage('main.menus.app.view.clearCacheAndReload', 'Clear Cache and Reload'),
|
|
accelerator: 'Shift+CmdOrCtrl+R',
|
|
click() {
|
|
session.defaultSession.clearCache();
|
|
ViewManager.reload();
|
|
},
|
|
}, {
|
|
role: 'togglefullscreen',
|
|
label: localizeMessage('main.menus.app.view.fullscreen', 'Toggle Full Screen'),
|
|
accelerator: isMac ? 'Ctrl+Cmd+F' : 'F11',
|
|
}, separatorItem, {
|
|
label: localizeMessage('main.menus.app.view.actualSize', 'Actual Size'),
|
|
role: 'resetZoom',
|
|
accelerator: 'CmdOrCtrl+0',
|
|
}, {
|
|
role: 'zoomIn',
|
|
label: localizeMessage('main.menus.app.view.zoomIn', 'Zoom In'),
|
|
accelerator: 'CmdOrCtrl+=',
|
|
}, {
|
|
role: 'zoomIn',
|
|
visible: false,
|
|
accelerator: 'CmdOrCtrl+Shift+=',
|
|
}, {
|
|
role: 'zoomOut',
|
|
label: localizeMessage('main.menus.app.view.zoomOut', 'Zoom Out'),
|
|
accelerator: 'CmdOrCtrl+-',
|
|
}, {
|
|
role: 'zoomOut',
|
|
visible: false,
|
|
accelerator: 'CmdOrCtrl+Shift+-',
|
|
}, separatorItem, {
|
|
id: 'app-menu-downloads',
|
|
label: localizeMessage('main.menus.app.view.downloads', 'Downloads'),
|
|
enabled: downloadsManager.hasDownloads(),
|
|
click() {
|
|
return downloadsManager.openDownloadsDropdown();
|
|
},
|
|
}, separatorItem, {
|
|
label: localizeMessage('main.menus.app.view.devToolsSubMenu', 'Developer Tools'),
|
|
submenu: devToolsSubMenu,
|
|
}];
|
|
|
|
if (process.platform !== 'darwin' && process.platform !== 'win32') {
|
|
viewSubMenu.push(separatorItem);
|
|
viewSubMenu.push({
|
|
label: localizeMessage('main.menus.app.view.toggleDarkMode', 'Toggle Dark Mode'),
|
|
click() {
|
|
config.set('darkMode', !config.darkMode);
|
|
},
|
|
});
|
|
}
|
|
|
|
template.push({
|
|
id: 'view',
|
|
label: localizeMessage('main.menus.app.view', '&View'),
|
|
submenu: viewSubMenu,
|
|
});
|
|
template.push({
|
|
id: 'history',
|
|
label: localizeMessage('main.menus.app.history', '&History'),
|
|
submenu: [{
|
|
label: localizeMessage('main.menus.app.history.back', 'Back'),
|
|
accelerator: process.platform === 'darwin' ? 'Cmd+[' : 'Alt+Left',
|
|
click: () => {
|
|
ViewManager.getCurrentView()?.goToOffset(-1);
|
|
},
|
|
}, {
|
|
label: localizeMessage('main.menus.app.history.forward', 'Forward'),
|
|
accelerator: process.platform === 'darwin' ? 'Cmd+]' : 'Alt+Right',
|
|
click: () => {
|
|
ViewManager.getCurrentView()?.goToOffset(1);
|
|
},
|
|
}],
|
|
});
|
|
|
|
const servers = ServerManager.getOrderedServers();
|
|
const windowMenu = {
|
|
id: 'window',
|
|
label: localizeMessage('main.menus.app.window', '&Window'),
|
|
role: isMac ? 'windowMenu' : null,
|
|
submenu: [{
|
|
role: 'minimize',
|
|
label: localizeMessage('main.menus.app.window.minimize', 'Minimize'),
|
|
|
|
// empty string removes shortcut on Windows; null will default by OS
|
|
accelerator: process.platform === 'win32' ? '' : null,
|
|
}, ...(isMac ? [{
|
|
role: 'zoom',
|
|
label: localizeMessage('main.menus.app.window.zoom', 'Zoom'),
|
|
}, separatorItem,
|
|
] : []), {
|
|
role: 'close',
|
|
label: isMac ? localizeMessage('main.menus.app.window.closeWindow', 'Close Window') : localizeMessage('main.menus.app.window.close', 'Close'),
|
|
accelerator: 'CmdOrCtrl+W',
|
|
}, separatorItem,
|
|
...(ServerManager.hasServers() ? [{
|
|
label: localizeMessage('main.menus.app.window.showServers', 'Show Servers'),
|
|
accelerator: `${process.platform === 'darwin' ? 'Cmd+Ctrl' : 'Ctrl+Shift'}+S`,
|
|
click() {
|
|
ipcMain.emit(OPEN_SERVERS_DROPDOWN);
|
|
},
|
|
}] : []),
|
|
...servers.slice(0, 9).map((server, i) => {
|
|
const items = [];
|
|
items.push({
|
|
label: server.name,
|
|
accelerator: `${process.platform === 'darwin' ? 'Cmd+Ctrl' : 'Ctrl+Shift'}+${i + 1}`,
|
|
click() {
|
|
ServerViewState.switchServer(server.id);
|
|
},
|
|
});
|
|
if (ServerViewState.getCurrentServer().id === server.id) {
|
|
ServerManager.getOrderedTabsForServer(server.id).slice(0, 9).forEach((view, i) => {
|
|
items.push({
|
|
label: ` ${localizeMessage(`common.views.${view.type}`, getViewDisplayName(view.type as ViewType))}`,
|
|
accelerator: `CmdOrCtrl+${i + 1}`,
|
|
click() {
|
|
ViewManager.showById(view.id);
|
|
},
|
|
});
|
|
});
|
|
}
|
|
return items;
|
|
}).flat(), separatorItem, {
|
|
label: localizeMessage('main.menus.app.window.selectNextTab', 'Select Next Tab'),
|
|
accelerator: 'Ctrl+Tab',
|
|
click() {
|
|
ServerViewState.selectNextView();
|
|
},
|
|
enabled: (servers.length > 1),
|
|
}, {
|
|
label: localizeMessage('main.menus.app.window.selectPreviousTab', 'Select Previous Tab'),
|
|
accelerator: 'Ctrl+Shift+Tab',
|
|
click() {
|
|
ServerViewState.selectPreviousView();
|
|
},
|
|
enabled: (servers.length > 1),
|
|
}, ...(isMac ? [separatorItem, {
|
|
role: 'front',
|
|
label: localizeMessage('main.menus.app.window.bringAllToFront', 'Bring All to Front'),
|
|
}] : []),
|
|
],
|
|
};
|
|
template.push(windowMenu);
|
|
const submenu = [];
|
|
if (updateManager && config.canUpgrade) {
|
|
if (updateManager.versionDownloaded) {
|
|
submenu.push({
|
|
label: localizeMessage('main.menus.app.help.restartAndUpdate', 'Restart and Update'),
|
|
click() {
|
|
updateManager.handleUpdate();
|
|
},
|
|
});
|
|
} else if (updateManager.versionAvailable) {
|
|
submenu.push({
|
|
label: localizeMessage('main.menus.app.help.downloadUpdate', 'Download Update'),
|
|
click() {
|
|
updateManager.handleDownload();
|
|
},
|
|
});
|
|
} else {
|
|
submenu.push({
|
|
label: localizeMessage('main.menus.app.help.checkForUpdates', 'Check for Updates'),
|
|
click() {
|
|
updateManager.checkForUpdates(true);
|
|
},
|
|
});
|
|
}
|
|
}
|
|
if (config.helpLink) {
|
|
submenu.push({
|
|
label: localizeMessage('main.menus.app.help.learnMore', 'Learn More...'),
|
|
click() {
|
|
shell.openExternal(config.helpLink!);
|
|
},
|
|
});
|
|
submenu.push(separatorItem);
|
|
}
|
|
|
|
submenu.push({
|
|
id: 'Show logs',
|
|
label: localizeMessage('main.menus.app.help.ShowLogs', 'Show logs'),
|
|
click() {
|
|
shell.showItemInFolder(log.transports.file.getFile().path);
|
|
},
|
|
});
|
|
|
|
submenu.push({
|
|
id: 'diagnostics',
|
|
label: localizeMessage('main.menus.app.help.RunDiagnostics', 'Run diagnostics'),
|
|
click() {
|
|
Diagnostics.run();
|
|
},
|
|
});
|
|
submenu.push(separatorItem);
|
|
|
|
const version = localizeMessage('main.menus.app.help.versionString', 'Version {version}{commit}', {
|
|
version: app.getVersion(),
|
|
// eslint-disable-next-line no-undef
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
commit: __HASH_VERSION__ ? localizeMessage('main.menus.app.help.commitString', ' commit: {hashVersion}', {hashVersion: __HASH_VERSION__}) : '',
|
|
});
|
|
submenu.push({
|
|
label: version,
|
|
enabled: true,
|
|
click() {
|
|
clipboard.writeText(version);
|
|
},
|
|
});
|
|
|
|
template.push({id: 'help', label: localizeMessage('main.menus.app.help', 'Hel&p'), submenu});
|
|
return template;
|
|
}
|
|
|
|
export function createMenu(config: Config, updateManager: UpdateManager) {
|
|
// TODO: Electron is enforcing certain variables that it doesn't need
|
|
return Menu.buildFromTemplate(createTemplate(config, updateManager) as Array<MenuItemConstructorOptions | MenuItem>);
|
|
}
|
|
|
|
t('common.tabs.TAB_MESSAGING');
|
|
t('common.tabs.TAB_FOCALBOARD');
|
|
t('common.tabs.TAB_PLAYBOOKS');
|