- Finding 1: add AppState::authed_get/authed_post helpers that attach Bearer token when present; all 4 commands now use them - Finding 2: MessageInput accepts onSent callback, calls it after successful send; ChatPage passes refreshKey bump as onSent - Finding 3: MessageList useEffect uses cancellation flag so stale in-flight responses cannot overwrite a newly selected conversation - Finding 4: scrollIntoView moved to separate effect keyed on messages.length so scroll only fires when new messages arrive
37 lines
1.2 KiB
TypeScript
37 lines
1.2 KiB
TypeScript
import { useState } from "react";
|
|
import { useParams } from "react-router-dom";
|
|
import ConversationList from "../components/ConversationList";
|
|
import MessageList from "../components/MessageList";
|
|
import MessageInput from "../components/MessageInput";
|
|
|
|
export default function ChatPage() {
|
|
const { workspaceId } = useParams<{ workspaceId: string }>();
|
|
const [conversationId, setConversationId] = useState<string | null>(null);
|
|
const [refreshKey, setRefreshKey] = useState(0);
|
|
|
|
return (
|
|
<div style={{ display: "flex", height: "100vh" }}>
|
|
<ConversationList
|
|
workspaceId={workspaceId!}
|
|
onSelect={setConversationId}
|
|
selectedId={conversationId}
|
|
/>
|
|
<div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
|
|
{conversationId ? (
|
|
<>
|
|
<MessageList conversationId={conversationId} refreshKey={refreshKey} />
|
|
<MessageInput
|
|
conversationId={conversationId}
|
|
onSent={() => setRefreshKey((k) => k + 1)}
|
|
/>
|
|
</>
|
|
) : (
|
|
<div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", color: "#888" }}>
|
|
Select a conversation
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|