import { useCallback, useEffect, useRef, useState } from "react"; import type { Channel } from "@/types/Channel"; import type { Message } from "@/types/Message"; import { getChannels, getMessages } from "@/api"; import { ChannelSidebar } from "@/components/ChannelSidebar"; import { MessageItem } from "@/components/MessageItem"; import { ComposeBox } from "@/components/ComposeBox"; import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; import { Button } from "@/components/ui/button"; export default function App() { const [channels, setChannels] = useState([]); const [activeChannelId, setActiveChannelId] = useState(null); const [messages, setMessages] = useState([]); const [replyTo, setReplyTo] = useState(null); const [sheetOpen, setSheetOpen] = useState(false); const scrollRef = useRef(null); const prevMsgCountRef = useRef(0); const activeChannelRef = useRef(activeChannelId); activeChannelRef.current = activeChannelId; const loadChannels = useCallback(async () => { const chs = await getChannels(); setChannels(chs); setActiveChannelId((prev) => (prev ? prev : chs[0]?.id ?? null)); }, []); const loadMessages = useCallback(async () => { const channelId = activeChannelRef.current; if (!channelId) return; try { const msgs = await getMessages(channelId); if (activeChannelRef.current === channelId) { setMessages(msgs); } } catch { // Silently ignore fetch errors during polling } }, []); useEffect(() => { loadChannels(); }, [loadChannels]); useEffect(() => { setMessages([]); setReplyTo(null); prevMsgCountRef.current = 0; loadMessages(); }, [activeChannelId, loadMessages]); useEffect(() => { if (messages.length > prevMsgCountRef.current && scrollRef.current) { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } prevMsgCountRef.current = messages.length; }, [messages]); useEffect(() => { const interval = setInterval(loadMessages, 3000); return () => clearInterval(interval); }, [loadMessages]); const messagesById = new Map(messages.map((m) => [m.id, m])); const activeChannel = channels.find((c) => c.id === activeChannelId); const sidebar = ( { setActiveChannelId(id); setSheetOpen(false); }} onChannelCreated={loadChannels} /> ); return (
{/* Desktop sidebar */}
{sidebar}
{/* Channel header */}
{/* Mobile: Sheet trigger */} {sidebar} {activeChannel ? ( <> # {activeChannel.name} {activeChannel.description && ( {activeChannel.description} )} {messages.length} msg ) : ( select a channel )}
{/* Messages */}
{messages.length === 0 && activeChannelId && (
no messages yet
)} {messages.map((msg) => ( ))}
{activeChannelId && ( setReplyTo(null)} onMessageSent={loadMessages} /> )}
); }