Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 55 additions & 32 deletions src/components/Conversations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import { toConversationItems } from '@/utils/conversation';
import { demoConversations, type DemoConversation } from '@/democonversations';
import { useSearchParams, useNavigate } from 'react-router-dom';
import { Memo, use$, useObservable, useObserveEffect } from '@legendapp/state/react';
import { initializeConversations, selectedConversation$ } from '@/stores/conversations';
import {
initializeConversations,
selectedConversation$,
initConversation,
} from '@/stores/conversations';

interface Props {
className?: string;
Expand All @@ -27,15 +31,26 @@ const Conversations: FC<Props> = ({ route }) => {
const { api, isConnected$, connectionConfig } = useApi();
const queryClient = useQueryClient();
const isConnected = use$(isConnected$);

// Update selected conversation when URL param changes
const conversation$ = useObservable<ConversationItem | undefined>(undefined);
// Track demo initialization
// Initialize demo conversations and handle selection on mount
useEffect(() => {
// Initialize demos in store
demoConversations.forEach((conv) => {
initConversation(conv.name, {
log: conv.messages,
logfile: conv.name,
branches: {},
});
});

// Handle initial conversation selection
if (conversationParam) {
selectedConversation$.set(conversationParam);
}
}, [conversationParam]);

// Fetch conversations from API with proper caching
// Fetch conversations from API
const {
data: apiConversations = [],
isError,
Expand All @@ -45,11 +60,6 @@ const Conversations: FC<Props> = ({ route }) => {
} = useQuery({
queryKey: ['conversations', connectionConfig.baseUrl, isConnected],
queryFn: async () => {
console.log('Fetching conversations, connection state:', isConnected);
if (!isConnected) {
console.warn('Attempting to fetch conversations while disconnected');
return [];
}
try {
const conversations = await api.getConversations();
console.log('Fetched conversations:', conversations);
Expand All @@ -60,7 +70,7 @@ const Conversations: FC<Props> = ({ route }) => {
}
},
enabled: isConnected,
staleTime: 0, // Always refetch when query is invalidated
staleTime: 0,
gcTime: 5 * 60 * 1000,
refetchOnWindowFocus: false,
});
Expand All @@ -70,30 +80,44 @@ const Conversations: FC<Props> = ({ route }) => {
console.error('Conversation query error:', error);
}

// Combine demo and API conversations and initialize store
const allConversations: ConversationItem[] = useMemo(() => {
// Initialize API conversations in store
if (apiConversations.length) {
console.log('[Conversations] Initializing conversations in store');
// Prepare demo conversation items
const demoItems = useMemo(
() =>
demoConversations.map((conv: DemoConversation) => ({
name: conv.name,
lastUpdated: conv.lastUpdated,
messageCount: conv.messages.length,
readonly: true,
})),
[]
);

// Handle API conversations separately
const apiItems = useMemo(() => {
if (!isConnected) return [];
return toConversationItems(apiConversations);
}, [isConnected, apiConversations]);

// Initialize API conversations in store when available
useEffect(() => {
if (isConnected && apiConversations.length) {
console.log('[Conversations] Initializing API conversations');
void initializeConversations(
api,
apiConversations.map((c) => c.name),
10
);
}
}, [isConnected, apiConversations, api]);

return [
// Convert demo conversations to ConversationItems
...demoConversations.map((conv: DemoConversation) => ({
name: conv.name,
lastUpdated: conv.lastUpdated,
messageCount: conv.messages.length,
readonly: true,
})),
// Convert API conversations to ConversationItems
...toConversationItems(apiConversations),
];
}, [apiConversations, api]);
// Combine demo and API conversations
const allConversations = useMemo(() => {
console.log('[Conversations] Combining conversations', {
demoCount: demoItems.length,
apiCount: apiItems.length,
});
return [...demoItems, ...apiItems];
}, [demoItems, apiItems]);

const handleSelectConversation = useCallback(
(id: string) => {
Expand All @@ -112,16 +136,15 @@ const Conversations: FC<Props> = ({ route }) => {
[queryClient, navigate, route]
);

const conversation$ = useObservable<ConversationItem | undefined>(undefined);

// Update conversation$ when selectedConversation$ changes
// Update conversation$ when selected conversation changes
useObserveEffect(selectedConversation$, ({ value: selectedConversation }) => {
conversation$.set(allConversations.find((conv) => conv.name === selectedConversation));
});

// Update conversation$ when allConversations changes
// Update conversation$ when available conversations change
useEffect(() => {
conversation$.set(allConversations.find((conv) => conv.name === selectedConversation$.get()));
const selected = selectedConversation$.get();
conversation$.set(allConversations.find((conv) => conv.name === selected));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [allConversations]);

Expand Down
2 changes: 1 addition & 1 deletion src/stores/conversations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export function updateConversationData(id: string, data: ConversationResponse) {
conversations$.get(id)?.data.set(data);
}

// Bulk initialize conversations with their data
// Initialize conversations with their data
export async function initializeConversations(
api: { getConversation: (id: string) => Promise<ConversationResponse> },
conversationIds: string[],
Expand Down
Loading