diff --git a/Project/src/App.css b/Project/src/App.css index 9c4691c..f8d8a6c 100644 --- a/Project/src/App.css +++ b/Project/src/App.css @@ -393,6 +393,7 @@ div.ms-Checkbox>input[type="checkbox"]+label.ms-Checkbox-label>span.ms-Checkbox- display: flex; padding-bottom: 25px; flex-flow: row wrap; + justify-content: center; } @media screen and (max-width: 1024px){ @@ -401,11 +402,31 @@ div.ms-Checkbox>input[type="checkbox"]+label.ms-Checkbox-label>span.ms-Checkbox- } } -.pptLive { - display: block; - padding: 2vh 2vw; - width: 100%; - height: 50vh; +.stream-container.pinned { + order: 0; + flex: 0 100% !important; +} + +.stream-container { + order: 1; + display: none; + position: relative; + flex: 0 20%; +} + +.stream-container.stream-count-1, +.stream-container.stream-count-2, +.stream-container.stream-count-3, +.stream-container.stream-count-4 { + flex: 0 49%; +} + +.stream-container.stream-count-5, +.stream-container.stream-count-6, +.stream-container.stream-count-7, +.stream-container.stream-count-8, +.stream-container.stream-count-9 { + flex: 0 33%; } .video-title { @@ -473,6 +494,13 @@ div.ms-Checkbox>input[type="checkbox"]+label.ms-Checkbox-label>span.ms-Checkbox- transform: translate(-50%, -50%); } +.pptLive { + display: block; + padding: 2vh 2vw; + width: 100%; + height: 50vh; +} + .icon-text-large { vertical-align: middle; font-size: large; @@ -1111,33 +1139,6 @@ div.volumeVisualizer::before { padding: 8px; } -.stream-container { - order: 1; - display: none; - position: relative; - flex: 1 20%; -} - -.stream-container.stream-count-1, -.stream-container.stream-count-2, -.stream-container.stream-count-3, -.stream-container.stream-count-4 { - flex: 1 49%; -} - -.stream-container.stream-count-5, -.stream-container.stream-count-6, -.stream-container.stream-count-7, -.stream-container.stream-count-8, -.stream-container.stream-count-9 { - flex: 1 33%; -} - -.stream-container[id*="ScreenSharing"] { - order: 0; - grid-column: span 3 !important; -} - .scrollable-captions-container { overflow: auto; max-height: 300px; diff --git a/Project/src/MakeCall/CallCard.js b/Project/src/MakeCall/CallCard.js index 37a6f62..4ac49e0 100644 --- a/Project/src/MakeCall/CallCard.js +++ b/Project/src/MakeCall/CallCard.js @@ -128,7 +128,8 @@ export default class CallCard extends React.Component { meetingMediaAccess: { isAudioPermitted: meetingMediaAccess?.isAudioPermitted, isVideoPermitted: meetingMediaAccess?.isVideoPermitted, - } + }, + showPin2VideosList: false, }; this.selectedRemoteParticipants = new Set(); this.dataChannelRef = React.createRef(); @@ -1387,6 +1388,27 @@ export default class CallCard extends React.Component { this.call.setConstraints(constraints); } + handleVideoPin = (streamTuple, e) => { + // e.preventDefault(); + const checked = e.target.checked; + const allRemoteParticipantStreams = this.state.allRemoteParticipantStreams; + if (allRemoteParticipantStreams.filter(streamTuple => streamTuple.isPinned).length >= 2 && checked) { + return; + } + + allRemoteParticipantStreams.forEach(v => { + if (streamTuple === v) { + v.isPinned = checked; + } else { + v.isPinned = !!v.isPinned; + } + }); + + this.setState({ allRemoteParticipantStreams: allRemoteParticipantStreams }, () => { + this.updateListOfParticipantsToRender('Pinned videos changed'); + }); + } + render() { const emojis = ['👍', '❤️', '😂', '👏', '😲']; const streamCount = this.state.allRemoteParticipantStreams.length; @@ -1433,7 +1455,7 @@ export default class CallCard extends React.Component {
{ this.state.callState === 'Connected' && this.state.isShowParticipants && -
+
{ this.state.showAddParticipantPanel && @@ -1473,47 +1495,46 @@ export default class CallCard extends React.Component {
} -
-
- { - (this.state.callState === 'Connected' || - this.state.callState === 'LocalHold' || - this.state.callState === 'RemoteHold') && - this.state.allRemoteParticipantStreams.map(v => - - ) - } - { - ( - this.state.remoteScreenShareStream && - - ) - } -
+
+ { + this.state.remoteScreenShareStream && + + } +
+
+ { + (this.state.callState === 'Connected' || + this.state.callState === 'LocalHold' || + this.state.callState === 'RemoteHold') && + this.state.allRemoteParticipantStreams.map(v => + + ) + }
-
+
this.handleRaiseHand()}> - + + } + { + this.setState({showPin2VideosList: !this.state.showPin2VideosList})}> + + }
} + { + this.state.showPin2VideosList && +
+
+

+ Pin 2 videos +

+
+
+ {this.state.allRemoteParticipantStreams.map((streamTuple) => ( +
+ this.handleVideoPin(streamTuple, e)} + /> + {utils.getIdentifierText(streamTuple.participant.identifier)} +
+ ))} +
+
+ }
); } -} +} \ No newline at end of file diff --git a/Project/src/MakeCall/FunctionalStreamRenderer.js b/Project/src/MakeCall/FunctionalStreamRenderer.js index b56de7f..6221763 100644 --- a/Project/src/MakeCall/FunctionalStreamRenderer.js +++ b/Project/src/MakeCall/FunctionalStreamRenderer.js @@ -7,6 +7,7 @@ import VideoReceiveStats from './VideoReceiveStats'; export const FunctionalStreamRenderer = forwardRef(({ remoteParticipant, stream, + isPinned, dominantRemoteParticipant, dominantSpeakerMode, call, @@ -143,7 +144,7 @@ export const FunctionalStreamRenderer = forwardRef(({ if (stream.isAvailable) { return ( -
+

{displayName ? displayName : remoteParticipant.displayName ? remoteParticipant.displayName : utils.getIdentifierText(remoteParticipant.identifier)}