@@ -22,6 +22,7 @@ import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed';
2222import { logger } from 'matrix-js-sdk/src/logger' ;
2323import MemberAvatar from "../avatars/MemberAvatar" ;
2424import { replaceableComponent } from "../../../utils/replaceableComponent" ;
25+ import { SDPStreamMetadataPurpose } from 'matrix-js-sdk/src/webrtc/callEventTypes' ;
2526
2627interface IProps {
2728 call : MatrixCall ;
@@ -47,7 +48,7 @@ interface IState {
4748}
4849
4950@replaceableComponent ( "views.voip.VideoFeed" )
50- export default class VideoFeed extends React . Component < IProps , IState > {
51+ export default class VideoFeed extends React . PureComponent < IProps , IState > {
5152 private element : HTMLVideoElement ;
5253
5354 constructor ( props : IProps ) {
@@ -68,8 +69,15 @@ export default class VideoFeed extends React.Component<IProps, IState> {
6869 this . updateFeed ( this . props . feed , null ) ;
6970 }
7071
71- componentDidUpdate ( prevProps : IProps ) {
72+ componentDidUpdate ( prevProps : IProps , prevState : IState ) {
7273 this . updateFeed ( prevProps . feed , this . props . feed ) ;
74+ // If the mutes state has changed, we try to playMedia()
75+ if (
76+ prevState . videoMuted !== this . state . videoMuted ||
77+ prevProps . feed . stream !== this . props . feed . stream
78+ ) {
79+ this . playMedia ( ) ;
80+ }
7381 }
7482
7583 static getDerivedStateFromProps ( props : IProps ) {
@@ -94,10 +102,12 @@ export default class VideoFeed extends React.Component<IProps, IState> {
94102
95103 if ( oldFeed ) {
96104 this . props . feed . removeListener ( CallFeedEvent . NewStream , this . onNewStream ) ;
105+ this . props . feed . removeListener ( CallFeedEvent . MuteStateChanged , this . onMuteStateChanged ) ;
97106 this . stopMedia ( ) ;
98107 }
99108 if ( newFeed ) {
100109 this . props . feed . addListener ( CallFeedEvent . NewStream , this . onNewStream ) ;
110+ this . props . feed . addListener ( CallFeedEvent . MuteStateChanged , this . onMuteStateChanged ) ;
101111 this . playMedia ( ) ;
102112 }
103113 }
@@ -143,7 +153,13 @@ export default class VideoFeed extends React.Component<IProps, IState> {
143153 audioMuted : this . props . feed . isAudioMuted ( ) ,
144154 videoMuted : this . props . feed . isVideoMuted ( ) ,
145155 } ) ;
146- this . playMedia ( ) ;
156+ } ;
157+
158+ private onMuteStateChanged = ( ) => {
159+ this . setState ( {
160+ audioMuted : this . props . feed . isAudioMuted ( ) ,
161+ videoMuted : this . props . feed . isVideoMuted ( ) ,
162+ } ) ;
147163 } ;
148164
149165 private onResize = ( e ) => {
@@ -153,39 +169,58 @@ export default class VideoFeed extends React.Component<IProps, IState> {
153169 } ;
154170
155171 render ( ) {
156- const videoClasses = {
157- mx_VideoFeed : true ,
172+ const { pipMode, primary, feed } = this . props ;
173+
174+ const wrapperClasses = classnames ( "mx_VideoFeed" , {
158175 mx_VideoFeed_voice : this . state . videoMuted ,
159- mx_VideoFeed_video : ! this . state . videoMuted ,
160- mx_VideoFeed_mirror : (
161- this . props . feed . isLocal ( ) &&
162- SettingsStore . getValue ( 'VideoView.flipVideoHorizontally' )
163- ) ,
164- } ;
176+ } ) ;
177+ const micIconClasses = classnames ( "mx_VideoFeed_mic" , {
178+ mx_VideoFeed_mic_muted : this . state . audioMuted ,
179+ mx_VideoFeed_mic_unmuted : ! this . state . audioMuted ,
180+ } ) ;
165181
166- const { pipMode, primary } = this . props ;
182+ let micIcon ;
183+ if ( feed . purpose !== SDPStreamMetadataPurpose . Screenshare && ! pipMode ) {
184+ micIcon = (
185+ < div className = { micIconClasses } />
186+ ) ;
187+ }
167188
189+ let content ;
168190 if ( this . state . videoMuted ) {
169191 const member = this . props . feed . getMember ( ) ;
192+
170193 let avatarSize ;
171194 if ( pipMode && primary ) avatarSize = 76 ;
172195 else if ( pipMode && ! primary ) avatarSize = 16 ;
173196 else if ( ! pipMode && primary ) avatarSize = 160 ;
174197 else ; // TBD
175198
176- return (
177- < div className = { classnames ( videoClasses ) } >
178- < MemberAvatar
179- member = { member }
180- height = { avatarSize }
181- width = { avatarSize }
182- />
183- </ div >
199+ content = (
200+ < MemberAvatar
201+ member = { member }
202+ height = { avatarSize }
203+ width = { avatarSize }
204+ />
184205 ) ;
185206 } else {
186- return (
187- < video className = { classnames ( videoClasses ) } ref = { this . setElementRef } />
207+ const videoClasses = classnames ( "mx_VideoFeed_video" , {
208+ mx_VideoFeed_video_mirror : (
209+ this . props . feed . isLocal ( ) &&
210+ SettingsStore . getValue ( 'VideoView.flipVideoHorizontally' )
211+ ) ,
212+ } ) ;
213+
214+ content = (
215+ < video className = { videoClasses } ref = { this . setElementRef } />
188216 ) ;
189217 }
218+
219+ return (
220+ < div className = { wrapperClasses } >
221+ { micIcon }
222+ { content }
223+ </ div >
224+ ) ;
190225 }
191226}
0 commit comments