Shortcuts for Stopwatch, closes #368

This commit is contained in:
Alexander Drozdov
2022-05-04 20:04:01 +03:00
parent fef9aab468
commit c605cd8c4d
7 changed files with 122 additions and 16 deletions

View File

@@ -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

View File

@@ -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 {

View File

@@ -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') {

View File

@@ -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 () {

View File

@@ -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
}
}
})

View File

@@ -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>

View 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>