Simplify chat session state hook and disable send button when blocked

This commit is contained in:
CREDO23 2026-01-20 19:48:28 +02:00
parent 22ead877fa
commit 17f8c993df
2 changed files with 22 additions and 13 deletions

View file

@ -226,7 +226,7 @@ const Composer: FC = () => {
const isThreadEmpty = useAssistantState(({ thread }) => thread.isEmpty); const isThreadEmpty = useAssistantState(({ thread }) => thread.isEmpty);
const isThreadRunning = useAssistantState(({ thread }) => thread.isRunning); const isThreadRunning = useAssistantState(({ thread }) => thread.isRunning);
// Live collaboration: track AI responding state // Live collaboration state
const { data: currentUser } = useAtomValue(currentUserAtom); const { data: currentUser } = useAtomValue(currentUserAtom);
const { data: members } = useAtomValue(membersAtom); const { data: members } = useAtomValue(membersAtom);
const threadId = useMemo(() => { const threadId = useMemo(() => {
@ -439,13 +439,17 @@ const Composer: FC = () => {
/>, />,
document.body document.body
)} )}
<ComposerAction /> <ComposerAction isBlockedByOtherUser={isBlockedByOtherUser} />
</ComposerPrimitive.AttachmentDropzone> </ComposerPrimitive.AttachmentDropzone>
</ComposerPrimitive.Root> </ComposerPrimitive.Root>
); );
}; };
const ComposerAction: FC = () => { interface ComposerActionProps {
isBlockedByOtherUser?: boolean;
}
const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false }) => {
// Check if any attachments are still being processed (running AND progress < 100) // Check if any attachments are still being processed (running AND progress < 100)
// When progress is 100, processing is done but waiting for send() // When progress is 100, processing is done but waiting for send()
const hasProcessingAttachments = useAssistantState(({ composer }) => const hasProcessingAttachments = useAssistantState(({ composer }) =>
@ -480,7 +484,8 @@ const ComposerAction: FC = () => {
return userConfigs?.some((c) => c.id === agentLlmId) ?? false; return userConfigs?.some((c) => c.id === agentLlmId) ?? false;
}, [preferences, globalConfigs, userConfigs]); }, [preferences, globalConfigs, userConfigs]);
const isSendDisabled = hasProcessingAttachments || isComposerEmpty || !hasModelConfigured; const isSendDisabled =
hasProcessingAttachments || isComposerEmpty || !hasModelConfigured || isBlockedByOtherUser;
return ( return (
<div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between"> <div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between">
@ -509,13 +514,15 @@ const ComposerAction: FC = () => {
<ComposerPrimitive.Send asChild disabled={isSendDisabled}> <ComposerPrimitive.Send asChild disabled={isSendDisabled}>
<TooltipIconButton <TooltipIconButton
tooltip={ tooltip={
!hasModelConfigured isBlockedByOtherUser
? "Please select a model from the header to start chatting" ? "Wait for AI to finish responding"
: hasProcessingAttachments : !hasModelConfigured
? "Wait for attachments to process" ? "Please select a model from the header to start chatting"
: isComposerEmpty : hasProcessingAttachments
? "Enter a message to send" ? "Wait for attachments to process"
: "Send message" : isComposerEmpty
? "Enter a message to send"
: "Send message"
} }
side="bottom" side="bottom"
type="submit" type="submit"

View file

@ -5,6 +5,10 @@ import type { ChatSessionState } from "@/contracts/types/chat-session-state.type
const ELECTRIC_URL = process.env.NEXT_PUBLIC_ELECTRIC_URL || "http://localhost:5133"; const ELECTRIC_URL = process.env.NEXT_PUBLIC_ELECTRIC_URL || "http://localhost:5133";
/**
* Hook to get live chat session state for collaboration.
* Tracks which user the AI is currently responding to.
*/
export function useChatSessionState(threadId: number | null) { export function useChatSessionState(threadId: number | null) {
const { data, isLoading, isError, error } = useShape<ChatSessionState>({ const { data, isLoading, isError, error } = useShape<ChatSessionState>({
url: `${ELECTRIC_URL}/v1/shape`, url: `${ELECTRIC_URL}/v1/shape`,
@ -12,8 +16,6 @@ export function useChatSessionState(threadId: number | null) {
table: "chat_session_state", table: "chat_session_state",
where: `thread_id = ${threadId}`, where: `thread_id = ${threadId}`,
}, },
// Skip fetching if no threadId
...(threadId ? {} : { url: undefined as unknown as string }),
}); });
const sessionState = data?.[0] ?? null; const sessionState = data?.[0] ?? null;