230 lines
6.5 KiB
TypeScript
230 lines
6.5 KiB
TypeScript
import { Shortcut } from '@types'
|
|
import { BrowserWindow, globalShortcut } from 'electron'
|
|
import Logger from 'electron-log'
|
|
|
|
import { configManager } from './ConfigManager'
|
|
import { windowService } from './WindowService'
|
|
|
|
let showAppAccelerator: string | null = null
|
|
let showMiniWindowAccelerator: string | null = null
|
|
|
|
// store the focus and blur handlers for each window to unregister them later
|
|
const windowOnHandlers = new Map<BrowserWindow, { onFocusHandler: () => void; onBlurHandler: () => void }>()
|
|
|
|
function getShortcutHandler(shortcut: Shortcut) {
|
|
switch (shortcut.key) {
|
|
case 'zoom_in':
|
|
return (window: BrowserWindow) => handleZoom(0.1)(window)
|
|
case 'zoom_out':
|
|
return (window: BrowserWindow) => handleZoom(-0.1)(window)
|
|
case 'zoom_reset':
|
|
return (window: BrowserWindow) => {
|
|
window.webContents.setZoomFactor(1)
|
|
configManager.setZoomFactor(1)
|
|
}
|
|
case 'show_app':
|
|
return (window: BrowserWindow) => {
|
|
if (window.isVisible()) {
|
|
if (window.isFocused()) {
|
|
window.hide()
|
|
} else {
|
|
window.focus()
|
|
}
|
|
} else {
|
|
window.show()
|
|
window.focus()
|
|
}
|
|
}
|
|
case 'mini_window':
|
|
return () => {
|
|
windowService.toggleMiniWindow()
|
|
}
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
|
|
function formatShortcutKey(shortcut: string[]): string {
|
|
return shortcut.join('+')
|
|
}
|
|
|
|
function handleZoom(delta: number) {
|
|
return (window: BrowserWindow) => {
|
|
const currentZoom = configManager.getZoomFactor()
|
|
const newZoom = Number((currentZoom + delta).toFixed(1))
|
|
if (newZoom >= 0.1 && newZoom <= 5.0) {
|
|
window.webContents.setZoomFactor(newZoom)
|
|
configManager.setZoomFactor(newZoom)
|
|
}
|
|
}
|
|
}
|
|
|
|
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 'Command':
|
|
return 'CommandOrControl'
|
|
case 'Control':
|
|
return 'Control'
|
|
case 'Ctrl':
|
|
return 'Control'
|
|
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) {
|
|
const register = () => {
|
|
if (window.isDestroyed()) return
|
|
|
|
const shortcuts = configManager.getShortcuts()
|
|
if (!shortcuts) return
|
|
|
|
shortcuts.forEach((shortcut) => {
|
|
try {
|
|
if (shortcut.shortcut.length === 0) {
|
|
return
|
|
}
|
|
|
|
//if not enabled, exit early from the process.
|
|
if (!shortcut.enabled) {
|
|
return
|
|
}
|
|
|
|
const handler = getShortcutHandler(shortcut)
|
|
if (!handler) {
|
|
return
|
|
}
|
|
|
|
switch (shortcut.key) {
|
|
case 'show_app':
|
|
showAppAccelerator = formatShortcutKey(shortcut.shortcut)
|
|
break
|
|
|
|
case 'mini_window':
|
|
//available only when QuickAssistant enabled
|
|
if (!configManager.getEnableQuickAssistant()) {
|
|
return
|
|
}
|
|
showMiniWindowAccelerator = formatShortcutKey(shortcut.shortcut)
|
|
break
|
|
|
|
//the following ZOOMs will register shortcuts seperately, so will return
|
|
case 'zoom_in':
|
|
globalShortcut.register('CommandOrControl+=', () => handler(window))
|
|
globalShortcut.register('CommandOrControl+numadd', () => handler(window))
|
|
return
|
|
|
|
case 'zoom_out':
|
|
globalShortcut.register('CommandOrControl+-', () => handler(window))
|
|
globalShortcut.register('CommandOrControl+numsub', () => handler(window))
|
|
return
|
|
|
|
case 'zoom_reset':
|
|
globalShortcut.register('CommandOrControl+0', () => handler(window))
|
|
return
|
|
}
|
|
|
|
const accelerator = convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat(
|
|
shortcut.shortcut
|
|
)
|
|
|
|
globalShortcut.register(accelerator, () => handler(window))
|
|
} catch (error) {
|
|
Logger.error(`[ShortcutService] Failed to register shortcut ${shortcut.key}`)
|
|
}
|
|
})
|
|
}
|
|
|
|
const unregister = () => {
|
|
if (window.isDestroyed()) return
|
|
|
|
try {
|
|
globalShortcut.unregisterAll()
|
|
|
|
if (showAppAccelerator) {
|
|
const handler = getShortcutHandler({ key: 'show_app' } as Shortcut)
|
|
const accelerator =
|
|
convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat(showAppAccelerator)
|
|
handler && globalShortcut.register(accelerator, () => handler(window))
|
|
}
|
|
|
|
if (showMiniWindowAccelerator) {
|
|
const handler = getShortcutHandler({ key: 'mini_window' } as Shortcut)
|
|
const accelerator =
|
|
convertShortcutRecordedByKeyboardEventKeyValueToElectronGlobalShortcutFormat(showMiniWindowAccelerator)
|
|
handler && globalShortcut.register(accelerator, () => handler(window))
|
|
}
|
|
} catch (error) {
|
|
Logger.error('[ShortcutService] Failed to unregister shortcuts')
|
|
}
|
|
}
|
|
|
|
// only register the event handlers once
|
|
if (undefined === windowOnHandlers.get(window)) {
|
|
window.on('focus', register)
|
|
window.on('blur', unregister)
|
|
windowOnHandlers.set(window, { onFocusHandler: register, onBlurHandler: unregister })
|
|
}
|
|
|
|
if (!window.isDestroyed() && window.isFocused()) {
|
|
register()
|
|
}
|
|
}
|
|
|
|
export function unregisterAllShortcuts() {
|
|
try {
|
|
showAppAccelerator = null
|
|
showMiniWindowAccelerator = null
|
|
windowOnHandlers.forEach((handlers, window) => {
|
|
window.off('focus', handlers.onFocusHandler)
|
|
window.off('blur', handlers.onBlurHandler)
|
|
})
|
|
windowOnHandlers.clear()
|
|
globalShortcut.unregisterAll()
|
|
} catch (error) {
|
|
Logger.error('[ShortcutService] Failed to unregister all shortcuts')
|
|
}
|
|
}
|