'use client';
import React, { useState, useEffect } from 'react';
import { DisconnectButton, useRoomContext } from '@livekit/components-react';
import { Room, RoomEvent, Track } from 'livekit-client';
import { mergeClasses } from '@/lib/client-utils';
import { ToggleSource } from '@livekit/components-core';
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 = () => {
setParticipantCount(room.numParticipants);
};
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 */}
radio_button_checked
call_end
{/* Participants, Settings btn */}
people
{participantCount}
settings
);
}
interface ControlButtonProps {
enabled?: boolean;
icon: React.ReactNode;
className?: string;
onClick?: () => void;
}
function ControlButton({ enabled = true, icon, className, onClick }: ControlButtonProps) {
return (
);
}
function TrackToggle({ source }: { source: ToggleSource }) {
const { enabled, toggle } = useTrackToggle({ source });
const isScreenShare = source === Track.Source.ScreenShare;
return (
}
/>
);
}
interface TrackIconProps {
trackSource: ToggleSource;
enabled: boolean;
}
function TrackIcon({ trackSource, enabled }: TrackIconProps) {
switch (trackSource) {
case Track.Source.Camera:
return enabled ? (
videocam
) : (
videocam_off
);
case Track.Source.Microphone:
return enabled ? (
mic
) : (
mic_off
);
case Track.Source.ScreenShare:
return enabled ? (
screen_share
) : (
stop_screen_share
);
}
}
// Custom hook for track toggle
function useTrackToggle({ source }: { source: ToggleSource }) {
const { localParticipant } = useRoomContext();
const toggle = () => {
switch (source) {
case Track.Source.Camera:
return localParticipant.setCameraEnabled(!enabled);
case Track.Source.Microphone:
return localParticipant.setMicrophoneEnabled(!enabled);
case Track.Source.ScreenShare:
return localParticipant.setScreenShareEnabled(!enabled);
}
};
const enabled = (() => {
switch (source) {
case Track.Source.Camera:
return localParticipant.isCameraEnabled;
case Track.Source.Microphone:
return localParticipant.isMicrophoneEnabled;
case Track.Source.ScreenShare:
return localParticipant.isScreenShareEnabled;
}
})();
return { enabled, toggle };
}