fix(web): make right sidebar header toggle work across mobile, projects, and groups
This commit is contained in:
parent
35b7291660
commit
996af168ef
@ -662,7 +662,7 @@ export function ShellPage() {
|
||||
);
|
||||
const inProject = Boolean(activeSpace && !activeSpace.isDefault);
|
||||
const coordinatorBot: Bot | undefined = useMemo(() => {
|
||||
if (!inProject || !activeSpace) return undefined;
|
||||
if ((!inProject && !inGroup) || !activeSpace) return undefined;
|
||||
const leadId =
|
||||
snapshot?.leadBotId ??
|
||||
activeGroup?.leadBotId ??
|
||||
@ -673,10 +673,12 @@ export function ShellPage() {
|
||||
bots.find((b) => b.kind === "main" && b.spaceId === activeSpace.id) ??
|
||||
bots.find((b) => b.spaceId === activeSpace.id);
|
||||
if (!found) return undefined;
|
||||
const isLegacyName = found.name === "Chief" || found.name === "Projektkoordinator";
|
||||
const isLegacyName =
|
||||
inProject && (found.name === "Chief" || found.name === "Projektkoordinator");
|
||||
return isLegacyName ? { ...found, name: "Projektmanager" } : found;
|
||||
}, [
|
||||
inProject,
|
||||
inGroup,
|
||||
activeSpace,
|
||||
snapshot?.leadBotId,
|
||||
activeGroup?.leadBotId,
|
||||
@ -786,6 +788,8 @@ export function ShellPage() {
|
||||
routeGroupId.current = groupId;
|
||||
const activeBotId = useRef<string | undefined>(inGroup ? undefined : active?.id);
|
||||
activeBotId.current = inGroup ? undefined : active?.id;
|
||||
const coordinatorBotIdRef = useRef<string | undefined>(coordinatorBot?.id);
|
||||
coordinatorBotIdRef.current = coordinatorBot?.id;
|
||||
const activeGroupId = useRef<string | undefined>(groupId);
|
||||
activeGroupId.current = groupId;
|
||||
const screenRequest = useRef(0);
|
||||
@ -1053,7 +1057,9 @@ export function ShellPage() {
|
||||
return loadComputerScreen({
|
||||
load: () => rpc.computer.screenUrl({ botId: id }),
|
||||
isCurrent: () =>
|
||||
request === screenRequest.current && activeBotId.current === id && computerVisible.current,
|
||||
request === screenRequest.current &&
|
||||
(activeBotId.current === id || coordinatorBotIdRef.current === id) &&
|
||||
computerVisible.current,
|
||||
commit: (screen) => {
|
||||
setScreenUrl(screen.url);
|
||||
setComputerError(screen.error);
|
||||
@ -1480,17 +1486,21 @@ export function ShellPage() {
|
||||
void refreshThread(active.id).catch(() => undefined);
|
||||
} else if (isComputerStatusEvent(event)) {
|
||||
void refreshComputerScreen(active.id).catch(() => undefined);
|
||||
} else if (event.type === "thread.computer") {
|
||||
}
|
||||
if (event.type === "thread.computer") {
|
||||
agentPointerFeed.publish(event.botId, event.payload, event.createdAt);
|
||||
const screenRun = liveScreenRunId(event);
|
||||
if (screenRun) {
|
||||
setScreenRunId(screenRun);
|
||||
setScreenActive(true);
|
||||
window.clearTimeout(screenActiveTimer.current);
|
||||
screenActiveTimer.current = window.setTimeout(
|
||||
() => setScreenActive(false),
|
||||
SCREEN_ACTIVE_MS,
|
||||
);
|
||||
}
|
||||
const screenRun = liveScreenRunId(event);
|
||||
if (screenRun) {
|
||||
setScreenRunId(screenRun);
|
||||
setScreenActive(true);
|
||||
window.clearTimeout(screenActiveTimer.current);
|
||||
screenActiveTimer.current = window.setTimeout(
|
||||
() => setScreenActive(false),
|
||||
SCREEN_ACTIVE_MS,
|
||||
);
|
||||
if (computerRef.current?.state !== "running") {
|
||||
void refreshComputerScreen(active.id).catch(() => undefined);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1598,6 +1608,9 @@ export function ShellPage() {
|
||||
// waiting_input: reconcile ask cards if a stale post-send refresh raced SSE.
|
||||
void refreshGroupThread(groupId).catch(() => undefined);
|
||||
}
|
||||
if (event.type === "thread.computer") {
|
||||
agentPointerFeed.publish(event.botId, event.payload, event.createdAt);
|
||||
}
|
||||
},
|
||||
});
|
||||
return () => {
|
||||
@ -1910,10 +1923,11 @@ export function ShellPage() {
|
||||
const handleRunErrorPresented = useCallback((runId: string) => {
|
||||
rememberSeenRunErrorId(runId);
|
||||
}, []);
|
||||
const groupComputerBotId =
|
||||
inGroup && activeSnapshot?.leadBotId && bots.some((bot) => bot.id === activeSnapshot.leadBotId)
|
||||
? activeSnapshot.leadBotId
|
||||
: undefined;
|
||||
const groupComputerBotId = inGroup
|
||||
? (activeSnapshot?.leadBotId && bots.some((bot) => bot.id === activeSnapshot.leadBotId)
|
||||
? activeSnapshot.leadBotId
|
||||
: coordinatorBot?.id)
|
||||
: undefined;
|
||||
// A bot message without a sender speaks for the conversation's own bot, never as an anonymous one.
|
||||
const defaultSpeakerId = inGroup ? activeSnapshot?.leadBotId : active?.id;
|
||||
const transcriptMessages = useMemo(() => {
|
||||
@ -2031,6 +2045,7 @@ export function ShellPage() {
|
||||
const workspaceFocusRef = useRef<{ threadId: string; focus: WorkspaceFocus } | null>(null);
|
||||
const autoPanelRef = useRef(autoPanel);
|
||||
autoPanelRef.current = autoPanel;
|
||||
const autoLayoutSplitRef = useRef(false);
|
||||
const autoCloseTimer = useRef<number | undefined>(undefined);
|
||||
useEffect(() => () => window.clearTimeout(autoCloseTimer.current), []);
|
||||
// The pane follows the bot's work on focus edges only, so it never jumps while nothing changed.
|
||||
@ -2049,7 +2064,7 @@ export function ShellPage() {
|
||||
if (!wideLayout) return;
|
||||
const paneState: PaneState = {
|
||||
open:
|
||||
panel === "computer"
|
||||
panel === "computer" || panel === "browser"
|
||||
? "screen"
|
||||
: panel === "artifact"
|
||||
? "artifact"
|
||||
@ -2066,13 +2081,22 @@ export function ShellPage() {
|
||||
if (closing === null || autoPanelRef.current !== closing) return;
|
||||
setPanel(null);
|
||||
setAutoPanel(null);
|
||||
if (autoLayoutSplitRef.current) {
|
||||
autoLayoutSplitRef.current = false;
|
||||
dualSurface.setLayoutMode("stream");
|
||||
}
|
||||
}, AUTO_SCREEN_CLOSE_DELAY_MS);
|
||||
return;
|
||||
}
|
||||
if (next.open === "artifact") setArtifactPane(workspaceFocus.artifact);
|
||||
if (next.open === "screen") setCanvasTab("browser");
|
||||
const nextPanel: Panel = next.open === "screen" ? "computer" : next.open;
|
||||
setPanel(nextPanel);
|
||||
setAutoPanel(next.auto ? nextPanel : null);
|
||||
if (dualSurface.layoutMode === "stream") {
|
||||
autoLayoutSplitRef.current = Boolean(next.auto);
|
||||
dualSurface.setLayoutMode("split");
|
||||
}
|
||||
}, [workspaceFocus.key, activeSnapshot?.threadId, wideLayout]);
|
||||
const learnScreenPane = useCallback(
|
||||
(choice: "opened" | "dismissed") => {
|
||||
@ -2091,6 +2115,7 @@ export function ShellPage() {
|
||||
if (autoPanel === "computer" && panel === null && focus?.pane === "screen" && !focus.takeover) {
|
||||
learnScreenPane("dismissed");
|
||||
}
|
||||
autoLayoutSplitRef.current = false;
|
||||
setAutoPanel(null);
|
||||
}, [panel]);
|
||||
const openArtifactBeside = useCallback((artifact: WorkspaceArtifact) => {
|
||||
@ -3886,6 +3911,7 @@ export function ShellPage() {
|
||||
panel &&
|
||||
(active ||
|
||||
activeGroup ||
|
||||
coordinatorBot ||
|
||||
panel === "create" ||
|
||||
panel === "create-group" ||
|
||||
panel === "browser")
|
||||
@ -3898,6 +3924,7 @@ export function ShellPage() {
|
||||
panel &&
|
||||
(active ||
|
||||
activeGroup ||
|
||||
coordinatorBot ||
|
||||
panel === "create" ||
|
||||
panel === "create-group" ||
|
||||
panel === "browser"),
|
||||
@ -4116,56 +4143,46 @@ export function ShellPage() {
|
||||
layoutMode={showCanvasOnDesktop ? dualSurface.layoutMode : "stream"}
|
||||
orientation={dualSurface.orientation}
|
||||
onSelectMode={handleSelectLayoutMode}
|
||||
onToggleOrientation={dualSurface.toggleOrientation}
|
||||
onToggleOrientation={() => {
|
||||
dualSurface.toggleOrientation();
|
||||
if (!showCanvasOnDesktop) {
|
||||
handleSelectLayoutMode("split");
|
||||
}
|
||||
}}
|
||||
disabled={dualSurface.isMobile}
|
||||
className="hidden md:flex"
|
||||
/>
|
||||
{active || groupComputerBotId ? (
|
||||
{active || activeGroup || inProject || groupComputerBotId ? (
|
||||
<button
|
||||
type="button"
|
||||
title={t`Agent computer`}
|
||||
aria-label={t`Agent computer`}
|
||||
onClick={() => {
|
||||
if (inProject && !active) {
|
||||
if (showCanvasOnDesktop) {
|
||||
setPanel(null);
|
||||
dualSurface.setLayoutMode("stream");
|
||||
} else {
|
||||
dualSurface.setLayoutMode("split");
|
||||
}
|
||||
return;
|
||||
}
|
||||
// The computer belongs to a bot; from a group, open its lead's computer.
|
||||
if (!active && groupComputerBotId) {
|
||||
navigate(`/app/${groupComputerBotId}`);
|
||||
setCanvasTab("browser");
|
||||
setPanel("computer");
|
||||
dualSurface.setLayoutMode("split");
|
||||
return;
|
||||
}
|
||||
const isCurrentlyOpen =
|
||||
(panel === "computer" || panel === "browser") &&
|
||||
dualSurface.layoutMode !== "stream";
|
||||
if (isCurrentlyOpen) {
|
||||
if (isPanelVisible) {
|
||||
setPanel(null);
|
||||
dualSurface.setLayoutMode("stream");
|
||||
} else {
|
||||
if (transcriptRunning) learnScreenPane("opened");
|
||||
setCanvasTab("browser");
|
||||
setPanel("computer");
|
||||
dualSurface.setLayoutMode("split");
|
||||
if (active) {
|
||||
// Refresh run/computer so Take control isn't stuck on a stale busyBotName.
|
||||
void refreshThread(active.id).catch(() => undefined);
|
||||
return;
|
||||
}
|
||||
if (inProject && !active) {
|
||||
if (dualSurface.isMobile) {
|
||||
setCanvasTab("overview");
|
||||
setPanel("computer");
|
||||
}
|
||||
dualSurface.setLayoutMode("split");
|
||||
return;
|
||||
}
|
||||
if (transcriptRunning) learnScreenPane("opened");
|
||||
setCanvasTab(inProject ? "overview" : "browser");
|
||||
setPanel("computer");
|
||||
dualSurface.setLayoutMode("split");
|
||||
if (active) {
|
||||
// Refresh run/computer so Take control isn't stuck on a stale busyBotName.
|
||||
void refreshThread(active.id).catch(() => undefined);
|
||||
} else if (groupComputerBotId) {
|
||||
void refreshComputerScreen(groupComputerBotId).catch(() => undefined);
|
||||
}
|
||||
}}
|
||||
data-active={
|
||||
(panel === "computer" || panel === "browser" || (inProject && !active)) &&
|
||||
showCanvasOnDesktop
|
||||
? ""
|
||||
: undefined
|
||||
}
|
||||
data-active={isPanelVisible ? "" : undefined}
|
||||
className="app-no-drag rk-touch-target grid size-control-sm min-h-control-sm min-w-control-sm place-items-center rounded-lg hover:bg-accent data-active:bg-accent"
|
||||
>
|
||||
<PanelRight strokeWidth={1.7} className="text-foreground/75 size-icon-sm" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user