Replace mousetrap with @vueuse/core useMagicKeys, drop custom debounce

main
Warinyourself 3 months ago
parent f4ea175888
commit 0397c71b2b

60
package-lock.json generated

@ -9,7 +9,7 @@
"version": "0.0.0",
"dependencies": {
"@lucide/vue": "^1.17.0",
"mousetrap": "^1.6.5",
"@vueuse/core": "^14.3.0",
"pinia": "^3.0.4",
"vue": "^3.5.32",
"vue-i18n": "^11.4.5",
@ -17,7 +17,6 @@
},
"devDependencies": {
"@tsconfig/node24": "^24.0.4",
"@types/mousetrap": "^1.6.15",
"@types/node": "^24.12.2",
"@vitejs/plugin-vue": "^6.0.6",
"@vitejs/plugin-vue-jsx": "^5.1.5",
@ -999,13 +998,6 @@
"integrity": "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==",
"license": "MIT"
},
"node_modules/@types/mousetrap": {
"version": "1.6.15",
"resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.15.tgz",
"integrity": "sha512-qL0hyIMNPow317QWW/63RvL1x5MVMV+Ru3NaY9f/CuEpCqrmb7WeuK2071ZY5hczOnm38qExWM2i2WtkXLSqFw==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.13.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.1.tgz",
@ -1016,6 +1008,12 @@
"undici-types": "~7.18.0"
}
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
"integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
"license": "MIT"
},
"node_modules/@vitejs/plugin-vue": {
"version": "6.0.7",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.7.tgz",
@ -1372,6 +1370,44 @@
}
}
},
"node_modules/@vueuse/core": {
"version": "14.3.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.3.0.tgz",
"integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==",
"license": "MIT",
"dependencies": {
"@types/web-bluetooth": "^0.0.21",
"@vueuse/metadata": "14.3.0",
"@vueuse/shared": "14.3.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vue": "^3.5.0"
}
},
"node_modules/@vueuse/metadata": {
"version": "14.3.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.3.0.tgz",
"integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "14.3.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.3.0.tgz",
"integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vue": "^3.5.0"
}
},
"node_modules/acorn": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
@ -2589,12 +2625,6 @@
"pathe": "^2.0.1"
}
},
"node_modules/mousetrap": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz",
"integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==",
"license": "Apache-2.0 WITH LLVM-exception"
},
"node_modules/mrmime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",

