// src/components/control-tray/ControlTray.tsx // ... (ایمپورت‌های اولیه و SVGهای دیگر مثل قبل) ... import cn from "classnames"; import React, { memo, ReactNode, RefObject, useEffect, useState } from "react"; import { useLiveAPIContext } from "../../contexts/LiveAPIContext"; import { AudioRecorder } from "../../lib/audio-recorder"; import LogoAnimation from '../logo-animation/LogoAnimation'; // ... (SVG Icons: SvgPauseIcon, SvgCameraIcon, SvgStopCamIcon, SvgSwitchCameraIcon بدون تغییر) ... export type ControlTrayProps = { videoRef: RefObject; supportsVideo: boolean; onVideoStreamChange: (stream: MediaStream | null) => void; isAppMicActive: boolean; onAppMicToggle: (active: boolean) => void; isAppCamActive: boolean; onAppCamToggle: (active: boolean) => void; ReferenceMicrophoneIcon: () => JSX.Element; initialFacingMode: 'user' | 'environment'; // *** NEW PROP *** onFacingModeChange: (newMode: 'user' | 'environment') => void; // *** NEW PROP *** }; const ControlTray: React.FC = ({ videoRef, onVideoStreamChange, supportsVideo, isAppMicActive, onAppMicToggle, isAppCamActive, onAppCamToggle, ReferenceMicrophoneIcon, initialFacingMode, // *** NEW PROP *** onFacingModeChange, // *** NEW PROP *** }) => { const { client, connected, connect } = useLiveAPIContext(); const [audioRecorder] = useState(() => new AudioRecorder()); const [activeLocalVideoStream, setActiveLocalVideoStream] = useState(null); // *** currentFacingMode حالا از initialFacingMode مقدار اولیه می‌گیرد *** const [currentFacingMode, setCurrentFacingMode] = useState<'user' | 'environment'>(initialFacingMode); const [isSwitchingCamera, setIsSwitchingCamera] = useState(false); const renderCanvasRef = React.useRef(null); // وقتی initialFacingMode از بیرون تغییر می‌کند، state داخلی را هم آپدیت کن useEffect(() => { setCurrentFacingMode(initialFacingMode); }, [initialFacingMode]); // ... (useEffect های audioRecorder, sendVideoFrame, videoRef.srcObject بدون تغییر) ... useEffect(() => { if (isAppCamActive && !activeLocalVideoStream && !isSwitchingCamera) { // هنگام شروع وب‌کم، از currentFacingMode داخلی استفاده کن startWebcam(currentFacingMode); } else if (!isAppCamActive && activeLocalVideoStream) { stopWebcam(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isAppCamActive, activeLocalVideoStream, isSwitchingCamera]); // currentFacingMode را از وابستگی‌ها حذف می‌کنیم تا startWebcam فقط یکبار با مقدار اولیه اجرا شود و بعدا توسط handleSwitchCamera مدیریت شود. const startWebcam = async (facingModeToTry: 'user' | 'environment' = currentFacingMode) => { if (isSwitchingCamera) return; setIsSwitchingCamera(true); try { const mediaStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: facingModeToTry }, audio: false }); setActiveLocalVideoStream(mediaStream); onVideoStreamChange(mediaStream); setCurrentFacingMode(facingModeToTry); // آپدیت state داخلی onFacingModeChange(facingModeToTry); // اطلاع به والد } catch (error) { console.error(`❌ Start WC err ${facingModeToTry}:`, error); setActiveLocalVideoStream(null); onVideoStreamChange(null); onAppCamToggle(false); // اگر وب‌کم شروع نشد، دکمه دوربین را خاموش کن } finally { setIsSwitchingCamera(false); } }; // ... (stopWebcam, ensureConnectedAndReady, handleMicToggle, handleCamToggle بدون تغییر عمده) ... // فقط handleCamToggle ممکن است نیاز به استفاده از currentFacingMode داشته باشد اگر اولین بار دوربین را با جهت خاصی می‌خواهید روشن کنید const handleSwitchCamera = async () => { if (!isAppCamActive || !activeLocalVideoStream || isSwitchingCamera) return; setIsSwitchingCamera(true); const targetFacingMode = currentFacingMode === 'user' ? 'environment' : 'user'; activeLocalVideoStream.getTracks().forEach(track => track.stop()); try { const newStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: targetFacingMode } }, audio: false }); setActiveLocalVideoStream(newStream); onVideoStreamChange(newStream); setCurrentFacingMode(targetFacingMode); // آپدیت state داخلی onFacingModeChange(targetFacingMode); // اطلاع به والد } catch (error) { console.error(`❌ Switch Cam err ${targetFacingMode}:`, error); // سعی در بازگرداندن به دوربین قبلی try { const restoredStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: currentFacingMode }, audio: false }); // استفاده از currentFacingMode قبلی setActiveLocalVideoStream(restoredStream); onVideoStreamChange(restoredStream); // onFacingModeChange(currentFacingMode); // نیازی نیست چون به حالت قبلی برگشتیم } catch (restoreError) { console.error('❌ Restore Cam err:', restoreError); setActiveLocalVideoStream(null); onVideoStreamChange(null); onAppCamToggle(false); } } finally { setIsSwitchingCamera(false); } }; // ... (بقیه useEffect ها و توابع handle مثل قبل) const ensureConnectedAndReady = async (): Promise => { /* ... */ return false; }; const handleMicToggle = async () => { /* ... */ }; const handleCamToggle = async () => { /* ... */ }; return ( ); }; export default memo(ControlTray);