From b0d2b640944b709be8ecd23d4badf159450472c3 Mon Sep 17 00:00:00 2001 From: Taylor Ho Date: Tue, 4 Aug 2026 16:35:39 -0700 Subject: [PATCH] fix(composer): restore card mint status in activity rail Render the existing card-mint status chip inside the unified composer activity row so minting, ready, and failure states remain visible alongside live agent pills and typing. Co-authored-by: Taylor Ho Signed-off-by: Taylor Ho --- .../channels/ui/ChannelComposerActivityRow.tsx | 4 +++- desktop/src/features/channels/ui/ChannelPane.tsx | 16 ---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/desktop/src/features/channels/ui/ChannelComposerActivityRow.tsx b/desktop/src/features/channels/ui/ChannelComposerActivityRow.tsx index a62afea38..29b0f0587 100644 --- a/desktop/src/features/channels/ui/ChannelComposerActivityRow.tsx +++ b/desktop/src/features/channels/ui/ChannelComposerActivityRow.tsx @@ -9,6 +9,7 @@ import { getAgentTranscript, subscribeAgentObserverStore, } from "@/features/agents/observerRelayStore"; +import { CardMintComposerChip } from "@/features/agents/ui/CardMintComposerChip"; import { BotActivityComposerAction, type BotActivityAgent, @@ -136,7 +137,8 @@ export function ChannelComposerActivityRow({ className="h-8.5 overflow-visible bg-background px-5 pb-1.5 pt-0" data-testid="channel-composer-activity-row" > -
+
+ {/* One strip hosts both groups: working pills plus the typing group as the strip's trailing slot sibling, so they share the scroller, edge fades, and layout/enter/exit animations. When the row gets diff --git a/desktop/src/features/channels/ui/ChannelPane.tsx b/desktop/src/features/channels/ui/ChannelPane.tsx index fc013722b..c7a3f84e9 100644 --- a/desktop/src/features/channels/ui/ChannelPane.tsx +++ b/desktop/src/features/channels/ui/ChannelPane.tsx @@ -37,7 +37,6 @@ import { getThreadPanelLayout } from "@/features/channels/lib/threadPanelLayout" import { useThreadViewMode } from "@/features/channels/lib/threadViewModePreference"; import { useThreadViewModeSwitch } from "@/features/channels/ui/useThreadViewModeSwitch"; import { useFocusDrawerPresence } from "@/features/channels/ui/useFocusDrawerPresence"; -import { useChannelWorkingAgentPubkeys } from "@/features/agents/agentWorkingSignal"; import { useCardMintJobs } from "@/features/agents/cardMintStore"; import { BotActivityComposerAction } from "@/features/channels/ui/BotActivityBar"; import { ChannelComposerActivityRow } from "@/features/channels/ui/ChannelComposerActivityRow"; @@ -287,7 +286,6 @@ export const ChannelPane = React.memo(function ChannelPane({ onEdit(target); return true; }, [findLastOwnEditable, messages, onEdit]); - const handleEditLastOwnThreadMessage = React.useCallback((): boolean => { if (!onEdit) return false; const scope: TimelineMessage[] = []; @@ -298,9 +296,7 @@ export const ChannelPane = React.memo(function ChannelPane({ onEdit(target); return true; }, [findLastOwnEditable, onEdit, threadHeadMessage, threadMessages]); - const timeoutState = useTimeoutState(); - // A moderation DM (1:1 with the relay identity) is read-only for the member; // only DMs pay for the NIP-11 `self` lookup. Fails open: no `relaySelf` → // ordinary DM, composer enabled. @@ -310,7 +306,6 @@ export const ChannelPane = React.memo(function ChannelPane({ currentPubkey, relaySelfQuery.data, ); - const isComposerDisabled = !activeChannel?.isMember || activeChannel.archivedAt !== null || @@ -320,7 +315,6 @@ export const ChannelPane = React.memo(function ChannelPane({ isSending; const knownAgentPubkeys = React.useMemo(() => { const pubkeys = new Set(); - for (const pubkey of agentPubkeys ?? []) { pubkeys.add(pubkey.toLowerCase()); } @@ -330,14 +324,12 @@ export const ChannelPane = React.memo(function ChannelPane({ for (const agent of activityAgents) { pubkeys.add(agent.pubkey.toLowerCase()); } - return pubkeys; }, [activityAgents, agentPubkeys, agentSessionAgents]); const completeWelcomeComposerBanner = React.useCallback(() => { if (!activeChannelId || !isActiveWelcomeChannel) { return; } - clearWelcomeComposerDismissTimer(); completedWelcomeBannerChannelIdsRef.current.add(activeChannelId); setWelcomeComposerBannerState("complete"); @@ -369,10 +361,8 @@ export const ChannelPane = React.memo(function ChannelPane({ isActiveWelcomeChannel && (containsWelcomePersonaMention(content) || mentionsKnownAgent(mentionPubkeys, knownAgentPubkeys)); - messageTimelineRef.current?.scrollToBottomOnNextUpdate(); await onSendMessage(content, mentionPubkeys, mediaTags, channelId); - if ( channelId && channelId !== activeChannelId && @@ -381,7 +371,6 @@ export const ChannelPane = React.memo(function ChannelPane({ ) { await goChannel(channelId, { replace: true }); } - if (shouldCompleteWelcomeBanner) { completeWelcomeComposerBanner(); } @@ -435,7 +424,6 @@ export const ChannelPane = React.memo(function ChannelPane({ }), [activeChannel, currentPubkey, profiles], ); - const handleWelcomeAddAgent = React.useCallback(() => { onAddAgent?.({ beforeSend: () => @@ -477,7 +465,6 @@ export const ChannelPane = React.memo(function ChannelPane({ for (const message of threadAllMessages) { messagesById.set(message.id, message); } - return buildVideoReviewContextsByMessageId({ channelId: activeChannel?.id ?? null, channelName: activeChannel?.name, @@ -498,7 +485,6 @@ export const ChannelPane = React.memo(function ChannelPane({ threadAllMessages, threadHeadMessage, ]); - const isOverlay = useIsThreadPanelOverlay(); const useSplitAuxiliaryPane = !isSinglePanelView && !isOverlay; const threadViewMode = useThreadViewMode(); @@ -591,7 +577,6 @@ export const ChannelPane = React.memo(function ChannelPane({ data-testid="channel-shared-header-backdrop" /> ) : null} - {!isSinglePanelView ? (
) : null} - {/* * `AnimatePresence` keeps the focus thread drawer mounted through its exit * animation — without it the drawer's own existence condition