@owdproject/core 3.1.2 → 3.1.4-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +9 -10
  3. package/bin/owd.js +14 -14
  4. package/index.ts +5 -2
  5. package/module.ts +64 -55
  6. package/package.json +19 -17
  7. package/project.json +4 -0
  8. package/runtime/components/Core/Application/CoreApplicationRender.vue +6 -5
  9. package/runtime/components/Core/Application/CoreApplicationWindowsRender.vue +8 -8
  10. package/runtime/components/Core/Background/CoreBackground.vue +1 -1
  11. package/runtime/components/Core/Desktop/CoreDesktop.vue +23 -20
  12. package/runtime/components/Core/Explorer/CoreExplorerFile.vue +47 -38
  13. package/runtime/components/Core/Explorer/CoreExplorerFolder.vue +0 -1
  14. package/runtime/components/Core/Time/CoreTime.vue +10 -7
  15. package/runtime/components/Core/Window/CoreWindow.vue +46 -34
  16. package/runtime/components/Core/Window/CoreWindowContent.vue +3 -5
  17. package/runtime/components/Core/Window/CoreWindowNav.vue +12 -7
  18. package/runtime/composables/useApplicationEntries.ts +51 -0
  19. package/runtime/composables/useApplicationManager.ts +3 -3
  20. package/runtime/composables/useClipboardFs.ts +11 -11
  21. package/runtime/composables/useDesktopManager.ts +2 -2
  22. package/runtime/composables/useTerminalManager.ts +3 -3
  23. package/runtime/core/controllers/ApplicationController.ts +211 -200
  24. package/runtime/core/controllers/WindowController.ts +349 -312
  25. package/runtime/core/managers/ApplicationManager.ts +240 -196
  26. package/runtime/core/managers/DesktopManager.ts +35 -25
  27. package/runtime/core/managers/TerminalManager.ts +36 -32
  28. package/runtime/plugins/resize.client.ts +4 -4
  29. package/runtime/stores/storeApplication.ts +235 -0
  30. package/runtime/stores/storeApplicationMeta.ts +12 -8
  31. package/runtime/stores/storeApplicationWindows.ts +16 -12
  32. package/runtime/stores/storeDesktop.ts +33 -29
  33. package/runtime/stores/storeDesktopVolume.ts +12 -12
  34. package/runtime/stores/storeDesktopWindow.ts +13 -13
  35. package/runtime/stores/storeDesktopWorkspace.ts +35 -31
  36. package/runtime/utils/utilApp.ts +27 -22
  37. package/runtime/utils/utilCommon.ts +43 -43
  38. package/runtime/utils/utilDebug.ts +17 -17
  39. package/runtime/utils/utilDesktop.ts +4 -4
  40. package/runtime/utils/utilTerminal.ts +6 -5
  41. package/runtime/utils/utilWindow.ts +11 -11
  42. package/test/fixtures/basic/app.vue +1 -2
  43. package/test/fixtures/basic/nuxt.config.ts +1 -3
  44. package/tsconfig.app.json +1 -1
  45. package/tsconfig.json +1 -1
  46. package/types/index.d.ts +235 -207
  47. package/vitest.config.ts +3 -3
  48. package/.editorconfig +0 -12
  49. package/eslint.config.mjs +0 -30
  50. package/runtime/composables/useAppEntries.ts +0 -36
@@ -0,0 +1,235 @@
1
+ import { defineStore } from 'pinia'
2
+ import { reactive, ref, computed } from 'vue'
3
+ import { nanoid } from 'nanoid'
4
+ import { WindowController } from '../core/controllers/WindowController'
5
+ import { useApplicationManager } from '../composables/useApplicationManager'
6
+ import { useApplicationWindowsStore } from './storeApplicationWindows'
7
+ import { useApplicationMetaStore } from './storeApplicationMeta'
8
+ import { useTerminalManager } from '../composables/useTerminalManager'
9
+ import { useDesktopManager } from '../composables/useDesktopManager'
10
+ import { useDesktopWorkspaceStore } from './storeDesktopWorkspace'
11
+ import { debugLog, debugError } from '../utils/utilDebug'
12
+
13
+ interface WindowStoredState {
14
+ model: string
15
+ state: any
16
+ meta?: any
17
+ }
18
+
19
+ export const useApplicationStore = function(applicationId: string, applicationConfig: ApplicationConfig) {
20
+ return defineStore(`owd/application/${applicationId}`, () => {
21
+ // reactive state
22
+ const windows = reactive(new Map<string, WindowController>())
23
+ const isRunning = ref<boolean>(false)
24
+
25
+ // composables e stores esterni
26
+ const applicationManager = useApplicationManager()
27
+ const terminalManager = useTerminalManager()
28
+ const desktopManager = useDesktopManager()
29
+ const desktopWorkspaceStore = useDesktopWorkspaceStore()
30
+
31
+ // stores figli
32
+ let storeWindows: ReturnType<typeof useApplicationWindowsStore>
33
+ let storeMeta: ReturnType<typeof useApplicationMetaStore>
34
+
35
+ // init application
36
+ async function initApplication() {
37
+ storeWindows = useApplicationWindowsStore(applicationId)
38
+ storeMeta = useApplicationMetaStore(applicationId)
39
+
40
+ // Fornisci applicazione di default se presente
41
+ if (applicationConfig.provides) {
42
+ const existingDefault = desktopManager.getDefaultApp(
43
+ applicationConfig.provides.name,
44
+ )
45
+ if (!existingDefault) {
46
+ desktopManager.setDefaultApp(
47
+ applicationConfig.provides.name,
48
+ store, // store o qualcosa che rappresenta questa app?
49
+ applicationConfig.entries![applicationConfig.provides.entry]!,
50
+ )
51
+ debugLog(
52
+ `${applicationConfig.title} set as predefined app for "${applicationConfig.provides.name}"`,
53
+ )
54
+ }
55
+ }
56
+
57
+ // registra comandi terminale
58
+ if (applicationConfig.commands) {
59
+ for (const commandKey of Object.keys(applicationConfig.commands)) {
60
+ terminalManager.addCommand({
61
+ applicationId,
62
+ name: commandKey,
63
+ })
64
+ }
65
+ }
66
+
67
+ if (storeWindows.$persistedState) await storeWindows.$persistedState.isReady()
68
+ if (storeMeta.$persistedState) await storeMeta.$persistedState.isReady()
69
+
70
+ await restoreApplication()
71
+
72
+ if (typeof applicationConfig.onReady === 'function') {
73
+ applicationConfig.onReady(store)
74
+ }
75
+ }
76
+
77
+ // restore
78
+ async function restoreApplication() {
79
+ if (typeof applicationConfig.onRestore === 'function') {
80
+ await applicationConfig.onRestore(store)
81
+ }
82
+
83
+ if (!storeWindows.windows || Object.keys(storeWindows.windows).length === 0) {
84
+ return false
85
+ }
86
+
87
+ restoreWindows()
88
+ setRunning(true)
89
+ return true
90
+ }
91
+
92
+ function restoreWindows() {
93
+ Object.keys(storeWindows.windows).forEach((windowId) => {
94
+ const windowStore = storeWindows.windows[windowId]
95
+ if (windowStore) {
96
+ openWindow(windowStore.model, windowStore, { isRestoring: true })
97
+ }
98
+ })
99
+ debugLog('Windows restored', windows)
100
+ }
101
+
102
+ // open window
103
+ function openWindow(
104
+ model: string,
105
+ windowStoredState?: WindowStoredState,
106
+ meta?: any,
107
+ ): WindowController | undefined {
108
+ if (!applicationConfig.windows || !applicationConfig.windows.hasOwnProperty(model)) {
109
+ debugError(`Window model "${model}" not found`)
110
+ return
111
+ }
112
+
113
+ let windowId: string
114
+
115
+ if (!windowStoredState) {
116
+ windowId = `${model}-${nanoid(6)}`
117
+ const windowConfig = applicationConfig.windows[model] as WindowConfig
118
+ const screenHeight = window.innerHeight
119
+ const centerY = (screenHeight - Number(windowConfig.size.height)) / 2
120
+ const positionY =
121
+ windowConfig.position?.y !== undefined
122
+ ? window.scrollY + windowConfig.position.y
123
+ : window.scrollY + centerY
124
+
125
+ storeWindows.windows[windowId] = {
126
+ model,
127
+ state: {
128
+ id: windowId,
129
+ active: true,
130
+ focused: false,
131
+ position: {
132
+ x: windowConfig.position?.x,
133
+ y: positionY,
134
+ },
135
+ createdAt: +new Date(),
136
+ workspace: desktopWorkspaceStore.active,
137
+ },
138
+ meta,
139
+ }
140
+
141
+ windowStoredState = storeWindows.windows[windowId]
142
+ } else {
143
+ windowId = windowStoredState.state.id
144
+ }
145
+
146
+ const windowConfig = applicationConfig.windows[model] as WindowConfig
147
+ const windowController = new WindowController(store, model, windowConfig, windowStoredState!)
148
+
149
+ if (!meta?.isRestoring) {
150
+ windowController.actions.bringToFront()
151
+ }
152
+
153
+ windows.set(windowId, windowController)
154
+ setRunning(true)
155
+
156
+ return windowController
157
+ }
158
+
159
+ // close window
160
+ function closeWindow(windowId: string) {
161
+ delete storeWindows.windows[windowId]
162
+ windows.delete(windowId)
163
+
164
+ if (windows.size === 0) {
165
+ applicationManager.closeApp(applicationId)
166
+ }
167
+ }
168
+
169
+ // close all windows
170
+ function closeAllWindows() {
171
+ storeWindows.windows = {}
172
+ windows.clear()
173
+ }
174
+
175
+ // getters
176
+ const windowsOpened = computed(() => windows)
177
+
178
+ function getWindowById(id: string) {
179
+ return windows.get(id)
180
+ }
181
+
182
+ function getWindowsByModel(model: string) {
183
+ return Array.from(windows.values()).filter((w) => w.model === model)
184
+ }
185
+
186
+ function getFirstWindowByModel(model: string) {
187
+ return Array.from(windows.values()).find((w) => w.model === model)
188
+ }
189
+
190
+ function setRunning(value: boolean) {
191
+ isRunning.value = value
192
+ }
193
+
194
+ // meta management
195
+ const meta = computed(() => storeMeta.meta)
196
+
197
+ function getMeta(key: string) {
198
+ return meta.value[key]
199
+ }
200
+
201
+ function setMeta(key: string, value: any) {
202
+ storeMeta.meta[key] = value
203
+ }
204
+
205
+ // command exec
206
+ async function execCommand(command: string) {
207
+ return applicationManager.execAppCommand(applicationId, command)
208
+ }
209
+
210
+ const store = {
211
+ id: applicationId,
212
+ config: applicationConfig,
213
+ storeWindows,
214
+ storeMeta,
215
+ windows,
216
+ isRunning,
217
+ initApplication,
218
+ restoreApplication,
219
+ openWindow,
220
+ closeWindow,
221
+ closeAllWindows,
222
+ windowsOpened,
223
+ getWindowById,
224
+ getWindowsByModel,
225
+ getFirstWindowByModel,
226
+ setRunning,
227
+ meta,
228
+ getMeta,
229
+ setMeta,
230
+ execCommand,
231
+ }
232
+
233
+ return store
234
+ })()
235
+ }
@@ -1,11 +1,15 @@
1
- import {defineStore} from "pinia"
1
+ import { defineStore } from 'pinia'
2
2
 
3
3
  export const useApplicationMetaStore = (appId: string, states: any = {}) => {
4
- return defineStore(`owd/application/${appId}/meta`, () => {
5
- return states
6
- }, {
7
- persistedState: {
8
- persist: true
9
- },
10
- })
4
+ return defineStore(
5
+ `owd/application/${appId}/meta`,
6
+ () => {
7
+ return states
8
+ },
9
+ {
10
+ persistedState: {
11
+ persist: true,
12
+ },
13
+ },
14
+ )
11
15
  }
@@ -1,16 +1,20 @@
1
- import {defineStore} from "pinia"
2
- import {ref} from "vue"
1
+ import { defineStore } from 'pinia'
2
+ import { ref } from 'vue'
3
3
 
4
4
  export const useApplicationWindowsStore = (appId: string) => {
5
- return defineStore(`owd/application/${appId}/windows`, () => {
6
- const windows: Ref<{[windowId: string]: WindowStoredState}> = ref({})
5
+ return defineStore(
6
+ `owd/application/${appId}/windows`,
7
+ () => {
8
+ const windows: Ref<{ [windowId: string]: WindowStoredState }> = ref({})
7
9
 
8
- return {
9
- windows,
10
- }
11
- }, {
12
- persistedState: {
13
- persist: true
14
- },
15
- })()
10
+ return {
11
+ windows,
12
+ }
13
+ },
14
+ {
15
+ persistedState: {
16
+ persist: true,
17
+ },
18
+ },
19
+ )()
16
20
  }
