Improve composer visiblity (#8578)

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Germain 2022-06-07 08:28:29 +01:00 committed by GitHub
parent 8c13a0f8d4
commit f14374a51c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 323 additions and 174 deletions

View file

@ -22,6 +22,7 @@ import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { EventType } from 'matrix-js-sdk/src/@types/event';
import { Optional } from "matrix-events-sdk";
import { THREAD_RELATION_TYPE } from 'matrix-js-sdk/src/models/thread';
import { CSSTransition } from 'react-transition-group';
import { _t } from '../../../languageHandler';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
@ -51,12 +52,14 @@ import { SettingUpdatedPayload } from "../../../dispatcher/payloads/SettingUpdat
import MessageComposerButtons from './MessageComposerButtons';
import { ButtonEvent } from '../elements/AccessibleButton';
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { Icon as InfoIcon } from "../../../../res/img/element-icons/room/room-summary.svg";
let instanceCount = 0;
interface ISendButtonProps {
onClick: (ev: ButtonEvent) => void;
title?: string; // defaults to something generic
"aria-hidden"?: boolean;
}
function SendButton(props: ISendButtonProps) {
@ -65,6 +68,7 @@ function SendButton(props: ISendButtonProps) {
className="mx_MessageComposer_sendMessage"
onClick={props.onClick}
title={props.title ?? _t('Send message')}
aria-hidden={props['aria-hidden'] ?? false}
/>
);
}
@ -263,15 +267,15 @@ export default class MessageComposer extends React.Component<IProps, IState> {
} else if (replyingToThread) {
return _t('Reply to thread…');
} else if (this.props.e2eStatus) {
return _t('Send an encrypted reply…');
return _t('Send encrypted reply…');
} else {
return _t('Send a reply…');
return _t('Send reply…');
}
} else {
if (this.props.e2eStatus) {
return _t('Send an encrypted message…');
return _t('Send encrypted message…');
} else {
return _t('Send a message…');
return _t('Send message…');
}
}
};
@ -351,11 +355,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
};
public render() {
const controls = [
this.props.e2eStatus ?
<E2EIcon key="e2eIcon" status={this.props.e2eStatus} className="mx_MessageComposer_e2eIcon" /> :
null,
];
const controls = [];
let menuPosition: AboveLeftOf | undefined;
if (this.ref.current) {
@ -363,6 +363,8 @@ export default class MessageComposer extends React.Component<IProps, IState> {
menuPosition = aboveLeftOf(contentRect);
}
const roomReplaced = !!this.context.tombstone;
const canSendMessages = this.context.canSendMessages && !this.context.tombstone;
if (canSendMessages) {
controls.push(
@ -379,34 +381,23 @@ export default class MessageComposer extends React.Component<IProps, IState> {
toggleStickerPickerOpen={this.toggleStickerPickerOpen}
/>,
);
controls.push(<VoiceRecordComposerTile
key="controls_voice_record"
ref={this.voiceRecordingButton}
room={this.props.room} />);
} else if (this.context.tombstone) {
} else if (roomReplaced) {
const replacementRoomId = this.context.tombstone.getContent()['replacement_room'];
const continuesLink = replacementRoomId ? (
<a href={makeRoomPermalink(replacementRoomId)}
className="mx_MessageComposer_roomReplaced_link"
onClick={this.onTombstoneClick}
>
{ _t("The conversation continues here.") }
</a>
) : '';
controls.push(<div className="mx_MessageComposer_replaced_wrapper" key="room_replaced">
<div className="mx_MessageComposer_replaced_valign">
<img className="mx_MessageComposer_roomReplaced_icon"
src={require("../../../../res/img/room_replaced.svg").default}
/>
<span className="mx_MessageComposer_roomReplaced_header">
{ _t("This room has been replaced and is no longer active.") }
</span><br />
{ continuesLink }
</div>
</div>);
controls.push(<p key="room_replaced">
<InfoIcon width={24} />
&nbsp;
{ _t("This room has been replaced and is no longer active.") }
&nbsp;
{ replacementRoomId && (
<a href={makeRoomPermalink(replacementRoomId)}
className="mx_MessageComposer_roomReplaced_link"
onClick={this.onTombstoneClick}
>
{ _t("The conversation continues here.") }
</a>
) }
</p>);
} else {
controls.push(
<div key="controls_error" className="mx_MessageComposer_noperm_error">
@ -441,6 +432,12 @@ export default class MessageComposer extends React.Component<IProps, IState> {
const showSendButton = !this.state.isComposerEmpty || this.state.haveRecording;
if (this.props.e2eStatus) {
controls.push(
<E2EIcon key="e2eIcon" status={this.props.e2eStatus} className="mx_MessageComposer_e2eIcon" />,
);
}
const classes = classNames({
"mx_MessageComposer": true,
"mx_GroupLayout": true,
@ -455,8 +452,17 @@ export default class MessageComposer extends React.Component<IProps, IState> {
<ReplyPreview
replyToEvent={this.props.replyToEvent}
permalinkCreator={this.props.permalinkCreator} />
<div className="mx_MessageComposer_row">
<div
className="mx_MessageComposer_row"
aria-disabled={!canSendMessages && !roomReplaced}
data-notice={roomReplaced}>
{ controls }
</div>
<div className="mx_MessageComposer_controls">
{ canSendMessages && <VoiceRecordComposerTile
key="controls_voice_record"
ref={this.voiceRecordingButton}
room={this.props.room} /> }
{ canSendMessages && <MessageComposerButtons
addEmoji={this.addEmoji}
haveRecording={this.state.haveRecording}
@ -476,13 +482,20 @@ export default class MessageComposer extends React.Component<IProps, IState> {
showStickersButton={this.state.showStickersButton}
toggleButtonMenu={this.toggleButtonMenu}
/> }
{ showSendButton && (
<SendButton
key="controls_send"
onClick={this.sendMessage}
title={this.state.haveRecording ? _t("Send voice message") : undefined}
/>
) }
<CSSTransition
in={showSendButton}
classNames="mx_MessageComposer_sendMessageWrapper"
addEndListener={() => {}}
>
<div className='mx_MessageComposer_sendMessageWrapper'>
<SendButton
key="controls_send"
onClick={this.sendMessage}
title={this.state.haveRecording ? _t("Send voice message") : undefined}
aria-hidden={!showSendButton}
/>
</div>
</CSSTransition>
</div>
</div>
</div>