diff --git a/app/chat/page.tsx b/app/chat/page.tsx index 086f773..ed20c01 100644 --- a/app/chat/page.tsx +++ b/app/chat/page.tsx @@ -24,6 +24,8 @@ import { Phone, Video, MoreVertical, + Paperclip, + Smile, Star, } from "lucide-react"; import { calculateReputation, trackActivity } from "@/lib/reputation"; @@ -60,17 +62,50 @@ export default function ChatPage() { const [selectedChatId, setSelectedChatId] = useState(null); const [query, setQuery] = useState(""); const [inputMessage, setInputMessage] = useState(""); - const [roomMembersOpen, setRoomMembersOpen] = useState(false); const [walletConnected, setWalletConnected] = useState(false); + const [roomMembersOpen, setRoomMembersOpen] = useState(false); const [currentPublicKey, setCurrentPublicKey] = useState(null); const [reputationScore, setReputationScore] = useState(0); + const bottomRef = useRef(null); - const [messagesByChat, setMessagesByChat] = useState>({ + const [chats, setChats] = useState([ + { + id: "1", + name: "Anon Whisper", + address: "GABC...1234", + lastMessage: "Got your message, will reply soon.", + lastSeen: "Today - 14:32", + unreadCount: 2, + status: "online", + }, + { + id: "2", + name: "Room #xf23", + address: "GCDE...5678", + lastMessage: "Pinned the latest proposal for review.", + lastSeen: "Today - 09:10", + unreadCount: 0, + status: "recently_active", + }, + { + id: "3", + name: "Collector", + address: "GHJK...9012", + lastMessage: "Let's sync tomorrow.", + lastSeen: "Yesterday - 18:04", + unreadCount: 0, + status: "offline", + }, + ]); + + const [messagesByChat, setMessagesByChat] = useState< + Record + >({ "1": [ { id: "m1", author: "them", - text: "Hey, welcome to AnonChat 👋", + text: "Hey, welcome to AnonChat!", time: "14:20", delivered: true, read: true, @@ -114,7 +149,7 @@ export default function ChatPage() { { id: "m3", author: "them", - text: "Messages stay end‑to‑end encrypted here.", + text: "Messages stay end-to-end encrypted here.", time: "14:25", delivered: true, read: false, @@ -134,73 +169,57 @@ export default function ChatPage() { { id: "m5", author: "me", - text: "Let’s catch up on the drop.", + text: "Let's catch up on the drop.", time: "17:40", delivered: true, read: true, }, ], - }) + }); - // Update reputation score + // Auto-scroll to latest message useEffect(() => { - const updateScore = () => { - setReputationScore(calculateReputation(currentPublicKey)) - } - updateScore() - window.addEventListener("reputationUpdate", updateScore) - return () => window.removeEventListener("reputationUpdate", updateScore) - }, [currentPublicKey]) + bottomRef.current?.scrollIntoView({ behavior: "smooth" }); + }, [messagesByChat, selectedChatId]); - // Sync wallet state properly + // Sync wallet state useEffect(() => { const checkWallet = async () => { - const address = await getPublicKey() - setWalletConnected(!!address) - setCurrentPublicKey(address ?? null) - } - checkWallet() + const address = await getPublicKey(); + setWalletConnected(!!address); + if (address) setCurrentPublicKey(address); + }; + checkWallet(); const unsubscribe = onDisconnect(() => { - setWalletConnected(false) - setCurrentPublicKey(null) - }) - const interval = setInterval(checkWallet, 1000) - + setWalletConnected(false); + setCurrentPublicKey(null); + }); + const interval = setInterval(checkWallet, 3000); return () => { - unsubscribe() - clearInterval(interval) - } - }, []) + unsubscribe(); + clearInterval(interval); + }; + }, []); - const [chats, setChats] = useState([ - { - id: "1", - name: "Anon Whisper", - address: "GABC ... 1234", - lastMessage: "Got your message, will reply soon.", - lastSeen: "Today • 14:32", - unreadCount: 2, - status: "online", - }, - { - id: "2", - name: "Room #xf23", - address: "GCDE ... 5678", - lastMessage: "Pinned the latest proposal for review.", - lastSeen: "Today • 09:10", - unreadCount: 0, - status: "recently_active", - }, - { - id: "3", - name: "Collector", - address: "GHJK ... 9012", - lastMessage: "Let’s sync tomorrow.", - lastSeen: "Yesterday • 18:04", - unreadCount: 0, - status: "offline", - }, - ]); + // Update reputation score + useEffect(() => { + const updateScore = () => + setReputationScore(calculateReputation(currentPublicKey)); + updateScore(); + window.addEventListener("reputationUpdate", updateScore); + return () => window.removeEventListener("reputationUpdate", updateScore); + }, [currentPublicKey]); + + // Listen for new room creation + useEffect(() => { + const handleRoomCreated = (e: any) => { + const newRoom = e.detail; + setChats((prev) => [newRoom, ...prev]); + setSelectedChatId(newRoom.id); + }; + window.addEventListener("roomCreated", handleRoomCreated); + return () => window.removeEventListener("roomCreated", handleRoomCreated); + }, []); const markRoomRead = async (roomId: string) => { try { @@ -208,11 +227,11 @@ export default function ChatPage() { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ roomId }), - }) + }); } catch (err) { - console.error("Failed to mark room read", err) + console.error("Failed to mark room read", err); } - } + }; const handleSelectChat = async (id: string) => { setSelectedChatId(id) @@ -240,33 +259,41 @@ export default function ChatPage() { id: `m${Date.now()}`, author: "me", text: inputMessage, - time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false }), + time: new Date().toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + hour12: false, + }), delivered: false, read: false, - status: "sent" - } - - setMessagesByChat(prev => ({ + status: "sent", + }; + setMessagesByChat((prev) => ({ ...prev, - [selectedChatId]: [...(prev[selectedChatId] || []), newMessage] - })) - - setChats(prev => prev.map(chat => - chat.id === selectedChatId - ? { ...chat, lastMessage: inputMessage, lastSeen: "Just now", unreadCount: 0 } - : chat - )) - - setInputMessage("") - trackActivity(currentPublicKey, 'message') - } + [selectedChatId]: [...(prev[selectedChatId] || []), newMessage], + })); + setChats((prev) => + prev.map((chat) => + chat.id === selectedChatId + ? { + ...chat, + lastMessage: inputMessage, + lastSeen: "Just now", + unreadCount: 0, + } + : chat, + ), + ); + setInputMessage(""); + trackActivity(currentPublicKey, "message"); + }; const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { - e.preventDefault() - handleSendMessage() + e.preventDefault(); + handleSendMessage(); } - } + }; const getDeliveryStatus = (message: ChatMessage) => { if (message.status) return message.status; @@ -345,7 +372,6 @@ export default function ChatPage() { return (
-
{/* Sidebar */} @@ -366,7 +392,7 @@ export default function ChatPage() { AnonChat
- End‑to‑end encrypted + End-to-end encrypted
@@ -376,7 +402,7 @@ export default function ChatPage() { {walletConnected && ( -
+
@@ -386,21 +412,24 @@ export default function ChatPage() { CONNECTED - {currentPublicKey ? `${currentPublicKey.slice(0, 4)} ... ${currentPublicKey.slice(-4)}` : "None"} + {currentPublicKey + ? `${currentPublicKey.slice(0, 4)}...${currentPublicKey.slice(-4)}` + : "None"}
- {CONFIG.EXPERIMENTAL_REPUTATION_ENABLED && ( -
+
{reputationScore}
)} - - @@ -433,7 +462,7 @@ export default function ChatPage() { ) : (
    {filteredChats.map((chat) => { - const isSelected = chat.id === selectedChatId + const isSelected = chat.id === selectedChatId; return (
+ {chat.unreadCount > 0 && ( + + {chat.unreadCount} + + )} - ) + ); })} )} @@ -500,7 +534,6 @@ export default function ChatPage() {
)} - {/* Conversation view */} {selectedChat && ( <> {/* Header */} @@ -553,7 +586,7 @@ export default function ChatPage() { @@ -619,6 +652,7 @@ export default function ChatPage() {
); })} +
{/* Typing indicator */} @@ -647,8 +681,7 @@ export default function ChatPage() { -