diff --git a/bigbluebutton-html5/imports/ui/components/screenshare/container.jsx b/bigbluebutton-html5/imports/ui/components/screenshare/container.jsx index aec8a87bee..6f550e236b 100755 --- a/bigbluebutton-html5/imports/ui/components/screenshare/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/screenshare/container.jsx @@ -1,22 +1,20 @@ import React from 'react'; -import { withTracker } from 'meteor/react-meteor-data'; import { useMutation, useReactiveVar } from '@apollo/client'; import { defineMessages } from 'react-intl'; import { getSharingContentType, getBroadcastContentType, - isScreenGloballyBroadcasting, - isCameraAsContentGloballyBroadcasting, isScreenBroadcasting, isCameraAsContentBroadcasting, - shouldEnableVolumeControl, useIsSharing, useSharingContentType, + useIsScreenGloballyBroadcasting, + useIsCameraAsContentGloballyBroadcasting, + useShouldEnableVolumeControl, } from './service'; import ScreenshareComponent from './component'; import { layoutSelect, layoutSelectOutput, layoutDispatch } from '../layout/context'; import getFromUserSettings from '/imports/ui/services/users-settings'; -import MediaService from '/imports/ui/components/media/service'; import { EXTERNAL_VIDEO_STOP } from '../external-video-player/mutations'; import { PINNED_PAD_SUBSCRIPTION } from '../notes/queries'; import useDeduplicatedSubscription from '../../core/hooks/useDeduplicatedSubscription'; @@ -105,6 +103,7 @@ const ScreenshareContainer = (props) => { const { data: pinnedPadData } = useDeduplicatedSubscription(PINNED_PAD_SUBSCRIPTION); const NOTES_CONFIG = window.meetingClientSettings.public.notes; + const LAYOUT_CONFIG = window.meetingClientSettings.public.layout; const isSharedNotesPinned = !!pinnedPadData && pinnedPadData.sharedNotes[0]?.sharedNotesExtId === NOTES_CONFIG.id; @@ -133,6 +132,9 @@ const ScreenshareContainer = (props) => { const isSharing = useIsSharing(); const sharingContentType = useSharingContentType(); const outputDeviceId = useReactiveVar(AudioManager._outputDeviceId.value); + const screenIsGloballyBroadcasting = useIsScreenGloballyBroadcasting(); + const cameraAsContentIsGloballyBroadcasting = useIsCameraAsContentGloballyBroadcasting(); + const enableVolumeControl = useShouldEnableVolumeControl(); if ( isScreenBroadcasting(isSharing, sharingContentType) @@ -150,6 +152,13 @@ const ScreenshareContainer = (props) => { isSharedNotesPinned, stopExternalVideoShare, outputDeviceId, + enableVolumeControl, + isGloballyBroadcasting: screenIsGloballyBroadcasting + || cameraAsContentIsGloballyBroadcasting, + hidePresentationOnJoin: getFromUserSettings( + 'bbb_hide_presentation_on_join', + LAYOUT_CONFIG.hidePresentationOnJoin, + ), ...selectedInfo, } } @@ -159,13 +168,4 @@ const ScreenshareContainer = (props) => { return null; }; -export default withTracker(() => { - const LAYOUT_CONFIG = window.meetingClientSettings.public.layout; - - return { - isGloballyBroadcasting: isScreenGloballyBroadcasting() || isCameraAsContentGloballyBroadcasting(), - toggleSwapLayout: MediaService.toggleSwapLayout, - hidePresentationOnJoin: getFromUserSettings('bbb_hide_presentation_on_join', LAYOUT_CONFIG.hidePresentationOnJoin), - enableVolumeControl: shouldEnableVolumeControl(), - }; -})(ScreenshareContainer); +export default ScreenshareContainer; diff --git a/bigbluebutton-html5/imports/ui/components/screenshare/queries.ts b/bigbluebutton-html5/imports/ui/components/screenshare/queries.ts new file mode 100644 index 0000000000..a42c3d80da --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/screenshare/queries.ts @@ -0,0 +1,35 @@ +import { gql } from '@apollo/client'; + +export interface ScreenshareResponse { + contentType: string; + hasAudio: boolean; + screenshareConf: string; + screenshareId: string; + startedAt: string; + stoppedAt: string | null; + stream: string; + vidHeight: number; + vidWidth: number; + voiceConf: string; +} + +export const SCREENSHARE_SUBSCRIPTION = gql` + subscription Screenshare { + screenshare { + contentType + hasAudio + screenshareConf + screenshareId + startedAt + stoppedAt + stream + vidHeight + vidWidth + voiceConf + } + } +`; + +export default { + SCREENSHARE_SUBSCRIPTION, +}; diff --git a/bigbluebutton-html5/imports/ui/components/screenshare/service.js b/bigbluebutton-html5/imports/ui/components/screenshare/service.js index 10168873d7..01f3192d4f 100644 --- a/bigbluebutton-html5/imports/ui/components/screenshare/service.js +++ b/bigbluebutton-html5/imports/ui/components/screenshare/service.js @@ -8,6 +8,8 @@ import AudioService from '/imports/ui/components/audio/service'; import MediaStreamUtils from '/imports/utils/media-stream-utils'; import ConnectionStatusService from '/imports/ui/components/connection-status/service'; import browserInfo from '/imports/utils/browserInfo'; +import createUseSubscription from '/imports/ui/core/hooks/createUseSubscription'; +import { SCREENSHARE_SUBSCRIPTION } from './queries'; const SCREENSHARE_MEDIA_ELEMENT_NAME = 'screenshareVideo'; @@ -23,6 +25,8 @@ const isSharingVar = makeVar(false); const sharingContentTypeVar = makeVar(false); const cameraAsContentDeviceIdTypeVar = makeVar(''); +const useScreenshare = createUseSubscription(SCREENSHARE_SUBSCRIPTION, {}, true); + const useIsSharing = () => useReactiveVar(isSharingVar); const useSharingContentType = () => useReactiveVar(sharingContentTypeVar); const useCameraAsContentDeviceIdType = () => useReactiveVar(cameraAsContentDeviceIdTypeVar); @@ -108,6 +112,11 @@ const isScreenGloballyBroadcasting = () => { return (!screenshareEntry ? false : !!screenshareEntry.screenshare.stream); }; +const useIsScreenGloballyBroadcasting = () => { + const { data } = useScreenshare(); + return Boolean(data && data[0] && data[0].stream); +}; + // A simplified, trackable version of isCameraContentBroadcasting that DOES NOT // account for the presenter's local sharing state. // It reflects the GLOBAL camera as content sharing state (akka-apps) @@ -118,6 +127,12 @@ const isCameraAsContentGloballyBroadcasting = () => { return (!cameraAsContentEntry ? false : !!cameraAsContentEntry.screenshare.stream); }; +const useIsCameraAsContentGloballyBroadcasting = () => { + const { data } = useScreenshare(); + + return Boolean(data && data[0] && data[0].contentType === CONTENT_TYPE_CAMERA && data[0].stream); +}; + // when the meeting information has been updated check to see if it was // screensharing. If it has changed either trigger a call to receive video // and display it, or end the call and hide the video @@ -161,6 +176,12 @@ const screenshareHasAudio = () => { return !!screenshareEntry.screenshare.hasAudio; }; +const useScreenshareHasAudio = () => { + const { data } = useScreenshare(); + + return Boolean(data && data[0] && data[0].hasAudio); +}; + const getBroadcastContentType = () => { const screenshareEntry = Screenshare.findOne({ meetindId: Auth.meedingID }, { fields: { 'screenshare.contentType': 1 } }); @@ -206,6 +227,14 @@ const shouldEnableVolumeControl = () => { return VOLUME_CONTROL_ENABLED && screenshareHasAudio(); } +const useShouldEnableVolumeControl = () => { + const SCREENSHARE_CONFIG = window.meetingClientSettings.public.kurento.screenshare; + const VOLUME_CONTROL_ENABLED = SCREENSHARE_CONFIG.enableVolumeControl; + const hasAudio = useScreenshareHasAudio(); + + return VOLUME_CONTROL_ENABLED && hasAudio; +}; + const attachLocalPreviewStream = (mediaElement) => { const { isTabletApp } = browserInfo; if (isTabletApp) { @@ -394,4 +423,7 @@ export { useCameraAsContentDeviceIdType, useIsSharing, useSharingContentType, + useIsScreenGloballyBroadcasting, + useIsCameraAsContentGloballyBroadcasting, + useShouldEnableVolumeControl, };