Add a speaking indicator
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>pull/21833/head
							parent
							
								
									5a1633d53c
								
							
						
					
					
						commit
						abab31c33b
					
				|  | @ -74,9 +74,9 @@ limitations under the License. | |||
|     > .mx_VideoFeed { | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         border-width: 0 !important; // Override mx_VideoFeed_speaking | ||||
| 
 | ||||
|         &.mx_VideoFeed_voice { | ||||
|             background-color: $inverted-bg-color; | ||||
|             display: flex; | ||||
|             justify-content: center; | ||||
|             align-items: center; | ||||
|  |  | |||
|  | @ -17,12 +17,17 @@ limitations under the License. | |||
| .mx_VideoFeed { | ||||
|     overflow: hidden; | ||||
|     position: relative; | ||||
|     box-sizing: border-box; | ||||
| 
 | ||||
|     &.mx_VideoFeed_voice { | ||||
|         background-color: $inverted-bg-color; | ||||
|         aspect-ratio: 16 / 9; | ||||
|     } | ||||
| 
 | ||||
|     &.mx_VideoFeed_speaking { | ||||
|         border: $accent-color 2px solid; | ||||
|     } | ||||
| 
 | ||||
|     .mx_VideoFeed_video { | ||||
|         width: 100%; | ||||
|         background-color: transparent; | ||||
|  |  | |||
|  | @ -24,6 +24,8 @@ import MemberAvatar from "../avatars/MemberAvatar"; | |||
| import { replaceableComponent } from "../../../utils/replaceableComponent"; | ||||
| import { SDPStreamMetadataPurpose } from 'matrix-js-sdk/src/webrtc/callEventTypes'; | ||||
| 
 | ||||
| const SPEAKING_THRESHOLD = -60; | ||||
| 
 | ||||
| interface IProps { | ||||
|     call: MatrixCall; | ||||
| 
 | ||||
|  | @ -45,6 +47,7 @@ interface IProps { | |||
| interface IState { | ||||
|     audioMuted: boolean; | ||||
|     videoMuted: boolean; | ||||
|     speaking: boolean; | ||||
| } | ||||
| 
 | ||||
| @replaceableComponent("views.voip.VideoFeed") | ||||
|  | @ -57,6 +60,7 @@ export default class VideoFeed extends React.PureComponent<IProps, IState> { | |||
|         this.state = { | ||||
|             audioMuted: this.props.feed.isAudioMuted(), | ||||
|             videoMuted: this.props.feed.isVideoMuted(), | ||||
|             speaking: false, | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|  | @ -103,11 +107,19 @@ export default class VideoFeed extends React.PureComponent<IProps, IState> { | |||
|         if (oldFeed) { | ||||
|             this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); | ||||
|             this.props.feed.removeListener(CallFeedEvent.MuteStateChanged, this.onMuteStateChanged); | ||||
|             if (this.props.feed.purpose === SDPStreamMetadataPurpose.Usermedia) { | ||||
|                 this.props.feed.removeListener(CallFeedEvent.VolumeChanged, this.onVolumeChanged); | ||||
|                 this.props.feed.measureVolumeActivity(false); | ||||
|             } | ||||
|             this.stopMedia(); | ||||
|         } | ||||
|         if (newFeed) { | ||||
|             this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); | ||||
|             this.props.feed.addListener(CallFeedEvent.MuteStateChanged, this.onMuteStateChanged); | ||||
|             if (this.props.feed.purpose === SDPStreamMetadataPurpose.Usermedia) { | ||||
|                 this.props.feed.addListener(CallFeedEvent.VolumeChanged, this.onVolumeChanged); | ||||
|                 this.props.feed.measureVolumeActivity(true); | ||||
|             } | ||||
|             this.playMedia(); | ||||
|         } | ||||
|     } | ||||
|  | @ -162,6 +174,10 @@ export default class VideoFeed extends React.PureComponent<IProps, IState> { | |||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     private onVolumeChanged = (volume: number): void => { | ||||
|         this.setState({ speaking: volume > SPEAKING_THRESHOLD }); | ||||
|     }; | ||||
| 
 | ||||
|     private onResize = (e) => { | ||||
|         if (this.props.onResize && !this.props.feed.isLocal()) { | ||||
|             this.props.onResize(e); | ||||
|  | @ -173,6 +189,7 @@ export default class VideoFeed extends React.PureComponent<IProps, IState> { | |||
| 
 | ||||
|         const wrapperClasses = classnames("mx_VideoFeed", { | ||||
|             mx_VideoFeed_voice: this.state.videoMuted, | ||||
|             mx_VideoFeed_speaking: this.state.speaking, | ||||
|         }); | ||||
|         const micIconClasses = classnames("mx_VideoFeed_mic", { | ||||
|             mx_VideoFeed_mic_muted: this.state.audioMuted, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Šimon Brandner
						Šimon Brandner