mirror of https://github.com/jitsi/jitsi-meet
feat(title-bar) Update design (#12851)
Convert some files to TS Move some styles from SCSS to JSS Update designpull/12868/head jitsi-meet_8274
parent
a594aac078
commit
09e4696c60
@ -1,180 +0,0 @@ |
||||
// @flow
|
||||
|
||||
import { Component } from 'react'; |
||||
|
||||
import { renderConferenceTimer } from '../'; |
||||
import { getConferenceTimestamp } from '../../base/conference/functions'; |
||||
import { getLocalizedDurationFormatter } from '../../base/i18n'; |
||||
import { connect } from '../../base/redux'; |
||||
|
||||
/** |
||||
* The type of the React {@code Component} props of {@link ConferenceTimer}. |
||||
*/ |
||||
type Props = { |
||||
|
||||
/** |
||||
* The UTC timestamp representing the time when first participant joined. |
||||
*/ |
||||
_startTimestamp: ?number, |
||||
|
||||
/** |
||||
* Style to be applied to the rendered text. |
||||
*/ |
||||
textStyle: ?Object, |
||||
|
||||
/** |
||||
* The redux {@code dispatch} function. |
||||
*/ |
||||
dispatch: Function |
||||
}; |
||||
|
||||
/** |
||||
* The type of the React {@code Component} state of {@link ConferenceTimer}. |
||||
*/ |
||||
type State = { |
||||
|
||||
/** |
||||
* Value of current conference time. |
||||
*/ |
||||
timerValue: string |
||||
}; |
||||
|
||||
/** |
||||
* ConferenceTimer react component. |
||||
* |
||||
* @class ConferenceTimer |
||||
* @augments Component |
||||
*/ |
||||
class ConferenceTimer extends Component<Props, State> { |
||||
|
||||
/** |
||||
* Handle for setInterval timer. |
||||
*/ |
||||
_interval; |
||||
|
||||
/** |
||||
* Initializes a new {@code ConferenceTimer} instance. |
||||
* |
||||
* @param {Props} props - The read-only properties with which the new |
||||
* instance is to be initialized. |
||||
*/ |
||||
constructor(props: Props) { |
||||
super(props); |
||||
|
||||
this.state = { |
||||
timerValue: getLocalizedDurationFormatter(0) |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Starts the conference timer when component will be |
||||
* mounted. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
componentDidMount() { |
||||
this._startTimer(); |
||||
} |
||||
|
||||
/** |
||||
* Stops the conference timer when component will be |
||||
* unmounted. |
||||
* |
||||
* @inheritdoc |
||||
*/ |
||||
componentWillUnmount() { |
||||
this._stopTimer(); |
||||
} |
||||
|
||||
/** |
||||
* Implements React's {@link Component#render()}. |
||||
* |
||||
* @inheritdoc |
||||
* @returns {ReactElement} |
||||
*/ |
||||
render() { |
||||
const { timerValue } = this.state; |
||||
const { _startTimestamp, textStyle } = this.props; |
||||
|
||||
if (!_startTimestamp) { |
||||
return null; |
||||
} |
||||
|
||||
return renderConferenceTimer(timerValue, textStyle); |
||||
} |
||||
|
||||
/** |
||||
* Sets the current state values that will be used to render the timer. |
||||
* |
||||
* @param {number} refValueUTC - The initial UTC timestamp value. |
||||
* @param {number} currentValueUTC - The current UTC timestamp value. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
_setStateFromUTC(refValueUTC, currentValueUTC) { |
||||
if (!refValueUTC || !currentValueUTC) { |
||||
return; |
||||
} |
||||
|
||||
if (currentValueUTC < refValueUTC) { |
||||
return; |
||||
} |
||||
|
||||
const timerMsValue = currentValueUTC - refValueUTC; |
||||
|
||||
const localizedTime = getLocalizedDurationFormatter(timerMsValue); |
||||
|
||||
this.setState({ |
||||
timerValue: localizedTime |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Start conference timer. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
_startTimer() { |
||||
if (!this._interval) { |
||||
this._setStateFromUTC(this.props._startTimestamp, new Date().getTime()); |
||||
|
||||
this._interval = setInterval(() => { |
||||
this._setStateFromUTC(this.props._startTimestamp, new Date().getTime()); |
||||
}, 1000); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Stop conference timer. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
_stopTimer() { |
||||
if (this._interval) { |
||||
clearInterval(this._interval); |
||||
} |
||||
|
||||
this.setState({ |
||||
timerValue: getLocalizedDurationFormatter(0) |
||||
}); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Maps (parts of) the Redux state to the associated |
||||
* {@code ConferenceTimer}'s props. |
||||
* |
||||
* @param {Object} state - The Redux state. |
||||
* @private |
||||
* @returns {{ |
||||
* _startTimestamp: number |
||||
* }} |
||||
*/ |
||||
export function _mapStateToProps(state: Object) { |
||||
|
||||
return { |
||||
_startTimestamp: getConferenceTimestamp(state) |
||||
}; |
||||
} |
||||
|
||||
export default connect(_mapStateToProps)(ConferenceTimer); |
@ -0,0 +1,106 @@ |
||||
import React, { useCallback, useEffect, useRef, useState } from 'react'; |
||||
import { useSelector } from 'react-redux'; |
||||
|
||||
// @ts-ignore
|
||||
import { ConferenceTimerDisplay } from '..'; |
||||
import { getConferenceTimestamp } from '../../base/conference/functions'; |
||||
import { getLocalizedDurationFormatter } from '../../base/i18n/dateUtil'; |
||||
|
||||
/** |
||||
* The type of the React {@code Component} props of {@link ConferenceTimer}. |
||||
*/ |
||||
interface IProps { |
||||
|
||||
/** |
||||
* Style to be applied to the rendered text. |
||||
*/ |
||||
textStyle?: Object; |
||||
} |
||||
|
||||
export interface IDisplayProps { |
||||
|
||||
/** |
||||
* Style to be applied to text (native only). |
||||
*/ |
||||
textStyle: Object; |
||||
|
||||
/** |
||||
* String to display as time. |
||||
*/ |
||||
timerValue: string; |
||||
} |
||||
|
||||
const ConferenceTimer = ({ textStyle }: IProps) => { |
||||
const startTimestamp = useSelector(getConferenceTimestamp); |
||||
const [ timerValue, setTimerValue ] = useState(getLocalizedDurationFormatter(0)); |
||||
const interval = useRef<number>(); |
||||
|
||||
/** |
||||
* Sets the current state values that will be used to render the timer. |
||||
* |
||||
* @param {number} refValueUTC - The initial UTC timestamp value. |
||||
* @param {number} currentValueUTC - The current UTC timestamp value. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
const setStateFromUTC = useCallback((refValueUTC, currentValueUTC) => { |
||||
if (!refValueUTC || !currentValueUTC) { |
||||
return; |
||||
} |
||||
|
||||
if (currentValueUTC < refValueUTC) { |
||||
return; |
||||
} |
||||
|
||||
const timerMsValue = currentValueUTC - refValueUTC; |
||||
|
||||
const localizedTime = getLocalizedDurationFormatter(timerMsValue); |
||||
|
||||
setTimerValue(localizedTime); |
||||
}, []); |
||||
|
||||
/** |
||||
* Start conference timer. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
const startTimer = useCallback(() => { |
||||
if (!interval.current && startTimestamp) { |
||||
setStateFromUTC(startTimestamp, new Date().getTime()); |
||||
|
||||
interval.current = window.setInterval(() => { |
||||
setStateFromUTC(startTimestamp, new Date().getTime()); |
||||
}, 1000); |
||||
} |
||||
}, [ startTimestamp, interval ]); |
||||
|
||||
/** |
||||
* Stop conference timer. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
const stopTimer = useCallback(() => { |
||||
if (interval.current) { |
||||
clearInterval(interval.current); |
||||
} |
||||
|
||||
setTimerValue(getLocalizedDurationFormatter(0)); |
||||
}, [ interval ]); |
||||
|
||||
useEffect(() => { |
||||
startTimer(); |
||||
|
||||
return () => stopTimer(); |
||||
}, [ startTimestamp ]); |
||||
|
||||
|
||||
if (!startTimestamp) { |
||||
return null; |
||||
} |
||||
|
||||
return (<ConferenceTimerDisplay |
||||
textStyle = { textStyle } |
||||
timerValue = { timerValue } />); |
||||
}; |
||||
|
||||
export default ConferenceTimer; |
@ -1,17 +1,16 @@ |
||||
// @flow
|
||||
|
||||
import React from 'react'; |
||||
import { Text } from 'react-native'; |
||||
|
||||
import { IDisplayProps } from '../ConferenceTimer'; |
||||
|
||||
/** |
||||
* Returns native element to be rendered. |
||||
* |
||||
* @param {string} timerValue - String to display as time. |
||||
* @param {Object} textStyle - Style to be applied to the text. |
||||
* @param {Object} props - Component props. |
||||
* |
||||
* @returns {ReactElement} |
||||
*/ |
||||
export default function renderConferenceTimer(timerValue: string, textStyle: Object) { |
||||
export default function ConferenceTimerDisplay({ timerValue, textStyle }: IDisplayProps) { |
||||
return ( |
||||
<Text |
||||
numberOfLines = { 1 } |
@ -1,5 +1,5 @@ |
||||
// @flow
|
||||
|
||||
export { default as Conference } from './Conference'; |
||||
export { default as renderConferenceTimer } from './ConferenceTimerDisplay'; |
||||
export { default as ConferenceTimerDisplay } from './ConferenceTimerDisplay'; |
||||
export { default as InsecureRoomNameLabel } from './InsecureRoomNameLabel'; |
||||
|
@ -1,19 +0,0 @@ |
||||
// @flow
|
||||
|
||||
/* eslint-disable no-unused-vars */ |
||||
|
||||
import React from 'react'; |
||||
|
||||
/** |
||||
* Returns web element to be rendered. |
||||
* |
||||
* @param {string} timerValue - String to display as time. |
||||
* @param {Object} textStyle - Unused on web. |
||||
* |
||||
* @returns {ReactElement} |
||||
*/ |
||||
export default function renderConferenceTimer(timerValue: string, textStyle: Object) { |
||||
return ( |
||||
<span className = 'subject-timer'>{ timerValue }</span> |
||||
); |
||||
} |
@ -0,0 +1,37 @@ |
||||
import React from 'react'; |
||||
import { makeStyles } from 'tss-react/mui'; |
||||
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web'; |
||||
import { IDisplayProps } from '../ConferenceTimer'; |
||||
|
||||
const useStyles = makeStyles()(theme => { |
||||
return { |
||||
timer: { |
||||
...withPixelLineHeight(theme.typography.labelRegular), |
||||
color: theme.palette.text01, |
||||
padding: '6px 8px', |
||||
backgroundColor: 'rgba(0, 0, 0, 0.8)', |
||||
boxSizing: 'border-box', |
||||
height: '28px', |
||||
borderRadius: `0 ${theme.shape.borderRadius}px ${theme.shape.borderRadius}px 0`, |
||||
marginRight: '2px', |
||||
|
||||
'@media (max-width: 300px)': { |
||||
display: 'none' |
||||
} |
||||
} |
||||
}; |
||||
}); |
||||
|
||||
/** |
||||
* Returns web element to be rendered. |
||||
* |
||||
* @returns {ReactElement} |
||||
*/ |
||||
export default function ConferenceTimerDisplay({ timerValue, textStyle: _textStyle }: IDisplayProps) { |
||||
const { classes } = useStyles(); |
||||
|
||||
return ( |
||||
<span className = { classes.timer }>{ timerValue }</span> |
||||
); |
||||
} |
@ -1,13 +1,11 @@ |
||||
// @flow
|
||||
|
||||
import Tooltip from '@atlaskit/tooltip'; |
||||
import React from 'react'; |
||||
import { connect } from 'react-redux'; |
||||
|
||||
import { translate } from '../../../base/i18n'; |
||||
import { translate } from '../../../base/i18n/functions'; |
||||
import { IconExclamationTriangle } from '../../../base/icons/svg'; |
||||
import { Label } from '../../../base/label'; |
||||
import Label from '../../../base/label/components/web/Label'; |
||||
import { COLORS } from '../../../base/label/constants'; |
||||
import { connect } from '../../../base/redux'; |
||||
import AbstractInsecureRoomNameLabel, { _mapStateToProps } from '../AbstractInsecureRoomNameLabel'; |
||||
|
||||
/** |
@ -1,50 +0,0 @@ |
||||
/* @flow */ |
||||
|
||||
import React from 'react'; |
||||
|
||||
import { getConferenceName } from '../../../base/conference/functions'; |
||||
import { connect } from '../../../base/redux'; |
||||
import { Tooltip } from '../../../base/tooltip'; |
||||
|
||||
type Props = { |
||||
|
||||
/** |
||||
* The conference display name. |
||||
*/ |
||||
_subject: string |
||||
} |
||||
|
||||
/** |
||||
* Label for the conference name. |
||||
* |
||||
* @param {Props} props - The props of the component. |
||||
* @returns {ReactElement} |
||||
*/ |
||||
const SubjectText = ({ _subject }: Props) => ( |
||||
<div className = 'subject-text'> |
||||
<Tooltip |
||||
content = { _subject } |
||||
position = 'bottom'> |
||||
<div className = 'subject-text--content'>{ _subject }</div> |
||||
</Tooltip> |
||||
</div> |
||||
); |
||||
|
||||
|
||||
/** |
||||
* Maps (parts of) the Redux state to the associated |
||||
* {@code Subject}'s props. |
||||
* |
||||
* @param {Object} state - The Redux state. |
||||
* @private |
||||
* @returns {{ |
||||
* _subject: string, |
||||
* }} |
||||
*/ |
||||
function _mapStateToProps(state) { |
||||
return { |
||||
_subject: getConferenceName(state) |
||||
}; |
||||
} |
||||
|
||||
export default connect(_mapStateToProps)(SubjectText); |
@ -0,0 +1,57 @@ |
||||
import clsx from 'clsx'; |
||||
import React from 'react'; |
||||
import { useSelector } from 'react-redux'; |
||||
import { makeStyles } from 'tss-react/mui'; |
||||
|
||||
import { getConferenceName } from '../../../base/conference/functions'; |
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web'; |
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import { Tooltip } from '../../../base/tooltip'; |
||||
|
||||
const useStyles = makeStyles()(theme => { |
||||
return { |
||||
container: { |
||||
...withPixelLineHeight(theme.typography.bodyLongRegular), |
||||
color: theme.palette.text01, |
||||
padding: '2px 16px', |
||||
backgroundColor: 'rgba(0, 0, 0, 0.6)', |
||||
maxWidth: '324px', |
||||
boxSizing: 'border-box', |
||||
height: '28px', |
||||
borderRadius: `${theme.shape.borderRadius}px 0 0 ${theme.shape.borderRadius}px`, |
||||
marginLeft: '2px', |
||||
|
||||
'@media (max-width: 300px)': { |
||||
display: 'none' |
||||
} |
||||
}, |
||||
content: { |
||||
overflow: 'hidden', |
||||
textOverflow: 'ellipsis', |
||||
whiteSpace: 'nowrap' |
||||
} |
||||
}; |
||||
}); |
||||
|
||||
/** |
||||
* Label for the conference name. |
||||
* |
||||
* @returns {ReactElement} |
||||
*/ |
||||
const SubjectText = () => { |
||||
const subject = useSelector(getConferenceName); |
||||
const { classes } = useStyles(); |
||||
|
||||
return ( |
||||
<div className = { classes.container }> |
||||
<Tooltip |
||||
content = { subject } |
||||
position = 'bottom'> |
||||
<div className = { clsx('subject-text--content', classes.content) }>{subject}</div> |
||||
</Tooltip> |
||||
</div> |
||||
); |
||||
}; |
||||
|
||||
export default SubjectText; |
@ -1,7 +1,7 @@ |
||||
// @flow
|
||||
|
||||
export { default as Conference } from './Conference'; |
||||
export { default as renderConferenceTimer } from './ConferenceTimerDisplay'; |
||||
export { default as ConferenceTimerDisplay } from './ConferenceTimerDisplay'; |
||||
export { default as InsecureRoomNameLabel } from './InsecureRoomNameLabel'; |
||||
export { default as ConferenceInfo } from './ConferenceInfo'; |
||||
export { default as SubjectText } from './SubjectText'; |
||||
|
@ -1,32 +1,28 @@ |
||||
// @flow
|
||||
import { WithTranslation } from 'react-i18next'; |
||||
|
||||
import { IReduxState } from '../../app/types'; |
||||
|
||||
export type Props = { |
||||
export interface IProps extends WithTranslation { |
||||
|
||||
/** |
||||
* Custom e2ee labels. |
||||
*/ |
||||
_e2eeLabels?: Object; |
||||
_e2eeLabels?: any; |
||||
|
||||
/** |
||||
* True if the label needs to be rendered, false otherwise. |
||||
*/ |
||||
_showLabel: boolean, |
||||
|
||||
/** |
||||
* Invoked to obtain translated strings. |
||||
*/ |
||||
t: Function |
||||
}; |
||||
_showLabel?: boolean; |
||||
} |
||||
|
||||
/** |
||||
* Maps (parts of) the redux state to the associated props of this {@code Component}. |
||||
* |
||||
* @param {Object} state - The redux state. |
||||
* @private |
||||
* @returns {Props} |
||||
* @returns {IProps} |
||||
*/ |
||||
export function _mapStateToProps(state: Object) { |
||||
export function _mapStateToProps(state: IReduxState) { |
||||
const { e2ee = {} } = state['features/base/config']; |
||||
|
||||
return { |
@ -1,47 +0,0 @@ |
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react'; |
||||
|
||||
import { translate } from '../../base/i18n'; |
||||
import { IconE2EE } from '../../base/icons'; |
||||
import { Label } from '../../base/label'; |
||||
import { COLORS } from '../../base/label/constants'; |
||||
import { connect } from '../../base/redux'; |
||||
import { Tooltip } from '../../base/tooltip'; |
||||
|
||||
import { type Props, _mapStateToProps } from './AbstractE2EELabel'; |
||||
|
||||
|
||||
/** |
||||
* React {@code Component} for displaying a label when everyone has E2EE enabled in a conference. |
||||
* |
||||
* @augments Component |
||||
*/ |
||||
class E2EELabel extends Component<Props> { |
||||
|
||||
/** |
||||
* Implements React's {@link Component#render()}. |
||||
* |
||||
* @inheritdoc |
||||
* @returns {ReactElement} |
||||
*/ |
||||
render() { |
||||
if (!this.props._showLabel) { |
||||
return null; |
||||
} |
||||
const { _e2eeLabels, t } = this.props; |
||||
const content = _e2eeLabels?.labelToolTip || t('e2ee.labelToolTip'); |
||||
|
||||
return ( |
||||
<Tooltip |
||||
content = { content } |
||||
position = { 'bottom' }> |
||||
<Label |
||||
color = { COLORS.green } |
||||
icon = { IconE2EE } /> |
||||
</Tooltip> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export default translate(connect(_mapStateToProps)(E2EELabel)); |
@ -0,0 +1,32 @@ |
||||
import React from 'react'; |
||||
import { connect } from 'react-redux'; |
||||
|
||||
import { translate } from '../../base/i18n/functions'; |
||||
import { IconE2EE } from '../../base/icons/svg'; |
||||
import Label from '../../base/label/components/web/Label'; |
||||
import { COLORS } from '../../base/label/constants'; |
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import { Tooltip } from '../../base/tooltip'; |
||||
|
||||
import { IProps, _mapStateToProps } from './AbstractE2EELabel'; |
||||
|
||||
|
||||
const E2EELabel = ({ _e2eeLabels, _showLabel, t }: IProps) => { |
||||
if (!_showLabel) { |
||||
return null; |
||||
} |
||||
const content = _e2eeLabels?.labelToolTip || t('e2ee.labelToolTip'); |
||||
|
||||
return ( |
||||
<Tooltip |
||||
content = { content } |
||||
position = { 'bottom' }> |
||||
<Label |
||||
color = { COLORS.green } |
||||
icon = { IconE2EE } /> |
||||
</Tooltip> |
||||
); |
||||
}; |
||||
|
||||
export default translate(connect(_mapStateToProps)(E2EELabel)); |
@ -1,44 +0,0 @@ |
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react'; |
||||
|
||||
import { translate } from '../../base/i18n'; |
||||
import { Label } from '../../base/label'; |
||||
import { connect } from '../../base/redux'; |
||||
import { Tooltip } from '../../base/tooltip'; |
||||
|
||||
import { type Props, _mapStateToProps } from './AbstractTranscribingLabel'; |
||||
|
||||
/** |
||||
* React {@code Component} for displaying a label when a transcriber is in the |
||||
* conference. |
||||
* |
||||
* @augments Component |
||||
*/ |
||||
class TranscribingLabel extends Component<Props> { |
||||
|
||||
/** |
||||
* Implements React's {@link Component#render()}. |
||||
* |
||||
* @inheritdoc |
||||
* @returns {ReactElement} |
||||
*/ |
||||
render() { |
||||
if (!this.props._showLabel) { |
||||
return null; |
||||
} |
||||
|
||||
return ( |
||||
<Tooltip |
||||
content = { this.props.t('transcribing.labelToolTip') } |
||||
position = { 'left' }> |
||||
<Label |
||||
className = 'recording-label' |
||||
text = { this.props.t('transcribing.tr') } /> |
||||
</Tooltip> |
||||
); |
||||
} |
||||
|
||||
} |
||||
|
||||
export default translate(connect(_mapStateToProps)(TranscribingLabel)); |
@ -0,0 +1,28 @@ |
||||
import React from 'react'; |
||||
import { connect } from 'react-redux'; |
||||
|
||||
import { translate } from '../../base/i18n/functions'; |
||||
import Label from '../../base/label/components/web/Label'; |
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import { Tooltip } from '../../base/tooltip'; |
||||
|
||||
import { Props, _mapStateToProps } from './AbstractTranscribingLabel'; |
||||
|
||||
const TranscribingLabel = ({ _showLabel, t }: Props) => { |
||||
if (!_showLabel) { |
||||
return null; |
||||
} |
||||
|
||||
return ( |
||||
<Tooltip |
||||
content = { t('transcribing.labelToolTip') } |
||||
position = { 'left' }> |
||||
<Label |
||||
className = 'recording-label' |
||||
text = { t('transcribing.tr') } /> |
||||
</Tooltip> |
||||
); |
||||
}; |
||||
|
||||
export default translate(connect(_mapStateToProps)(TranscribingLabel)); |
Loading…
Reference in new issue