@@ -1,39 +1,43 @@
1
- import {defineStore} from "pinia"
2
- import {ref} from "vue"
1
+ import { defineStore } from 'pinia'
2
+ import { ref } from 'vue'
3
3
 
4
- export const useDesktopStore = defineStore('owd/desktop', () => {
4
+ export const useDesktopStore = defineStore(
5
+ 'owd/desktop',
6
+ () => {
5
7
  const state = ref<{
6
- workspace: {
7
- overview: boolean
8
- active: string
9
- list: string[]
10
- }
11
- volume: {
12
- master: number
13
- }
14
- window: {
15
- positionZ: number
16
- }
8
+ workspace: {
9
+ overview: boolean
10
+ active: string
11
+ list: string[]
12
+ }
13
+ volume: {
14
+ master: number
15
+ }
16
+ window: {
17
+ positionZ: number
18
+ }
17
19
  }>({
18
- workspace: {
19
- overview: false,
20
- active: '',
21
- list: [],
22
- },
23
- volume: {
24
- master: 100,
25
- },
26
- window: {
27
- positionZ: 0
28
- }
20
+ workspace: {
21
+ overview: false,
22
+ active: '',
23
+ list: [],
24
+ },
25
+ volume: {
26
+ master: 100,
27
+ },
28
+ window: {
29
+ positionZ: 0,
30
+ },
29
31
  })
30
32
 
31
33
  return {
32
- state
34
+ state,
33
35
  }
34
- }, {
36
+ },
37
+ {
35
38
  // @ts-expect-error
36
39
  persistedState: {
37
- persist: true
40
+ persist: true,
38
41
  },
39
- })
42
+ },
43
+ )
@@ -1,18 +1,18 @@
1
- import {defineStore} from "pinia"
2
- import {computed} from "vue"
3
- import {useDesktopStore} from "./storeDesktop"
1
+ import { defineStore } from 'pinia'
2
+ import { computed } from 'vue'
3
+ import { useDesktopStore } from './storeDesktop'
4
4
 
