mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 10:27:33 +00:00
* refactor(mobile): give relay and encryption concrete owners * refactor(mobile): organize session and review feature owners * refactor(mobile): organize RPC and host ownership * test(mobile): point render fixtures at concrete owners * refactor(mobile): use explicit type-only owner imports
130 lines
3.9 KiB
TypeScript
130 lines
3.9 KiB
TypeScript
import { agentNoUpdateLabel } from '../../../src/shared/agent-status/presentation/agent-row-decay-state'
|
||
import { memo, type ReactNode } from 'react'
|
||
import { Pressable, Text, View } from 'react-native'
|
||
import type { RuntimeWorktreeAgentRow } from '../../../src/shared/runtime-types'
|
||
import { withoutNativeChatVisualDirectiveLines } from '../../../src/shared/native-chat/native-chat-visual-directive'
|
||
import { colors, spacing, pressedStyle } from '../theme/mobile-theme'
|
||
import { themedStyleSheet } from '../theme/themed-styles'
|
||
import { useMobileColorScheme } from '../theme/use-mobile-color-scheme'
|
||
import {
|
||
agentDisplayLabel,
|
||
agentDotState,
|
||
agentRowTimeAt,
|
||
formatTimeAgo
|
||
} from '../worktree/agent-row-display'
|
||
import { AgentStateDot } from './AgentStateDot'
|
||
import { MobileAgentIcon } from './MobileAgentIcon'
|
||
import type { AgentChildRowModel } from '../../../src/shared/agent-status/presentation/agent-child-row-model'
|
||
import { mobileAgentChildRowText } from '../worktree/mobile-agent-child-row-text'
|
||
|
||
export const AGENT_ROW_INDENT_PER_DEPTH = 14
|
||
|
||
type Props = {
|
||
agent: RuntimeWorktreeAgentRow
|
||
depth: number
|
||
now: number
|
||
// Use workspace’s unvisited signal for agent bold/foreground too, matching desktop.
|
||
unvisited: boolean
|
||
childRow?: AgentChildRowModel
|
||
isReadOnly?: boolean
|
||
onPress?: (paneKey: string) => void
|
||
onLongPress?: () => void
|
||
trailing?: ReactNode
|
||
}
|
||
|
||
// Match compact desktop DashboardAgentRow: state→identity→message/prompt→age.
|
||
function WorktreeAgentRowComponent({
|
||
agent,
|
||
depth,
|
||
now,
|
||
unvisited,
|
||
childRow,
|
||
isReadOnly,
|
||
onPress,
|
||
onLongPress,
|
||
trailing
|
||
}: Props) {
|
||
useMobileColorScheme()
|
||
const dotState = childRow?.displayState ?? agentDotState(agent, now)
|
||
// Visuals render only in transcript; row keeps surrounding prose and treats visual-only reply as empty.
|
||
const reply = agent.lastAssistantMessage
|
||
const label = agentDisplayLabel(
|
||
reply
|
||
? { ...agent, lastAssistantMessage: withoutNativeChatVisualDirectiveLines(reply) }
|
||
: agent,
|
||
now
|
||
)
|
||
const childText = childRow ? mobileAgentChildRowText(childRow, now) : null
|
||
const timeAt = childRow ? childRow.firstObservedAt : agentRowTimeAt(agent)
|
||
// Like desktop, a silent row reports how long since its last update, not when its turn began.
|
||
const ts =
|
||
childRow && timeAt <= 0
|
||
? ''
|
||
: !childRow && dotState === 'unverifiable'
|
||
? agentNoUpdateLabel(agent, now)
|
||
: formatTimeAgo(timeAt, now)
|
||
|
||
const content = (
|
||
<View style={[styles.row, { paddingLeft: depth * AGENT_ROW_INDENT_PER_DEPTH }]}>
|
||
<AgentStateDot state={dotState} />
|
||
{/* Use desktop-style agent identity logo instead of two-letter code. */}
|
||
{!childRow && agent.agentType ? (
|
||
<MobileAgentIcon agentId={agent.agentType} size={13} />
|
||
) : null}
|
||
<Text style={[styles.label, unvisited && styles.labelUnvisited]} numberOfLines={1}>
|
||
{childText ? (
|
||
<>
|
||
{childText.lead}
|
||
{childText.trail ? ` · ${childText.trail}` : ''}
|
||
</>
|
||
) : (
|
||
label
|
||
)}
|
||
</Text>
|
||
{trailing}
|
||
<Text style={styles.time}>{ts}</Text>
|
||
</View>
|
||
)
|
||
return onPress ? (
|
||
<Pressable
|
||
style={({ pressed }) => pressed && pressedStyle}
|
||
disabled={isReadOnly}
|
||
accessibilityRole="button"
|
||
onPress={(event) => {
|
||
event.stopPropagation()
|
||
onPress(agent.paneKey)
|
||
}}
|
||
onLongPress={onLongPress}
|
||
delayLongPress={400}
|
||
>
|
||
{content}
|
||
</Pressable>
|
||
) : (
|
||
content
|
||
)
|
||
}
|
||
|
||
export const WorktreeAgentRow = memo(WorktreeAgentRowComponent)
|
||
|
||
const styles = themedStyleSheet(() => ({
|
||
row: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
gap: spacing.xs,
|
||
marginTop: 3
|
||
},
|
||
label: {
|
||
flex: 1,
|
||
fontSize: 11,
|
||
color: colors.textMuted
|
||
},
|
||
labelUnvisited: {
|
||
color: colors.textPrimary,
|
||
fontWeight: '600'
|
||
},
|
||
time: {
|
||
fontSize: 10,
|
||
color: colors.textMuted
|
||
}
|
||
}))
|