@ -12,7 +12,7 @@
},
"dependencies": {
"@lucide/vue": "^1.17.0",
"mousetrap": "^1.6.5",
"@vueuse/core": "^14.3.0",
"pinia": "^3.0.4",
"vue": "^3.5.32",
"vue-i18n": "^11.4.5",
@ -20,7 +20,6 @@
},
"devDependencies": {
"@tsconfig/node24": "^24.0.4",
"@types/mousetrap": "^1.6.15",
"@types/node": "^24.12.2",
"@vitejs/plugin-vue": "^6.0.6",
"@vitejs/plugin-vue-jsx": "^5.1.5",

@ -1,9 +1,9 @@
import { defineComponent, watch } from 'vue'
import Mousetrap from 'mousetrap'
import { useMagicKeys, useDebounceFn, whenever } from '@vueuse/core'
import { useAppStore } from '@/store/app'
import { usePageStore } from '@/store/page'
import { debounce, focusInputPassword, setCSSVariable } from '@/utils/helper'
import { hotkeys } from '@/utils/hotkeys'
import { focusInputPassword, setCSSVariable } from '@/utils/helper'
import { hotkeys, toMagicKeyCombo } from '@/utils/hotkeys'
export default defineComponent({
name: 'MainApp',
@ -11,15 +11,16 @@ export default defineComponent({
setup() {
const appStore = useAppStore()
const pageStore = usePageStore()
const keys = useMagicKeys()
const initZoom = () => {
setCSSVariable('--zoom', appStore.zoom + '' || '1')
}
const initKeybinds = () => {
hotkeys.forEach(({ keys, callback }) => Mousetrap.bind(keys.join('+'), callback))
hotkeys.forEach(({ keys: keyList, callback }) => whenever(keys[toMagicKeyCombo(keyList)]!, callback))
Mousetrap.bind('escape', () => {
whenever(keys.escape!, () => {
const isFocusPassword = document.querySelector('#password:focus') as HTMLInputElement
if (pageStore.dialog) {
pageStore.closeDialog()
@ -32,7 +33,7 @@ export default defineComponent({
}
})
Mousetrap.bind('enter', () => {
whenever(keys.enter!, () => {
const isFocusPassword = document.querySelector('#password:focus')
if (isFocusPassword) {
appStore.login()
@ -48,7 +49,7 @@ export default defineComponent({
watch(
() => appStore.getMainSettings,
debounce(() => appStore.syncSettingsWithCache(), 100),
useDebounceFn(() => appStore.syncSettingsWithCache(), 100),
{ deep: true }
)

@ -31,7 +31,6 @@ export default defineComponent({
name="password"
autocomplete="on"
autofocus
class="mousetrap"
placeholder={t('text.password')}
onKeyup={handleKeyup}
value={appStore.password}

@ -1,5 +1,6 @@
import { defineComponent, computed, onUpdated, type VNode } from 'vue'
import { useI18n } from 'vue-i18n'
import { useDebounceFn } from '@vueuse/core'
import { useAppStore } from '@/store/app'
import AppSlider from '@/components/app/AppSlider'
import AppButton from '@/components/app/AppButton'
@ -7,7 +8,6 @@ import AppSwitch from '@/components/app/AppSwitch'
import AppSelector from '@/components/app/AppSelector'
import AppColorSelector from '@/components/app/AppColorSelector'
import AppPaletteSelector from '@/components/app/AppPaletteSelector'
import { debounce } from '@/utils/helper'
import type {
AppInputButton,
AppInputColor,
@ -24,7 +24,7 @@ export default defineComponent({
const { t } = useI18n()
const inputs = computed(() => appStore.activeTheme?.settings || [])
const debouncedSync = debounce(() => appStore.syncStoreWithQuery(), 300)
const debouncedSync = useDebounceFn(() => appStore.syncStoreWithQuery(), 300)
onUpdated(() => debouncedSync())

@ -1,11 +1,12 @@
import { defineComponent, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useDebounceFn } from '@vueuse/core'
import { useAppStore } from '@/store/app'
import { usePageStore } from '@/store/page'
import { useRouter } from 'vue-router'
import AppSelector from '@/components/app/AppSelector'
import AppSlider from '@/components/app/AppSlider'
import { debounce, generateDesktopIcons, languageMap, setCSSVariable } from '@/utils/helper'
import { generateDesktopIcons, languageMap, setCSSVariable } from '@/utils/helper'
import type { LoginPosition } from '@/models/page'
export default defineComponent({
@ -49,7 +50,7 @@ export default defineComponent({
appStore.saveStateApp({ key: 'desktop', value })
}
const updateZoom = debounce((value: number) => {
const updateZoom = useDebounceFn((value: number) => {
setCSSVariable('--zoom', value + '' || '1')
appStore.zoom = parseFloat(value + '')
}, 100)

@ -22,14 +22,6 @@ export function isDifferentRoute(to: RouteLocationRaw) {
return router.currentRoute.value.fullPath !== resolve.fullPath
}
export function debounce<T extends (...args: any[]) => void>(fn: T, wait = 500) {
let timeout: ReturnType<typeof setTimeout>
return ((...args: Parameters<T>) => {
clearTimeout(timeout)
timeout = setTimeout(() => fn(...args), wait)
}) as T
}
export function parseQueryValue(value: string) {
const isBoolean = ['false', 'true'].includes(value)
if (isBoolean) return value === 'true'

@ -76,3 +76,11 @@ export const hotkeys = [
]
export type hotkeysType = (typeof hotkeys)[number]
// Converts a display key list (e.g. ['ctrl', 'P']) into a useMagicKeys combo
// (e.g. 'ctrl+shift+p'), since an uppercase letter implies the Shift modifier
export function toMagicKeyCombo(keys: string[]): string {
return keys
.flatMap((key) => (key.length === 1 && key !== key.toLowerCase() ? ['shift', key.toLowerCase()] : [key.toLowerCase()]))
.join('+')
}

Loading…
Cancel
Save