import * as Popover from '@radix-ui/react-popover' import { Pencil, Trash2 } from 'lucide-react' import { useCallback, useEffect, useRef, useState } from 'react' import { ChatConversationMeta } from '../../types/chat' function TitleInput({ title, onSubmit, }: { title: string onSubmit: (title: string) => Promise }) { const [value, setValue] = useState(title) const inputRef = useRef(null) useEffect(() => { if (inputRef.current) { inputRef.current.select() inputRef.current.scrollLeft = 0 } }, []) return ( e.stopPropagation()} onChange={(e) => setValue(e.target.value)} onKeyDown={(e) => { e.stopPropagation() if (e.key === 'Enter') { onSubmit(value) } }} autoFocus maxLength={100} /> ) } function ChatListItem({ title, isFocused, isEditing, onMouseEnter, onSelect, onDelete, onStartEdit, onFinishEdit, }: { title: string isFocused: boolean isEditing: boolean onMouseEnter: () => void onSelect: () => Promise onDelete: () => Promise onStartEdit: () => void onFinishEdit: (title: string) => Promise }) { const itemRef = useRef(null) useEffect(() => { if (isFocused && itemRef.current) { itemRef.current.scrollIntoView({ block: 'nearest', }) } }, [isFocused]) return (
  • {isEditing ? ( ) : (
    {title}
    )}
    { e.stopPropagation() onStartEdit() }} className="infio-chat-list-dropdown-item-icon" >
    { e.stopPropagation() await onDelete() }} className="infio-chat-list-dropdown-item-icon" >
  • ) } export function ChatHistory({ chatList, currentConversationId, onSelect, onDelete, onUpdateTitle, className, children, }: { chatList: ChatConversationMeta[] currentConversationId: string onSelect: (conversationId: string) => Promise onDelete: (conversationId: string) => Promise onUpdateTitle: (conversationId: string, newTitle: string) => Promise className?: string children: React.ReactNode }) { const [open, setOpen] = useState(false) const [focusedIndex, setFocusedIndex] = useState(0) const [editingId, setEditingId] = useState(null) useEffect(() => { if (open) { const currentIndex = chatList.findIndex( (chat) => chat.id === currentConversationId, ) setFocusedIndex(currentIndex === -1 ? 0 : currentIndex) setEditingId(null) } }, [open]) const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === 'ArrowUp') { setFocusedIndex(Math.max(0, focusedIndex - 1)) } else if (e.key === 'ArrowDown') { setFocusedIndex(Math.min(chatList.length - 1, focusedIndex + 1)) } else if (e.key === 'Enter') { onSelect(chatList[focusedIndex].id) setOpen(false) } }, [chatList, focusedIndex, setFocusedIndex, onSelect], ) return (
      {chatList.length === 0 ? (
    • No conversations
    • ) : ( chatList.map((chat, index) => ( { setFocusedIndex(index) }} onSelect={async () => { await onSelect(chat.id) setOpen(false) }} onDelete={async () => { await onDelete(chat.id) }} onStartEdit={() => { setEditingId(chat.id) }} onFinishEdit={async (title) => { await onUpdateTitle(chat.id, title) setEditingId(null) }} /> )) )}
    ) }