From 1d531e106b6dad1df20707b86237df59022c0324 Mon Sep 17 00:00:00 2001 From: JelianRadoev Date: Wed, 27 May 2020 13:22:41 +0300 Subject: [PATCH 1/5] NY-10492 Initial styling and jsx --- .../AudioVideoFullScreenView.js | 20 +++++++++++--- .../AudioVideoFullScreenView.styles.js | 27 ++++++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.js b/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.js index bc563a583..15d02cc70 100644 --- a/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.js +++ b/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.js @@ -125,7 +125,8 @@ class AudioVideoFullScreenView extends Component {
{this.renderControls()} - {this.renderFeeds()} + {this.renderMyFeed()} + {this.renderOtherFeeds()} {this.renderActiveSpeekers()}
@@ -139,7 +140,8 @@ class AudioVideoFullScreenView extends Component {
{this.renderControls()} - {this.renderFeeds()} + {this.renderMyFeed()} + {this.renderOtherFeeds()} {this.renderActiveSpeekers()}
@@ -166,12 +168,12 @@ class AudioVideoFullScreenView extends Component { return null; } - renderFeeds = () => { + renderMyFeed = () => { const { classes, t, setMemberMediaFeed, memberSelf, isAdmin } = this.props; return ( -
+
@@ -179,6 +181,16 @@ class AudioVideoFullScreenView extends Component { ); } + renderOtherFeeds = () => { + const { classes, t } = this.props; + return ( + +
+
+
+ ); + } + renderActiveSpeekers = () => { const { classes, callData } = this.props; const { activeSpeakers, p2p } = callData; diff --git a/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.styles.js b/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.styles.js index 63feb94b9..8b2c5e8aa 100644 --- a/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.styles.js +++ b/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.styles.js @@ -2,6 +2,17 @@ export default theme => ({ wrapp: { width: '100%', height: '100%', + scrollbarColor: `${theme.palette.themeColors.colors.scrollColor} transparent !important`, + '& *::-webkit-scrollbar': { + WebkitAppearance: 'none', + width: 12, + }, + '& *::-webkit-scrollbar-thumb': { + borderRadius: 10, + backgroundColor: theme.palette.themeColors.colors.scrollColor, + width: 12, + boxShadow: 'none', + }, }, fullScreenWrapp: { '& video': { @@ -31,7 +42,7 @@ export default theme => ({ left: '50%', transform: 'translateX(-50%)', }, - feedsWrapp: { + myFeedWrapp: { height: 114, width: 179, position: 'absolute', @@ -39,6 +50,16 @@ export default theme => ({ right: 49, zIndex: 2147483647, }, + otherFeedsWrapp: { + height: '60%', + width: 190, + position: 'absolute', + top: 140, + right: 49, + zIndex: 2147483647, + overflowX: 'hidden', + overflowY: 'scroll', + }, speakersWrapp: { position: 'absolute', top: 100, @@ -48,6 +69,10 @@ export default theme => ({ opacity: 0.8, cursor: 'pointer', }, + feed: { + height: 114, + width: 179, + }, infoSpeakerNames: { color: theme.palette.themeColors.audioVideo.infoLineSpeakersColor, display: 'flex', -- GitLab From 06ee5363c41e60d0f0c23b84e0a66f47d3149dde Mon Sep 17 00:00:00 2001 From: JelianRadoev Date: Wed, 27 May 2020 18:09:11 +0300 Subject: [PATCH 2/5] NY-10492 Show members' video feeds when a media is on full screen --- src/componets/AudioVideo/AudioVideo.js | 9 ++- .../AudioVideoFullScreenView.js | 58 ++++++++++++++++++- .../AudioVideoMembersView.js | 14 ++--- .../AudioVideoScreenSharing.js | 24 ++++++++ 4 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 src/componets/AudioVideo/AudioVideoScreenSharing/AudioVideoScreenSharing.js diff --git a/src/componets/AudioVideo/AudioVideo.js b/src/componets/AudioVideo/AudioVideo.js index 14cdac0d7..6c12ce2bf 100644 --- a/src/componets/AudioVideo/AudioVideo.js +++ b/src/componets/AudioVideo/AudioVideo.js @@ -21,7 +21,7 @@ import icVideo from 'Assets/img/icons/ic_menu_videocall_normal.svg'; import { KeyboardArrowUp } from '@material-ui/icons'; import Draggable from 'react-draggable'; import { MenuAppBar } from '../../containers'; -import { profileSelectors } from 'Resource/profile'; +import { profileSelectors } from '../../core/resource/profile'; import BrowserNotification from './BrowserNotification/BrowserNotification'; import ConfirmDialog from '../Modals/ConfirmDialog/ConfirmDialog'; import AudioVideoControls from './AudioVideoControls/AudioVideoControls'; @@ -70,6 +70,7 @@ const getUser = (state) => { minimized: audioVideoSelectors.isMinimized(state), getMemberById: (roomId, phoneId) => roomListSelectors.getMemberByPhoneId(state, roomId, phoneId), isUnreadInChat: conversationSelectors.getUnreadStatusForCall(state), + myPhoneId: profileSelectors.getPhoneId(state), }), dispatch => ({ actions: bindActionCreators({ openMessageModal: notificationActions.openMessageModal, @@ -738,7 +739,9 @@ class AudioVideo extends Component { } render() { - const { personalData, classes, t, callData, anonymousUser, roomToJoinName, minimized, isUnreadInChat } = this.props; + const { personalData, classes, t, callData, anonymousUser, + roomToJoinName, minimized, isUnreadInChat, myPhoneId, + } = this.props; const { isInFullscreen, fullScreenData } = this.state; const { members: membersAll, muted, speakerMuted, isAdmin, video, p2p, screenSharing } = callData; @@ -1077,7 +1080,7 @@ class AudioVideo extends Component { } {showFullScreenMode && - stylesFunc(theme); @@ -12,7 +13,10 @@ class AudioVideoFullScreenView extends Component { constructor(props) { super(props); - this.state = { showControls: false }; + this.state = { + showControls: false, + feedData: [], + }; this.controlsTimeout = null; this.fullScreenRef = createRef(); @@ -31,12 +35,25 @@ class AudioVideoFullScreenView extends Component { this.setFullScreen(); if (isVideo) { setMemberMediaFeed(this.fullScreenRef.current, isSelf, member); + this.buildFeedsOrder(true); } else if (isScreenSharing && this.ssRef && this.ssRef.current) { setRemoteScreenShareElement(this.ssRef.current); + this.buildFeedsOrder(true); } } } + componentDidUpdate(prevProps) { + const oldSpeekers = prevProps.callData.activeSpeakers ? prevProps.callData.activeSpeakers.join(', ') : ''; + const newSpeekers = this.props.callData.activeSpeakers ? this.props.callData.activeSpeakers.join(', ') : ''; + + if (oldSpeekers !== newSpeekers) { + console.log('[CHANGES-IN-SPEEKERS-OLD]', oldSpeekers); + console.log('[CHANGES-IN-SPEEKERS-NEW]', newSpeekers); + //this.buildFeedsOrder(false); + } + } + componentWillUnmount() { const { fullScreenData, memberSelf, disableFullScreenMode, setMemberMediaFeed, @@ -45,7 +62,7 @@ class AudioVideoFullScreenView extends Component { if (isVideo) { setMemberMediaFeed(null, isSelf, member); - setMemberMediaFeed(null, true, memberSelf) + setMemberMediaFeed(null, true, memberSelf); } this.removeEventListeners(); @@ -118,6 +135,27 @@ class AudioVideoFullScreenView extends Component { } } + buildFeedsOrder = (isInit) => { + const { callData, fullScreenData, myPhoneId } = this.props; + const { member } = fullScreenData; + const { members } = callData; + const result = []; + + if (isInit) { + members.forEach(m => { + const { video, phone_id } = m; + const fullScreenFeedId = member ? member.phone_id : ''; + if (video && phone_id !== myPhoneId && fullScreenFeedId !== phone_id) { + result.push(m); + } + }); + } else { + + } + + this.setState({ feedData: result }); + } + renderFullScreenVideo = () => { const { classes } = this.props; @@ -182,10 +220,23 @@ class AudioVideoFullScreenView extends Component { } renderOtherFeeds = () => { - const { classes, t } = this.props; + const { classes, fullScreenData, setRemoteScreenShareElement, callData } = this.props; + const { feedData } = this.state; + const { isVideo } = fullScreenData; + const { screenSharer } = callData; + return (
+ {isVideo && screenSharer && + + } + {feedData.map(d => { + return ( +
Ho
+ ); + })}
); @@ -236,6 +287,7 @@ AudioVideoFullScreenView.propTypes = { setRemoteScreenShareElement: PropTypes.func.isRequired, memberSelf: PropTypes.object.isRequired, isAdmin: PropTypes.bool, + myPhoneId: PropTypes.string.isRequired, }; export default withStyles(styles)(AudioVideoFullScreenView); diff --git a/src/componets/AudioVideo/AudioVideoMembersView/AudioVideoMembersView.js b/src/componets/AudioVideo/AudioVideoMembersView/AudioVideoMembersView.js index 6aa8c19eb..b396150d7 100644 --- a/src/componets/AudioVideo/AudioVideoMembersView/AudioVideoMembersView.js +++ b/src/componets/AudioVideo/AudioVideoMembersView/AudioVideoMembersView.js @@ -5,6 +5,7 @@ import PropTypes from 'prop-types'; import stylesFunc from './AudioVideoMembersView.styles'; import { isMobile } from 'react-device-detect'; import AudioVideoMemberWithMenu from '../AudioVideoMember/AudioVideoMemberWithMenu'; +import AudioVideoScreenSharing from '../AudioVideoScreenSharing/AudioVideoScreenSharing'; import icFullScreen from "Assets/img/icons/ic_user_full_screen.svg"; import { withTranslation } from 'react-i18next'; @@ -22,12 +23,6 @@ class AudioVideoMembersView extends PureComponent { } }; - setRemoteScreenShareElement = (el) => { - if (this.props.callbacks.setRemoteScreenShareElement) { - this.props.callbacks.setRemoteScreenShareElement(el); - } - }; - render() { const { t, classes, data } = this.props; const { callData, maxSteps, fullScreenMember, memberSelf, @@ -71,10 +66,9 @@ class AudioVideoMembersView extends PureComponent { onClick={this.handleBack} disabled={activeMembersStep === 0}> - {remoteScreenSharing && -
-
+ {remoteScreenSharing && this.props.callbacks.setRemoteScreenShareElement && + } {!fullScreenMember && !remoteScreenSharing &&
diff --git a/src/componets/AudioVideo/AudioVideoScreenSharing/AudioVideoScreenSharing.js b/src/componets/AudioVideo/AudioVideoScreenSharing/AudioVideoScreenSharing.js new file mode 100644 index 000000000..2ed26563b --- /dev/null +++ b/src/componets/AudioVideo/AudioVideoScreenSharing/AudioVideoScreenSharing.js @@ -0,0 +1,24 @@ +import React, { useRef, useEffect } from 'react'; +import PropTypes from 'prop-types'; + +const AudioVideoScreenSharing = (props) => { + const sharingRef = useRef(null); + const { classWrap, setRemoteScreenShareElement } = props; + + useEffect(() => { + setRemoteScreenShareElement(sharingRef.current); + }, []); + + return ( +
+
+ ); +}; + +AudioVideoScreenSharing.propTypes = { + setRemoteScreenShareElement: PropTypes.func.isRequired, + classWrap: PropTypes.string.isRequired, +}; + +export default AudioVideoScreenSharing; -- GitLab From 7d01aa50743e5d926de500c9d42ef9108ad58e56 Mon Sep 17 00:00:00 2001 From: JelianRadoev Date: Thu, 28 May 2020 14:54:17 +0300 Subject: [PATCH 3/5] NY-10492 fullscreen video feeds partisl commit --- src/componets/AudioVideo/AudioVideo.js | 6 +- .../AudioVideoFullScreenView.js | 60 +++++++++++++------ .../audioVideo/modules/AudioVideo.module.js | 20 +++++++ 3 files changed, 65 insertions(+), 21 deletions(-) diff --git a/src/componets/AudioVideo/AudioVideo.js b/src/componets/AudioVideo/AudioVideo.js index 6c12ce2bf..4b59794b9 100644 --- a/src/componets/AudioVideo/AudioVideo.js +++ b/src/componets/AudioVideo/AudioVideo.js @@ -70,7 +70,7 @@ const getUser = (state) => { minimized: audioVideoSelectors.isMinimized(state), getMemberById: (roomId, phoneId) => roomListSelectors.getMemberByPhoneId(state, roomId, phoneId), isUnreadInChat: conversationSelectors.getUnreadStatusForCall(state), - myPhoneId: profileSelectors.getPhoneId(state), + membersWithVideo: audioVideoSelectors.getOtherMembersWithVideo(state, profileSelectors.getPhoneId(state)), }), dispatch => ({ actions: bindActionCreators({ openMessageModal: notificationActions.openMessageModal, @@ -740,7 +740,7 @@ class AudioVideo extends Component { render() { const { personalData, classes, t, callData, anonymousUser, - roomToJoinName, minimized, isUnreadInChat, myPhoneId, + roomToJoinName, minimized, isUnreadInChat, membersWithVideo, } = this.props; const { isInFullscreen, fullScreenData } = this.state; const { members: membersAll, muted, speakerMuted, isAdmin, video, p2p, screenSharing } = callData; @@ -1080,7 +1080,7 @@ class AudioVideo extends Component { } {showFullScreenMode && - { - const { callData, fullScreenData, myPhoneId } = this.props; + buildFeedsOrder = (isInit, isActiveSpeekers, isMembersWithVideo) => { + const { callData, fullScreenData, membersWithVideo } = this.props; + const { feedData } = this.state; const { member } = fullScreenData; - const { members } = callData; - const result = []; + const { activeSpeakers } = callData; if (isInit) { - members.forEach(m => { - const { video, phone_id } = m; + const result = []; + membersWithVideo.forEach(m => { const fullScreenFeedId = member ? member.phone_id : ''; - if (video && phone_id !== myPhoneId && fullScreenFeedId !== phone_id) { + if (fullScreenFeedId !== m.phone_id) { result.push(m); } }); - } else { - + this.setState({ feedData: result }); + } else if (isActiveSpeekers) { + const newSpeakers = activeSpeakers ? activeSpeakers : []; + const newTopSpeakerName = newSpeakers[0]; + if (newTopSpeakerName) { + const currentTopSpeaker = feedData[0]; + if (currentTopSpeaker && currentTopSpeaker.displayName !== newTopSpeakerName) { + const newTopSpeaker = membersWithVideo.find(m => m.displayName === newTopSpeakerName); + if (newTopSpeaker) { + const newFeedData = feedData.filter(d => d.displayName !== newTopSpeakerName); + newFeedData.unshift(newTopSpeaker); + this.setState({ feedData: newFeedData }); + } + } + } + } else if (isMembersWithVideo) { + } - - this.setState({ feedData: result }); } renderFullScreenVideo = () => { @@ -220,7 +241,7 @@ class AudioVideoFullScreenView extends Component { } renderOtherFeeds = () => { - const { classes, fullScreenData, setRemoteScreenShareElement, callData } = this.props; + const { classes, fullScreenData, setRemoteScreenShareElement, callData, t, isAdmin } = this.props; const { feedData } = this.state; const { isVideo } = fullScreenData; const { screenSharer } = callData; @@ -232,9 +253,12 @@ class AudioVideoFullScreenView extends Component { } - {feedData.map(d => { + {feedData.map(data => { return ( -
Ho
+
+ +
); })}
@@ -287,7 +311,7 @@ AudioVideoFullScreenView.propTypes = { setRemoteScreenShareElement: PropTypes.func.isRequired, memberSelf: PropTypes.object.isRequired, isAdmin: PropTypes.bool, - myPhoneId: PropTypes.string.isRequired, + membersWithVideo: PropTypes.array.isRequired, }; export default withStyles(styles)(AudioVideoFullScreenView); diff --git a/src/core/resource/audioVideo/modules/AudioVideo.module.js b/src/core/resource/audioVideo/modules/AudioVideo.module.js index 1ab1c7889..a55a6cad4 100644 --- a/src/core/resource/audioVideo/modules/AudioVideo.module.js +++ b/src/core/resource/audioVideo/modules/AudioVideo.module.js @@ -311,6 +311,25 @@ const isInFullScreenCall = (state) => { return !instance.minimizeRequested; }; +const getOtherMembersWithVideo = (state, myPhoneId) => { + const result = []; + const instance = getInstance(state); + + if (!instance || !instance.conferenceId) { + return result; + } + + if (instance.members && Array.isArray(instance.members)) { + instance.members.forEach(m => { + if (m.video && m.phone_id !== myPhoneId) { + result.push(m); + } + }); + } + + return result; +}; + const audioVideoActions = { incomingCall, endCall, @@ -352,6 +371,7 @@ const audioVideoSelectors = { isMinimized, getAllActiveCallsRaw, isInFullScreenCall, + getOtherMembersWithVideo, }; export default audioVideo; -- GitLab From 076cc4d56f9a100a2042a97970c4c02189849609 Mon Sep 17 00:00:00 2001 From: JelianRadoev Date: Fri, 29 May 2020 18:07:29 +0300 Subject: [PATCH 4/5] NY-10492 Show video feeds and screen sharing in fullscreen mode --- .../AudioVideoFullScreenView.js | 131 ++++++++++-------- .../AudioVideoFullScreenView.styles.js | 21 +-- .../AudioVideoMember/AudioVideoMember.js | 12 +- 3 files changed, 94 insertions(+), 70 deletions(-) diff --git a/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.js b/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.js index 115f14a77..4d5f69e5f 100644 --- a/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.js +++ b/src/componets/AudioVideo/AudioVideoFullScreenView/AudioVideoFullScreenView.js @@ -6,6 +6,7 @@ import Draggable from 'react-draggable'; import AudioVideoMember from '../AudioVideoMember/AudioVideoMember'; import AudioVideoScreenSharing from '../AudioVideoScreenSharing/AudioVideoScreenSharing'; import constants from '../../../core/configs/Constants.config'; +import differenceBy from 'lodash/differenceBy'; const styles = theme => stylesFunc(theme); @@ -35,10 +36,10 @@ class AudioVideoFullScreenView extends Component { this.setFullScreen(); if (isVideo) { setMemberMediaFeed(this.fullScreenRef.current, isSelf, member); - this.buildFeedsOrder(true, false, false); + this.orderFeedsInit(); } else if (isScreenSharing && this.ssRef && this.ssRef.current) { setRemoteScreenShareElement(this.ssRef.current); - this.buildFeedsOrder(true, false, false); + this.orderFeedsInit(); } } } @@ -50,15 +51,11 @@ class AudioVideoFullScreenView extends Component { const newLen = this.props.membersWithVideo.length; if (oldSpeekers !== newSpeekers) { - console.log('[CHANGES-IN-SPEEKERS-OLD]', oldSpeekers); - console.log('[CHANGES-IN-SPEEKERS-NEW]', newSpeekers); - //this.buildFeedsOrder(false, true, false); + this.reorderFeedsChangedActiveSpeakers(); } if (prevLen !== newLen) { - console.log('[CHANGES-IN-MEMBERS-WITH-VIDEO-OLD]', prevLen); - console.log('[CHANGES-IN-MEMBERS-WITH-VIDEO-NEW]', newLen); - //this.buildFeedsOrder(false, false, true); + this.reorderFeedsChangedMembers(prevProps.membersWithVideo, this.props.membersWithVideo, prevLen, newLen); } } @@ -143,37 +140,58 @@ class AudioVideoFullScreenView extends Component { } } - buildFeedsOrder = (isInit, isActiveSpeekers, isMembersWithVideo) => { + orderFeedsInit = () => { + const { fullScreenData, membersWithVideo } = this.props; + const { member } = fullScreenData; + const memberOnFullscreenId = member ? member.phone_id : ''; + + this.setState({ feedData: membersWithVideo.filter(m => m.phone_id !== memberOnFullscreenId) }); + } + + reorderFeedsChangedActiveSpeakers = () => { const { callData, fullScreenData, membersWithVideo } = this.props; const { feedData } = this.state; const { member } = fullScreenData; const { activeSpeakers } = callData; - - if (isInit) { - const result = []; - membersWithVideo.forEach(m => { - const fullScreenFeedId = member ? member.phone_id : ''; - if (fullScreenFeedId !== m.phone_id) { - result.push(m); - } - }); - this.setState({ feedData: result }); - } else if (isActiveSpeekers) { - const newSpeakers = activeSpeakers ? activeSpeakers : []; - const newTopSpeakerName = newSpeakers[0]; - if (newTopSpeakerName) { - const currentTopSpeaker = feedData[0]; - if (currentTopSpeaker && currentTopSpeaker.displayName !== newTopSpeakerName) { - const newTopSpeaker = membersWithVideo.find(m => m.displayName === newTopSpeakerName); - if (newTopSpeaker) { - const newFeedData = feedData.filter(d => d.displayName !== newTopSpeakerName); - newFeedData.unshift(newTopSpeaker); - this.setState({ feedData: newFeedData }); - } + const newSpeakers = activeSpeakers ? activeSpeakers : []; + const newTopSpeakerName = newSpeakers[newSpeakers.length - 1]; + const memberOnFullscreenName = member ? member.displayName : ''; + + if (newTopSpeakerName) { + const currentTopSpeaker = feedData[0]; + if (currentTopSpeaker && currentTopSpeaker.displayName !== newTopSpeakerName && memberOnFullscreenName !== newTopSpeakerName) { + const newTopSpeaker = membersWithVideo.find(m => m.displayName === newTopSpeakerName); + if (newTopSpeaker) { + const newFeedData = [newTopSpeaker, ...feedData.filter(d => d.displayName !== newTopSpeakerName)]; + this.setState({ feedData: newFeedData }); } } - } else if (isMembersWithVideo) { - + } + } + + /** + * @param {Array} oldList + * @param {Array} newList + * @param {Number} prevLen + * @param {Number} newLen + * @returns void + */ + reorderFeedsChangedMembers = (oldList, newList, prevLen, newLen) => { + const { member } = this.props; + const memberOnFullscreenId = member ? member.phone_id : ''; + + if (newLen > prevLen) { + this.setState({ + feedData: [ + ...differenceBy( + newList.filter(d => d.phone_id !== memberOnFullscreenId), + oldList, + 'phone_id', + ), + ...oldList], + }); + } else { + this.orderFeedsInit(); } } @@ -186,7 +204,7 @@ class AudioVideoFullScreenView extends Component { {this.renderControls()} {this.renderMyFeed()} {this.renderOtherFeeds()} - {this.renderActiveSpeekers()} + {/* {this.renderActiveSpeekers()} */}
) @@ -201,7 +219,7 @@ class AudioVideoFullScreenView extends Component { {this.renderControls()} {this.renderMyFeed()} {this.renderOtherFeeds()} - {this.renderActiveSpeekers()} + {/* {this.renderActiveSpeekers()} */}