Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Skeleton } from "@/browser/components/Skeleton/Skeleton";

const REVEAL_SKELETON_LINE_WIDTHS: readonly string[] = [
"w-[72%]",
"w-[46%]",
"w-[88%]",
"w-[61%]",
"w-[80%]",
"w-[52%]",
"w-[70%]",
"w-[92%]",
"w-[44%]",
"w-[83%]",
"w-[58%]",
"w-[76%]",
"w-[49%]",
"w-[87%]",
"w-[65%]",
"w-[79%]",
"w-[54%]",
"w-[91%]",
"w-[68%]",
"w-[42%]",
"w-[74%]",
"w-[85%]",
"w-[57%]",
"w-[78%]",
];

export function ImmersiveDiffRevealLoadingState(props: { label: string }) {
return (
<div
role="status"
aria-busy="true"
aria-label={props.label}
data-testid="immersive-diff-reveal-skeleton"
className="mx-auto flex h-full w-full max-w-5xl flex-col gap-3 overflow-hidden px-4 py-5 select-none"
>
{/* Match the transcript hydration shimmer instead of a centered spinner: the
diff-shaped placeholder keeps the hidden geometry swap feeling like code
is hydrating in place rather than a blocking modal flash. */}
<Skeleton variant="shimmer" className="mb-1 block h-3 w-40 rounded" />
<div className="flex min-h-0 flex-1 flex-col gap-2.5 overflow-hidden">
{REVEAL_SKELETON_LINE_WIDTHS.map((width, rowIndex) => (
<div key={rowIndex} className="grid grid-cols-[3.5rem_1fr] items-center gap-3">
<Skeleton variant="shimmer" className="h-2 w-8 rounded" />
<Skeleton variant="shimmer" className={`${width} h-2 rounded`} />
</div>
))}
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,27 @@ export const ImmersiveReviewAgentStatusBar: React.FC<ImmersiveReviewAgentStatusB
// `todos` keeps a stable reference from the aggregator (same basis as
// PinnedTodoList reading only `.todos`).
const workspaceStore = useWorkspaceStoreRaw();
const hasRegisteredWorkspace = () =>
// Some unit tests mock only the store selectors they exercise; keep the
// immersive status bar crash-safe in those partial-store environments too.
typeof workspaceStore.hasRegisteredWorkspace === "function" &&
workspaceStore.hasRegisteredWorkspace(workspaceId);
const subscribe = (callback: () => void) =>
workspaceStore.hasRegisteredWorkspace(workspaceId)
? workspaceStore.subscribeKey(workspaceId, callback)
: () => undefined;
hasRegisteredWorkspace() ? workspaceStore.subscribeKey(workspaceId, callback) : () => undefined;
const todos = useSyncExternalStore(subscribe, () =>
workspaceStore.hasRegisteredWorkspace(workspaceId)
? workspaceStore.getWorkspaceState(workspaceId).todos
: EMPTY_TODOS
hasRegisteredWorkspace() ? workspaceStore.getWorkspaceState(workspaceId).todos : EMPTY_TODOS
);
const canInterrupt = useSyncExternalStore(subscribe, () =>
workspaceStore.hasRegisteredWorkspace(workspaceId)
? workspaceStore.getWorkspaceState(workspaceId).canInterrupt
: false
hasRegisteredWorkspace() ? workspaceStore.getWorkspaceState(workspaceId).canInterrupt : false
);
// Sidebar derives `isStarting` directly from `isStreamStarting`.
const isStarting = useSyncExternalStore(subscribe, () =>
workspaceStore.hasRegisteredWorkspace(workspaceId)
hasRegisteredWorkspace()
? workspaceStore.getWorkspaceState(workspaceId).isStreamStarting
: false
);
const awaitingUserQuestion = useSyncExternalStore(subscribe, () =>
workspaceStore.hasRegisteredWorkspace(workspaceId)
hasRegisteredWorkspace()
? workspaceStore.getWorkspaceState(workspaceId).awaitingUserQuestion
: false
);
Expand Down
Loading
Loading