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..7b0c9ab 100644 --- a/app/custom/CustomControlBar.tsx +++ b/app/custom/CustomControlBar.tsx @@ -1,17 +1,14 @@ 'use client'; import React, { useState, useEffect } from 'react'; -import { - TrackToggle, - DisconnectButton -} from '@livekit/components-react'; -import { - Room, - RoomEvent, - Track -} from 'livekit-client'; +import { DisconnectButton, useLayoutContext, 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'; - +import { CameraOffSVG, CameraOnSVG } from '../svg/camera'; +import { MicOffSVG, MicOnSVG } from '../svg/mic'; +import { ScreenShareOnSVG } from '../svg/screen-share'; interface CustomControlBarProps { room: Room; @@ -20,30 +17,21 @@ interface CustomControlBarProps { export function CustomControlBar({ room, roomName }: CustomControlBarProps) { const [recording, setRecording] = useState(false); - const [participantCount, setParticipantCount] = useState(1); + const [participantCount, setParticipantCount] = useState(1); + const { dispatch } = useLayoutContext().widget; 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(); - } - 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,103 @@ export function CustomControlBar({ room, roomName }: CustomControlBarProps) { people {participantCount}
- -
+ +
{ + if (dispatch) dispatch({ msg: 'toggle_settings' }); + }} + > 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 ? : ; + case Track.Source.Microphone: + return enabled ? : ; + case Track.Source.ScreenShare: + return enabled ? ( + + ) : ( + + 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/VideoConferenceClientImpl.tsx b/app/custom/VideoConferenceClientImpl.tsx index 391ddb6..2ec69b7 100644 --- a/app/custom/VideoConferenceClientImpl.tsx +++ b/app/custom/VideoConferenceClientImpl.tsx @@ -15,7 +15,6 @@ import { import { DebugMode } from '@/lib/Debug'; import { useMemo, useEffect, useState } from 'react'; import { decodePassphrase } from '@/lib/client-utils'; -import { SettingsMenu } from '@/lib/SettingsMenu'; export function VideoConferenceClientImpl(props: { liveKitUrl: string; @@ -65,11 +64,7 @@ export function VideoConferenceClientImpl(props: { return; } console.log('ROOM!!!'); - const updateTranscriptions = ( - segments: TranscriptionSegment[], - participant: any, - publication: any, - ) => { + const updateTranscriptions = (segments: TranscriptionSegment[]) => { console.log('received transcriptions', segments); setTranscriptions((prev) => { const newTranscriptions = { ...prev }; @@ -95,12 +90,7 @@ export function VideoConferenceClientImpl(props: { audio={true} video={true} > - + ); 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