// actually unused import { defineStore } from 'pinia' import { reactive, ref, computed } from 'vue' import { nanoid } from 'nanoid' import { WindowController } from '../core/controllers/WindowController' import { useApplicationManager } from '../composables/useApplicationManager' import { useApplicationWindowsStore } from './storeApplicationWindows' import { useApplicationMetaStore } from './storeApplicationMeta' import { useTerminalManager } from '../composables/useTerminalManager' import { useDesktopDefaultAppsStore } from './storeDesktopDefaultApps' import { useDesktopWorkspaceStore } from './storeDesktopWorkspace' import { debugLog, debugError } from '../utils/utilDebug' interface WindowStoredState { model: string state: any meta?: any } export const useApplicationStore = function(applicationId: string, applicationConfig: ApplicationConfig) { return defineStore(`owd/application/${applicationId}`, () => { // reactive state const windows = reactive(new Map()) const isRunning = ref(false) // composables and external stores const applicationManager = useApplicationManager() const terminalManager = useTerminalManager() const desktopDefaultAppsStore = useDesktopDefaultAppsStore() const desktopWorkspaceStore = useDesktopWorkspaceStore() let storeWindows: ReturnType let storeMeta: ReturnType // init application async function initApplication() { storeWindows = useApplicationWindowsStore(applicationId) storeMeta = useApplicationMetaStore(applicationId) // set default app if (applicationConfig.provides) { const existingDefault = desktopDefaultAppsStore.getDefaultApp( applicationConfig.provides.name, ) if (!existingDefault) { desktopDefaultAppsStore.setDefaultApp( applicationConfig.provides.name, store, // store o qualcosa che rappresenta questa app? applicationConfig.entries![applicationConfig.provides.entry]!, ) debugLog( `${applicationConfig.title} set as predefined app for "${applicationConfig.provides.name}"`, ) } } // register terminal commands if (applicationConfig.commands) { for (const commandKey of Object.keys(applicationConfig.commands)) { terminalManager.addCommand({ applicationId, name: commandKey, }) } } if (storeWindows.$persistedState) await storeWindows.$persistedState.isReady() if (storeMeta.$persistedState) await storeMeta.$persistedState.isReady() await restoreApplication() if (typeof applicationConfig.onReady === 'function') { applicationConfig.onReady(store) } } // restore async function restoreApplication() { if (typeof applicationConfig.onRestore === 'function') { await applicationConfig.onRestore(store) } if (!storeWindows.windows || Object.keys(storeWindows.windows).length === 0) { return false } restoreWindows() setRunning(true) return true } function restoreWindows() { Object.keys(storeWindows.windows).forEach((windowId) => { const windowStore = storeWindows.windows[windowId] if (windowStore) { openWindow(windowStore.model, windowStore, { isRestoring: true }) } }) debugLog('Windows restored', windows) } // open window function openWindow( model: string, windowStoredState?: WindowStoredState, meta?: any, ): WindowController | undefined { if (!applicationConfig.windows || !applicationConfig.windows.hasOwnProperty(model)) { debugError(`Window model "${model}" not found`) return } let windowId: string if (!windowStoredState) { windowId = `${model}-${nanoid(6)}` const windowConfig = applicationConfig.windows[model] as WindowConfig const screenHeight = window.innerHeight const centerY = (screenHeight - Number(windowConfig.size.height)) / 2 const positionY = windowConfig.position?.y !== undefined ? window.scrollY + windowConfig.position.y : window.scrollY + centerY storeWindows.windows[windowId] = { model, state: { id: windowId, active: true, focused: false, position: { x: windowConfig.position?.x, y: positionY, }, createdAt: +new Date(), workspace: desktopWorkspaceStore.active, }, meta, } windowStoredState = storeWindows.windows[windowId] } else { windowId = windowStoredState.state.id } const windowConfig = applicationConfig.windows[model] as WindowConfig const windowController = new WindowController(store, model, windowConfig, windowStoredState!) if (!meta?.isRestoring) { windowController.actions.bringToFront() } windows.set(windowId, windowController) setRunning(true) return windowController } // close window function closeWindow(windowId: string) { delete storeWindows.windows[windowId] windows.delete(windowId) if (windows.size === 0) { applicationManager.closeApp(applicationId) } } // close all windows function closeAllWindows() { storeWindows.windows = {} windows.clear() } // getters const windowsOpened = computed(() => windows) function getWindowById(id: string) { return windows.get(id) } function getWindowsByModel(model: string) { return Array.from(windows.values()).filter((w) => w.model === model) } function getFirstWindowByModel(model: string) { return Array.from(windows.values()).find((w) => w.model === model) } function setRunning(value: boolean) { isRunning.value = value } // meta management const meta = computed(() => storeMeta.meta) function getMeta(key: string) { return meta.value[key] } function setMeta(key: string, value: any) { storeMeta.meta[key] = value } // command exec async function execCommand(command: string) { return applicationManager.execAppCommand(applicationId, command) } const store = { id: applicationId, config: applicationConfig, storeWindows, storeMeta, windows, isRunning, initApplication, restoreApplication, openWindow, closeWindow, closeAllWindows, windowsOpened, getWindowById, getWindowsByModel, getFirstWindowByModel, setRunning, meta, getMeta, setMeta, execCommand, } return store })() }