fix(native): give the "Files" guide row its glyph
The guide renders `entry.icon`, and the `files` kind takeover registered
without one — so after the editor type stopped contributing its own
duplicate row (b56ceec), the single "Files" row was the only entry in the
new-tab list with a blank icon slot. The takeover now carries the editor
descriptor's icon (the takeover IS that descriptor's page).
Extracted `guideIconOf` so both registration sites build the icon field
the same way; the lifecycle test asserts the takeover's guide entry has
an icon.
This commit is contained in:
@@ -63,6 +63,17 @@ function titleOf(descriptor: TabDescriptor): string {
|
||||
return typeof descriptor.title === 'function' ? descriptor.title() : descriptor.title
|
||||
}
|
||||
|
||||
/**
|
||||
* The guide row's glyph for a descriptor icon (nothing when it has none).
|
||||
* The native guide renders `entry.icon`, so a takeover registered without one
|
||||
* is the only row in the list with a blank leading slot.
|
||||
* @param icon - the descriptor's icon value.
|
||||
* @returns the guide-entry icon fields, or an empty object.
|
||||
*/
|
||||
function guideIconOf(icon: TabDescriptor['icon']): { icon?: (props: { size?: number }) => unknown } {
|
||||
return typeof icon === 'function' ? { icon: (props: { size?: number }) => icon(props.size ?? 16) } : {}
|
||||
}
|
||||
|
||||
/**
|
||||
* The chip title of a file address: its own file name. A resource tab is
|
||||
* identified by its address, so the strip must name the FILE — the
|
||||
@@ -171,9 +182,7 @@ export function registerNativeSurface(deps: NativeSurfaceDeps): () => void {
|
||||
order: descriptor.order ?? 100,
|
||||
title: () => titleOf(descriptor),
|
||||
description: () => t('nativeGuideDesc'),
|
||||
...(typeof icon === 'function'
|
||||
? { icon: (props: { size?: number }) => icon(props.size ?? 16) }
|
||||
: {}),
|
||||
...guideIconOf(icon),
|
||||
}],
|
||||
}),
|
||||
})
|
||||
@@ -189,7 +198,7 @@ export function registerNativeSurface(deps: NativeSurfaceDeps): () => void {
|
||||
}
|
||||
|
||||
/** One `files`-kind takeover: the plugin's explorer under the built-in kind. */
|
||||
const registerFilesKind = (): (() => void) => {
|
||||
const registerFilesKind = (editor: TabDescriptor | undefined): (() => void) => {
|
||||
const id = 'dsh-better-sidebar:files'
|
||||
const disposeType = tabs.register({
|
||||
id,
|
||||
@@ -200,6 +209,10 @@ export function registerNativeSurface(deps: NativeSurfaceDeps): () => void {
|
||||
order: 10,
|
||||
title: () => t('files'),
|
||||
description: () => t('nativeGuideDesc'),
|
||||
// The takeover IS the editor descriptor's page, so it carries the
|
||||
// editor's glyph: without it the "Files" row is the only guide
|
||||
// entry with an empty icon slot.
|
||||
...guideIconOf(editor?.icon),
|
||||
}],
|
||||
})
|
||||
const slots = registerSlots(id, { ctx, store, service, records, descriptorId: EDITOR_KIND }, {})
|
||||
@@ -229,7 +242,9 @@ export function registerNativeSurface(deps: NativeSurfaceDeps): () => void {
|
||||
// editor disabled the plugin has no explorer to put there.
|
||||
const wantsFiles = service.isTabEnabled(EDITOR_KIND)
|
||||
const hasFiles = live.has(FILES_KIND)
|
||||
if (wantsFiles && !hasFiles) live.set(FILES_KIND, { dispose: registerFilesKind() })
|
||||
if (wantsFiles && !hasFiles) {
|
||||
live.set(FILES_KIND, { dispose: registerFilesKind(service.getTab(EDITOR_KIND)) })
|
||||
}
|
||||
if (!wantsFiles && hasFiles) {
|
||||
live.get(FILES_KIND)?.dispose()
|
||||
live.delete(FILES_KIND)
|
||||
|
||||
@@ -88,7 +88,7 @@ describe('service routing into the native surface', () => {
|
||||
service.setSurface(surface)
|
||||
service.registerTab({ id: 'terminal', title: 'Terminal', component: () => null, createTab: state => ({ tab: { id: `terminal:${state.nextTerminal}`, type: 'terminal', title: 'Terminal', meta: { n: state.nextTerminal } } }) })
|
||||
service.registerTab({ id: 'git', title: 'Changes', component: () => null })
|
||||
service.registerTab({ id: 'editor', title: 'Files', component: () => null })
|
||||
service.registerTab({ id: 'editor', title: 'Files', component: () => null, icon: () => null })
|
||||
return { surface, calls, service }
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('registerNativeSurface lifecycle (service-driven registration)', () =>
|
||||
store.setSession('s1')
|
||||
const service = createBetterSidebarService(store)
|
||||
service.registerTab({ id: 'terminal', title: 'Terminal', component: () => null })
|
||||
service.registerTab({ id: 'editor', title: 'Files', component: () => null })
|
||||
service.registerTab({ id: 'editor', title: 'Files', component: () => null, icon: () => null })
|
||||
const records = createNativeTabRecords()
|
||||
|
||||
const registered: Array<{ id: string; kind: string; title: (address: string) => string; guide: unknown }> = []
|
||||
@@ -223,6 +223,10 @@ describe('registerNativeSurface lifecycle (service-driven registration)', () =>
|
||||
expect(editorType?.guide).toBeUndefined()
|
||||
const filesType = registered.find(entry => entry.kind === 'files')
|
||||
expect(filesType?.guide).toBeDefined()
|
||||
// The takeover carries the editor's glyph, so the "Files" guide row is
|
||||
// not the only one with a blank icon slot.
|
||||
const filesGuide = filesType?.guide as Array<{ icon?: unknown }> | undefined
|
||||
expect(filesGuide?.[0]?.icon).toBeDefined()
|
||||
|
||||
dispose()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user