diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 5c8f6809de..26db5dbafe 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -358,12 +358,16 @@ limitations under the License. margin-right: 0; .mx_MessageComposer_wrapper { - padding: 0; + padding: 0 0 0 25px; } .mx_MessageComposer_button:last-child { margin-right: 0; } + + .mx_MessageComposer_e2eIcon { + left: 0; + } } .mx_MessageComposer_Menu .mx_CallContextMenu_item { diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index 67634c63d2..114d020c66 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -53,6 +53,7 @@ import PinnedMessagesCard from "../views/right_panel/PinnedMessagesCard"; import { throttle } from 'lodash'; import SpaceStore from "../../stores/SpaceStore"; import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks'; +import { E2EStatus } from '../../utils/ShieldUtils'; interface IProps { room?: Room; // if showing panels for a given room, this is set @@ -60,6 +61,7 @@ interface IProps { user?: User; // used if we know the user ahead of opening the panel resizeNotifier: ResizeNotifier; permalinkCreator?: RoomPermalinkCreator; + e2eStatus?: E2EStatus; } interface IState { @@ -319,7 +321,8 @@ export default class RightPanel extends React.Component { resizeNotifier={this.props.resizeNotifier} onClose={this.onClose} mxEvent={this.state.event} - permalinkCreator={this.props.permalinkCreator} />; + permalinkCreator={this.props.permalinkCreator} + e2eStatus={this.props.e2eStatus} />; break; case RightPanelPhases.ThreadPanel: diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 8223c12e77..9dea4b1d1d 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -2054,7 +2054,8 @@ export default class RoomView extends React.Component { ? + permalinkCreator={this.getPermalinkCreatorForRoom(this.state.room)} + e2eStatus={this.state.e2eStatus} /> : null; const timelineClasses = classNames("mx_RoomView_timeline", { diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index 134f018aed..304479cce3 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -33,6 +33,7 @@ import { ActionPayload } from '../../dispatcher/payloads'; import { SetRightPanelPhasePayload } from '../../dispatcher/payloads/SetRightPanelPhasePayload'; import { Action } from '../../dispatcher/actions'; import { MatrixClientPeg } from '../../MatrixClientPeg'; +import { E2EStatus } from '../../utils/ShieldUtils'; interface IProps { room: Room; @@ -40,6 +41,7 @@ interface IProps { resizeNotifier: ResizeNotifier; mxEvent: MatrixEvent; permalinkCreator?: RoomPermalinkCreator; + e2eStatus?: E2EStatus; } interface IState { @@ -144,6 +146,7 @@ export default class ThreadView extends React.Component { replyToEvent={this.state?.thread?.replyToEvent} showReplyPreview={false} permalinkCreator={this.props.permalinkCreator} + e2eStatus={this.props.e2eStatus} compact={true} /> diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index 6b66ae4ba3..49acb13592 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -53,6 +53,7 @@ import EmojiPicker from '../emojipicker/EmojiPicker'; import MemberStatusMessageAvatar from "../avatars/MemberStatusMessageAvatar"; import UIStore, { UI_EVENTS } from '../../../stores/UIStore'; +let instanceCount = 0; const NARROW_MODE_BREAKPOINT = 500; interface IComposerAvatarProps { @@ -216,6 +217,7 @@ export default class MessageComposer extends React.Component { private messageComposerInput: SendMessageComposer; private voiceRecordingButton: VoiceRecordComposerTile; private ref: React.RefObject = createRef(); + private instanceId: number; static defaultProps = { replyInThread: false, @@ -236,14 +238,16 @@ export default class MessageComposer extends React.Component { isMenuOpen: false, showStickers: false, }; + + this.instanceId = instanceCount++; } componentDidMount() { this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on("RoomState.events", this.onRoomStateEvents); this.waitForOwnMember(); - UIStore.instance.trackElementDimensions("MessageComposer", this.ref.current); - UIStore.instance.on("MessageComposer", this.onResize); + UIStore.instance.trackElementDimensions(`MessageComposer${this.instanceId}`, this.ref.current); + UIStore.instance.on(`MessageComposer${this.instanceId}`, this.onResize); } private onResize = (type: UI_EVENTS, entry: ResizeObserverEntry) => { @@ -291,8 +295,8 @@ export default class MessageComposer extends React.Component { } VoiceRecordingStore.instance.off(UPDATE_EVENT, this.onVoiceStoreUpdate); dis.unregister(this.dispatcherRef); - UIStore.instance.stopTrackingElementDimensions("MessageComposer"); - UIStore.instance.removeListener("MessageComposer", this.onResize); + UIStore.instance.stopTrackingElementDimensions(`MessageComposer${this.instanceId}`); + UIStore.instance.removeListener(`MessageComposer${this.instanceId}`, this.onResize); } private onRoomStateEvents = (ev, state) => { @@ -342,7 +346,11 @@ export default class MessageComposer extends React.Component { private renderPlaceholderText = () => { if (this.props.replyToEvent) { - if (this.props.e2eStatus) { + if (this.props.replyInThread && this.props.e2eStatus) { + return _t('Reply to encrypted thread…'); + } else if (this.props.replyInThread) { + return _t('Reply to thread…'); + } else if (this.props.e2eStatus) { return _t('Send an encrypted reply…'); } else { return _t('Send a reply…'); @@ -419,17 +427,17 @@ export default class MessageComposer extends React.Component { const buttons = new Map(); if (!this.state.haveRecording) { buttons.set( - _t("Send File"), + _t("Send a file"), , ); buttons.set( - _t("Show Emojis"), + _t("Add emoji"), , ); } if (this.shouldShowStickerPicker()) { buttons.set( - _t("Show Stickers"), + _t("Send a sticker"), { } if (!this.state.haveRecording && !this.state.narrowMode) { buttons.set( - _t("Send voice message"), + _t("Send a voice message"), this.voiceRecordingButton?.onRecordStartEndClick()} @@ -450,8 +458,9 @@ export default class MessageComposer extends React.Component { ); } + const buttonsArray = Array.from(buttons.values()); if (!this.state.narrowMode) { - return Array.from(buttons.values()); + return buttonsArray; } else { const classnames = classNames({ mx_MessageComposer_button: true, @@ -460,11 +469,11 @@ export default class MessageComposer extends React.Component { }); return <> - { buttons[0] } + { buttonsArray[0] } { this.state.isMenuOpen && ( diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 1f8104da1d..b4b1071013 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1560,16 +1560,20 @@ "Send message": "Send message", "Emoji picker": "Emoji picker", "Upload file": "Upload file", + "Reply to encrypted thread…": "Reply to encrypted thread…", + "Reply to thread…": "Reply to thread…", "Send an encrypted reply…": "Send an encrypted reply…", "Send a reply…": "Send a reply…", "Send an encrypted message…": "Send an encrypted message…", "Send a message…": "Send a message…", - "Send File": "Send File", - "Show Emojis": "Show Emojis", - "Show Stickers": "Show Stickers", + "Send a file": "Send a file", + "Add emoji": "Add emoji", + "Send a sticker": "Send a sticker", "Hide Stickers": "Hide Stickers", + "Show Stickers": "Show Stickers", + "Send a voice message": "Send a voice message", "Send voice message": "Send voice message", - "Composer menu": "Composer menu", + "More options": "More options", "The conversation continues here.": "The conversation continues here.", "This room has been replaced and is no longer active.": "This room has been replaced and is no longer active.", "You do not have permission to post to this room": "You do not have permission to post to this room",