mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2025-12-08 09:05:44 +00:00
Shortcuts for Stopwatch, closes #368
This commit is contained in:
@@ -18,7 +18,8 @@ export type IpcEvent =
|
||||
IpcOpenCraftOfExile |
|
||||
IpcImportFile |
|
||||
IpcToggleDelveGrid |
|
||||
IpcClientLog
|
||||
IpcClientLog |
|
||||
IpcStopwatchAction
|
||||
|
||||
export type IpcEventPayload<Name extends IpcEvent['name'], T extends IpcEvent = IpcEvent> =
|
||||
T extends { name: Name } ? T['payload'] : never
|
||||
@@ -103,6 +104,12 @@ export type IpcClientLog =
|
||||
lines: string[]
|
||||
}>
|
||||
|
||||
export type IpcStopwatchAction =
|
||||
Event<'MAIN->OVERLAY::stopwatch', {
|
||||
wmId: number
|
||||
type: 'start-stop' | 'reset'
|
||||
}>
|
||||
|
||||
interface Event<TName extends string, TPayload = undefined> {
|
||||
name: TName
|
||||
payload: TPayload
|
||||
|
||||
@@ -57,6 +57,8 @@ export interface ItemCheckWidget extends Widget {
|
||||
|
||||
export interface StopwatchWidget extends Widget {
|
||||
anchor: Anchor
|
||||
toggleKey: string | null
|
||||
resetKey: string | null
|
||||
}
|
||||
|
||||
export interface StashSearchWidget extends Widget {
|
||||
|
||||
@@ -8,8 +8,8 @@ import { config } from './config'
|
||||
import { PoeWindow } from './PoeWindow'
|
||||
import { logger } from './logger'
|
||||
import { toggleOverlayState, assertOverlayActive, assertPoEActive, overlayOnEvent, overlaySendEvent } from './overlay-window'
|
||||
import * as ipc from '../../ipc/ipc-event'
|
||||
import { StashSearchWidget } from '../../ipc/widgets'
|
||||
import type * as ipc from '../../ipc/ipc-event'
|
||||
import type * as widget from '../../ipc/widgets'
|
||||
import { typeInChat } from './game-chat'
|
||||
import { gameConfig } from './game-config'
|
||||
import { restoreClipboard } from './clipboard-saver'
|
||||
@@ -29,10 +29,12 @@ export interface ShortcutAction {
|
||||
'price-check-locked'
|
||||
)
|
||||
focusOverlay?: boolean
|
||||
} | {
|
||||
} | ({
|
||||
type: 'trigger-event'
|
||||
eventName: ipc.IpcToggleDelveGrid['name']
|
||||
} | {
|
||||
} & (
|
||||
ShortcutActionTriggerEvent<ipc.IpcToggleDelveGrid['name']> |
|
||||
ShortcutActionTriggerEvent<ipc.IpcStopwatchAction['name']>
|
||||
)) | {
|
||||
type: 'stash-search'
|
||||
text: string
|
||||
} | {
|
||||
@@ -46,6 +48,11 @@ export interface ShortcutAction {
|
||||
}
|
||||
}
|
||||
|
||||
interface ShortcutActionTriggerEvent<Name extends ipc.IpcEvent['name']> {
|
||||
eventName: Name
|
||||
payload: ipc.IpcEventPayload<Name>
|
||||
}
|
||||
|
||||
function shortcutsFromConfig () {
|
||||
let actions: ShortcutAction[] = []
|
||||
|
||||
@@ -89,7 +96,7 @@ function shortcutsFromConfig () {
|
||||
if (config.get('delveGridKey')) {
|
||||
actions.push({
|
||||
shortcut: config.get('delveGridKey')!,
|
||||
action: { type: 'trigger-event', eventName: 'MAIN->OVERLAY::delve-grid' },
|
||||
action: { type: 'trigger-event', eventName: 'MAIN->OVERLAY::delve-grid', payload: undefined },
|
||||
keepModKeys: true
|
||||
})
|
||||
}
|
||||
@@ -110,7 +117,7 @@ function shortcutsFromConfig () {
|
||||
}
|
||||
for (const widget of config.get('widgets')) {
|
||||
if (widget.wmType === 'stash-search') {
|
||||
const stashSearch = widget as StashSearchWidget
|
||||
const stashSearch = widget as widget.StashSearchWidget
|
||||
for (const entry of stashSearch.entries) {
|
||||
if (entry.hotkey) {
|
||||
actions.push({
|
||||
@@ -119,6 +126,30 @@ function shortcutsFromConfig () {
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (widget.wmType === 'timer') {
|
||||
const stopwatch = widget as widget.StopwatchWidget
|
||||
if (stopwatch.toggleKey) {
|
||||
actions.push({
|
||||
shortcut: stopwatch.toggleKey,
|
||||
keepModKeys: true,
|
||||
action: {
|
||||
type: 'trigger-event',
|
||||
eventName: 'MAIN->OVERLAY::stopwatch',
|
||||
payload: { wmId: widget.wmId, type: 'start-stop' }
|
||||
}
|
||||
})
|
||||
}
|
||||
if (stopwatch.resetKey) {
|
||||
actions.push({
|
||||
shortcut: stopwatch.resetKey,
|
||||
keepModKeys: true,
|
||||
action: {
|
||||
type: 'trigger-event',
|
||||
eventName: 'MAIN->OVERLAY::stopwatch',
|
||||
payload: { wmId: widget.wmId, type: 'reset' }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +203,7 @@ function registerGlobal () {
|
||||
} else if (entry.action.type === 'paste-in-chat') {
|
||||
typeInChat(entry.action.text, entry.action.send)
|
||||
} else if (entry.action.type === 'trigger-event') {
|
||||
overlaySendEvent({ name: entry.action.eventName, payload: undefined })
|
||||
overlaySendEvent({ name: entry.action.eventName, payload: entry.action.payload } as ipc.IpcEvent)
|
||||
} else if (entry.action.type === 'stash-search') {
|
||||
stashSearch(entry.action.text)
|
||||
} else if (entry.action.type === 'copy-item') {
|
||||
|
||||
@@ -33,10 +33,12 @@ class MainProcessBinding {
|
||||
onEvent<Name extends IpcEvent['name']> (
|
||||
name: Name,
|
||||
cb: (payload: IpcEventPayload<Name>) => void
|
||||
) {
|
||||
): AbortController {
|
||||
const controller = new AbortController()
|
||||
this.evBus.addEventListener(name, (e) => {
|
||||
cb((e as CustomEvent<IpcEventPayload<Name>>).detail)
|
||||
})
|
||||
}, { signal: controller.signal })
|
||||
return controller
|
||||
}
|
||||
|
||||
closeOverlay () {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<widget :config="config" move-handles="center" v-slot="{ isMoving }" readonly :hideable="false">
|
||||
<widget :config="config" move-handles="center" v-slot="{ isMoving }" :inline-edit="false" :hideable="false">
|
||||
<div :class="$style.wrapper">
|
||||
<div :class="$style.timer">
|
||||
<span>{{ formatted.h }}:{{ formatted.m }}:</span><span>{{ formatted.s }}</span>
|
||||
@@ -8,7 +8,7 @@
|
||||
<div v-if="!isMoving" :class="$style.controls">
|
||||
<button v-if="!isRunning" @click="start" :class="$style.button"><i class="fas fa-play"></i></button>
|
||||
<button v-else @click="stop" :class="$style.button"><i class="fas fa-pause"></i></button>
|
||||
<button @click="restart" :class="$style.button"><i class="fas fa-redo"></i></button>
|
||||
<button @click="reset" :class="$style.button"><i class="fas fa-redo"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</widget>
|
||||
@@ -18,6 +18,7 @@
|
||||
import { defineComponent, PropType, inject, ref, onUnmounted, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import Widget from './Widget.vue'
|
||||
import { MainProcess } from '@/web/background/IPC'
|
||||
import { Duration } from 'luxon'
|
||||
import { WidgetManager, StopwatchWidget } from './interfaces'
|
||||
|
||||
@@ -38,10 +39,25 @@ export default defineComponent({
|
||||
x: (Math.random() * (60 - 40) + 40),
|
||||
y: (Math.random() * (60 - 40) + 40)
|
||||
}
|
||||
props.config.toggleKey = null
|
||||
props.config.resetKey = null
|
||||
wm.show(props.config.wmId)
|
||||
}
|
||||
props.config.wmFlags = ['invisible-on-blur']
|
||||
|
||||
const hotkeyController = MainProcess.onEvent('MAIN->OVERLAY::stopwatch', (action) => {
|
||||
if (action.wmId !== props.config.wmId) return
|
||||
|
||||
if (action.type === 'start-stop') {
|
||||
isRunning.value ? stop() : start()
|
||||
} else if (action.type === 'reset') {
|
||||
reset()
|
||||
}
|
||||
})
|
||||
onUnmounted(() => {
|
||||
hotkeyController.abort()
|
||||
})
|
||||
|
||||
const isRunning = ref(false)
|
||||
const millis = ref(0)
|
||||
const prevTick = ref(0)
|
||||
@@ -73,7 +89,7 @@ export default defineComponent({
|
||||
wm.setFlag(props.config.wmId, 'invisible-on-blur', true)
|
||||
}
|
||||
}
|
||||
function restart () {
|
||||
function reset () {
|
||||
prevTick.value = Date.now()
|
||||
millis.value = (isRunning.value) ? 1000 : 0
|
||||
if (!isRunning.value) {
|
||||
@@ -96,7 +112,7 @@ export default defineComponent({
|
||||
isRunning,
|
||||
start,
|
||||
stop,
|
||||
restart
|
||||
reset
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -38,6 +38,7 @@ import SettingsPricecheck from './price-check.vue'
|
||||
import SettingsDebug from './debug.vue'
|
||||
import SettingsMaps from './maps/maps.vue'
|
||||
import SettingsStashSearch from './stash-search.vue'
|
||||
import SettingsStopwatch from './stopwatch.vue'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -121,6 +122,8 @@ function menuByType (type?: string) {
|
||||
switch (type) {
|
||||
case 'stash-search':
|
||||
return [[SettingsStashSearch]]
|
||||
case 'timer':
|
||||
return [[SettingsStopwatch]]
|
||||
default:
|
||||
return [
|
||||
[SettingsHotkeys, SettingsChat],
|
||||
@@ -185,7 +188,8 @@ function flatJoin<T, J> (arr: T[][], joinEl: () => J) {
|
||||
"Maps": "Карты",
|
||||
"Debug": "Debug",
|
||||
"Chat": "Чат",
|
||||
"Stash search": "Поиск в тайнике"
|
||||
"Stash search": "Поиск в тайнике",
|
||||
"Stopwatch": "Секундомер"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
44
renderer/src/web/settings/stopwatch.vue
Normal file
44
renderer/src/web/settings/stopwatch.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="max-w-md p-2">
|
||||
<div class="mb-4 flex">
|
||||
<label class="flex-1">{{ t('Start and Pause') }}</label>
|
||||
<hotkey-input v-model="toggleKey" class="w-48" />
|
||||
</div>
|
||||
<div class="mb-4 flex">
|
||||
<label class="flex-1">{{ t('Reset') }}</label>
|
||||
<hotkey-input v-model="resetKey" class="w-48" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import HotkeyInput from './HotkeyInput.vue'
|
||||
import { configProp, configModelValue } from './utils'
|
||||
import type { StopwatchWidget } from '@/web/overlay/interfaces'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Stopwatch',
|
||||
components: { HotkeyInput },
|
||||
props: configProp<StopwatchWidget>(),
|
||||
setup (props) {
|
||||
const { t } = useI18n()
|
||||
|
||||
return {
|
||||
t,
|
||||
toggleKey: configModelValue(() => props.configWidget, 'toggleKey'),
|
||||
resetKey: configModelValue(() => props.configWidget, 'resetKey')
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<i18n>
|
||||
{
|
||||
"ru": {
|
||||
"Start and Pause": "Старт и пауза",
|
||||
"Reset": "Сброс"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
Reference in New Issue
Block a user