@@ -12,10 +12,7 @@ import { API_URL } from "@/config/index";
1212import useCamera , { cameraPermissions } from "@/hooks/meeting/useCamera" ;
1313import { API } from "@escolalms/sdk/lib" ;
1414import { IMeetRecording } from "@/components/Consultations/ConsultationCard/JitsyMeeting/types" ;
15- import {
16- JITSY_ANALYTICS_INTERVAL ,
17- JITSY_TUTOR_INTERVAL ,
18- } from "@/utils/constants" ;
15+ import { JITSY_ANALYTICS_INTERVAL } from "@/utils/constants" ;
1916import { Text } from "@escolalms/components/lib/components/atoms/Typography/Text" ;
2017import { Button } from "@escolalms/components/lib/components/atoms/Button/Button" ;
2118import { useJitsyAnalyticsControl } from "@/hooks/meeting/useJitsyAnalyticsControl" ;
@@ -78,7 +75,7 @@ const JitsyMeeting: React.FC<JitsyMeetingProps> = ({
7875 const { consultation, token } = useContext ( EscolaLMSContext ) ;
7976 const { isStudent } = useRoles ( ) ;
8077 const { t } = useTranslation ( ) ;
81- const { camera, getDataUrl, cameraAccessStatus } = useCamera ( ) ;
78+ const { camera, getDataUrl, cameraAccessStatus, stopCamera } = useCamera ( ) ;
8279 const userConsentedRef = useRef ( false ) ;
8380 const isCameraMutedRef = useRef ( false ) ;
8481
@@ -91,6 +88,8 @@ const JitsyMeeting: React.FC<JitsyMeetingProps> = ({
9188 const workerRef = useRef < Worker | null > ( null ) ;
9289 const apiRef = useRef < IJitsiMeetExternalApi | null > ( null ) ;
9390 const recordingTimeoutRef = useRef < NodeJS . Timeout | null > ( null ) ;
91+ const hasSentEndEventRef = useRef ( false ) ;
92+
9493 const { shouldRunAnalytics } = useJitsyAnalyticsControl ( {
9594 modelType,
9695 participantCount,
@@ -140,6 +139,13 @@ const JitsyMeeting: React.FC<JitsyMeetingProps> = ({
140139 const sendRecordingEvent = useCallback (
141140 async ( action : "start-recording" | "end-recording" ) => {
142141 if ( isStudent ) return ;
142+
143+ if (
144+ action === "end-recording" &&
145+ ( hasSentEndEventRef . current || ! recordingIdRef . current )
146+ ) {
147+ return ;
148+ }
143149 try {
144150 const payload = preparePayload ( action ) ;
145151
@@ -156,6 +162,10 @@ const JitsyMeeting: React.FC<JitsyMeetingProps> = ({
156162 }
157163 ) ;
158164
165+ if ( action === "end-recording" ) {
166+ recordingIdRef . current = null ;
167+ }
168+
159169 const result = await response . json ( ) ;
160170
161171 if ( action === "start-recording" && result ?. data ?. id ) {
@@ -364,13 +374,25 @@ const JitsyMeeting: React.FC<JitsyMeetingProps> = ({
364374 useEffect ( ( ) => {
365375 const init = async ( ) => {
366376 try {
367- await navigator . mediaDevices . getUserMedia ( { video : true , audio : true } ) ;
377+ const stream = await navigator . mediaDevices . getUserMedia ( {
378+ video : true ,
379+ audio : true ,
380+ } ) ;
381+
382+ stream . getTracks ( ) . forEach ( ( track ) => {
383+ track . stop ( ) ;
384+ console . log ( "Init test track stopped" ) ;
385+ } ) ;
386+
368387 isStudent ? setShowModal ( true ) : setShowMeeting ( true ) ;
369- } catch {
388+ } catch ( err ) {
389+ console . warn ( "Camera access failed in init" , err ) ;
370390 setShowMeeting ( true ) ;
371391 }
372392 } ;
373393 init ( ) ;
394+
395+ return ( ) => { } ;
374396 } , [ isStudent ] ) ;
375397
376398 const getProperRoomName = ( ) => {
@@ -393,6 +415,7 @@ const JitsyMeeting: React.FC<JitsyMeetingProps> = ({
393415 } }
394416 onReadyToClose = { async ( ) => {
395417 stopAllIntervals ( ) ;
418+ stopCamera ( ) ;
396419 if ( ! isStudent && recordingIdRef . current ) {
397420 await sendRecordingEvent ( "end-recording" ) ;
398421 }
0 commit comments