diff --git a/apps/stage-tamagotchi/src-tauri/src/lib.rs b/apps/stage-tamagotchi/src-tauri/src/lib.rs index bf39e8f13..dec15e204 100644 --- a/apps/stage-tamagotchi/src-tauri/src/lib.rs +++ b/apps/stage-tamagotchi/src-tauri/src/lib.rs @@ -105,10 +105,27 @@ pub fn run() { ], )?; + let window_mode_fade_on_hover = MenuItem::with_id(app, "window-mode.fade-on-hover", "Fade On Hover", true, None::<&str>)?; + let window_mode_move = MenuItem::with_id(app, "window-mode.move", "Move", true, None::<&str>)?; + let window_mode_resize = MenuItem::with_id(app, "window-mode.resize", "Resize", true, None::<&str>)?; + + let window_mode_sub_menu = Submenu::with_id_and_items( + app, + "window-mode", + "Window Mode", + true, + &[ + &window_mode_fade_on_hover, + &window_mode_move, + &window_mode_resize, + ], + )?; + let menu = Menu::with_items( app, &[ &settings_item, + &window_mode_sub_menu, &position_sub_menu, &hide_item, &show_item, @@ -142,6 +159,24 @@ pub fn run() { app::windows::settings::new_settings_window(app, None).unwrap(); } + "window-mode.fade-on-hover" => { + let window = app.get_webview_window("main"); + if let Some(window) = window { + window.emit("tauri-main:main:window-mode:fade-on-hover", true).map_err(|_| ()).unwrap(); + } + } + "window-mode.move" => { + let window = app.get_webview_window("main"); + if let Some(window) = window { + window.emit("tauri-main:main:window-mode:move", true).map_err(|_| ()).unwrap(); + } + } + "window-mode.resize" => { + let window = app.get_webview_window("main"); + if let Some(window) = window { + window.emit("tauri-main:main:window-mode:resize", true).map_err(|_| ()).unwrap(); + } + } "center" => { let _ = app.get_webview_window("main") .ok_or(()) diff --git a/apps/stage-tamagotchi/src/App.vue b/apps/stage-tamagotchi/src/App.vue index 4c1ddc84e..6c9d1d0a2 100644 --- a/apps/stage-tamagotchi/src/App.vue +++ b/apps/stage-tamagotchi/src/App.vue @@ -3,7 +3,6 @@ import type { AiriTamagotchiEvents } from './composables/tauri' import { useMcpStore, useOnboardingStore, useSettings } from '@proj-airi/stage-ui/stores' import { Window } from '@tauri-apps/api/window' -import { useEventListener } from '@vueuse/core' import { storeToRefs } from 'pinia' import { computed, onMounted, watch } from 'vue' import { useI18n } from 'vue-i18n' @@ -12,22 +11,17 @@ import { RouterView } from 'vue-router' import { commands } from './bindings/tauri-plugins/window-router-link' import { useAppRuntime } from './composables/runtime' import { useTauriEvent } from './composables/tauri' -import { useWindowControlStore } from './stores/window-controls' +import { useWindowMode } from './stores/window-controls' +useWindowMode() const { language, themeColorsHue, themeColorsHueDynamic, allowVisibleOnAllWorkspaces } = storeToRefs(useSettings()) const i18n = useI18n() -const windowControlStore = useWindowControlStore() const mcpStore = useMcpStore() const onboardingStore = useOnboardingStore() const { shouldShowSetup } = storeToRefs(onboardingStore) const { platform } = useAppRuntime() const { listen } = useTauriEvent() -useEventListener(window, 'resize', () => { - windowControlStore.size.width = window.innerWidth - windowControlStore.size.height = window.innerHeight -}) - watch(language, () => { i18n.locale.value = language.value }) diff --git a/apps/stage-tamagotchi/src/composables/tauri.ts b/apps/stage-tamagotchi/src/composables/tauri.ts index e88f04ed2..4d62a40fa 100644 --- a/apps/stage-tamagotchi/src/composables/tauri.ts +++ b/apps/stage-tamagotchi/src/composables/tauri.ts @@ -52,6 +52,11 @@ interface Events { } export interface AiriTamagotchiEvents extends Events { + // from main + 'tauri-main:main:window-mode:fade-on-hover': true + 'tauri-main:main:window-mode:move': true + 'tauri-main:main:window-mode:resize': true + // from tauri-plugin-window-pass-through-on-hover 'tauri-plugins:tauri-plugin-window-pass-through-on-hover:cursor-position': Point 'tauri-plugins:tauri-plugin-window-pass-through-on-hover:window-frame': WindowFrame diff --git a/apps/stage-tamagotchi/src/stores/shortcuts.ts b/apps/stage-tamagotchi/src/stores/shortcuts.ts index 39d39d39f..33df89550 100644 --- a/apps/stage-tamagotchi/src/stores/shortcuts.ts +++ b/apps/stage-tamagotchi/src/stores/shortcuts.ts @@ -77,8 +77,7 @@ export const useShortcutsStore = defineStore('shortcuts', () => { group: 'window', type: 'move', handle: async () => { - windowStore.setMode(WindowControlMode.MOVE) - windowStore.toggleControl() + windowStore.toggleMode(WindowControlMode.MOVE) }, }, { @@ -87,8 +86,7 @@ export const useShortcutsStore = defineStore('shortcuts', () => { group: 'window', type: 'resize', handle: async () => { - windowStore.setMode(WindowControlMode.RESIZE) - windowStore.toggleControl() + windowStore.toggleMode(WindowControlMode.RESIZE) }, }, { diff --git a/apps/stage-tamagotchi/src/stores/window-controls.ts b/apps/stage-tamagotchi/src/stores/window-controls.ts index 3d5250610..6004de257 100644 --- a/apps/stage-tamagotchi/src/stores/window-controls.ts +++ b/apps/stage-tamagotchi/src/stores/window-controls.ts @@ -1,8 +1,9 @@ -import { getCurrentWindow } from '@tauri-apps/api/window' -import { useLocalStorage } from '@vueuse/core' -import { defineStore } from 'pinia' -import { ref } from 'vue' +import type { AiriTamagotchiEvents } from '../composables/tauri' +import { defineStore } from 'pinia' +import { onMounted, onUnmounted, ref } from 'vue' + +import { useTauriEvent } from '../composables/tauri' import { WindowControlMode } from '../types/window-controls' import { startClickThrough, stopClickThrough } from '../utils/windows' @@ -10,14 +11,9 @@ export const useWindowControlStore = defineStore('windowControl', () => { const controlMode = ref(WindowControlMode.NONE) const isControlActive = ref(false) const isIgnoringMouseEvent = ref(true) - const size = useLocalStorage('window/control/size', { width: 300 * 1.5, height: 400 * 1.5 }) - const position = useLocalStorage('window/control/position', { x: 0, y: 0 }) - function setMode(mode: WindowControlMode) { + function toggleMode(mode: WindowControlMode) { controlMode.value = mode - } - - function toggleControl() { isControlActive.value = !isControlActive.value if (!isControlActive.value) { controlMode.value = WindowControlMode.NONE @@ -34,9 +30,46 @@ export const useWindowControlStore = defineStore('windowControl', () => { controlMode, isControlActive, isIgnoringMouseEvent, - size, - position, - setMode, - toggleControl, + toggleMode, + } +}) + +export const useWindowMode = defineStore('window-mode', () => { + const { listen } = useTauriEvent() + const windowStore = useWindowControlStore() + + const unlistenFuncs = ref<(() => void)[]>([]) + + async function setup() { + unlistenFuncs.value.push(await listen('tauri-main:main:window-mode:move', () => { + windowStore.toggleMode(WindowControlMode.MOVE) + })) + + unlistenFuncs.value.push(await listen('tauri-main:main:window-mode:resize', () => { + windowStore.toggleMode(WindowControlMode.RESIZE) + })) + + unlistenFuncs.value.push(await listen('tauri-main:main:window-mode:fade-on-hover', async () => { + windowStore.isIgnoringMouseEvent = !windowStore.isIgnoringMouseEvent + if (windowStore.isIgnoringMouseEvent) { + await startClickThrough() + return + } + + await stopClickThrough() + })) + } + + function cleanup() { + unlistenFuncs.value.forEach(unlisten => unlisten()) + unlistenFuncs.value.length = 0 + } + + onMounted(setup) + onUnmounted(cleanup) + + if (import.meta.hot) { // For better DX + import.meta.hot.on('vite:beforeUpdate', () => cleanup()) + import.meta.hot.on('vite:afterUpdate', async () => await setup()) } })