feat(Labels): Redesign labels on mobile & web
This commit is contained in:
parent
7656985fe1
commit
b135e2a06a
|
@ -1,68 +1,37 @@
|
|||
.large-video-labels {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 30px;
|
||||
transition: right 0.5s;
|
||||
z-index: $labelsZ;
|
||||
|
||||
.circular-label {
|
||||
.label {
|
||||
align-items: center;
|
||||
color: white;
|
||||
background: #36383C;
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
font-weight: bold;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
height: 28px;
|
||||
margin: 0 0 4px 4px;
|
||||
padding: 0 8px;
|
||||
|
||||
&--green {
|
||||
background: #31B76A;
|
||||
}
|
||||
|
||||
&--red {
|
||||
background: #E34F56
|
||||
}
|
||||
|
||||
&--white {
|
||||
background: #fff;
|
||||
color: #5e6d7a;
|
||||
|
||||
svg {
|
||||
fill: #5e6d7a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.label-text-with-icon {
|
||||
margin-left: 8px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.circular-label {
|
||||
background: #B8C7E0;
|
||||
}
|
||||
|
||||
.circular-label.e2ee {
|
||||
align-items: center;
|
||||
background: #76CF9C;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.circular-label.file {
|
||||
background: #FF5630;
|
||||
}
|
||||
|
||||
.circular-label.local-rec {
|
||||
background: #FF5630;
|
||||
}
|
||||
|
||||
.circular-label.stream {
|
||||
background: #0065FF;
|
||||
}
|
||||
|
||||
.circular-label.insecure {
|
||||
background: $defaultWarningColor;
|
||||
}
|
||||
|
||||
.recording-label.center-message {
|
||||
background: $videoStateIndicatorBackground;
|
||||
bottom: 50%;
|
||||
display: block;
|
||||
left: 50%;
|
||||
padding: 10px;
|
||||
position: fixed;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: $centeredVideoLabelZ;
|
||||
}
|
||||
}
|
||||
|
||||
.circular-label {
|
||||
background: $videoStateIndicatorBackground;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
font-size: 13px;
|
||||
height: $videoStateIndicatorSize;
|
||||
line-height: $videoStateIndicatorSize;
|
||||
text-align: center;
|
||||
min-width: $videoStateIndicatorSize;
|
||||
.participants-count {
|
||||
cursor: pointer;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
.participants-count {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
color: #5e6d7a;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
margin-left: 16px;
|
||||
padding: 4px 8px;
|
||||
pointer-events: auto;
|
||||
|
||||
&-number {
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
background: url('../images/user-groups.svg');
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
|
@ -1,35 +1,60 @@
|
|||
.subject {
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
margin-top: 20px;
|
||||
position: absolute;
|
||||
top: -120px;
|
||||
transition: top .3s ease-in;
|
||||
height: 95px;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
padding: 25px 140px 0 140px;
|
||||
text-align: center;
|
||||
font-size: 17px;
|
||||
color: #fff;
|
||||
z-index: $zindex10;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
z-index: $zindex3;
|
||||
|
||||
&.visible {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
&.gradient {
|
||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
&-text {
|
||||
vertical-align: middle;
|
||||
.subject-info-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
max-width: calc(100% - 280px);
|
||||
margin: 0 auto;
|
||||
|
||||
&--full-width {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
&-conference-timer {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
opacity: 0.6;
|
||||
@media (max-width: 500px) {
|
||||
flex-wrap: wrap;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.subject-info {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
max-width: 80%;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.subject-text {
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 3px 0px 0px 3px;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
padding: 2px 16px;
|
||||
height: 24px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.subject-timer {
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 0px 3px 3px 0px;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
min-width: 34px;
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ $flagsImagePath: "../images/";
|
|||
@import 'videolayout_default';
|
||||
@import 'notice';
|
||||
@import 'subject';
|
||||
@import 'participants-count';
|
||||
@import 'popup_menu';
|
||||
@import 'recording';
|
||||
@import 'login_menu';
|
||||
|
|
|
@ -111,6 +111,7 @@ export { default as IconVideoQualityAudioOnly } from './AUD.svg';
|
|||
export { default as IconVideoQualityHD } from './HD.svg';
|
||||
export { default as IconVideoQualityLD } from './LD.svg';
|
||||
export { default as IconVideoQualitySD } from './SD.svg';
|
||||
export { default as IconUserGroups } from './user-groups.svg';
|
||||
export { default as IconVirtualBackground } from './virtual-background.svg';
|
||||
export { default as IconVolume } from './volume.svg';
|
||||
export { default as IconVolumeEmpty } from './volume-empty.svg';
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.33331 2C6.28101 2 7.09675 2.56499 7.46207 3.37651C7.00766 3.45023 6.58406 3.61583 6.21095 3.85361C6.04111 3.54356 5.71176 3.33333 5.33331 3.33333C4.78103 3.33333 4.33331 3.78105 4.33331 4.33333C4.33331 4.75895 4.59921 5.12246 4.97395 5.26682C4.77672 5.69245 4.66665 6.16671 4.66665 6.66667L4.66678 6.6967C3.12249 6.85332 2.66665 7.65415 2.66665 9.83333C2.66665 9.89666 2.66835 9.95222 2.67088 10H3.13441C2.977 10.3982 2.86114 10.8423 2.7841 11.3333H2.33331C1.66665 11.3333 1.33331 10.8333 1.33331 9.83333C1.33331 7.60559 1.88097 6.20498 3.39417 5.63152C3.14521 5.26038 2.99998 4.81382 2.99998 4.33333C2.99998 3.04467 4.04465 2 5.33331 2ZM9.78901 3.85361C9.4159 3.61583 8.9923 3.45023 8.53788 3.37651C8.90321 2.56499 9.71895 2 10.6666 2C11.9553 2 13 3.04467 13 4.33333C13 4.81382 12.8547 5.26038 12.6058 5.63152C14.119 6.20498 14.6666 7.60559 14.6666 9.83333C14.6666 10.8333 14.3333 11.3333 13.6666 11.3333H13.2159C13.1388 10.8423 13.023 10.3982 12.8656 10H13.3291C13.3316 9.95222 13.3333 9.89666 13.3333 9.83333C13.3333 7.65415 12.8775 6.85332 11.3332 6.6967L11.3333 6.66667C11.3333 6.1667 11.2232 5.69245 11.026 5.26682C11.4008 5.12246 11.6666 4.75895 11.6666 4.33333C11.6666 3.78105 11.2189 3.33333 10.6666 3.33333C10.2882 3.33333 9.95885 3.54356 9.78901 3.85361ZM4.49998 14.6667C3.7222 14.6667 3.33331 14.1111 3.33331 13C3.33331 10.4598 4.0062 8.8875 5.87888 8.28308C5.5366 7.83462 5.33331 7.27438 5.33331 6.66667C5.33331 5.19391 6.52722 4 7.99998 4C9.47274 4 10.6666 5.19391 10.6666 6.66667C10.6666 7.27438 10.4634 7.83462 10.1211 8.28308C11.9938 8.8875 12.6666 10.4598 12.6666 13C12.6666 14.1111 12.2778 14.6667 11.5 14.6667H4.49998ZM9.33331 6.66667C9.33331 7.40305 8.73636 8 7.99998 8C7.2636 8 6.66665 7.40305 6.66665 6.66667C6.66665 5.93029 7.2636 5.33333 7.99998 5.33333C8.73636 5.33333 9.33331 5.93029 9.33331 6.66667ZM11.3333 13C11.3333 13.1426 11.3252 13.2536 11.3152 13.3333H4.68477C4.67476 13.2536 4.66665 13.1426 4.66665 13C4.66665 10.1957 5.42021 9.33333 7.99998 9.33333C10.5797 9.33333 11.3333 10.1957 11.3333 13Z" fill="#5E6D7A"/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.33331 2C6.28101 2 7.09675 2.56499 7.46207 3.37651C7.00766 3.45023 6.58406 3.61583 6.21095 3.85361C6.04111 3.54356 5.71176 3.33333 5.33331 3.33333C4.78103 3.33333 4.33331 3.78105 4.33331 4.33333C4.33331 4.75895 4.59921 5.12246 4.97395 5.26682C4.77672 5.69245 4.66665 6.16671 4.66665 6.66667L4.66678 6.6967C3.12249 6.85332 2.66665 7.65415 2.66665 9.83333C2.66665 9.89666 2.66835 9.95222 2.67088 10H3.13441C2.977 10.3982 2.86114 10.8423 2.7841 11.3333H2.33331C1.66665 11.3333 1.33331 10.8333 1.33331 9.83333C1.33331 7.60559 1.88097 6.20498 3.39417 5.63152C3.14521 5.26038 2.99998 4.81382 2.99998 4.33333C2.99998 3.04467 4.04465 2 5.33331 2ZM9.78901 3.85361C9.4159 3.61583 8.9923 3.45023 8.53788 3.37651C8.90321 2.56499 9.71895 2 10.6666 2C11.9553 2 13 3.04467 13 4.33333C13 4.81382 12.8547 5.26038 12.6058 5.63152C14.119 6.20498 14.6666 7.60559 14.6666 9.83333C14.6666 10.8333 14.3333 11.3333 13.6666 11.3333H13.2159C13.1388 10.8423 13.023 10.3982 12.8656 10H13.3291C13.3316 9.95222 13.3333 9.89666 13.3333 9.83333C13.3333 7.65415 12.8775 6.85332 11.3332 6.6967L11.3333 6.66667C11.3333 6.1667 11.2232 5.69245 11.026 5.26682C11.4008 5.12246 11.6666 4.75895 11.6666 4.33333C11.6666 3.78105 11.2189 3.33333 10.6666 3.33333C10.2882 3.33333 9.95885 3.54356 9.78901 3.85361ZM4.49998 14.6667C3.7222 14.6667 3.33331 14.1111 3.33331 13C3.33331 10.4598 4.0062 8.8875 5.87888 8.28308C5.5366 7.83462 5.33331 7.27438 5.33331 6.66667C5.33331 5.19391 6.52722 4 7.99998 4C9.47274 4 10.6666 5.19391 10.6666 6.66667C10.6666 7.27438 10.4634 7.83462 10.1211 8.28308C11.9938 8.8875 12.6666 10.4598 12.6666 13C12.6666 14.1111 12.2778 14.6667 11.5 14.6667H4.49998ZM9.33331 6.66667C9.33331 7.40305 8.73636 8 7.99998 8C7.2636 8 6.66665 7.40305 6.66665 6.66667C6.66665 5.93029 7.2636 5.33333 7.99998 5.33333C8.73636 5.33333 9.33331 5.93029 9.33331 6.66667ZM11.3333 13C11.3333 13.1426 11.3252 13.2536 11.3152 13.3333H4.68477C4.67476 13.2536 4.66665 13.1426 4.66665 13C4.66665 10.1957 5.42021 9.33333 7.99998 9.33333C10.5797 9.33333 11.3333 10.1957 11.3333 13Z" />
|
||||
</svg>
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.1 KiB |
|
@ -12,13 +12,12 @@ export type Props = {
|
|||
/**
|
||||
* String or component that will be rendered as the label itself.
|
||||
*/
|
||||
label: string
|
||||
text: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract class for the {@code CircularLabel} component.
|
||||
* Abstract class for the {@code Label} component.
|
||||
*/
|
||||
export default class AbstractCircularLabel<P: Props, S: *>
|
||||
export default class Label<P: Props, S: *>
|
||||
extends Component<P, S> {
|
||||
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Icon from '../../icons/components/Icon';
|
||||
|
||||
import AbstractCircularLabel, {
|
||||
type Props as AbstractProps
|
||||
} from './AbstractCircularLabel';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
|
||||
/**
|
||||
* Additional CSS class names to add to the root of {@code CircularLabel}.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* HTML ID attribute to add to the root of {@code CircularLabel}.
|
||||
*/
|
||||
id: string
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* React Component for showing short text in a circle.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
export default class CircularLabel extends AbstractCircularLabel<Props, {}> {
|
||||
/**
|
||||
* Default values for {@code CircularLabel} component's properties.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static defaultProps = {
|
||||
className: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
icon,
|
||||
id,
|
||||
label
|
||||
} = this.props;
|
||||
|
||||
const labelComponent = icon
|
||||
? (
|
||||
<Icon
|
||||
src = { icon } />
|
||||
) : label;
|
||||
|
||||
return (
|
||||
<div
|
||||
className = { `circular-label ${className}` }
|
||||
id = { id }>
|
||||
{ labelComponent }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Animated, Text, View } from 'react-native';
|
||||
|
||||
import styles, { DEFAULT_COLOR, LABEL_MARGIN, LABEL_SIZE } from './styles';
|
||||
import styles, { DEFAULT_COLOR } from './styles';
|
||||
|
||||
export type Props = {
|
||||
|
||||
|
@ -19,21 +19,9 @@ type State = {
|
|||
/**
|
||||
* The opacity animation Object.
|
||||
*/
|
||||
opacityAnimation: Object,
|
||||
|
||||
/**
|
||||
* A boolean to decide to show or not show the arrow. This is required as
|
||||
* we can't easily animate this transformed Component so we render it once
|
||||
* the animation is done.
|
||||
*/
|
||||
showArrow: boolean
|
||||
opacityAnimation: Object
|
||||
};
|
||||
|
||||
/**
|
||||
* Offset to the arrow to be rendered in the right position.
|
||||
*/
|
||||
const ARROW_OFFSET = 0;
|
||||
|
||||
/**
|
||||
* A react {@code Component} that implements an expanded label as tooltip-like
|
||||
* component to explain the meaning of the {@code Label}.
|
||||
|
@ -48,8 +36,7 @@ export default class ExpandedLabel<P: Props> extends Component<P, State> {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
opacityAnimation: new Animated.Value(0),
|
||||
showArrow: false
|
||||
opacityAnimation: new Animated.Value(0)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -63,11 +50,7 @@ export default class ExpandedLabel<P: Props> extends Component<P, State> {
|
|||
toValue: 1,
|
||||
velocity: 1,
|
||||
useNativeDriver: true
|
||||
}).start(({ finished }) => {
|
||||
finished && this.setState({
|
||||
showArrow: true
|
||||
});
|
||||
});
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,32 +59,12 @@ export default class ExpandedLabel<P: Props> extends Component<P, State> {
|
|||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
const arrowPosition
|
||||
= this.props.parentPosition - LABEL_MARGIN - (LABEL_SIZE / 2);
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
style = { [
|
||||
styles.expandedLabelWrapper,
|
||||
{
|
||||
opacity: this.state.opacityAnimation
|
||||
}
|
||||
] } >
|
||||
style = { [ styles.expandedLabelContainer, { opacity: this.state.opacityAnimation } ] }>
|
||||
<View
|
||||
style = { [
|
||||
styles.expandedLabelArrow,
|
||||
{
|
||||
backgroundColor: this._getColor() || DEFAULT_COLOR,
|
||||
marginRight: arrowPosition + ARROW_OFFSET
|
||||
}
|
||||
] } />
|
||||
<View
|
||||
style = { [
|
||||
styles.expandedLabelContainer,
|
||||
{
|
||||
backgroundColor: this._getColor() || DEFAULT_COLOR
|
||||
}
|
||||
] }>
|
||||
style = { [ styles.expandedLabelTextContainer,
|
||||
{ backgroundColor: this._getColor() || DEFAULT_COLOR } ] }>
|
||||
<Text style = { styles.expandedLabelText }>
|
||||
{ this._getLabel() }
|
||||
</Text>
|
||||
|
|
|
@ -5,9 +5,9 @@ import { Animated, Text } from 'react-native';
|
|||
import Icon from '../../icons/components/Icon';
|
||||
import { combineStyles, type StyleType } from '../../styles';
|
||||
|
||||
import AbstractCircularLabel, {
|
||||
import AbstractLabel, {
|
||||
type Props as AbstractProps
|
||||
} from './AbstractCircularLabel';
|
||||
} from './AbstractLabel';
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
|
@ -48,14 +48,14 @@ type State = {
|
|||
* Renders a circular indicator to be used for status icons, such as recording
|
||||
* on, audio-only conference, video quality and similar.
|
||||
*/
|
||||
export default class CircularLabel extends AbstractCircularLabel<Props, State> {
|
||||
export default class Label extends AbstractLabel<Props, State> {
|
||||
/**
|
||||
* A reference to the started animation of this label.
|
||||
*/
|
||||
animationReference: Object;
|
||||
|
||||
/**
|
||||
* Instantiates a new instance of {@code CircularLabel}.
|
||||
* Instantiates a new instance of {@code Label}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
@ -91,7 +91,7 @@ export default class CircularLabel extends AbstractCircularLabel<Props, State> {
|
|||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
const { icon, label, status, style } = this.props;
|
||||
const { icon, text, status, style } = this.props;
|
||||
|
||||
let extraStyle = null;
|
||||
|
||||
|
@ -106,24 +106,18 @@ export default class CircularLabel extends AbstractCircularLabel<Props, State> {
|
|||
break;
|
||||
}
|
||||
|
||||
const labelComponent = icon
|
||||
? (
|
||||
<Icon
|
||||
src = { icon }
|
||||
style = { styles.indicatorIcon } />
|
||||
) : (
|
||||
<Text style = { styles.indicatorText }>
|
||||
{ label }
|
||||
</Text>
|
||||
);
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
style = { [
|
||||
combineStyles(styles.indicatorContainer, style),
|
||||
combineStyles(styles.labelContainer, style),
|
||||
extraStyle
|
||||
] }>
|
||||
{ labelComponent }
|
||||
{ icon && <Icon
|
||||
size = '18'
|
||||
src = { icon } /> }
|
||||
{ text && <Text style = { styles.labelText }>
|
||||
{ text }
|
||||
</Text>}
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Icon from '../../icons/components/Icon';
|
||||
|
||||
import AbstractLabel, {
|
||||
type Props as AbstractProps
|
||||
} from './AbstractLabel';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
|
||||
/**
|
||||
* Additional CSS class names to add to the root of {@code Label}.
|
||||
*/
|
||||
className: string,
|
||||
|
||||
/**
|
||||
* HTML ID attribute to add to the root of {@code Label}.
|
||||
*/
|
||||
id: string
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* React Component for showing short text in a circle.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
export default class Label extends AbstractLabel<Props, *> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
icon,
|
||||
id,
|
||||
text
|
||||
} = this.props;
|
||||
|
||||
const labelClassName = icon ? 'label-text-with-icon' : '';
|
||||
|
||||
return (
|
||||
<div
|
||||
className = { `label ${className}` }
|
||||
id = { id }>
|
||||
{ icon && <Icon
|
||||
size = '16'
|
||||
src = { icon } /> }
|
||||
{ text && <span className = { labelClassName }>{text}</span> }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,2 +1,2 @@
|
|||
export { default as CircularLabel } from './CircularLabel';
|
||||
export { default as Label } from './Label';
|
||||
export { default as ExpandedLabel } from './ExpandedLabel';
|
||||
|
|
|
@ -1,76 +1,65 @@
|
|||
// @flow
|
||||
|
||||
import { BoxModel, ColorPalette } from '../../styles';
|
||||
import { ColorPalette } from '../../styles';
|
||||
|
||||
/**
|
||||
* The default color of the {@code Label} and {@code ExpandedLabel}.
|
||||
*/
|
||||
export const DEFAULT_COLOR = '#808080';
|
||||
export const DEFAULT_COLOR = '#36383C';
|
||||
|
||||
/**
|
||||
* Margin of the {@Label} - to be reused when rendering the
|
||||
* {@code ExpandedLabel}.
|
||||
*/
|
||||
export const LABEL_MARGIN = 5;
|
||||
export const LABEL_MARGIN = 8;
|
||||
|
||||
/**
|
||||
* Size of the {@Label} - to be reused when rendering the
|
||||
* {@code ExpandedLabel}.
|
||||
*/
|
||||
export const LABEL_SIZE = 36;
|
||||
export const LABEL_SIZE = 28;
|
||||
|
||||
/**
|
||||
* The styles of the native base/label feature.
|
||||
*/
|
||||
export default {
|
||||
|
||||
expandedLabelArrow: {
|
||||
backgroundColor: ColorPalette.blue,
|
||||
height: 15,
|
||||
transform: [ { rotate: '45deg' }, { translateX: 10 } ],
|
||||
width: 15
|
||||
expandedLabelContainer: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 36,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
|
||||
expandedLabelContainer: {
|
||||
backgroundColor: ColorPalette.blue,
|
||||
borderColor: ColorPalette.blue,
|
||||
borderRadius: 6,
|
||||
marginHorizontal: BoxModel.margin,
|
||||
padding: BoxModel.padding
|
||||
expandedLabelTextContainer: {
|
||||
borderRadius: 3,
|
||||
paddingHorizontal: LABEL_MARGIN,
|
||||
paddingVertical: LABEL_MARGIN / 2
|
||||
},
|
||||
|
||||
expandedLabelText: {
|
||||
color: ColorPalette.white
|
||||
},
|
||||
|
||||
expandedLabelWrapper: {
|
||||
alignItems: 'flex-end',
|
||||
flexDirection: 'column'
|
||||
},
|
||||
|
||||
/**
|
||||
* The outermost view.
|
||||
*/
|
||||
indicatorContainer: {
|
||||
alignItems: 'center',
|
||||
labelContainer: {
|
||||
alignItems: 'space-between',
|
||||
backgroundColor: DEFAULT_COLOR,
|
||||
borderRadius: LABEL_SIZE / 2,
|
||||
borderWidth: 0,
|
||||
borderRadius: 3,
|
||||
flex: 0,
|
||||
height: LABEL_SIZE,
|
||||
justifyContent: 'center',
|
||||
marginHorizontal: LABEL_MARGIN,
|
||||
opacity: 0.6,
|
||||
width: LABEL_SIZE
|
||||
marginLeft: LABEL_MARGIN,
|
||||
marginBottom: LABEL_MARGIN,
|
||||
paddingHorizontal: 8
|
||||
},
|
||||
|
||||
indicatorIcon: {
|
||||
fontSize: 24
|
||||
},
|
||||
|
||||
indicatorText: {
|
||||
labelText: {
|
||||
color: ColorPalette.white,
|
||||
fontSize: 10
|
||||
fontSize: 12
|
||||
},
|
||||
|
||||
labelOff: {
|
||||
|
|
|
@ -1,130 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { E2EELabel } from '../../e2ee';
|
||||
import { isFilmstripVisible } from '../../filmstrip';
|
||||
import { LocalRecordingLabel } from '../../local-recording';
|
||||
import { RecordingLabel } from '../../recording';
|
||||
import { TranscribingLabel } from '../../transcribing';
|
||||
import { shouldDisplayTileView } from '../../video-layout';
|
||||
import { VideoQualityLabel } from '../../video-quality';
|
||||
|
||||
import { InsecureRoomNameLabel } from '.';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link AbstractLabels}.
|
||||
*/
|
||||
export type Props = {
|
||||
|
||||
/**
|
||||
* Whether the filmstrip is displayed with remote videos. Used to determine
|
||||
* display classes to set.
|
||||
*/
|
||||
_filmstripVisible: boolean,
|
||||
|
||||
/**
|
||||
* Whether the video quality label should be displayed.
|
||||
*/
|
||||
_showVideoQualityLabel: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* A container to hold video status labels, including recording status and
|
||||
* current large video quality.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
export default class AbstractLabels<P: Props, S> extends Component<P, S> {
|
||||
/**
|
||||
* Renders the {@code E2EELabel}.
|
||||
*
|
||||
* @protected
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderE2EELabel() {
|
||||
return (
|
||||
<E2EELabel />
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the {@code LocalRecordingLabel}.
|
||||
*
|
||||
* @protected
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderLocalRecordingLabel() {
|
||||
return (
|
||||
<LocalRecordingLabel />
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the {@code RecordingLabel} that is platform independent.
|
||||
*
|
||||
* @param {string} mode - The recording mode that this label is rendered
|
||||
* for.
|
||||
* @protected
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderRecordingLabel(mode: string) {
|
||||
return (
|
||||
<RecordingLabel mode = { mode } />
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the {@code TranscribingLabel}.
|
||||
*
|
||||
* @protected
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderTranscribingLabel() {
|
||||
return (
|
||||
<TranscribingLabel />
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the {@code InsecureRoomNameLabel}.
|
||||
*
|
||||
* @protected
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderInsecureRoomNameLabel() {
|
||||
return (
|
||||
<InsecureRoomNameLabel />
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the {@code VideoQualityLabel} that is platform independent.
|
||||
*
|
||||
* @protected
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderVideoQualityLabel() {
|
||||
return (
|
||||
<VideoQualityLabel />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps (parts of) the redux state to the associated props of the {@link Labels}
|
||||
* {@code Component}.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @private
|
||||
* @returns {{
|
||||
* _filmstripVisible: boolean,
|
||||
* _showVideoQualityLabel: boolean
|
||||
* }}
|
||||
*/
|
||||
export function _abstractMapStateToProps(state: Object) {
|
||||
return {
|
||||
_filmstripVisible: isFilmstripVisible(state),
|
||||
_showVideoQualityLabel: !shouldDisplayTileView(state)
|
||||
};
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { IconWarning } from '../../../base/icons';
|
||||
import { CircularLabel } from '../../../base/label';
|
||||
import { Label } from '../../../base/label';
|
||||
import { connect } from '../../../base/redux';
|
||||
import AbstractInsecureRoomNameLabel, { _mapStateToProps } from '../AbstractInsecureRoomNameLabel';
|
||||
|
||||
|
@ -20,7 +20,7 @@ class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
|
|||
*/
|
||||
_render() {
|
||||
return (
|
||||
<CircularLabel
|
||||
<Label
|
||||
icon = { IconWarning }
|
||||
style = { styles.insecureRoomNameLabel } />
|
||||
);
|
||||
|
|
|
@ -1,80 +1,22 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { TouchableOpacity, View } from 'react-native';
|
||||
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { ASPECT_RATIO_WIDE } from '../../../base/responsive-ui/constants';
|
||||
import {
|
||||
RecordingExpandedLabel
|
||||
} from '../../../recording';
|
||||
import { TranscribingExpandedLabel } from '../../../transcribing';
|
||||
import { shouldDisplayTileView } from '../../../video-layout';
|
||||
import { VideoQualityExpandedLabel } from '../../../video-quality';
|
||||
import { shouldDisplayNotifications } from '../../functions';
|
||||
import AbstractLabels, {
|
||||
_abstractMapStateToProps,
|
||||
type Props as AbstractLabelsProps
|
||||
} from '../AbstractLabels';
|
||||
import { RecordingLabel, RecordingExpandedLabel } from '../../../recording';
|
||||
import { TranscribingExpandedLabel, TranscribingLabel } from '../../../transcribing';
|
||||
import { VideoQualityExpandedLabel, VideoQualityLabel } from '../../../video-quality';
|
||||
|
||||
import InsecureRoomNameExpandedLabel from './InsecureRoomNameExpandedLabel';
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Labels}.
|
||||
*/
|
||||
type Props = AbstractLabelsProps & {
|
||||
import { InsecureRoomNameLabel } from '.';
|
||||
|
||||
/**
|
||||
* Application's aspect ratio.
|
||||
*/
|
||||
_aspectRatio: Symbol,
|
||||
|
||||
/**
|
||||
* True if tile view is being diaplyed, false otherwise.
|
||||
*/
|
||||
_shouldDisplayTileView: boolean,
|
||||
|
||||
/**
|
||||
* True if the labels should be visible, false otherwise.
|
||||
*/
|
||||
_visible: boolean,
|
||||
|
||||
/**
|
||||
* Function to translate i18n labels.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
type Props = {}
|
||||
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Layout object of the outermost container. For structure please see:
|
||||
* https://facebook.github.io/react-native/docs/view#onlayout
|
||||
*/
|
||||
containerLayout: ?Object,
|
||||
|
||||
/**
|
||||
* Layout objects of the individual labels. This data type contains the same
|
||||
* structure as the layout is defined here:
|
||||
* https://facebook.github.io/react-native/docs/view#onlayout
|
||||
* but keyed with the ID of the label its layout it contains. E.g.
|
||||
*
|
||||
* {
|
||||
* transcribing: {
|
||||
* { layout: { x, y, width, height } }
|
||||
* },
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
labelLayouts: Object,
|
||||
|
||||
/**
|
||||
* Position of the label to render the {@code ExpandedLabel} to.
|
||||
*/
|
||||
parentPosition: ?number,
|
||||
|
||||
/**
|
||||
* String to show which {@code ExpandedLabel} to be shown. (Equals to the
|
||||
* label IDs below.)
|
||||
|
@ -88,26 +30,33 @@ const LABEL_ID_STREAMING = 'streaming';
|
|||
const LABEL_ID_TRANSCRIBING = 'transcribing';
|
||||
const LABEL_ID_INSECURE_ROOM_NAME = 'insecure-room-name';
|
||||
|
||||
const LabelHitSlop = {
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
left: 0,
|
||||
right: 0
|
||||
};
|
||||
|
||||
/**
|
||||
* The {@code ExpandedLabel} components to be rendered for the individual
|
||||
* {@code Label}s.
|
||||
*/
|
||||
const EXPANDED_LABELS = {
|
||||
quality: VideoQualityExpandedLabel,
|
||||
recording: {
|
||||
[LABEL_ID_QUALITY]: VideoQualityExpandedLabel,
|
||||
[LABEL_ID_RECORDING]: {
|
||||
component: RecordingExpandedLabel,
|
||||
props: {
|
||||
mode: JitsiRecordingConstants.mode.FILE
|
||||
}
|
||||
},
|
||||
streaming: {
|
||||
[LABEL_ID_STREAMING]: {
|
||||
component: RecordingExpandedLabel,
|
||||
props: {
|
||||
mode: JitsiRecordingConstants.mode.STREAM
|
||||
}
|
||||
},
|
||||
transcribing: TranscribingExpandedLabel,
|
||||
'insecure-room-name': InsecureRoomNameExpandedLabel
|
||||
[LABEL_ID_TRANSCRIBING]: TranscribingExpandedLabel,
|
||||
[LABEL_ID_INSECURE_ROOM_NAME]: InsecureRoomNameExpandedLabel
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -118,7 +67,7 @@ const EXPANDED_LABEL_TIMEOUT = 5000;
|
|||
/**
|
||||
* A container that renders the conference indicators, if any.
|
||||
*/
|
||||
class Labels extends AbstractLabels<Props, State> {
|
||||
class Labels extends Component<Props, State> {
|
||||
/**
|
||||
* Timeout for the expanded labels to disappear.
|
||||
*/
|
||||
|
@ -131,15 +80,9 @@ class Labels extends AbstractLabels<Props, State> {
|
|||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
containerLayout: undefined,
|
||||
labelLayouts: {},
|
||||
parentPosition: undefined,
|
||||
visibleExpandedLabel: undefined
|
||||
};
|
||||
|
||||
this._onTopViewLayout = this._onTopViewLayout.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,110 +100,49 @@ class Labels extends AbstractLabels<Props, State> {
|
|||
* @inheritdoc
|
||||
*/
|
||||
render() {
|
||||
const { _aspectRatio, _filmstripVisible, _shouldDisplayTileView, _visible } = this.props;
|
||||
|
||||
if (!_visible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const wide = _aspectRatio === ASPECT_RATIO_WIDE;
|
||||
|
||||
return (
|
||||
<>
|
||||
<View pointerEvents = 'box-none'>
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.labelWrapper }>
|
||||
<View
|
||||
onLayout = { this._onTopViewLayout }
|
||||
pointerEvents = 'box-none'
|
||||
style = { [
|
||||
styles.indicatorContainer,
|
||||
wide && _filmstripVisible && !_shouldDisplayTileView
|
||||
&& styles.indicatorContainerWide
|
||||
] }>
|
||||
style = { styles.indicatorContainer }>
|
||||
<TouchableOpacity
|
||||
onLayout = { this._createOnLayout(LABEL_ID_RECORDING) }
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = { this._createOnPress(LABEL_ID_RECORDING) } >
|
||||
{
|
||||
this._renderRecordingLabel(
|
||||
JitsiRecordingConstants.mode.FILE)
|
||||
}
|
||||
<RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onLayout = { this._createOnLayout(LABEL_ID_STREAMING) }
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = { this._createOnPress(LABEL_ID_STREAMING) } >
|
||||
{
|
||||
this._renderRecordingLabel(
|
||||
JitsiRecordingConstants.mode.STREAM)
|
||||
}
|
||||
<RecordingLabel mode = { JitsiRecordingConstants.mode.STREAM } />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onLayout = {
|
||||
this._createOnLayout(LABEL_ID_TRANSCRIBING)
|
||||
}
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = {
|
||||
this._createOnPress(LABEL_ID_TRANSCRIBING)
|
||||
} >
|
||||
{
|
||||
this._renderTranscribingLabel()
|
||||
}
|
||||
<TranscribingLabel />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onLayout = {
|
||||
this._createOnLayout(LABEL_ID_INSECURE_ROOM_NAME)
|
||||
}
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = {
|
||||
this._createOnPress(LABEL_ID_INSECURE_ROOM_NAME)
|
||||
} >
|
||||
{
|
||||
this._renderInsecureRoomNameLabel()
|
||||
}
|
||||
<InsecureRoomNameLabel />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onLayout = {
|
||||
this._createOnLayout(LABEL_ID_QUALITY) }
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = {
|
||||
this._createOnPress(LABEL_ID_QUALITY) } >
|
||||
{ this._renderVideoQualityLabel() }
|
||||
<VideoQualityLabel />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View
|
||||
style = { [
|
||||
styles.indicatorContainer,
|
||||
wide && _filmstripVisible && !_shouldDisplayTileView
|
||||
&& styles.indicatorContainerWide
|
||||
] }>
|
||||
{
|
||||
this._renderExpandedLabel()
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
{ this._renderExpandedLabel() }
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function to be invoked when the onLayout of the touchables are
|
||||
* triggered.
|
||||
*
|
||||
* @param {string} label - The identifier of the label that's onLayout is
|
||||
* triggered.
|
||||
* @returns {Function}
|
||||
*/
|
||||
_createOnLayout(label) {
|
||||
return ({ nativeEvent: { layout } }) => {
|
||||
const { labelLayouts } = this.state;
|
||||
const updatedLayout = {};
|
||||
|
||||
updatedLayout[label] = layout;
|
||||
|
||||
this.setState({
|
||||
labelLayouts: {
|
||||
...labelLayouts,
|
||||
...updatedLayout
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function to be invoked when the onPress of the touchables are
|
||||
* triggered.
|
||||
|
@ -271,25 +153,13 @@ class Labels extends AbstractLabels<Props, State> {
|
|||
*/
|
||||
_createOnPress(label) {
|
||||
return () => {
|
||||
const {
|
||||
containerLayout,
|
||||
labelLayouts
|
||||
} = this.state;
|
||||
let { visibleExpandedLabel } = this.state;
|
||||
|
||||
if (containerLayout) {
|
||||
const labelLayout = labelLayouts[label];
|
||||
|
||||
// This calculation has to be changed if the labels are not
|
||||
// positioned right anymore.
|
||||
const right = containerLayout.width - labelLayout.x;
|
||||
|
||||
visibleExpandedLabel
|
||||
= visibleExpandedLabel === label ? undefined : label;
|
||||
|
||||
clearTimeout(this.expandedLabelTimeout);
|
||||
this.setState({
|
||||
parentPosition: right,
|
||||
visibleExpandedLabel
|
||||
});
|
||||
|
||||
|
@ -300,73 +170,30 @@ class Labels extends AbstractLabels<Props, State> {
|
|||
});
|
||||
}, EXPANDED_LABEL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_onTopViewLayout: Object => void
|
||||
|
||||
/**
|
||||
* Invoked when the View containing the {@code Label}s is laid out.
|
||||
*
|
||||
* @param {Object} layout - The native layout object.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onTopViewLayout({ nativeEvent: { layout } }) {
|
||||
this.setState({
|
||||
containerLayout: layout
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendes the expanded (explaining) label for the label that was touched.
|
||||
*
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderExpandedLabel() {
|
||||
const { parentPosition, visibleExpandedLabel } = this.state;
|
||||
const { visibleExpandedLabel } = this.state;
|
||||
|
||||
if (visibleExpandedLabel) {
|
||||
const expandedLabel = EXPANDED_LABELS[visibleExpandedLabel];
|
||||
|
||||
if (expandedLabel) {
|
||||
const component = expandedLabel.component || expandedLabel;
|
||||
const expandedLabelProps = expandedLabel.props || {};
|
||||
const LabelComponent = expandedLabel.component || expandedLabel;
|
||||
const { props } = expandedLabel || {};
|
||||
|
||||
return React.createElement(component, {
|
||||
...expandedLabelProps,
|
||||
parentPosition
|
||||
});
|
||||
return <LabelComponent { ...props } />;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
_renderRecordingLabel: string => React$Element<any>;
|
||||
|
||||
_renderTranscribingLabel: () => React$Element<any>;
|
||||
|
||||
_renderInsecureRoomNameLabel: () => React$Element<any>;
|
||||
|
||||
_renderVideoQualityLabel: () => React$Element<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps (parts of) the redux state to the associated
|
||||
* {@code Labels}'s props.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @private
|
||||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
return {
|
||||
..._abstractMapStateToProps(state),
|
||||
_aspectRatio: state['features/base/responsive-ui'].aspectRatio,
|
||||
_shouldDisplayTileView: shouldDisplayTileView(state),
|
||||
_visible: !shouldDisplayNotifications(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(_mapStateToProps)(Labels);
|
||||
export default Labels;
|
||||
|
|
|
@ -55,9 +55,6 @@ const NavigationBar = (props: Props) => {
|
|||
style = { styles.navBarWrapper }>
|
||||
<PictureInPictureButton
|
||||
styles = { styles.navBarButton } />
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.roomNameContainer }>
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.roomNameWrapper }>
|
||||
|
@ -77,7 +74,6 @@ const NavigationBar = (props: Props) => {
|
|||
<ConferenceTimer textStyle = { styles.roomTimer } />
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
<Labels />
|
||||
</View>
|
||||
</View>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
|
||||
import { BoxModel, ColorPalette, fixAndroidViewClipping } from '../../../base/styles';
|
||||
import { FILMSTRIP_SIZE } from '../../../filmstrip';
|
||||
|
||||
export const INSECURE_ROOM_NAME_LABEL_COLOR = ColorPalette.warning;
|
||||
|
||||
|
@ -27,23 +26,9 @@ export default {
|
|||
*/
|
||||
indicatorContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end'
|
||||
flexDirection: 'row'
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicator container for wide aspect ratio.
|
||||
*/
|
||||
indicatorContainerWide: {
|
||||
marginRight: FILMSTRIP_SIZE + BoxModel.margin
|
||||
},
|
||||
|
||||
labelWrapper: {
|
||||
flexDirection: 'column',
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
top: 0
|
||||
},
|
||||
|
||||
lonelyButton: {
|
||||
alignItems: 'center',
|
||||
|
@ -77,14 +62,6 @@ export default {
|
|||
underlayColor: 'transparent'
|
||||
},
|
||||
|
||||
navBarContainer: {
|
||||
flexDirection: 'column',
|
||||
left: 0,
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
top: 0
|
||||
},
|
||||
|
||||
navBarSafeView: {
|
||||
left: 0,
|
||||
position: 'absolute',
|
||||
|
@ -97,14 +74,15 @@ export default {
|
|||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
height: 44,
|
||||
justifyContent: 'space-between',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 14
|
||||
},
|
||||
|
||||
roomTimer: {
|
||||
color: ColorPalette.white,
|
||||
fontSize: 12,
|
||||
fontWeight: '400'
|
||||
fontWeight: '400',
|
||||
paddingHorizontal: 8
|
||||
},
|
||||
|
||||
roomTimerView: {
|
||||
|
@ -113,7 +91,7 @@ export default {
|
|||
borderTopRightRadius: 3,
|
||||
height: 28,
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 10
|
||||
minWidth: 50
|
||||
},
|
||||
|
||||
roomName: {
|
||||
|
@ -126,21 +104,13 @@ export default {
|
|||
backgroundColor: 'rgba(0,0,0,0.6)',
|
||||
borderBottomLeftRadius: 3,
|
||||
borderTopLeftRadius: 3,
|
||||
flexShrink: 1,
|
||||
height: 28,
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 10
|
||||
},
|
||||
|
||||
roomNameContainer: {
|
||||
alignItems: 'center',
|
||||
left: 0,
|
||||
paddingHorizontal: 48,
|
||||
position: 'absolute',
|
||||
right: 0
|
||||
},
|
||||
|
||||
roomNameWrapper: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
} from '../AbstractConference';
|
||||
import type { AbstractProps } from '../AbstractConference';
|
||||
|
||||
import Labels from './Labels';
|
||||
import ConferenceInfo from './ConferenceInfo';
|
||||
import { default as Notice } from './Notice';
|
||||
|
||||
declare var APP: Object;
|
||||
|
@ -67,11 +67,6 @@ type Props = AbstractProps & {
|
|||
*/
|
||||
_backgroundAlpha: number,
|
||||
|
||||
/**
|
||||
* Whether the local participant is recording the conference.
|
||||
*/
|
||||
_iAmRecorder: boolean,
|
||||
|
||||
/**
|
||||
* Returns true if the 'lobby screen' is visible.
|
||||
*/
|
||||
|
@ -183,12 +178,10 @@ class Conference extends AbstractConference<Props, *> {
|
|||
*/
|
||||
render() {
|
||||
const {
|
||||
_iAmRecorder,
|
||||
_isLobbyScreenVisible,
|
||||
_layoutClassName,
|
||||
_showPrejoin
|
||||
} = this.props;
|
||||
const hideLabels = _iAmRecorder;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -196,13 +189,13 @@ class Conference extends AbstractConference<Props, *> {
|
|||
id = 'videoconference_page'
|
||||
onMouseMove = { this._onShowToolbar }
|
||||
ref = { this._setBackground }>
|
||||
<ConferenceInfo />
|
||||
|
||||
<Notice />
|
||||
<div id = 'videospace'>
|
||||
<LargeVideo />
|
||||
<KnockingParticipantList />
|
||||
<Filmstrip />
|
||||
{ hideLabels || <Labels /> }
|
||||
</div>
|
||||
|
||||
{ _showPrejoin || _isLobbyScreenVisible || <Toolbox /> }
|
||||
|
@ -302,7 +295,6 @@ class Conference extends AbstractConference<Props, *> {
|
|||
function _mapStateToProps(state) {
|
||||
return {
|
||||
...abstractMapStateToProps(state),
|
||||
_iAmRecorder: state['features/base/config'].iAmRecorder,
|
||||
_backgroundAlpha: state['features/base/config'].backgroundAlpha,
|
||||
_isLobbyScreenVisible: state['features/base/dialog']?.component === LobbyScreen,
|
||||
_layoutClassName: LAYOUT_CLASSNAMES[getCurrentLayout(state)],
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { getConferenceName } from '../../../base/conference/functions';
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import { getParticipantCount } from '../../../base/participants/functions';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { E2EELabel } from '../../../e2ee';
|
||||
import { LocalRecordingLabel } from '../../../local-recording';
|
||||
import { RecordingLabel } from '../../../recording';
|
||||
import { isToolboxVisible } from '../../../toolbox/functions.web';
|
||||
import { TranscribingLabel } from '../../../transcribing';
|
||||
import { VideoQualityLabel } from '../../../video-quality';
|
||||
import ConferenceTimer from '../ConferenceTimer';
|
||||
|
||||
import ParticipantsCount from './ParticipantsCount';
|
||||
|
||||
import { InsecureRoomNameLabel } from '.';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Subject}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether the info should span across the full width.
|
||||
*/
|
||||
_fullWidth: boolean,
|
||||
|
||||
/**
|
||||
* Whether the conference name and timer should be displayed or not.
|
||||
*/
|
||||
_hideConferenceNameAndTimer: boolean,
|
||||
|
||||
/**
|
||||
* Whether the conference timer should be shown or not.
|
||||
*/
|
||||
_hideConferenceTimer: boolean,
|
||||
|
||||
/**
|
||||
* Whether the participant count should be shown or not.
|
||||
*/
|
||||
_showParticipantCount: boolean,
|
||||
|
||||
/**
|
||||
* The subject or the of the conference.
|
||||
* Falls back to conference name.
|
||||
*/
|
||||
_subject: string,
|
||||
|
||||
/**
|
||||
* Indicates whether the component should be visible or not.
|
||||
*/
|
||||
_visible: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* The upper band of the meeing containing the conference name, timer and labels.
|
||||
*
|
||||
* @param {Object} props - The props of the component.
|
||||
* @returns {React$None}
|
||||
*/
|
||||
function ConferenceInfo(props: Props) {
|
||||
const {
|
||||
_hideConferenceNameAndTimer,
|
||||
_hideConferenceTimer,
|
||||
_showParticipantCount,
|
||||
_subject,
|
||||
_fullWidth,
|
||||
_visible
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div className = { `subject ${_visible ? 'visible' : ''}` }>
|
||||
<div className = { `subject-info-container${_fullWidth ? ' subject-info-container--full-width' : ''}` }>
|
||||
{
|
||||
!_hideConferenceNameAndTimer
|
||||
&& <div className = 'subject-info'>
|
||||
{ _subject && <span className = 'subject-text'>{ _subject }</span>}
|
||||
{ !_hideConferenceTimer && <ConferenceTimer /> }
|
||||
</div>
|
||||
}
|
||||
{ _showParticipantCount && <ParticipantsCount /> }
|
||||
<E2EELabel />
|
||||
<RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />
|
||||
<RecordingLabel mode = { JitsiRecordingConstants.mode.STREAM } />
|
||||
<LocalRecordingLabel />
|
||||
<TranscribingLabel />
|
||||
<VideoQualityLabel />
|
||||
<InsecureRoomNameLabel />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps (parts of) the Redux state to the associated
|
||||
* {@code Subject}'s props.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @private
|
||||
* @returns {{
|
||||
* _hideConferenceTimer: boolean,
|
||||
* _showParticipantCount: boolean,
|
||||
* _subject: string,
|
||||
* _visible: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
const participantCount = getParticipantCount(state);
|
||||
const { hideConferenceTimer, hideConferenceSubject, hideParticipantsStats } = state['features/base/config'];
|
||||
const { clientWidth } = state['features/base/responsive-ui'];
|
||||
|
||||
return {
|
||||
_hideConferenceNameAndTimer: clientWidth < 300,
|
||||
_hideConferenceTimer: Boolean(hideConferenceTimer),
|
||||
_fullWidth: state['features/video-layout'].tileViewEnabled,
|
||||
_showParticipantCount: participantCount > 2 && !hideParticipantsStats,
|
||||
_subject: hideConferenceSubject ? '' : getConferenceName(state),
|
||||
_visible: isToolboxVisible(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(_mapStateToProps)(ConferenceInfo);
|
|
@ -14,6 +14,6 @@ import React from 'react';
|
|||
*/
|
||||
export default function renderConferenceTimer(timerValue: string, textStyle: Object) {
|
||||
return (
|
||||
<span className = 'subject-conference-timer' >{ timerValue }</span>
|
||||
<span className = 'subject-timer'>{ timerValue }</span>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import React from 'react';
|
|||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { IconWarning } from '../../../base/icons';
|
||||
import { CircularLabel } from '../../../base/label';
|
||||
import { Label } from '../../../base/label';
|
||||
import { connect } from '../../../base/redux';
|
||||
import AbstractInsecureRoomNameLabel, { _mapStateToProps } from '../AbstractInsecureRoomNameLabel';
|
||||
|
||||
|
@ -22,9 +22,9 @@ class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
|
|||
return (
|
||||
<Tooltip
|
||||
content = { this.props.t('security.insecureRoomNameWarning') }
|
||||
position = 'left'>
|
||||
<CircularLabel
|
||||
className = 'insecure'
|
||||
position = 'bottom'>
|
||||
<Label
|
||||
className = 'label--red'
|
||||
icon = { IconWarning } />
|
||||
</Tooltip>
|
||||
);
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import { connect } from '../../../base/redux';
|
||||
import AbstractLabels, {
|
||||
_abstractMapStateToProps as _mapStateToProps,
|
||||
type Props
|
||||
} from '../AbstractLabels';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link Labels}.
|
||||
*/
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* Whether or not the filmstrip was not visible but has transitioned in the
|
||||
* latest component update to visible. This boolean is used to set a class
|
||||
* for position animations.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
filmstripBecomingVisible: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* A container to hold video status labels, including recording status and
|
||||
* current large video quality.
|
||||
*
|
||||
* @extends Component
|
||||
*/
|
||||
class Labels extends AbstractLabels<Props, State> {
|
||||
/**
|
||||
* Updates the state for whether or not the filmstrip is transitioning to
|
||||
* a displayed state.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static getDerivedStateFromProps(props: Props, prevState: State) {
|
||||
return {
|
||||
filmstripBecomingVisible: !prevState.filmstripBecomingVisible && props._filmstripVisible
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new {@code Labels} instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
filmstripBecomingVisible: false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { _filmstripVisible } = this.props;
|
||||
const { filmstripBecomingVisible } = this.state;
|
||||
const { VIDEO_QUALITY_LABEL_DISABLED } = interfaceConfig;
|
||||
const className = `large-video-labels ${
|
||||
filmstripBecomingVisible ? 'opening' : ''} ${
|
||||
_filmstripVisible ? 'with-filmstrip' : 'without-filmstrip'}`;
|
||||
|
||||
return (
|
||||
<div className = { className } >
|
||||
{
|
||||
this._renderE2EELabel()
|
||||
}
|
||||
{
|
||||
this._renderRecordingLabel(
|
||||
JitsiRecordingConstants.mode.FILE)
|
||||
}
|
||||
{
|
||||
this._renderRecordingLabel(
|
||||
JitsiRecordingConstants.mode.STREAM)
|
||||
}
|
||||
{
|
||||
this._renderLocalRecordingLabel()
|
||||
}
|
||||
{
|
||||
this._renderTranscribingLabel()
|
||||
}
|
||||
{
|
||||
this.props._showVideoQualityLabel && !VIDEO_QUALITY_LABEL_DISABLED
|
||||
&& this._renderVideoQualityLabel()
|
||||
}
|
||||
{
|
||||
this._renderInsecureRoomNameLabel()
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_renderE2EELabel: () => React$Element<*>;
|
||||
|
||||
_renderLocalRecordingLabel: () => React$Element<*>;
|
||||
|
||||
_renderRecordingLabel: string => React$Element<*>;
|
||||
|
||||
_renderTranscribingLabel: () => React$Element<*>;
|
||||
|
||||
_renderInsecureRoomNameLabel: () => React$Element<any>;
|
||||
|
||||
_renderVideoQualityLabel: () => React$Element<*>;
|
||||
}
|
||||
|
||||
export default connect(_mapStateToProps)(Labels);
|
|
@ -4,10 +4,13 @@ import React, { PureComponent } from 'react';
|
|||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { openDialog } from '../../../base/dialog';
|
||||
import { IconUserGroups } from '../../../base/icons';
|
||||
import { Label } from '../../../base/label';
|
||||
import { getParticipantCount } from '../../../base/participants';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { SpeakerStats } from '../../../speaker-stats';
|
||||
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link ParticipantsCount}.
|
||||
*/
|
||||
|
@ -73,10 +76,10 @@ class ParticipantsCount extends PureComponent<Props> {
|
|||
<div
|
||||
className = 'participants-count'
|
||||
onClick = { this._onClick }>
|
||||
<span className = 'participants-count-number'>
|
||||
{this.props.count}
|
||||
</span>
|
||||
<span className = 'participants-count-icon' />
|
||||
<Label
|
||||
className = 'label--white'
|
||||
icon = { IconUserGroups }
|
||||
text = { this.props.count } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { getConferenceName } from '../../../base/conference/functions';
|
||||
import { getParticipantCount } from '../../../base/participants/functions';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { isToolboxVisible } from '../../../toolbox/functions.web';
|
||||
import ConferenceTimer from '../ConferenceTimer';
|
||||
|
||||
import ParticipantsCount from './ParticipantsCount';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Subject}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Whether the conference timer should be shown or not.
|
||||
*/
|
||||
_hideConferenceTimer: Boolean,
|
||||
|
||||
/**
|
||||
* Whether the participant count should be shown or not.
|
||||
*/
|
||||
_showParticipantCount: boolean,
|
||||
|
||||
/**
|
||||
* Whether the conference subject should be shown or not.
|
||||
*/
|
||||
_showSubject: boolean,
|
||||
|
||||
/**
|
||||
* The subject or the of the conference.
|
||||
* Falls back to conference name.
|
||||
*/
|
||||
_subject: string,
|
||||
|
||||
/**
|
||||
* Indicates whether the component should be visible or not.
|
||||
*/
|
||||
_visible: boolean
|
||||
};
|
||||
|
||||
/**
|
||||
* Subject react component.
|
||||
*
|
||||
* @class Subject
|
||||
*/
|
||||
class Subject extends Component<Props> {
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { _hideConferenceTimer, _showParticipantCount, _showSubject, _subject, _visible } = this.props;
|
||||
let className = `subject ${_visible ? 'visible' : ''}`;
|
||||
|
||||
if (!_hideConferenceTimer || _showParticipantCount || _showSubject) {
|
||||
className += ' gradient';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className = { className }>
|
||||
{ _showSubject && <span className = 'subject-text'>{ _subject }</span>}
|
||||
{ _showParticipantCount && <ParticipantsCount /> }
|
||||
{ !_hideConferenceTimer && <ConferenceTimer /> }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps (parts of) the Redux state to the associated
|
||||
* {@code Subject}'s props.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @private
|
||||
* @returns {{
|
||||
* _hideConferenceTimer: boolean,
|
||||
* _showParticipantCount: boolean,
|
||||
* _showSubject: boolean,
|
||||
* _subject: string,
|
||||
* _visible: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
const participantCount = getParticipantCount(state);
|
||||
const { hideConferenceTimer, hideConferenceSubject, hideParticipantsStats } = state['features/base/config'];
|
||||
|
||||
return {
|
||||
_hideConferenceTimer: Boolean(hideConferenceTimer),
|
||||
_showParticipantCount: participantCount > 2 && !hideParticipantsStats,
|
||||
_showSubject: !hideConferenceSubject,
|
||||
_subject: getConferenceName(state),
|
||||
_visible: isToolboxVisible(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(_mapStateToProps)(Subject);
|
|
@ -4,4 +4,4 @@ export { default as Conference } from './Conference';
|
|||
export { default as renderConferenceTimer } from './ConferenceTimerDisplay';
|
||||
export { default as InsecureRoomNameLabel } from './InsecureRoomNameLabel';
|
||||
export { default as InviteMore } from './InviteMore';
|
||||
export { default as Subject } from './Subject';
|
||||
export { default as ConferenceInfo } from './ConferenceInfo';
|
||||
|
|
|
@ -4,7 +4,7 @@ import React, { Component } from 'react';
|
|||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { IconE2EE } from '../../base/icons';
|
||||
import { CircularLabel } from '../../base/label';
|
||||
import { Label } from '../../base/label';
|
||||
import { connect } from '../../base/redux';
|
||||
import { Tooltip } from '../../base/tooltip';
|
||||
|
||||
|
@ -32,9 +32,9 @@ class E2EELabel extends Component<Props> {
|
|||
return (
|
||||
<Tooltip
|
||||
content = { this.props.t('e2ee.labelToolTip') }
|
||||
position = { 'left' }>
|
||||
<CircularLabel
|
||||
className = 'e2ee'
|
||||
position = { 'bottom' }>
|
||||
<Label
|
||||
className = 'label--green'
|
||||
icon = { IconE2EE } />
|
||||
</Tooltip>
|
||||
);
|
||||
|
|
|
@ -5,7 +5,6 @@ import React, { Component } from 'react';
|
|||
import { Watermarks } from '../../base/react';
|
||||
import { connect } from '../../base/redux';
|
||||
import { setColorAlpha } from '../../base/util';
|
||||
import { Subject } from '../../conference';
|
||||
import { fetchCustomBrandingData } from '../../dynamic-branding';
|
||||
import { Captions } from '../../subtitles/';
|
||||
|
||||
|
@ -76,7 +75,6 @@ class LargeVideo extends Component<Props> {
|
|||
className = { className }
|
||||
id = 'largeVideoContainer'
|
||||
style = { style }>
|
||||
<Subject />
|
||||
<div id = 'sharedVideo'>
|
||||
<div id = 'sharedVideoIFrame' />
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n/index';
|
||||
import { CircularLabel } from '../../base/label/index';
|
||||
import { Label } from '../../base/label/index';
|
||||
import { connect } from '../../base/redux';
|
||||
import { Tooltip } from '../../base/tooltip';
|
||||
|
||||
|
@ -45,10 +45,10 @@ class LocalRecordingLabel extends Component<Props> {
|
|||
return (
|
||||
<Tooltip
|
||||
content = { this.props.t('localRecording.labelToolTip') }
|
||||
position = { 'left' }>
|
||||
<CircularLabel
|
||||
position = { 'bottom' }>
|
||||
<Label
|
||||
className = 'local-rec'
|
||||
label = { this.props.t('localRecording.label') } />
|
||||
text = { this.props.t('localRecording.label') } />
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { CircularLabel } from '../../../base/label';
|
||||
import { Label } from '../../../base/label';
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import { connect } from '../../../base/redux';
|
||||
import AbstractRecordingLabel, {
|
||||
|
@ -52,10 +52,10 @@ class RecordingLabel extends AbstractRecordingLabel {
|
|||
}
|
||||
|
||||
return (
|
||||
<CircularLabel
|
||||
label = { this.props.t(this._getLabelKey()) }
|
||||
<Label
|
||||
status = { status }
|
||||
style = { indicatorStyle } />
|
||||
style = { indicatorStyle }
|
||||
text = { this.props.t(this._getLabelKey()) } />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { CircularLabel } from '../../../base/label';
|
||||
import { Label } from '../../../base/label';
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import { connect } from '../../../base/redux';
|
||||
import AbstractRecordingLabel, {
|
||||
|
@ -31,9 +31,9 @@ class RecordingLabel extends AbstractRecordingLabel {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<CircularLabel
|
||||
<Label
|
||||
className = { this.props.mode }
|
||||
label = { this.props.t(this._getLabelKey()) } />
|
||||
text = { this.props.t(this._getLabelKey()) } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { CircularLabel } from '../../base/label';
|
||||
import { Label } from '../../base/label';
|
||||
import { connect } from '../../base/redux';
|
||||
|
||||
import { _mapStateToProps, type Props } from './AbstractTranscribingLabel';
|
||||
|
@ -26,10 +26,7 @@ class TranscribingLabel extends Component<Props> {
|
|||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<CircularLabel
|
||||
label = { this.props.t('transcribing.tr') } />
|
||||
);
|
||||
return <Label text = { this.props.t('transcribing.tr') } />;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { CircularLabel } from '../../base/label';
|
||||
import { Label } from '../../base/label';
|
||||
import { connect } from '../../base/redux';
|
||||
import { Tooltip } from '../../base/tooltip';
|
||||
|
||||
|
@ -32,9 +32,9 @@ class TranscribingLabel extends Component<Props> {
|
|||
<Tooltip
|
||||
content = { this.props.t('transcribing.labelToolTip') }
|
||||
position = { 'left' }>
|
||||
<CircularLabel
|
||||
<Label
|
||||
className = 'recording-label'
|
||||
label = { this.props.t('transcribing.tr') } />
|
||||
text = { this.props.t('transcribing.tr') } />
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { CircularLabel } from '../../base/label';
|
||||
import { Label } from '../../base/label';
|
||||
import { connect } from '../../base/redux';
|
||||
import { combineStyles, type StyleType } from '../../base/styles';
|
||||
|
||||
|
@ -46,11 +46,9 @@ class VideoQualityLabel extends AbstractVideoQualityLabel<Props> {
|
|||
}
|
||||
|
||||
return (
|
||||
<CircularLabel
|
||||
label = { t('videoStatus.audioOnly') }
|
||||
style = {
|
||||
combineStyles(styles.indicatorAudioOnly, style)
|
||||
} />
|
||||
<Label
|
||||
style = { combineStyles(styles.indicatorAudioOnly, style) }
|
||||
text = { t('videoStatus.audioOnly') } />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,17 +3,20 @@
|
|||
import React from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { CircularLabel } from '../../base/label';
|
||||
import { Label } from '../../base/label';
|
||||
import { MEDIA_TYPE } from '../../base/media';
|
||||
import { connect } from '../../base/redux';
|
||||
import { Tooltip } from '../../base/tooltip';
|
||||
import { getTrackByMediaTypeAndParticipant } from '../../base/tracks';
|
||||
import { shouldDisplayTileView } from '../../video-layout';
|
||||
|
||||
import AbstractVideoQualityLabel, {
|
||||
_abstractMapStateToProps,
|
||||
type Props as AbstractProps
|
||||
} from './AbstractVideoQualityLabel';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
type Props = AbstractProps & {
|
||||
|
||||
/**
|
||||
|
@ -21,6 +24,11 @@ type Props = AbstractProps & {
|
|||
*/
|
||||
_labelKey: string,
|
||||
|
||||
/**
|
||||
* Whether to show video quality label or not.
|
||||
*/
|
||||
_showVideoQualityLabel: boolean,
|
||||
|
||||
/**
|
||||
* The message to show within the label's tooltip.
|
||||
*/
|
||||
|
@ -29,7 +37,12 @@ type Props = AbstractProps & {
|
|||
/**
|
||||
* The redux representation of the JitsiTrack displayed on large video.
|
||||
*/
|
||||
_videoTrack: Object
|
||||
_videoTrack: Object,
|
||||
|
||||
/**
|
||||
* Flag controlling visibility of the component.
|
||||
*/
|
||||
_visible: boolean,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -75,10 +88,15 @@ export class VideoQualityLabel extends AbstractVideoQualityLabel<Props> {
|
|||
_labelKey,
|
||||
_tooltipKey,
|
||||
_videoTrack,
|
||||
_visible,
|
||||
t
|
||||
} = this.props;
|
||||
|
||||
|
||||
if (!_visible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let className, labelContent, tooltipKey;
|
||||
|
||||
if (_audioOnly) {
|
||||
|
@ -99,11 +117,11 @@ export class VideoQualityLabel extends AbstractVideoQualityLabel<Props> {
|
|||
return (
|
||||
<Tooltip
|
||||
content = { t(tooltipKey) }
|
||||
position = { 'left' }>
|
||||
<CircularLabel
|
||||
position = { 'bottom' }>
|
||||
<Label
|
||||
className = { className }
|
||||
id = 'videoResolutionLabel'
|
||||
label = { labelContent } />
|
||||
text = { labelContent } />
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
@ -171,7 +189,8 @@ function _mapStateToProps(state) {
|
|||
..._abstractMapStateToProps(state),
|
||||
_labelKey: translationKeys.labelKey,
|
||||
_tooltipKey: translationKeys.tooltipKey,
|
||||
_videoTrack: videoTrackOnLargeVideo
|
||||
_videoTrack: videoTrackOnLargeVideo,
|
||||
_visible: !(shouldDisplayTileView(state) || interfaceConfig.VIDEO_QUALITY_LABEL_DISABLED)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue