@owdproject/core 3.3.1 → 4.0.0-alpha.3

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 (93) hide show
  1. package/README.md +91 -59
  2. package/dist/dom/index.d.mts +65 -0
  3. package/dist/dom/index.d.ts +65 -0
  4. package/dist/dom/index.mjs +224 -0
  5. package/dist/events/index.d.mts +70 -0
  6. package/dist/events/index.d.ts +70 -0
  7. package/dist/events/index.mjs +3 -0
  8. package/dist/index.d.mts +73 -0
  9. package/dist/index.d.ts +73 -0
  10. package/dist/index.mjs +115 -0
  11. package/dist/layout/index.d.mts +41 -0
  12. package/dist/layout/index.d.ts +41 -0
  13. package/dist/layout/index.mjs +64 -0
  14. package/dist/machines/index.d.mts +31 -0
  15. package/dist/machines/index.d.ts +31 -0
  16. package/dist/machines/index.mjs +2 -0
  17. package/dist/managers/index.d.mts +117 -0
  18. package/dist/managers/index.d.ts +117 -0
  19. package/dist/managers/index.mjs +6 -0
  20. package/dist/session/index.d.mts +57 -0
  21. package/dist/session/index.d.ts +57 -0
  22. package/dist/session/index.mjs +65 -0
  23. package/dist/shared/core.B0B0KfVK.mjs +865 -0
  24. package/dist/shared/core.B1XxB289.mjs +239 -0
  25. package/dist/shared/core.B3mp7ztE.mjs +237 -0
  26. package/dist/shared/core.BOvFdEVQ.d.ts +114 -0
  27. package/dist/shared/core.CsDFgGnX.mjs +40 -0
  28. package/dist/shared/core.Di1eFcr_.d.mts +114 -0
  29. package/dist/shared/core.Pd_Ogt4g.mjs +101 -0
  30. package/dist/shared/core.b3Xldzyu.mjs +29 -0
  31. package/dist/types/index.d.mts +266 -0
  32. package/dist/types/index.d.ts +266 -0
  33. package/dist/types/index.mjs +1 -0
  34. package/package.json +60 -87
  35. package/bin/cli.js +0 -395
  36. package/bin/desktop.js +0 -5
  37. package/bin/lib/catalog.js +0 -293
  38. package/bin/lib/config.js +0 -109
  39. package/bin/lib/desktopConfig.js +0 -56
  40. package/bin/lib/generateTemplate.js +0 -389
  41. package/bin/lib/install.js +0 -408
  42. package/bin/lib/migrateModulePlayground.config.mjs +0 -164
  43. package/bin/lib/migrateModulePlayground.mjs +0 -313
  44. package/bin/lib/npmVersions.js +0 -124
  45. package/bin/lib/playgroundContext.js +0 -188
  46. package/bin/lib/scaffold.js +0 -197
  47. package/bin/lib/status.js +0 -289
  48. package/bin/lib/validateModule.js +0 -697
  49. package/bin/lib/workspace.js +0 -182
  50. package/bin/owd.js +0 -5
  51. package/bin/tui.js +0 -1379
  52. package/dist/module.d.mts +0 -13
  53. package/dist/module.json +0 -9
  54. package/dist/module.mjs +0 -268
  55. package/dist/types.d.mts +0 -7
  56. package/index.ts +0 -5
  57. package/module.ts +0 -223
  58. package/runtime/components/Desktop/Application/DesktopApplicationRender.vue +0 -20
  59. package/runtime/components/Desktop/Application/DesktopApplicationWindowsRender.vue +0 -38
  60. package/runtime/components/Desktop/Background/DesktopBackground.vue +0 -16
  61. package/runtime/components/Desktop/Core/DesktopCore.vue +0 -90
  62. package/runtime/components/Desktop/Time/DesktopTime.vue +0 -56
  63. package/runtime/components/Desktop/Window/DesktopWindow.vue +0 -204
  64. package/runtime/components/Desktop/Window/DesktopWindowContent.vue +0 -28
  65. package/runtime/components/Desktop/Window/DesktopWindowNav.vue +0 -66
  66. package/runtime/composables/useApplicationEntries.ts +0 -51
  67. package/runtime/composables/useApplicationManager.ts +0 -285
  68. package/runtime/composables/useDesktopManager.ts +0 -49
  69. package/runtime/composables/useTerminalManager.ts +0 -66
  70. package/runtime/composables/useWorkspaceManager.ts +0 -41
  71. package/runtime/internal/controllers/ApplicationController.ts +0 -345
  72. package/runtime/internal/controllers/WindowController.ts +0 -462
  73. package/runtime/plugins/02.desktop-register-desktop-apps.client.ts +0 -17
  74. package/runtime/plugins/resize.client.ts +0 -6
  75. package/runtime/stores/storeApplicationMeta.ts +0 -59
  76. package/runtime/stores/storeApplicationWindows.ts +0 -20
  77. package/runtime/stores/storeDesktop.ts +0 -111
  78. package/runtime/stores/storeDesktopDefaultApps.ts +0 -53
  79. package/runtime/stores/storeDesktopVolume.ts +0 -18
  80. package/runtime/stores/storeDesktopWindow.ts +0 -20
  81. package/runtime/stores/storeDesktopWorkspace.ts +0 -75
  82. package/runtime/utils/captureElementToCanvas.ts +0 -21
  83. package/runtime/utils/explorerEntryPath.ts +0 -10
  84. package/runtime/utils/resolveDesktopConfigPath.ts +0 -52
  85. package/runtime/utils/splitDesktopUserConfig.ts +0 -85
  86. package/runtime/utils/utilApp.ts +0 -37
  87. package/runtime/utils/utilCommon.ts +0 -26
  88. package/runtime/utils/utilDebug.ts +0 -30
  89. package/runtime/utils/utilDesktop.ts +0 -35
  90. package/runtime/utils/utilTerminal.ts +0 -6
  91. package/runtime/utils/utilWindow.ts +0 -15
  92. package/runtime/utils/validateDesktopUserConfig.ts +0 -44
  93. package/types/index.d.ts +0 -420
