diff --git a/.env.example b/.env.example deleted file mode 100644 index f961fa0..0000000 --- a/.env.example +++ /dev/null @@ -1,30 +0,0 @@ -# 1. Copy this file and rename it to .env.local -# 2. Update the enviroment variables below. - -# REQUIRED SETTINGS -# ################# -# If you are using LiveKit Cloud, the API key and secret can be generated from the Cloud Dashboard. -LIVEKIT_API_KEY= -LIVEKIT_API_SECRET= -# URL pointing to the LiveKit server. (example: `wss://my-livekit-project.livekit.cloud`) -LIVEKIT_URL= - - -# OPTIONAL SETTINGS -# ################# -# Recording -# S3_KEY_ID= -# S3_KEY_SECRET= -# S3_ENDPOINT= -# S3_BUCKET= -# S3_REGION= - -# PUBLIC -# Uncomment settings menu when using a LiveKit Cloud, it'll enable Krisp noise filters. -# NEXT_PUBLIC_SHOW_SETTINGS_MENU=true -# NEXT_PUBLIC_LK_RECORD_ENDPOINT=/api/record - -# Optional, to pipe logs to datadog -# NEXT_PUBLIC_DATADOG_CLIENT_TOKEN=client-token -# NEXT_PUBLIC_DATADOG_SITE=datadog-site - diff --git a/app/custom/CustomControlBar.tsx b/app/custom/CustomControlBar.tsx new file mode 100644 index 0000000..9b3d4fe --- /dev/null +++ b/app/custom/CustomControlBar.tsx @@ -0,0 +1,111 @@ +'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'; + + +interface CustomControlBarProps { + room: Room; + roomName: string; +} + +export function CustomControlBar({ room, roomName }: CustomControlBarProps) { + const [recording, setRecording] = useState(false); + const [participantCount, setParticipantCount] = useState(1); + + useEffect(() => { + if (room) { + + const updateRecordingStatus = () => setRecording(room.isRecording); + + + 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]); + + const handleCopyLink = () => { + navigator.clipboard.writeText(window.location.href) + .then(() => alert('Link copied to clipboard!')) + .catch((err) => console.error('Failed to copy link:', err)); + }; + + return ( +
+ +
+ {roomName} + +
+ + {/* Center: Control Buttons */} +
+ + {/* mic + mic_off */} + + + + {/* videocam + videocam_off */} + + +
+ radio_button_checked +
+ + + {/* screen_share + screen_share */} + + + + call_end + +
+ + {/* 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