cherry-studio/src/main/services/ContextMenu.ts
beyondkmp 14e31018f7
fix: support spell check for mini app (#7602)
* feat(IpcChannel): add Webview_SetSpellCheckEnabled channel and implement spell check handling for webviews

- Introduced a new IPC channel for enabling/disabling spell check in webviews.
- Updated the registerIpc function to handle spell check settings for all webviews.
- Enhanced WebviewContainer to set spell check state on DOM ready event.
- Refactored context menu setup to accommodate webview context menus.

* refactor(ContextMenu): update methods to use Electron.WebContents instead of BrowserWindow

- Changed method signatures to accept Electron.WebContents for better context handling.
- Updated internal calls to utilize the new WebContents reference for toggling dev tools and managing spell check functionality.

* refactor(WebviewContainer): clean up import order and remove unused code

- Adjusted the import order in WebviewContainer.tsx for better readability.
- Removed redundant import of useSettings to streamline the component.
2025-06-28 08:36:32 +08:00

136 lines
3.8 KiB
TypeScript

import { Menu, MenuItemConstructorOptions } from 'electron'
import { locales } from '../utils/locales'
import { configManager } from './ConfigManager'
class ContextMenu {
public contextMenu(w: Electron.WebContents) {
w.on('context-menu', (_event, properties) => {
const template: MenuItemConstructorOptions[] = this.createEditMenuItems(properties)
const filtered = template.filter((item) => item.visible !== false)
if (filtered.length > 0) {
let template = [...filtered, ...this.createInspectMenuItems(w)]
const dictionarySuggestions = this.createDictionarySuggestions(properties, w)
if (dictionarySuggestions.length > 0) {
template = [
...dictionarySuggestions,
{ type: 'separator' },
this.createSpellCheckMenuItem(properties, w),
{ type: 'separator' },
...template
]
}
const menu = Menu.buildFromTemplate(template)
menu.popup()
}
})
}
private createInspectMenuItems(w: Electron.WebContents): MenuItemConstructorOptions[] {
const locale = locales[configManager.getLanguage()]
const { common } = locale.translation
const template: MenuItemConstructorOptions[] = [
{
id: 'inspect',
label: common.inspect,
click: () => {
w.toggleDevTools()
},
enabled: true
}
]
return template
}
private createEditMenuItems(properties: Electron.ContextMenuParams): MenuItemConstructorOptions[] {
const locale = locales[configManager.getLanguage()]
const { common } = locale.translation
const hasText = properties.selectionText.trim().length > 0
const can = (type: string) => properties.editFlags[`can${type}`] && hasText
const template: MenuItemConstructorOptions[] = [
{
id: 'copy',
label: common.copy,
role: 'copy',
enabled: can('Copy'),
visible: properties.isEditable || hasText
},
{
id: 'paste',
label: common.paste,
role: 'paste',
enabled: properties.editFlags.canPaste,
visible: properties.isEditable
},
{
id: 'cut',
label: common.cut,
role: 'cut',
enabled: can('Cut'),
visible: properties.isEditable
}
]
// remove role from items that are not enabled
// https://github.com/electron/electron/issues/13554
template.forEach((item) => {
if (item.enabled === false) {
item.role = undefined
}
})
return template
}
private createSpellCheckMenuItem(
properties: Electron.ContextMenuParams,
w: Electron.WebContents
): MenuItemConstructorOptions {
const hasText = properties.selectionText.length > 0
return {
id: 'learnSpelling',
label: '&Learn Spelling',
visible: Boolean(properties.isEditable && hasText && properties.misspelledWord),
click: () => {
w.session.addWordToSpellCheckerDictionary(properties.misspelledWord)
}
}
}
private createDictionarySuggestions(
properties: Electron.ContextMenuParams,
w: Electron.WebContents
): MenuItemConstructorOptions[] {
const hasText = properties.selectionText.length > 0
if (!hasText || !properties.misspelledWord) {
return []
}
if (properties.dictionarySuggestions.length === 0) {
return [
{
id: 'dictionarySuggestions',
label: 'No Guesses Found',
visible: true,
enabled: false
}
]
}
return properties.dictionarySuggestions.map((suggestion) => ({
id: 'dictionarySuggestions',
label: suggestion,
visible: Boolean(properties.isEditable && hasText && properties.misspelledWord),
click: (menuItem: Electron.MenuItem) => {
w.replaceMisspelling(menuItem.label)
}
}))
}
}
export const contextMenu = new ContextMenu()