diff --git a/client/src/MediaControl.tsx b/client/src/MediaControl.tsx index f646318..ea241a9 100644 --- a/client/src/MediaControl.tsx +++ b/client/src/MediaControl.tsx @@ -1340,6 +1340,18 @@ const MediaControl: React.FC = ({ isSelf, peer, className }) const spacerRef = useRef(null); const moveableRef = useRef(null); const [isDragging, setIsDragging] = useState(false); + // Reset drag state on pointerup/touchend/mouseup anywhere in the document + useEffect(() => { + const resetDrag = () => setIsDragging(false); + document.addEventListener("pointerup", resetDrag); + document.addEventListener("touchend", resetDrag); + document.addEventListener("mouseup", resetDrag); + return () => { + document.removeEventListener("pointerup", resetDrag); + document.removeEventListener("touchend", resetDrag); + document.removeEventListener("mouseup", resetDrag); + }; + }, []); useEffect(() => { console.log( @@ -1600,15 +1612,15 @@ const MediaControl: React.FC = ({ isSelf, peer, className }) > {isSelf ? ( - + {muted ? : } ) : ( - + {muted ? : } )} - + {videoOn ? : } @@ -1651,6 +1663,15 @@ const MediaControl: React.FC = ({ isSelf, peer, className }) origin={false} edge onDragStart={(e) => { + // Only block drag if the event is a pointerdown/touchstart on a button, but do not interfere with click/touch events + const controls = containerRef.current?.querySelector('.Controls'); + const target = e.inputEvent?.target as HTMLElement; + if (controls && target && (target.closest('button') || target.closest('.MuiIconButton-root'))) { + if (typeof e.stopDrag === 'function') { + e.stopDrag(); + } + return; + } setIsDragging(true); }} onDrag={(e) => { diff --git a/client/src/UserList.tsx b/client/src/UserList.tsx index dec77a3..28a8bd5 100644 --- a/client/src/UserList.tsx +++ b/client/src/UserList.tsx @@ -116,7 +116,7 @@ const UserList: React.FC = (props: UserListProps) => { const message = JSON.parse(event.data); const data: any = message.data; switch (message.type) { - case "lobby_state": + case "lobby_state": { type LobbyStateData = { participants: User[]; }; @@ -128,6 +128,14 @@ const UserList: React.FC = (props: UserListProps) => { lobby_state.participants.sort(sortUsers); setUsers(lobby_state.participants); break; + } + case "update_name": { + // Update local session name immediately + if (data && typeof data.name === "string") { + session.name = data.name; + } + break; + } default: break; } @@ -143,6 +151,19 @@ const UserList: React.FC = (props: UserListProps) => { }); }, [users, sendJsonMessage]); + // Add state for name change UI + const [newName, setNewName] = useState(""); + const [changingName, setChangingName] = useState(false); + + // Handler for changing name + const handleChangeName = () => { + if (!newName.trim()) return; + setChangingName(true); + sendJsonMessage({ type: "set_name", data: { name: newName } }); + setNewName(""); + setTimeout(() => setChangingName(false), 1000); // UI feedback + }; + return ( = (props: UserListProps) => { m: { xs: 0, sm: 2 }, }} > + {/* Name change UI for local user */} + {session && ( + + setNewName(e.target.value)} + placeholder="Change your name" + style={{ fontSize: "1em", padding: "4px 8px", borderRadius: 4, border: "1px solid #ccc" }} + disabled={changingName} + /> + + + )} {users?.map((user) => (