From a50af98f9a8c7f453d6ddbe1631e29d2a0f5471b Mon Sep 17 00:00:00 2001 From: Pihkaal Date: Wed, 25 Feb 2026 17:09:41 +0100 Subject: [PATCH] feat(nds): improve fullscreen button and add volume slider --- app/components/Controls.vue | 79 +++++++++++++++++++++++++++++++++ app/composables/useAssets.ts.in | 3 +- app/composables/useClockTick.ts | 2 +- app/composables/useKeyDown.ts | 6 +++ app/pages/index.vue | 51 +-------------------- app/stores/app.ts | 2 + 6 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 app/components/Controls.vue diff --git a/app/components/Controls.vue b/app/components/Controls.vue new file mode 100644 index 0000000..64ea814 --- /dev/null +++ b/app/components/Controls.vue @@ -0,0 +1,79 @@ + + + diff --git a/app/composables/useAssets.ts.in b/app/composables/useAssets.ts.in index e559362..1c71e88 100644 --- a/app/composables/useAssets.ts.in +++ b/app/composables/useAssets.ts.in @@ -12,8 +12,9 @@ const createAudio = (path: string) => { return { play: (volume = 1) => { if (!source) return; + const app = useAppStore(); const audio = source.cloneNode() as HTMLAudioElement; - audio.volume = volume; + audio.volume = Math.min(1, volume * app.settings.volume); audio.addEventListener("ended", () => audio.remove(), { once: true }); audio.play().catch(() => {}); }, diff --git a/app/composables/useClockTick.ts b/app/composables/useClockTick.ts index a24cfc3..8c7d077 100644 --- a/app/composables/useClockTick.ts +++ b/app/composables/useClockTick.ts @@ -7,6 +7,6 @@ export const useClockTick = () => { const s = now.getSeconds(); if (s === lastSecond) return; lastSecond = s; - assets.audio.clockTick.play(s === 0 ? 1 : 0.7); + assets.audio.clockTick.play(s === 0 ? 2 : 1.4); }; }; diff --git a/app/composables/useKeyDown.ts b/app/composables/useKeyDown.ts index e92080b..cddf325 100644 --- a/app/composables/useKeyDown.ts +++ b/app/composables/useKeyDown.ts @@ -13,6 +13,12 @@ export const useKeyDown = (callback: KeyDownCallback) => { if (app.lagDetected) return; const ndsButton = mapCodeToNDS(event.code); + if ( + ndsButton && + document.activeElement && + document.activeElement !== document.body + ) + return; callback({ key: ndsButton ? `NDS_${ndsButton}` : event.key, ndsButton, diff --git a/app/pages/index.vue b/app/pages/index.vue index f7a3c3c..4bfad66 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -23,20 +23,9 @@ const bottomScreen = useTemplateRef("bottomScreen"); const topScreenCanvas = computed(() => topScreen.value?.canvas ?? null); const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null); -const isIOS = () => /iPad|iPhone|iPod/.test(navigator.userAgent); const isTouchDevice = () => "ontouchstart" in window || navigator.maxTouchPoints > 0; -const showFullscreenBtn = ref(true); - -const toggleFullscreen = () => { - if (document.fullscreenElement) { - document.exitFullscreen(); - } else { - document.documentElement.requestFullscreen(); - } -}; - const windowSize = useWindowSize(); watch([windowSize.width, windowSize.height], ([width, height]) => { @@ -116,10 +105,6 @@ watch( ); onMounted(async () => { - if (isIOS()) { - showFullscreenBtn.value = false; - } - if (isTouchDevice()) { const landscape = window.matchMedia("(orientation: landscape)"); @@ -229,22 +214,7 @@ useKeyDown(async ({ key, repeated }) => { ? - + @@ -270,23 +240,4 @@ useKeyDown(async ({ key, repeated }) => { .help-btn:hover { opacity: 1; } - -.fullscreen-btn { - position: fixed; - bottom: 16px; - right: 16px; - width: 32px; - height: 32px; - padding: 4px; - background: none; - border: none; - color: #666; - cursor: pointer; - opacity: 0.5; - transition: opacity 0.2s; -} - -.fullscreen-btn:hover { - opacity: 1; -} diff --git a/app/stores/app.ts b/app/stores/app.ts index f4866b8..b1d06fd 100644 --- a/app/stores/app.ts +++ b/app/stores/app.ts @@ -24,6 +24,7 @@ const settingsSchema = z.object({ row: z.number(), }), renderingMode: z.enum(["3d", "2d"]), + volume: z.number(), }); type Settings = z.infer; @@ -31,6 +32,7 @@ type Settings = z.infer; const defaultSettings = (): Settings => ({ color: { col: 0, row: 0 }, renderingMode: "3d", + volume: 0.5, }); export const useAppStore = defineStore("app", {