windows/stores/apps.ts

167 lines
4.2 KiB
TypeScript

import { ref, computed } from 'vue';
import { defineStore } from 'pinia';
export interface AppInfo {
id: string;
name: string;
icon: string;
component: string;
description: string;
category: string;
}
export interface AppInstance {
id: string;
appId: string;
title: string;
x: number;
y: number;
width: number;
height: number;
zIndex: number;
isMinimized: boolean;
isMaximized: boolean;
isFocused: boolean;
}
let appInstanceIdCounter = 0;
export const useAppsStore = defineStore('apps', () => {
// Available apps registry
const availableApps = ref<AppInfo[]>([
{
id: 'calculator',
name: 'Calculator',
icon: '🧮',
component: 'Calculator',
description: 'A simple calculator for basic arithmetic operations',
category: 'Utilities'
},
// More apps can be added here in the future
]);
// Running app instances
const appInstances = ref<AppInstance[]>([]);
const nextZIndex = ref(100);
// Getters
const getAppById = computed(() => {
return (id: string) => availableApps.value.find(app => app.id === id);
});
const getAppInstanceById = computed(() => {
return (id: string) => appInstances.value.find(instance => instance.id === id);
});
const orderedAppInstances = computed(() => {
return [...appInstances.value].sort((a, b) => a.zIndex - b.zIndex);
});
const focusedAppInstance = computed(() => {
return appInstances.value.find(instance => instance.isFocused);
});
// Actions
function launchApp(appId: string) {
const app = getAppById.value(appId);
if (!app) {
console.error(`App with id "${appId}" not found`);
return null;
}
const newInstanceId = appInstanceIdCounter++;
const newInstance: AppInstance = {
id: `app-${appId}-${newInstanceId}`,
appId: appId,
title: `${app.name} #${newInstanceId + 1}`,
x: Math.random() * 200 + 50,
y: Math.random() * 100 + 50 + 48, // Below taskbar
width: 320,
height: 400,
zIndex: nextZIndex.value++,
isMinimized: false,
isMaximized: false,
isFocused: true,
};
// Unfocus all other instances
appInstances.value.forEach(instance => instance.isFocused = false);
appInstances.value.push(newInstance);
return newInstance;
}
function focusAppInstance(instanceId: string) {
const instance = appInstances.value.find(i => i.id === instanceId);
if (!instance || instance.isFocused) return;
// Unfocus all other instances
appInstances.value.forEach(i => i.isFocused = false);
instance.zIndex = nextZIndex.value++;
instance.isFocused = true;
if (instance.isMinimized) {
instance.isMinimized = false;
}
}
function closeAppInstance(instanceId: string) {
appInstances.value = appInstances.value.filter(i => i.id !== instanceId);
}
function minimizeAppInstance(instanceId: string) {
const instance = appInstances.value.find(i => i.id === instanceId);
if (instance) {
instance.isMinimized = true;
instance.isFocused = false;
}
}
function toggleMaximizeAppInstance(instanceId: string) {
const instance = appInstances.value.find(i => i.id === instanceId);
if (instance) {
instance.isMaximized = !instance.isMaximized;
focusAppInstance(instanceId);
}
}
function updateAppInstancePosition({ id, x, y }: { id: string; x: number; y: number }) {
const instance = appInstances.value.find(i => i.id === id);
if (instance && !instance.isMaximized) {
instance.x = x;
instance.y = y;
}
}
function updateAppInstanceSize({ id, width, height }: { id: string; width: number; height: number }) {
const instance = appInstances.value.find(i => i.id === id);
if (instance && !instance.isMaximized) {
instance.width = width;
instance.height = height;
}
}
function closeAllAppInstances() {
appInstances.value = [];
}
return {
availableApps,
appInstances,
nextZIndex,
getAppById,
getAppInstanceById,
orderedAppInstances,
focusedAppInstance,
launchApp,
focusAppInstance,
closeAppInstance,
minimizeAppInstance,
toggleMaximizeAppInstance,
updateAppInstancePosition,
updateAppInstanceSize,
closeAllAppInstances,
};
});