mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 06:30:10 +08:00
feat(SelectionAssistant): shortcut key to toggle on/off (#6983)
* feat: add toggle selection assistant functionality and corresponding shortcuts - Implemented toggleEnabled method in SelectionService to manage the selection assistant state. - Registered new shortcut for toggling the selection assistant in ShortcutService. - Updated StoreSyncService to sync the selection assistant state across renderer windows. - Added localization for the toggle selection assistant feature in multiple languages. - Adjusted ShortcutSettings to conditionally display the toggle selection assistant shortcut based on the platform. - Included toggle selection assistant in the initial state of shortcuts in the store. * fix: shortcut key * fix: accelerator name
This commit is contained in:
parent
26d018b1b7
commit
f6a935f14f
@ -14,6 +14,7 @@ import type {
|
||||
|
||||
import type { ActionItem } from '../../renderer/src/types/selectionTypes'
|
||||
import { ConfigKeys, configManager } from './ConfigManager'
|
||||
import storeSyncService from './StoreSyncService'
|
||||
|
||||
let SelectionHook: SelectionHookConstructor | null = null
|
||||
try {
|
||||
@ -334,6 +335,20 @@ export class SelectionService {
|
||||
this.logInfo('SelectionService Quitted')
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the enabled state of the selection service
|
||||
* Will sync the new enabled store to all renderer windows
|
||||
*/
|
||||
public toggleEnabled(enabled: boolean | undefined = undefined) {
|
||||
if (!this.selectionHook) return
|
||||
|
||||
const newEnabled = enabled === undefined ? !configManager.getSelectionAssistantEnabled() : enabled
|
||||
|
||||
configManager.setSelectionAssistantEnabled(newEnabled)
|
||||
|
||||
//sync the new enabled state to all renderer windows
|
||||
storeSyncService.syncToRenderer('selectionStore/setSelectionEnabled', newEnabled)
|
||||
}
|
||||
/**
|
||||
* Create and configure the toolbar window
|
||||
* Sets up window properties, event handlers, and loads the toolbar UI
|
||||
|
||||
@ -4,10 +4,15 @@ import { BrowserWindow, globalShortcut } from 'electron'
|
||||
import Logger from 'electron-log'
|
||||
|
||||
import { configManager } from './ConfigManager'
|
||||
import selectionService from './SelectionService'
|
||||
import { windowService } from './WindowService'
|
||||
|
||||
let showAppAccelerator: string | null = null
|
||||
let showMiniWindowAccelerator: string | null = null
|
||||
let selectionAssistantToggleAccelerator: string | null = null
|
||||
|
||||
//indicate if the shortcuts are registered on app boot time
|
||||
let isRegisterOnBoot = true
|
||||
|
||||
// store the focus and blur handlers for each window to unregister them later
|
||||
const windowOnHandlers = new Map<BrowserWindow, { onFocusHandler: () => void; onBlurHandler: () => void }>()
|
||||
@ -28,6 +33,12 @@ function getShortcutHandler(shortcut: Shortcut) {
|
||||
return () => {
|
||||
windowService.toggleMiniWindow()
|
||||
}
|
||||
case 'selection_assistant_toggle':
|
||||
return () => {
|
||||
if (selectionService) {
|
||||
selectionService.toggleEnabled()
|
||||
}
|
||||
}
|
||||
default:
|
||||
return null
|
||||
}
|
||||
@ -93,11 +104,14 @@ const convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutForm
|
||||
}
|
||||
|
||||
export function registerShortcuts(window: BrowserWindow) {
|
||||
window.once('ready-to-show', () => {
|
||||
if (configManager.getLaunchToTray()) {
|
||||
registerOnlyUniversalShortcuts()
|
||||
}
|
||||
})
|
||||
if (isRegisterOnBoot) {
|
||||
window.once('ready-to-show', () => {
|
||||
if (configManager.getLaunchToTray()) {
|
||||
registerOnlyUniversalShortcuts()
|
||||
}
|
||||
})
|
||||
isRegisterOnBoot = false
|
||||
}
|
||||
|
||||
//only for clearer code
|
||||
const registerOnlyUniversalShortcuts = () => {
|
||||
@ -124,7 +138,10 @@ export function registerShortcuts(window: BrowserWindow) {
|
||||
}
|
||||
|
||||
// only register universal shortcuts when needed
|
||||
if (onlyUniversalShortcuts && !['show_app', 'mini_window'].includes(shortcut.key)) {
|
||||
if (
|
||||
onlyUniversalShortcuts &&
|
||||
!['show_app', 'mini_window', 'selection_assistant_toggle'].includes(shortcut.key)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -146,6 +163,10 @@ export function registerShortcuts(window: BrowserWindow) {
|
||||
showMiniWindowAccelerator = formatShortcutKey(shortcut.shortcut)
|
||||
break
|
||||
|
||||
case 'selection_assistant_toggle':
|
||||
selectionAssistantToggleAccelerator = formatShortcutKey(shortcut.shortcut)
|
||||
break
|
||||
|
||||
//the following ZOOMs will register shortcuts seperately, so will return
|
||||
case 'zoom_in':
|
||||
globalShortcut.register('CommandOrControl+=', () => handler(window))
|
||||
@ -192,6 +213,14 @@ export function registerShortcuts(window: BrowserWindow) {
|
||||
convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat(showMiniWindowAccelerator)
|
||||
handler && globalShortcut.register(accelerator, () => handler(window))
|
||||
}
|
||||
|
||||
if (selectionAssistantToggleAccelerator) {
|
||||
const handler = getShortcutHandler({ key: 'selection_assistant_toggle' } as Shortcut)
|
||||
const accelerator = convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat(
|
||||
selectionAssistantToggleAccelerator
|
||||
)
|
||||
handler && globalShortcut.register(accelerator, () => handler(window))
|
||||
}
|
||||
} catch (error) {
|
||||
Logger.error('[ShortcutService] Failed to unregister shortcuts')
|
||||
}
|
||||
@ -217,6 +246,7 @@ export function unregisterAllShortcuts() {
|
||||
try {
|
||||
showAppAccelerator = null
|
||||
showMiniWindowAccelerator = null
|
||||
selectionAssistantToggleAccelerator = null
|
||||
windowOnHandlers.forEach((handlers, window) => {
|
||||
window.off('focus', handlers.onFocusHandler)
|
||||
window.off('blur', handlers.onBlurHandler)
|
||||
|
||||
@ -49,6 +49,23 @@ export class StoreSyncService {
|
||||
this.windowIds = this.windowIds.filter((id) => id !== windowId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync an action to all renderer windows
|
||||
* @param type Action type, like 'settings/setTray'
|
||||
* @param payload Action payload
|
||||
*
|
||||
* NOTICE: DO NOT use directly in ConfigManager, may cause infinite sync loop
|
||||
*/
|
||||
public syncToRenderer(type: string, payload: any): void {
|
||||
const action: StoreSyncAction = {
|
||||
type,
|
||||
payload
|
||||
}
|
||||
|
||||
//-1 means the action is from the main process, will be broadcast to all windows
|
||||
this.broadcastToOtherWindows(-1, action)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register IPC handlers for store sync communication
|
||||
* Handles window subscription, unsubscription and action broadcasting
|
||||
|
||||
@ -1701,6 +1701,7 @@
|
||||
"exit_fullscreen": "Exit Fullscreen",
|
||||
"key": "Key",
|
||||
"mini_window": "Quick Assistant",
|
||||
"selection_assistant_toggle": "Toggle Selection Assistant",
|
||||
"new_topic": "New Topic",
|
||||
"press_shortcut": "Press Shortcut",
|
||||
"reset_defaults": "Reset Defaults",
|
||||
|
||||
@ -1689,6 +1689,7 @@
|
||||
"exit_fullscreen": "フルスクリーンを終了",
|
||||
"key": "キー",
|
||||
"mini_window": "クイックアシスタント",
|
||||
"selection_assistant_toggle": "選択アシスタントを切り替え",
|
||||
"new_topic": "新しいトピック",
|
||||
"press_shortcut": "ショートカットを押す",
|
||||
"reset_defaults": "デフォルトのショートカットをリセット",
|
||||
|
||||
@ -1689,6 +1689,7 @@
|
||||
"exit_fullscreen": "Выйти из полноэкранного режима",
|
||||
"key": "Клавиша",
|
||||
"mini_window": "Быстрый помощник",
|
||||
"selection_assistant_toggle": "Переключить помощник выделения",
|
||||
"new_topic": "Новый топик",
|
||||
"press_shortcut": "Нажмите сочетание клавиш",
|
||||
"reset_defaults": "Сбросить настройки по умолчанию",
|
||||
|
||||
@ -1701,6 +1701,7 @@
|
||||
"exit_fullscreen": "退出全屏",
|
||||
"key": "按键",
|
||||
"mini_window": "快捷助手",
|
||||
"selection_assistant_toggle": "开关划词助手",
|
||||
"new_topic": "新建话题",
|
||||
"press_shortcut": "按下快捷键",
|
||||
"reset_defaults": "重置默认快捷键",
|
||||
|
||||
@ -1691,6 +1691,7 @@
|
||||
"copy_last_message": "複製上一則訊息",
|
||||
"key": "按鍵",
|
||||
"mini_window": "快捷助手",
|
||||
"selection_assistant_toggle": "開關劃詞助手",
|
||||
"new_topic": "新增話題",
|
||||
"press_shortcut": "按下快捷鍵",
|
||||
"reset_defaults": "重設預設快捷鍵",
|
||||
|
||||
@ -18,10 +18,17 @@ const ShortcutSettings: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
const dispatch = useAppDispatch()
|
||||
const { shortcuts } = useShortcuts()
|
||||
const { shortcuts: originalShortcuts } = useShortcuts()
|
||||
const inputRefs = useRef<Record<string, InputRef>>({})
|
||||
const [editingKey, setEditingKey] = useState<string | null>(null)
|
||||
|
||||
//TODO: if shortcut is not available on all the platforms, block the shortcut here
|
||||
let shortcuts = originalShortcuts
|
||||
if (!isWindows) {
|
||||
//Selection Assistant only available on Windows now
|
||||
shortcuts = shortcuts.filter((s) => s.key !== 'selection_assistant_toggle')
|
||||
}
|
||||
|
||||
const handleClear = (record: Shortcut) => {
|
||||
dispatch(
|
||||
updateShortcut({
|
||||
|
||||
@ -1508,6 +1508,24 @@ const migrateConfig = {
|
||||
state.llm.translateModel = SYSTEM_MODELS.defaultModel[2]
|
||||
}
|
||||
|
||||
// Add selection_assistant_toggle shortcut after mini_window if it doesn't exist
|
||||
if (state.shortcuts) {
|
||||
const miniWindowIndex = state.shortcuts.shortcuts.findIndex((shortcut) => shortcut.key === 'mini_window')
|
||||
const hasSelectionAssistant = state.shortcuts.shortcuts.some(
|
||||
(shortcut) => shortcut.key === 'selection_assistant_toggle'
|
||||
)
|
||||
|
||||
if (miniWindowIndex !== -1 && !hasSelectionAssistant) {
|
||||
state.shortcuts.shortcuts.splice(miniWindowIndex + 1, 0, {
|
||||
key: 'selection_assistant_toggle',
|
||||
shortcut: [],
|
||||
editable: true,
|
||||
enabled: false,
|
||||
system: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
} catch (error) {
|
||||
return state
|
||||
|
||||
@ -31,6 +31,14 @@ const initialState: ShortcutsState = {
|
||||
enabled: false,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
//enable/disable selection assistant
|
||||
key: 'selection_assistant_toggle',
|
||||
shortcut: [],
|
||||
editable: true,
|
||||
enabled: false,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
key: 'new_topic',
|
||||
shortcut: [isMac ? 'Command' : 'Ctrl', 'N'],
|
||||
@ -45,6 +53,7 @@ const initialState: ShortcutsState = {
|
||||
enabled: true,
|
||||
system: false
|
||||
},
|
||||
|
||||
{
|
||||
key: 'toggle_show_topics',
|
||||
shortcut: [isMac ? 'Command' : 'Ctrl', ']'],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user