Supersession (newer navigation, path editing, closing, unmount) now aborts the in-flight listing's request instead of only discarding its result: the browser mints an AbortController per listing, the signal rides the workspace face (IWorkspaces.listDirectory gains an optional signal) onto the fetch carrier, and the Host scan stops with it (817's cancellation chain). apps/cli keeps both picker packages as dependencies so the documented one-row cordis.yml swap to the native backend resolves at boot.
44 lines
1.9 KiB
TypeScript
44 lines
1.9 KiB
TypeScript
/**
|
|
* The browse picking occupant (package-internal; the `./client` surface
|
|
* exposes only the Loader exports). Same-package tests exercise it directly
|
|
* through this module.
|
|
*/
|
|
import { createElement } from 'react'
|
|
import type { ReactElement } from 'react'
|
|
import type { DirectoryListing } from '@deepseek-ai/dsh-client-runtime/client'
|
|
import type { Translate } from '@deepseek-ai/dsh-client-locale/client'
|
|
// Type-only: the owner contract of the directory-flow holes.
|
|
import type { DirectoryFlowOwnerProps } from '@deepseek-ai/dsh-client-ui-workspace/client'
|
|
import { DirectoryBrowser } from './DirectoryBrowser.tsx'
|
|
|
|
/** Injected face: the browse wire calls and copy the dialog drives (bound in apply's closure). */
|
|
export interface BrowseFlowInjected {
|
|
/** List one directory level (absent path = the Host home directory); the signal aborts a superseded scan. */
|
|
listDirectory: (path?: string, signal?: AbortSignal) => Promise<DirectoryListing>
|
|
/** Create one child directory under an existing parent. */
|
|
createDirectory: (path: string, name: string) => Promise<string>
|
|
/** Localized dialog copy (this package's namespace). */
|
|
t: Translate
|
|
}
|
|
|
|
/**
|
|
* Flow occupant: adapts the hole's owner conversation onto the browser
|
|
* dialog — a confirmed directory is the picked path, dismissal is the
|
|
* cancellation. Browse failures (unreadable targets, create conflicts) stay
|
|
* inside the dialog's own alert surfaces, so the owner's `onError` arm is
|
|
* never driven by this occupant.
|
|
* @param props - owner conversation plus the injected browse face.
|
|
* @returns the dialog element (renders nothing while closed).
|
|
*/
|
|
export function BrowseDirectoryFlow(props: DirectoryFlowOwnerProps & BrowseFlowInjected): ReactElement {
|
|
return createElement(DirectoryBrowser, {
|
|
open: props.open,
|
|
busy: props.busy,
|
|
listDirectory: props.listDirectory,
|
|
createDirectory: props.createDirectory,
|
|
t: props.t,
|
|
onOpen: props.onPicked,
|
|
onClose: props.onCancel,
|
|
})
|
|
}
|