@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,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="visible"
|
|
4
|
+
class="apphub-dev-origin-bar"
|
|
5
|
+
:class="`apphub-dev-origin-bar--${placement}`"
|
|
6
|
+
role="region"
|
|
7
|
+
:aria-label="labels.title"
|
|
8
|
+
>
|
|
9
|
+
<span class="apphub-dev-origin-bar__badge">DEV</span>
|
|
10
|
+
<div v-if="placement === 'corner'" class="apphub-dev-origin-bar__text">
|
|
11
|
+
<strong class="apphub-dev-origin-bar__title">{{ labels.title }}</strong>
|
|
12
|
+
<span class="apphub-dev-origin-bar__status">{{ statusLabel }}</span>
|
|
13
|
+
</div>
|
|
14
|
+
<span v-else class="apphub-dev-origin-bar__status apphub-dev-origin-bar__status--inline">
|
|
15
|
+
{{ statusLabel }}
|
|
16
|
+
</span>
|
|
17
|
+
<button
|
|
18
|
+
type="button"
|
|
19
|
+
class="apphub-dev-origin-bar__btn"
|
|
20
|
+
:title="labels.title"
|
|
21
|
+
@click="toggle"
|
|
22
|
+
>
|
|
23
|
+
{{ actionLabel }}
|
|
24
|
+
</button>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script setup>
|
|
29
|
+
import { computed, inject } from 'vue'
|
|
30
|
+
import { t } from '../../../i18n/index.js'
|
|
31
|
+
import { resolveLang } from '../../../i18n/resolveLang.js'
|
|
32
|
+
import { useDevOriginToggle } from '../../../composables/useDevOriginToggle.js'
|
|
33
|
+
|
|
34
|
+
defineProps({
|
|
35
|
+
placement: { type: String, default: 'corner' },
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const { visible, devFriendlyOn, toggle } = useDevOriginToggle()
|
|
39
|
+
const moduleOptions = inject('apphubOptions', {})
|
|
40
|
+
const lang = computed(() => resolveLang(moduleOptions?.language, 'vi'))
|
|
41
|
+
|
|
42
|
+
const labels = computed(() => ({
|
|
43
|
+
title: t('dev_origin_bar_title', lang.value),
|
|
44
|
+
status_relaxed: t('dev_origin_status_relaxed', lang.value),
|
|
45
|
+
status_strict: t('dev_origin_status_strict', lang.value),
|
|
46
|
+
action_enable_strict: t('dev_origin_action_strict', lang.value),
|
|
47
|
+
action_enable_relaxed: t('dev_origin_action_relaxed', lang.value),
|
|
48
|
+
}))
|
|
49
|
+
|
|
50
|
+
const statusLabel = computed(() =>
|
|
51
|
+
devFriendlyOn.value ? labels.value.status_relaxed : labels.value.status_strict,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
const actionLabel = computed(() =>
|
|
55
|
+
devFriendlyOn.value ? labels.value.action_enable_strict : labels.value.action_enable_relaxed,
|
|
56
|
+
)
|
|
57
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="apphub-drop-layer">
|
|
3
|
+
<div class="apphub-drop-layer__glow" />
|
|
4
|
+
<div class="apphub-drop-layer__hint">
|
|
5
|
+
<span class="apphub-drop-layer__hint-icon">⬇</span>
|
|
6
|
+
<p>{{ hint }}</p>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup>
|
|
12
|
+
defineProps({
|
|
13
|
+
hint: { type: String, default: '' },
|
|
14
|
+
})
|
|
15
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="target"
|
|
4
|
+
class="apphub-desktop__drop-target"
|
|
5
|
+
:style="{ left: `${target.x}px`, top: `${target.y}px` }"
|
|
6
|
+
>
|
|
7
|
+
<div class="apphub-desktop__drop-target-panel">
|
|
8
|
+
<p class="apphub-desktop__drop-target-label">{{ label }}</p>
|
|
9
|
+
<div class="apphub-desktop__drop-target-grid">
|
|
10
|
+
<span
|
|
11
|
+
v-for="app in previewApps"
|
|
12
|
+
:key="app.id"
|
|
13
|
+
class="apphub-desktop__drop-target-icon"
|
|
14
|
+
:title="app.name"
|
|
15
|
+
>
|
|
16
|
+
{{ app.icon }}
|
|
17
|
+
</span>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup>
|
|
24
|
+
import { computed } from 'vue'
|
|
25
|
+
|
|
26
|
+
const props = defineProps({
|
|
27
|
+
target: { type: Object, default: null },
|
|
28
|
+
label: { type: String, default: '' },
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const previewApps = computed(() => props.target?.apps?.slice(0, 9) ?? [])
|
|
32
|
+
</script>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="open"
|
|
4
|
+
class="apphub-icon-menu"
|
|
5
|
+
:style="{ left: `${x}px`, top: `${y}px` }"
|
|
6
|
+
role="menu"
|
|
7
|
+
@click.stop
|
|
8
|
+
@contextmenu.prevent
|
|
9
|
+
>
|
|
10
|
+
<button type="button" class="apphub-icon-menu__item" role="menuitem" @click="emit('open')">
|
|
11
|
+
{{ openLabel }}
|
|
12
|
+
</button>
|
|
13
|
+
<button
|
|
14
|
+
v-if="showPin"
|
|
15
|
+
type="button"
|
|
16
|
+
class="apphub-icon-menu__item"
|
|
17
|
+
role="menuitem"
|
|
18
|
+
@click="emit('pin')"
|
|
19
|
+
>
|
|
20
|
+
{{ pinLabel }}
|
|
21
|
+
</button>
|
|
22
|
+
<button
|
|
23
|
+
v-if="showFavorite"
|
|
24
|
+
type="button"
|
|
25
|
+
class="apphub-icon-menu__item"
|
|
26
|
+
role="menuitem"
|
|
27
|
+
@click="emit('favorite')"
|
|
28
|
+
>
|
|
29
|
+
{{ favoriteLabel }}
|
|
30
|
+
</button>
|
|
31
|
+
<button
|
|
32
|
+
v-if="canRename"
|
|
33
|
+
type="button"
|
|
34
|
+
class="apphub-icon-menu__item"
|
|
35
|
+
role="menuitem"
|
|
36
|
+
@click="emit('rename')"
|
|
37
|
+
>
|
|
38
|
+
{{ renameLabel }}
|
|
39
|
+
</button>
|
|
40
|
+
<button
|
|
41
|
+
v-if="showUninstall"
|
|
42
|
+
type="button"
|
|
43
|
+
class="apphub-icon-menu__item apphub-icon-menu__item--danger"
|
|
44
|
+
role="menuitem"
|
|
45
|
+
@click="emit('uninstall')"
|
|
46
|
+
>
|
|
47
|
+
{{ uninstallLabel }}
|
|
48
|
+
</button>
|
|
49
|
+
<div class="apphub-icon-menu__sep" role="separator" />
|
|
50
|
+
<button type="button" class="apphub-icon-menu__item" role="menuitem" @click="emit('info')">
|
|
51
|
+
{{ propertiesLabel }}
|
|
52
|
+
</button>
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<script setup>
|
|
57
|
+
defineProps({
|
|
58
|
+
open: { type: Boolean, default: false },
|
|
59
|
+
x: { type: Number, default: 0 },
|
|
60
|
+
y: { type: Number, default: 0 },
|
|
61
|
+
canRename: { type: Boolean, default: true },
|
|
62
|
+
showPin: { type: Boolean, default: false },
|
|
63
|
+
showFavorite: { type: Boolean, default: false },
|
|
64
|
+
showUninstall: { type: Boolean, default: false },
|
|
65
|
+
openLabel: { type: String, default: '' },
|
|
66
|
+
pinLabel: { type: String, default: '' },
|
|
67
|
+
favoriteLabel: { type: String, default: '' },
|
|
68
|
+
renameLabel: { type: String, default: '' },
|
|
69
|
+
uninstallLabel: { type: String, default: '' },
|
|
70
|
+
propertiesLabel: { type: String, default: '' },
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const emit = defineEmits(['open', 'pin', 'favorite', 'uninstall', 'rename', 'info', 'close'])
|
|
74
|
+
</script>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="open"
|
|
4
|
+
class="apphub-icon-folder"
|
|
5
|
+
:class="{ 'apphub-icon-folder--preview': preview }"
|
|
6
|
+
:style="{ left: `${x}px`, top: `${y}px` }"
|
|
7
|
+
@mousedown.stop
|
|
8
|
+
@click.stop
|
|
9
|
+
>
|
|
10
|
+
<div class="apphub-icon-folder__panel">
|
|
11
|
+
<header class="apphub-icon-folder__header">
|
|
12
|
+
<span class="apphub-icon-folder__title">{{ title }}</span>
|
|
13
|
+
<span class="apphub-icon-folder__count">{{ countLabel }}</span>
|
|
14
|
+
</header>
|
|
15
|
+
<div class="apphub-icon-folder__grid">
|
|
16
|
+
<button
|
|
17
|
+
v-for="app in apps"
|
|
18
|
+
:key="app.id"
|
|
19
|
+
type="button"
|
|
20
|
+
class="apphub-icon-folder__item"
|
|
21
|
+
:class="{
|
|
22
|
+
'apphub-icon-folder__item--dragging': !preview && isDragging(app.id),
|
|
23
|
+
'apphub-icon-folder__item--holding': !preview && isHolding(app.id),
|
|
24
|
+
'apphub-icon-folder__item--preview-new':
|
|
25
|
+
preview && previewNewIds.includes(app.id),
|
|
26
|
+
}"
|
|
27
|
+
:tabindex="preview ? -1 : 0"
|
|
28
|
+
@mousedown.stop="!preview && emit('item-pointer-down', app, $event)"
|
|
29
|
+
@dblclick.stop="!preview && emit('open-app', app)"
|
|
30
|
+
@contextmenu.prevent.stop="!preview && emit('item-context-menu', app, $event)"
|
|
31
|
+
>
|
|
32
|
+
<span class="apphub-icon-folder__item-icon-wrap">
|
|
33
|
+
<span class="apphub-icon-folder__item-icon">{{ app.icon }}</span>
|
|
34
|
+
<span v-if="app.status === 'draft'" class="apphub-icon-folder__item-flag">D</span>
|
|
35
|
+
</span>
|
|
36
|
+
<span class="apphub-icon-folder__item-label">{{ app.name }}</span>
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
<p class="apphub-icon-folder__hint">{{ hint }}</p>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script setup>
|
|
45
|
+
defineProps({
|
|
46
|
+
open: { type: Boolean, default: false },
|
|
47
|
+
preview: { type: Boolean, default: false },
|
|
48
|
+
x: { type: Number, default: 0 },
|
|
49
|
+
y: { type: Number, default: 0 },
|
|
50
|
+
apps: { type: Array, default: () => [] },
|
|
51
|
+
title: { type: String, default: '' },
|
|
52
|
+
countLabel: { type: String, default: '' },
|
|
53
|
+
hint: { type: String, default: '' },
|
|
54
|
+
previewNewIds: { type: Array, default: () => [] },
|
|
55
|
+
isDragging: { type: Function, default: () => false },
|
|
56
|
+
isHolding: { type: Function, default: () => false },
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const emit = defineEmits(['item-pointer-down', 'open-app', 'item-context-menu'])
|
|
60
|
+
</script>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<button
|
|
3
|
+
type="button"
|
|
4
|
+
class="apphub-desktop__icon apphub-desktop__icon--placed apphub-desktop__icon--group"
|
|
5
|
+
:class="{
|
|
6
|
+
'apphub-desktop__icon--dragging': dragging,
|
|
7
|
+
'apphub-desktop__icon--holding': holding,
|
|
8
|
+
'apphub-desktop__icon--drop-target': dropHighlight,
|
|
9
|
+
}"
|
|
10
|
+
:style="{ left: `${x}px`, top: `${y}px` }"
|
|
11
|
+
:title="title"
|
|
12
|
+
@mousedown.stop="emit('pointer-down', $event)"
|
|
13
|
+
@click.stop="emit('click')"
|
|
14
|
+
@contextmenu.prevent.stop="emit('context-menu', $event)"
|
|
15
|
+
>
|
|
16
|
+
<span class="apphub-desktop__group-preview">
|
|
17
|
+
<span
|
|
18
|
+
v-for="(app, i) in previewApps"
|
|
19
|
+
:key="app.id"
|
|
20
|
+
class="apphub-desktop__group-preview-item"
|
|
21
|
+
:style="previewStyle(i)"
|
|
22
|
+
>
|
|
23
|
+
{{ app.icon }}
|
|
24
|
+
</span>
|
|
25
|
+
</span>
|
|
26
|
+
<span class="apphub-desktop__icon-label" :title="label">{{ label }}</span>
|
|
27
|
+
</button>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup>
|
|
31
|
+
import { computed } from 'vue'
|
|
32
|
+
|
|
33
|
+
const props = defineProps({
|
|
34
|
+
apps: { type: Array, default: () => [] },
|
|
35
|
+
x: { type: Number, required: true },
|
|
36
|
+
y: { type: Number, required: true },
|
|
37
|
+
label: { type: String, default: '' },
|
|
38
|
+
title: { type: String, default: '' },
|
|
39
|
+
dragging: { type: Boolean, default: false },
|
|
40
|
+
holding: { type: Boolean, default: false },
|
|
41
|
+
dropHighlight: { type: Boolean, default: false },
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const emit = defineEmits(['pointer-down', 'click', 'context-menu'])
|
|
45
|
+
|
|
46
|
+
const previewApps = computed(() => props.apps.slice(0, 4))
|
|
47
|
+
|
|
48
|
+
const previewOffsets = [
|
|
49
|
+
{ left: '4px', top: '4px' },
|
|
50
|
+
{ left: '22px', top: '4px' },
|
|
51
|
+
{ left: '4px', top: '22px' },
|
|
52
|
+
{ left: '22px', top: '22px' },
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
function previewStyle(index) {
|
|
56
|
+
return previewOffsets[index] ?? previewOffsets[0]
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="open" class="apphub-icon-info" @click.self="emit('close')">
|
|
3
|
+
<div class="apphub-icon-info__panel" role="dialog" aria-modal="true">
|
|
4
|
+
<header class="apphub-icon-info__header">
|
|
5
|
+
<span class="apphub-icon-info__icon">{{ app?.icon }}</span>
|
|
6
|
+
<h3 class="apphub-icon-info__title">{{ title }}</h3>
|
|
7
|
+
</header>
|
|
8
|
+
<dl class="apphub-icon-info__list">
|
|
9
|
+
<div v-for="row in rows" :key="row.label" class="apphub-icon-info__row">
|
|
10
|
+
<dt>{{ row.label }}</dt>
|
|
11
|
+
<dd>{{ row.value }}</dd>
|
|
12
|
+
</div>
|
|
13
|
+
</dl>
|
|
14
|
+
<footer class="apphub-icon-info__actions">
|
|
15
|
+
<button type="button" class="apphub-icon-info__btn" @click="emit('close')">
|
|
16
|
+
{{ closeLabel }}
|
|
17
|
+
</button>
|
|
18
|
+
</footer>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup>
|
|
24
|
+
defineProps({
|
|
25
|
+
open: { type: Boolean, default: false },
|
|
26
|
+
title: { type: String, default: '' },
|
|
27
|
+
app: { type: Object, default: null },
|
|
28
|
+
rows: { type: Array, default: () => [] },
|
|
29
|
+
closeLabel: { type: String, default: '' },
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const emit = defineEmits(['close'])
|
|
33
|
+
</script>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="open" class="apphub-icon-rename" @click.self="emit('cancel')">
|
|
3
|
+
<div class="apphub-icon-rename__panel" role="dialog" aria-modal="true">
|
|
4
|
+
<h3 class="apphub-icon-rename__title">{{ title }}</h3>
|
|
5
|
+
<label class="apphub-icon-rename__label">
|
|
6
|
+
<span>{{ nameLabel }}</span>
|
|
7
|
+
<input
|
|
8
|
+
ref="inputRef"
|
|
9
|
+
v-model="draft"
|
|
10
|
+
type="text"
|
|
11
|
+
class="apphub-icon-rename__input"
|
|
12
|
+
maxlength="64"
|
|
13
|
+
@keydown.enter="onSave"
|
|
14
|
+
@keydown.esc="emit('cancel')"
|
|
15
|
+
/>
|
|
16
|
+
</label>
|
|
17
|
+
<p v-if="error" class="apphub-icon-rename__error">{{ error }}</p>
|
|
18
|
+
<div class="apphub-icon-rename__actions">
|
|
19
|
+
<button type="button" class="apphub-icon-rename__btn apphub-icon-rename__btn--primary" @click="onSave">
|
|
20
|
+
{{ saveLabel }}
|
|
21
|
+
</button>
|
|
22
|
+
<button type="button" class="apphub-icon-rename__btn" @click="emit('cancel')">
|
|
23
|
+
{{ cancelLabel }}
|
|
24
|
+
</button>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup>
|
|
31
|
+
import { nextTick, ref, watch } from 'vue'
|
|
32
|
+
|
|
33
|
+
const props = defineProps({
|
|
34
|
+
open: { type: Boolean, default: false },
|
|
35
|
+
title: { type: String, default: '' },
|
|
36
|
+
nameLabel: { type: String, default: '' },
|
|
37
|
+
initialName: { type: String, default: '' },
|
|
38
|
+
saveLabel: { type: String, default: '' },
|
|
39
|
+
cancelLabel: { type: String, default: '' },
|
|
40
|
+
error: { type: String, default: '' },
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const emit = defineEmits(['save', 'cancel'])
|
|
44
|
+
|
|
45
|
+
const draft = ref('')
|
|
46
|
+
const inputRef = ref(null)
|
|
47
|
+
|
|
48
|
+
watch(
|
|
49
|
+
() => props.open,
|
|
50
|
+
async (isOpen) => {
|
|
51
|
+
if (!isOpen) return
|
|
52
|
+
draft.value = props.initialName
|
|
53
|
+
await nextTick()
|
|
54
|
+
inputRef.value?.focus()
|
|
55
|
+
inputRef.value?.select()
|
|
56
|
+
},
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
function onSave() {
|
|
60
|
+
emit('save', draft.value.trim())
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="apphub-desktop-settings">
|
|
3
|
+
<label v-if="showThemeToggle" class="apphub-desktop-settings__row">
|
|
4
|
+
<input
|
|
5
|
+
type="checkbox"
|
|
6
|
+
:checked="theme === 'light'"
|
|
7
|
+
@change="emit('update:theme', $event.target.checked ? 'light' : 'dark')"
|
|
8
|
+
/>
|
|
9
|
+
<span>{{ themeLabel }}</span>
|
|
10
|
+
</label>
|
|
11
|
+
<label class="apphub-desktop-settings__row">
|
|
12
|
+
<input type="checkbox" :checked="snapToGrid" @change="emit('update:snapToGrid', $event.target.checked)" />
|
|
13
|
+
<span>{{ snapLabel }}</span>
|
|
14
|
+
</label>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup>
|
|
19
|
+
defineProps({
|
|
20
|
+
theme: { type: String, default: 'dark' },
|
|
21
|
+
themeLabel: { type: String, default: '' },
|
|
22
|
+
showThemeToggle: { type: Boolean, default: true },
|
|
23
|
+
snapToGrid: { type: Boolean, default: true },
|
|
24
|
+
snapLabel: { type: String, default: '' },
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const emit = defineEmits(['update:theme', 'update:snapToGrid'])
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="apphub-drop-badge"
|
|
4
|
+
:class="{
|
|
5
|
+
'apphub-drop-badge--installing': job.status === 'installing',
|
|
6
|
+
'apphub-drop-badge--done': job.status === 'done',
|
|
7
|
+
'apphub-drop-badge--error': job.status === 'error',
|
|
8
|
+
}"
|
|
9
|
+
:style="badgeStyle"
|
|
10
|
+
>
|
|
11
|
+
<div class="apphub-drop-badge__icon-wrap">
|
|
12
|
+
<div class="apphub-drop-badge__icon-bg" />
|
|
13
|
+
<span class="apphub-drop-badge__icon">{{ job.icon }}</span>
|
|
14
|
+
<svg v-if="job.status === 'installing'" class="apphub-drop-badge__ring" viewBox="0 0 64 64">
|
|
15
|
+
<circle class="apphub-drop-badge__ring-track" cx="32" cy="32" r="28" />
|
|
16
|
+
<circle
|
|
17
|
+
class="apphub-drop-badge__ring-progress"
|
|
18
|
+
cx="32"
|
|
19
|
+
cy="32"
|
|
20
|
+
r="28"
|
|
21
|
+
:style="{ strokeDashoffset: ringOffset }"
|
|
22
|
+
/>
|
|
23
|
+
</svg>
|
|
24
|
+
<span v-if="job.status === 'done'" class="apphub-drop-badge__check">✓</span>
|
|
25
|
+
</div>
|
|
26
|
+
<p class="apphub-drop-badge__label">
|
|
27
|
+
<template v-if="job.status === 'installing'">{{ loadingLabel }}</template>
|
|
28
|
+
<template v-else-if="job.status === 'done'">{{ doneLabel }}</template>
|
|
29
|
+
<template v-else>{{ job.errorMessage || errorLabel }}</template>
|
|
30
|
+
</p>
|
|
31
|
+
<p v-if="job.status === 'installing'" class="apphub-drop-badge__method">{{ methodLabel }}</p>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script setup>
|
|
36
|
+
import { computed } from 'vue'
|
|
37
|
+
|
|
38
|
+
const props = defineProps({
|
|
39
|
+
job: { type: Object, required: true },
|
|
40
|
+
loadingLabel: { type: String, default: '' },
|
|
41
|
+
errorLabel: { type: String, default: '' },
|
|
42
|
+
methodLabel: { type: String, default: '' },
|
|
43
|
+
donePublishLabel: { type: String, default: '' },
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const doneLabel = computed(() => {
|
|
47
|
+
if (props.job.publishSubmitted && props.job.name) {
|
|
48
|
+
return props.job.name
|
|
49
|
+
}
|
|
50
|
+
if (props.job.publishSubmitted && props.donePublishLabel) {
|
|
51
|
+
return props.donePublishLabel
|
|
52
|
+
}
|
|
53
|
+
return props.job.name
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const badgeStyle = computed(() => ({
|
|
57
|
+
left: `${props.job.x}px`,
|
|
58
|
+
top: `${props.job.y}px`,
|
|
59
|
+
}))
|
|
60
|
+
|
|
61
|
+
const ringOffset = computed(() => {
|
|
62
|
+
const circumference = 2 * Math.PI * 28
|
|
63
|
+
return circumference - (circumference * props.job.progress) / 100
|
|
64
|
+
})
|
|
65
|
+
</script>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="open" class="apphub-dup-dialog" @click.self="onCancel">
|
|
3
|
+
<div class="apphub-dup-dialog__panel" role="dialog" aria-modal="true">
|
|
4
|
+
<h3 class="apphub-dup-dialog__title">{{ title }}</h3>
|
|
5
|
+
<p class="apphub-dup-dialog__message">{{ message }}</p>
|
|
6
|
+
<p class="apphub-dup-dialog__hint">{{ hint }}</p>
|
|
7
|
+
<div class="apphub-dup-dialog__actions">
|
|
8
|
+
<button type="button" class="apphub-dup-dialog__btn apphub-dup-dialog__btn--primary" @click="emit('replace')">
|
|
9
|
+
{{ replaceLabel }}
|
|
10
|
+
</button>
|
|
11
|
+
<button type="button" class="apphub-dup-dialog__btn" @click="emit('keep')">
|
|
12
|
+
{{ keepLabel }}
|
|
13
|
+
</button>
|
|
14
|
+
<button type="button" class="apphub-dup-dialog__btn apphub-dup-dialog__btn--ghost" @click="onCancel">
|
|
15
|
+
{{ cancelLabel }}
|
|
16
|
+
</button>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup>
|
|
23
|
+
defineProps({
|
|
24
|
+
open: { type: Boolean, default: false },
|
|
25
|
+
title: { type: String, default: '' },
|
|
26
|
+
message: { type: String, default: '' },
|
|
27
|
+
hint: { type: String, default: '' },
|
|
28
|
+
replaceLabel: { type: String, default: '' },
|
|
29
|
+
keepLabel: { type: String, default: '' },
|
|
30
|
+
cancelLabel: { type: String, default: '' },
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const emit = defineEmits(['replace', 'keep', 'cancel'])
|
|
34
|
+
|
|
35
|
+
function onCancel() {
|
|
36
|
+
emit('cancel')
|
|
37
|
+
}
|
|
38
|
+
</script>
|