import {clientIconClassToImage} from "./IconHelper"; import * as contextmenu from "tc-shared/ui/elements/ContextMenu"; import * as electron from "electron"; const remote = electron.remote; const {Menu, MenuItem} = remote; class ElectronContextMenu implements contextmenu.ContextMenuProvider { private _close_listeners: (() => any)[] = []; private _current_menu: electron.Menu; private _div: JQuery; despawn_context_menu() { if(!this._current_menu) return; this._current_menu.closePopup(); this._current_menu = undefined; for(const listener of this._close_listeners) { if(listener) { try { listener(); } catch (e) { console.error("Failed to call context menu close listener: %o", e); } } } this._close_listeners = []; } finalize() { if(this._div) this._div.detach(); this._div = undefined; } initialize() { } private _entry_id = 0; private build_menu(entry: contextmenu.MenuEntry) : electron.MenuItem { if(entry.type == contextmenu.MenuEntryType.CLOSE) { this._close_listeners.push(entry.callback); return undefined; } const click_callback = () => { if(entry.callback) entry.callback(); this.despawn_context_menu(); }; const _id = "entry_" + (this._entry_id++); if(entry.type == contextmenu.MenuEntryType.ENTRY) { return new MenuItem({ id: _id, label: (typeof entry.name === "function" ? (entry.name as (() => string))() : entry.name) as string, type: "normal", click: click_callback, icon: clientIconClassToImage(entry.icon_class), visible: entry.visible, enabled: !entry.disabled }); } else if(entry.type == contextmenu.MenuEntryType.HR) { if(typeof(entry.visible) === "boolean" && !entry.visible) return undefined; return new MenuItem({ id: _id, type: "separator", label: '', click: click_callback }) } else if(entry.type == contextmenu.MenuEntryType.CHECKBOX) { return new MenuItem({ id: _id, label: (typeof entry.name === "function" ? (entry.name as (() => string))() : entry.name) as string, type: "checkbox", checked: !!entry.checkbox_checked, click: click_callback, icon: clientIconClassToImage(entry.icon_class), visible: entry.visible, enabled: !entry.disabled }); } else if (entry.type == contextmenu.MenuEntryType.SUB_MENU) { const sub_menu = new Menu(); for(const e of entry.sub_menu) { const build = this.build_menu(e); if(!build) continue; sub_menu.append(build); } return new MenuItem({ id: _id, label: (typeof entry.name === "function" ? (entry.name as (() => string))() : entry.name) as string, type: "submenu", submenu: sub_menu, click: click_callback, icon: clientIconClassToImage(entry.icon_class), visible: entry.visible, enabled: !entry.disabled }); } return undefined; } spawn_context_menu(x: number, y: number, ...entries: contextmenu.MenuEntry[]) { this.despawn_context_menu(); this._current_menu = new Menu(); for(const entry of entries) { const build = this.build_menu(entry); if(!build) continue; this._current_menu.append(build); } this._current_menu.popup({ window: remote.getCurrentWindow(), x: x, y: y, callback: () => this.despawn_context_menu() }); } html_format_enabled() { return false; } } contextmenu.set_provider(new ElectronContextMenu());