feat(client): surface pending session interactions
This commit is contained in:
@@ -306,6 +306,7 @@ function SearchResults({
|
||||
result={result}
|
||||
currentId={list.current}
|
||||
onOpen={open}
|
||||
t={t}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -47,6 +47,8 @@ export const zh = {
|
||||
'status.running': '进行中',
|
||||
'status.idle': '空闲',
|
||||
'status.waitingApproval': '等待审批',
|
||||
'status.planReview': '计划待审',
|
||||
'status.waitingAnswer': '等待回答',
|
||||
'hover.created': '创建于 {time}',
|
||||
'hover.copied': '已复制',
|
||||
'date.ymd': '{y}年{m}月{d}日',
|
||||
@@ -105,6 +107,8 @@ export const en = {
|
||||
'status.running': 'Running',
|
||||
'status.idle': 'Idle',
|
||||
'status.waitingApproval': 'Waiting for approval',
|
||||
'status.planReview': 'Plan awaiting review',
|
||||
'status.waitingAnswer': 'Waiting for answer',
|
||||
'hover.created': 'Created {time}',
|
||||
'hover.copied': 'Copied',
|
||||
'date.ymd': '{y}-{m}-{d}',
|
||||
|
||||
@@ -166,14 +166,29 @@ export function ProjectRowItem({ group, onToggle, onCreate, actions, t }: {
|
||||
)
|
||||
}
|
||||
|
||||
/** Session status presentation; approval waiting outranks the underlying running state. */
|
||||
function sessionStatus(node: SessionNode, t: RowTranslate): { state: StateDotState; label: string } {
|
||||
if (node.waitingApproval) return { state: 'warning', label: t('status.waitingApproval') }
|
||||
/* v8 ignore next 3 -- closed-union backstop; only reached if the status is forged */
|
||||
function assertNever(value: never): never {
|
||||
throw new Error(`unknown pending interaction: ${String(value)}`)
|
||||
}
|
||||
|
||||
/** Session status presentation; pending user interaction outranks the running state. */
|
||||
function sessionStatus(
|
||||
node: Pick<SessionNode, 'pendingInteraction' | 'running'>,
|
||||
t: RowTranslate,
|
||||
): { state: StateDotState; label: string } {
|
||||
switch (node.pendingInteraction) {
|
||||
case 'approval': return { state: 'warning', label: t('status.waitingApproval') }
|
||||
case 'plan-review': return { state: 'warning', label: t('status.planReview') }
|
||||
case 'question': return { state: 'warning', label: t('status.waitingAnswer') }
|
||||
case undefined: break
|
||||
/* v8 ignore next -- closed PendingInteractionStatus union */
|
||||
default: return assertNever(node.pendingInteraction)
|
||||
}
|
||||
if (node.running) return { state: 'ongoing', label: t('status.running') }
|
||||
return { state: 'done', label: t('status.idle') }
|
||||
}
|
||||
|
||||
/** Hover-card body: full title, relative time, and approval/running/idle status. */
|
||||
/** Hover-card body: full title, relative time, and interaction/running/idle status. */
|
||||
function SessionHoverContent({ node, now, t }: { node: SessionNode; now: number; t: RowTranslate }) {
|
||||
const status = sessionStatus(node, t)
|
||||
return (
|
||||
@@ -215,14 +230,17 @@ export interface RowDragProps {
|
||||
* @param props.result - merged local/content search row.
|
||||
* @param props.currentId - selected session id.
|
||||
* @param props.onOpen - open the selected session.
|
||||
* @param props.t - Workspace-browser translation seat.
|
||||
* @returns the result button.
|
||||
*/
|
||||
export function SearchResultItem({ result, currentId, onOpen }: {
|
||||
export function SearchResultItem({ result, currentId, onOpen, t }: {
|
||||
result: SearchResultNode
|
||||
currentId: string | undefined
|
||||
onOpen: (id: SearchResultNode['id']) => void
|
||||
t: RowTranslate
|
||||
}) {
|
||||
const selected = result.id === currentId
|
||||
const status = sessionStatus(result, t)
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
@@ -232,7 +250,14 @@ export function SearchResultItem({ result, currentId, onOpen }: {
|
||||
onClick={() => { onOpen(result.id) }}
|
||||
>
|
||||
<span className={css.searchResultHeading}>
|
||||
<span className={css.slot}>{result.running && <StateDot state="ongoing" />}</span>
|
||||
<span className={css.slot}>
|
||||
{status.state !== 'done' && (
|
||||
<>
|
||||
<StateDot state={status.state} />
|
||||
<span className={css.visuallyHidden}>{status.label}</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
<span className={css.searchResultTitle}>{result.title}</span>
|
||||
</span>
|
||||
<span className={css.searchResultWorkspace}>{result.workspace}</span>
|
||||
@@ -250,7 +275,7 @@ function rowHalf(e: { clientY: number; currentTarget: HTMLElement }): 'before' |
|
||||
}
|
||||
|
||||
/**
|
||||
* One top-level 34px session row: status dot (approval waiting outranks
|
||||
* One top-level 34px session row: status dot (pending user interaction outranks
|
||||
* running), title, relative time, and the row actions menu.
|
||||
* @param props.node - derived session node.
|
||||
* @param props.currentId - selected session id (row highlight).
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
* remains visible.
|
||||
*/
|
||||
import type {
|
||||
SessionId, SessionListState, SessionSearchResultItem, SessionSummary, WorkspaceId, WorkspaceView,
|
||||
PendingInteractionStatus, SessionId, SessionListState, SessionSearchResultItem, SessionSummary,
|
||||
WorkspaceId, WorkspaceView,
|
||||
} from '@deepseek-ai/dsh-client-runtime/client'
|
||||
|
||||
/** Group key for Sessions outside every Workspace. */
|
||||
@@ -20,8 +21,8 @@ export interface SessionNode {
|
||||
title: string
|
||||
/** The provisional blank session (renderer shows the localized New Session title). */
|
||||
blank: boolean
|
||||
/** The runtime Session list reports a pending approval request for this Session. */
|
||||
waitingApproval: boolean
|
||||
/** The runtime Session list reports an interaction awaiting this user. */
|
||||
pendingInteraction?: PendingInteractionStatus
|
||||
running: boolean
|
||||
updatedAt: number
|
||||
}
|
||||
@@ -50,6 +51,8 @@ export interface SearchResultNode {
|
||||
id: SessionId
|
||||
title: string
|
||||
workspace: string
|
||||
/** The runtime Session list reports an interaction awaiting this user. */
|
||||
pendingInteraction?: PendingInteractionStatus
|
||||
running: boolean
|
||||
snippet?: string
|
||||
}
|
||||
@@ -171,9 +174,9 @@ function sessionNode(s: SessionSummary): SessionNode {
|
||||
id: s.id,
|
||||
title: sessionTitle(s),
|
||||
blank: s.blank,
|
||||
waitingApproval: s.waitingApproval,
|
||||
running: s.running,
|
||||
updatedAt: s.updatedAt,
|
||||
...(s.pendingInteraction === undefined ? {} : { pendingInteraction: s.pendingInteraction }),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,6 +327,9 @@ export function deriveSearchResults(
|
||||
title: sessionTitle(summary),
|
||||
workspace: labelOf(summary),
|
||||
running: summary.running,
|
||||
...(summary.pendingInteraction === undefined
|
||||
? {}
|
||||
: { pendingInteraction: summary.pendingInteraction }),
|
||||
...match === undefined ? {} : { snippet: match.snippet },
|
||||
}
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user