Handle narrow layouts
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
parent
4dda4b241a
commit
9e4f5719a4
2 changed files with 218 additions and 143 deletions
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { createRef } from 'react';
|
||||
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { _t, _td } from '../../../languageHandler';
|
||||
|
@ -26,6 +26,8 @@ import InfoTooltip, { InfoTooltipKind } from '../elements/InfoTooltip';
|
|||
import classNames from 'classnames';
|
||||
import AccessibleTooltipButton from '../elements/AccessibleTooltipButton';
|
||||
|
||||
const MAX_NON_NARROW_WIDTH = 400 / 70 * 100;
|
||||
|
||||
interface IProps {
|
||||
mxEvent: MatrixEvent;
|
||||
callEventGrouper: CallEventGrouper;
|
||||
|
@ -34,6 +36,7 @@ interface IProps {
|
|||
interface IState {
|
||||
callState: CallState | CustomCallState;
|
||||
silenced: boolean;
|
||||
narrow: boolean;
|
||||
}
|
||||
|
||||
const TEXTUAL_STATES: Map<CallState | CustomCallState, string> = new Map([
|
||||
|
@ -41,26 +44,42 @@ const TEXTUAL_STATES: Map<CallState | CustomCallState, string> = new Map([
|
|||
[CallState.Connecting, _td("Connecting")],
|
||||
]);
|
||||
|
||||
export default class CallEvent extends React.Component<IProps, IState> {
|
||||
export default class CallEvent extends React.PureComponent<IProps, IState> {
|
||||
private wrapperElement = createRef<HTMLDivElement>();
|
||||
private resizeObserver: ResizeObserver;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
callState: this.props.callEventGrouper.state,
|
||||
silenced: false,
|
||||
narrow: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.callEventGrouper.addListener(CallEventGrouperEvent.StateChanged, this.onStateChanged);
|
||||
this.props.callEventGrouper.addListener(CallEventGrouperEvent.SilencedChanged, this.onSilencedChanged);
|
||||
|
||||
this.resizeObserver = new ResizeObserver(this.resizeObserverCallback);
|
||||
this.resizeObserver.observe(this.wrapperElement.current);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.callEventGrouper.removeListener(CallEventGrouperEvent.StateChanged, this.onStateChanged);
|
||||
this.props.callEventGrouper.removeListener(CallEventGrouperEvent.SilencedChanged, this.onSilencedChanged);
|
||||
|
||||
this.resizeObserver.disconnect();
|
||||
}
|
||||
|
||||
private resizeObserverCallback = (entries: ResizeObserverEntry[]): void => {
|
||||
const wrapperElementEntry = entries.find((entry) => entry.target === this.wrapperElement.current);
|
||||
if (!wrapperElementEntry) return;
|
||||
|
||||
this.setState({ narrow: wrapperElementEntry.contentRect.width < MAX_NON_NARROW_WIDTH });
|
||||
};
|
||||
|
||||
private onSilencedChanged = (newState) => {
|
||||
this.setState({ silenced: newState });
|
||||
};
|
||||
|
@ -81,21 +100,32 @@ export default class CallEvent extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
private renderSilenceIcon(): JSX.Element {
|
||||
const silenceClass = classNames({
|
||||
"mx_CallEvent_iconButton": true,
|
||||
"mx_CallEvent_unSilence": this.state.silenced,
|
||||
"mx_CallEvent_silence": !this.state.silenced,
|
||||
});
|
||||
|
||||
return (
|
||||
<AccessibleTooltipButton
|
||||
className={silenceClass}
|
||||
onClick={this.props.callEventGrouper.toggleSilenced}
|
||||
title={this.state.silenced ? _t("Sound on") : _t("Silence call")}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
private renderContent(state: CallState | CustomCallState): JSX.Element {
|
||||
if (state === CallState.Ringing) {
|
||||
const silenceClass = classNames({
|
||||
"mx_CallEvent_iconButton": true,
|
||||
"mx_CallEvent_unSilence": this.state.silenced,
|
||||
"mx_CallEvent_silence": !this.state.silenced,
|
||||
});
|
||||
let silenceIcon;
|
||||
if (!this.state.narrow) {
|
||||
silenceIcon = this.renderSilenceIcon();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_CallEvent_content">
|
||||
<AccessibleTooltipButton
|
||||
className={silenceClass}
|
||||
onClick={this.props.callEventGrouper.toggleSilenced}
|
||||
title={this.state.silenced ? _t("Sound on"): _t("Silence call")}
|
||||
/>
|
||||
{ silenceIcon }
|
||||
<AccessibleButton
|
||||
className="mx_CallEvent_content_button mx_CallEvent_content_button_reject"
|
||||
onClick={this.props.callEventGrouper.rejectCall}
|
||||
|
@ -209,35 +239,42 @@ export default class CallEvent extends React.Component<IProps, IState> {
|
|||
const callState = this.state.callState;
|
||||
const hangupReason = this.props.callEventGrouper.hangupReason;
|
||||
const content = this.renderContent(callState);
|
||||
const className = classNames({
|
||||
mx_CallEvent: true,
|
||||
const className = classNames("mx_CallEvent", {
|
||||
mx_CallEvent_voice: isVoice,
|
||||
mx_CallEvent_video: !isVoice,
|
||||
mx_CallEvent_narrow: this.state.narrow,
|
||||
mx_CallEvent_missed: (
|
||||
callState === CustomCallState.Missed ||
|
||||
(callState === CallState.Ended && hangupReason === CallErrorCode.InviteTimeout)
|
||||
),
|
||||
});
|
||||
let silenceIcon;
|
||||
if (this.state.narrow && this.state.callState === CallState.Ringing) {
|
||||
silenceIcon = this.renderSilenceIcon();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="mx_CallEvent_info">
|
||||
<MemberAvatar
|
||||
member={event.sender}
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<div className="mx_CallEvent_info_basic">
|
||||
<div className="mx_CallEvent_sender">
|
||||
{ sender }
|
||||
</div>
|
||||
<div className="mx_CallEvent_type">
|
||||
<div className="mx_CallEvent_type_icon" />
|
||||
{ callType }
|
||||
<div className="mx_CallEvent_wrapper" ref={this.wrapperElement}>
|
||||
<div className={className}>
|
||||
{ silenceIcon }
|
||||
<div className="mx_CallEvent_info">
|
||||
<MemberAvatar
|
||||
member={event.sender}
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<div className="mx_CallEvent_info_basic">
|
||||
<div className="mx_CallEvent_sender">
|
||||
{ sender }
|
||||
</div>
|
||||
<div className="mx_CallEvent_type">
|
||||
<div className="mx_CallEvent_type_icon" />
|
||||
{ callType }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{ content }
|
||||
</div>
|
||||
{ content }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue