@kennofizet/apphub-frontend 0.1.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/README.md +84 -0
- package/package.json +31 -0
- package/src/api/coreApi.js +25 -0
- package/src/api/index.js +80 -0
- package/src/composables/createZoneContext.js +156 -0
- package/src/composables/useAppHubHostApi.js +24 -0
- package/src/composables/useAppHubZoneContext.js +11 -0
- package/src/composables/useDevOriginToggle.js +40 -0
- package/src/i18n/index.js +16 -0
- package/src/i18n/resolveLang.js +6 -0
- package/src/i18n/resolveTheme.js +30 -0
- package/src/i18n/translations/en.js +303 -0
- package/src/i18n/translations/vi.js +302 -0
- package/src/index.js +427 -0
- package/src/moduleStore.js +10 -0
- package/src/modules/app-store/components/AppHubAppStoreApp.vue +210 -0
- package/src/modules/app-store/components/AppHubAppStoreCard.vue +88 -0
- package/src/modules/app-store/components/AppHubAppStoreSettingsPanel.vue +266 -0
- package/src/modules/app-store/components/AppHubAppVersionHistory.vue +77 -0
- package/src/modules/app-store/components/AppHubDevReviewPanel.vue +206 -0
- package/src/modules/app-store/components/AppHubDraftStoreApp.vue +184 -0
- package/src/modules/app-store/components/AppHubDraftStoreCard.vue +116 -0
- package/src/modules/app-store/composables/useAppStore.js +206 -0
- package/src/modules/app-store/composables/useCatalogInfiniteScroll.js +47 -0
- package/src/modules/app-store/constants/catalogModes.js +2 -0
- package/src/modules/app-store/data/defaultCatalog.js +19 -0
- package/src/modules/app-store/index.js +9 -0
- package/src/modules/app-store/utils/normalizeCatalogApp.js +37 -0
- package/src/modules/desktop/components/AppHubDesktop.vue +1510 -0
- package/src/modules/desktop/components/AppHubDesktopDevOriginBar.vue +57 -0
- package/src/modules/desktop/components/AppHubDesktopDropLayer.vue +15 -0
- package/src/modules/desktop/components/AppHubDesktopDropTarget.vue +32 -0
- package/src/modules/desktop/components/AppHubDesktopIconContextMenu.vue +74 -0
- package/src/modules/desktop/components/AppHubDesktopIconFolder.vue +60 -0
- package/src/modules/desktop/components/AppHubDesktopIconGroup.vue +58 -0
- package/src/modules/desktop/components/AppHubDesktopIconInfoDialog.vue +33 -0
- package/src/modules/desktop/components/AppHubDesktopIconRenameDialog.vue +62 -0
- package/src/modules/desktop/components/AppHubDesktopSettings.vue +28 -0
- package/src/modules/desktop/components/AppHubDropInstallBadge.vue +65 -0
- package/src/modules/desktop/components/AppHubDuplicateAppDialog.vue +38 -0
- package/src/modules/desktop/components/AppHubGuideApp.vue +278 -0
- package/src/modules/desktop/components/AppHubOriginBlockScreen.vue +105 -0
- package/src/modules/desktop/components/AppHubOriginLoadingScreen.vue +23 -0
- package/src/modules/desktop/components/AppHubPlaceholderApp.vue +14 -0
- package/src/modules/desktop/components/AppHubSettingsApp.vue +319 -0
- package/src/modules/desktop/components/AppHubStartButton.vue +24 -0
- package/src/modules/desktop/components/AppHubStartMenu.vue +182 -0
- package/src/modules/desktop/components/AppHubTaskbarPins.vue +23 -0
- package/src/modules/desktop/components/settings/AppHubSettingsKeyboardPanel.vue +82 -0
- package/src/modules/desktop/components/settings/AppHubSettingsScreenPanel.vue +41 -0
- package/src/modules/desktop/components/settings/AppHubSettingsStartMenuPanel.vue +95 -0
- package/src/modules/desktop/composables/simulateInstallProgress.js +15 -0
- package/src/modules/desktop/composables/useDesktopDropInstall.js +272 -0
- package/src/modules/desktop/composables/useDesktopHubSettings.js +51 -0
- package/src/modules/desktop/composables/useDesktopIconDrag.js +207 -0
- package/src/modules/desktop/composables/useDesktopShell.js +335 -0
- package/src/modules/desktop/data/builtinApps.js +77 -0
- package/src/modules/desktop/index.js +12 -0
- package/src/modules/desktop/styles/desktop.css +3104 -0
- package/src/modules/desktop/styles/theme.css +616 -0
- package/src/modules/desktop/utils/desktopGrid.js +43 -0
- package/src/modules/desktop/utils/desktopIconGroups.js +103 -0
- package/src/modules/desktop/utils/desktopSession.js +40 -0
- package/src/modules/desktop/utils/desktopSettings.js +37 -0
- package/src/modules/desktop/utils/dropPackageParser.js +140 -0
- package/src/modules/desktop/utils/duplicateAppUtils.js +28 -0
- package/src/modules/desktop/utils/hubKeyboardSettings.js +63 -0
- package/src/modules/desktop/utils/recentApps.js +148 -0
- package/src/modules/desktop/utils/startMenuFavorites.js +100 -0
- package/src/modules/desktop/utils/startMenuPins.js +90 -0
- package/src/modules/notifications/components/AppHubDesktopNotifications.vue +54 -0
- package/src/modules/notifications/composables/createDesktopNotifications.js +86 -0
- package/src/modules/notifications/index.js +9 -0
- package/src/modules/notifications/styles/notifications.css +118 -0
- package/src/modules/notifications/utils/parseApiError.js +29 -0
- package/src/modules/runner/components/AppHubRunner.vue +292 -0
- package/src/modules/runner/index.js +1 -0
- package/src/modules/window-manager/components/AppHubWindowFrame.vue +224 -0
- package/src/modules/window-manager/composables/useWindowManager.js +652 -0
- package/src/modules/window-manager/index.js +7 -0
- package/src/modules/window-manager/utils/sessionLayout.js +28 -0
- package/src/modules/window-manager/utils/windowLayout.js +236 -0
- package/src/modules/window-manager/utils/windowSnap.js +146 -0
- package/src/utils/bootstrapCache.js +47 -0
- package/src/utils/devOriginSettings.js +22 -0
- package/src/utils/launchUrl.js +111 -0
- package/src/utils/originSafety.js +267 -0
- package/src/utils/safeStorage.js +191 -0
- package/src/utils/semver.js +30 -0
- package/src/utils/zoneContext.js +38 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { computed, reactive, watchEffect } from 'vue'
|
|
2
|
+
import { AppHubAppStoreApp } from '../../app-store/index.js'
|
|
3
|
+
import { AppHubDraftStoreApp } from '../../app-store/index.js'
|
|
4
|
+
import { BUILTIN_APP_STORE_ID, getBuiltinDesktopApps, getTaskbarBuiltinApps } from '../data/builtinApps.js'
|
|
5
|
+
import AppHubGuideApp from '../components/AppHubGuideApp.vue'
|
|
6
|
+
import AppHubSettingsApp from '../components/AppHubSettingsApp.vue'
|
|
7
|
+
import AppHubPlaceholderApp from '../components/AppHubPlaceholderApp.vue'
|
|
8
|
+
import { AppHubRunner } from '../../runner/index.js'
|
|
9
|
+
import { findAppByName, nextDuplicateName, nextDuplicateSlug } from '../utils/duplicateAppUtils.js'
|
|
10
|
+
|
|
11
|
+
function isUserRuntimeApp(app) {
|
|
12
|
+
return Boolean(app && !app.builtin && app.slug)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function resolveShellLanguage(options) {
|
|
16
|
+
const lang = options.language
|
|
17
|
+
if (lang && typeof lang === 'object' && 'value' in lang) {
|
|
18
|
+
return lang.value ?? 'vi'
|
|
19
|
+
}
|
|
20
|
+
return typeof lang === 'string' ? lang : 'vi'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Desktop shell โ Windows-style surface, icons, launches windows via window-manager.
|
|
25
|
+
*/
|
|
26
|
+
export function createDesktopShell(options = {}) {
|
|
27
|
+
const resolveLabels = typeof options.getLabels === 'function'
|
|
28
|
+
? options.getLabels
|
|
29
|
+
: () => options.labels ?? {}
|
|
30
|
+
|
|
31
|
+
const state = reactive({
|
|
32
|
+
userApps: [],
|
|
33
|
+
startOpen: false,
|
|
34
|
+
clock: '',
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const builtinApps = computed(() => getBuiltinDesktopApps(resolveLabels()))
|
|
38
|
+
const taskbarBuiltinApps = computed(() => getTaskbarBuiltinApps(resolveLabels()))
|
|
39
|
+
|
|
40
|
+
const desktopIcons = computed(() => {
|
|
41
|
+
const icons = [...(builtinApps.value ?? []), ...state.userApps]
|
|
42
|
+
return icons.filter((app) => app && app.id)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const iconList = reactive([])
|
|
46
|
+
watchEffect(() => {
|
|
47
|
+
iconList.splice(0, iconList.length, ...desktopIcons.value)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
function allUserAppNames() {
|
|
51
|
+
return state.userApps.map((a) => a.name)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function resolveWindowComponent(app) {
|
|
55
|
+
if (app.module === 'app-store') return AppHubAppStoreApp
|
|
56
|
+
if (app.module === 'draft-store') return AppHubDraftStoreApp
|
|
57
|
+
if (app.module === 'guide') return AppHubGuideApp
|
|
58
|
+
if (app.module === 'settings') return AppHubSettingsApp
|
|
59
|
+
if (isUserRuntimeApp(app)) return AppHubRunner
|
|
60
|
+
return AppHubPlaceholderApp
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const handleInstall = options.handleInstall ?? null
|
|
64
|
+
const handleUninstall = options.handleUninstall ?? null
|
|
65
|
+
|
|
66
|
+
function resolveWindowProps(app) {
|
|
67
|
+
if (app.module === 'app-store' || app.module === 'draft-store') {
|
|
68
|
+
return {
|
|
69
|
+
getInstalledVersion: (slug) => findUserAppBySlug(slug)?.installedVersion ?? null,
|
|
70
|
+
onInstalled: async (item) => {
|
|
71
|
+
if (handleInstall) return handleInstall(item, null, 'appstore')
|
|
72
|
+
return onUserAppInstalled(item)
|
|
73
|
+
},
|
|
74
|
+
onUpdateApp: async (item) => {
|
|
75
|
+
if (options.onUpdateApp) return options.onUpdateApp(item)
|
|
76
|
+
return updateInstalledVersion(item?.slug, item?.version)
|
|
77
|
+
},
|
|
78
|
+
onUninstalled: async (item) => {
|
|
79
|
+
if (handleUninstall) return handleUninstall(item)
|
|
80
|
+
if (item?.slug) removeUserApp(`user-${item.slug}`)
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (isUserRuntimeApp(app)) {
|
|
85
|
+
return {
|
|
86
|
+
slug: app.slug,
|
|
87
|
+
status: app.status ?? 'active',
|
|
88
|
+
installedVersion: app.installedVersion ?? app.version ?? null,
|
|
89
|
+
entryUrl: app.entry_url ?? null,
|
|
90
|
+
healthcheckUrl: app.healthcheck_url ?? null,
|
|
91
|
+
icon: app.icon ?? '๐ฆ',
|
|
92
|
+
language: resolveShellLanguage(options),
|
|
93
|
+
runtimeType: app.runtime_type ?? 'iframe',
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { title: app.name, icon: app.icon }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function buildWindowDefinition(app) {
|
|
100
|
+
const runner = isUserRuntimeApp(app)
|
|
101
|
+
const defaultWidth = runner ? 960 : 720
|
|
102
|
+
const defaultHeight = runner ? 600 : 480
|
|
103
|
+
const defaultMiniWidth = runner ? 720 : 720
|
|
104
|
+
const defaultMiniHeight = runner ? 480 : 480
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
id: `win-${app.id}`,
|
|
108
|
+
title: app.windowTitle ?? app.name,
|
|
109
|
+
icon: app.icon,
|
|
110
|
+
component: resolveWindowComponent(app),
|
|
111
|
+
props: resolveWindowProps(app),
|
|
112
|
+
layoutKey: app.layoutKey,
|
|
113
|
+
defaultDisplay: app.defaultDisplay,
|
|
114
|
+
miniWidth: app.miniWidth ?? defaultMiniWidth,
|
|
115
|
+
miniHeight: app.miniHeight ?? defaultMiniHeight,
|
|
116
|
+
width: app.width ?? defaultWidth,
|
|
117
|
+
height: app.height ?? defaultHeight,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function findDesktopApp(appId) {
|
|
122
|
+
return desktopIcons.value.find((a) => a.id === appId)
|
|
123
|
+
?? taskbarBuiltinApps.value.find((a) => a.id === appId)
|
|
124
|
+
?? null
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function openApp(app, windowManager, sessionState = null) {
|
|
128
|
+
if (app?.id && !sessionState) options.onAppOpened?.(app.id)
|
|
129
|
+
windowManager.openWindow(buildWindowDefinition(app), sessionState)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function restoreSession(session, windowManager) {
|
|
133
|
+
if (!session) return false
|
|
134
|
+
|
|
135
|
+
if (Array.isArray(session.userApps) && session.userApps.length) {
|
|
136
|
+
state.userApps.splice(0, state.userApps.length, ...session.userApps)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const savedWindows = session.windows ?? []
|
|
140
|
+
for (const saved of savedWindows) {
|
|
141
|
+
const app = findDesktopApp(saved.appId)
|
|
142
|
+
if (app) openApp(app, windowManager, saved)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
windowManager.finishSessionRestore?.(session.activeId)
|
|
146
|
+
return savedWindows.length > 0
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function removeUserApp(appOrId) {
|
|
150
|
+
const id = typeof appOrId === 'string' ? appOrId : appOrId?.id
|
|
151
|
+
const idx = state.userApps.findIndex((a) => a.id === id)
|
|
152
|
+
if (idx !== -1) state.userApps.splice(idx, 1)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function resolveInstalledVersion(app) {
|
|
156
|
+
if (typeof app.installedVersion === 'string' && app.installedVersion.trim()) {
|
|
157
|
+
return app.installedVersion.trim()
|
|
158
|
+
}
|
|
159
|
+
if (typeof app.version === 'string' && app.version.trim()) {
|
|
160
|
+
return app.version.trim()
|
|
161
|
+
}
|
|
162
|
+
return null
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function buildUserApp(app, position, method = null) {
|
|
166
|
+
const status = typeof app.status === 'string' ? app.status : 'active'
|
|
167
|
+
const installedVersion = resolveInstalledVersion(app)
|
|
168
|
+
return {
|
|
169
|
+
id: `user-${app.slug}`,
|
|
170
|
+
slug: app.slug,
|
|
171
|
+
installedVersion,
|
|
172
|
+
version: installedVersion,
|
|
173
|
+
name: app.name,
|
|
174
|
+
icon: app.icon ?? '๐ฆ',
|
|
175
|
+
hint: app.description ?? '',
|
|
176
|
+
status,
|
|
177
|
+
runtime_type: typeof app.runtime_type === 'string' ? app.runtime_type : 'iframe',
|
|
178
|
+
entry_url: typeof app.entry_url === 'string' ? app.entry_url : null,
|
|
179
|
+
healthcheck_url: typeof app.healthcheck_url === 'string' ? app.healthcheck_url : null,
|
|
180
|
+
builtin: false,
|
|
181
|
+
local: method === 'local' || app.local === true,
|
|
182
|
+
installMethod: method === 'local' || method === 'appstore' || method === 'publish'
|
|
183
|
+
? method
|
|
184
|
+
: (app.local ? 'local' : 'appstore'),
|
|
185
|
+
createdAt: app.createdAt ?? new Date().toISOString(),
|
|
186
|
+
windowTitle: app.name,
|
|
187
|
+
width: 960,
|
|
188
|
+
height: 600,
|
|
189
|
+
miniWidth: 720,
|
|
190
|
+
miniHeight: 480,
|
|
191
|
+
desktopX: position?.x ?? null,
|
|
192
|
+
desktopY: position?.y ?? null,
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function renameUserApp(appId, newName) {
|
|
197
|
+
const app = state.userApps.find((a) => a.id === appId)
|
|
198
|
+
if (!app) return { ok: false, error: 'not_found' }
|
|
199
|
+
const name = String(newName ?? '').trim()
|
|
200
|
+
if (!name) return { ok: false, error: 'empty' }
|
|
201
|
+
const conflict = findAppByName(name, state.userApps)
|
|
202
|
+
if (conflict && conflict.id !== appId) return { ok: false, error: 'duplicate' }
|
|
203
|
+
app.name = name
|
|
204
|
+
app.windowTitle = name
|
|
205
|
+
return { ok: true, app }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Install user app with duplicate handling.
|
|
210
|
+
* @returns {'added'|'replaced'|'updated'|'cancelled'|null}
|
|
211
|
+
*/
|
|
212
|
+
function installUserApp(app, position, method = 'local', duplicateChoice = null) {
|
|
213
|
+
if (!app?.slug && !app?.name) return null
|
|
214
|
+
|
|
215
|
+
const existingBySlug = app.slug
|
|
216
|
+
? state.userApps.find((a) => a.slug === app.slug)
|
|
217
|
+
: null
|
|
218
|
+
|
|
219
|
+
// Same slug โ publish upgrade or catalog refresh. Never show duplicate dialog.
|
|
220
|
+
if (existingBySlug) {
|
|
221
|
+
if (app.status) existingBySlug.status = app.status
|
|
222
|
+
if (app.runtime_type) existingBySlug.runtime_type = app.runtime_type
|
|
223
|
+
if (app.entry_url) existingBySlug.entry_url = app.entry_url
|
|
224
|
+
if (app.healthcheck_url) existingBySlug.healthcheck_url = app.healthcheck_url
|
|
225
|
+
if (app.description) existingBySlug.hint = app.description
|
|
226
|
+
if (method !== 'publish') {
|
|
227
|
+
const nextVersion = resolveInstalledVersion(app)
|
|
228
|
+
if (nextVersion && !existingBySlug.installedVersion) {
|
|
229
|
+
existingBySlug.installedVersion = nextVersion
|
|
230
|
+
existingBySlug.version = nextVersion
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (position) {
|
|
234
|
+
existingBySlug.desktopX = position.x
|
|
235
|
+
existingBySlug.desktopY = position.y
|
|
236
|
+
}
|
|
237
|
+
return 'updated'
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const existingByName = findAppByName(app.name, state.userApps)
|
|
241
|
+
|
|
242
|
+
if (existingByName && duplicateChoice === null) {
|
|
243
|
+
return { needsDuplicateChoice: true, existing: existingByName, app, position, method }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (duplicateChoice === 'cancel') return 'cancelled'
|
|
247
|
+
|
|
248
|
+
if (existingByName && duplicateChoice === 'replace') {
|
|
249
|
+
removeUserApp(existingByName)
|
|
250
|
+
const entry = buildUserApp({ ...app, slug: app.slug ?? existingByName.slug }, position, method)
|
|
251
|
+
state.userApps.push(entry)
|
|
252
|
+
return 'replaced'
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (existingByName && duplicateChoice === 'keep') {
|
|
256
|
+
const name = nextDuplicateName(app.name, state.userApps)
|
|
257
|
+
const slug = nextDuplicateSlug(app.slug ?? app.name, state.userApps)
|
|
258
|
+
state.userApps.push(buildUserApp({ ...app, name, slug }, position, method))
|
|
259
|
+
return 'added'
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
state.userApps.push(buildUserApp(app, position, method))
|
|
263
|
+
return 'added'
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function updateInstalledVersion(slug, version) {
|
|
267
|
+
const normalizedSlug = String(slug ?? '').trim()
|
|
268
|
+
const normalizedVersion = String(version ?? '').trim()
|
|
269
|
+
if (!normalizedSlug || !normalizedVersion) return false
|
|
270
|
+
|
|
271
|
+
const app = findUserAppBySlug(normalizedSlug)
|
|
272
|
+
if (!app) return false
|
|
273
|
+
|
|
274
|
+
app.installedVersion = normalizedVersion
|
|
275
|
+
app.version = normalizedVersion
|
|
276
|
+
return true
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function moveUserApp(appId, x, y) {
|
|
280
|
+
const app = state.userApps.find((a) => a.id === appId)
|
|
281
|
+
if (!app) return
|
|
282
|
+
app.desktopX = x
|
|
283
|
+
app.desktopY = y
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function findUserApp(appId) {
|
|
287
|
+
return state.userApps.find((a) => a.id === appId) ?? null
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function findUserAppBySlug(slug) {
|
|
291
|
+
const normalized = String(slug ?? '').trim()
|
|
292
|
+
if (!normalized) return null
|
|
293
|
+
return state.userApps.find((a) => a.slug === normalized) ?? null
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function onUserAppInstalled(app, position = null) {
|
|
297
|
+
return installUserApp(app, position, 'appstore')
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function addDroppedApp(app, position, method = 'local', duplicateChoice = null) {
|
|
301
|
+
return installUserApp(app, position, method, duplicateChoice)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function openBuiltinAppStore(windowManager) {
|
|
305
|
+
const app = builtinApps.value.find((a) => a.id === BUILTIN_APP_STORE_ID)
|
|
306
|
+
if (app) openApp(app, windowManager)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function tickClock() {
|
|
310
|
+
const now = new Date()
|
|
311
|
+
state.clock = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
state,
|
|
316
|
+
desktopIcons,
|
|
317
|
+
taskbarBuiltinApps,
|
|
318
|
+
iconList,
|
|
319
|
+
allUserAppNames,
|
|
320
|
+
openApp,
|
|
321
|
+
openBuiltinAppStore,
|
|
322
|
+
restoreSession,
|
|
323
|
+
findDesktopApp,
|
|
324
|
+
onUserAppInstalled,
|
|
325
|
+
installUserApp,
|
|
326
|
+
addDroppedApp,
|
|
327
|
+
moveUserApp,
|
|
328
|
+
findUserApp,
|
|
329
|
+
findUserAppBySlug,
|
|
330
|
+
updateInstalledVersion,
|
|
331
|
+
renameUserApp,
|
|
332
|
+
removeUserApp,
|
|
333
|
+
tickClock,
|
|
334
|
+
}
|
|
335
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/** Built-in desktop apps (always on the Hub desktop). */
|
|
2
|
+
export const BUILTIN_APP_STORE_ID = 'builtin-app-store'
|
|
3
|
+
export const BUILTIN_GUIDE_ID = 'builtin-guide'
|
|
4
|
+
export const BUILTIN_SETTINGS_ID = 'builtin-settings'
|
|
5
|
+
|
|
6
|
+
/** Draft App Store โ taskbar only, not on desktop surface. */
|
|
7
|
+
export const BUILTIN_DRAFT_STORE_ID = 'builtin-draft-store'
|
|
8
|
+
|
|
9
|
+
export const PILOT_DRAFT_SLUG = 'pilot-draft'
|
|
10
|
+
|
|
11
|
+
export function getBuiltinDesktopApps(labels) {
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
id: BUILTIN_APP_STORE_ID,
|
|
15
|
+
slug: BUILTIN_APP_STORE_ID,
|
|
16
|
+
name: labels.desktop_app_store,
|
|
17
|
+
hint: labels.desktop_app_store_hint,
|
|
18
|
+
icon: '๐',
|
|
19
|
+
builtin: true,
|
|
20
|
+
windowTitle: labels.app_store_title,
|
|
21
|
+
module: 'app-store',
|
|
22
|
+
layoutKey: BUILTIN_APP_STORE_ID,
|
|
23
|
+
defaultDisplay: 'fullscreen',
|
|
24
|
+
miniWidth: 820,
|
|
25
|
+
miniHeight: 520,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: BUILTIN_GUIDE_ID,
|
|
29
|
+
slug: BUILTIN_GUIDE_ID,
|
|
30
|
+
name: labels.guide_app_name,
|
|
31
|
+
hint: labels.guide_app_hint,
|
|
32
|
+
icon: '๐',
|
|
33
|
+
builtin: true,
|
|
34
|
+
windowTitle: labels.guide_app_title,
|
|
35
|
+
module: 'guide',
|
|
36
|
+
layoutKey: BUILTIN_GUIDE_ID,
|
|
37
|
+
defaultDisplay: 'mini',
|
|
38
|
+
miniWidth: 760,
|
|
39
|
+
miniHeight: 560,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: BUILTIN_SETTINGS_ID,
|
|
43
|
+
slug: BUILTIN_SETTINGS_ID,
|
|
44
|
+
name: labels.hub_settings_app_name,
|
|
45
|
+
hint: labels.hub_settings_app_hint,
|
|
46
|
+
icon: 'โ๏ธ',
|
|
47
|
+
builtin: true,
|
|
48
|
+
windowTitle: labels.hub_settings_app_title,
|
|
49
|
+
module: 'settings',
|
|
50
|
+
layoutKey: BUILTIN_SETTINGS_ID,
|
|
51
|
+
defaultDisplay: 'mini',
|
|
52
|
+
miniWidth: 720,
|
|
53
|
+
miniHeight: 520,
|
|
54
|
+
},
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Built-ins that open from the taskbar only (no desktop icon). */
|
|
59
|
+
export function getTaskbarBuiltinApps(labels) {
|
|
60
|
+
return [
|
|
61
|
+
{
|
|
62
|
+
id: BUILTIN_DRAFT_STORE_ID,
|
|
63
|
+
slug: BUILTIN_DRAFT_STORE_ID,
|
|
64
|
+
name: labels.draft_store_app_name,
|
|
65
|
+
hint: labels.draft_store_app_hint,
|
|
66
|
+
icon: '๐งช',
|
|
67
|
+
builtin: true,
|
|
68
|
+
taskbarOnly: true,
|
|
69
|
+
windowTitle: labels.draft_store_title,
|
|
70
|
+
module: 'draft-store',
|
|
71
|
+
layoutKey: BUILTIN_DRAFT_STORE_ID,
|
|
72
|
+
defaultDisplay: 'mini',
|
|
73
|
+
miniWidth: 640,
|
|
74
|
+
miniHeight: 480,
|
|
75
|
+
},
|
|
76
|
+
]
|
|
77
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export {
|
|
2
|
+
BUILTIN_APP_STORE_ID,
|
|
3
|
+
BUILTIN_DRAFT_STORE_ID,
|
|
4
|
+
BUILTIN_GUIDE_ID,
|
|
5
|
+
PILOT_DRAFT_SLUG,
|
|
6
|
+
getBuiltinDesktopApps,
|
|
7
|
+
getTaskbarBuiltinApps,
|
|
8
|
+
} from './data/builtinApps.js'
|
|
9
|
+
export { createDesktopShell } from './composables/useDesktopShell.js'
|
|
10
|
+
export { default as AppHubDesktop } from './components/AppHubDesktop.vue'
|
|
11
|
+
export { default as AppHubGuideApp } from './components/AppHubGuideApp.vue'
|
|
12
|
+
export { default as AppHubPlaceholderApp } from './components/AppHubPlaceholderApp.vue'
|