From dc977565a192fd28c5ec6a40c3e68cd6dd1daddd Mon Sep 17 00:00:00 2001 From: Dnouv <61188295+Dnouv@users.noreply.github.com> Date: Fri, 1 Apr 2022 23:37:36 +0530 Subject: [PATCH] Add Jitsi component and support for Alumni Summit Adding despite LGTM warnings during CI build - as per @debdutdeb 's advice. --- app/.env.local.sample | 2 + .../clientsideonly/jitsibroadcaster.js | 669 +++++++++++------- app/package.json | 1 + app/pages/virtualconf/greenroom/index.js | 2 +- docs/components/jitsi/README.md | 64 ++ docs/components/jitsi/jitsiDemo.png | Bin 0 -> 232564 bytes 6 files changed, 474 insertions(+), 264 deletions(-) create mode 100644 docs/components/jitsi/README.md create mode 100644 docs/components/jitsi/jitsiDemo.png diff --git a/app/.env.local.sample b/app/.env.local.sample index c0c15538..edb7dd0e 100644 --- a/app/.env.local.sample +++ b/app/.env.local.sample @@ -44,3 +44,5 @@ NEXT_PUBLIC_ROCKET_CHAT_HOST=requiredInProd NEXT_PUBLIC_ROCKET_CHAT_CONF_RID=required # id of the greenroom NEXT_PUBLIC_ROCKET_CHAT_GREENROOM_RID=required +NEXT_PUBLIC_ROCKET_CHAT_GREENROOM_RTMP="rtmp://bkk.contribute.live-video.net/app/{stream_key}" + diff --git a/app/components/clientsideonly/jitsibroadcaster.js b/app/components/clientsideonly/jitsibroadcaster.js index f87c8b06..f9a80f08 100644 --- a/app/components/clientsideonly/jitsibroadcaster.js +++ b/app/components/clientsideonly/jitsibroadcaster.js @@ -1,269 +1,412 @@ - -import dynamic from 'next/dynamic' -import React, { useRef, useState } from 'react' - - -const JitsiMeeting = dynamic( () => import('@jitsi/web-sdk').then((mod) => mod.JitsiMeeting) , {ssr: false } ) - - -const Jitsibroadcaster = () => { - const apiRef = useRef(); - const apiRefNew = useRef(); - const [ logItems, updateLog ] = useState([]); - const [ showNew, toggleShowNew ] = useState(false); - const [ knockingParticipants, updateKnockingParticipants ] = useState([]); - - const printEventOutput = payload => { - updateLog(items => [ ...items, JSON.stringify(payload) ]); - }; - - const handleAudioStatusChange = (payload, feature) => { - if (payload.muted) { - updateLog(items => [ ...items, `${feature} off` ]) - } else { - updateLog(items => [ ...items, `${feature} on` ]) - } - }; - - const handleChatUpdates = (payload, ref) => { - if (payload.isOpen || !payload.unreadCount) { - return; - } - ref.current.executeCommand('toggleChat'); - updateLog(items => [ ...items, `you have ${payload.unreadCount} unread messages` ]) - }; - - const handleKnockingParticipant = payload => { - updateLog(items => [ ...items, JSON.stringify(payload) ]); - updateKnockingParticipants(participants => [ ...participants, payload?.participant ]) - }; - - const resolveKnockingParticipants = (ref, condition) => { - knockingParticipants.forEach(participant => { - ref.current.executeCommand('answerKnockingParticipant', participant?.id, condition(participant)); - updateKnockingParticipants(participants => participants.filter(item => item.id === participant.id)); +import dynamic from "next/dynamic"; +import React, { useEffect, useRef, useState } from "react"; +import { Button, ButtonGroup } from "react-bootstrap"; +import { BiMicrophone, BiMicrophoneOff } from "react-icons/bi"; + +const JitsiMeeting = dynamic( + () => import("@jitsi/react-sdk").then((mod) => mod.JitsiMeeting), + { ssr: false } +); + +const rtmp = process.env.NEXT_PUBLIC_ROCKET_CHAT_GREENROOM_RTMP; + +const Jitsibroadcaster = ({room, disName, rtmpSrc}) => { + const apiRef = useRef(); + const [logItems, updateLog] = useState([]); + const [knockingParticipants, updateKnockingParticipants] = useState([]); + const [mute, setMute] = useState(true); + const [name, setName] = useState(null) + const dataArr = [{speaker: "A", hour: "10"}, {speaker: "B", hour: "20"}, {speaker: "C", hour: "30"}, {speaker: "D", hour: "40"}, {speaker: "Z", hour: "50"}] + + const handleDisplayName = async (hr) => { + const tar = dataArr.find(o => o.hour === hr) + if (!tar || tar.speaker == name) { + return + } + setName(tar.speaker) + await apiRef.current.executeCommand("displayName", tar.speaker) + } + + useEffect(() => { + setInterval(() => { + const tada = new Date() + handleDisplayName(tada.getHours().toString()) + }, 900000); + }, []) + + const printEventOutput = (payload) => { + updateLog((items) => [...items, JSON.stringify(payload)]); + }; + + const handleAudioStatusChange = (payload, feature) => { + if (payload.muted) { + updateLog((items) => [...items, `${feature} off`]); + } else { + updateLog((items) => [...items, `${feature} on`]); + } + }; + + const handleChatUpdates = (payload, ref) => { + if (payload.isOpen || !payload.unreadCount) { + return; + } + ref.current.executeCommand("toggleChat"); + updateLog((items) => [ + ...items, + `you have ${payload.unreadCount} unread messages`, + ]); + }; + + const handleKnockingParticipant = (payload) => { + updateLog((items) => [...items, JSON.stringify(payload)]); + updateKnockingParticipants((participants) => [ + ...participants, + payload?.participant, + ]); + }; + + const resolveKnockingParticipants = (ref, condition) => { + knockingParticipants.forEach((participant) => { + ref.current.executeCommand( + "answerKnockingParticipant", + participant?.id, + condition(participant) + ); + updateKnockingParticipants((participants) => + participants.filter((item) => item.id === participant.id) + ); + }); + }; + + const handleJitsiIFrameRef1 = (iframeRef) => { + iframeRef.style.border = "10px solid cadetblue"; + iframeRef.style.background = "cadetblue"; + iframeRef.style.height = "720px"; + iframeRef.style.overflow = "auto"; + iframeRef.style.resize = "both"; + }; + + const showDevices = async (ref) => { + const videoInputs = []; + // get all available video input + const devices = await ref.current.getAvailableDevices(); + + for (const [key, value] of Object.entries(devices)) { + if (key == "videoInput") { + value.forEach((vid) => { + videoInputs.push(vid.label); }); - }; - - const handleJitsiIFrameRef1 = iframeRef => { - iframeRef.style.border = '10px solid cadetblue'; - iframeRef.style.background = 'cadetblue'; - iframeRef.style.height = '720px'; - }; - - const handleJitsiIFrameRef2 = iframeRef => { - iframeRef.style.marginTop = '10px'; - iframeRef.style.border = '10px dashed tomato'; - iframeRef.style.padding = '5px'; - iframeRef.style.height = '400px'; - }; - - - const showDevices = async (ref) => { - const videoInputs = []; - let currentDevice = ""; - // get all available video input - const devices = await ref.current.getAvailableDevices(); - - for (const [key, value] of Object.entries(devices)) { - if ( key == 'videoInput') { - value.forEach( (vid) => { - videoInputs.push( vid.label ); - }); - - } + } + } + // log for debug + updateLog((items) => [...items, JSON.stringify(videoInputs)]); + + let nextDevice = ""; + let devs = await ref.current.getCurrentDevices(); + + for (const [key, value] of Object.entries(devs)) { + if (key == "videoInput") { + updateLog((items) => [...items, "found " + JSON.stringify(value)]); + let devLabel = value.label; + let idx = 0; + videoInputs.forEach((vid) => { + if (devLabel == vid) { + let cur = idx + 1; + if (cur >= videoInputs.length) { + nextDevice = videoInputs[0]; + } else { + nextDevice = videoInputs[cur]; + updateLog((items) => [...items, "next is " + nextDevice]); } - // log for debug - updateLog(items => [ ...items, JSON.stringify(videoInputs) ]) - - let nextDevice = ""; - let devs = await ref.current.getCurrentDevices(); - - for (const [key, value] of Object.entries(devs)) { - if ( key == 'videoInput') { - updateLog(items => [ ...items, "found " + JSON.stringify(value) ]) - let devLabel = value.label; - let idx = 0; - videoInputs.forEach( (vid) => { - if (devLabel == vid) { - let cur = idx + 1; - if (cur >= videoInputs.length) { - nextDevice = videoInputs[0]; - } else { - nextDevice = videoInputs[cur]; - updateLog(items => [ ...items, "next is " + nextDevice ]) - } - - } - idx++; - }); - - - } - - - } - updateLog(items => [ ...items, "switching to " + nextDevice ]) - await ref.current.setVideoInputDevice(nextDevice); - }; - - const handleApiReady = async (apiObj, ref) => { - ref.current = apiObj; - await ref.current.addEventListeners({ - // Listening to events from the external API - audioMuteStatusChanged: payload => handleAudioStatusChange(payload, 'audio'), - videoMuteStatusChanged: payload => handleAudioStatusChange(payload, 'video'), - raiseHandUpdated: printEventOutput, - tileViewChanged: printEventOutput, - chatUpdated: payload => handleChatUpdates(payload, ref), - knockingParticipant: handleKnockingParticipant + } + idx++; }); - - - await ref.current.executeCommand('toggleFilmStrip'); - - } ; - - // Multiple instances demo - const showUsers = async (ref, which) => { - - const pinfo = await ref.current.getParticipantsInfo(); - updateLog(items => [ ...items, "participantes " + JSON.stringify(pinfo) ]) - await ref.current.executeCommand('setTileView', false); - await ref.current.setLargeVideoParticipant( pinfo[which].participantId); - }; - - const makeTile = (ref) => { - - ref.current.executeCommand('setTileView', true); - }; - const renderButtons = () => ( -
@YWuV3oY(8<`Y
zkM2h~7|~1n?_$eWq~~JRiYis=uF+59HjUb#(qACXLPG~8-H5zn_N`K%XcchDl>f=sdi~4gjh67p(
zbDwq|>bF6~wbje=((EJ@6Ulzm_--%*KeFqYDqm)`qGHCZpirSYb{X7dLxT-#lr^&~
z>`jNID*kQCd5yBNuEWbJ{>_HePaJ?a_*sQPP=eh;m|!#@9e1{?vW)BbK#UO_$m$P-
zwWgTbrQwFTXQF^q5{((T)rUN
zy9r9KsLs;JWf&prBQ7_^xT($a)JD9C!XGsBT}-}?a=6oQNIvDWwynR8SI3qgKLL&W
zis#bm@ark|ddQ>tFV+|I+A^Xh(kQW$#>Jj+mSyC8RY-KPv7%ZB1s{_q+KqHt)_tYl
zNgb!sqpoI)ia@?U-
z8DiriXa``RzfPXVYK9V)kV2cwsrrI^r>lRbnk_Sm=Sm9wI5hXnyNypsfqB(~cECT2
zGD`*22XRI~Wh&=Ikqo-HnzIFTlu1##22zIdH^jz1;<7bv|I{>ZJ*#jH1Xa--8HF-`
zd!{x+C!i`aoS?@@@gSy@`*y{C;UsR><@kO
y2F7rcJ@(*tlNEj_7hS>AK1)2Wb^pKE_Sb(+!MDDA^pM_VXJotojHm!(G`z$7
z`!z?-u10|9(?GDh+JF67GWcQg#p>T(JAcnL5x5n%VC;#%u8Q;k2h}89b9?^rFLUn>
zgj(h@FviIkBCo$EnUMfIZKVud6*!OQ-!AOOAAb`cAaUd`8`Ts7V}xF4J@~KJ{M+|5
zgDr5MYnbBSe)q3G``=ma??s2-7!%+DqeJG2{xZvdGCcnB|J|DV+v;GHf|kHo&Gj#j
z{f{5}E(vv~zr{12e~k7obN=yL>LOs-iRUH1I|=@~C%`{;D2RWxciAZZG1`BhP;iFa
zKMs%jd#nB9i$F{N@#T@w4@CcIpZ&w)Z}Gdi=*rw55BA?b1~|tKR9mGaj{WOe_{WIA
zqumFVz0j9JJ;0__b-HkKx#yI*(dm=_$*h0fec@(?C8lM=TGaIJIWRpJIySff+}j>o
z`VV{HuQ3Tmfq-