Zalan khan
Zalan khan

Reputation: 11

How to resume a video call in agora-rtc-react when switched to another tab

Currently my video call is working fine using agora-rtc-react in reactjs but when I switch the tab then the video call isn't working in the floating video call.

I made a floating video call component in i'm passing the channelName, appId, token but it's not working as expected. here is my floating video call component:

// src/components/FloatingVideo.js
import React, { useEffect, useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import {createClient,createMicrophoneAndCameraTracks,AgoraVideoPlayer} from 'agora-rtc-react'
import styles from './FloatingChat.module.scss'
import { addLiveCallDetails } from 'slices/livecall'
import Controls from './Controls'
import { FaMicrophoneSlash } from 'react-icons/fa6'
import { IoVideocamOffOutline } from 'react-icons/io5'
import Draggable from 'react-draggable'

const config = { mode: 'rtc', codec: 'vp8' }
const useClient = createClient(config)
const useMicrophoneAndCameraTracks = createMicrophoneAndCameraTracks()

const FloatingVideo = (props) => {
  const client = useClient()
  const { ready, tracks } = useMicrophoneAndCameraTracks()
  const dispatch = useDispatch()
  const [isAudioEnabled, setIsAudioEnabled] = useState(true)
  const [isVideoEnabled, setIsVideoEnabled] = useState(true)
  const [start, setStart] = useState(false)
  const [users, setUsers] = useState([])
  const [remoteConnectionState, setRemoteConnectionState] = useState({audio: true, video: true,})
  const { liveCallDetails } = useSelector((state) => state.mentalHealth)
  const { channelName, appId, token, inCall } = liveCallDetails

  useEffect(() => {
    const joinChannel = async () => {
      if (ready && tracks && channelName && appId && token && !inCall) {
        try {
          await client.join(appId, channelName, token, null)
          await client.publish(tracks)
          dispatch(addLiveCallDetails({ ...liveCallDetails, inCall: true }))
          setStart(true)

          client.on('user-published', async (user, mediaType) => {
            await client.subscribe(user, mediaType)
            setUsers((prevUsers) => [...prevUsers, user])

            if (mediaType === 'audio') {
              user.audioTrack?.play()
            }
          })

          client.on('user-unpublished', (user, type) => {
            if (type === 'audio') {
              user.audioTrack?.stop()
            }
            setUsers((prevUsers) => prevUsers.filter((u) => u.uid !== user.uid))
          })

          client.on('user-left', (user) => {
            setUsers((prevUsers) => prevUsers.filter((u) => u.uid !== user.uid))
          })
        } catch (error) {
          console.error('Failed to join the channel:', error)
        }
      }
    }

    joinChannel()

    return () => {
      if (inCall) {
        client.leave()
        dispatch(addLiveCallDetails({ ...liveCallDetails, inCall: false }))
      }
    }
  }, [
    client,
    ready,
    tracks,
    channelName,
    appId,
    token,
    inCall,
    dispatch,
    liveCallDetails,
  ])

  const toggleAudio = async () => {
    if (tracks[0]) {
      await tracks[0].setEnabled(!isAudioEnabled)
      setIsAudioEnabled(!isAudioEnabled)
    }
  }

  const toggleVideo = async () => {
    if (tracks[1]) {
      await tracks[1].setEnabled(!isVideoEnabled)
      setIsVideoEnabled(!isVideoEnabled)
    }
  }

  const leaveCall = async () => {
    if (inCall) {
      await client.leave()
      dispatch(addLiveCallDetails(null))
    }
  }

  if (!ready || !channelName) return null

  return (
    <>
      {ready && tracks && (
        <div className={styles.callContainer}>
          {start && tracks && (
            <div className={styles.container}>
              <Draggable bounds="parent">
                <div className={styles.hostVideo}>
                  {tracks[1] && (
                    <AgoraVideoPlayer
                      className={styles.video_frame}
                      videoTrack={tracks[1]}
                    />
                  )}
                </div>
              </Draggable>
              <div className={styles.controls}>
                <Controls
                  tracks={tracks}
                  setStart={setStart}
                  id={channelName}
                  setInCall={props.setInCall}
                  client={client}
                  type={'videoCall'}
                />
                <button onClick={toggleAudio}>
                  {isAudioEnabled ? 'Mute' : 'Unmute'}
                </button>
                <button onClick={toggleVideo}>
                  {isVideoEnabled ? 'Pause Video' : 'Resume Video'}
                </button>
                <button onClick={leaveCall}>Leave Call</button>
              </div>
              {users.map((user) =>
                user.videoTrack ? (
                  <AgoraVideoPlayer
                    className={styles.video_frame_remote}
                    videoTrack={user.videoTrack}
                    key={user.uid}
                  />
                ) : (
                  <div
                    className={styles.video_frame_black_remote}
                    key={user.uid}
                  >
                    <IoVideocamOffOutline color="white" size={30} />
                  </div>
                ),
              )}
            </div>
          )}
        </div>
      )}
</>
)
}

export default FloatingVideo

Upvotes: 0

Views: 57

Answers (0)

Related Questions