diff --git a/desktop/src/features/channels/ui/ChannelComposerActivityAccessory.tsx b/desktop/src/features/channels/ui/ChannelComposerActivityAccessory.tsx deleted file mode 100644 index f99888f01..000000000 --- a/desktop/src/features/channels/ui/ChannelComposerActivityAccessory.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import type { ComponentProps } from "react"; - -import { CardMintComposerChip } from "@/features/agents/ui/CardMintComposerChip"; -import { useCardMintJobs } from "@/features/agents/cardMintStore"; -import { BotActivityComposerAction } from "@/features/channels/ui/BotActivityBar"; -import { ComposerActivityAccessory } from "@/features/messages/ui/ComposerActivityAccessory"; -import { TypingIndicatorRow } from "@/features/messages/ui/TypingIndicatorRow"; - -type ChannelComposerActivityAccessoryProps = { - agents: ComponentProps["agents"]; - channel: ComponentProps["channel"]; - currentPubkey: ComponentProps["currentPubkey"]; - onOpenAgentSession: ComponentProps< - typeof BotActivityComposerAction - >["onOpenAgentSession"]; - openAgentSessionPubkey: ComponentProps< - typeof BotActivityComposerAction - >["openAgentSessionPubkey"]; - profiles: ComponentProps["profiles"]; - typingPubkeys: string[]; - visible: boolean; - workingBotPubkeys: string[]; -}; - -export function ChannelComposerActivityAccessory({ - agents, - channel, - currentPubkey, - onOpenAgentSession, - openAgentSessionPubkey, - profiles, - typingPubkeys, - visible, - workingBotPubkeys, -}: ChannelComposerActivityAccessoryProps) { - const cardMintJobs = useCardMintJobs(); - return ( - -
- {cardMintJobs.length > 0 ? : null} - {workingBotPubkeys.length > 0 ? ( -
- -
- ) : null} - {typingPubkeys.length > 0 ? ( - - ) : null} -
-
- ); -} diff --git a/desktop/src/features/channels/ui/ChannelPane.tsx b/desktop/src/features/channels/ui/ChannelPane.tsx index dc17a2b03..fc013722b 100644 --- a/desktop/src/features/channels/ui/ChannelPane.tsx +++ b/desktop/src/features/channels/ui/ChannelPane.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import { Hash, LogIn } from "lucide-react"; import { AnimatePresence } from "motion/react"; import { useAppNavigation } from "@/app/navigation/useAppNavigation"; +import { useChannelWorkingAgentPubkeys } from "@/features/agents/agentWorkingSignal"; import { useMediaUpload } from "@/features/messages/lib/useMediaUpload"; import { ComposerDockBackdrop } from "@/features/messages/ui/ComposerDockBackdrop"; import { ComposerUploadProgressOverlay } from "@/features/messages/ui/ComposerUploadProgressOverlay"; @@ -399,18 +400,18 @@ export const ChannelPane = React.memo(function ChannelPane({ !isComposerDisabled && !isMainDeferredEditPending && !isSinglePanelView; - const hasTypingActivity = typingPubkeys.length > 0; - // Unified working set for the composer bar: observer-derived turns primary, - // bot typing fallback (both folded together by agentWorkingSignal). This is - // what makes the bar show for an agent whose observer stream is live but - // whose typing signal never arrives — and vice versa. + // Working set for the composer bar (observer turns + bot-typing fallback, + // folded by agentWorkingSignal); gates the dock's reserved bottom rail. const composerWorkingBotPubkeys = useChannelWorkingAgentPubkeys( activeChannel?.id ?? null, ); - const hasComposerBotActivity = composerWorkingBotPubkeys.length > 0; + // Background card mints surface in the same rail ("Minting card…" chip), + // so they must also reserve the activity row. const hasCardMintActivity = useCardMintJobs().length > 0; const hasComposerBottomActivity = - hasComposerBotActivity || hasTypingActivity || hasCardMintActivity; + composerWorkingBotPubkeys.length > 0 || + typingPubkeys.length > 0 || + hasCardMintActivity; const threadComposerBotTypingPubkeys = React.useMemo(() => { if (!openThreadHeadId) return []; return botTypingEntries @@ -795,10 +796,9 @@ export const ChannelPane = React.memo(function ChannelPane({ } showTopBorder={false} /> - {/* The activity accessory is anchored in the dock's reserved - bottom rail, so fading it cannot change the observed - overlay height or move the conversation. Its natural - content height remains responsive. */} + {/* The accessory is anchored in the dock's reserved bottom + rail, so fading it cannot change the observed overlay + height or move the conversation. */} 0 + hasThreadComposerBotActivity || threadTypingPubkeys.length > 0 } activityAccessoryContent={ hasThreadComposerBotActivity ||