mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2026-09-27 15:15:48 +00:00
move hotkey validation to main, use log for errors
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user