move hotkey validation to main, use log for errors

This commit is contained in:
Alexander Drozdov
2021-09-17 14:45:21 +03:00
parent 5e313206bd
commit 11d0404823
8 changed files with 54 additions and 108 deletions
-7
View File
@@ -222,13 +222,6 @@ export const KeyToElectron = {
Shift: 'Shift'
}
export const forbidden = [
'Ctrl + C', 'Ctrl + V', 'Ctrl + A', 'Ctrl + F', 'Ctrl + Enter',
'Home', 'Delete', 'Enter',
'ArrowUp', 'ArrowRight', 'ArrowLeft'
]
export const forbiddenCtrl = ['C', 'V', 'A', 'F', 'Enter']
export function hotkeyToString (keys: string[], ctrl = false, shift = false, alt = false): string {
if (keys.includes('Ctrl')) ctrl = true
if (keys.includes('Shift')) shift = true
-7
View File
@@ -1,12 +1,5 @@
import type { Config as AppConfig } from '@/ipc/types'
import type { GameConfig } from '@/main/game-config'
export const GET_CONFIG = 'get-config'
export const PUSH_CONFIG = 'push-config'
export interface IpcConfigs {
app: AppConfig
game: GameConfig | null
}
export const PRICE_CHECK_HIDE = 'OVERLAY->MAIN::price-check-hide'
+2 -7
View File
@@ -98,16 +98,11 @@ class MainProcessBinding extends EventTarget {
}
}
getConfig (): ipcEvent.IpcConfigs {
getConfig (): Config {
if (electron) {
return electron.ipcRenderer.sendSync(ipcEvent.GET_CONFIG)
} else {
return {
app: defaultConfig,
game: {
highlightKey: 'Alt'
}
}
return defaultConfig
}
}
+3 -6
View File
@@ -2,19 +2,16 @@ import Store from 'electron-store'
import { dialog, ipcMain, app } from 'electron'
import isDeepEq from 'fast-deep-equal'
import { Config, defaultConfig } from '@/ipc/types'
import { GET_CONFIG, PUSH_CONFIG, CLOSE_SETTINGS_WINDOW, IpcConfigs } from '@/ipc/ipc-event'
import { GET_CONFIG, PUSH_CONFIG, CLOSE_SETTINGS_WINDOW } from '@/ipc/ipc-event'
import { overlayWindow } from './overlay-window'
import { logger } from './logger'
import { LogWatcher } from './LogWatcher'
import { ItemCheckWidget } from '@/web/overlay/interfaces'
import { readConfig as readGameConfig, loadAndCache as loadAndCacheGameCfg } from './game-config'
import { loadAndCache as loadAndCacheGameCfg } from './game-config'
export function setupConfigEvents () {
ipcMain.on(GET_CONFIG, (e) => {
e.returnValue = {
app: config.store,
game: readGameConfig()
} as IpcConfigs
e.returnValue = config.store
})
ipcMain.on(PUSH_CONFIG, (e, cfg: Config) => {
batchUpdateConfig(cfg, false)
+37 -10
View File
@@ -35,8 +35,8 @@ export interface ShortcutAction {
}
}
function shortcutsfromConfig () {
const actions: ShortcutAction[] = []
function shortcutsFromConfig () {
let actions: ShortcutAction[] = []
const priceCheckCfg = priceCheckConfig()
if (priceCheckCfg.hotkey) {
@@ -90,21 +90,48 @@ function shortcutsfromConfig () {
})
}
}
const copyItemShortcut = mergeTwoHotkeys('Ctrl + C', gameConfig?.highlightKey || 'Alt')
if (copyItemShortcut !== 'Ctrl + C') {
actions.push({
shortcut: copyItemShortcut,
action: { type: 'test-only' }
})
}
{
const copyItemShortcut = mergeTwoHotkeys('Ctrl + C', gameConfig?.highlightKey || 'Alt')
if (copyItemShortcut !== 'Ctrl + C') {
actions.push({
shortcut: copyItemShortcut,
action: { type: 'test-only' }
})
const allShortcuts = new Set([
'Ctrl + C', 'Ctrl + V', 'Ctrl + A',
'Ctrl + F',
'Ctrl + Enter',
'Home', 'Delete', 'Enter',
'ArrowUp', 'ArrowRight', 'ArrowLeft',
copyItemShortcut
])
for (const action of actions) {
if (allShortcuts.has(action.shortcut) && action.action.type !== 'test-only') {
logger.error('Hotkey reserved by the game will not be registered.', { source: 'shortcuts', shortcut: action.shortcut })
}
}
actions = actions.filter(action => !allShortcuts.has(action.shortcut))
const duplicates = new Set<string>()
for (const action of actions) {
if (allShortcuts.has(action.shortcut)) {
logger.error('It is not possible to use the same hotkey for multiple actions.', { source: 'shortcuts', shortcut: action.shortcut })
duplicates.add(action.shortcut)
} else {
allShortcuts.add(action.shortcut)
}
}
actions = actions.filter(action => !duplicates.has(action.shortcut))
}
return actions
}
function registerGlobal () {
const toRegister = shortcutsfromConfig()
const toRegister = shortcutsFromConfig()
for (const entry of toRegister) {
const isOk = globalShortcut.register(shortcutToElectron(entry.shortcut), () => {
if (entry.keepModKeys) {
@@ -149,7 +176,7 @@ function registerGlobal () {
})
if (!isOk) {
logger.error('Cannot register shortcut, because it is already registered by another application.', { source: 'shortcuts', shortcut: entry.shortcut })
logger.error('Failed to register a shortcut. It is already registered by another application.', { source: 'shortcuts', shortcut: entry.shortcut })
}
if (entry.action.type === 'test-only') {
+1 -5
View File
@@ -1,18 +1,14 @@
import { reactive } from 'vue'
import { MainProcess } from '@/ipc/main-process-bindings'
import type { Config as ConfigType } from '@/ipc/types'
import type { GameConfig } from '@/main/game-config'
import type { PriceCheckWidget } from './overlay/interfaces'
import { PUSH_CONFIG } from '@/ipc/ipc-event'
class ConfigService {
store: ConfigType
gameConfig: GameConfig | null
constructor () {
const configs = MainProcess.getConfig()
this.store = reactive(configs.app)
this.gameConfig = configs.game
this.store = reactive(MainProcess.getConfig())
MainProcess.addEventListener(PUSH_CONFIG, (e) => {
const config = (e as CustomEvent<ConfigType>).detail
+8 -13
View File
@@ -10,7 +10,7 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useI18n } from 'vue-i18n'
import { KeyToCode, forbidden, hotkeyToString } from '@/ipc/KeyToCode'
import { KeyToCode, hotkeyToString } from '@/ipc/KeyToCode'
export default defineComponent({
emits: ['update:modelValue'],
@@ -19,9 +19,9 @@ export default defineComponent({
type: String,
default: undefined
},
forbidden: {
type: Array,
default: () => forbidden
noModKeys: {
type: Boolean,
default: false
},
required: {
type: Boolean,
@@ -54,17 +54,12 @@ export default defineComponent({
code = 'Cancel'
}
if (
(KeyToCode as Record<string, number>)[code] &&
(ctrlKey ? !props.forbidden.includes('Ctrl') : true) &&
(shiftKey ? !props.forbidden.includes('Shift') : true) &&
(altKey ? !props.forbidden.includes('Alt') : true)
) {
if ((KeyToCode as Record<string, number>)[code]) {
code = hotkeyToString([code], ctrlKey, shiftKey, altKey)
if (!props.forbidden.includes(code)) {
ctx.emit('update:modelValue', code)
if (props.noModKeys && code.includes('+')) {
return
}
ctx.emit('update:modelValue', code)
}
}
}
+3 -53
View File
@@ -10,7 +10,7 @@
<button :class="{ border: configPriceCheck.hotkeyHold === 'Ctrl', 'line-through': configPriceCheck.hotkey === null }" @click="configPriceCheck.hotkeyHold = 'Ctrl'; configPriceCheck.hotkey = null" class="rounded px-1 bg-gray-900 leading-none mr-1">Ctrl</button>
<button :class="{ border: configPriceCheck.hotkeyHold === 'Alt', 'line-through': configPriceCheck.hotkey === null }" @click="configPriceCheck.hotkeyHold = 'Alt'; configPriceCheck.hotkey = null" class="rounded px-1 bg-gray-900 leading-none">Alt</button>
<span class="mx-4">+</span>
<hotkey-input v-model="configPriceCheck.hotkey" :forbidden="['Ctrl','Shift','Alt', ...(configPriceCheck.hotkeyHold === 'Ctrl' ? ['C','V','A','F','Enter'] : [])]" class="w-20" />
<hotkey-input v-model="configPriceCheck.hotkey" class="w-20" no-mod-keys />
</div>
</div>
<div class="text-right mt-2">
@@ -58,39 +58,6 @@
</div>
</div>
</div>
<div class="bg-gray-700 rounded px-2 py-1 mb-2 leading-none">{{ t('Keys reserved by the game') }}</div>
<div class="mb-4">
<div class="flex">
<div class="flex-1">{{ t('Advanced Mod Descriptions') }}</div>
<hotkey-input :model-value="advancedModKey || 'Alt'" class="w-48" />
</div>
<div v-if="!advancedModKey"
class="text-red-400 mt-1 mr-2 ml-auto text-right">
<i class="fas fa-exclamation-triangle"></i> {{ t('Failed to detect key') }}</div>
</div>
<div class="mb-4">
<div class="flex">
<div class="flex-1">{{ t('Copy item text') }}</div>
<span class="text-gray-500 mr-2">{{ t('Normal') }}</span>
<hotkey-input :model-value="copyTextNormal" class="w-48" />
</div>
<div class="text-right mt-2">
<span class="text-gray-500 mr-2">{{ t('Advanced') }}</span>
<hotkey-input :model-value="copyTextAdvanced" class="w-48" />
</div>
</div>
<div class="mb-4">
<div class="flex">
<div class="flex-1">{{ t('Text editing') }}</div>
<hotkey-input model-value="Ctrl+C, Ctrl+V, Ctrl+A" class="w-48" />
</div>
</div>
<div class="mb-8">
<div class="flex">
<div class="flex-1">{{ t('Search in Stash') }}</div>
<hotkey-input model-value="Ctrl + F" class="w-48" />
</div>
</div>
</div>
</template>
@@ -99,7 +66,6 @@ import { defineComponent, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { Config } from '@/web/Config'
import HotkeyInput from './HotkeyInput.vue'
import { mergeTwoHotkeys } from '@/ipc/KeyToCode'
export default defineComponent({
components: { HotkeyInput },
@@ -109,15 +75,7 @@ export default defineComponent({
return {
t,
config: computed(() => Config.store),
configPriceCheck: computed(() => Config.priceCheck),
advancedModKey: computed(() => Config.gameConfig?.highlightKey),
copyTextNormal: computed(() => {
const keys = (Config.gameConfig?.highlightKey || 'Alt').split(' + ')
return (keys.includes('Ctrl') || keys.includes('C')) ? null : 'Ctrl + C'
}),
copyTextAdvanced: computed(() => {
return mergeTwoHotkeys(Config.gameConfig?.highlightKey || 'Alt', 'Ctrl + C')
})
configPriceCheck: computed(() => Config.priceCheck)
}
}
})
@@ -135,15 +93,7 @@ export default defineComponent({
"Map check": "Проверка карты",
"Item info": "Проверка предмета",
"Stash tab scrolling": "Прокрутка вкладок тайника",
"Delve grid": "Сетка \"Спуска\"",
"Keys reserved by the game": "Клавиши зарезервированные игрой",
"Copy item text": "Копировать текст предмета",
"Advanced Mod Descriptions": "Расширенные описания свойств",
"Normal": "Обычный",
"Advanced": "Расширенный",
"Failed to detect key": "Не удалось определить клавишу",
"Text editing": "Редактирование текста",
"Search in Stash": "Поиск в тайнике"
"Delve grid": "Сетка \"Спуска\""
}
}
</i18n>