feat(stage-tamagotchi): allow resize window, save window size and position (#37)

* feat(stage-tamagotchi): allow resize window, save window size and position

* fix(stage-tamagotchi): set default window size
This commit is contained in:
LemonNeko
2025-02-28 00:24:33 +08:00
committed by GitHub
parent fca23e1045
commit c778afe82e
4 changed files with 65 additions and 0 deletions
+24
View File
@@ -177,4 +177,28 @@ app.whenReady().then(() => {
rebuildTrayMenu()
createApplicationMenu(i18n, showQuitDialog, createSettingsWindow)
})
ipcMain.on('start-resize-window', () => {
mainWindow.setResizable(true)
})
ipcMain.on('stop-resize-window', () => {
mainWindow.setResizable(false)
})
ipcMain.handle('stop-move-window', () => {
return mainWindow.getPosition()
})
ipcMain.on('window-size-changed', (_, width: number, height: number) => {
if (width === 0 || height === 0) {
mainWindow.setSize(300 * 1.5, 400 * 1.5) // back to default size
return
}
mainWindow.setSize(width, height)
})
ipcMain.on('window-position-changed', (_, x: number, y: number) => {
mainWindow.setPosition(x, y)
})
})
@@ -1,11 +1,20 @@
<script setup lang="ts">
import { useSettings } from '@proj-airi/stage-ui/stores'
import { useEventListener } from '@vueuse/core'
import { onMounted, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { RouterView } from 'vue-router'
import { useWindowControlStore } from './stores/window-controls'
const settings = useSettings()
const i18n = useI18n()
const windowControlStore = useWindowControlStore()
useEventListener(window, 'resize', () => {
windowControlStore.size.width = window.innerWidth
windowControlStore.size.height = window.innerHeight
})
watch(() => settings.language, (language) => {
i18n.locale.value = language
@@ -15,6 +24,8 @@ watch(() => settings.language, (language) => {
// FIXME: store settings to file
onMounted(() => {
window.electron.ipcRenderer.send('locale-changed', settings.language)
window.electron.ipcRenderer.send('window-size-changed', windowControlStore.size.width, windowControlStore.size.height)
window.electron.ipcRenderer.send('window-position-changed', windowControlStore.position.x, windowControlStore.position.y)
})
</script>
@@ -71,6 +71,21 @@ const modeIndicatorClass = computed(() => {
</div>
</div>
</Transition>
<Transition
enter-active-class="transition-opacity duration-250"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="transition-opacity duration-250"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div
v-if="windowStore.controlMode === WindowControlMode.RESIZE"
class="absolute left-0 top-0 z-999 h-full w-full"
>
<div h-full w-full animate-flash animate-duration-2.5s animate-count-infinite b-8 b-pink rounded-2xl />
</div>
</Transition>
</template>
<style scoped>
@@ -1,3 +1,4 @@
import { useLocalStorage } from '@vueuse/core'
import { defineStore } from 'pinia'
import { ref } from 'vue'
@@ -6,9 +7,21 @@ import { WindowControlMode } from '../types/window-controls'
export const useWindowControlStore = defineStore('windowControl', () => {
const controlMode = ref<WindowControlMode>(WindowControlMode.DEFAULT)
const isControlActive = ref(false)
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) {
controlMode.value = mode
if (mode === WindowControlMode.RESIZE) {
window.electron.ipcRenderer.send('start-resize-window')
return
}
window.electron.ipcRenderer.invoke('stop-move-window').then((p: [number, number]) => {
position.value = { x: p[0], y: p[1] }
})
window.electron.ipcRenderer.send('stop-resize-window')
}
function toggleControl() {
@@ -21,6 +34,8 @@ export const useWindowControlStore = defineStore('windowControl', () => {
return {
controlMode,
isControlActive,
size,
position,
setMode,
toggleControl,
}