From 76ceee0e6ca582875f560772dbf6e3eb736918e2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 13:31:26 +0100 Subject: [PATCH 01/20] silence react warning when showing edited marker, by also giving the body a key --- src/HtmlUtils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 1032c52e32..97f547ceb4 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -541,8 +541,8 @@ export function bodyToHtml(content, highlights, opts={}) { }); return isDisplayedWithHtml ? - : - { strippedBody }; + : + { strippedBody }; } export function emojifyText(text, addAlt) { From 9a3752c5713e2b05bfa9f9ac68b7b8f78e52971f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 15:30:07 +0100 Subject: [PATCH 02/20] show message editor in textual body instead of replacing event tile --- src/components/structures/MessagePanel.js | 7 ++----- src/components/views/messages/MessageEvent.js | 1 + src/components/views/messages/TextualBody.js | 5 +++++ src/components/views/rooms/EventTile.js | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index dbaab57adf..001097f846 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -450,14 +450,10 @@ module.exports = React.createClass({ _getTilesForEvent: function(prevEvent, mxEv, last) { const EventTile = sdk.getComponent('rooms.EventTile'); - const MessageEditor = sdk.getComponent('elements.MessageEditor'); const DateSeparator = sdk.getComponent('messages.DateSeparator'); const ret = []; - if (this.props.editEvent && this.props.editEvent.getId() === mxEv.getId()) { - return []; - } - + const isEditing = this.props.editEvent && this.props.editEvent.getId() === mxEv.getId(); // is this a continuation of the previous message? let continuation = false; @@ -527,6 +523,7 @@ module.exports = React.createClass({ continuation={continuation} isRedacted={mxEv.isRedacted()} replacingEventId={mxEv.replacingEventId()} + isEditing={isEditing} onHeightChanged={this._onHeightChanged} readReceipts={readReceipts} readReceiptMap={this._readReceiptMap} diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index 357da1cd10..8c90ec5a46 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -90,6 +90,7 @@ module.exports = React.createClass({ tileShape={this.props.tileShape} maxImageHeight={this.props.maxImageHeight} replacingEventId={this.props.replacingEventId} + isEditing={this.props.isEditing} onHeightChanged={this.props.onHeightChanged} />; }, }); diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 44c807e4e4..c4a60c3bab 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -148,6 +148,7 @@ module.exports = React.createClass({ nextProps.replacingEventId !== this.props.replacingEventId || nextProps.highlightLink !== this.props.highlightLink || nextProps.showUrlPreview !== this.props.showUrlPreview || + nextProps.isEditing !== this.props.isEditing || nextState.links !== this.state.links || nextState.editedMarkerHovered !== this.state.editedMarkerHovered || nextState.widgetHidden !== this.state.widgetHidden); @@ -463,6 +464,10 @@ module.exports = React.createClass({ }, render: function() { + if (this.props.isEditing) { + const MessageEditor = sdk.getComponent('elements.MessageEditor'); + return ; + } const EmojiText = sdk.getComponent('elements.EmojiText'); const mxEvent = this.props.mxEvent; const content = mxEvent.getContent(); diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index f38e3c3946..9977d10395 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -780,6 +780,7 @@ module.exports = withMatrixClient(React.createClass({ Date: Fri, 17 May 2019 15:31:09 +0100 Subject: [PATCH 03/20] update design of editor to look as close to original tile (and design) the buttons below the composer are overlayed onto the previous event. In case of the last event, for now we make them not overflow, but make the tile grow. The design says it should overlay on the main composer for the last event tile, postponing that for a bit though as not sure what is the best way to do that. --- res/css/views/elements/_MessageEditor.scss | 19 +++++++++++++++---- res/css/views/rooms/_EventTile.scss | 4 ++++ src/components/views/rooms/EventTile.js | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/res/css/views/elements/_MessageEditor.scss b/res/css/views/elements/_MessageEditor.scss index ec6d903753..15b342b436 100644 --- a/res/css/views/elements/_MessageEditor.scss +++ b/res/css/views/elements/_MessageEditor.scss @@ -16,14 +16,14 @@ limitations under the License. .mx_MessageEditor { border-radius: 4px; - background-color: $header-panel-bg-color; - padding: 11px 13px 7px 56px; + padding: 3px; + margin: -7px -7px -5px -7px; // no idea why this is working .mx_MessageEditor_editor { border-radius: 4px; border: solid 1px #e9edf1; background-color: #ffffff; - padding: 10px; + padding: 3px; white-space: pre-wrap; word-wrap: break-word; outline: none; @@ -49,7 +49,14 @@ limitations under the License. display: flex; flex-direction: row; justify-content: end; - padding: 5px 0; + padding: 5px; + position: absolute; + left: 0; + background: $header-panel-bg-color; + z-index: 100; + right: 0; + margin: 0 -110px 0 0; + padding-right: 108px; .mx_AccessibleButton { margin-left: 5px; @@ -62,3 +69,7 @@ limitations under the License. height: 0; } } + +.mx_EventTile_last .mx_MessageEditor_buttons { + position: static; +} diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index aa473ec317..93d97b2913 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -43,6 +43,10 @@ limitations under the License. padding-top: 0px ! important; } +.mx_EventTile_isEditing { + background-color: $header-panel-bg-color; +} + .mx_EventTile .mx_SenderProfile { color: $primary-fg-color; font-size: 14px; diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 9977d10395..a4a9004041 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -540,6 +540,7 @@ module.exports = withMatrixClient(React.createClass({ const classes = classNames({ mx_EventTile: true, + mx_EventTile_isEditing: this.props.isEditing, mx_EventTile_info: isInfoMessage, mx_EventTile_12hr: this.props.isTwelveHour, mx_EventTile_encrypting: this.props.eventSendStatus === 'encrypting', From 62b8973e720531dba9fea1b714e739479280ee04 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 15:35:14 +0100 Subject: [PATCH 04/20] cancel the edit when pressing escape --- src/components/views/elements/MessageEditor.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/MessageEditor.js b/src/components/views/elements/MessageEditor.js index c18d1f56fd..0c249d067b 100644 --- a/src/components/views/elements/MessageEditor.js +++ b/src/components/views/elements/MessageEditor.js @@ -107,10 +107,12 @@ export default class MessageEditor extends React.Component { } else if (event.key === "Enter") { this._sendEdit(); event.preventDefault(); + } else if (event.key === "Escape") { + this._cancelEdit(); } } - _onCancelClicked = () => { + _cancelEdit = () => { dis.dispatch({action: "edit_event", event: null}); } @@ -185,7 +187,7 @@ export default class MessageEditor extends React.Component { ref={ref => this._editorRef = ref} >
- {_t("Cancel")} + {_t("Cancel")} {_t("Save")}
; From 578a183f49a9f3fe239f19bfc6a5b50d6e4426ca Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 15:35:28 +0100 Subject: [PATCH 05/20] hide the action bar while editing --- src/components/views/rooms/EventTile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index a4a9004041..39e830a228 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -618,14 +618,14 @@ module.exports = withMatrixClient(React.createClass({ } const MessageActionBar = sdk.getComponent('messages.MessageActionBar'); - const actionBar = ; + /> : undefined; const timestamp = this.props.mxEvent.getTs() ? : null; From 2544decab2af9b3d40be58828c0b1a032fef802b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:00:08 +0100 Subject: [PATCH 06/20] fix chrome not right aligning buttons --- res/css/views/elements/_MessageEditor.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/elements/_MessageEditor.scss b/res/css/views/elements/_MessageEditor.scss index 15b342b436..cfa62e000f 100644 --- a/res/css/views/elements/_MessageEditor.scss +++ b/res/css/views/elements/_MessageEditor.scss @@ -48,7 +48,7 @@ limitations under the License. .mx_MessageEditor_buttons { display: flex; flex-direction: row; - justify-content: end; + justify-content: flex-end; padding: 5px; position: absolute; left: 0; From 81245e9c05bb2dd0c011ab68442ec1c9195199a6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:00:22 +0100 Subject: [PATCH 07/20] cull editor height to 200px --- res/css/views/elements/_MessageEditor.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/views/elements/_MessageEditor.scss b/res/css/views/elements/_MessageEditor.scss index cfa62e000f..e48e93aa63 100644 --- a/res/css/views/elements/_MessageEditor.scss +++ b/res/css/views/elements/_MessageEditor.scss @@ -27,6 +27,8 @@ limitations under the License. white-space: pre-wrap; word-wrap: break-word; outline: none; + max-height: 200px; + overflow-x: auto; span { display: inline-block; From cf8189ed4371650293e0822db2950b2c686e08a6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:00:39 +0100 Subject: [PATCH 08/20] align buttons perfectly with editor edge --- res/css/views/elements/_MessageEditor.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/elements/_MessageEditor.scss b/res/css/views/elements/_MessageEditor.scss index e48e93aa63..d537584f1c 100644 --- a/res/css/views/elements/_MessageEditor.scss +++ b/res/css/views/elements/_MessageEditor.scss @@ -58,7 +58,7 @@ limitations under the License. z-index: 100; right: 0; margin: 0 -110px 0 0; - padding-right: 108px; + padding-right: 107px; .mx_AccessibleButton { margin-left: 5px; From aeea4ee83a4ef4d196327bfb456bc980421b499a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:00:58 +0100 Subject: [PATCH 09/20] a bit more horizontal padding for the editor --- res/css/views/elements/_MessageEditor.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/views/elements/_MessageEditor.scss b/res/css/views/elements/_MessageEditor.scss index d537584f1c..6a5f25532f 100644 --- a/res/css/views/elements/_MessageEditor.scss +++ b/res/css/views/elements/_MessageEditor.scss @@ -17,13 +17,13 @@ limitations under the License. .mx_MessageEditor { border-radius: 4px; padding: 3px; - margin: -7px -7px -5px -7px; // no idea why this is working + margin: -7px -10px -5px -10px; // from fiddling around in inspector .mx_MessageEditor_editor { border-radius: 4px; border: solid 1px #e9edf1; background-color: #ffffff; - padding: 3px; + padding: 3px 6px; white-space: pre-wrap; word-wrap: break-word; outline: none; From 5adae63555f31496494aeab08e054fe4edebca39 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:01:30 +0100 Subject: [PATCH 10/20] don't apply formatting to body when showing editor in TextualBody it throws --- src/components/views/messages/TextualBody.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index c4a60c3bab..bd37f98360 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -89,7 +89,9 @@ module.exports = React.createClass({ componentDidMount: function() { this._unmounted = false; - this._applyFormatting(); + if (!this.props.isEditing) { + this._applyFormatting(); + } }, _applyFormatting() { @@ -128,11 +130,13 @@ module.exports = React.createClass({ }, componentDidUpdate: function(prevProps) { - const messageWasEdited = prevProps.replacingEventId !== this.props.replacingEventId; - if (messageWasEdited) { - this._applyFormatting(); + if (!this.props.isEditing) { + const messageWasEdited = prevProps.replacingEventId !== this.props.replacingEventId; + if (messageWasEdited) { + this._applyFormatting(); + } + this.calculateUrlPreview(); } - this.calculateUrlPreview(); }, componentWillUnmount: function() { From f9462d1012d46b6f7ec0b1c2654b2c018a7ebb10 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:01:52 +0100 Subject: [PATCH 11/20] hide timestamp while editing --- res/css/views/rooms/_EventTile.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 93d97b2913..dfc560e670 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -76,6 +76,10 @@ limitations under the License. } } +.mx_EventTile_isEditing .mx_MessageTimestamp { + visibility: hidden !important; +} + .mx_EventTile .mx_MessageTimestamp { display: block; visibility: hidden; From aef9323f216ed74dac2aa17bbed519c7c1bb554e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:10:11 +0100 Subject: [PATCH 12/20] explain negative margin --- res/css/views/elements/_MessageEditor.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/res/css/views/elements/_MessageEditor.scss b/res/css/views/elements/_MessageEditor.scss index 6a5f25532f..8f3fdfb9ef 100644 --- a/res/css/views/elements/_MessageEditor.scss +++ b/res/css/views/elements/_MessageEditor.scss @@ -17,7 +17,10 @@ limitations under the License. .mx_MessageEditor { border-radius: 4px; padding: 3px; - margin: -7px -10px -5px -10px; // from fiddling around in inspector + // this is to try not make the text move but still have some + // padding around and in the editor. + // Actual values from fiddling around in inspector + margin: -7px -10px -5px -10px; .mx_MessageEditor_editor { border-radius: 4px; From 8ce8ca18ff2deaeb8362f3cbc7cbb541cff57359 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:10:21 +0100 Subject: [PATCH 13/20] theme-ify! --- res/css/views/elements/_MessageEditor.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/views/elements/_MessageEditor.scss b/res/css/views/elements/_MessageEditor.scss index 8f3fdfb9ef..40bc132edb 100644 --- a/res/css/views/elements/_MessageEditor.scss +++ b/res/css/views/elements/_MessageEditor.scss @@ -24,8 +24,8 @@ limitations under the License. .mx_MessageEditor_editor { border-radius: 4px; - border: solid 1px #e9edf1; - background-color: #ffffff; + border: solid 1px $primary-hairline-color; + background-color: $primary-bg-color; padding: 3px 6px; white-space: pre-wrap; word-wrap: break-word; From d81ab2464bb5cd1d52996a92f5d5a975a91cf5c7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 May 2019 16:15:06 +0100 Subject: [PATCH 14/20] better button alignment also fix sticking out at the right side when not overlaying --- res/css/views/elements/_MessageEditor.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/css/views/elements/_MessageEditor.scss b/res/css/views/elements/_MessageEditor.scss index 40bc132edb..cc5649a224 100644 --- a/res/css/views/elements/_MessageEditor.scss +++ b/res/css/views/elements/_MessageEditor.scss @@ -61,7 +61,7 @@ limitations under the License. z-index: 100; right: 0; margin: 0 -110px 0 0; - padding-right: 107px; + padding-right: 104px; .mx_AccessibleButton { margin-left: 5px; @@ -77,4 +77,5 @@ limitations under the License. .mx_EventTile_last .mx_MessageEditor_buttons { position: static; + margin-right: -103px; } From 3a405701a31f671cbcb6f96c01cc64b48480882f Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 2 May 2019 15:11:06 +0100 Subject: [PATCH 15/20] Debug: Show all events --- res/css/_components.scss | 1 + res/css/views/messages/_ViewSourceEvent.scss | 50 ++++++++++++++ src/components/structures/MessagePanel.js | 5 ++ .../views/messages/ViewSourceEvent.js | 67 +++++++++++++++++++ src/components/views/rooms/EventTile.js | 5 +- src/i18n/strings/en_EN.json | 1 + src/settings/Settings.js | 6 ++ 7 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 res/css/views/messages/_ViewSourceEvent.scss create mode 100644 src/components/views/messages/ViewSourceEvent.js diff --git a/res/css/_components.scss b/res/css/_components.scss index 9823b4ac3d..4b8b687146 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -124,6 +124,7 @@ @import "./views/messages/_SenderProfile.scss"; @import "./views/messages/_TextualEvent.scss"; @import "./views/messages/_UnknownBody.scss"; +@import "./views/messages/_ViewSourceEvent.scss"; @import "./views/room_settings/_AliasSettings.scss"; @import "./views/room_settings/_ColorSettings.scss"; @import "./views/rooms/_AppsDrawer.scss"; diff --git a/res/css/views/messages/_ViewSourceEvent.scss b/res/css/views/messages/_ViewSourceEvent.scss new file mode 100644 index 0000000000..a15924e759 --- /dev/null +++ b/res/css/views/messages/_ViewSourceEvent.scss @@ -0,0 +1,50 @@ +/* +Copyright 2019 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_EventTile_content.mx_ViewSourceEvent { + display: flex; + opacity: 0.6; + font-size: 12px; + + pre, code { + flex: 1; + } + + pre { + line-height: 1.2; + margin: 3.5px 0; + } + + .mx_ViewSourceEvent_toggle { + width: 12px; + mask-repeat: no-repeat; + mask-position: 0 center; + mask-size: auto 12px; + visibility: hidden; + background-color: $accent-color; + mask-image: url('$(res)/img/feather-customised/widget/maximise.svg'); + } + + &.mx_ViewSourceEvent_expanded .mx_ViewSourceEvent_toggle { + mask-position: 0 bottom; + margin-bottom: 7px; + mask-image: url('$(res)/img/feather-customised/widget/minimise.svg'); + } + + &:hover .mx_ViewSourceEvent_toggle { + visibility: visible; + } +} diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index dbaab57adf..562d067a7b 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -24,6 +24,7 @@ import {wantsDateSeparator} from '../../DateUtils'; import sdk from '../../index'; import MatrixClientPeg from '../../MatrixClientPeg'; +import SettingsStore from '../../settings/SettingsStore'; const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes const continuedTypes = ['m.sticker', 'm.room.message']; @@ -248,6 +249,10 @@ module.exports = React.createClass({ return false; // ignored = no show (only happens if the ignore happens after an event was received) } + if (SettingsStore.isFeatureEnabled("showHiddenEventsInTimeline")) { + return true; + } + const EventTile = sdk.getComponent('rooms.EventTile'); if (!EventTile.haveTileForEvent(mxEv)) { return false; // no tile = no show diff --git a/src/components/views/messages/ViewSourceEvent.js b/src/components/views/messages/ViewSourceEvent.js new file mode 100644 index 0000000000..717a4b0f05 --- /dev/null +++ b/src/components/views/messages/ViewSourceEvent.js @@ -0,0 +1,67 @@ +/* +Copyright 2019 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +export default class ViewSourceEvent extends React.PureComponent { + static propTypes = { + /* the MatrixEvent to show */ + mxEvent: PropTypes.object.isRequired, + }; + + constructor(props) { + super(props); + + this.state = { + expanded: false, + }; + } + + onToggle = (ev) => { + ev.preventDefault(); + const { expanded } = this.state; + this.setState({ + expanded: !expanded, + }); + } + + render() { + const { mxEvent } = this.props; + const { expanded } = this.state; + + let content; + if (expanded) { + content =
{JSON.stringify(mxEvent, null, 4)}
; + } else { + content = {`{ "type": ${mxEvent.getType()} }`}; + } + + const classes = classNames("mx_ViewSourceEvent mx_EventTile_content", { + mx_ViewSourceEvent_expanded: expanded, + }); + + return + {content} + + ; + } + } diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index f38e3c3946..91699c0c99 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -520,7 +520,10 @@ module.exports = withMatrixClient(React.createClass({ eventType !== 'm.room.message' && eventType !== 'm.sticker' && eventType != 'm.room.create' ); - const tileHandler = getHandlerTile(this.props.mxEvent); + let tileHandler = getHandlerTile(this.props.mxEvent); + if (!tileHandler && SettingsStore.isFeatureEnabled("showHiddenEventsInTimeline")) { + tileHandler = "messages.ViewSourceEvent"; + } // This shouldn't happen: the caller should check we support this type // before trying to instantiate us if (!tileHandler) { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 86131645cf..067c2bdeef 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -302,6 +302,7 @@ "Render simple counters in room header": "Render simple counters in room header", "Edit messages after they have been sent (refresh to apply changes)": "Edit messages after they have been sent (refresh to apply changes)", "React to messages with emoji (refresh to apply changes)": "React to messages with emoji (refresh to apply changes)", + "Show hidden events in timeline": "Show hidden events in timeline", "Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing", "Use compact timeline layout": "Use compact timeline layout", "Show a placeholder for removed messages": "Show a placeholder for removed messages", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 429030d862..5db8599112 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -130,6 +130,12 @@ export const SETTINGS = { supportedLevels: LEVELS_FEATURE, default: false, }, + "showHiddenEventsInTimeline": { + isFeature: true, + displayName: _td("Show hidden events in timeline"), + supportedLevels: LEVELS_FEATURE, + default: false, + }, "MessageComposerInput.suggestEmoji": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td('Enable Emoji suggestions while typing'), From 45cdf880b1305a161b73c072a8cdd3acfba90124 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 17 May 2019 17:43:08 +0100 Subject: [PATCH 16/20] Change setting style --- src/components/structures/MessagePanel.js | 2 +- src/components/views/rooms/EventTile.js | 2 +- .../views/settings/tabs/user/LabsUserSettingsTab.js | 1 + src/i18n/strings/en_EN.json | 2 +- src/settings/Settings.js | 11 +++++------ 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 562d067a7b..4d86305753 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -249,7 +249,7 @@ module.exports = React.createClass({ return false; // ignored = no show (only happens if the ignore happens after an event was received) } - if (SettingsStore.isFeatureEnabled("showHiddenEventsInTimeline")) { + if (SettingsStore.getValue("showHiddenEventsInTimeline")) { return true; } diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 91699c0c99..8269717cc7 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -521,7 +521,7 @@ module.exports = withMatrixClient(React.createClass({ ); let tileHandler = getHandlerTile(this.props.mxEvent); - if (!tileHandler && SettingsStore.isFeatureEnabled("showHiddenEventsInTimeline")) { + if (!tileHandler && SettingsStore.getValue("showHiddenEventsInTimeline")) { tileHandler = "messages.ViewSourceEvent"; } // This shouldn't happen: the caller should check we support this type diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js index c2e62044a3..d272d74d29 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js @@ -52,6 +52,7 @@ export default class LabsUserSettingsTab extends React.Component {
{flags} +
); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 067c2bdeef..b886e70422 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -302,7 +302,6 @@ "Render simple counters in room header": "Render simple counters in room header", "Edit messages after they have been sent (refresh to apply changes)": "Edit messages after they have been sent (refresh to apply changes)", "React to messages with emoji (refresh to apply changes)": "React to messages with emoji (refresh to apply changes)", - "Show hidden events in timeline": "Show hidden events in timeline", "Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing", "Use compact timeline layout": "Use compact timeline layout", "Show a placeholder for removed messages": "Show a placeholder for removed messages", @@ -334,6 +333,7 @@ "Prompt before sending invites to potentially invalid matrix IDs": "Prompt before sending invites to potentially invalid matrix IDs", "Show developer tools": "Show developer tools", "Order rooms in the room list by most important first instead of most recent": "Order rooms in the room list by most important first instead of most recent", + "Show hidden events in timeline": "Show hidden events in timeline", "Collecting app version information": "Collecting app version information", "Collecting logs": "Collecting logs", "Uploading report": "Uploading report", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 5db8599112..116526b63a 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -130,12 +130,6 @@ export const SETTINGS = { supportedLevels: LEVELS_FEATURE, default: false, }, - "showHiddenEventsInTimeline": { - isFeature: true, - displayName: _td("Show hidden events in timeline"), - supportedLevels: LEVELS_FEATURE, - default: false, - }, "MessageComposerInput.suggestEmoji": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td('Enable Emoji suggestions while typing'), @@ -374,4 +368,9 @@ export const SETTINGS = { displayName: _td('Order rooms in the room list by most important first instead of most recent'), default: true, }, + "showHiddenEventsInTimeline": { + displayName: _td("Show hidden events in timeline"), + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS, + default: false, + }, }; From 5144907983bbd781d03d28b71dd6ea51942c2b97 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 17 May 2019 17:44:11 +0100 Subject: [PATCH 17/20] Fix indent --- src/components/views/messages/ViewSourceEvent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/ViewSourceEvent.js b/src/components/views/messages/ViewSourceEvent.js index 717a4b0f05..62cf45fb6e 100644 --- a/src/components/views/messages/ViewSourceEvent.js +++ b/src/components/views/messages/ViewSourceEvent.js @@ -63,5 +63,5 @@ export default class ViewSourceEvent extends React.PureComponent { onClick={this.onToggle} />
; - } } +} From 0c0052d06e0804d7e3e5e6ef017a3dfa73edf2d7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 20 May 2019 10:19:29 +0200 Subject: [PATCH 18/20] re-apply formatting when editor is closed --- src/components/views/messages/TextualBody.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index bd37f98360..380d04d1db 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -131,8 +131,9 @@ module.exports = React.createClass({ componentDidUpdate: function(prevProps) { if (!this.props.isEditing) { + const stoppedEditing = prevProps.isEditing && !this.props.isEditing; const messageWasEdited = prevProps.replacingEventId !== this.props.replacingEventId; - if (messageWasEdited) { + if (messageWasEdited || stoppedEditing) { this._applyFormatting(); } this.calculateUrlPreview(); From 0e5f0f24cc34a24b6506a8c7b1959b8856d6e32e Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 20 May 2019 15:16:12 +0100 Subject: [PATCH 19/20] Extract MELS-style comma separated list to shared utility This allows other UI components to use the same formatting for a long list. --- .../views/elements/MemberEventListSummary.js | 38 +++---------------- src/i18n/strings/en_EN.json | 6 +-- src/utils/FormattingUtils.js | 31 +++++++++++++++ 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index 3c58f90a2b..dc9c72df6e 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -1,5 +1,6 @@ /* Copyright 2016 OpenMarket Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13,11 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ + import React from 'react'; import PropTypes from 'prop-types'; import sdk from '../../../index'; -const MemberAvatar = require('../avatars/MemberAvatar.js'); +import MemberAvatar from '../avatars/MemberAvatar'; import { _t } from '../../../languageHandler'; +import { formatCommaSeparatedList } from '../../../utils/FormattingUtils'; module.exports = React.createClass({ displayName: 'MemberEventListSummary', @@ -105,7 +108,7 @@ module.exports = React.createClass({ ); }); - const desc = this._renderCommaSeparatedList(descs); + const desc = formatCommaSeparatedList(descs); return _t('%(nameList)s %(transitionList)s', { nameList: nameList, transitionList: desc }); }); @@ -132,7 +135,7 @@ module.exports = React.createClass({ * included before "and [n] others". */ _renderNameList: function(users) { - return this._renderCommaSeparatedList(users, this.props.summaryLength); + return formatCommaSeparatedList(users, this.props.summaryLength); }, /** @@ -283,35 +286,6 @@ module.exports = React.createClass({ return res; }, - /** - * Constructs a written English string representing `items`, with an optional limit on - * the number of items included in the result. If specified and if the length of - *`items` is greater than the limit, the string "and n others" will be appended onto - * the result. - * If `items` is empty, returns the empty string. If there is only one item, return - * it. - * @param {string[]} items the items to construct a string from. - * @param {number?} itemLimit the number by which to limit the list. - * @returns {string} a string constructed by joining `items` with a comma between each - * item, but with the last item appended as " and [lastItem]". - */ - _renderCommaSeparatedList(items, itemLimit) { - const remaining = itemLimit === undefined ? 0 : Math.max( - items.length - itemLimit, 0, - ); - if (items.length === 0) { - return ""; - } else if (items.length === 1) { - return items[0]; - } else if (remaining > 0) { - items = items.slice(0, itemLimit); - return _t("%(items)s and %(count)s others", { items: items.join(', '), count: remaining } ); - } else { - const lastItem = items.pop(); - return _t("%(items)s and %(lastItem)s", { items: items.join(', '), lastItem: lastItem }); - } - }, - _renderAvatars: function(roomMembers) { const avatars = roomMembers.slice(0, this.props.avatarsMaxLength).map((m) => { return ( diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b886e70422..ad5cdd248d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -253,6 +253,9 @@ "This homeserver has exceeded one of its resource limits.": "This homeserver has exceeded one of its resource limits.", "Please contact your service administrator to continue using the service.": "Please contact your service administrator to continue using the service.", "Unable to connect to Homeserver. Retrying...": "Unable to connect to Homeserver. Retrying...", + "%(items)s and %(count)s others|other": "%(items)s and %(count)s others", + "%(items)s and %(count)s others|one": "%(items)s and one other", + "%(items)s and %(lastItem)s": "%(items)s and %(lastItem)s", "Your browser does not support the required cryptography extensions": "Your browser does not support the required cryptography extensions", "Not a valid Riot keyfile": "Not a valid Riot keyfile", "Authentication check failed: incorrect password?": "Authentication check failed: incorrect password?", @@ -1046,9 +1049,6 @@ "%(severalUsers)schanged their avatar %(count)s times|one": "%(severalUsers)schanged their avatar", "%(oneUser)schanged their avatar %(count)s times|other": "%(oneUser)schanged their avatar %(count)s times", "%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)schanged their avatar", - "%(items)s and %(count)s others|other": "%(items)s and %(count)s others", - "%(items)s and %(count)s others|one": "%(items)s and one other", - "%(items)s and %(lastItem)s": "%(items)s and %(lastItem)s", "collapse": "collapse", "expand": "expand", "Power level": "Power level", diff --git a/src/utils/FormattingUtils.js b/src/utils/FormattingUtils.js index b461d22079..1fd7d00feb 100644 --- a/src/utils/FormattingUtils.js +++ b/src/utils/FormattingUtils.js @@ -1,5 +1,6 @@ /* Copyright 2016 OpenMarket Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,6 +15,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { _t } from '../languageHandler'; + /** * formats numbers to fit into ~3 characters, suitable for badge counts * e.g: 999, 9.9K, 99K, 0.9M, 9.9M, 99M, 0.9B, 9.9B @@ -63,3 +66,31 @@ export function getUserNameColorClass(userId) { const colorNumber = (hashCode(userId) % 8) + 1; return `mx_Username_color${colorNumber}`; } + +/** + * Constructs a written English string representing `items`, with an optional + * limit on the number of items included in the result. If specified and if the + * length of `items` is greater than the limit, the string "and n others" will + * be appended onto the result. If `items` is empty, returns the empty string. + * If there is only one item, return it. + * @param {string[]} items the items to construct a string from. + * @param {number?} itemLimit the number by which to limit the list. + * @returns {string} a string constructed by joining `items` with a comma + * between each item, but with the last item appended as " and [lastItem]". + */ +export function formatCommaSeparatedList(items, itemLimit) { + const remaining = itemLimit === undefined ? 0 : Math.max( + items.length - itemLimit, 0, + ); + if (items.length === 0) { + return ""; + } else if (items.length === 1) { + return items[0]; + } else if (remaining > 0) { + items = items.slice(0, itemLimit); + return _t("%(items)s and %(count)s others", { items: items.join(', '), count: remaining } ); + } else { + const lastItem = items.pop(); + return _t("%(items)s and %(lastItem)s", { items: items.join(', '), lastItem: lastItem }); + } +} From 1bc9badeacd85ac5b07a096114f3cc205c1b7e8d Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 20 May 2019 16:02:10 +0100 Subject: [PATCH 20/20] Limit reaction sender tooltip to 6 people This limits the number of senders shown in the reaction sender tooltip shown when hovering a reaction to 6 people followed by "and N others" for the rest. Fixes https://github.com/vector-im/riot-web/issues/9722 --- src/components/views/messages/ReactionsRowButtonTooltip.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/ReactionsRowButtonTooltip.js b/src/components/views/messages/ReactionsRowButtonTooltip.js index 4f26cea708..e9ec58e8d0 100644 --- a/src/components/views/messages/ReactionsRowButtonTooltip.js +++ b/src/components/views/messages/ReactionsRowButtonTooltip.js @@ -21,6 +21,7 @@ import MatrixClientPeg from '../../../MatrixClientPeg'; import sdk from '../../../index'; import { unicodeToShort } from '../../../HtmlUtils'; import { _t } from '../../../languageHandler'; +import { formatCommaSeparatedList } from '../../../utils/FormattingUtils'; export default class ReactionsRowButtonTooltip extends React.PureComponent { static propTypes = { @@ -54,7 +55,7 @@ export default class ReactionsRowButtonTooltip extends React.PureComponent { { reactors: () => { return
- {senders.join(", ")} + {formatCommaSeparatedList(senders, 6)}
; }, reactedWith: (sub) => {