diff --git a/apps/mobile/src/screens/thread/ThreadDetailHeader.tsx b/apps/mobile/src/screens/thread/ThreadDetailHeader.tsx index 75ebdbe3f1..604a047631 100644 --- a/apps/mobile/src/screens/thread/ThreadDetailHeader.tsx +++ b/apps/mobile/src/screens/thread/ThreadDetailHeader.tsx @@ -1,13 +1,13 @@ import { Pressable, View } from "react-native"; import { useTheme } from "@/theme"; -import { cn, Icon, Spinner, Text } from "@/ui"; +import { cn, Icon, Text } from "@/ui"; import { PanelToggleButton } from "../panel/PanelToggleButton"; import type { ThreadStatusPill } from "./thread-detail-header-model"; /** * The thread screen's native header pieces. There is one header only: the * title (tap to rename) with a status subtitle while the thread needs - * attention or works, and two buttons on the right — the workspace panel + * attention, has an error, or waits on a host, and two buttons on the right — the workspace panel * and the "…" menu. Everything else the old two-layer header carried * (environment line, child roll-up, git action) lives in the menu sheet. */ @@ -21,13 +21,18 @@ export interface ThreadHeaderTitleProps { onPressTitle: (() => void) | null; } -/** Subtitle shown under the title; idle / archived threads show none. */ +/** + * Subtitle shown under the title. Idle threads show none, and working threads + * show none either: the timeline's working indicator already carries that. + */ export function headerSubtitle( statusPill: ThreadStatusPill, childPillLabel: ThreadHeaderTitleProps["childPillLabel"], ): string | null { const parts: string[] = []; - if (statusPill.tone !== "idle") parts.push(statusPill.label); + if (statusPill.tone !== "idle" && statusPill.tone !== "working") { + parts.push(statusPill.label); + } if (childPillLabel) parts.push(childPillLabel); return parts.length > 0 ? parts.join(" · ") : null; } @@ -68,21 +73,14 @@ export function ThreadHeaderTitle({ {title} {subtitle ? ( - - {statusPill.spinning ? ( - - ) : null} - - {subtitle} - - + {subtitle} + ) : null} ); diff --git a/apps/mobile/src/screens/thread/thread-detail-header-model.ts b/apps/mobile/src/screens/thread/thread-detail-header-model.ts index 087cce4e39..add23552f0 100644 --- a/apps/mobile/src/screens/thread/thread-detail-header-model.ts +++ b/apps/mobile/src/screens/thread/thread-detail-header-model.ts @@ -10,7 +10,8 @@ import { assertNever } from "@bb/thread-view"; /** * Pure header facts for the thread detail screen: the status pill (from the * client-core runtime display status, with the thread's own status and - * pending input layered on) and the one-line environment summary. + * pending input layered on) and the one-line environment summary. The header + * hides "working" tones; the timeline's working indicator already shows them. */ export type ThreadStatusPillTone = @@ -23,8 +24,6 @@ export type ThreadStatusPillTone = export interface ThreadStatusPill { label: string; tone: ThreadStatusPillTone; - /** Shows a spinner glyph instead of a static one. */ - spinning: boolean; } export function describeThreadStatusPill({ @@ -39,33 +38,33 @@ export function describeThreadStatusPill({ archived: boolean; }): ThreadStatusPill { if (hasPendingInteraction) { - return { label: "Needs input", tone: "attention", spinning: false }; + return { label: "Needs input", tone: "attention" }; } if (threadStatus === "stopping") { - return { label: "Stopping", tone: "working", spinning: true }; + return { label: "Stopping", tone: "working" }; } switch (runtimeDisplayStatus) { case "active": - return { label: "Working", tone: "working", spinning: true }; + return { label: "Working", tone: "working" }; case "provisioning": - return { label: "Provisioning", tone: "working", spinning: true }; + return { label: "Provisioning", tone: "working" }; case "starting": - return { label: "Starting", tone: "working", spinning: true }; + return { label: "Starting", tone: "working" }; case "stopping": - return { label: "Stopping", tone: "working", spinning: true }; + return { label: "Stopping", tone: "working" }; case "host-reconnecting": - return { label: "Reconnecting", tone: "working", spinning: true }; + return { label: "Reconnecting", tone: "working" }; case "waiting-for-host": - return { label: "Waiting for host", tone: "muted", spinning: false }; + return { label: "Waiting for host", tone: "muted" }; case "error": - return { label: "Error", tone: "error", spinning: false }; + return { label: "Error", tone: "error" }; case "idle": if (threadStatus === "error") { - return { label: "Error", tone: "error", spinning: false }; + return { label: "Error", tone: "error" }; } return archived - ? { label: "Archived", tone: "muted", spinning: false } - : { label: "Idle", tone: "idle", spinning: false }; + ? { label: "Archived", tone: "muted" } + : { label: "Idle", tone: "idle" }; default: return assertNever(runtimeDisplayStatus); }