5
5
  export const useDesktopVolumeStore = defineStore('owd/desktop/volume', () => {
6
- const desktopStore = useDesktopStore()
6
+ const desktopStore = useDesktopStore()
7
7
 
8
- const master = computed(() => desktopStore.state.volume.master)
8
+ const master = computed(() => desktopStore.state.volume.master)
9
9
 
10
- function setMasterVolume(value: number) {
11
- desktopStore.state.volume.master = value
12
- }
10
+ function setMasterVolume(value: number) {
11
+ desktopStore.state.volume.master = value
12
+ }
13
13
 
14
- return {
15
- master,
16
- setMasterVolume
17
- }
14
+ return {
15
+ master,
16
+ setMasterVolume,
17
+ }
18
18
  })
@@ -1,20 +1,20 @@
1
- import {defineStore} from "pinia"
2
- import {computed} from "vue"
3
- import {useDesktopStore} from "./storeDesktop"
1
+ import { defineStore } from 'pinia'
2
+ import { computed } from 'vue'
3
+ import { useDesktopStore } from './storeDesktop'
4
4
 
5
5
  export const useDesktopWindowStore = defineStore('owd/desktop/window', () => {
6
- const desktopStore = useDesktopStore()
6
+ const desktopStore = useDesktopStore()
7
7
 
8
- const positionZ = computed(() => desktopStore.state.window.positionZ)
8
+ const positionZ = computed(() => desktopStore.state.window.positionZ)
9
9
 
10
- function incrementPositionZ() {
11
- desktopStore.state.window.positionZ++
10
+ function incrementPositionZ() {
11
+ desktopStore.state.window.positionZ++
12
12
 
13
- return desktopStore.state.window.positionZ
14
- }
13
+ return desktopStore.state.window.positionZ
14
+ }
15
15
 
16
- return {
17
- positionZ,
18
- incrementPositionZ
19
- }
16
+ return {
17
+ positionZ,
18
+ incrementPositionZ,
19
+ }
20
20
  })
@@ -1,59 +1,63 @@
1
- import {defineStore} from "pinia"
2
- import {computed} from "vue"
3
- import {useDesktopStore} from "./storeDesktop"
4
- import {nanoid} from "nanoid";
5
-
6
- export const useDesktopWorkspaceStore = defineStore('owd/desktop/workspace', () => {
1
+ import { defineStore } from 'pinia'
2
+ import { computed } from 'vue'
3
+ import { useDesktopStore } from './storeDesktop'
4
+ import { nanoid } from 'nanoid'
5
+
6
+ export const useDesktopWorkspaceStore = defineStore(
7
+ 'owd/desktop/workspace',
8
+ () => {
7
9
  const desktopStore = useDesktopStore()
8
10
 
9
11
  const active = computed(() => {
10
- return desktopStore.state.workspace.active
12
+ return desktopStore.state.workspace.active
11
13
  })
12
14
 
13
15
  const overview = computed(() => {
14
- return desktopStore.state.workspace.overview
16
+ return desktopStore.state.workspace.overview
15
17
  })
16
18
 
17
19
  const list = computed(() => {
18
- return desktopStore.state.workspace.list
20
+ return desktopStore.state.workspace.list
19
21
  })
20
22
 
21
23
  function setupWorkspaces() {
22
- if (desktopStore.state.workspace.list.length === 0) {
23
- createWorkspace()
24
- desktopStore.state.workspace.active = desktopStore.state.workspace.list[0] as string
25
- }
26
-
27
- if (desktopStore.state.workspace.list.length === 1) {
28
- createWorkspace()
29
- }
24
+ if (desktopStore.state.workspace.list.length === 0) {
25
+ createWorkspace()
26
+ desktopStore.state.workspace.active = desktopStore.state.workspace
27
+ .list[0] as string
28
+ }
29
+
30
+ if (desktopStore.state.workspace.list.length === 1) {
31
+ createWorkspace()
32
+ }
30
33
  }
31
34
 
32
35
  function setOverview(value: boolean) {
33
- desktopStore.state.workspace.overview = value
36
+ desktopStore.state.workspace.overview = value
34
37
  }
35
38
 
36
39
  function setWorkspace(value: string) {
37
- desktopStore.state.workspace.active = value
40
+ desktopStore.state.workspace.active = value
38
41
  }
39
42
 
40
43
  function createWorkspace() {
41
- desktopStore.state.workspace.list.push(nanoid(8))
44
+ desktopStore.state.workspace.list.push(nanoid(8))
42
45
  }
43
46
 
44
47
  const workspaceActiveIndex = computed(() => {
45
- return desktopStore.state.workspace.list.findIndex(
46
- workspace => workspace === desktopStore.state.workspace.active
47
- )
48
+ return desktopStore.state.workspace.list.findIndex(
49
+ (workspace) => workspace === desktopStore.state.workspace.active,
50
+ )
48
51
  })
49
52
 
50
53
  return {
51
- active,
52
- overview,
53
- list,
54
- workspaceActiveIndex,
55
- setupWorkspaces,
56
- setOverview,
57
- setWorkspace,
54
+ active,
55
+ overview,
56
+ list,
57
+ workspaceActiveIndex,
58
+ setupWorkspaces,
59
+ setOverview,
60
+ setWorkspace,
58
61
  }
59
- })
62
+ },
63
+ )
@@ -1,32 +1,37 @@
1
- import type {Nuxt} from "@nuxt/schema";
1
+ import type { Nuxt } from '@nuxt/schema'
2
2
 
