'use client' import { BackButton } from '@/app/components/BackButton' import { DiscordButton } from '@/app/components/DiscordButton' import { GetIconForUser } from '@/util/bd' import { getCookie } from '@/util/cookie' import axios from 'axios' import { useEffect, useRef, useState } from 'react' interface WSMessage { success: boolean message: string | null for: string data: any } type BirdColor = [number, number, number] interface Message { username: string userId: number content: string id: number icon: number overlay: number birdColor: BirdColor overlayColor: BirdColor customIcon: string | null } interface CustomIconEntry { data: string id: string } export default function BerryDashChatroom () { const [connected, setConnected] = useState(false) const [loggedIn, setLoggedIn] = useState(false) const [token, setToken] = useState(null) const [messages, setMessages] = useState([]) const [customIconCache, setCustomIconCache] = useState([]) const [ws, setWs] = useState(null) const messagesDiv = useRef(null) const [input, setInput] = useState('') useEffect(() => { document.title = 'Lncvrt Games - Chatroom' const token = getCookie('accountToken', '-1') if (token !== '-1') { setLoggedIn(true) setToken(token) } const socket = new WebSocket('/api/ws') socket.onopen = () => { setConnected(true) socket.send( JSON.stringify({ type: 'info_request', kind: 'chatroom_messages', timestamp: Date.now() }) ) } socket.onmessage = event => { const message = JSON.parse(event.data) as WSMessage if (message.for == 'info_request:chatroom_messages') { const messages = message.data as Message[] setMessages(messages) } else if (message.for == 'upload:chatroom_message') { const msg = message.data as Message setMessages(prev => [...prev.slice(1), msg]) } else if (message.for == 'delete:chatroom_message') { const msg = message.data.fillerMessage as Message setMessages(prev => [msg, ...prev.slice(0, -1)]) } else if (message.for == 'edit:chatroom_message') { setMessages(prev => prev.map(msg => msg.id === message.data.id ? { ...msg, content: btoa(message.data.newContent) } : msg ) ) } } socket.onclose = () => { setConnected(false) setMessages([]) } setWs(socket) return () => { socket.close() } }, []) useEffect(() => { if (messagesDiv.current) { messagesDiv.current.scrollTop = messagesDiv.current.scrollHeight } const all = customIconCache.map(icon => icon.id) const allFromMessages = Array.from( new Set( messages .filter(icon => icon.customIcon != null) .map(icon => icon.customIcon as string) ) ) const notInAllIds = allFromMessages .filter(id => !all.includes(id)) .map(id => `"${id}"`) .join(',') if (notInAllIds.length != 0) { ;(async () => { const result = await axios.get( `/api/berrydash/icon-marketplace/icon?ids=[${notInAllIds}]` ) if (result.data.success) { const add: CustomIconEntry[] = [] for (const item of result.data.data) { add.push({ data: item.data, id: item.id }) } setCustomIconCache(prev => [ ...prev, ...result.data.data.map((item: CustomIconEntry) => ({ data: item.data, id: item.id })) ]) } })() } }, [messages]) return (

Berry Dash Chatroom

{connected && ( <>
{messages.map(item => { return (
i.id === item.customIcon) ? 'data:image/png;base64,' + customIconCache.find(i => i.id === item.customIcon) ?.data : 'https://games-r2.lncvrt.xyz/game-assets/berrydash/other/loading.png' } className='pointer-events-none' width={48} height={48} >

{item.username}

{atob(item.content)}

) })}
{loggedIn ? (
{ e.preventDefault() setInput('') ws?.send( JSON.stringify({ type: 'upload', kind: 'chatroom_message', data: { content: input, auth: token }, timestamp: Date.now() }) ) }} className='flex flex-row gap-2 -mb-4 mt-6' > setInput(e.target.value)} >
) : (

You must be logged in to send messages

)} )} {!connected && (

Not connected to the chatroom

)}
) }