| 4 | const trackedContents = new WeakSet<WebContents>() |
| 5 | |
| 6 | const addContextMenu = (wc: WebContents) => { |
| 7 | if (trackedContents.has(wc)) { |
| 8 | return |
| 9 | } |
| 10 | trackedContents.add(wc) |
| 11 | |
| 12 | wc.once("destroyed", () => { |
| 13 | trackedContents.delete(wc) |
| 14 | }) |
| 15 | |
| 16 | wc.on("context-menu", (_event, params: ContextMenuParams) => { |
| 17 | try { |
| 18 | const template = buildNativeContextMenuTemplate( |
| 19 | params, |
| 20 | { |
| 21 | replaceMisspelling: (word: string) => wc.replaceMisspelling(word), |
| 22 | learnSpelling: (word: string) => wc.session.addWordToSpellCheckerDictionary(word), |
| 23 | lookUpSelection: () => wc.showDefinitionForSelection(), |
| 24 | copyImageAt: (x: number, y: number) => wc.copyImageAt(x, y), |
| 25 | copyImageAddress: (url: string) => clipboard.write({ text: url, bookmark: url }), |
| 26 | copyVideoAddress: (url: string) => clipboard.write({ text: url, bookmark: url }), |
| 27 | copyLink: (url: string, text: string) => clipboard.write({ text: url, bookmark: text || url }), |
| 28 | }, |
| 29 | process.platform |
| 30 | ) |
| 31 | |
| 32 | if (template.length === 0) { |
| 33 | return |
| 34 | } |
| 35 | |
| 36 | Menu.buildFromTemplate(template).popup() |
| 37 | } catch (error) { |
| 38 | console.error("[contextMenu] Failed to build or show context menu:", error) |
| 39 | } |
| 40 | }) |
| 41 | } |
| 42 | |
| 43 | export const load = () => { |
| 44 | app.on("web-contents-created", (_, wc) => { |