Merge pull request #20329 from JoVictorNunes/remove-screenshare-tracker

refactor(screenshare): replace `Tracker.Dependency` with `makeVar`
This commit is contained in:
Ramón Souza 2024-06-03 09:33:08 -03:00 committed by GitHub
commit 018a170251
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 155 additions and 86 deletions

View File

@ -8,7 +8,7 @@ import Auth from '/imports/ui/services/auth';
import ActionsBar from './component';
import { layoutSelectOutput, layoutDispatch } from '../layout/context';
import { isExternalVideoEnabled, isPollingEnabled, isPresentationEnabled, isTimerFeatureEnabled } from '/imports/ui/services/features';
import { isScreenBroadcasting, isCameraAsContentBroadcasting } from '/imports/ui/components/screenshare/service';
import { isScreenBroadcasting, isCameraAsContentBroadcasting, useIsSharing, useSharingContentType } from '/imports/ui/components/screenshare/service';
import { PluginsContext } from '/imports/ui/components/components-data/plugin-context/context';
import {
CURRENT_PRESENTATION_PAGE_SUBSCRIPTION,
@ -105,13 +105,29 @@ const isReactionsButtonEnabled = () => {
return USER_REACTIONS_ENABLED && REACTIONS_BUTTON_ENABLED;
};
export default withTracker(() => ({
const ActionsBarTracker = withTracker(({ isSharing, sharingContentType }) => ({
enableVideo: getFromUserSettings('bbb_enable_video', window.meetingClientSettings.public.kurento.enableVideo),
setPresentationIsOpen: MediaService.setPresentationIsOpen,
hasScreenshare: isScreenBroadcasting(),
hasCameraAsContent: isCameraAsContentBroadcasting(),
hasScreenshare: isScreenBroadcasting(isSharing, sharingContentType),
hasCameraAsContent: isCameraAsContentBroadcasting(isSharing, sharingContentType),
isMeteorConnected: Meteor.status().connected,
isPollingEnabled: isPollingEnabled() && isPresentationEnabled(),
isReactionsButtonEnabled: isReactionsButtonEnabled(),
allowExternalVideo: isExternalVideoEnabled(),
}))(injectIntl(ActionsBarContainer));
// TODO: Remove this
// Temporary component until we remove all trackers
export default (props) => {
const isSharing = useIsSharing();
const sharingContentType = useSharingContentType();
return (
<ActionsBarTracker
{...{
...props,
isSharing,
sharingContentType,
}}
/>
);
};

View File

@ -2,7 +2,11 @@ import React from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import ScreenshareButton from './component';
import { isScreenSharingEnabled } from '/imports/ui/services/features';
import { isScreenBroadcasting } from '/imports/ui/components/screenshare/service';
import {
isScreenBroadcasting,
useIsSharing,
useSharingContentType,
} from '/imports/ui/components/screenshare/service';
import useSettings from '/imports/ui/services/settings/hooks/useSettings';
import { SETTINGS } from '/imports/ui/services/settings/enums';
@ -21,7 +25,23 @@ const ScreenshareButtonContainer = (props) => {
* isMeteorConnected,
* screenshareDataSavingSetting,
*/
export default withTracker(() => ({
isScreenBroadcasting: isScreenBroadcasting(),
const ScreenshareButtonContainerTracker = withTracker(({ isSharing, sharingContentType }) => ({
isScreenBroadcasting: isScreenBroadcasting(isSharing, sharingContentType),
enabled: isScreenSharingEnabled(),
}))(ScreenshareButtonContainer);
// TODO: Remove this
// Temporary component until we remove all trackers
export default (props) => {
const isSharing = useIsSharing();
const sharingContentType = useSharingContentType();
return (
<ScreenshareButtonContainerTracker
{...{
...props,
isSharing,
sharingContentType,
}}
/>
);
};

View File

@ -31,6 +31,7 @@ import useToggleVoice from '../audio/audio-graphql/hooks/useToggleVoice';
import useUserChangedLocalSettings from '../../services/settings/hooks/useUserChangedLocalSettings';
import { PINNED_PAD_SUBSCRIPTION } from '../notes/queries';
import VideoStreamsState from '../video-provider/video-provider-graphql/state';
import { useIsSharing, useSharingContentType } from '../screenshare/service';
import useSettings from '../../services/settings/hooks/useSettings';
import { SETTINGS } from '../../services/settings/enums';
@ -260,8 +261,12 @@ const currentUserEmoji = (currentUser) => (currentUser
}
);
export default withTracker((props) => {
const { viewScreenshare } = props;
const AppTracker = withTracker((props) => {
const {
viewScreenshare,
isScreenSharing,
screenSharingContentType,
} = props;
const currentUser = Users.findOne(
{ userId: Auth.userID },
{
@ -288,7 +293,11 @@ export default withTracker((props) => {
const meetingLayoutUpdatedAt = new Date(layout.updatedAt).getTime();
const meetingPresentationIsOpen = !layout.presentationMinimized;
const shouldShowScreenshare = MediaService.shouldShowScreenshare(viewScreenshare);
const shouldShowScreenshare = MediaService.shouldShowScreenshare(
viewScreenshare,
isScreenSharing,
screenSharingContentType,
);
let customStyleUrl = getFromUserSettings('bbb_custom_style_url', false);
const CUSTOM_STYLE_URL = window.meetingClientSettings.public.app.customStyleUrl;
@ -332,3 +341,19 @@ export default withTracker((props) => {
User: currentUser,
};
})(AppContainer);
// TODO: Remove this
// Temporary component until we remove all trackers
export default (props) => {
const isScreenSharing = useIsSharing();
const screenSharingContentType = useSharingContentType();
return (
<AppTracker
{...{
...props,
isScreenSharing,
screenSharingContentType,
}}
/>
);
};

View File

@ -10,10 +10,13 @@ function shouldShowWhiteboard() {
return true;
}
function shouldShowScreenshare(viewScreenshare) {
function shouldShowScreenshare(viewScreenshare, active, sharingContentType) {
return (isScreenSharingEnabled() || isCameraAsContentEnabled())
&& (viewScreenshare || UserService.isUserPresenter())
&& (isScreenBroadcasting() || isCameraAsContentBroadcasting());
&& (
isScreenBroadcasting(active, sharingContentType)
|| isCameraAsContentBroadcasting(active, sharingContentType)
);
}
function shouldShowOverlay() {

View File

@ -19,6 +19,8 @@ import { EXTERNAL_VIDEO_STOP } from '/imports/ui/components/external-video-playe
import {
screenshareHasEnded,
isScreenBroadcasting,
useIsSharing,
useSharingContentType,
} from '/imports/ui/components/screenshare/service';
const intlMessages = defineMessages({
@ -193,11 +195,13 @@ const NotesContainerGraphql: React.FC<NotesContainerGraphqlProps> = (props) => {
&& pinnedPadData.sharedNotes[0]?.sharedNotesExtId === NOTES_CONFIG.id;
const [stopExternalVideoShare] = useMutation(EXTERNAL_VIDEO_STOP);
const isSharingScreen = useIsSharing();
const sharingContentType = useSharingContentType();
const handlePinSharedNotes = (pinned: boolean) => {
if (pinned) {
stopExternalVideoShare();
if (isScreenBroadcasting()) screenshareHasEnded();
if (isScreenBroadcasting(isSharingScreen, sharingContentType)) screenshareHasEnded();
}
pinSharedNotes({ variables: { pinned } });
};

View File

@ -530,6 +530,7 @@ class ScreenshareComponent extends React.Component {
|| (isPresenter && !isGloballyBroadcasting)
|| (!mediaFlowing && loaded && isGloballyBroadcasting);
const display = (width > 0 && height > 0) ? 'inherit' : 'none';
const Settings = getSettingsSingletonInstance();
const { animations } = Settings.application;

View File

@ -1,6 +1,7 @@
import React from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import { useMutation, useSubscription } from '@apollo/client';
import { defineMessages } from 'react-intl';
import {
getSharingContentType,
getBroadcastContentType,
@ -9,13 +10,14 @@ import {
isScreenBroadcasting,
isCameraAsContentBroadcasting,
shouldEnableVolumeControl,
useIsSharing,
useSharingContentType,
} from './service';
import ScreenshareComponent from './component';
import { layoutSelect, layoutSelectOutput, layoutDispatch } from '../layout/context';
import getFromUserSettings from '/imports/ui/services/users-settings';
import AudioService from '/imports/ui/components/audio/service';
import MediaService from '/imports/ui/components/media/service';
import { defineMessages } from 'react-intl';
import { EXTERNAL_VIDEO_STOP } from '../external-video-player/mutations';
import { PINNED_PAD_SUBSCRIPTION } from '../notes/queries';
@ -51,7 +53,7 @@ const screenshareIntlMessages = defineMessages({
endedDueToDataSaving: {
id: 'app.media.screenshare.endDueToDataSaving',
description: 'toast to show when a screenshare has ended by changing data savings option',
}
},
});
const cameraAsContentIntlMessages = defineMessages({
@ -110,27 +112,30 @@ const ScreenshareContainer = (props) => {
const info = {
screenshare: {
icon: "desktop",
icon: 'desktop',
locales: screenshareIntlMessages,
startPreviewSizeBig: false,
showSwitchPreviewSizeButton: true,
},
camera: {
icon: "video",
icon: 'video',
locales: cameraAsContentIntlMessages,
startPreviewSizeBig: true,
showSwitchPreviewSizeButton: false,
},
};
const getContentType = () => {
return isPresenter ? getSharingContentType() : getBroadcastContentType();
}
const getContentType = () => (isPresenter ? getSharingContentType() : getBroadcastContentType());
const contentTypeInfo = info[getContentType()];
const defaultInfo = info.camera;
const selectedInfo = contentTypeInfo ? contentTypeInfo : defaultInfo;
const selectedInfo = contentTypeInfo || defaultInfo;
const isSharing = useIsSharing();
const sharingContentType = useSharingContentType();
if (isScreenBroadcasting() || isCameraAsContentBroadcasting()) {
if (
isScreenBroadcasting(isSharing, sharingContentType)
|| isCameraAsContentBroadcasting(isSharing, sharingContentType)
) {
return (
<ScreenshareComponent
{

View File

@ -1,3 +1,4 @@
import { makeVar, useReactiveVar } from '@apollo/client';
import Screenshare from '/imports/api/screenshare';
import KurentoBridge from '/imports/api/screenshare/client/bridge';
import BridgeService from '/imports/api/screenshare/client/bridge/service';
@ -15,58 +16,38 @@ const DEFAULT_SCREENSHARE_STATS_TYPES = [
'inbound-rtp',
];
const CONTENT_TYPE_CAMERA = "camera";
const CONTENT_TYPE_SCREENSHARE = "screenshare";
const CONTENT_TYPE_CAMERA = 'camera';
const CONTENT_TYPE_SCREENSHARE = 'screenshare';
let _isSharingScreen = false;
const _isSharingDep = {
value: false,
tracker: new Tracker.Dependency(),
};
const isSharingVar = makeVar(false);
const sharingContentTypeVar = makeVar(false);
const cameraAsContentDeviceIdTypeVar = makeVar('');
const _sharingContentTypeDep = {
value: false,
tracker: new Tracker.Dependency(),
};
const useIsSharing = () => useReactiveVar(isSharingVar);
const useSharingContentType = () => useReactiveVar(sharingContentTypeVar);
const useCameraAsContentDeviceIdType = () => useReactiveVar(cameraAsContentDeviceIdTypeVar);
const _cameraAsContentDeviceIdTypeDep = {
value: '',
tracker: new Tracker.Dependency(),
};
const isSharing = () => isSharingVar();
const isSharing = () => {
_isSharingDep.tracker.depend();
return _isSharingDep.value;
};
const setIsSharing = (isSharing) => {
if (_isSharingDep.value !== isSharing) {
_isSharingDep.value = isSharing;
_isSharingDep.tracker.changed();
const setIsSharing = (sharing) => {
if (isSharing() !== sharing) {
isSharingVar(sharing);
}
};
const getSharingContentType = () => sharingContentTypeVar();
const setSharingContentType = (contentType) => {
if (_sharingContentTypeDep.value !== contentType) {
_sharingContentTypeDep.value = contentType;
_sharingContentTypeDep.tracker.changed();
if (getSharingContentType() !== contentType) {
sharingContentTypeVar(contentType);
}
}
const getSharingContentType = () => {
_sharingContentTypeDep.tracker.depend();
return _sharingContentTypeDep.value;
};
const getCameraAsContentDeviceId = () => {
_cameraAsContentDeviceIdTypeDep.tracker.depend();
return _cameraAsContentDeviceIdTypeDep.value;
};
const getCameraAsContentDeviceId = () => cameraAsContentDeviceIdTypeVar();
const setCameraAsContentDeviceId = (deviceId) => {
if (_cameraAsContentDeviceIdTypeDep.value !== deviceId) {
_cameraAsContentDeviceIdTypeDep.value = deviceId;
_cameraAsContentDeviceIdTypeDep.tracker.changed();
if (getCameraAsContentDeviceId() !== deviceId) {
cameraAsContentDeviceIdTypeVar(deviceId);
}
};
@ -108,10 +89,10 @@ const _trackStreamTermination = (stream, handler) => {
};
const _isStreamActive = (stream) => {
const tracksAreActive = !stream.getTracks().some(track => track.readyState === 'ended');
const tracksAreActive = !stream.getTracks().some((track) => track.readyState === 'ended');
return tracksAreActive && stream.active;
}
};
const _handleStreamTermination = () => {
screenshareHasEnded();
@ -121,28 +102,28 @@ const _handleStreamTermination = () => {
// account for the presenter's local sharing state.
// It reflects the GLOBAL screen sharing state (akka-apps)
const isScreenGloballyBroadcasting = () => {
const screenshareEntry = Screenshare.findOne({ meetingId: Auth.meetingID, "screenshare.contentType": CONTENT_TYPE_SCREENSHARE },
const screenshareEntry = Screenshare.findOne({ meetingId: Auth.meetingID, 'screenshare.contentType': CONTENT_TYPE_SCREENSHARE },
{ fields: { 'screenshare.stream': 1 } });
return (!screenshareEntry ? false : !!screenshareEntry.screenshare.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)
const isCameraAsContentGloballyBroadcasting = () => {
const cameraAsContentEntry = Screenshare.findOne({ meetingId: Auth.meetingID, "screenshare.contentType": CONTENT_TYPE_CAMERA },
const cameraAsContentEntry = Screenshare.findOne({ meetingId: Auth.meetingID, 'screenshare.contentType': CONTENT_TYPE_CAMERA },
{ fields: { 'screenshare.stream': 1 } });
return (!cameraAsContentEntry ? false : !!cameraAsContentEntry.screenshare.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
const isScreenBroadcasting = () => {
const sharing = isSharing() && getSharingContentType() == CONTENT_TYPE_SCREENSHARE;
const screenshareEntry = Screenshare.findOne({ meetingId: Auth.meetingID, "screenshare.contentType": CONTENT_TYPE_SCREENSHARE },
const isScreenBroadcasting = (active, sharingContentType) => {
const sharing = active && sharingContentType === CONTENT_TYPE_SCREENSHARE;
const screenshareEntry = Screenshare.findOne({ meetingId: Auth.meetingID, 'screenshare.contentType': CONTENT_TYPE_SCREENSHARE },
{ fields: { 'screenshare.stream': 1 } });
const screenIsShared = !screenshareEntry ? false : !!screenshareEntry.screenshare.stream;
@ -156,9 +137,9 @@ const isScreenBroadcasting = () => {
// when the meeting information has been updated check to see if it was
// sharing camera as content. If it has changed either trigger a call to receive video
// and display it, or end the call and hide the video
const isCameraAsContentBroadcasting = () => {
const sharing = isSharing() && getSharingContentType() === CONTENT_TYPE_CAMERA;
const screenshareEntry = Screenshare.findOne({ meetingId: Auth.meetingID, "screenshare.contentType": CONTENT_TYPE_CAMERA },
const isCameraAsContentBroadcasting = (active, sharingContentType) => {
const sharing = active && sharingContentType === CONTENT_TYPE_CAMERA;
const screenshareEntry = Screenshare.findOne({ meetingId: Auth.meetingID, 'screenshare.contentType': CONTENT_TYPE_CAMERA },
{ fields: { 'screenshare.stream': 1 } });
const cameraAsContentIsShared = !screenshareEntry ? false : !!screenshareEntry.screenshare.stream;
@ -178,11 +159,11 @@ const screenshareHasAudio = () => {
}
return !!screenshareEntry.screenshare.hasAudio;
}
};
const getBroadcastContentType = () => {
const screenshareEntry = Screenshare.findOne({meetindId: Auth.meedingID},
{ fields: { 'screenshare.contentType': 1} });
const screenshareEntry = Screenshare.findOne({ meetindId: Auth.meedingID },
{ fields: { 'screenshare.contentType': 1 } });
if (!screenshareEntry) {
// defaults to contentType: "camera"
@ -190,10 +171,10 @@ const getBroadcastContentType = () => {
}
return screenshareEntry.screenshare.contentType;
}
};
const screenshareHasEnded = () => {
if (isSharing()) {
if (isSharingVar()) {
setIsSharing(false);
}
if (getSharingContentType() === CONTENT_TYPE_CAMERA) {
@ -203,9 +184,7 @@ const screenshareHasEnded = () => {
KurentoBridge.stop();
};
const getMediaElement = () => {
return document.getElementById(SCREENSHARE_MEDIA_ELEMENT_NAME);
}
const getMediaElement = () => document.getElementById(SCREENSHARE_MEDIA_ELEMENT_NAME);
const getMediaElementDimensions = () => {
const element = getMediaElement();
@ -228,7 +207,7 @@ const shouldEnableVolumeControl = () => {
}
const attachLocalPreviewStream = (mediaElement) => {
const {isTabletApp} = browserInfo;
const { isTabletApp } = browserInfo;
if (isTabletApp) {
// We don't show preview for mobile app, as the stream is only available in native code
return;
@ -279,7 +258,7 @@ const screenshareHasStarted = (isPresenter, options = {}) => {
};
const shareScreen = async (stopWatching, isPresenter, onFail, options = {}) => {
if (isCameraAsContentBroadcasting()) {
if (isCameraAsContentBroadcasting(isSharingVar(), sharingContentTypeVar())) {
screenshareHasEnded();
}
@ -412,4 +391,7 @@ export {
setCameraAsContentDeviceId,
getCameraAsContentDeviceId,
setOutputDeviceId,
useCameraAsContentDeviceIdType,
useIsSharing,
useSharingContentType,
};

View File

@ -4,7 +4,7 @@ import { withTracker } from 'meteor/react-meteor-data';
import Service from './service';
import VideoPreview from './component';
import VideoService from '../video-provider/video-provider-graphql/service';
import ScreenShareService from '/imports/ui/components/screenshare/service';
import * as ScreenShareService from '/imports/ui/components/screenshare/service';
import logger from '/imports/startup/client/logger';
import { SCREENSHARING_ERRORS } from '/imports/api/screenshare/client/bridge/errors';
import { EXTERNAL_VIDEO_STOP } from '../external-video-player/mutations';
@ -78,7 +78,7 @@ const VideoPreviewContainer = (props) => {
);
};
export default withTracker(({ setIsOpen, callbackToClose }) => ({
const VideoPreviewContainerTracker = withTracker(({ setIsOpen, callbackToClose }) => ({
startSharing: (deviceId) => {
callbackToClose();
setIsOpen(false);
@ -89,10 +89,23 @@ export default withTracker(({ setIsOpen, callbackToClose }) => ({
setIsOpen(false);
ScreenShareService.screenshareHasEnded();
},
cameraAsContentDeviceId: ScreenShareService.getCameraAsContentDeviceId(),
closeModal: () => {
callbackToClose();
setIsOpen(false);
},
webcamDeviceId: Service.webcamDeviceId(),
}))(VideoPreviewContainer);
// TODO: Remove this
// Temporary component until we remove all trackers
export default (props) => {
const cameraAsContentDeviceId = ScreenShareService.useCameraAsContentDeviceIdType();
return (
<VideoPreviewContainerTracker
{...{
...props,
cameraAsContentDeviceId,
}}
/>
);
};