windows/stores/windows.ts

178 lines
4.8 KiB
TypeScript
Raw Normal View History

2025-09-23 16:43:57 +00:00
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;
}
}
}
2025-09-24 09:45:36 +00:00
function closeAllWindows() {
windows.value = [];
focusedWindowId.value = null;
}
2025-09-23 16:43:57 +00:00
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;
2025-09-24 09:45:36 +00:00
const taskbarHeight = 22; // Updated taskbar height
2025-09-23 16:43:57 +00:00
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,
2025-09-24 09:45:36 +00:00
closeAllWindows,
2025-09-23 16:43:57 +00:00
minimizeWindow,
toggleMaximize,
snapWindow,
updateWindowPosition,
updateWindowSize,
};
});