3
- export function normalizeApplicationConfig(config: ApplicationConfig): ApplicationConfig {
4
- const normalizedEntries: Record<string, ApplicationEntry> = {}
3
+ export function normalizeApplicationConfig(
4
+ config: ApplicationConfig,
5
+ ): ApplicationConfig {
6
+ const normalizedEntries: Record<string, ApplicationEntry> = {}
5
7
 
8
+ if (config.entries) {
6
9
  for (const [key, entry] of Object.entries(config.entries)) {
7
- normalizedEntries[key] = {
8
- ...entry,
9
- title: entry.title ?? config.title,
10
- icon: entry.icon ?? config.icon,
11
- category: entry.category ?? config.category,
12
- visibility: entry.visibility ?? 'primary',
13
- }
10
+ normalizedEntries[key] = {
11
+ ...entry,
12
+ title: entry.title ?? config.title,
13
+ icon: entry.icon ?? config.icon,
14
+ category: entry.category ?? config.category,
15
+ visibility: entry.visibility ?? 'primary',
16
+ }
14
17
  }
18
+ }
15
19
 
16
- return {
17
- ...config,
18
- version: config.version ?? 'unknown',
19
- description: config.description ?? '',
20
- category: config.category ?? 'other',
21
- entries: normalizedEntries,
22
- }
20
+ return {
21
+ ...config,
22
+ version: config.version ?? 'unknown',
23
+ description: config.description ?? '',
24
+ category: config.category ?? 'other',
25
+ entries: normalizedEntries,
26
+ }
23
27
  }
24
28
 
25
29
  export function registerTailwindPath(nuxt: Nuxt, path: string) {
26
- nuxt.options.runtimeConfig.app.owd = nuxt.options.runtimeConfig.app.owd || {}
27
- nuxt.options.runtimeConfig.app.owd.tailwindPaths = nuxt.options.runtimeConfig.app.owd.tailwindPaths || []
30
+ nuxt.options.runtimeConfig.app.owd = nuxt.options.runtimeConfig.app.owd || {}
31
+ nuxt.options.runtimeConfig.app.owd.tailwindPaths =
32
+ nuxt.options.runtimeConfig.app.owd.tailwindPaths || []
28
33
 
29
- if (!nuxt.options.runtimeConfig.app.owd.tailwindPaths.includes(path)) {
30
- nuxt.options.runtimeConfig.app.owd.tailwindPaths.push(path)
31
- }
34
+ if (!nuxt.options.runtimeConfig.app.owd.tailwindPaths.includes(path)) {
35
+ nuxt.options.runtimeConfig.app.owd.tailwindPaths.push(path)
36
+ }
32
37
  }