[RN] Add UI for raised hand feature

This commit is contained in:
Bettenbuk Zoltan 2019-03-27 11:23:41 +01:00 committed by Saúl Ibarra Corretgé
parent ce9744b9c3
commit e65918564b
9 changed files with 268 additions and 206 deletions

View File

@ -824,6 +824,7 @@ SmallVideo.prototype.updateIndicators = function() {
}
ReactDOM.render(
<Provider store = { APP.store }>
<I18nextProvider i18n = { i18next }>
<div>
<AtlasKitThemeProvider mode = 'dark'>
@ -842,6 +843,7 @@ SmallVideo.prototype.updateIndicators = function() {
{ this._showRaisedHand
? <RaisedHandIndicator
iconSize = { iconSize }
participantId = { this.id }
tooltipPosition = { tooltipPosition } />
: null }
{ this._showDominantSpeaker
@ -851,7 +853,8 @@ SmallVideo.prototype.updateIndicators = function() {
: null }
</AtlasKitThemeProvider>
</div>
</I18nextProvider>,
</I18nextProvider>
</Provider>,
indicatorToolbar
);
};

View File

@ -0,0 +1,42 @@
// @flow
import { Component } from 'react';
import { getParticipantById } from '../../base/participants';
export type Props = {
/**
* The participant id who we want to render the raised hand indicator
* for.
*/
participantId: string,
/**
* True if the hand is raised for this participant.
*/
_raisedHand: boolean
}
/**
* Implements an abstract class for the RaisedHandIndicator component.
*/
export default class AbstractRaisedHandIndicator<P: Props>
extends Component<P> {
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @param {Props} ownProps - The own props of the component.
* @returns {Object}
*/
export function _mapStateToProps(state: Object, ownProps: Props): Object {
const participant = getParticipantById(state, ownProps.participantId);
return {
_raisedHand: participant && participant.raisedHand
};
}

View File

@ -1,3 +1,5 @@
// @flow
import React, { Component } from 'react';
import { View } from 'react-native';
@ -9,7 +11,7 @@ import styles from './styles';
* Thumbnail badge showing that the participant is the dominant speaker in
* the conference.
*/
export default class DominantSpeakerIndicator extends Component {
export default class DominantSpeakerIndicator extends Component<{}> {
/**
* Implements React's {@link Component#render()}.
*
@ -17,10 +19,10 @@ export default class DominantSpeakerIndicator extends Component {
*/
render() {
return (
<View style = { styles.dominantSpeakerIndicatorBackground }>
<View style = { styles.indicatorBackground }>
<Icon
name = 'dominant-speaker'
style = { styles.dominantSpeakerIndicator } />
style = { styles.indicator } />
</View>
);
}

View File

@ -6,7 +6,7 @@ import { View } from 'react-native';
import { getLocalParticipant } from '../../../base/participants';
import { connect } from '../../../base/redux';
import styles from '../styles';
import styles from './styles';
import Thumbnail from './Thumbnail';
type Props = {

View File

@ -0,0 +1,42 @@
/* @flow */
import React from 'react';
import { View } from 'react-native';
import { Icon } from '../../../base/font-icons';
import { connect } from '../../../base/redux';
import AbstractRaisedHandIndicator, {
type Props,
_mapStateToProps
} from '../AbstractRaisedHandIndicator';
import styles from './styles';
/**
* Thumbnail badge showing that the participant would like to speak.
*
* @extends Component
*/
class RaisedHandIndicator extends AbstractRaisedHandIndicator<Props> {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
*/
render() {
if (!this.props._raisedHand) {
return null;
}
return (
<View style = { styles.indicatorBackground }>
<Icon
name = 'raised-hand'
style = { styles.indicator } />
</View>
);
}
}
export default connect(_mapStateToProps)(RaisedHandIndicator);

View File

@ -22,8 +22,8 @@ import { RemoteVideoMenu } from '../../../remote-video-menu';
import AudioMutedIndicator from './AudioMutedIndicator';
import DominantSpeakerIndicator from './DominantSpeakerIndicator';
import ModeratorIndicator from './ModeratorIndicator';
import { AVATAR_SIZE } from '../styles';
import styles from './styles';
import RaisedHandIndicator from './RaisedHandIndicator';
import styles, { AVATAR_SIZE } from './styles';
import VideoMutedIndicator from './VideoMutedIndicator';
/**
@ -168,6 +168,8 @@ class Thumbnail extends Component<Props> {
{ participant.dominantSpeaker
&& <DominantSpeakerIndicator /> }
<RaisedHandIndicator participantId = { participant.id } />
<Container style = { styles.thumbnailIndicatorContainer }>
{ audioMuted
&& <AudioMutedIndicator /> }

View File

@ -1,6 +1,14 @@
import { ColorPalette, createStyleSheet } from '../../../base/styles';
// @flow
import { default as platformIndependentStyles } from '../styles';
import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
import { ColorPalette } from '../../../base/styles';
import { FILMSTRIP_SIZE } from '../../constants';
/**
* Size for the Avatar.
*/
export const AVATAR_SIZE = 50;
/**
* The base/default style of indicators such as audioMutedIndicator,
@ -17,34 +25,171 @@ const indicator = {
/**
* The styles of the feature filmstrip.
*/
export default createStyleSheet(platformIndependentStyles, {
dominantSpeakerIndicator: {
export default {
/**
* Dominant speaker indicator style.
*/
indicator: {
color: ColorPalette.white,
fontSize: 12
},
/**
* Dominant speaker indicator background style.
*/
dominantSpeakerIndicatorBackground: {
indicatorBackground: {
backgroundColor: ColorPalette.blue,
borderRadius: 16,
padding: 4
left: 4,
padding: 4,
position: 'absolute',
top: 4
},
/**
* The style of the narrow {@link Filmstrip} version which displays
* thumbnails in a row at the bottom of the screen.
*/
filmstripNarrow: {
flexDirection: 'row',
flexGrow: 0,
justifyContent: 'flex-end',
height: FILMSTRIP_SIZE
},
/**
* The style of the wide {@link Filmstrip} version which displays thumbnails
* in a column on the short size of the screen.
*
* NOTE: width is calculated based on the children, but it should also align
* to {@code FILMSTRIP_SIZE}.
*/
filmstripWide: {
bottom: 0,
flexDirection: 'column',
flexGrow: 0,
position: 'absolute',
right: 0,
top: 0
},
/**
* Container of the {@link LocalThumbnail}.
*/
localThumbnail: {
alignContent: 'stretch',
alignSelf: 'stretch',
aspectRatio: 1,
flexShrink: 0,
flexDirection: 'row'
},
/**
* Moderator indicator style.
*/
moderatorIndicator: indicator,
moderatorIndicator: {
backgroundColor: 'transparent',
bottom: 4,
color: ColorPalette.white,
position: 'absolute',
right: 4,
...indicator
},
/**
* Video thumbnail style.
* The style of the scrollview containing the remote thumbnails.
*/
scrollView: {
flexGrow: 0
},
/**
* The style of a participant's Thumbnail which renders either the video or
* the avatar of the associated participant.
*/
thumbnail: {
alignItems: 'stretch',
backgroundColor: ColorPalette.appBackground,
borderColor: '#424242',
borderRadius: 3,
borderStyle: 'solid',
borderWidth: 1,
flex: 1,
height: 80,
justifyContent: 'center',
margin: 2,
overflow: 'hidden',
position: 'relative',
width: 80
},
/**
* Audio muted indicator style.
* The thumbnail audio and video muted indicator style.
*/
thumbnailIndicator: indicator
thumbnailIndicator: {
backgroundColor: 'transparent',
color: ColorPalette.white,
paddingLeft: 1,
paddingRight: 1,
position: 'relative',
...indicator
},
/**
* The thumbnails indicator container.
*/
thumbnailIndicatorContainer: {
alignSelf: 'stretch',
bottom: 4,
flex: 1,
flexDirection: 'row',
left: 4,
position: 'absolute'
},
tileView: {
alignSelf: 'center'
},
tileViewRows: {
justifyContent: 'center'
},
tileViewRow: {
flexDirection: 'row',
justifyContent: 'center'
}
};
/**
* Color schemed styles for the @{code Thumbnail} component.
*/
ColorSchemeRegistry.register('Thumbnail', {
/**
* Tinting style of the on-stage participant thumbnail.
*/
activeThumbnailTint: {
backgroundColor: schemeColor('activeParticipantTint')
},
/**
* Coloring if the thumbnail background.
*/
participantViewStyle: {
backgroundColor: schemeColor('background')
},
/**
* Pinned video thumbnail style.
*/
thumbnailPinned: {
borderColor: schemeColor('activeParticipantHighlight'),
shadowColor: schemeColor('activeParticipantHighlight'),
shadowOffset: {
height: 5,
width: 5
},
shadowRadius: 5
}
});

View File

@ -1,185 +0,0 @@
// @flow
import { ColorSchemeRegistry, schemeColor } from '../../base/color-scheme';
import { ColorPalette } from '../../base/styles';
import { FILMSTRIP_SIZE } from '../constants';
/**
* Size for the Avatar.
*/
export const AVATAR_SIZE = 50;
/**
* The base style of {@link Filmstrip} shared between narrow and wide versions.
*/
const filmstrip = {
flexGrow: 0
};
/**
* The styles of the feature filmstrip common to both Web and native.
*/
export default {
/**
* Dominant speaker indicator style.
*/
dominantSpeakerIndicator: {
color: ColorPalette.white,
fontSize: 15
},
/**
* Dominant speaker indicator background style.
*/
dominantSpeakerIndicatorBackground: {
backgroundColor: ColorPalette.blue,
borderRadius: 15,
left: 4,
padding: 5,
position: 'absolute',
top: 4
},
/**
* The style of the narrow {@link Filmstrip} version which displays
* thumbnails in a row at the bottom of the screen.
*/
filmstripNarrow: {
...filmstrip,
flexDirection: 'row',
justifyContent: 'flex-end',
height: FILMSTRIP_SIZE
},
/**
* The style of the wide {@link Filmstrip} version which displays thumbnails
* in a column on the short size of the screen.
*
* NOTE: width is calculated based on the children, but it should also align
* to {@code FILMSTRIP_SIZE}.
*/
filmstripWide: {
...filmstrip,
bottom: 0,
flexDirection: 'column',
position: 'absolute',
right: 0,
top: 0
},
/**
* Container of the {@link LocalThumbnail}.
*/
localThumbnail: {
alignContent: 'stretch',
alignSelf: 'stretch',
aspectRatio: 1,
flexShrink: 0,
flexDirection: 'row'
},
/**
* Moderator indicator style.
*/
moderatorIndicator: {
backgroundColor: 'transparent',
bottom: 4,
color: ColorPalette.white,
position: 'absolute',
right: 4
},
/**
* The style of the scrollview containing the remote thumbnails.
*/
scrollView: {
flexGrow: 0
},
/**
* The style of a participant's Thumbnail which renders either the video or
* the avatar of the associated participant.
*/
thumbnail: {
alignItems: 'stretch',
backgroundColor: ColorPalette.appBackground,
borderColor: '#424242',
borderRadius: 3,
borderStyle: 'solid',
borderWidth: 1,
flex: 1,
justifyContent: 'center',
margin: 2,
overflow: 'hidden',
position: 'relative'
},
/**
* The thumbnail audio and video muted indicator style.
*/
thumbnailIndicator: {
backgroundColor: 'transparent',
color: ColorPalette.white,
paddingLeft: 1,
paddingRight: 1,
position: 'relative'
},
/**
* The thumbnails indicator container.
*/
thumbnailIndicatorContainer: {
alignSelf: 'stretch',
bottom: 4,
flex: 1,
flexDirection: 'row',
left: 4,
position: 'absolute'
},
tileView: {
alignSelf: 'center'
},
tileViewRows: {
justifyContent: 'center'
},
tileViewRow: {
flexDirection: 'row',
justifyContent: 'center'
}
};
/**
* Color schemed styles for the @{code Thumbnail} component.
*/
ColorSchemeRegistry.register('Thumbnail', {
/**
* Tinting style of the on-stage participant thumbnail.
*/
activeThumbnailTint: {
backgroundColor: schemeColor('activeParticipantTint')
},
/**
* Coloring if the thumbnail background.
*/
participantViewStyle: {
backgroundColor: schemeColor('background')
},
/**
* Pinned video thumbnail style.
*/
thumbnailPinned: {
borderColor: schemeColor('activeParticipantHighlight'),
shadowColor: schemeColor('activeParticipantHighlight'),
shadowOffset: {
height: 5,
width: 5
},
shadowRadius: 5
}
});

View File

@ -1,13 +1,20 @@
/* @flow */
import React, { Component } from 'react';
import React from 'react';
import { connect } from '../../../base/redux';
import AbstractRaisedHandIndicator, {
type Props as AbstractProps,
_mapStateToProps
} from '../AbstractRaisedHandIndicator';
import BaseIndicator from './BaseIndicator';
/**
* The type of the React {@code Component} props of {@link RaisedHandIndicator}.
*/
type Props = {
type Props = AbstractProps & {
/**
* The font-size for the icon.
@ -25,13 +32,17 @@ type Props = {
*
* @extends Component
*/
class RaisedHandIndicator extends Component<Props> {
class RaisedHandIndicator extends AbstractRaisedHandIndicator<Props> {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
*/
render() {
if (!this.props._raisedHand) {
return null;
}
return (
<BaseIndicator
className = 'raisehandindicator indicator show-inline'
@ -43,4 +54,4 @@ class RaisedHandIndicator extends Component<Props> {
}
}
export default RaisedHandIndicator;
export default connect(_mapStateToProps)(RaisedHandIndicator);