167 lines
4.2 KiB
TypeScript
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,
|
||
|
};
|
||
|
});
|