@owdproject/core 3.0.0-alpha.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.
- package/LICENSE +674 -0
- package/README.md +141 -0
- package/index.ts +10 -0
- package/module/index.ts +146 -0
- package/package.json +45 -0
- package/runtime/components/Core/Application/CoreApplicationRender.vue +17 -0
- package/runtime/components/Core/Application/CoreApplicationWindowsRender.vue +19 -0
- package/runtime/components/Core/Background/CoreBackground.vue +17 -0
- package/runtime/components/Core/Desktop/CoreDesktop.vue +77 -0
- package/runtime/components/Core/Explorer/CoreExplorerFile.vue +67 -0
- package/runtime/components/Core/Explorer/CoreExplorerFolder.vue +11 -0
- package/runtime/components/Core/Time/CoreTime.vue +53 -0
- package/runtime/components/Core/Window/CoreWindow.vue +157 -0
- package/runtime/components/Core/Window/CoreWindowContent.vue +30 -0
- package/runtime/components/Core/Window/CoreWindowNav.vue +43 -0
- package/runtime/composables/useAppEntries.ts +21 -0
- package/runtime/composables/useApplicationManager.ts +7 -0
- package/runtime/composables/useApplicationState.ts +19 -0
- package/runtime/composables/useDesktopManager.ts +7 -0
- package/runtime/composables/useTerminalManager.ts +3 -0
- package/runtime/core/controllers/ApplicationController.ts +209 -0
- package/runtime/core/controllers/WindowController.ts +413 -0
- package/runtime/core/managers/ApplicationManager.ts +256 -0
- package/runtime/core/managers/DesktopManager.ts +41 -0
- package/runtime/plugins/resize.client.ts +6 -0
- package/runtime/stores/storeDesktop.ts +39 -0
- package/runtime/stores/storeDesktopVolume.ts +17 -0
- package/runtime/stores/storeDesktopWindow.ts +20 -0
- package/runtime/stores/storeDesktopWorkspace.ts +59 -0
- package/runtime/utils/utilsCommon.ts +35 -0
- package/runtime/utils/utilsDebug.ts +30 -0
- package/runtime/utils/utilsDesktop.ts +12 -0
- package/runtime/utils/utilsTerminal.ts +5 -0
- package/runtime/utils/utilsWindow.ts +14 -0
- package/tsconfig.json +3 -0
- package/types/index.d.ts +9 -0
- package/types/owd.d.ts +313 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import {useApplicationManager} from '../../composables/useApplicationManager'
|
|
2
|
+
import {useDesktopWindowStore} from '../../stores/storeDesktopWindow'
|
|
3
|
+
import {deepClone} from '../../utils/utilsCommon'
|
|
4
|
+
import {markRaw} from '@vue/reactivity'
|
|
5
|
+
import {defineAsyncComponent} from "vue"
|
|
6
|
+
|
|
7
|
+
export class WindowController implements IWindowController {
|
|
8
|
+
public readonly application: IApplicationController
|
|
9
|
+
|
|
10
|
+
public readonly instanced: boolean = true
|
|
11
|
+
public readonly model: string
|
|
12
|
+
|
|
13
|
+
public config: WindowConfig = {
|
|
14
|
+
title: '',
|
|
15
|
+
category: '',
|
|
16
|
+
|
|
17
|
+
component: undefined,
|
|
18
|
+
|
|
19
|
+
// position
|
|
20
|
+
position: {
|
|
21
|
+
x: 0,
|
|
22
|
+
y: 0,
|
|
23
|
+
z: 0,
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// sizes
|
|
27
|
+
size: {
|
|
28
|
+
width: undefined,
|
|
29
|
+
height: undefined,
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
// minimize
|
|
33
|
+
minimizable: true,
|
|
34
|
+
|
|
35
|
+
// maximize
|
|
36
|
+
maximized: false,
|
|
37
|
+
maximizable: false,
|
|
38
|
+
|
|
39
|
+
// destroy
|
|
40
|
+
destroyable: true,
|
|
41
|
+
|
|
42
|
+
// draggable
|
|
43
|
+
draggable: true,
|
|
44
|
+
|
|
45
|
+
// resizable
|
|
46
|
+
resizable: true,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public override: WindowOverride = {}
|
|
50
|
+
|
|
51
|
+
public meta: any = {}
|
|
52
|
+
private storedState: WindowStoredState
|
|
53
|
+
|
|
54
|
+
constructor(
|
|
55
|
+
application: IApplicationController,
|
|
56
|
+
model: string,
|
|
57
|
+
windowConfig: WindowConfig,
|
|
58
|
+
windowStoredState: WindowStoredState,
|
|
59
|
+
) {
|
|
60
|
+
this.application = application
|
|
61
|
+
this.model = model
|
|
62
|
+
this.storedState = windowStoredState
|
|
63
|
+
|
|
64
|
+
this.setConfig(windowConfig)
|
|
65
|
+
|
|
66
|
+
this.restoreState()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private setConfig(config: WindowConfig) {
|
|
70
|
+
// component
|
|
71
|
+
if (config.component) {
|
|
72
|
+
this.config.component = markRaw(
|
|
73
|
+
defineAsyncComponent(config.component)
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// title
|
|
78
|
+
if (config.title) this.config.title = config.title
|
|
79
|
+
if (config.icon) this.config.icon = config.icon
|
|
80
|
+
|
|
81
|
+
// position
|
|
82
|
+
if (!this.config.position) this.config.position = { x: 0, y: 0, z: 0 }
|
|
83
|
+
if (config.position?.x) this.config.position.x = config.position.x
|
|
84
|
+
if (config.position?.y) this.config.position.y = config.position.y
|
|
85
|
+
if (config.position?.z) this.config.position.z = config.position.z
|
|
86
|
+
|
|
87
|
+
// sizes
|
|
88
|
+
if (config.size?.width) this.config.size.width = config.size.width
|
|
89
|
+
if (config.size?.height) this.config.size.height = config.size.height
|
|
90
|
+
if (config.size?.minWidth) this.config.size.minWidth = config.size.minWidth
|
|
91
|
+
if (config.size?.minHeight) this.config.size.minHeight = config.size.minHeight
|
|
92
|
+
if (config.size?.maxWidth) this.config.size.maxWidth = config.size.maxWidth
|
|
93
|
+
if (config.size?.maxHeight) this.config.size.maxHeight = config.size.maxHeight
|
|
94
|
+
|
|
95
|
+
// minimize
|
|
96
|
+
if (typeof config.minimizable !== 'undefined') {
|
|
97
|
+
this.config.minimizable = config.minimizable
|
|
98
|
+
}
|
|
99
|
+
if (typeof config.maximizable !== 'undefined') {
|
|
100
|
+
this.config.maximizable = config.maximizable
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// maximize
|
|
104
|
+
if (typeof config.maximized !== 'undefined') {
|
|
105
|
+
this.config.maximized = config.maximized
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// draggable
|
|
109
|
+
if (typeof config.draggable !== 'undefined') {
|
|
110
|
+
this.config.draggable = config.draggable
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// resizable
|
|
114
|
+
if (typeof config.resizable !== 'undefined') {
|
|
115
|
+
this.config.resizable = config.resizable
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// destroy
|
|
119
|
+
if (typeof config.destroyable !== 'undefined') {
|
|
120
|
+
this.config.destroyable = config.destroyable
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// state
|
|
125
|
+
|
|
126
|
+
get state() {
|
|
127
|
+
return this.storedState.state
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private restoreState() {
|
|
131
|
+
if (!this.state.pinned) this.state.pinned = this.config.pinned
|
|
132
|
+
if (!this.state.position) this.state.position = deepClone(this.config.position)
|
|
133
|
+
|
|
134
|
+
if (!this.state.minimizable) this.state.minimizable = this.config.minimizable
|
|
135
|
+
if (!this.state.maximized) this.state.maximized = this.config.maximized
|
|
136
|
+
if (!this.state.destroyable) this.state.destroyable = this.config.destroyable
|
|
137
|
+
if (!this.state.draggable) this.state.draggable = this.config.draggable
|
|
138
|
+
if (!this.state.resizable) this.state.resizable = this.config.resizable
|
|
139
|
+
|
|
140
|
+
if (!this.state.size) {
|
|
141
|
+
this.state.size = deepClone(this.config.size)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// position
|
|
146
|
+
|
|
147
|
+
private setPosition(data: { x: number, y: number}) {
|
|
148
|
+
if (!this.state.position) {
|
|
149
|
+
this.state.position = { x: 0, y: 0}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.state.position.x = data.x
|
|
153
|
+
this.state.position.y = data.y
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private setActive(value: boolean) {
|
|
157
|
+
this.state.active = value
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private setFocus(value: boolean) {
|
|
161
|
+
this.state.focused = value
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private bringToFront() {
|
|
165
|
+
const applicationManager = useApplicationManager()
|
|
166
|
+
const desktopWindowStore = useDesktopWindowStore()
|
|
167
|
+
|
|
168
|
+
if (!this.state.position) {
|
|
169
|
+
this.state.position = { x: 0, y: 0, z: 0 }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// already focused
|
|
173
|
+
if (this.state.focused) {
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// set focus false on all other windows
|
|
178
|
+
for (const [windowId, window] of applicationManager.windowsOpened) {
|
|
179
|
+
window.actions.setFocus(false)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
this.setFocus(true)
|
|
183
|
+
|
|
184
|
+
this.state.position.z = desktopWindowStore.incrementPositionZ()
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// common
|
|
188
|
+
|
|
189
|
+
get title(): string {
|
|
190
|
+
if (typeof this.override.title !== 'undefined') {
|
|
191
|
+
return this.override.title
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (this.config.title) {
|
|
195
|
+
return this.config.title
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return this.application.config.title
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
get icon() {
|
|
202
|
+
if (typeof this.override.icon !== 'undefined') {
|
|
203
|
+
return this.override.icon
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (this.config.icon) {
|
|
207
|
+
return this.config.icon
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return this.application.config.icon
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// sizes
|
|
214
|
+
|
|
215
|
+
get width() {
|
|
216
|
+
if (typeof this.state.size?.width === 'undefined') {
|
|
217
|
+
return this.config.size.width
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return this.state.size.width
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
get maxWidth() {
|
|
224
|
+
if (typeof this.state.size?.maxWidth === 'undefined') {
|
|
225
|
+
return this.config.size.maxWidth
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return this.state.size.maxWidth
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
get minWidth() {
|
|
232
|
+
if (typeof this.state.size?.minWidth === 'undefined') {
|
|
233
|
+
return this.config.size.minWidth
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return this.state.size.minWidth
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
get height() {
|
|
240
|
+
if (typeof this.state.size?.height === 'undefined') {
|
|
241
|
+
return this.config.size.height
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return this.state.size.height
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
get maxHeight() {
|
|
248
|
+
if (typeof this.state.size?.maxHeight === 'undefined') {
|
|
249
|
+
return this.config.size.maxHeight ?? 600
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return this.state.size.maxHeight
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
get minHeight() {
|
|
256
|
+
if (typeof this.state.size?.minHeight === 'undefined') {
|
|
257
|
+
return this.config.size.minHeight
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return this.state.size.minHeight
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private setSize(data: { width: number, height: number}) {
|
|
264
|
+
if (!this.state.size) {
|
|
265
|
+
this.state.size = { width: undefined, height: undefined }
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
this.state.size.width = data.width
|
|
269
|
+
this.state.size.height = data.height
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// minimize
|
|
273
|
+
|
|
274
|
+
get isMinimizable() {
|
|
275
|
+
if (typeof this.state.minimizable === 'undefined') {
|
|
276
|
+
return !!this.config.minimizable
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return this.state.minimizable
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private minimize() {
|
|
283
|
+
if (!this.isMinimizable) {
|
|
284
|
+
return false
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
this.state.active = false
|
|
288
|
+
return true
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private toggleMinimize() {
|
|
292
|
+
this.state.active = !this.state.active
|
|
293
|
+
this.bringToFront()
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// maximize
|
|
297
|
+
|
|
298
|
+
get isMaximizable() {
|
|
299
|
+
if (typeof this.state.maximizable === 'undefined') {
|
|
300
|
+
return !!this.config.maximizable
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return this.state.maximizable
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
get isMaximized() {
|
|
307
|
+
if (typeof this.state.maximized === 'undefined') {
|
|
308
|
+
return !!this.config.maximized
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return this.state.maximized
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private toggleMaximize() {
|
|
315
|
+
if (!this.isMaximizable) {
|
|
316
|
+
return false
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
this.state.maximized = !this.state.maximized
|
|
320
|
+
return true
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private maximize() {
|
|
324
|
+
if (!this.isMaximizable) {
|
|
325
|
+
return false
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
this.state.maximized = true
|
|
329
|
+
return true
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
private unmaximize() {
|
|
333
|
+
if (!this.isMaximizable) {
|
|
334
|
+
return false
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
this.state.maximized = false
|
|
338
|
+
return true
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// destroy
|
|
342
|
+
|
|
343
|
+
get isDestroyable() {
|
|
344
|
+
return !!this.state.destroyable
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
private destroy() {
|
|
348
|
+
if (!this.isDestroyable) {
|
|
349
|
+
return false
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
this.application.closeWindow(this.state.id)
|
|
353
|
+
|
|
354
|
+
return true
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// draggable
|
|
358
|
+
get isDraggable() {
|
|
359
|
+
return !!this.state.draggable
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// resizable
|
|
363
|
+
get isResizable() {
|
|
364
|
+
return !!this.state.resizable
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// workspace
|
|
368
|
+
private setWorkspace(workspaceId: string) {
|
|
369
|
+
this.state.workspace = workspaceId
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// override
|
|
373
|
+
|
|
374
|
+
setTitleOverride(value: undefined|string) {
|
|
375
|
+
this.override.title = value
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
resetTitleOverride() {
|
|
379
|
+
this.override.title = undefined
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
get actions() {
|
|
383
|
+
return {
|
|
384
|
+
// position
|
|
385
|
+
setActive: this.setActive.bind(this),
|
|
386
|
+
setFocus: this.setFocus.bind(this),
|
|
387
|
+
bringToFront: this.bringToFront.bind(this),
|
|
388
|
+
setPosition: this.setPosition.bind(this),
|
|
389
|
+
|
|
390
|
+
// size
|
|
391
|
+
setSize: this.setSize.bind(this),
|
|
392
|
+
|
|
393
|
+
// minimize
|
|
394
|
+
minimize: this.minimize.bind(this),
|
|
395
|
+
toggleMinimize: this.toggleMinimize.bind(this),
|
|
396
|
+
|
|
397
|
+
// maximize
|
|
398
|
+
toggleMaximize: this.toggleMaximize.bind(this),
|
|
399
|
+
maximize: this.maximize.bind(this),
|
|
400
|
+
unmaximize: this.unmaximize.bind(this),
|
|
401
|
+
|
|
402
|
+
// destroy
|
|
403
|
+
destroy: this.destroy.bind(this),
|
|
404
|
+
|
|
405
|
+
// workspace
|
|
406
|
+
setWorkspace: this.setWorkspace.bind(this),
|
|
407
|
+
|
|
408
|
+
// override
|
|
409
|
+
setTitleOverride: this.setTitleOverride.bind(this),
|
|
410
|
+
resetTitleOverride: this.resetTitleOverride.bind(this),
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import type {Reactive} from "@vue/reactivity"
|
|
2
|
+
import {reactive, markRaw} from "@vue/reactivity"
|
|
3
|
+
import {ApplicationController} from "../controllers/ApplicationController";
|
|
4
|
+
import {debugLog} from "../../utils/utilsDebug"
|
|
5
|
+
|
|
6
|
+
export class ApplicationManager implements IApplicationManager {
|
|
7
|
+
public apps = reactive(
|
|
8
|
+
new Map<string, IApplicationController>()
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Import applications on nuxt start
|
|
16
|
+
*/
|
|
17
|
+
public async importApps() {
|
|
18
|
+
const {owdConfig} = await import(`~~/owd.config`)
|
|
19
|
+
|
|
20
|
+
if (owdConfig && typeof owdConfig.loader === 'function') {
|
|
21
|
+
await owdConfig.loader()
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Define new application
|
|
27
|
+
*
|
|
28
|
+
* @param id
|
|
29
|
+
* @param config
|
|
30
|
+
*/
|
|
31
|
+
public async defineApp(id: string, config: ApplicationConfig) {
|
|
32
|
+
if (this.isAppDefined(id)) {
|
|
33
|
+
debugLog(`App "${id}" is already defined`);
|
|
34
|
+
return this.apps.get(id)!;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!config.version) config.version = 'unknown'
|
|
38
|
+
if (!config.description) config.description = ''
|
|
39
|
+
if (!config.category) config.category = 'other'
|
|
40
|
+
|
|
41
|
+
const applicationConfig = markRaw(config)
|
|
42
|
+
|
|
43
|
+
const applicationController: IApplicationController = new ApplicationController(id, applicationConfig)
|
|
44
|
+
|
|
45
|
+
// finalize application setup doing other async operations
|
|
46
|
+
await applicationController.initApplication()
|
|
47
|
+
|
|
48
|
+
// define application
|
|
49
|
+
this.apps.set(id, applicationController)
|
|
50
|
+
|
|
51
|
+
return applicationController
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if app has been defned
|
|
56
|
+
*
|
|
57
|
+
* @param id
|
|
58
|
+
*/
|
|
59
|
+
public isAppDefined(id: string) {
|
|
60
|
+
return this.apps.has(id)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Check if app is running
|
|
65
|
+
*
|
|
66
|
+
* @param id
|
|
67
|
+
*/
|
|
68
|
+
public isAppRunning(id: string) {
|
|
69
|
+
if (!this.isAppDefined(id)) {
|
|
70
|
+
throw Error(`App "${id}" is not defined`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const applicationController: IApplicationController = this.apps.get(id)!
|
|
74
|
+
|
|
75
|
+
if (!applicationController.isRunning) {
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return true
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Launch app rntry
|
|
84
|
+
*
|
|
85
|
+
* @param id
|
|
86
|
+
* @param entryKey
|
|
87
|
+
*/
|
|
88
|
+
public async launchAppEntry(id: string, entryKey: string) {
|
|
89
|
+
if (!this.isAppDefined(id)) {
|
|
90
|
+
throw Error(`App "${id}" is not defined`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const applicationController: IApplicationController = this.apps.get(id)!
|
|
94
|
+
|
|
95
|
+
if (applicationController.config.entries && !applicationController.config.entries.hasOwnProperty(entryKey)) {
|
|
96
|
+
throw Error(`App entry "${entryKey}" is not defined in ${id} application`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const entry: ApplicationEntry = applicationController.config.entries[entryKey]!
|
|
100
|
+
|
|
101
|
+
console.log('dio cane', entry)
|
|
102
|
+
|
|
103
|
+
await this.execAppCommand(applicationController.id, entry.command)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Run app command
|
|
108
|
+
*
|
|
109
|
+
* @param id
|
|
110
|
+
* @param command
|
|
111
|
+
*/
|
|
112
|
+
public async execAppCommand(id: string, command: string) {
|
|
113
|
+
if (!this.isAppDefined(id)) {
|
|
114
|
+
throw Error(`App "${id}" is not defined`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const applicationController: IApplicationController = this.apps.get(id)!
|
|
118
|
+
|
|
119
|
+
if (applicationController.config.commands && !applicationController.config.commands.hasOwnProperty(command)) {
|
|
120
|
+
throw Error(`App command "${command}" is not defined in ${id} application`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const commandSplit: string[] = command.split(" ")
|
|
124
|
+
|
|
125
|
+
const commandFn: any = applicationController.config.commands![
|
|
126
|
+
commandSplit[0] as keyof typeof applicationController.config.commands
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
commandFn(applicationController, commandSplit.shift())
|
|
130
|
+
|
|
131
|
+
applicationController.setRunning(true)
|
|
132
|
+
|
|
133
|
+
return applicationController;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Close application
|
|
138
|
+
*
|
|
139
|
+
* @param id
|
|
140
|
+
*/
|
|
141
|
+
public closeApp(id: string) {
|
|
142
|
+
if (!this.isAppDefined(id)) {
|
|
143
|
+
throw Error(`App "${id}" is not defined`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const applicationController: IApplicationController = this.apps.get(id)!
|
|
147
|
+
|
|
148
|
+
applicationController.closeAllWindows()
|
|
149
|
+
applicationController.setRunning(false)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Array of available menu entries for system bars, docks
|
|
154
|
+
*/
|
|
155
|
+
public get appsEntries() {
|
|
156
|
+
const entries: Reactive<ApplicationEntryWithInherited[]> = reactive([])
|
|
157
|
+
|
|
158
|
+
for (const applicationController of this.apps.values()) {
|
|
159
|
+
if (!applicationController.config.entries) {
|
|
160
|
+
continue
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
for (const entryKey of Object.keys(applicationController.config.entries)) {
|
|
164
|
+
const entry: ApplicationEntry = applicationController.config.entries[entryKey]!
|
|
165
|
+
|
|
166
|
+
entries.push({
|
|
167
|
+
application: applicationController,
|
|
168
|
+
title: entry.title !== undefined ? entry.title : applicationController.config.title,
|
|
169
|
+
icon: entry.icon !== undefined ? entry.icon : applicationController.config.icon,
|
|
170
|
+
category: entry.category !== undefined ? entry.category : applicationController.config.category,
|
|
171
|
+
command: entry.command
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return entries
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Array of opened windows for system bars, docks
|
|
181
|
+
*/
|
|
182
|
+
public get windowsOpened() {
|
|
183
|
+
const windows: Reactive<Map<string, IWindowController>[]> = reactive([])
|
|
184
|
+
|
|
185
|
+
for (const applicationController of this.apps.values()) {
|
|
186
|
+
if (applicationController.isRunning) {
|
|
187
|
+
windows.push(...applicationController.windows)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return windows
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Array of opened windows for system bars, docks
|
|
196
|
+
*/
|
|
197
|
+
public get appsRunning() {
|
|
198
|
+
const applications: Reactive<IApplicationController[]> = reactive([])
|
|
199
|
+
|
|
200
|
+
for (const applicationController of this.apps.values()) {
|
|
201
|
+
if (applicationController.isRunning) {
|
|
202
|
+
applications.push(applicationController)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return applications
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public getWindowOpenedId(windowId: string) {
|
|
210
|
+
const mapWindowFound: Map<string, IWindowController> | undefined = this.windowsOpened.find((window: any) => {
|
|
211
|
+
return window[1].state.id === windowId
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
if (mapWindowFound) {
|
|
215
|
+
// @ts-ignore
|
|
216
|
+
return mapWindowFound[1] as IWindowController
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Gets all unique categories from the installed apps
|
|
222
|
+
*/
|
|
223
|
+
public get appCategories(): string[] {
|
|
224
|
+
const categories = new Set<string>()
|
|
225
|
+
|
|
226
|
+
for (const applicationController of this.apps.values()) {
|
|
227
|
+
if (applicationController.config.category) {
|
|
228
|
+
categories.add(applicationController.config.category)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return Array.from(categories).sort()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Gets the apps ordered by category
|
|
236
|
+
*/
|
|
237
|
+
public get appsByCategory(): { [category: string]: IApplicationController[] } {
|
|
238
|
+
const categorizedApps: { [category: string]: IApplicationController[] } = {}
|
|
239
|
+
|
|
240
|
+
for (const applicationController of this.apps.values()) {
|
|
241
|
+
const category = applicationController.config.category || 'other'
|
|
242
|
+
if (!categorizedApps[category]) {
|
|
243
|
+
categorizedApps[category] = []
|
|
244
|
+
}
|
|
245
|
+
categorizedApps[category].push(applicationController)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
for (const category in categorizedApps) {
|
|
249
|
+
categorizedApps[category]!.sort(
|
|
250
|
+
(a, b) => a.config.title.localeCompare(b.config.title)
|
|
251
|
+
)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return categorizedApps
|
|
255
|
+
}
|
|
256
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {deepMerge} from "../../utils/utilsCommon"
|
|
2
|
+
|
|
3
|
+
export class DesktopManager {
|
|
4
|
+
public config: DesktopConfig = {} as DesktopConfig
|
|
5
|
+
private defaultApps: DefaultAppsConfig = {}
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public hasFeature(featureName: string) {
|
|
12
|
+
return this.config.features?.indexOf(featureName) !== -1
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public setConfig(config: DesktopConfig) {
|
|
16
|
+
this.config = config
|
|
17
|
+
this.loadDefaultAppsFromConfig()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public overrideConfig(config: Partial<DesktopConfig>) {
|
|
21
|
+
this.config = deepMerge(this.config, config) as DesktopConfig
|
|
22
|
+
this.loadDefaultAppsFromConfig()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public setDefaultApp(feature: string, application: IApplicationController, entry: ApplicationEntry) {
|
|
26
|
+
this.defaultApps[feature] = {
|
|
27
|
+
application,
|
|
28
|
+
entry
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public getDefaultApp(feature: string): DefaultAppConfig {
|
|
33
|
+
return this.defaultApps[feature] as DefaultAppConfig
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private loadDefaultAppsFromConfig() {
|
|
37
|
+
if (this.config.defaultApps) {
|
|
38
|
+
this.defaultApps = { ...this.config.defaultApps }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|