"use client"; import { useCallback, useEffect, useRef, useState } from "react"; import { Box, Button, Text, VStack, HStack, Icon } from "@chakra-ui/react"; import { toaster } from "../../components/ui/toaster"; import { useRouter } from "next/navigation"; import useSessionStatus from "../../lib/useSessionStatus"; import { useRecordingConsent } from "../../recordingConsentContext"; import useApi from "../../lib/useApi"; import { FaBars } from "react-icons/fa6"; import DailyIframe from "@daily-co/daily-js"; interface Meeting { id: string; room_url: string; host_room_url?: string; recording_type: string; platform?: string; } interface DailyRoomProps { meeting: Meeting; } function ConsentDialogButton({ meetingId }: { meetingId: string }) { const { state: consentState, touch, hasConsent } = useRecordingConsent(); const [consentLoading, setConsentLoading] = useState(false); const [modalOpen, setModalOpen] = useState(false); const api = useApi(); const handleConsent = useCallback( async (meetingId: string, given: boolean) => { if (!api) return; setConsentLoading(true); try { await api.v1MeetingAudioConsent({ meetingId, requestBody: { consent_given: given }, }); touch(meetingId); } catch (error) { console.error("Error submitting consent:", error); } finally { setConsentLoading(false); } }, [api, touch], ); const showConsentModal = useCallback(() => { if (modalOpen) return; setModalOpen(true); const toastId = toaster.create({ placement: "top", duration: null, render: ({ dismiss }) => ( Can we have your permission to store this meeting's audio recording on our servers? ), }); // Set modal state when toast is dismissed toastId.then((id) => { const checkToastStatus = setInterval(() => { if (!toaster.isActive(id)) { setModalOpen(false); clearInterval(checkToastStatus); } }, 100); }); // Handle escape key to close the toast const handleKeyDown = (event: KeyboardEvent) => { if (event.key === "Escape") { toastId.then((id) => toaster.dismiss(id)); } }; document.addEventListener("keydown", handleKeyDown); const cleanup = () => { toastId.then((id) => toaster.dismiss(id)); document.removeEventListener("keydown", handleKeyDown); }; return cleanup; }, [meetingId, handleConsent, modalOpen]); if (!consentState.ready || hasConsent(meetingId) || consentLoading) { return null; } return ( ); } const recordingTypeRequiresConsent = (recordingType: string) => { return recordingType === "cloud"; }; export default function DailyRoom({ meeting }: DailyRoomProps) { const router = useRouter(); const { isLoading, isAuthenticated } = useSessionStatus(); const [callFrame, setCallFrame] = useState(null); const containerRef = useRef(null); const roomUrl = meeting?.host_room_url ? meeting?.host_room_url : meeting?.room_url; const handleLeave = useCallback(() => { router.push("/browse"); }, [router]); // Initialize Daily.co call frame useEffect(() => { if (isLoading || !isAuthenticated || !roomUrl) return; const frame = DailyIframe.createFrame(containerRef.current!, { iframeStyle: { width: "100vw", height: "100vh", border: "none", }, showLeaveButton: true, showFullscreenButton: true, }); frame.on("left-meeting", handleLeave); frame.join({ url: roomUrl }); setCallFrame(frame); return () => { frame.destroy(); }; }, [roomUrl, isLoading, isAuthenticated, handleLeave]); if (!roomUrl) { return null; } return (
{recordingTypeRequiresConsent(meeting.recording_type) && ( )} ); }