96 lines
2.7 KiB
Vue
96 lines
2.7 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import { storeToRefs } from 'pinia';
|
|
import { useWindowsStore } from '../stores/windows';
|
|
import { useSettingsStore } from '../stores/settings';
|
|
import { useUIStore } from '../stores/ui';
|
|
import Window from './Window.vue';
|
|
import Taskbar from './Taskbar.vue';
|
|
import SnapPreview from './SnapPreview.vue';
|
|
import StartMenu from './StartMenu.vue';
|
|
import type { SnapType } from '../composables/useDraggable';
|
|
|
|
const windowsStore = useWindowsStore();
|
|
const settingsStore = useSettingsStore();
|
|
const uiStore = useUIStore();
|
|
|
|
const { orderedWindows } = storeToRefs(windowsStore);
|
|
const { createWindow, snapWindow } = windowsStore;
|
|
const { toggleTheme } = settingsStore;
|
|
const { closeStartMenu } = uiStore;
|
|
|
|
const snapPreview = ref<{ x: number; y: number; width: number; height: number; } | null>(null);
|
|
|
|
function handleSnapPreview(snapType: SnapType) {
|
|
if (!snapType) {
|
|
snapPreview.value = null;
|
|
return;
|
|
}
|
|
|
|
const taskbarHeight = 48;
|
|
const screenWidth = window.innerWidth;
|
|
const screenHeight = window.innerHeight - taskbarHeight;
|
|
|
|
switch (snapType) {
|
|
case 'left':
|
|
snapPreview.value = { x: 0, y: taskbarHeight, width: screenWidth / 2, height: screenHeight };
|
|
break;
|
|
case 'right':
|
|
snapPreview.value = { x: screenWidth / 2, y: taskbarHeight, width: screenWidth / 2, height: screenHeight };
|
|
break;
|
|
case 'top':
|
|
snapPreview.value = { x: 0, y: taskbarHeight, width: screenWidth, height: screenHeight };
|
|
break;
|
|
}
|
|
}
|
|
|
|
function handleSnapExecute({ windowId, snapType }: { windowId: string; snapType: SnapType }) {
|
|
snapPreview.value = null;
|
|
if (snapType) {
|
|
snapWindow(windowId, snapType);
|
|
}
|
|
}
|
|
|
|
function handleDesktopClick() {
|
|
closeStartMenu();
|
|
}
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="desktop" @click.self="handleDesktopClick">
|
|
<Window
|
|
v-for="window in orderedWindows"
|
|
:key="window.id"
|
|
:window="window"
|
|
@snap-preview="handleSnapPreview"
|
|
@snap-execute="handleSnapExecute"
|
|
/>
|
|
|
|
<SnapPreview v-if="snapPreview" :preview="snapPreview" />
|
|
<StartMenu />
|
|
|
|
<div class="fixed top-14 left-4 z-[9999] flex flex-col gap-2">
|
|
<button @click="() => createWindow('New App')" class="bg-white/20 backdrop-blur-md text-white font-bold py-2 px-4 rounded-lg shadow-lg">
|
|
+ Create Window
|
|
</button>
|
|
<button @click="toggleTheme" class="bg-white/20 backdrop-blur-md text-white font-bold py-2 px-4 rounded-lg shadow-lg">
|
|
Toggle Theme
|
|
</button>
|
|
</div>
|
|
|
|
<Taskbar />
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.desktop {
|
|
position: relative;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
background: var(--background-desktop);
|
|
overflow: hidden;
|
|
padding-top: 48px;
|
|
}
|
|
</style>
|