@@ -1,56 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, onMounted, onUnmounted } from 'vue'
3
- import { computed } from '@vue/reactivity'
4
- import { useI18n } from 'vue-i18n'
5
-
6
- const date: Ref<Date> = ref(new Date())
7
- const { locale } = useI18n()
8
-
9
- let minuteTimeout: any
10
-
11
- onMounted(() => {
12
- function scheduleNextMinute() {
13
- const now = new Date()
14
- const millisecondsToNextMinute =
15
- (60 - now.getSeconds()) * 1000 - now.getMilliseconds()
16
- minuteTimeout = setTimeout(() => {
17
- date.value = new Date()
18
- scheduleNextMinute()
19
- }, millisecondsToNextMinute)
20
- }
21
- scheduleNextMinute()
22
- })
23
-
24
- onUnmounted(() => {
25
- clearTimeout(minuteTimeout)
26
- })
27
-
28
- const time = computed(() => {
29
- if (!date.value) {
30
- return ''
31
- }
32
-
33
- let hours = date.value.getHours()
34
- let minutes: string = date.value.getMinutes().toString()
35
- let period = 'AM'
36
-
37
- if (locale.value !== 'it') {
38
- if (hours >= 12) {
39
- period = 'PM'
40
- if (hours > 12) hours -= 12
41
- } else if (hours === 0) {
42
- hours = 12
43
- }
44
- }
45
-
46
- if (minutes.length === 1) minutes = `0${minutes}`
47
-
48
- return locale.value === 'it'
49
- ? `${hours}:${minutes}`
50
- : `${hours}:${minutes} ${period}`
51
- })
52
- </script>
53
-
54
- <template>
55
- <time class="owd-time" v-text="time" />
56
- </template>
@@ -1,204 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, provide } from 'vue'
3
- import { computed } from '@vue/reactivity'
4
- import { useAppConfig } from 'nuxt/app'
5
- import { handleWindowControllerProps } from '@owdproject/core/runtime/utils/utilWindow'
6
- import { useDesktopWorkspaceStore } from '../../../stores/storeDesktopWorkspace'
7
-
8
- const props = defineProps<{
9
- window?: IWindowController
10
- content?: WindowContent
11
- }>()
12
-
13
- const desktopWorkspaceStore = useDesktopWorkspaceStore()
14
-
15
- const emit = defineEmits([
16
- 'resize:start',
17
- 'resize:move',
18
- 'resize:end',
19
- 'drag:start',
20
- 'drag:move',
21
- 'drag:end',
22
- 'close',
23
- 'open',
24
- 'blur',
25
- 'focus',
26
- 'minimize',
27
- 'restore',
28
- 'maximize',
29
- 'unmaximize',
30
- 'toggle-maximize',
31
- ])
32
-
33
- const appConfig = useAppConfig()
34
- const windowController: IWindowController = handleWindowControllerProps(
35
- props.window,
36
- )
37
-
38
- provide<IWindowController>('windowController', windowController)
39
- provide<WindowContent>('windowContent', props.content ?? {})
40
-
41
- const isDragging = ref(false)
42
- const isResizing = ref(false)
43
-
44
- function onWindowPointerDown() {
45
- windowController?.actions?.setActive(true)
46
- windowController?.actions?.bringToFront()
47
- }
48
-
49
- function onWindowDragStart(data: any) {
50
- isDragging.value = true
51
-
52
- emit('drag:start', data)
53
- }
54
-
55
- function onWindowDragMove(data: any) {
56
- emit('drag:move', data)
57
- }
58
-
59
- function onWindowDragEnd(data: { left: number; top: number }) {
60
- windowController?.actions?.setPosition({
61
- x: data.left,
62
- y: data.top,
63
- })
64
-
65
- isDragging.value = false
66
-
67
- emit('drag:end', data)
68
- }
69
-
70
- function onWindowResizeStart(data: any) {
71
- isResizing.value = true
72
-
73
- emit('resize:start', data)
74
- }
75
-
76
- function onWindowResizeMove(data: any) {
77
- emit('resize:move', data)
78
- }
79
-
80
- /**
81
- * Window end resize event
82
- */
83
- function onWindowResizeEnd(data: {
84
- left: number
85
- top: number
86
- width: number
87
- height: number
88
- }) {
89
- isResizing.value = false
90
-
91
- windowController?.actions?.setPosition({
92
- x: data.left,
93
- y: data.top,
94
- })
95
-
96
- windowController?.actions?.setSize({
97
- width: data.width,
98
- height: data.height,
99
- })
100
-
101
- emit('resize:end', data)
102
- }
103
-
104
- const classes = computed(() => {
105
- const list = ['owd-window']
106
-
107
- if (windowController?.state.focused) {
108
- list.push('owd-window--focused')
109
- }
110
-
111
- if (isDragging.value) {
112
- list.push('owd-window--dragging')
113
- }
114
-
115
- if (isResizing.value) {
116
- list.push('owd-window--resizing')
117
- }
118
-
119
- return list
120
- })
121
-
122
- /** While workspace overview is open, disable vue-resizable chrome drag and use native HTML5 drag to move windows between desktops. */
123
- const workspaceChromeDragSelector = computed(() => {
124
- if (desktopWorkspaceStore.overview) {
125
- return '.owd-window-overview-drag-none'
126
- }
127
- return windowController?.isDraggable
128
- ? '.owd-window-nav__draggable'
129
- : '.owd-window-nav__draggable-none'
130
- })
131
-
132
- function onOverviewNativeDragStart(e: DragEvent) {
133
- if (!desktopWorkspaceStore.overview || !windowController) return
134
- e.stopPropagation()
135
- e.dataTransfer?.setData('text/plain', windowController.state.id)
136
- e.dataTransfer!.effectAllowed = 'move'
137
- try {
138
- const img = new Image()
139
- img.src =
140
- 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
141
- e.dataTransfer?.setDragImage(img, 0, 0)
142
- } catch {
143
- /* noop */
144
- }
145
- }
146
-
147
- /** `fit-parent` clamps drag/resize to the parent box — wrong for viewport-fixed shells (Win11, GNOME). */
148
- const shouldFitParent = computed(
149
- () => appConfig.desktop.windows.position !== 'fixed',
150
- )
151
- </script>
152
-
153
- <template>
154
- <vue-resizable
155
- ref="windowResizableController"
156
- :class="classes"
157
- :width="windowController?.size.width"
158
- :height="windowController?.size.height"
159
- :min-width="windowController?.size.minWidth"
160
- :min-height="windowController?.size.minHeight"
161
- :max-width="windowController?.size.maxWidth"
162
- :max-height="windowController?.size.maxHeight"
163
- :left="windowController?.position?.x"
164
- :top="windowController?.position?.y"
165
- :active="windowController?.isResizable ? undefined : []"
166
- :fit-parent="shouldFitParent"
167
- @drag:start="onWindowDragStart"
168
- @drag:move="onWindowDragMove"
169
- @drag:end="onWindowDragEnd"
170
- @resize:start="onWindowResizeStart"
171
- @resize:move="onWindowResizeMove"
172
- @resize:end="onWindowResizeEnd"
173
- :style="{ zIndex: windowController?.position?.z }"
174
- :drag-selector="workspaceChromeDragSelector"
175
- :draggable="desktopWorkspaceStore.overview"
176
- @pointerdown="onWindowPointerDown"
177
- @dragstart="onOverviewNativeDragStart"
178
- >
179
- <slot />
180
- </vue-resizable>
181
- </template>
182
-
183
- <style scoped lang="scss">
184
- /* vue-resizable sets `.resizable-component { position: relative }` — override so desktop geometry stays consistent */
185
- .owd-window.resizable-component {
186
- position: v-bind('appConfig.desktop.windows.position') !important;
187
- }
188
-
189
- .owd-window {
190
- position: v-bind('appConfig.desktop.windows.position');
191
-
192
- &--dragging,
193
- &--resizing {
194
- :deep(.owd-window__content) {
195
- pointer-events: none;
196
- }
197
- }
198
-
199
- :deep(.owd-window__content) {
200
- overflow-y: auto;
201
- height: 100%;
202
- }
203
- }
204
- </style>
@@ -1,28 +0,0 @@
1
- <script setup lang="ts">
2
- import { inject } from 'vue'
3
- import { computed } from '@vue/reactivity'
4
-
5
- const windowContent = inject<WindowContent>('windowContent')
6
-
7
- const classes = computed(() => {
8
- const list = ['owd-window__content']
9
-
10
- if (windowContent?.centered) {
11
- list.push('owd-window__content--centered')
12
- }
13
-
14
- if (windowContent?.padded) {
15
- list.push('owd-window__content--padded')
16
- }
17
-
18
- return list
19
- })
20
- </script>
21
-
22
- <template>
23
- <div :class="classes">
24
- <slot />
25
- </div>
26
- </template>
27
-
28
- <style scoped lang="scss"></style>
@@ -1,66 +0,0 @@
1
- <script setup lang="ts">
2
- import { inject } from 'vue'
3
- import { computed } from '@vue/reactivity'
4
-
5
- const windowController = inject<IWindowController>('windowController')
6
-
7
- const classes = computed(() => {
8
- const list = ['owd-window-nav']
9
-
10
- if (
11
- typeof windowController?.state.active === 'undefined' ||
12
- !!windowController?.state.active
13
- ) {
14
- list.push('owd-window-nav--active')
15
- }
16
-
17
- if (windowController?.state.focused) {
18
- list.push('owd-window-nav--focused')
19
- }
20
-
21
- return list
22
- })
23
- </script>
24
-
25
- <template>
26
- <div :class="classes">
27
- <div class="owd-window-nav__draggable" />
28
-
29
- <slot />
30
- </div>
31
- </template>
32
-
33
- <style lang="scss">
34
- /**
35
- * Title/icon sit above the drag layer in DOM order; use pointer-events so
36
- * mousedown reaches `.owd-window-nav__draggable` for vue-resizable. Window
37
- * controls stay clickable.
38
- */
39
- .owd-window-nav {
40
- position: relative;
41
- display: flex;
42
- align-items: stretch;
43
- width: 100%;
44
- min-height: 0;
45
-
46
- &__draggable {
47
- position: absolute;
48
- inset: 0;
49
- z-index: 1;
50
- }
51
-
52
- > :not(.owd-window-nav__draggable) {
53
- position: relative;
54
- z-index: 2;
55
- pointer-events: none;
56
- }
57
-
58
- > .owd-window-nav__btn-group {
59
- pointer-events: auto;
60
- }
61
-
62
- > .owd-window-nav__interactive {
63
- pointer-events: auto;
64
- }
65
- }
66
- </style>
@@ -1,51 +0,0 @@
1
- import { useApplicationManager } from './useApplicationManager'
2
- import { computed } from '@vue/reactivity'
3
-
4
- type SortBy =
5
- | 'title'
6
- | 'category'
7
- | ((
8
- a: ApplicationEntryWithInherited,
9
- b: ApplicationEntryWithInherited,
10
- ) => number)
11
- type Visibility =
12
- | 'primary'
13
- | 'all'
14
- | ((entry: ApplicationEntryWithInherited) => boolean)
15
-
16
- export function useApplicationEntries() {
17
- const applicationManager = useApplicationManager()
18
-
19
- const sortedAppEntries = function (
20
- sortBy: SortBy = 'title',
21
- visibility: Visibility = 'primary',
22
- ): Ref<ApplicationEntryWithInherited[]> {
23
- return computed(() => {
24
- const currentEntries = [...applicationManager.appsEntries.value]
25
-
26
- // filtering
27
- const filtered =
28
- typeof visibility === 'function'
29
- ? currentEntries.filter(visibility)
30
- : visibility === 'primary'
31
- ? currentEntries.filter((e) => e.visibility !== 'secondary')
32
- : currentEntries
33
-
34
- // sorting
35
- const sorted =
36
- typeof sortBy === 'function'
37
- ? filtered.sort(sortBy)
38
- : sortBy === 'title'
39
- ? filtered.sort((a, b) =>
40
- (a.title || '').localeCompare(b.title || ''),
41
- )
42
- : filtered.sort((a, b) =>
43
- (a.category || '').localeCompare(b.category || ''),
44
- )
45
-
46
- return sorted
47
- })
48
- }
49
-
50
- return { sortedAppEntries }
51
- }
@@ -1,285 +0,0 @@
1
- import { reactive, markRaw, computed } from 'vue'
2
- import { ApplicationController } from '../internal/controllers/ApplicationController'
3
- import { normalizeApplicationConfig } from '../utils/utilApp'
4
- import { debugLog } from '../utils/utilDebug'
5
- import * as shellwords from 'shellwords'
6
- import getopts from "getopts"
7
-
8
- const apps = reactive(new Map<string, IApplicationController>())
9
-
10
- /**
11
- * Application Manager Composable (Singleton)
12
- */
13
- export function useApplicationManager() {
14
- /**
15
- * Define new application
16
- *
17
- * @param id
18
- * @param config
19
- */
20
- async function defineApp(id: string, config: ApplicationConfig) {
21
- if (isAppDefined(id)) {
22
- debugLog(`App "${id}" is already defined`)
23
- return getAppById(id)!
24
- }
25
-
26
- const normalizedConfig = normalizeApplicationConfig(config)
27
- const applicationConfig = markRaw(normalizedConfig)
28
-
29
- const applicationController: IApplicationController = new ApplicationController(id, applicationConfig)
30
- await applicationController.initApplication()
31
-
32
- apps.set(id, markRaw(applicationController))
33
-
34
- return applicationController
35
- }
36
-
37
- /**
38
- * Check if app has been defined
39
- *
40
- * @param {string} id
41
- */
42
- function isAppDefined(id: string) {
43
- return getAppById(id)
44
- }
45
-
46
- /**
47
- * Retrieves an app instance by its unique identifier
48
- *
49
- * @param {string} id
50
- */
51
- function getAppById(id: string) {
52
- return apps.get(id)
53
- }
54
-
55
- /**
56
- * Check if app is running
57
- *
58
- * @param {string} id
59
- */
60
- function isAppRunning(id: string) {
61
- if (!isAppDefined(id)) {
62
- throw Error(`App "${id}" is not defined`)
63
- }
64
-
65
- const applicationController = getAppById(id)!
66
- return applicationController.isRunning
67
- }
68
-
69
- /**
70
- * Launch app entry
71
- *
72
- * @param id
73
- * @param entryKey
74
- * @param argument
75
- */
76
- async function launchAppEntry(
77
- id: string,
78
- entryKey: string,
79
- argument: string = ''
80
- ): Promise<IApplicationController | undefined | void> {
81
- if (!isAppDefined(id)) {
82
- throw Error(`App "${id}" is not defined`)
83
- }
84
-
85
- const applicationController = getAppById(id)!
86
-
87
- if (
88
- applicationController.config.entries &&
89
- !applicationController.config.entries.hasOwnProperty(entryKey)
90
- ) {
91
- throw Error(`App entry "${entryKey}" is not defined in ${id} application`)
92
- }
93
-
94
- const entry: ApplicationEntry = applicationController.config.entries[entryKey]!
95
-
96
- if (argument) argument = ` ${argument}`
97
-
98
- await execAppCommand(applicationController.id, entry.command + argument)
99
- }
100
-
101
- /**
102
- * Run app command
103
- *
104
- * @param id
105
- * @param rawCommand
106
- */
107
- async function execAppCommand(
108
- id: string,
109
- rawCommand: string,
110
- ): Promise<CommandOutput> {
111
- if (!isAppDefined(id)) {
112
- throw Error(`App "${id}" is not defined`)
113
- }
114
-
115
- const applicationController = getAppById(id)!
116
-
117
- const args = shellwords.split(rawCommand)
118
- const parsed = getopts(args)
119
- const command: string = parsed._[0]
120
-
121
- if (
122
- applicationController.config.commands &&
123
- !applicationController.config.commands.hasOwnProperty(command)
124
- ) {
125
- throw Error(
126
- `App command "${command}" is not defined in ${id} application`,
127
- )
128
- }
129
-
130
- const commandFn: any = applicationController.config.commands![command]
131
-
132
- const commandOutput = await commandFn(applicationController, parsed)
133
-
134
- applicationController.setRunning(true)
135
-
136
- return commandOutput
137
- }
138
-
139
- /**
140
- * Close application
141
- *
142
- * @param id
143
- */
144
- function closeApp(id: string) {
145
- if (!isAppDefined(id)) {
146
- throw Error(`App "${id}" is not defined`)
147
- }
148
-
149
- const applicationController = getAppById(id)!
150
-
151
- applicationController.closeAllWindows()
152
- applicationController.setRunning(false)
153
- }
154
-
155
- /**
156
- * Array of available menu entries for system bars, docks
157
- */
158
- const appsEntries = computed(() => {
159
- const entries: ApplicationEntryWithInherited[] = []
160
-
161
- for (const applicationController of apps.values()) {
162
- if (!applicationController.config.entries) {
163
- continue
164
- }
165
-
166
- for (const entryKey of Object.keys(applicationController.config.entries)) {
167
- const entry = applicationController.config.entries[entryKey]!
168
-
169
- entries.push({
170
- application: applicationController,
171
- title: entry.title ?? applicationController.config.title,
172
- icon: entry.icon ?? applicationController.config.icon,
173
- category: entry.category ?? applicationController.config.category,
174
- visibility: entry.visibility ?? 'primary',
175
- command: entry.command,
176
- })
177
- }
178
- }
179
-
180
- return entries
181
- })
182
-
183
- /**
184
- * Array of opened windows for system bars, docks
185
- */
186
- const windowsOpened = computed(() => {
187
- const windows = new Map<string, IWindowController>()
188
-
189
- for (const applicationController of apps.values()) {
190
- if (
191
- !applicationController.isRunning &&
192
- applicationController.openWindowCount.value === 0
193
- ) {
194
- continue
195
- }
196
-
197
- for (const [windowId, window] of applicationController.windows) {
198
- windows.set(windowId, window)
199
- }
200
- }
201
-
202
- return windows
203
- })
204
-
205
- /**
206
- * Array of running applications
207
- */
208
- const appsRunning = computed(() => {
209
- const runningApps: IApplicationController[] = []
210
-
211
- for (const applicationController of apps.values()) {
212
- const openCount = applicationController.openWindowCount.value
213
- if (applicationController.isRunning || openCount > 0) {
214
- runningApps.push(applicationController)
215
- }
216
- }
217
-
218
- return runningApps
219
- })
220
-
221
- function getWindowOpenedId(windowId: string) {
222
- for (const window of windowsOpened.value.values()) {
223
- if (window.state.id === windowId) {
224
- return window
225
- }
226
- }
227
- }
228
-
229
- /**
230
- * Gets all unique categories from the installed apps
231
- */
232
- const appCategories = computed(() => {
233
- const categories = new Set<string>()
234
-
235
- for (const applicationController of apps.values()) {
236
- if (applicationController.config.category) {
237
- categories.add(applicationController.config.category)
238
- }
239
- }
240
-
241
- return Array.from(categories).sort()
242
- })
243
-
244
- /**
245
- * Gets the apps ordered by category
246
- */
247
- const appsByCategory = computed(() => {
248
- const categorizedApps: {
249
- [category: string]: IApplicationController[]
250
- } = {}
251
-
252
- for (const applicationController of apps.values()) {
253
- const category = applicationController.config.category || 'other'
254
- if (!categorizedApps[category]) {
255
- categorizedApps[category] = []
256
- }
257
- categorizedApps[category].push(applicationController)
258
- }
259
-
260
- for (const category in categorizedApps) {
261
- categorizedApps[category].sort((a, b) =>
262
- a.config.title.localeCompare(b.config.title),
263
- )
264
- }
265
-
266
- return categorizedApps
267
- })
268
-
269
- return {
270
- defineApp,
271
- isAppDefined,
272
- getAppById,
273
- isAppRunning,
274
- launchAppEntry,
275
- execAppCommand,
276
- closeApp,
277
- getWindowOpenedId,
278
- apps,
279
- appsEntries,
280
- appsRunning,
281
- windowsOpened,
282
- appCategories,
283
- appsByCategory,
284
- }
285
- }