Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions packages/hub-ui/src/client/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,26 @@ export const BUILTIN_ENTRY_CLIENT_AUTH_NOTICE: DevframeViewBuiltin = Object.free
icon: 'ph:warning-duotone',
})

/**
* The viewer's own Settings view. hub-ui owns this `~builtin` dock rather than
* leaning on a host to register it server-side — so the Settings tab is visible
* by default in every consumer of the reference UI (the standalone viewer and
* the embedded dock alike). A `~builtin` view defaults its category to
* `~builtin`, so it groups and sorts last on the bar. A host that registers its
* own `~settings` dock (node-side, into `devframe:docks`) still wins the merge;
* this entry only fills the gap when none is present.
*/
export const BUILTIN_ENTRY_SETTINGS: DevframeViewBuiltin = Object.freeze({
type: '~builtin',
category: '~builtin',
id: '~settings',
title: 'Settings',
icon: 'ph:gear-duotone',
})

export const BUILTIN_ENTRIES: readonly DevframeViewBuiltin[] = Object.freeze([
BUILTIN_ENTRY_CLIENT_AUTH_NOTICE,
BUILTIN_ENTRY_SETTINGS,
])

export { DEFAULT_CATEGORIES_ORDER } from '@devframes/hub/constants'
38 changes: 25 additions & 13 deletions packages/hub-ui/src/client/state/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { HubDocksUserSettings } from './dock-settings'
import { attachFrameNavClient } from '@devframes/hub/client'
import { DEFAULT_STATE_USER_SETTINGS } from '@devframes/hub/constants'
import { computed, markRaw, reactive, ref, toRefs, watch, watchEffect } from 'vue'
import { BUILTIN_ENTRIES, HUB_UI_HIDE_EVENT } from '../constants'
import { BUILTIN_ENTRIES, BUILTIN_ENTRY_SETTINGS, HUB_UI_HIDE_EVENT } from '../constants'
import { useBranding } from './branding'
import { createCommandsContext } from './commands'
import { docksGroupByCategories, getCategoryLabel, getGroupMembers, getGroupMembersGrouped, getRegisteredGroupIds, resolveCommandIcon, resolveGroupDefaultChild } from './dock-settings'
Expand Down Expand Up @@ -36,20 +36,32 @@ export async function createDocksContext(
const clientDocks = reactive(new Map<string, DevframeDockEntry>())
const entries = computed<DevframeDockEntry[]>(() => {
const server = dockEntries.value
if (clientDocks.size === 0)
return server
const seen = new Set<string>()
const merged: DevframeDockEntry[] = []
for (const entry of server) {
seen.add(entry.id)
// a client dock sharing a server id overrides it in the local merge
merged.push(clientDocks.get(entry.id) ?? entry)
let base: DevframeDockEntry[]
if (clientDocks.size === 0) {
base = server
}
for (const [id, entry] of clientDocks) {
if (!seen.has(id))
merged.push(entry)
else {
const seen = new Set<string>()
const merged: DevframeDockEntry[] = []
for (const entry of server) {
seen.add(entry.id)
// a client dock sharing a server id overrides it in the local merge
merged.push(clientDocks.get(entry.id) ?? entry)
}
for (const [id, entry] of clientDocks) {
if (!seen.has(id))
merged.push(entry)
}
base = merged
}
return merged
// Surface the viewer's own built-in Settings tab by default. hub-ui owns it
// rather than depending on a host to register `~settings` server-side, so
// Settings is always reachable (dock bar + `devframes:open-settings`). A host
// that registered its own `~settings` entry wins — we only add ours when the
// merged list has none.
if (base.some(entry => entry.id === BUILTIN_ENTRY_SETTINGS.id))
return base
return [...base, BUILTIN_ENTRY_SETTINGS]
})

const selectedId = ref<string | null>(null)
Expand Down
Loading