зеркало из https://github.com/electron/electron.git
chore: tsify menu (#24358)
This commit is contained in:
Родитель
2a3437e5b5
Коммит
71a7e1b2e3
|
@ -96,7 +96,7 @@ Appends the `menuItem` to the menu.
|
|||
|
||||
* `id` String
|
||||
|
||||
Returns `MenuItem` the item with the specified `id`
|
||||
Returns `MenuItem | null` the item with the specified `id`
|
||||
|
||||
#### `menu.insert(pos, menuItem)`
|
||||
|
||||
|
|
|
@ -201,10 +201,10 @@ auto_filenames = {
|
|||
"lib/browser/api/global-shortcut.ts",
|
||||
"lib/browser/api/in-app-purchase.ts",
|
||||
"lib/browser/api/ipc-main.ts",
|
||||
"lib/browser/api/menu-item-roles.js",
|
||||
"lib/browser/api/menu-item.js",
|
||||
"lib/browser/api/menu-utils.js",
|
||||
"lib/browser/api/menu.js",
|
||||
"lib/browser/api/menu-item-roles.ts",
|
||||
"lib/browser/api/menu-item.ts",
|
||||
"lib/browser/api/menu-utils.ts",
|
||||
"lib/browser/api/menu.ts",
|
||||
"lib/browser/api/message-channel.ts",
|
||||
"lib/browser/api/module-list.ts",
|
||||
"lib/browser/api/native-theme.ts",
|
||||
|
|
|
@ -1,44 +1,56 @@
|
|||
'use strict';
|
||||
|
||||
const { app } = require('electron');
|
||||
import { app, BrowserWindow, WebContents, MenuItemConstructorOptions } from 'electron';
|
||||
|
||||
const isMac = process.platform === 'darwin';
|
||||
const isWindows = process.platform === 'win32';
|
||||
const isLinux = process.platform === 'linux';
|
||||
|
||||
const roles = {
|
||||
type RoleId = 'about' | 'close' | 'copy' | 'cut' | 'delete' | 'forcereload' | 'front' | 'help' | 'hide' | 'hideothers' | 'minimize' |
|
||||
'paste' | 'pasteandmatchstyle' | 'quit' | 'redo' | 'reload' | 'resetzoom' | 'selectall' | 'services' | 'recentdocuments' | 'clearrecentdocuments' | 'startspeaking' | 'stopspeaking' |
|
||||
'toggledevtools' | 'togglefullscreen' | 'undo' | 'unhide' | 'window' | 'zoom' | 'zoomin' | 'zoomout' | 'appmenu' | 'filemenu' | 'editmenu' | 'viewmenu' | 'windowmenu'
|
||||
interface Role {
|
||||
label: string;
|
||||
accelerator?: string;
|
||||
windowMethod?: ((window: BrowserWindow) => void);
|
||||
webContentsMethod?: ((webContents: WebContents) => void);
|
||||
appMethod?: () => void;
|
||||
registerAccelerator?: boolean;
|
||||
nonNativeMacOSRole?: boolean;
|
||||
submenu?: MenuItemConstructorOptions[];
|
||||
}
|
||||
|
||||
export const roleList: Record<RoleId, Role> = {
|
||||
about: {
|
||||
get label () {
|
||||
return isLinux ? 'About' : `About ${app.name}`;
|
||||
},
|
||||
...(isWindows && { appMethod: 'showAboutPanel' })
|
||||
...(isWindows && { appMethod: () => app.showAboutPanel() })
|
||||
},
|
||||
close: {
|
||||
label: isMac ? 'Close Window' : 'Close',
|
||||
accelerator: 'CommandOrControl+W',
|
||||
windowMethod: 'close'
|
||||
windowMethod: w => w.close()
|
||||
},
|
||||
copy: {
|
||||
label: 'Copy',
|
||||
accelerator: 'CommandOrControl+C',
|
||||
webContentsMethod: 'copy',
|
||||
webContentsMethod: wc => wc.copy(),
|
||||
registerAccelerator: false
|
||||
},
|
||||
cut: {
|
||||
label: 'Cut',
|
||||
accelerator: 'CommandOrControl+X',
|
||||
webContentsMethod: 'cut',
|
||||
webContentsMethod: wc => wc.cut(),
|
||||
registerAccelerator: false
|
||||
},
|
||||
delete: {
|
||||
label: 'Delete',
|
||||
webContentsMethod: 'delete'
|
||||
webContentsMethod: wc => wc.delete()
|
||||
},
|
||||
forcereload: {
|
||||
label: 'Force Reload',
|
||||
accelerator: 'Shift+CmdOrCtrl+R',
|
||||
nonNativeMacOSRole: true,
|
||||
windowMethod: (window) => {
|
||||
windowMethod: (window: BrowserWindow) => {
|
||||
window.webContents.reloadIgnoringCache();
|
||||
}
|
||||
},
|
||||
|
@ -61,18 +73,18 @@ const roles = {
|
|||
minimize: {
|
||||
label: 'Minimize',
|
||||
accelerator: 'CommandOrControl+M',
|
||||
windowMethod: 'minimize'
|
||||
windowMethod: w => w.minimize()
|
||||
},
|
||||
paste: {
|
||||
label: 'Paste',
|
||||
accelerator: 'CommandOrControl+V',
|
||||
webContentsMethod: 'paste',
|
||||
webContentsMethod: wc => wc.paste(),
|
||||
registerAccelerator: false
|
||||
},
|
||||
pasteandmatchstyle: {
|
||||
label: 'Paste and Match Style',
|
||||
accelerator: isMac ? 'Cmd+Option+Shift+V' : 'Shift+CommandOrControl+V',
|
||||
webContentsMethod: 'pasteAndMatchStyle',
|
||||
webContentsMethod: wc => wc.pasteAndMatchStyle(),
|
||||
registerAccelerator: false
|
||||
},
|
||||
quit: {
|
||||
|
@ -84,31 +96,31 @@ const roles = {
|
|||
}
|
||||
},
|
||||
accelerator: isWindows ? undefined : 'CommandOrControl+Q',
|
||||
appMethod: 'quit'
|
||||
appMethod: () => app.quit()
|
||||
},
|
||||
redo: {
|
||||
label: 'Redo',
|
||||
accelerator: isWindows ? 'Control+Y' : 'Shift+CommandOrControl+Z',
|
||||
webContentsMethod: 'redo'
|
||||
webContentsMethod: wc => wc.redo()
|
||||
},
|
||||
reload: {
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
nonNativeMacOSRole: true,
|
||||
windowMethod: 'reload'
|
||||
windowMethod: w => w.reload()
|
||||
},
|
||||
resetzoom: {
|
||||
label: 'Actual Size',
|
||||
accelerator: 'CommandOrControl+0',
|
||||
nonNativeMacOSRole: true,
|
||||
webContentsMethod: (webContents) => {
|
||||
webContentsMethod: (webContents: WebContents) => {
|
||||
webContents.zoomLevel = 0;
|
||||
}
|
||||
},
|
||||
selectall: {
|
||||
label: 'Select All',
|
||||
accelerator: 'CommandOrControl+A',
|
||||
webContentsMethod: 'selectAll'
|
||||
webContentsMethod: wc => wc.selectAll()
|
||||
},
|
||||
services: {
|
||||
label: 'Services'
|
||||
|
@ -129,19 +141,19 @@ const roles = {
|
|||
label: 'Toggle Developer Tools',
|
||||
accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
|
||||
nonNativeMacOSRole: true,
|
||||
windowMethod: 'toggleDevTools'
|
||||
windowMethod: w => w.webContents.toggleDevTools()
|
||||
},
|
||||
togglefullscreen: {
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: isMac ? 'Control+Command+F' : 'F11',
|
||||
windowMethod: (window) => {
|
||||
windowMethod: (window: BrowserWindow) => {
|
||||
window.setFullScreen(!window.isFullScreen());
|
||||
}
|
||||
},
|
||||
undo: {
|
||||
label: 'Undo',
|
||||
accelerator: 'CommandOrControl+Z',
|
||||
webContentsMethod: 'undo'
|
||||
webContentsMethod: wc => wc.undo()
|
||||
},
|
||||
unhide: {
|
||||
label: 'Show All'
|
||||
|
@ -156,7 +168,7 @@ const roles = {
|
|||
label: 'Zoom In',
|
||||
accelerator: 'CommandOrControl+Plus',
|
||||
nonNativeMacOSRole: true,
|
||||
webContentsMethod: (webContents) => {
|
||||
webContentsMethod: (webContents: WebContents) => {
|
||||
webContents.zoomLevel += 0.5;
|
||||
}
|
||||
},
|
||||
|
@ -164,7 +176,7 @@ const roles = {
|
|||
label: 'Zoom Out',
|
||||
accelerator: 'CommandOrControl+-',
|
||||
nonNativeMacOSRole: true,
|
||||
webContentsMethod: (webContents) => {
|
||||
webContentsMethod: (webContents: WebContents) => {
|
||||
webContents.zoomLevel -= 0.5;
|
||||
}
|
||||
},
|
||||
|
@ -214,11 +226,11 @@ const roles = {
|
|||
{ role: 'stopSpeaking' }
|
||||
]
|
||||
}
|
||||
] : [
|
||||
] as MenuItemConstructorOptions[] : [
|
||||
{ role: 'delete' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'selectAll' }
|
||||
])
|
||||
] as MenuItemConstructorOptions[])
|
||||
]
|
||||
},
|
||||
// View submenu
|
||||
|
@ -245,40 +257,38 @@ const roles = {
|
|||
...(isMac ? [
|
||||
{ type: 'separator' },
|
||||
{ role: 'front' }
|
||||
] : [
|
||||
] as MenuItemConstructorOptions[] : [
|
||||
{ role: 'close' }
|
||||
])
|
||||
] as MenuItemConstructorOptions[])
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
exports.roleList = roles;
|
||||
|
||||
const canExecuteRole = (role) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(roles, role)) return false;
|
||||
const canExecuteRole = (role: keyof typeof roleList) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(roleList, role)) return false;
|
||||
if (!isMac) return true;
|
||||
|
||||
// macOS handles all roles natively except for a few
|
||||
return roles[role].nonNativeMacOSRole;
|
||||
return roleList[role].nonNativeMacOSRole;
|
||||
};
|
||||
|
||||
exports.getDefaultLabel = (role) => {
|
||||
return Object.prototype.hasOwnProperty.call(roles, role) ? roles[role].label : '';
|
||||
};
|
||||
export function getDefaultLabel (role: RoleId) {
|
||||
return Object.prototype.hasOwnProperty.call(roleList, role) ? roleList[role].label : '';
|
||||
}
|
||||
|
||||
exports.getDefaultAccelerator = (role) => {
|
||||
if (Object.prototype.hasOwnProperty.call(roles, role)) return roles[role].accelerator;
|
||||
};
|
||||
export function getDefaultAccelerator (role: RoleId) {
|
||||
if (Object.prototype.hasOwnProperty.call(roleList, role)) return roleList[role].accelerator;
|
||||
}
|
||||
|
||||
exports.shouldRegisterAccelerator = (role) => {
|
||||
const hasRoleRegister = Object.prototype.hasOwnProperty.call(roles, role) && roles[role].registerAccelerator !== undefined;
|
||||
return hasRoleRegister ? roles[role].registerAccelerator : true;
|
||||
};
|
||||
export function shouldRegisterAccelerator (role: RoleId) {
|
||||
const hasRoleRegister = Object.prototype.hasOwnProperty.call(roleList, role) && roleList[role].registerAccelerator !== undefined;
|
||||
return hasRoleRegister ? roleList[role].registerAccelerator : true;
|
||||
}
|
||||
|
||||
exports.getDefaultSubmenu = (role) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(roles, role)) return;
|
||||
export function getDefaultSubmenu (role: RoleId) {
|
||||
if (!Object.prototype.hasOwnProperty.call(roleList, role)) return;
|
||||
|
||||
let { submenu } = roles[role];
|
||||
let { submenu } = roleList[role];
|
||||
|
||||
// remove null items from within the submenu
|
||||
if (Array.isArray(submenu)) {
|
||||
|
@ -286,35 +296,27 @@ exports.getDefaultSubmenu = (role) => {
|
|||
}
|
||||
|
||||
return submenu;
|
||||
};
|
||||
}
|
||||
|
||||
exports.execute = (role, focusedWindow, focusedWebContents) => {
|
||||
export function execute (role: RoleId, focusedWindow: BrowserWindow, focusedWebContents: WebContents) {
|
||||
if (!canExecuteRole(role)) return false;
|
||||
|
||||
const { appMethod, webContentsMethod, windowMethod } = roles[role];
|
||||
const { appMethod, webContentsMethod, windowMethod } = roleList[role];
|
||||
|
||||
if (appMethod) {
|
||||
app[appMethod]();
|
||||
appMethod();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (windowMethod && focusedWindow != null) {
|
||||
if (typeof windowMethod === 'function') {
|
||||
windowMethod(focusedWindow);
|
||||
} else {
|
||||
focusedWindow[windowMethod]();
|
||||
}
|
||||
windowMethod(focusedWindow);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (webContentsMethod && focusedWebContents != null) {
|
||||
if (typeof webContentsMethod === 'function') {
|
||||
webContentsMethod(focusedWebContents);
|
||||
} else {
|
||||
focusedWebContents[webContentsMethod]();
|
||||
}
|
||||
webContentsMethod(focusedWebContents);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
const roles = require('@electron/internal/browser/api/menu-item-roles');
|
||||
import * as roles from './menu-item-roles';
|
||||
import { Menu, Event, BrowserWindow, WebContents } from 'electron';
|
||||
|
||||
let nextCommandId = 0;
|
||||
|
||||
const MenuItem = function (options) {
|
||||
const { Menu } = require('electron');
|
||||
|
||||
const MenuItem = function (this: any, options: any) {
|
||||
// Preserve extra fields specified by user
|
||||
for (const key in options) {
|
||||
if (!(key in this)) this[key] = options[key];
|
||||
|
@ -47,7 +44,7 @@ const MenuItem = function (options) {
|
|||
this.overrideReadOnlyProperty('commandId', ++nextCommandId);
|
||||
|
||||
const click = options.click;
|
||||
this.click = (event, focusedWindow, focusedWebContents) => {
|
||||
this.click = (event: Event, focusedWindow: BrowserWindow, focusedWebContents: WebContents) => {
|
||||
// Manually flip the checked flags when clicked.
|
||||
if (this.type === 'checkbox' || this.type === 'radio') {
|
||||
this.checked = !this.checked;
|
||||
|
@ -69,13 +66,13 @@ MenuItem.prototype.getDefaultRoleAccelerator = function () {
|
|||
return roles.getDefaultAccelerator(this.role);
|
||||
};
|
||||
|
||||
MenuItem.prototype.overrideProperty = function (name, defaultValue = null) {
|
||||
MenuItem.prototype.overrideProperty = function (name: string, defaultValue: any = null) {
|
||||
if (this[name] == null) {
|
||||
this[name] = defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
|
||||
MenuItem.prototype.overrideReadOnlyProperty = function (name: string, defaultValue: any) {
|
||||
this.overrideProperty(name, defaultValue);
|
||||
Object.defineProperty(this, name, {
|
||||
enumerable: true,
|
|
@ -1,6 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
function splitArray (arr, predicate) {
|
||||
function splitArray<T> (arr: T[], predicate: (x: T) => boolean) {
|
||||
const result = arr.reduce((multi, item) => {
|
||||
const current = multi[multi.length - 1];
|
||||
if (predicate(item)) {
|
||||
|
@ -9,7 +7,7 @@ function splitArray (arr, predicate) {
|
|||
current.push(item);
|
||||
}
|
||||
return multi;
|
||||
}, [[]]);
|
||||
}, [[]] as T[][]);
|
||||
|
||||
if (result[result.length - 1].length === 0) {
|
||||
return result.slice(0, result.length - 1);
|
||||
|
@ -17,7 +15,7 @@ function splitArray (arr, predicate) {
|
|||
return result;
|
||||
}
|
||||
|
||||
function joinArrays (arrays, joinIDs) {
|
||||
function joinArrays (arrays: any[][], joinIDs: any[]) {
|
||||
return arrays.reduce((joined, arr, i) => {
|
||||
if (i > 0 && arr.length) {
|
||||
if (joinIDs.length > 0) {
|
||||
|
@ -31,14 +29,14 @@ function joinArrays (arrays, joinIDs) {
|
|||
}, []);
|
||||
}
|
||||
|
||||
function pushOntoMultiMap (map, key, value) {
|
||||
function pushOntoMultiMap<K, V> (map: Map<K, V[]>, key: K, value: V) {
|
||||
if (!map.has(key)) {
|
||||
map.set(key, []);
|
||||
}
|
||||
map.get(key).push(value);
|
||||
map.get(key)!.push(value);
|
||||
}
|
||||
|
||||
function indexOfGroupContainingID (groups, id, ignoreGroup) {
|
||||
function indexOfGroupContainingID<T> (groups: {id?: T}[][], id: T, ignoreGroup: {id?: T}[]) {
|
||||
return groups.findIndex(
|
||||
candidateGroup =>
|
||||
candidateGroup !== ignoreGroup &&
|
||||
|
@ -50,11 +48,11 @@ function indexOfGroupContainingID (groups, id, ignoreGroup) {
|
|||
|
||||
// Sort nodes topologically using a depth-first approach. Encountered cycles
|
||||
// are broken.
|
||||
function sortTopologically (originalOrder, edgesById) {
|
||||
const sorted = [];
|
||||
const marked = new Set();
|
||||
function sortTopologically<T> (originalOrder: T[], edgesById: Map<T, T[]>) {
|
||||
const sorted = [] as T[];
|
||||
const marked = new Set<T>();
|
||||
|
||||
const visit = (mark) => {
|
||||
const visit = (mark: T) => {
|
||||
if (marked.has(mark)) return;
|
||||
marked.add(mark);
|
||||
const edges = edgesById.get(mark);
|
||||
|
@ -68,7 +66,7 @@ function sortTopologically (originalOrder, edgesById) {
|
|||
return sorted;
|
||||
}
|
||||
|
||||
function attemptToMergeAGroup (groups) {
|
||||
function attemptToMergeAGroup<T> (groups: {before?: T[], after?: T[], id?: T}[][]) {
|
||||
for (let i = 0; i < groups.length; i++) {
|
||||
const group = groups[i];
|
||||
for (const item of group) {
|
||||
|
@ -87,7 +85,7 @@ function attemptToMergeAGroup (groups) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function mergeGroups (groups) {
|
||||
function mergeGroups<T> (groups: {before?: T[], after?: T[], id?: T}[][]) {
|
||||
let merged = true;
|
||||
while (merged) {
|
||||
merged = attemptToMergeAGroup(groups);
|
||||
|
@ -95,7 +93,7 @@ function mergeGroups (groups) {
|
|||
return groups;
|
||||
}
|
||||
|
||||
function sortItemsInGroup (group) {
|
||||
function sortItemsInGroup<T> (group: {before?: T[], after?: T[], id?: T}[]) {
|
||||
const originalOrder = group.map((node, i) => i);
|
||||
const edges = new Map();
|
||||
const idToIndex = new Map(group.map((item, i) => [item.id, i]));
|
||||
|
@ -123,7 +121,7 @@ function sortItemsInGroup (group) {
|
|||
return sortedNodes.map(i => group[i]);
|
||||
}
|
||||
|
||||
function findEdgesInGroup (groups, i, edges) {
|
||||
function findEdgesInGroup<T> (groups: {beforeGroupContaining?: T[], afterGroupContaining?: T[], id?: T}[][], i: number, edges: Map<any, any>) {
|
||||
const group = groups[i];
|
||||
for (const item of group) {
|
||||
if (item.beforeGroupContaining) {
|
||||
|
@ -147,7 +145,7 @@ function findEdgesInGroup (groups, i, edges) {
|
|||
}
|
||||
}
|
||||
|
||||
function sortGroups (groups) {
|
||||
function sortGroups<T> (groups: {id?: T}[][]) {
|
||||
const originalOrder = groups.map((item, i) => i);
|
||||
const edges = new Map();
|
||||
|
||||
|
@ -159,8 +157,8 @@ function sortGroups (groups) {
|
|||
return sortedGroupIndexes.map(i => groups[i]);
|
||||
}
|
||||
|
||||
function sortMenuItems (menuItems) {
|
||||
const isSeparator = (item) => item.type === 'separator';
|
||||
export function sortMenuItems (menuItems: {type?: string, id?: string}[]) {
|
||||
const isSeparator = (item: {type?: string}) => item.type === 'separator';
|
||||
const separators = menuItems.filter(i => i.type === 'separator');
|
||||
|
||||
// Split the items into their implicit groups based upon separators.
|
||||
|
@ -172,5 +170,3 @@ function sortMenuItems (menuItems) {
|
|||
const joined = joinArrays(sortedGroups, separators);
|
||||
return joined;
|
||||
}
|
||||
|
||||
module.exports = { sortMenuItems };
|
|
@ -1,13 +1,11 @@
|
|||
'use strict';
|
||||
import { BaseWindow, MenuItem, webContents, Menu as MenuType, BrowserWindow, MenuItemConstructorOptions } from 'electron';
|
||||
import { sortMenuItems } from './menu-utils';
|
||||
|
||||
const { BaseWindow, MenuItem, webContents } = require('electron');
|
||||
const { sortMenuItems } = require('@electron/internal/browser/api/menu-utils');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
const bindings = process._linkedBinding('electron_browser_menu');
|
||||
|
||||
const { Menu } = bindings;
|
||||
let applicationMenu = null;
|
||||
const { Menu } = bindings as { Menu: typeof MenuType };
|
||||
let applicationMenu: MenuType | null = null;
|
||||
let groupIdIndex = 0;
|
||||
|
||||
/* Instance Methods */
|
||||
|
@ -19,17 +17,17 @@ Menu.prototype._init = function () {
|
|||
};
|
||||
|
||||
Menu.prototype._isCommandIdChecked = function (id) {
|
||||
return this.commandsMap[id] ? this.commandsMap[id].checked : undefined;
|
||||
return this.commandsMap[id] ? this.commandsMap[id].checked : false;
|
||||
};
|
||||
|
||||
Menu.prototype._isCommandIdEnabled = function (id) {
|
||||
return this.commandsMap[id] ? this.commandsMap[id].enabled : undefined;
|
||||
return this.commandsMap[id] ? this.commandsMap[id].enabled : false;
|
||||
};
|
||||
Menu.prototype._shouldCommandIdWorkWhenHidden = function (id) {
|
||||
return this.commandsMap[id] ? this.commandsMap[id].acceleratorWorksWhenHidden : undefined;
|
||||
return this.commandsMap[id] ? !!this.commandsMap[id].acceleratorWorksWhenHidden : false;
|
||||
};
|
||||
Menu.prototype._isCommandIdVisible = function (id) {
|
||||
return this.commandsMap[id] ? this.commandsMap[id].visible : undefined;
|
||||
return this.commandsMap[id] ? this.commandsMap[id].visible : false;
|
||||
};
|
||||
|
||||
Menu.prototype._getAcceleratorForCommandId = function (id, useDefaultAccelerator) {
|
||||
|
@ -40,13 +38,14 @@ Menu.prototype._getAcceleratorForCommandId = function (id, useDefaultAccelerator
|
|||
};
|
||||
|
||||
Menu.prototype._shouldRegisterAcceleratorForCommandId = function (id) {
|
||||
return this.commandsMap[id] ? this.commandsMap[id].registerAccelerator : undefined;
|
||||
return this.commandsMap[id] ? this.commandsMap[id].registerAccelerator : false;
|
||||
};
|
||||
|
||||
Menu.prototype._executeCommand = function (event, id) {
|
||||
const command = this.commandsMap[id];
|
||||
if (!command) return;
|
||||
command.click(event, BaseWindow.getFocusedWindow(), webContents.getFocusedWebContents());
|
||||
const focusedWindow = BaseWindow.getFocusedWindow();
|
||||
command.click(event, focusedWindow instanceof BrowserWindow ? focusedWindow : undefined, webContents.getFocusedWebContents());
|
||||
};
|
||||
|
||||
Menu.prototype._menuWillShow = function () {
|
||||
|
@ -73,17 +72,17 @@ Menu.prototype.popup = function (options = {}) {
|
|||
|
||||
// find which window to use
|
||||
const wins = BaseWindow.getAllWindows();
|
||||
if (!wins || wins.indexOf(window) === -1) {
|
||||
window = BaseWindow.getFocusedWindow();
|
||||
if (!wins || wins.indexOf(window as any) === -1) {
|
||||
window = BaseWindow.getFocusedWindow() as any;
|
||||
if (!window && wins && wins.length > 0) {
|
||||
window = wins[0];
|
||||
window = wins[0] as any;
|
||||
}
|
||||
if (!window) {
|
||||
throw new Error('Cannot open Menu without a BaseWindow present');
|
||||
}
|
||||
}
|
||||
|
||||
this.popupAt(window, x, y, positioningItem, callback);
|
||||
this.popupAt(window as unknown as BaseWindow, x, y, positioningItem, callback);
|
||||
return { browserWindow: window, x, y, position: positioningItem };
|
||||
};
|
||||
|
||||
|
@ -102,8 +101,9 @@ Menu.prototype.getMenuItemById = function (id) {
|
|||
|
||||
let found = items.find(item => item.id === id) || null;
|
||||
for (let i = 0; !found && i < items.length; i++) {
|
||||
if (items[i].submenu) {
|
||||
found = items[i].submenu.getMenuItemById(id);
|
||||
const { submenu } = items[i];
|
||||
if (submenu) {
|
||||
found = submenu.getMenuItemById(id);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
|
@ -155,7 +155,7 @@ Menu.getApplicationMenu = () => applicationMenu;
|
|||
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder;
|
||||
|
||||
// set application menu with a preexisting menu
|
||||
Menu.setApplicationMenu = function (menu) {
|
||||
Menu.setApplicationMenu = function (menu: MenuType) {
|
||||
if (menu && menu.constructor !== Menu) {
|
||||
throw new TypeError('Invalid menu');
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ Menu.buildFromTemplate = function (template) {
|
|||
/* Helper Functions */
|
||||
|
||||
// validate the template against having the wrong attribute
|
||||
function areValidTemplateItems (template) {
|
||||
function areValidTemplateItems (template: (MenuItemConstructorOptions | MenuItem)[]) {
|
||||
return template.every(item =>
|
||||
item != null &&
|
||||
typeof item === 'object' &&
|
||||
|
@ -209,7 +209,7 @@ function areValidTemplateItems (template) {
|
|||
item.type === 'separator'));
|
||||
}
|
||||
|
||||
function sortTemplate (template) {
|
||||
function sortTemplate (template: (MenuItemConstructorOptions | MenuItem)[]) {
|
||||
const sorted = sortMenuItems(template);
|
||||
for (const item of sorted) {
|
||||
if (Array.isArray(item.submenu)) {
|
||||
|
@ -220,15 +220,15 @@ function sortTemplate (template) {
|
|||
}
|
||||
|
||||
// Search between separators to find a radio menu item and return its group id
|
||||
function generateGroupId (items, pos) {
|
||||
function generateGroupId (items: (MenuItemConstructorOptions | MenuItem)[], pos: number) {
|
||||
if (pos > 0) {
|
||||
for (let idx = pos - 1; idx >= 0; idx--) {
|
||||
if (items[idx].type === 'radio') return items[idx].groupId;
|
||||
if (items[idx].type === 'radio') return (items[idx] as any).groupId;
|
||||
if (items[idx].type === 'separator') break;
|
||||
}
|
||||
} else if (pos < items.length) {
|
||||
for (let idx = pos; idx <= items.length - 1; idx++) {
|
||||
if (items[idx].type === 'radio') return items[idx].groupId;
|
||||
if (items[idx].type === 'radio') return (items[idx] as any).groupId;
|
||||
if (items[idx].type === 'separator') break;
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ function generateGroupId (items, pos) {
|
|||
return groupIdIndex;
|
||||
}
|
||||
|
||||
function removeExtraSeparators (items) {
|
||||
function removeExtraSeparators (items: (MenuItemConstructorOptions | MenuItem)[]) {
|
||||
// fold adjacent separators together
|
||||
let ret = items.filter((e, idx, arr) => {
|
||||
if (e.visible === false) return true;
|
||||
|
@ -252,7 +252,7 @@ function removeExtraSeparators (items) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
function insertItemByType (item, pos) {
|
||||
function insertItemByType (this: MenuType, item: MenuItem, pos: number) {
|
||||
const types = {
|
||||
normal: () => this.insertItem(pos, item.commandId, item.label),
|
||||
checkbox: () => this.insertCheckItem(pos, item.commandId, item.label),
|
|
@ -1,16 +1,6 @@
|
|||
declare let standardScheme: string;
|
||||
|
||||
declare namespace Electron {
|
||||
interface Menu {
|
||||
_executeCommand(event: any, id: number): void;
|
||||
_menuWillShow(): void;
|
||||
getAcceleratorTextAt(index: number): string;
|
||||
}
|
||||
|
||||
interface MenuItem {
|
||||
getDefaultRoleAccelerator(): Accelerator | undefined;
|
||||
}
|
||||
|
||||
interface WebContents {
|
||||
getOwnerBrowserWindow(): BrowserWindow;
|
||||
getWebPreferences(): any;
|
||||
|
|
|
@ -107,6 +107,45 @@ declare namespace Electron {
|
|||
length(): number;
|
||||
}
|
||||
|
||||
interface Menu {
|
||||
_init(): void;
|
||||
_isCommandIdChecked(id: string): boolean;
|
||||
_isCommandIdEnabled(id: string): boolean;
|
||||
_shouldCommandIdWorkWhenHidden(id: string): boolean;
|
||||
_isCommandIdVisible(id: string): boolean;
|
||||
_getAcceleratorForCommandId(id: string, useDefaultAccelerator: boolean): Accelerator | undefined;
|
||||
_shouldRegisterAcceleratorForCommandId(id: string): boolean;
|
||||
_callMenuWillShow(): void;
|
||||
_executeCommand(event: any, id: number): void;
|
||||
_menuWillShow(): void;
|
||||
commandsMap: Record<string, MenuItem>;
|
||||
groupsMap: Record<string, {
|
||||
checked: boolean;
|
||||
}[]>;
|
||||
getItemCount(): number;
|
||||
popupAt(window: BaseWindow, x: number, y: number, positioning: number, callback: () => void): void;
|
||||
closePopupAt(id: number): void;
|
||||
setSublabel(index: number, label: string): void;
|
||||
setToolTip(index: number, tooltip: string): void;
|
||||
setIcon(index: number, image: string | NativeImage): void;
|
||||
setRole(index: number, role: string): void;
|
||||
insertItem(index: number, commandId: number, label: string): void;
|
||||
insertCheckItem(index: number, commandId: number, label: string): void;
|
||||
insertRadioItem(index: number, commandId: number, label: string, groupId: number): void;
|
||||
insertSeparator(index: number): void;
|
||||
insertSubMenu(index: number, commandId: number, label: string, submenu?: Menu): void;
|
||||
delegate?: any;
|
||||
getAcceleratorTextAt(index: number): string;
|
||||
}
|
||||
|
||||
interface MenuItem {
|
||||
overrideReadOnlyProperty(property: string, value: any): void;
|
||||
groupId: number;
|
||||
getDefaultRoleAccelerator(): Accelerator | undefined;
|
||||
acceleratorWorksWhenHidden?: boolean;
|
||||
}
|
||||
|
||||
|
||||
const deprecate: ElectronInternal.DeprecationUtil;
|
||||
|
||||
namespace Main {
|
||||
|
@ -123,6 +162,7 @@ declare namespace Electron {
|
|||
static getAllWindows(): BaseWindow[];
|
||||
isFocused(): boolean;
|
||||
static getFocusedWindow(): BaseWindow | undefined;
|
||||
setMenu(menu: Menu): void;
|
||||
}
|
||||
class WebContentsView {
|
||||
constructor(options: BrowserWindowConstructorOptions)
|
||||
|
|
Загрузка…
Ссылка в новой задаче