Files
deepseek-harness/packages/client/ui-sidebar-documentpreview/src/client/index.ts
T

131 lines
6.3 KiB
TypeScript

/**
* Browser half: register `text` as a right-Sidebar tab type.
*
* The type reaches the Sidebar through its public path only: the definition into
* `ctx.sidebarRightTabs`, the body into the keyed `sidebar.right.pane.tab`
* seat, and the chip title into `sidebar.right.pane.tab.title`, both under the
* definition's `id`. Nothing here reaches into the Sidebar's store, its
* panes, or its sequence. The file's metadata comes from the standard
* `useResource`, served by the `file` provider; the content is this type's own
* business, read through its face. Every import from another
* client plugin is a type.
*/
import type { Context as ClientContext } from '@deepseek-ai/cordis'
import type {} from '@deepseek-ai/dsh-api-remotes/client'
import type {} from '@deepseek-ai/dsh-client-locale/client'
import type {} from '@deepseek-ai/dsh-client-resources/client'
import type {} from '@deepseek-ai/dsh-client-ui-renderer/client'
import type {} from '@deepseek-ai/dsh-client-ui-session/client'
import type {} from '@deepseek-ai/dsh-client-ui-sidebar-right/client'
import type {} from '@deepseek-ai/dsh-api-gateway/client'
import type {} from '@deepseek-ai/dsh-api-workspace-files/remote'
import type { WorkspaceFileParams } from '@deepseek-ai/dsh-api-workspace-files/client'
import { TextPreview } from './TextPreview.tsx'
import type { TextPreviewInjected } from './TextPreview.tsx'
import { TextTitle } from './TextTitle.tsx'
import { TEXTPREVIEW_ID, textDefinition } from './definition.ts'
import { textFace } from './face.ts'
import { createReadPage } from './rpc.ts'
import { createTextStore } from './store.ts'
import { en, zh } from './locales.ts'
import { DocumentPreviewRegistry } from './document/registry.ts'
import { documentTabInfoFactory } from './document/contract.ts'
import { apply as registerText } from './text/index.ts'
import { apply as registerMarkdown } from './markdown/index.ts'
import { apply as registerHtml } from './html/index.ts'
import { apply as registerImage } from './image/index.ts'
import { apply as registerPdf } from './pdf/index.ts'
import { apply as registerCode } from './code/index.ts'
import { apply as registerOffice } from './office/index.ts'
import { apply as registerExcel } from './excel/index.ts'
import { Config } from '../config.ts'
// Values stay package-private unless another package needs them; the plugin
// surface is `apply`, `inject`, and the store factory another registration may
// share, plus the types a consumer of the seat or the store names.
export type { SidebarDocumentPreviewKey } from './locales.ts'
export type { TextPreviewProps } from './TextPreview.tsx'
export type { TextInjected } from './face.ts'
export type { ReadDocumentBytes, DocumentFileBytes, ReadWorkspaceFilePage, SessionFile, WorkspaceFilesReadRemote } from './rpc.ts'
export type { TextPage, TextState, TextStore, TextTabState } from './store.ts'
export type { DocumentContent, DocumentPreviewProps, DocumentTextPage } from './document/contract.ts'
export type { DocumentLoadMode, DocumentPreviewDefinition } from './document/registry.ts'
declare module '@deepseek-ai/cordis' {
interface Context {
/** File-extension renderer registrations, independent from their keyed document bodies. */
documentPreviews: DocumentPreviewRegistry
}
}
/** This package's copy namespace. */
const NS = 'sidebarDocumentPreview'
declare module '@deepseek-ai/dsh-client-ui-sidebar-right/client' {
interface SidebarRightResourceParamsMap {
/** File line navigation supported by the text preview. */
file: WorkspaceFileParams
}
}
declare module '@deepseek-ai/dsh-client-ui-slots' {
interface LocaleNamespaceMap {
/** Text-preview progress, paging, change, control, and failure lines. */
sidebarDocumentPreview: import('./locales.ts').SidebarDocumentPreviewKey
}
}
/**
* Required browser services: the tab registry, the slot registry, copy, and the
* workspace Remote for bytes and paged text reads.
*/
export const inject = ['slots', 'locale', 'sidebarRightTabs', 'remote', 'remote.workspaceFiles', 'configForms', 'resources']
/**
* Client plugin body: register the type, its dictionaries, its body, and its chip title.
* @param ctx - client root context carrying the registry, slots, copy, and file readers.
*/
export function apply(ctx: ClientContext): void {
const config = Config((globalThis as { __DSH_DOCUMENT_PREVIEW_CONFIG__?: unknown }).__DSH_DOCUMENT_PREVIEW_CONFIG__ ?? {})
const previews = new DocumentPreviewRegistry()
const disposePreviews = ctx.reflect.provide('documentPreviews', previews)
ctx.effect(() => disposePreviews)
ctx.effect(() => ctx.sidebarRightTabs.register(textDefinition()), 'ui-sidebar-documentpreview: text type')
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ui-sidebar-documentpreview: dictionaries')
const store = createTextStore()
const face = textFace(
createReadPage(ctx.remote),
(file, signal) => ctx.remote.workspaceFiles.readBytes(file.sessionId, file.path, {}, signal),
ctx.resources,
)
const source = { getSnapshot: previews.getSnapshot, subscribe: previews.subscribe }
ctx.effect(() => ctx.slots.inject('sidebar.right.pane.tab', () => ctx.slots.register(
{
name: 'sidebar.right.pane.tab', key: TEXTPREVIEW_ID, locale: NS, store,
children: {
'sidebar.right.tab.document': { kind: 'keyed', scope: 'session', inject: { hooks: { tabInfo: documentTabInfoFactory } } },
'sidebar.right.tab.document.actions': { kind: 'list', scope: 'session' },
'sidebar.right.tab.document.unpreviewable': { kind: 'list', scope: 'session' },
'sidebar.right.tab.document.action': { kind: 'keyed', scope: 'session', inject: { hooks: { tabInfo: documentTabInfoFactory } } },
},
inject: (sessionId, actions): TextPreviewInjected => ({
...face(sessionId, actions), hooks: { documentPreviews: source },
}),
},
TextPreview,
)), 'ui-sidebar-documentpreview: text body')
ctx.effect(() => ctx.slots.inject('sidebar.right.pane.tab.title', () => ctx.slots.register(
{ name: 'sidebar.right.pane.tab.title', key: TEXTPREVIEW_ID },
TextTitle,
)), 'ui-sidebar-documentpreview: text title')
registerText(ctx)
registerMarkdown(ctx)
registerHtml(ctx)
registerImage(ctx)
registerPdf(ctx)
registerOffice(ctx, config.office)
registerExcel(ctx, config.excel)
registerCode(ctx)
}