178 lines
4.8 KiB
TypeScript
178 lines
4.8 KiB
TypeScript
import { ref, computed } from 'vue';
|
|
import { defineStore } from 'pinia';
|
|
import type { SnapType } from '../composables/useDraggable';
|
|
|
|
// Define the shape of a window
|
|
export interface WindowState {
|
|
id: string;
|
|
title: string;
|
|
x: number;
|
|
y: number;
|
|
width: number;
|
|
height: number;
|
|
zIndex: number;
|
|
isMinimized: boolean;
|
|
isMaximized: boolean;
|
|
isFocused: boolean;
|
|
}
|
|
|
|
let windowIdCounter = 0;
|
|
|
|
// Converted to a Setup Store to avoid `this` context issues in SSR.
|
|
export const useWindowsStore = defineStore('windows', () => {
|
|
// State
|
|
const windows = ref<WindowState[]>([]);
|
|
const nextZIndex = ref(100);
|
|
const focusedWindowId = ref<string | null>(null);
|
|
|
|
// Getters
|
|
const getWindowById = computed(() => {
|
|
return (id: string) => windows.value.find(w => w.id === id);
|
|
});
|
|
|
|
const orderedWindows = computed(() => {
|
|
return [...windows.value].sort((a, b) => a.zIndex - b.zIndex);
|
|
});
|
|
|
|
// Actions
|
|
function createWindow(title: string = 'New Window') {
|
|
const newId = windowIdCounter++;
|
|
const newWindow: WindowState = {
|
|
id: `window-${newId}`,
|
|
title: `${title} #${newId + 1}`,
|
|
x: Math.random() * 200 + 50,
|
|
y: Math.random() * 100 + 50 + 48, // Adjust initial Y to be below taskbar
|
|
width: 520,
|
|
height: 320,
|
|
zIndex: nextZIndex.value++,
|
|
isMinimized: false,
|
|
isMaximized: false,
|
|
isFocused: true,
|
|
};
|
|
|
|
windows.value.forEach(w => w.isFocused = false);
|
|
windows.value.push(newWindow);
|
|
focusedWindowId.value = newWindow.id;
|
|
}
|
|
|
|
function focusWindow(id: string) {
|
|
const windowToFocus = windows.value.find(w => w.id === id);
|
|
if (!windowToFocus || windowToFocus.isFocused) return;
|
|
|
|
windows.value.forEach(w => { w.isFocused = false; });
|
|
|
|
windowToFocus.zIndex = nextZIndex.value++;
|
|
windowToFocus.isFocused = true;
|
|
focusedWindowId.value = id;
|
|
|
|
if (windowToFocus.isMinimized) {
|
|
windowToFocus.isMinimized = false;
|
|
}
|
|
}
|
|
|
|
function closeWindow(id: string) {
|
|
windows.value = windows.value.filter(w => w.id !== id);
|
|
if (focusedWindowId.value === id) {
|
|
const topWindow = orderedWindows.value[orderedWindows.value.length - 1];
|
|
if (topWindow) {
|
|
focusWindow(topWindow.id);
|
|
} else {
|
|
focusedWindowId.value = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
function closeAllWindows() {
|
|
windows.value = [];
|
|
focusedWindowId.value = null;
|
|
}
|
|
|
|
function minimizeWindow(id: string) {
|
|
const windowToMinimize = windows.value.find(w => w.id === id);
|
|
if (windowToMinimize) {
|
|
windowToMinimize.isMinimized = true;
|
|
windowToMinimize.isFocused = false;
|
|
const topWindow = orderedWindows.value.filter(w => !w.isMinimized).pop();
|
|
if (topWindow) {
|
|
focusWindow(topWindow.id);
|
|
} else {
|
|
focusedWindowId.value = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
function toggleMaximize(id: string) {
|
|
const windowToMaximize = windows.value.find(w => w.id === id);
|
|
if (windowToMaximize) {
|
|
windowToMaximize.isMaximized = !windowToMaximize.isMaximized;
|
|
focusWindow(id);
|
|
}
|
|
}
|
|
|
|
function snapWindow(id: string, snapType: SnapType) {
|
|
const windowToSnap = windows.value.find(w => w.id === id);
|
|
if (!windowToSnap) return;
|
|
|
|
const taskbarHeight = 22; // Updated taskbar height
|
|
const screenWidth = window.innerWidth;
|
|
const screenHeight = window.innerHeight - taskbarHeight;
|
|
|
|
windowToSnap.isMaximized = false; // Always unmaximize when snapping
|
|
|
|
switch (snapType) {
|
|
case 'left':
|
|
windowToSnap.x = 0;
|
|
windowToSnap.y = taskbarHeight;
|
|
windowToSnap.width = screenWidth / 2;
|
|
windowToSnap.height = screenHeight;
|
|
break;
|
|
case 'right':
|
|
windowToSnap.x = screenWidth / 2;
|
|
windowToSnap.y = taskbarHeight;
|
|
windowToSnap.width = screenWidth / 2;
|
|
windowToSnap.height = screenHeight;
|
|
break;
|
|
case 'top':
|
|
windowToSnap.x = 0;
|
|
windowToSnap.y = taskbarHeight;
|
|
windowToSnap.width = screenWidth;
|
|
windowToSnap.height = screenHeight;
|
|
break;
|
|
}
|
|
focusWindow(id);
|
|
}
|
|
|
|
function updateWindowPosition({ id, x, y }: { id: string; x: number; y: number }) {
|
|
const window = windows.value.find(w => w.id === id);
|
|
if (window && !window.isMaximized) {
|
|
window.x = x;
|
|
window.y = y;
|
|
}
|
|
}
|
|
|
|
function updateWindowSize({ id, width, height }: { id: string; width: number; height: number }) {
|
|
const window = windows.value.find(w => w.id === id);
|
|
if (window && !window.isMaximized) {
|
|
window.width = width;
|
|
window.height = height;
|
|
}
|
|
}
|
|
|
|
return {
|
|
windows,
|
|
nextZIndex,
|
|
focusedWindowId,
|
|
getWindowById,
|
|
orderedWindows,
|
|
createWindow,
|
|
focusWindow,
|
|
closeWindow,
|
|
closeAllWindows,
|
|
minimizeWindow,
|
|
toggleMaximize,
|
|
snapWindow,
|
|
updateWindowPosition,
|
|
updateWindowSize,
|
|
};
|
|
});
|