improvement(shortcut): Support more keyboard shortcuts
This commit is contained in:
parent
a869857fc1
commit
23a2a6b57c
@ -56,6 +56,59 @@ function handleZoom(delta: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat = (
|
||||||
|
shortcut: string | string[]
|
||||||
|
): string => {
|
||||||
|
const accelerator = (() => {
|
||||||
|
if (Array.isArray(shortcut)) {
|
||||||
|
return shortcut
|
||||||
|
} else {
|
||||||
|
return shortcut.split('+').map((key) => key.trim())
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
return accelerator
|
||||||
|
.map((key) => {
|
||||||
|
switch (key) {
|
||||||
|
case 'Control':
|
||||||
|
return 'CommandOrControl'
|
||||||
|
case 'Ctrl':
|
||||||
|
return 'CommandOrControl'
|
||||||
|
case 'ArrowUp':
|
||||||
|
return 'Up'
|
||||||
|
case 'ArrowDown':
|
||||||
|
return 'Down'
|
||||||
|
case 'ArrowLeft':
|
||||||
|
return 'Left'
|
||||||
|
case 'ArrowRight':
|
||||||
|
return 'Right'
|
||||||
|
case 'AltGraph':
|
||||||
|
return 'Alt'
|
||||||
|
case 'Slash':
|
||||||
|
return '/'
|
||||||
|
case 'Semicolon':
|
||||||
|
return ';'
|
||||||
|
case 'BracketLeft':
|
||||||
|
return '['
|
||||||
|
case 'BracketRight':
|
||||||
|
return ']'
|
||||||
|
case 'Backslash':
|
||||||
|
return '\\'
|
||||||
|
case 'Quote':
|
||||||
|
return "'"
|
||||||
|
case 'Comma':
|
||||||
|
return ','
|
||||||
|
case 'Minus':
|
||||||
|
return '-'
|
||||||
|
case 'Equal':
|
||||||
|
return '='
|
||||||
|
default:
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join('+')
|
||||||
|
}
|
||||||
|
|
||||||
export function registerShortcuts(window: BrowserWindow) {
|
export function registerShortcuts(window: BrowserWindow) {
|
||||||
window.webContents.setZoomFactor(configManager.getZoomFactor())
|
window.webContents.setZoomFactor(configManager.getZoomFactor())
|
||||||
|
|
||||||
@ -104,7 +157,10 @@ export function registerShortcuts(window: BrowserWindow) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shortcut.enabled) {
|
if (shortcut.enabled) {
|
||||||
globalShortcut.register(formatShortcutKey(shortcut.shortcut), () => handler(window))
|
const accelerator = convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat(
|
||||||
|
shortcut.shortcut
|
||||||
|
)
|
||||||
|
globalShortcut.register(accelerator, () => handler(window))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error(`[ShortcutService] Failed to register shortcut ${shortcut.key}`)
|
Logger.error(`[ShortcutService] Failed to register shortcut ${shortcut.key}`)
|
||||||
@ -120,12 +176,16 @@ export function registerShortcuts(window: BrowserWindow) {
|
|||||||
|
|
||||||
if (showAppAccelerator) {
|
if (showAppAccelerator) {
|
||||||
const handler = getShortcutHandler({ key: 'show_app' } as Shortcut)
|
const handler = getShortcutHandler({ key: 'show_app' } as Shortcut)
|
||||||
handler && globalShortcut.register(showAppAccelerator, () => handler(window))
|
const accelerator =
|
||||||
|
convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat(showAppAccelerator)
|
||||||
|
handler && globalShortcut.register(accelerator, () => handler(window))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showMiniWindowAccelerator) {
|
if (showMiniWindowAccelerator) {
|
||||||
const handler = getShortcutHandler({ key: 'mini_window' } as Shortcut)
|
const handler = getShortcutHandler({ key: 'mini_window' } as Shortcut)
|
||||||
handler && globalShortcut.register(showMiniWindowAccelerator, () => handler(window))
|
const accelerator =
|
||||||
|
convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat(showMiniWindowAccelerator)
|
||||||
|
handler && globalShortcut.register(accelerator, () => handler(window))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error('[ShortcutService] Failed to unregister shortcuts')
|
Logger.error('[ShortcutService] Failed to unregister shortcuts')
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { initialState, resetShortcuts, toggleShortcut, updateShortcut } from '@r
|
|||||||
import { Shortcut } from '@renderer/types'
|
import { Shortcut } from '@renderer/types'
|
||||||
import { Button, Input, InputRef, Switch, Table as AntTable, Tooltip } from 'antd'
|
import { Button, Input, InputRef, Switch, Table as AntTable, Tooltip } from 'antd'
|
||||||
import type { ColumnsType } from 'antd/es/table'
|
import type { ColumnsType } from 'antd/es/table'
|
||||||
import { FC, useRef, useState } from 'react'
|
import React, { FC, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
@ -92,8 +92,32 @@ const ShortcutSettings: FC = () => {
|
|||||||
return isMac ? '⇧' : 'Shift'
|
return isMac ? '⇧' : 'Shift'
|
||||||
case 'CommandOrControl':
|
case 'CommandOrControl':
|
||||||
return isMac ? '⌘' : 'Ctrl'
|
return isMac ? '⌘' : 'Ctrl'
|
||||||
case ' ':
|
case 'ArrowUp':
|
||||||
return 'Space'
|
return '↑'
|
||||||
|
case 'ArrowDown':
|
||||||
|
return '↓'
|
||||||
|
case 'ArrowLeft':
|
||||||
|
return '←'
|
||||||
|
case 'ArrowRight':
|
||||||
|
return '→'
|
||||||
|
case 'Slash':
|
||||||
|
return '/'
|
||||||
|
case 'Semicolon':
|
||||||
|
return ';'
|
||||||
|
case 'BracketLeft':
|
||||||
|
return '['
|
||||||
|
case 'BracketRight':
|
||||||
|
return ']'
|
||||||
|
case 'Backslash':
|
||||||
|
return '\\'
|
||||||
|
case 'Quote':
|
||||||
|
return "'"
|
||||||
|
case 'Comma':
|
||||||
|
return ','
|
||||||
|
case 'Minus':
|
||||||
|
return '-'
|
||||||
|
case 'Equal':
|
||||||
|
return '='
|
||||||
default:
|
default:
|
||||||
return key.charAt(0).toUpperCase() + key.slice(1)
|
return key.charAt(0).toUpperCase() + key.slice(1)
|
||||||
}
|
}
|
||||||
@ -101,13 +125,61 @@ const ShortcutSettings: FC = () => {
|
|||||||
.join(' + ')
|
.join(' + ')
|
||||||
}
|
}
|
||||||
|
|
||||||
const usableEndKeys = (key: string): string | null => {
|
const usableEndKeys = (event: React.KeyboardEvent): string | null => {
|
||||||
if (key.length === 1) {
|
const { code } = event
|
||||||
return key.toUpperCase()
|
// No lock keys
|
||||||
}
|
// Among the commonly used keys, not including: Escape, NumpadMultiply, NumpadDivide, NumpadSubtract, NumpadAdd, NumpadDecimal
|
||||||
switch (key) {
|
// The react-hotkeys-hook library does not differentiate between `Digit` and `Numpad`
|
||||||
|
switch (code) {
|
||||||
|
case 'KeyA':
|
||||||
|
case 'KeyB':
|
||||||
|
case 'KeyC':
|
||||||
|
case 'KeyD':
|
||||||
|
case 'KeyE':
|
||||||
|
case 'KeyF':
|
||||||
|
case 'KeyG':
|
||||||
|
case 'KeyH':
|
||||||
|
case 'KeyI':
|
||||||
|
case 'KeyJ':
|
||||||
|
case 'KeyK':
|
||||||
|
case 'KeyL':
|
||||||
|
case 'KeyM':
|
||||||
|
case 'KeyN':
|
||||||
|
case 'KeyO':
|
||||||
|
case 'KeyP':
|
||||||
|
case 'KeyQ':
|
||||||
|
case 'KeyR':
|
||||||
|
case 'KeyS':
|
||||||
|
case 'KeyT':
|
||||||
|
case 'KeyU':
|
||||||
|
case 'KeyV':
|
||||||
|
case 'KeyW':
|
||||||
|
case 'KeyX':
|
||||||
|
case 'KeyY':
|
||||||
|
case 'KeyZ':
|
||||||
|
case 'Digit0':
|
||||||
|
case 'Digit1':
|
||||||
|
case 'Digit2':
|
||||||
|
case 'Digit3':
|
||||||
|
case 'Digit4':
|
||||||
|
case 'Digit5':
|
||||||
|
case 'Digit6':
|
||||||
|
case 'Digit7':
|
||||||
|
case 'Digit8':
|
||||||
|
case 'Digit9':
|
||||||
|
case 'Numpad0':
|
||||||
|
case 'Numpad1':
|
||||||
|
case 'Numpad2':
|
||||||
|
case 'Numpad3':
|
||||||
|
case 'Numpad4':
|
||||||
|
case 'Numpad5':
|
||||||
|
case 'Numpad6':
|
||||||
|
case 'Numpad7':
|
||||||
|
case 'Numpad8':
|
||||||
|
case 'Numpad9':
|
||||||
|
return code.slice(-1)
|
||||||
|
case 'Space':
|
||||||
case 'Enter':
|
case 'Enter':
|
||||||
case 'Escape':
|
|
||||||
case 'Backspace':
|
case 'Backspace':
|
||||||
case 'Tab':
|
case 'Tab':
|
||||||
case 'Delete':
|
case 'Delete':
|
||||||
@ -139,10 +211,24 @@ const ShortcutSettings: FC = () => {
|
|||||||
case 'F17':
|
case 'F17':
|
||||||
case 'F18':
|
case 'F18':
|
||||||
case 'F19':
|
case 'F19':
|
||||||
case 'F20':
|
return code
|
||||||
return key
|
case 'Backquote':
|
||||||
case ' ':
|
return '`'
|
||||||
return 'Space'
|
case 'Period':
|
||||||
|
return '.'
|
||||||
|
case 'NumpadEnter':
|
||||||
|
return 'Enter'
|
||||||
|
// The react-hotkeys-hook library does not handle the symbol strings for the following keys
|
||||||
|
case 'Slash':
|
||||||
|
case 'Semicolon':
|
||||||
|
case 'BracketLeft':
|
||||||
|
case 'BracketRight':
|
||||||
|
case 'Backslash':
|
||||||
|
case 'Quote':
|
||||||
|
case 'Comma':
|
||||||
|
case 'Minus':
|
||||||
|
case 'Equal':
|
||||||
|
return code
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -156,15 +242,9 @@ const ShortcutSettings: FC = () => {
|
|||||||
if (e.metaKey) keys.push('Command')
|
if (e.metaKey) keys.push('Command')
|
||||||
if (e.altKey) keys.push('Alt')
|
if (e.altKey) keys.push('Alt')
|
||||||
if (e.shiftKey) keys.push('Shift')
|
if (e.shiftKey) keys.push('Shift')
|
||||||
|
const endKey = usableEndKeys(e)
|
||||||
const key = e.key
|
if (endKey) {
|
||||||
|
keys.push(endKey)
|
||||||
if (key.length === 1 && !['Control', 'Alt', 'Shift', 'Meta'].includes(key)) {
|
|
||||||
if (key === ' ') {
|
|
||||||
keys.push('Space')
|
|
||||||
} else {
|
|
||||||
keys.push(key.toUpperCase())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValidShortcut(keys)) {
|
if (!isValidShortcut(keys)) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user