diff --git a/app/custom/CustomControlBar.tsx b/app/custom/CustomControlBar.tsx index 4269dba..9b3d4fe 100644 --- a/app/custom/CustomControlBar.tsx +++ b/app/custom/CustomControlBar.tsx @@ -1,123 +1,111 @@ -// // import React from 'react'; -// // import { TrackToggle, DisconnectButton } from '@livekit/components-react'; -// // import SettingsMenu from '@/lib/SettingsMenu'; -// // import { MaterialSymbol } from 'material-symbols'; -// // import '../../styles/CustomControlBar.css'; +'use client'; + +import React, { useState, useEffect } from 'react'; +import { + TrackToggle, + DisconnectButton +} from '@livekit/components-react'; +import { + Room, + RoomEvent, + Track +} from 'livekit-client'; +import '../../styles/CustomControlBar.css'; -// // const CustomControlBar = ({ roomName, room }) => { -// // const [recording, setRecording] = React.useState(false); -// // const [showSettings, setShowSettings] = React.useState(false); +interface CustomControlBarProps { + room: Room; + roomName: string; +} -// // React.useEffect(() => { -// // if (room) { -// // room.on('recordedStatusChanged', () => { -// // setRecording(room.isRecording); -// // }); -// // return () => { -// // room.off('recordedStatusChanged'); -// // }; -// // } -// // }, [room]); +export function CustomControlBar({ room, roomName }: CustomControlBarProps) { + const [recording, setRecording] = useState(false); + const [participantCount, setParticipantCount] = useState(1); -// // const handleCopyLink = () => { -// // navigator.clipboard.writeText(window.location.href); -// // }; + useEffect(() => { + if (room) { -// // return ( -// //
-// //
-// //
-// // {roomName} -// // -// //
-// //
-// //
-// // -// // -// // {recording && ( -// //
-// // {/* */} -// //
-// // )} -// // -// // -// //
-// //
-// // -// // {showSettings && setShowSettings(false)} />} -// //
-// //
-// // ); -// // }; + const updateRecordingStatus = () => setRecording(room.isRecording); + -// // export default CustomControlBar; + const updateParticipantCount = () => { + if (room && room.participants) { + setParticipantCount(room.participants.size + 1); + } + }; + + if (room.state === 'connected') { + updateParticipantCount(); + } + + room.on(RoomEvent.Connected, updateParticipantCount); + room.on(RoomEvent.ParticipantConnected, updateParticipantCount); + room.on(RoomEvent.ParticipantDisconnected, updateParticipantCount); + room.on(RoomEvent.RecordingStatusChanged, updateRecordingStatus); + + return () => { + room.off(RoomEvent.Connected, updateParticipantCount); + room.off(RoomEvent.ParticipantConnected, updateParticipantCount); + room.off(RoomEvent.ParticipantDisconnected, updateParticipantCount); + room.off(RoomEvent.RecordingStatusChanged, updateRecordingStatus); + }; + } + }, [room]); -// import { TrackToggle, DisconnectButton, RoomAudioRenderer, GridLayout } from '@livekit/components-react'; -// import { useState, useEffect } from 'react'; + const handleCopyLink = () => { + navigator.clipboard.writeText(window.location.href) + .then(() => alert('Link copied to clipboard!')) + .catch((err) => console.error('Failed to copy link:', err)); + }; -// function CustomControlBar({ room, roomName }) { -// const [recording, setRecording] = useState(false); + return ( +
-// // Update recording status -// useEffect(() => { -// if (room) { -// const updateRecordingStatus = () => setRecording(room.isRecording); -// room.on(RoomEvent.RecordingStarted, updateRecordingStatus); -// room.on(RoomEvent.RecordingStopped, updateRecordingStatus); -// return () => { -// room.off(RoomEvent.RecordingStarted, updateRecordingStatus); -// room.off(RoomEvent.RecordingStopped, updateRecordingStatus); -// }; -// } -// }, [room]); +
+ {roomName} + +
-// // Copy room link to clipboard -// const handleCopyLink = () => { -// navigator.clipboard.writeText(window.location.href) -// .then(() => alert('Link copied to clipboard!')) -// .catch((err) => console.error('Failed to copy link:', err)); -// }; + {/* Center: Control Buttons */} +
+ + {/* mic + mic_off */} + + + + {/* videocam + videocam_off */} + + +
+ radio_button_checked +
+ + + {/* screen_share + screen_share */} + + + + call_end + +
-// return ( -//
-// {/* Left: Room Name Box */} -//
-// {roomName} -// -//
- -// {/* Center: Control Buttons */} -//
-// -// -// {recording && ( -//
-// radio_button_checked -//
-// )} -// -// -// call_end -// -//
- -// {/* Right: Settings Button */} -//
-// {SHOW_SETTINGS_MENU && ( -// -// )} -//
-//
-// ); -// } \ No newline at end of file + {/* Participants, Settings btn */} +
+
+ people + {participantCount} +
+ +
+ settings +
+
+
+ ); +} \ No newline at end of file diff --git a/app/custom/VideoTrack.tsx b/app/custom/VideoTrack.tsx new file mode 100644 index 0000000..9fc9fb6 --- /dev/null +++ b/app/custom/VideoTrack.tsx @@ -0,0 +1,27 @@ +'use client'; + +import React, { useRef, useEffect } from 'react'; +import { TrackReferenceOrPlaceholder } from '@livekit/components-react'; +import '../../styles/VideoTrack.css'; + +interface VideoTrackProps { + ref: TrackReferenceOrPlaceholder; +} + +export function VideoTrack({ ref: trackRef }: VideoTrackProps) { + const videoRef = useRef(null); + + useEffect(() => { + const videoEl = videoRef.current; + const track = trackRef.publication?.track; + + if (videoEl && track) { + track.attach(videoEl); + return () => { + track.detach(videoEl); + }; + } + }, [trackRef.publication?.track]); + + return