feat(tui): show time-since-last-user-message alongside session total (#8541)

StatusRule now renders `{sinceLastMsg}/{sinceSession}` (e.g. `12s/3m 45s`)
when a user has submitted in the current session; falls back to the total
alone otherwise. Wires `lastUserAt` through the state/session lifecycle:
- useSubmission stamps `setLastUserAt(Date.now())` on send
- useSessionLifecycle nulls it in reset/resetVisibleHistory
- /branch slash nulls it on fork
This commit is contained in:
Brooklyn Nicholson 2026-04-20 11:17:34 -05:00
parent b7e71fb727
commit 1e7de177e8
8 changed files with 48 additions and 8 deletions

View file

@ -102,6 +102,7 @@ export function useMainApp(gw: GatewayClient) {
const [voiceRecording, setVoiceRecording] = useState(false)
const [voiceProcessing, setVoiceProcessing] = useState(false)
const [sessionStartedAt, setSessionStartedAt] = useState(() => Date.now())
const [lastUserAt, setLastUserAt] = useState<null | number>(null)
const [goodVibesTick, setGoodVibesTick] = useState(0)
const [bellOnComplete, setBellOnComplete] = useState(false)
@ -275,6 +276,7 @@ export function useMainApp(gw: GatewayClient) {
rpc,
scrollRef,
setHistoryItems,
setLastUserAt,
setLastUserMsg,
setSessionStartedAt,
setStickyPrompt,
@ -374,6 +376,7 @@ export function useMainApp(gw: GatewayClient) {
composerState,
gw,
maybeGoodVibes,
setLastUserAt,
setLastUserMsg,
slashRef,
submitRef,
@ -497,6 +500,7 @@ export function useMainApp(gw: GatewayClient) {
newSession: session.newSession,
resetVisibleHistory: session.resetVisibleHistory,
resumeById: session.resumeById,
setLastUserAt,
setSessionStartedAt
},
slashFlightRef,
@ -631,13 +635,25 @@ export function useMainApp(gw: GatewayClient) {
() => ({
cwdLabel: fmtCwdBranch(cwd, gitBranch),
goodVibesTick,
lastUserAt: ui.sid ? lastUserAt : null,
sessionStartedAt: ui.sid ? sessionStartedAt : null,
showStickyPrompt: !!stickyPrompt,
statusColor: statusColorOf(ui.status, ui.theme.color),
stickyPrompt,
voiceLabel: voiceRecording ? 'REC' : voiceProcessing ? 'STT' : `voice ${voiceEnabled ? 'on' : 'off'}`
}),
[cwd, gitBranch, goodVibesTick, sessionStartedAt, stickyPrompt, ui, voiceEnabled, voiceProcessing, voiceRecording]
[
cwd,
gitBranch,
goodVibesTick,
lastUserAt,
sessionStartedAt,
stickyPrompt,
ui,
voiceEnabled,
voiceProcessing,
voiceRecording
]
)
const appTranscript = useMemo(