From 3676fb5543e8c1cf87a51a37af82d1c2d4f05ffe Mon Sep 17 00:00:00 2001 From: SujithThirumalaisamy Date: Mon, 17 Mar 2025 21:18:15 +0530 Subject: [PATCH 1/3] Refactored Custom Layout --- .eslintrc.json | 1 - app/custom/CustomControlBar.tsx | 168 +- app/custom/VideoTrack.tsx | 2 +- app/layout.tsx | 2 +- app/rooms/[roomName]/PageClientImpl.tsx | 66 +- assetlinks.json | 34 +- dev.yaml | 7 +- lib/CustomVideoLayout.tsx | 211 +- lib/ParticipantTile.tsx | 276 ++- lib/client-utils.ts | 43 + package.json | 1 + pnpm-lock.yaml | 2538 +++++++++++++++++------ prod.yaml | 9 +- styles/CustomControlBar.css | 53 +- styles/PageClientImpl.css | 48 +- styles/ParticipantTile.css | 103 + styles/Transcript.module.css | 21 +- styles/VideoTrack.css | 8 +- styles/globals.css | 82 + styles/participant-tile.css | 198 +- 20 files changed, 2688 insertions(+), 1183 deletions(-) delete mode 100644 .eslintrc.json create mode 100644 styles/ParticipantTile.css diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 0967ef4..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/app/custom/CustomControlBar.tsx b/app/custom/CustomControlBar.tsx index 9b3d4fe..467ffd7 100644 --- a/app/custom/CustomControlBar.tsx +++ b/app/custom/CustomControlBar.tsx @@ -1,18 +1,12 @@ 'use client'; import React, { useState, useEffect } from 'react'; -import { - TrackToggle, - DisconnectButton -} from '@livekit/components-react'; -import { - Room, - RoomEvent, - Track -} from 'livekit-client'; +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; @@ -20,30 +14,24 @@ interface CustomControlBarProps { export function CustomControlBar({ room, roomName }: CustomControlBarProps) { const [recording, setRecording] = useState(false); - const [participantCount, setParticipantCount] = useState(1); + const [participantCount, setParticipantCount] = useState(1); useEffect(() => { if (room) { - const updateRecordingStatus = () => setRecording(room.isRecording); - - const updateParticipantCount = () => { - if (room && room.participants) { - setParticipantCount(room.participants.size + 1); - } + setParticipantCount(room.numParticipants); }; - if (room.state === 'connected') { - updateParticipantCount(); + 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); @@ -54,14 +42,14 @@ export function CustomControlBar({ room, roomName }: CustomControlBarProps) { }, [room]); const handleCopyLink = () => { - navigator.clipboard.writeText(window.location.href) + 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 @@ -101,11 +78,118 @@ export function CustomControlBar({ room, roomName }: CustomControlBarProps) { people {participantCount}
- +
settings
); -} \ No newline at end of file +} + +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 }; +} diff --git a/app/custom/VideoTrack.tsx b/app/custom/VideoTrack.tsx index 9fc9fb6..338d83e 100644 --- a/app/custom/VideoTrack.tsx +++ b/app/custom/VideoTrack.tsx @@ -24,4 +24,4 @@ export function VideoTrack({ ref: trackRef }: VideoTrackProps) { }, [trackRef.publication?.track]); return