From afb393497ef644cc184438a41a0ec55b88332501 Mon Sep 17 00:00:00 2001 From: Spencer Collins Date: Sun, 24 Nov 2024 13:39:34 -0600 Subject: [PATCH] Escape Keybinding (#282) * Add standard menu keybinding for "Escape" * fix pipeline --- src/renderer/App.vue | 3 ++ src/renderer/components/common/Modal.vue | 13 ++++++ .../composables/useGlobalKeybindings.ts | 30 ++++++++++++++ src/renderer/index.ts | 40 ++++--------------- src/renderer/interface.d.ts | 18 ++++++++- 5 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 src/renderer/composables/useGlobalKeybindings.ts diff --git a/src/renderer/App.vue b/src/renderer/App.vue index 8dddb66b..0505fc1c 100644 --- a/src/renderer/App.vue +++ b/src/renderer/App.vue @@ -69,6 +69,7 @@ import PromptContainer from "@renderer/components/prompts/PromptContainer.vue"; import { playRandomMusic } from "@renderer/utils/play-random-music"; import { settingsStore } from "./store/settings.store"; import { infosStore } from "@renderer/store/infos.store"; +import { useGlobalKeybindings } from "@renderer/composables/useGlobalKeybindings"; const router = useRouter(); const videoVisible = toRef(!toValue(settingsStore.skipIntro)); @@ -83,6 +84,8 @@ const exitOpen = ref(false); provide("settingsOpen", settingsOpen); provide("exitOpen", exitOpen); +useGlobalKeybindings({ exitOpen }); + const toggleMessages: Ref<((open?: boolean, userId?: number) => void) | undefined> = ref(); provide("toggleMessages", toggleMessages); diff --git a/src/renderer/components/common/Modal.vue b/src/renderer/components/common/Modal.vue index 78ddd477..5e1839e6 100644 --- a/src/renderer/components/common/Modal.vue +++ b/src/renderer/components/common/Modal.vue @@ -34,6 +34,7 @@ import { nextTick, onMounted, Ref, ref, toRef, watch } from "vue"; import Panel from "@renderer/components/common/Panel.vue"; import { audioApi } from "@renderer/audio/audio"; +import { onKeyDown } from "@vueuse/core"; export type PanelProps = InstanceType["$props"]; export interface ModalProps extends /* @vue-ignore */ PanelProps { @@ -81,6 +82,18 @@ watch(isOpen, (open) => { } }); +onKeyDown( + "Escape", + (e) => { + if (isOpen.value) { + e.preventDefault(); + e.stopPropagation(); + close(); + } + }, + { target: document } +); + async function onSubmit() { const data: Record = {}; diff --git a/src/renderer/composables/useGlobalKeybindings.ts b/src/renderer/composables/useGlobalKeybindings.ts new file mode 100644 index 00000000..695d40ea --- /dev/null +++ b/src/renderer/composables/useGlobalKeybindings.ts @@ -0,0 +1,30 @@ +import { Ref } from "vue"; +import { useRouter } from "vue-router"; +import { onKeyDown } from "@vueuse/core"; +import { settingsStore } from "@renderer/store/settings.store"; + +type KeybindingProps = { exitOpen: Ref }; + +export function useGlobalKeybindings({ exitOpen }: KeybindingProps) { + const router = useRouter(); + + onKeyDown("F11", (e) => { + e.preventDefault(); + settingsStore.fullscreen = !settingsStore.fullscreen; + }); + + onKeyDown("Escape", (e) => { + e.preventDefault(); + if (router.currentRoute.value.path.startsWith("/login") || router.currentRoute.value.path.startsWith("/home")) { + exitOpen.value = !exitOpen.value; + } else { + const routeSegments = router.currentRoute.value.path.split("/"); + // "/primary/secondary" => ["", "primary", "secondary", ...] + if (routeSegments.length <= 3) { + router.push("/home"); + } else { + router.back(); + } + } + }); +} diff --git a/src/renderer/index.ts b/src/renderer/index.ts index 9fa9c9ba..75bc29d7 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -5,7 +5,6 @@ import "@renderer/styles/styles.scss"; import PrimeVue from "primevue/config"; import Tooltip from "primevue/tooltip"; -import type { TransitionProps } from "vue"; import { createApp } from "vue"; import { createI18n } from "vue-i18n"; import { localeFilePaths } from "@renderer/assets/assetFiles"; @@ -15,50 +14,27 @@ import { clickAwayDirective } from "@renderer/utils/click-away-directive"; import { elementInViewDirective } from "@renderer/utils/element-in-view-directive"; import { audioApi } from "@renderer/audio/audio"; import { router } from "@renderer/router"; -import { settingsStore } from "@renderer/store/settings.store"; import { initPreMountStores } from "@renderer/store/stores"; -declare module "vue-router" { - interface RouteMeta { - title?: string; - order?: number; - availableOffline?: boolean; - hide?: boolean; - empty?: boolean; - blurBg?: boolean; - transition?: TransitionProps; - overflowY?: "scroll" | "hidden"; - devOnly?: boolean; - redirect?: string; - } -} - -(async () => { - await setupVue(); - window.addEventListener("keydown", (event) => { - if (event.code === "F11") { - event.preventDefault(); - settingsStore.fullscreen = !settingsStore.fullscreen; - } - }); -})(); +setupVue(); async function setupVue() { const app = createApp(App); + + // Plugins app.use(router); - app.use(PrimeVue, { - ripple: true, - }); + app.use(PrimeVue, { ripple: true }); app.use(await setupI18n()); + + // Directives app.directive("click-away", clickAwayDirective); app.directive("in-view", elementInViewDirective); app.directive("tooltip", Tooltip); - if (process.env.NODE_ENV !== "production") { - app.config.globalProperties.window = window; - } + // Init stores before mounting app await initPreMountStores(); await audioApi.init(); + app.mount("#app"); } diff --git a/src/renderer/interface.d.ts b/src/renderer/interface.d.ts index 24fe0e43..b0d94430 100644 --- a/src/renderer/interface.d.ts +++ b/src/renderer/interface.d.ts @@ -1,4 +1,5 @@ -import { AccountApi, DownloadsApi, EngineApi, GameApi, InfoApi, MainWindowApi, MapsApi, MiscApi, ReplaysApi, SettingsApi, ShellApi } from "@preload/preload"; +import type { AccountApi, DownloadsApi, EngineApi, GameApi, InfoApi, MainWindowApi, MapsApi, MiscApi, ReplaysApi, SettingsApi, ShellApi } from "@preload/preload"; +import type { TransitionProps } from "vue"; declare global { interface Window { @@ -15,3 +16,18 @@ declare global { misc: MiscApi; } } + +declare module "vue-router" { + interface RouteMeta { + title?: string; + order?: number; + availableOffline?: boolean; + hide?: boolean; + empty?: boolean; + blurBg?: boolean; + transition?: TransitionProps; + overflowY?: "scroll" | "hidden"; + devOnly?: boolean; + redirect?: string; + } +}