copilot-swe-agent[bot]
Implement name handling and YouTube search close button
5877a31
"use client"
import { FC, useEffect, useState } from "react"
import Player from "./player/Player"
import {
ClientToServerEvents,
createClientSocket,
ServerToClientEvents,
} from "../lib/socket"
import Button from "./action/Button"
import { Socket } from "socket.io-client"
import ConnectingAlert from "./alert/ConnectingAlert"
import PlaylistMenu from "./playlist/PlaylistMenu"
import IconLoop from "./icon/IconLoop"
import InputUrl from "./input/InputUrl"
import UserList from "./user/UserList"
import ChatPanel from "./chat/ChatPanel"
import YoutubeSearch from "./search/YoutubeSearch"
import NameModal from "./modal/NameModal"
interface Props {
id: string
}
let connecting = false
const Room: FC<Props> = ({ id }) => {
const [connected, setConnected] = useState(false)
const [socket, setSocket] = useState<Socket<
ServerToClientEvents,
ClientToServerEvents
> | null>(null)
const [url, setUrl] = useState("")
const [showNameModal, setShowNameModal] = useState(false)
useEffect(() => {
fetch("/api/socketio").finally(() => {
if (socket !== null) {
setConnected(socket.connected)
} else {
// Get user name from localStorage
const userName = typeof window !== "undefined"
? localStorage.getItem("userName") || undefined
: undefined
// Show modal if no userName
if (!userName || !userName.trim()) {
setShowNameModal(true)
return
}
// Get room metadata from sessionStorage (set during creation)
const roomKey = `room_${id}_meta`
const roomMeta = typeof window !== "undefined" && sessionStorage.getItem(roomKey)
? JSON.parse(sessionStorage.getItem(roomKey) || "{}")
: {}
const isPublic = roomMeta.isPublic
const newSocket = createClientSocket(id, userName, isPublic)
newSocket.on("connect", () => {
setConnected(true)
})
setSocket(newSocket)
}
})
return () => {
if (socket !== null) {
socket.disconnect()
}
}
}, [id, socket])
const connectionCheck = () => {
if (socket !== null && socket.connected) {
connecting = false
setConnected(true)
return
}
setTimeout(connectionCheck, 100)
}
const handleNameSubmit = (name: string) => {
// Save to localStorage
if (typeof window !== "undefined") {
localStorage.setItem("userName", name)
}
setShowNameModal(false)
// Get room metadata from sessionStorage (set during creation)
const roomKey = `room_${id}_meta`
const roomMeta = typeof window !== "undefined" && sessionStorage.getItem(roomKey)
? JSON.parse(sessionStorage.getItem(roomKey) || "{}")
: {}
const isPublic = roomMeta.isPublic
// Create socket connection with the name
const newSocket = createClientSocket(id, name, isPublic)
newSocket.on("connect", () => {
setConnected(true)
})
setSocket(newSocket)
}
if (showNameModal) {
return <NameModal show={true} onSubmit={handleNameSubmit} />
}
if (!connected || socket === null) {
if (!connecting) {
connecting = true
connectionCheck()
}
return (
<div className={"flex justify-center"}>
<ConnectingAlert />
</div>
)
}
return (
<div className={"flex flex-col sm:flex-row gap-2"}>
<div className={"grow"}>
<Player roomId={id} socket={socket} />
<div className={"flex flex-row gap-2 p-2 bg-dark-900/50 rounded-lg border border-dark-700/50 mt-2"}>
<Button
tooltip={"Do a forced manual sync"}
className={"px-3 py-2 flex flex-row gap-2 items-center"}
actionClasses={"bg-dark-800 hover:bg-dark-700 active:bg-dark-600 border border-dark-700/50"}
onClick={() => {
console.log("Fetching update", socket?.id)
socket?.emit("fetch")
}}
>
<IconLoop className={"hover:animate-spin"} />
<div className={"hidden-below-sm"}>Manual sync</div>
</Button>
<InputUrl
className={"grow"}
url={url}
placeholder={"Play url now"}
tooltip={"Play given url now"}
onChange={setUrl}
onSubmit={() => {
console.log("Requesting", url, "now")
socket?.emit("playUrl", url)
setUrl("")
}}
>
Play
</InputUrl>
</div>
{/* Chat + YouTube Search */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 p-2 mt-2">
<ChatPanel socket={socket} />
<YoutubeSearch socket={socket} />
</div>
<UserList socket={socket} />
</div>
<PlaylistMenu socket={socket} />
</div>
)
}
export default Room