From 1739b7e0cc500a1ff52504d06a2b8c11ece49b83 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Thu, 20 Feb 2020 20:09:03 -0600 Subject: [PATCH 01/69] Don't ask to enable analytics when Do Not Track is enabled Signed-off-by: Aaron Raimist --- src/components/structures/LoggedInView.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 9597f99cd2..023272cef1 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -585,7 +585,8 @@ const LoggedInView = createReactClass({ limitType={usageLimitEvent.getContent().limit_type} />; } else if (this.props.showCookieBar && - this.props.config.piwik + this.props.config.piwik && + navigator.doNotTrack != 1 ) { const policyUrl = this.props.config.piwik.policyUrl || null; topBar = ; From 566db6c406c9b6905fbf154e18a89312258c41f0 Mon Sep 17 00:00:00 2001 From: Ben Parsons Date: Tue, 25 Feb 2020 17:29:59 +0000 Subject: [PATCH 02/69] link to matrix.org/security-disclosure-policy in help screen --- .../views/settings/tabs/user/HelpUserSettingsTab.js | 9 +++++++++ src/i18n/strings/en_EN.json | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js index 258b55bb4e..1222cc1634 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js @@ -225,6 +225,15 @@ export default class HelpUserSettingsTab extends React.Component { {_t("Clear cache and reload")} + { + _t( "To submit a security-related bug report, please read the Matrix.org " + + "Security Disclosure Policy.", {}, + { + 'a': (sub) => + {sub}, + }) + }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f702da6b4c..9223c13408 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2133,5 +2133,6 @@ "Message downloading sleep time(ms)": "Message downloading sleep time(ms)", "Failed to set direct chat tag": "Failed to set direct chat tag", "Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room", - "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room" + "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room", + "To submit a security-related bug report, please read the Matrix.org Security Disclosure Policy.": "To submit a security-related bug report, please read the Matrix.org Security Disclosure Policy." } From 92bc3e83ef08d99739961f81c22eeb529a72ca6a Mon Sep 17 00:00:00 2001 From: Ben Parsons Date: Tue, 25 Feb 2020 17:57:31 +0000 Subject: [PATCH 03/69] yarn i18n --- src/i18n/strings/en_EN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9223c13408..c0470af357 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -725,6 +725,7 @@ "If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.", "Submit debug logs": "Submit debug logs", "Clear cache and reload": "Clear cache and reload", + "To submit a security-related bug report, please read the Matrix.org Security Disclosure Policy.": "To submit a security-related bug report, please read the Matrix.org Security Disclosure Policy.", "FAQ": "FAQ", "Versions": "Versions", "riot-web version:": "riot-web version:", @@ -2133,6 +2134,5 @@ "Message downloading sleep time(ms)": "Message downloading sleep time(ms)", "Failed to set direct chat tag": "Failed to set direct chat tag", "Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room", - "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room", - "To submit a security-related bug report, please read the Matrix.org Security Disclosure Policy.": "To submit a security-related bug report, please read the Matrix.org Security Disclosure Policy." + "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room" } From 9afa66364e1a38362528c88fb496fc4466de7663 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 26 Feb 2020 14:24:58 +0000 Subject: [PATCH 04/69] Upgrade matrix-js-sdk to 5.1.0-rc.1 --- package.json | 2 +- yarn.lock | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 624f2d6ecb..5c18d9119e 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", + "matrix-js-sdk": "5.1.0-rc.1", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index d57ecfbeb9..b01b64a8b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5791,9 +5791,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc" integrity sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": - version "5.0.1" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/a998006842ae558f02819ca84fbaad43685cc10b" +matrix-js-sdk@5.1.0-rc.1: + version "5.1.0-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.1.0-rc.1.tgz#48154133f1c8bc19557164a24535d6d45d1cf482" + integrity sha512-3pf8NOziyaldtJkYsas9Cq/b8TloGMY89KRA4tJLRDCdMrlBEJoQ4qb9MCmhS53Yb8N4ysI7qUUC21FtBryAVQ== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From 9926b32f24c6c7b5564a4b7ebace3e06b12bb529 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 26 Feb 2020 14:29:31 +0000 Subject: [PATCH 05/69] Prepare changelog for v2.2.0-rc.1 --- CHANGELOG.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa02dc1ae3..e4b86317c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,89 @@ +Changes in [2.2.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.0-rc.1) (2020-02-26) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.1...v2.2.0-rc.1) + + * Upgrade JS SDK to 5.1.0-rc.1 + * Fix message context menu breaking on invalid m.room.pinned_events event + [\#4133](https://github.com/matrix-org/matrix-react-sdk/pull/4133) + * Update from Weblate + [\#4134](https://github.com/matrix-org/matrix-react-sdk/pull/4134) + * Notify platform of language changes + [\#4121](https://github.com/matrix-org/matrix-react-sdk/pull/4121) + * Handle errors when previewing rooms more safely + [\#4132](https://github.com/matrix-org/matrix-react-sdk/pull/4132) + * Don't try to collapse zero events with a group + [\#4131](https://github.com/matrix-org/matrix-react-sdk/pull/4131) + * Don't print errors when the tab is used with no autocomplete present + [\#4130](https://github.com/matrix-org/matrix-react-sdk/pull/4130) + * Improve UI feedback while waiting for network + [\#4126](https://github.com/matrix-org/matrix-react-sdk/pull/4126) + * Ensure DMs tagged outside of account data work in the invite dialog + [\#4123](https://github.com/matrix-org/matrix-react-sdk/pull/4123) + * Show a warning dialog when user indicates a new session wasn't them + [\#4125](https://github.com/matrix-org/matrix-react-sdk/pull/4125) + * Show cancel events as hidden events if we wouldn't usually render them + [\#4120](https://github.com/matrix-org/matrix-react-sdk/pull/4120) + * Collapsed room list has unaligned room tiles #4030 version 2 + [\#4033](https://github.com/matrix-org/matrix-react-sdk/pull/4033) + * Check for cross-signing homeserver support + [\#4118](https://github.com/matrix-org/matrix-react-sdk/pull/4118) + * Don't leak if show_sas never comes (or already came) + [\#4119](https://github.com/matrix-org/matrix-react-sdk/pull/4119) + * Add verification request viewer in devtools + [\#4106](https://github.com/matrix-org/matrix-react-sdk/pull/4106) + * update phase when request prop changes + [\#4117](https://github.com/matrix-org/matrix-react-sdk/pull/4117) + * Handle file downloading locally in electron rather than sending to browser + [\#4113](https://github.com/matrix-org/matrix-react-sdk/pull/4113) + * Remove unused CIDER setting watcher + [\#4116](https://github.com/matrix-org/matrix-react-sdk/pull/4116) + * Use alt_aliases for pills and autocomplete + [\#4102](https://github.com/matrix-org/matrix-react-sdk/pull/4102) + * Add shortcuts for beginning / end of composer + [\#4108](https://github.com/matrix-org/matrix-react-sdk/pull/4108) + * Update from Weblate + [\#4115](https://github.com/matrix-org/matrix-react-sdk/pull/4115) + * Revert "Fix escaped markdown passing backslashes through" + [\#4114](https://github.com/matrix-org/matrix-react-sdk/pull/4114) + * Fix a couple of React warnings/errors + [\#4112](https://github.com/matrix-org/matrix-react-sdk/pull/4112) + * Fix two big DOM leaks which were locking Chrome solid. + [\#4111](https://github.com/matrix-org/matrix-react-sdk/pull/4111) + * Filter out empty strings when pasting IDs into the invite dialog + [\#4109](https://github.com/matrix-org/matrix-react-sdk/pull/4109) + * Remove buildkite pipeline + [\#4107](https://github.com/matrix-org/matrix-react-sdk/pull/4107) + * Use binary packing for verification QR codes + [\#4091](https://github.com/matrix-org/matrix-react-sdk/pull/4091) + * Fix several small bugs with the invite/DM dialog + [\#4099](https://github.com/matrix-org/matrix-react-sdk/pull/4099) + * ignore e2e tests node_modules during linting + [\#4103](https://github.com/matrix-org/matrix-react-sdk/pull/4103) + * Apply null-guard to room pills for when we can't fetch the room + [\#4104](https://github.com/matrix-org/matrix-react-sdk/pull/4104) + * Fix theme being overridden to light even after login is completed + [\#4105](https://github.com/matrix-org/matrix-react-sdk/pull/4105) + * Fix bug where SSSS could be overwritten if user never cross-signs + [\#4100](https://github.com/matrix-org/matrix-react-sdk/pull/4100) + * Accept canonical alias for pills + [\#4096](https://github.com/matrix-org/matrix-react-sdk/pull/4096) + * Fix: don't advertise ability to scan a QR code for verification + [\#4094](https://github.com/matrix-org/matrix-react-sdk/pull/4094) + * Fixes for printing event indexing stats. + [\#4082](https://github.com/matrix-org/matrix-react-sdk/pull/4082) + * Remove exec so release script continues + [\#4095](https://github.com/matrix-org/matrix-react-sdk/pull/4095) + * Use Persistent Storage where possible + [\#4092](https://github.com/matrix-org/matrix-react-sdk/pull/4092) + * Fix user page (missing null check) + [\#4088](https://github.com/matrix-org/matrix-react-sdk/pull/4088) + * Cancel verification request on dialog close + [\#4081](https://github.com/matrix-org/matrix-react-sdk/pull/4081) + * Fix various memory leaks due to method re-binding + [\#4093](https://github.com/matrix-org/matrix-react-sdk/pull/4093) + * Fix share message context menu option keyboard a11y + [\#4073](https://github.com/matrix-org/matrix-react-sdk/pull/4073) + Changes in [2.1.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.1.1) (2020-02-19) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.0...v2.1.1) From c7246f8eabd55f8e2c98bd3ebc7d1c85b21fbb31 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 26 Feb 2020 14:29:31 +0000 Subject: [PATCH 06/69] v2.2.0-rc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5c18d9119e..db877edc8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.1.1", + "version": "2.2.0-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From b6a21509d5e1946aa36cc075f83be39f6e42d990 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 27 Feb 2020 11:38:31 +0000 Subject: [PATCH 07/69] Ignore cursor jumping shortcuts with shift This tweaks the new cursor jumping shortcuts in the composer so that they only activate without shift. When shift _is_ pressed, you want to extend the selection instead of just moving. Fixes https://github.com/vector-im/riot-web/issues/12549 --- src/components/views/rooms/BasicMessageComposer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/BasicMessageComposer.js b/src/components/views/rooms/BasicMessageComposer.js index e366a20326..53d78d7314 100644 --- a/src/components/views/rooms/BasicMessageComposer.js +++ b/src/components/views/rooms/BasicMessageComposer.js @@ -393,14 +393,14 @@ export default class BasicMessageEditor extends React.Component { this._insertText("\n"); handled = true; // move selection to start of composer - } else if (modKey && event.key === Key.HOME) { + } else if (modKey && event.key === Key.HOME && !event.shiftKey) { setSelection(this._editorRef, model, { index: 0, offset: 0, }); handled = true; // move selection to end of composer - } else if (modKey && event.key === Key.END) { + } else if (modKey && event.key === Key.END && !event.shiftKey) { setSelection(this._editorRef, model, { index: model.parts.length - 1, offset: model.parts[model.parts.length - 1].text.length, From c99db2c38543abc9b983d4ae7ed4142383c2d642 Mon Sep 17 00:00:00 2001 From: Ben Parsons Date: Thu, 27 Feb 2020 18:54:11 +0000 Subject: [PATCH 08/69] sanitise quotes --- .../views/settings/tabs/user/HelpUserSettingsTab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js index 1222cc1634..84403fe76e 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js @@ -163,7 +163,7 @@ export default class HelpUserSettingsTab extends React.Component { render() { let faqText = _t('For help with using Riot, click here.', {}, { 'a': (sub) => - {sub}, + {sub}, }); if (SdkConfig.get().welcomeUserId && getCurrentLanguage().startsWith('en')) { faqText = ( @@ -231,7 +231,7 @@ export default class HelpUserSettingsTab extends React.Component { { 'a': (sub) => {sub}, + rel="noreferrer noopener" target="_blank">{sub}, }) }
From 6269780f4b943ce4216faa6d29771dde3a599804 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 28 Feb 2020 13:57:56 -0700 Subject: [PATCH 09/69] Suggest the server's results as lower quality This is a quick win for fixing https://github.com/vector-im/riot-web/issues/12488 but might not be a long-term solution. Idea is to see how this feels and go from there, which may mean scoring the results again to filter them in or altering the debounce timers. --- src/components/views/dialogs/InviteDialog.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index e8c39b6d5a..b1ad4a34d0 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -906,24 +906,24 @@ export default class InviteDialog extends React.PureComponent { // Mix in the server results if we have any, but only if we're searching. We track the additional // members separately because we want to filter sourceMembers but trust the mixin arrays to have // the right members in them. - let additionalMembers = []; + let priorityAdditionalMembers = []; // Shows up before our own suggestions, higher quality + let otherAdditionalMembers = []; // Shows up after our own suggestions, lower quality const hasMixins = this.state.serverResultsMixin || this.state.threepidResultsMixin; if (this.state.filterText && hasMixins && kind === 'suggestions') { // We don't want to duplicate members though, so just exclude anyone we've already seen. const notAlreadyExists = (u: Member): boolean => { return !sourceMembers.some(m => m.userId === u.userId) - && !additionalMembers.some(m => m.userId === u.userId); + && !priorityAdditionalMembers.some(m => m.userId === u.userId) + && !otherAdditionalMembers.some(m => m.userId === u.userId); }; - const uniqueServerResults = this.state.serverResultsMixin.filter(notAlreadyExists); - additionalMembers = additionalMembers.concat(...uniqueServerResults); - - const uniqueThreepidResults = this.state.threepidResultsMixin.filter(notAlreadyExists); - additionalMembers = additionalMembers.concat(...uniqueThreepidResults); + otherAdditionalMembers = this.state.serverResultsMixin.filter(notAlreadyExists); + priorityAdditionalMembers = this.state.threepidResultsMixin.filter(notAlreadyExists); } + const hasAdditionalMembers = priorityAdditionalMembers.length > 0 || otherAdditionalMembers.length > 0; // Hide the section if there's nothing to filter by - if (sourceMembers.length === 0 && additionalMembers.length === 0) return null; + if (sourceMembers.length === 0 && !hasAdditionalMembers) return null; // Do some simple filtering on the input before going much further. If we get no results, say so. if (this.state.filterText) { @@ -931,7 +931,7 @@ export default class InviteDialog extends React.PureComponent { sourceMembers = sourceMembers .filter(m => m.user.name.toLowerCase().includes(filterBy) || m.userId.toLowerCase().includes(filterBy)); - if (sourceMembers.length === 0 && additionalMembers.length === 0) { + if (sourceMembers.length === 0 && !hasAdditionalMembers) { return (

{sectionName}

@@ -943,7 +943,7 @@ export default class InviteDialog extends React.PureComponent { // Now we mix in the additional members. Again, we presume these have already been filtered. We // also assume they are more relevant than our suggestions and prepend them to the list. - sourceMembers = [...additionalMembers, ...sourceMembers]; + sourceMembers = [...priorityAdditionalMembers, ...sourceMembers, ...otherAdditionalMembers]; // If we're going to hide one member behind 'show more', just use up the space of the button // with the member's tile instead. From 7cfaa63aac337462f24aa5ddd1f473fa2ab7cc9a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 28 Feb 2020 14:08:43 -0700 Subject: [PATCH 10/69] Fix the last char of people's names being cut off in the invite dialog If someone named "TravisR" was being searched for with just "Travis", the last R in their name would be cut off because of the highlighting. Entering "TravisR" would restore it. Likewise, searching for "vis" would have done the same thing. --- src/components/views/dialogs/InviteDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index e8c39b6d5a..a01c4cc481 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -219,7 +219,7 @@ class DMRoomTile extends React.PureComponent { } // Push any text we missed (end of text) - if (i < (str.length - 1)) { + if (i < str.length) { result.push({str.substring(i)}); } From 87e717cd397b651c6fef6a6d0a2ab3cc04b6f5df Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 28 Feb 2020 23:12:10 +0000 Subject: [PATCH 11/69] Fix Quote on search results page Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.js | 14 ++++++++++---- src/components/structures/RoomView.js | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 448cce933d..bc11e66d2c 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -559,13 +559,19 @@ export default createReactClass({ case 'view_user_info': this._viewUser(payload.userId, payload.subAction); break; - case 'view_room': + case 'view_room': { // Takes either a room ID or room alias: if switching to a room the client is already // known to be in (eg. user clicks on a room in the recents panel), supply the ID // If the user is clicking on a room in the context of the alias being presented // to them, supply the room alias. If both are supplied, the room ID will be ignored. - this._viewRoom(payload); + const promise = this._viewRoom(payload); + if (payload.deferred_action) { + promise.then(() => { + dis.dispatch(payload.deferred_action); + }); + } break; + } case 'view_prev_room': this._viewNextRoom(-1); break; @@ -862,7 +868,7 @@ export default createReactClass({ waitFor = this.firstSyncPromise.promise; } - waitFor.then(() => { + return waitFor.then(() => { let presentedId = roomInfo.room_alias || roomInfo.room_id; const room = MatrixClientPeg.get().getRoom(roomInfo.room_id); if (room) { @@ -885,7 +891,7 @@ export default createReactClass({ presentedId += "/" + roomInfo.event_id; } newState.ready = true; - this.setState(newState, ()=>{ + this.setState(newState, () => { this.notifyNewScreen('room/' + presentedId); }); }); diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index edd916697a..36e30343e4 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -614,6 +614,22 @@ export default createReactClass({ this.onCancelSearchClick(); } break; + case 'quote': + if (this.state.searchResults) { + const roomId = payload.event.getRoomId(); + if (roomId === this.state.roomId) { + this.onCancelSearchClick(); + } + + setImmediate(() => { + dis.dispatch({ + action: 'view_room', + room_id: roomId, + deferred_action: payload, + }); + }); + } + break; } }, From 9ff053c5a9fd48c0516f21183f0621114f5ae062 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 29 Feb 2020 00:09:19 +0000 Subject: [PATCH 12/69] Fix MELS not breaking on day boundaries regression Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MessagePanel.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index d0e35e1c2b..dd47028f8e 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -955,6 +955,9 @@ class MemberGrouper { } shouldGroup(ev) { + if (this.panel._wantsDateSeparator(this.events[0], ev.getDate())) { + return false; + } return isMembershipChange(ev); } From 86a1327259da5c1ed573bd4a3fd29c3acb5ef018 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 29 Feb 2020 00:31:56 +0000 Subject: [PATCH 13/69] don't show "This alias is available to use" if an alias is not provided Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/elements/RoomAliasField.js | 1 + src/components/views/elements/Validation.js | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/RoomAliasField.js b/src/components/views/elements/RoomAliasField.js index 007bd07a47..0139a9596b 100644 --- a/src/components/views/elements/RoomAliasField.js +++ b/src/components/views/elements/RoomAliasField.js @@ -92,6 +92,7 @@ export default class RoomAliasField extends React.PureComponent { invalid: () => _t("Please provide a room alias"), }, { key: "taken", + skip: ({value}) => !value, test: async ({value}) => { if (!value) { return true; diff --git a/src/components/views/elements/Validation.js b/src/components/views/elements/Validation.js index 31363b87c8..3454ab3aec 100644 --- a/src/components/views/elements/Validation.js +++ b/src/components/views/elements/Validation.js @@ -51,9 +51,16 @@ export default function withValidation({ description, rules }) { if (!rule.key || !rule.test) { continue; } + + const data = { value, allowEmpty }; + + if (rule.skip && rule.skip.call(this, data)) { + continue; + } + // We're setting `this` to whichever component holds the validation // function. That allows rules to access the state of the component. - const ruleValid = await rule.test.call(this, { value, allowEmpty }); + const ruleValid = await rule.test.call(this, data); valid = valid && ruleValid; if (ruleValid && rule.valid) { // If the rule's result is valid and has text to show for From 3e85f65d9e7a5b3a64091e061ff1137a9b58fcab Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 29 Feb 2020 00:36:01 +0000 Subject: [PATCH 14/69] Also skip alias availability check if alias looks invalid Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/elements/RoomAliasField.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/views/elements/RoomAliasField.js b/src/components/views/elements/RoomAliasField.js index 0139a9596b..06e608b14c 100644 --- a/src/components/views/elements/RoomAliasField.js +++ b/src/components/views/elements/RoomAliasField.js @@ -38,6 +38,13 @@ export default class RoomAliasField extends React.PureComponent { return `#${localpart}:${this.props.domain}`; } + _isValid(value) { + const fullAlias = this._asFullAlias(value); + // XXX: FIXME https://github.com/matrix-org/matrix-doc/issues/668 + return !value.includes("#") && !value.includes(":") && !value.includes(",") && + encodeURI(fullAlias) === fullAlias; + } + render() { const Field = sdk.getComponent('views.elements.Field'); const poundSign = (#); @@ -80,10 +87,7 @@ export default class RoomAliasField extends React.PureComponent { if (!value) { return true; } - const fullAlias = this._asFullAlias(value); - // XXX: FIXME https://github.com/matrix-org/matrix-doc/issues/668 - return !value.includes("#") && !value.includes(":") && !value.includes(",") && - encodeURI(fullAlias) === fullAlias; + return this._isValid(value); }, invalid: () => _t("Some characters not allowed"), }, { @@ -92,7 +96,7 @@ export default class RoomAliasField extends React.PureComponent { invalid: () => _t("Please provide a room alias"), }, { key: "taken", - skip: ({value}) => !value, + skip: ({value}) => !value || !this._isValid(value), test: async ({value}) => { if (!value) { return true; From 3a7454a52f4d39bea227be8184b16e15b68a4249 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Fri, 28 Feb 2020 18:37:52 -0600 Subject: [PATCH 15/69] Use !== instead Signed-off-by: Aaron Raimist --- src/components/structures/LoggedInView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 023272cef1..20217548b7 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -586,7 +586,7 @@ const LoggedInView = createReactClass({ />; } else if (this.props.showCookieBar && this.props.config.piwik && - navigator.doNotTrack != 1 + navigator.doNotTrack !== "1" ) { const policyUrl = this.props.config.piwik.policyUrl || null; topBar = ; From 8aaab0a3baa7efd812df05a401c1c7138fdd97ff Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 29 Feb 2020 01:00:57 +0000 Subject: [PATCH 16/69] refactor to add Validation::final Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/elements/RoomAliasField.js | 14 +++++--------- src/components/views/elements/Validation.js | 6 ++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/views/elements/RoomAliasField.js b/src/components/views/elements/RoomAliasField.js index 06e608b14c..b38047cd3b 100644 --- a/src/components/views/elements/RoomAliasField.js +++ b/src/components/views/elements/RoomAliasField.js @@ -38,13 +38,6 @@ export default class RoomAliasField extends React.PureComponent { return `#${localpart}:${this.props.domain}`; } - _isValid(value) { - const fullAlias = this._asFullAlias(value); - // XXX: FIXME https://github.com/matrix-org/matrix-doc/issues/668 - return !value.includes("#") && !value.includes(":") && !value.includes(",") && - encodeURI(fullAlias) === fullAlias; - } - render() { const Field = sdk.getComponent('views.elements.Field'); const poundSign = (#); @@ -87,7 +80,10 @@ export default class RoomAliasField extends React.PureComponent { if (!value) { return true; } - return this._isValid(value); + const fullAlias = this._asFullAlias(value); + // XXX: FIXME https://github.com/matrix-org/matrix-doc/issues/668 + return !value.includes("#") && !value.includes(":") && !value.includes(",") && + encodeURI(fullAlias) === fullAlias; }, invalid: () => _t("Some characters not allowed"), }, { @@ -96,7 +92,7 @@ export default class RoomAliasField extends React.PureComponent { invalid: () => _t("Please provide a room alias"), }, { key: "taken", - skip: ({value}) => !value || !this._isValid(value), + final: true, test: async ({value}) => { if (!value) { return true; diff --git a/src/components/views/elements/Validation.js b/src/components/views/elements/Validation.js index 3454ab3aec..2be526a3c3 100644 --- a/src/components/views/elements/Validation.js +++ b/src/components/views/elements/Validation.js @@ -28,9 +28,11 @@ import classNames from 'classnames'; * An array of rules describing how to check to input value. Each rule in an object * and may have the following properties: * - `key`: A unique ID for the rule. Required. + * - `skip`: A function used to determine whether the rule should even be evaluated. * - `test`: A function used to determine the rule's current validity. Required. * - `valid`: Function returning text to show when the rule is valid. Only shown if set. * - `invalid`: Function returning text to show when the rule is invalid. Only shown if set. + * - `final`: A Boolean if true states that this rule will only be considered if all rules before it returned valid. * @returns {Function} * A validation function that takes in the current input value and returns * the overall validity and a feedback UI that can be rendered for more detail. @@ -52,6 +54,10 @@ export default function withValidation({ description, rules }) { continue; } + if (!valid && rule.final) { + continue; + } + const data = { value, allowEmpty }; if (rule.skip && rule.skip.call(this, data)) { From a5e664410f9b45d727b2958c11ae4671564ea8a6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 29 Feb 2020 01:29:52 +0000 Subject: [PATCH 17/69] Add /whois SlashCommand to open UserInfo Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/SlashCommands.js | 20 ++++++++++++++++++++ src/i18n/strings/en_EN.json | 1 + 2 files changed, 21 insertions(+) diff --git a/src/SlashCommands.js b/src/SlashCommands.js index b39b8fb9ac..d306978f78 100644 --- a/src/SlashCommands.js +++ b/src/SlashCommands.js @@ -893,6 +893,26 @@ export const CommandMap = { }, category: CommandCategories.advanced, }), + + whois: new Command({ + name: "whois", + description: _td("Displays information about a user"), + args: '', + runFn: function(roomId, userId) { + if (!userId || !userId.startsWith("@") || !userId.includes(":")) { + return reject(this.getUsage()); + } + + const member = MatrixClientPeg.get().getRoom(roomId).getMember(userId); + + dis.dispatch({ + action: 'view_user', + member: member || {userId}, + }); + return success(); + }, + category: CommandCategories.advanced, + }), }; /* eslint-enable babel/no-invalid-this */ diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ba48f7cd37..ab18c58e90 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -204,6 +204,7 @@ "Sends the given message coloured as a rainbow": "Sends the given message coloured as a rainbow", "Sends the given emote coloured as a rainbow": "Sends the given emote coloured as a rainbow", "Displays list of commands with usages and descriptions": "Displays list of commands with usages and descriptions", + "Displays information about a user": "Displays information about a user", "Reason": "Reason", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s accepted the invitation for %(displayName)s.", "%(targetName)s accepted an invitation.": "%(targetName)s accepted an invitation.", From 4996139b1a933cb4baf180ce05de106e907eef0a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 29 Feb 2020 01:56:02 +0000 Subject: [PATCH 18/69] word-break in pills and wrap the background correctly Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/elements/_RichText.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/res/css/views/elements/_RichText.scss b/res/css/views/elements/_RichText.scss index 73f0be291f..5066ee10f3 100644 --- a/res/css/views/elements/_RichText.scss +++ b/res/css/views/elements/_RichText.scss @@ -13,6 +13,11 @@ padding-left: 5px; } +a.mx_Pill { + word-break: break-all; + display: inline; +} + /* More specific to override `.markdown-body a` text-decoration */ .mx_EventTile_content .markdown-body a.mx_Pill { text-decoration: none; From 8ec83d4a7711452c1c9857b6f9fad1f5343e10ae Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 2 Mar 2020 11:20:28 +0000 Subject: [PATCH 19/69] Revert to manual sorting for custom tag rooms --- src/stores/RoomListStore.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index 30b523d35d..561d865b66 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -62,15 +62,16 @@ const getListAlgorithm = (listKey, settingAlgorithm) => { // apply manual sorting only to m.favourite, otherwise respect the global setting // all the known tags are listed explicitly here to simplify future changes switch (listKey) { - case "m.favourite": - return ALGO_MANUAL; case "im.vector.fake.invite": case "im.vector.fake.recent": case "im.vector.fake.archived": case "m.lowpriority": case TAG_DM: - default: return settingAlgorithm; + + case "m.favourite": + default: // custom-tags + return ALGO_MANUAL; } }; From f8045e428bad7a1dde1df56fab1e4a3a62ea021d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 2 Mar 2020 14:59:54 +0000 Subject: [PATCH 20/69] riot-desktop open SSO in browser so user doesn't have to auth twice --- src/BasePlatform.js | 24 ++++++++++++ src/Login.js | 28 ++++--------- src/components/structures/auth/Login.js | 12 ++++-- src/components/structures/auth/SoftLogout.js | 31 ++------------- src/components/views/elements/SSOButton.js | 41 ++++++++++++++++++++ src/i18n/strings/en_EN.json | 2 +- 6 files changed, 86 insertions(+), 52 deletions(-) create mode 100644 src/components/views/elements/SSOButton.js diff --git a/src/BasePlatform.js b/src/BasePlatform.js index a935f4a767..809fe198d6 100644 --- a/src/BasePlatform.js +++ b/src/BasePlatform.js @@ -4,6 +4,7 @@ Copyright 2016 Aviral Dasgupta Copyright 2016 OpenMarket Ltd Copyright 2018 New Vector Ltd +Copyright 2020 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. @@ -18,6 +19,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import {MatrixClient} from "matrix-js-sdk"; import dis from './dispatcher'; import BaseEventIndexManager from './indexing/BaseEventIndexManager'; @@ -164,4 +166,26 @@ export default class BasePlatform { } setLanguage(preferredLangs: string[]) {} + + getSSOCallbackUrl(hsUrl: string, isUrl: string): URL { + const url = new URL(window.location.href); + // XXX: at this point, the fragment will always be #/login, which is no + // use to anyone. Ideally, we would get the intended fragment from + // MatrixChat.screenAfterLogin so that you could follow #/room links etc + // through an SSO login. + url.hash = ""; + url.searchParams.set("homeserver", hsUrl); + url.searchParams.set("identityServer", isUrl); + return url; + } + + /** + * Begin Single Sign On flows. + * @param mxClient the matrix client using which we should start the flow + * @param loginType the type of SSO it is, CAS/SSO. + */ + startSingleSignOn(mxClient: MatrixClient, loginType: "sso"|"cas") { + const callbackUrl = this.getSSOCallbackUrl(mxClient.getHomeserverUrl(), mxClient.getIdentityServerUrl()); + window.location.href = mxClient.getSsoLoginUrl(callbackUrl.toString(), loginType); // redirect to SSO + } } diff --git a/src/Login.js b/src/Login.js index d9ce8adaaa..1590e5ac28 100644 --- a/src/Login.js +++ b/src/Login.js @@ -3,6 +3,7 @@ Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd Copyright 2018 New Vector Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> +Copyright 2020 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. @@ -19,8 +20,6 @@ limitations under the License. import Matrix from "matrix-js-sdk"; -import url from 'url'; - export default class Login { constructor(hsUrl, isUrl, fallbackHsUrl, opts) { this._hsUrl = hsUrl; @@ -29,6 +28,7 @@ export default class Login { this._currentFlowIndex = 0; this._flows = []; this._defaultDeviceDisplayName = opts.defaultDeviceDisplayName; + this._tempClient = null; // memoize } getHomeserverUrl() { @@ -40,10 +40,12 @@ export default class Login { } setHomeserverUrl(hsUrl) { + this._tempClient = null; // clear memoization this._hsUrl = hsUrl; } setIdentityServerUrl(isUrl) { + this._tempClient = null; // clear memoization this._isUrl = isUrl; } @@ -52,8 +54,9 @@ export default class Login { * requests. * @returns {MatrixClient} */ - _createTemporaryClient() { - return Matrix.createClient({ + createTemporaryClient() { + if (this._tempClient) return this._tempClient; // use memoization + return this._tempClient = Matrix.createClient({ baseUrl: this._hsUrl, idBaseUrl: this._isUrl, }); @@ -61,7 +64,7 @@ export default class Login { getFlows() { const self = this; - const client = this._createTemporaryClient(); + const client = this.createTemporaryClient(); return client.loginFlows().then(function(result) { self._flows = result.flows; self._currentFlowIndex = 0; @@ -139,21 +142,6 @@ export default class Login { throw error; }); } - - getSsoLoginUrl(loginType) { - const client = this._createTemporaryClient(); - const parsedUrl = url.parse(window.location.href, true); - - // XXX: at this point, the fragment will always be #/login, which is no - // use to anyone. Ideally, we would get the intended fragment from - // MatrixChat.screenAfterLogin so that you could follow #/room links etc - // through an SSO login. - parsedUrl.hash = ""; - - parsedUrl.query["homeserver"] = client.getHomeserverUrl(); - parsedUrl.query["identityServer"] = client.getIdentityServerUrl(); - return client.getSsoLoginUrl(url.format(parsedUrl), loginType); - } } diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 24e4726416..3813146b5e 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -27,6 +27,7 @@ import { messageForResourceLimitError } from '../../../utils/ErrorUtils'; import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; import classNames from "classnames"; import AuthPage from "../../views/auth/AuthPage"; +import SSOButton from "../../views/elements/SSOButton"; // For validating phone numbers without country codes const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/; @@ -120,8 +121,8 @@ export default createReactClass({ 'm.login.password': this._renderPasswordStep, // CAS and SSO are the same thing, modulo the url we link to - 'm.login.cas': () => this._renderSsoStep(this._loginLogic.getSsoLoginUrl("cas")), - 'm.login.sso': () => this._renderSsoStep(this._loginLogic.getSsoLoginUrl("sso")), + 'm.login.cas': () => this._renderSsoStep("cas"), + 'm.login.sso': () => this._renderSsoStep("sso"), }; this._initLoginLogic(); @@ -585,7 +586,7 @@ export default createReactClass({ ); }, - _renderSsoStep: function(url) { + _renderSsoStep: function(loginType) { const SignInToText = sdk.getComponent('views.auth.SignInToText'); let onEditServerDetailsClick = null; @@ -606,7 +607,10 @@ export default createReactClass({ - { _t('Sign in with single sign-on') } +
); }, diff --git a/src/components/structures/auth/SoftLogout.js b/src/components/structures/auth/SoftLogout.js index 8481b3fc43..d38fcf3883 100644 --- a/src/components/structures/auth/SoftLogout.js +++ b/src/components/structures/auth/SoftLogout.js @@ -23,8 +23,8 @@ import * as Lifecycle from '../../../Lifecycle'; import Modal from '../../../Modal'; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import {sendLoginRequest} from "../../../Login"; -import url from 'url'; import AuthPage from "../../views/auth/AuthPage"; +import SSOButton from "../../views/elements/SSOButton"; const LOGIN_VIEW = { LOADING: 1, @@ -55,7 +55,6 @@ export default class SoftLogout extends React.Component { this.state = { loginView: LOGIN_VIEW.LOADING, keyBackupNeeded: true, // assume we do while we figure it out (see componentWillMount) - ssoUrl: null, busy: false, password: "", @@ -105,18 +104,6 @@ export default class SoftLogout extends React.Component { const chosenView = loginViews.filter(f => !!f)[0] || LOGIN_VIEW.UNSUPPORTED; this.setState({loginView: chosenView}); - - if (chosenView === LOGIN_VIEW.CAS || chosenView === LOGIN_VIEW.SSO) { - const client = MatrixClientPeg.get(); - - const appUrl = url.parse(window.location.href, true); - appUrl.hash = ""; // Clear #/soft_logout off the URL - appUrl.query["homeserver"] = client.getHomeserverUrl(); - appUrl.query["identityServer"] = client.getIdentityServerUrl(); - - const ssoUrl = client.getSsoLoginUrl(url.format(appUrl), chosenView === LOGIN_VIEW.CAS ? "cas" : "sso"); - this.setState({ssoUrl}); - } } onPasswordChange = (ev) => { @@ -195,14 +182,6 @@ export default class SoftLogout extends React.Component { }); } - onSsoLogin = async (ev) => { - ev.preventDefault(); - ev.stopPropagation(); - - this.setState({busy: true}); - window.location.href = this.state.ssoUrl; - }; - _renderSignInSection() { if (this.state.loginView === LOGIN_VIEW.LOADING) { const Spinner = sdk.getComponent("elements.Spinner"); @@ -257,8 +236,6 @@ export default class SoftLogout extends React.Component { } if (this.state.loginView === LOGIN_VIEW.SSO || this.state.loginView === LOGIN_VIEW.CAS) { - const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - if (!introText) { introText = _t("Sign in and regain access to your account."); } // else we already have a message and should use it (key backup warning) @@ -266,9 +243,9 @@ export default class SoftLogout extends React.Component { return (

{introText}

- - {_t('Sign in with single sign-on')} - +
); } diff --git a/src/components/views/elements/SSOButton.js b/src/components/views/elements/SSOButton.js new file mode 100644 index 0000000000..3e0757924b --- /dev/null +++ b/src/components/views/elements/SSOButton.js @@ -0,0 +1,41 @@ +/* +Copyright 2020 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 PlatformPeg from "../../../PlatformPeg"; +import AccessibleButton from "./AccessibleButton"; +import {_t} from "../../../languageHandler"; + +const SSOButton = ({matrixClient, loginType, ...props}) => { + const onClick = () => { + PlatformPeg.get().startSingleSignOn(matrixClient, loginType); + }; + + return ( + + {_t("Sign in with single sign-on")} + + ); +}; + +SSOButton.propTypes = { + matrixClient: PropTypes.object.isRequired, // does not use context as may use a temporary client + loginType: PropTypes.oneOf(["sso", "cas"]), // defaults to "sso" in base-apis +}; + +export default SSOButton; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ba48f7cd37..9471b62c59 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1429,6 +1429,7 @@ "This alias is available to use": "This alias is available to use", "This alias is already in use": "This alias is already in use", "Room directory": "Room directory", + "Sign in with single sign-on": "Sign in with single sign-on", "And %(count)s more...|other": "And %(count)s more...", "ex. @bob:example.com": "ex. @bob:example.com", "Add User": "Add User", @@ -2001,7 +2002,6 @@ "Error: Problem communicating with the given homeserver.": "Error: Problem communicating with the given homeserver.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.", "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.", - "Sign in with single sign-on": "Sign in with single sign-on", "Create account": "Create account", "Failed to fetch avatar URL": "Failed to fetch avatar URL", "Set a display name:": "Set a display name:", From 4d9d5a1ab7954b1e01be14cbd58754015b990b25 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 2 Mar 2020 15:05:56 +0000 Subject: [PATCH 21/69] improve comments --- src/BasePlatform.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BasePlatform.js b/src/BasePlatform.js index 809fe198d6..5d809eb28f 100644 --- a/src/BasePlatform.js +++ b/src/BasePlatform.js @@ -181,8 +181,8 @@ export default class BasePlatform { /** * Begin Single Sign On flows. - * @param mxClient the matrix client using which we should start the flow - * @param loginType the type of SSO it is, CAS/SSO. + * @param {MatrixClient} mxClient the matrix client using which we should start the flow + * @param {"sso"|"cas"} loginType the type of SSO it is, CAS/SSO. */ startSingleSignOn(mxClient: MatrixClient, loginType: "sso"|"cas") { const callbackUrl = this.getSSOCallbackUrl(mxClient.getHomeserverUrl(), mxClient.getIdentityServerUrl()); From 7fcad8c82c1b56736dfb589edce9893f64392f25 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 2 Mar 2020 17:29:36 +0000 Subject: [PATCH 22/69] Upgrade matrix-js-sdk to 5.1.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index db877edc8c..188db47416 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "5.1.0-rc.1", + "matrix-js-sdk": "5.1.0", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index b01b64a8b3..8770bf39e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5791,10 +5791,10 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.1.tgz#6dff66c99d55ecf739ca53c492e626f1d12a33cc" integrity sha512-pWB896KPGSGkp1XtyzRBftpTzwSOL0Gfk0wLvxt4f2mgzjY19o0LxJ3U25vNWTzsh7da+KTbuXQoQ3lOJZ8WHw== -matrix-js-sdk@5.1.0-rc.1: - version "5.1.0-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.1.0-rc.1.tgz#48154133f1c8bc19557164a24535d6d45d1cf482" - integrity sha512-3pf8NOziyaldtJkYsas9Cq/b8TloGMY89KRA4tJLRDCdMrlBEJoQ4qb9MCmhS53Yb8N4ysI7qUUC21FtBryAVQ== +matrix-js-sdk@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.1.0.tgz#9b3b02af227ecc2d0cc35fb7312c92b8a6754293" + integrity sha512-IGRq5iACiKp3iIxAghwtdBPrbdgORowc0i8YuIMkZZMpRJDXnNaudt2BFwyQdukV7gvzz7F0sfxBUerySfOnKA== dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From 51b10702f07dd2862fc7b6362f1414bff44cf462 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 2 Mar 2020 17:33:23 +0000 Subject: [PATCH 23/69] Prepare changelog for v2.2.0 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4b86317c8..88d1895691 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +Changes in [2.2.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.0) (2020-03-02) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.0-rc.1...v2.2.0) + + * Upgrade JS SDK to 5.1.0 + * Ignore cursor jumping shortcuts with shift + [\#4142](https://github.com/matrix-org/matrix-react-sdk/pull/4142) + Changes in [2.2.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.0-rc.1) (2020-02-26) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.1.1...v2.2.0-rc.1) From 134ca31b25b14bcd3e290029311d2127e3a522d6 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 2 Mar 2020 17:33:23 +0000 Subject: [PATCH 24/69] v2.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 188db47416..f5bd9ec19f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.2.0-rc.1", + "version": "2.2.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 00dc187f7165a0659ce1ae5bbd3fd491ba5650db Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 2 Mar 2020 17:43:21 +0000 Subject: [PATCH 25/69] Reset matrix-js-sdk back to develop --- package.json | 2 +- yarn.lock | 200 ++++----------------------------------------------- 2 files changed, 14 insertions(+), 188 deletions(-) diff --git a/package.json b/package.json index f5bd9ec19f..e453b63a4d 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "is-ip": "^2.0.0", "linkifyjs": "^2.1.6", "lodash": "^4.17.14", - "matrix-js-sdk": "5.1.0", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "minimist": "^1.2.0", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 7417fa2a78..87aeccd140 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1438,11 +1438,6 @@ abab@^2.0.0: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - acorn-globals@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" @@ -1576,19 +1571,11 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -aproba@^1.0.3, aproba@^1.1.1: +aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2494,11 +2481,6 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -2734,7 +2716,7 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.1.0, debug@^3.2.6: +debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -2810,11 +2792,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - des.js@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -2828,11 +2805,6 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" @@ -3833,13 +3805,6 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - fs-readdir-recursive@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" @@ -3902,20 +3867,6 @@ fuse.js@^2.2.0: resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-2.7.4.tgz#96e420fde7ef011ac49c258a621314fe576536f9" integrity sha1-luQg/efvARrEnCWKYhMU/ldlNvk= -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - "gemini-scrollbar@github:matrix-org/gemini-scrollbar#91e1e566", gemini-scrollbar@matrix-org/gemini-scrollbar#91e1e566: version "1.4.3" resolved "https://codeload.github.com/matrix-org/gemini-scrollbar/tar.gz/91e1e566fa33324188f278801baf4a79f9f554ab" @@ -4117,11 +4068,6 @@ has-symbols@^1.0.0, has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -4309,7 +4255,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4326,13 +4272,6 @@ iferr@^0.1.5: resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= -ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - ignore@^4.0.3, ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -5714,10 +5653,9 @@ mathml-tag-names@^2.0.1: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@5.1.0: +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "5.1.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-5.1.0.tgz#9b3b02af227ecc2d0cc35fb7312c92b8a6754293" - integrity sha512-IGRq5iACiKp3iIxAghwtdBPrbdgORowc0i8YuIMkZZMpRJDXnNaudt2BFwyQdukV7gvzz7F0sfxBUerySfOnKA== + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/da96765020b632deb5b433077827a4f4a64e16e9" dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" @@ -5907,21 +5845,6 @@ minimist@1.2.0, minimist@^1.1.1, minimist@^1.2.0, "minimist@~ 1.2.0": resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -5946,7 +5869,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -6023,15 +5946,6 @@ nearley@^2.7.10: randexp "0.4.6" semver "^5.4.1" -needle@^2.2.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.2.tgz#3342dea100b7160960a450dc8c22160ac712a528" - integrity sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - neo-async@^2.5.0, neo-async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" @@ -6109,22 +6023,6 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - node-releases@^1.1.49: version "1.1.50" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.50.tgz#803c40d2c45db172d0410e4efec83aa8c6ad0592" @@ -6132,14 +6030,6 @@ node-releases@^1.1.49: dependencies: semver "^6.3.0" -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -6172,27 +6062,6 @@ normalize-selector@^0.2.0: resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= -npm-bundled@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" - integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== - dependencies: - npm-normalize-package-bin "^1.0.1" - -npm-normalize-package-bin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" - integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== - -npm-packlist@^1.1.6: - version "1.4.8" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" - integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-normalize-package-bin "^1.0.1" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -6200,16 +6069,6 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - nth-check@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -6359,11 +6218,6 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - os-locale@^3.0.0, os-locale@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" @@ -6373,19 +6227,11 @@ os-locale@^3.0.0, os-locale@^3.1.0: lcid "^2.0.0" mem "^4.0.0" -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -7015,7 +6861,7 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -rc@1.2.8, rc@^1.2.7, rc@^1.2.8: +rc@1.2.8, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -7179,7 +7025,7 @@ read-pkg@^4.0.1: parse-json "^4.0.0" pify "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -7538,7 +7384,7 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.4.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@^2.4.3, rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -7700,7 +7546,7 @@ serialize-javascript@^2.1.2: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -8036,7 +7882,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -8299,19 +8145,6 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^4.4.2: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - terser-webpack-plugin@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" @@ -9031,13 +8864,6 @@ which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -9115,7 +8941,7 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== From 677dce75c5fe4827ff24ab742686a6193441cdf1 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 2 Mar 2020 17:48:38 +0000 Subject: [PATCH 26/69] Use bash for release script This fixes this repo to use bash for this script, matching the other repos. --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 3c28084bb7..1b99e870ac 100755 --- a/release.sh +++ b/release.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Script to perform a release of matrix-react-sdk. # From d95f843cd0bf16adf17ba1c25c530c124b84241c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 2 Mar 2020 17:52:20 -0700 Subject: [PATCH 27/69] Don't group blank membership changes We already drop noop membership changes when they don't make it into a MELS, so we just need to make the MELS aware enough to drop messages early that are noops. Fixes https://github.com/vector-im/riot-web/issues/12575 --- src/components/structures/MessagePanel.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index dd47028f8e..0029090a94 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -962,6 +962,17 @@ class MemberGrouper { } add(ev) { + if (ev.getType() === 'm.room.member') { + // We'll just double check that it's worth our time to do so... + if (ev.getPrevContent()) { + const membershipChange = ev.getPrevContent()['membership'] !== ev.getContent()['membership']; + const displayNameChange = ev.getPrevContent()['displayname'] !== ev.getContent()['displayname']; + const avatarChange = ev.getPrevContent()['avatar_url'] !== ev.getContent()['avatar_url']; + if (!membershipChange && !displayNameChange && !avatarChange) { + return; // Not a substantial change - quietly ignore + } + } + } this.readMarker = this.readMarker || this.panel._readMarkerForEvent(ev.getId()); this.events.push(ev); } From 88f351d5ca8e113b38f1b126d4b7e2ad5d544e3a Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Tue, 3 Mar 2020 10:40:58 +0000 Subject: [PATCH 28/69] Keep sign in button disabled on success This changes password login to keep the sign in button locked when proceeding successfully to avoid the possibility of double device sign in. Part of https://github.com/vector-im/riot-web/issues/12546 --- src/components/structures/auth/Login.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 24e4726416..589accacc3 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -245,6 +245,7 @@ export default createReactClass({ } this.setState({ + busy: false, errorText: errorText, // 401 would be the sensible status code for 'incorrect password' // but the login API gives a 403 https://matrix.org/jira/browse/SYN-744 @@ -252,13 +253,6 @@ export default createReactClass({ // We treat both as an incorrect password loginIncorrect: error.httpStatus === 401 || error.httpStatus === 403, }); - }).finally(() => { - if (this._unmounted) { - return; - } - this.setState({ - busy: false, - }); }); }, From 0e65d54af298399bb1a2b70a0c1211e3648391b2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 3 Mar 2020 11:03:40 +0000 Subject: [PATCH 29/69] Fix having to decrypt & download in two steps --- src/components/views/messages/MFileBody.js | 4 +++- src/usercontent/index.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js index 886afbb666..312346f412 100644 --- a/src/components/views/messages/MFileBody.js +++ b/src/components/views/messages/MFileBody.js @@ -247,6 +247,8 @@ export default createReactClass({ }); }; + // This button should actually Download because usercontent/ will try to click itself + // but it is not guaranteed between various browsers' settings. return (
@@ -290,7 +292,7 @@ export default createReactClass({ src={`${url}?origin=${encodeURIComponent(window.location.origin)}`} onLoad={onIframeLoad} ref={this._iframe} - sandbox="allow-scripts allow-downloads" /> + sandbox="allow-scripts allow-downloads allow-downloads-without-user-activation" />
); diff --git a/src/usercontent/index.js b/src/usercontent/index.js index 08769d6bd1..47eb83964f 100644 --- a/src/usercontent/index.js +++ b/src/usercontent/index.js @@ -27,6 +27,7 @@ function remoteRender(event) { // Don't display scrollbars if the link takes more than one line to display. body.style = "margin: 0px; overflow: hidden"; body.appendChild(a); + a.click(); // try to trigger download automatically } function remoteSetTint(event) { From c0b68ccd53e7c718fd6197f85f885c1e182a421a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 3 Mar 2020 13:23:33 +0000 Subject: [PATCH 30/69] only automatically download in usercontent if user requested it --- src/components/views/messages/MFileBody.js | 2 ++ src/usercontent/index.js | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js index 312346f412..125c538f82 100644 --- a/src/components/views/messages/MFileBody.js +++ b/src/components/views/messages/MFileBody.js @@ -271,6 +271,8 @@ export default createReactClass({ // We can't provide a Content-Disposition header like we would for HTTP. download: fileName, textContent: _t("Download %(text)s", { text: text }), + // only auto-download if a user triggered this iframe explicitly + auto: !this.props.decryptedBlob, }, "*"); }; diff --git a/src/usercontent/index.js b/src/usercontent/index.js index 47eb83964f..2e87e182af 100644 --- a/src/usercontent/index.js +++ b/src/usercontent/index.js @@ -27,7 +27,10 @@ function remoteRender(event) { // Don't display scrollbars if the link takes more than one line to display. body.style = "margin: 0px; overflow: hidden"; body.appendChild(a); - a.click(); // try to trigger download automatically + + if (event.data.auto) { + a.click(); // try to trigger download automatically + } } function remoteSetTint(event) { From 59c4e36ba884b7b32cf6d1b0e170092df1abd91d Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Tue, 3 Mar 2020 14:40:21 +0000 Subject: [PATCH 31/69] Lock interactive auth as busy until state change This keeps interactive auth locked as busy until a state change so that e.g. accepting a terms step will remain "busy looking" until the next step of the process appears. Fixes https://github.com/vector-im/riot-web/issues/12546 --- src/components/structures/InteractiveAuth.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js index 3d63029b06..9521dd76ec 100644 --- a/src/components/structures/InteractiveAuth.js +++ b/src/components/structures/InteractiveAuth.js @@ -161,6 +161,7 @@ export default createReactClass({ _authStateUpdated: function(stageType, stageState) { const oldStage = this.state.authStage; this.setState({ + busy: false, authStage: stageType, stageState: stageState, errorText: stageState.error, @@ -184,10 +185,6 @@ export default createReactClass({ errorText: null, stageErrorText: null, }); - } else { - this.setState({ - busy: false, - }); } }, From f9d2d45b242c1035a68ec3961ca05eafdad39aa2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 3 Mar 2020 15:42:22 +0100 Subject: [PATCH 32/69] use relative scrolling to compensate when changing height --- src/components/structures/ScrollPanel.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 5121dd3f9d..72d5330451 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -705,17 +705,15 @@ export default createReactClass({ // the currently filled piece of the timeline if (trackedNode) { const oldTop = trackedNode.offsetTop; - // changing the height might change the scrollTop - // if the new height is smaller than the scrollTop. - // We calculate the diff that needs to be applied - // ourselves, so be sure to measure the - // scrollTop before changing the height. - const preexistingScrollTop = sn.scrollTop; itemlist.style.height = `${newHeight}px`; const newTop = trackedNode.offsetTop; const topDiff = newTop - oldTop; - sn.scrollTop = preexistingScrollTop + topDiff; - debuglog("updateHeight to", {newHeight, topDiff, preexistingScrollTop}); + // important to scroll by a relative amount as + // reading scrollTop and then setting it might + // yield out of date values and cause a jump + // when setting it + sn.scrollBy(0, topDiff); + debuglog("updateHeight to", {newHeight, topDiff}); } } }, From 223956a206f217e4d6ed5e2abfb1b0558b336414 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 3 Mar 2020 15:42:44 +0100 Subject: [PATCH 33/69] add comment how offset from bottom is calculated --- src/components/structures/ScrollPanel.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 72d5330451..548dd70748 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -765,6 +765,7 @@ export default createReactClass({ }, _topFromBottom(node) { + // current capped height - distance from top = distance from bottom of container to top of tracked element return this._itemlist.current.clientHeight - node.offsetTop; }, From 3e39cebb8f18006a5e20a44a45f3e21aaf59b17c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 3 Mar 2020 15:44:59 +0100 Subject: [PATCH 34/69] also use relative scrolling when eh ... doing relative scrolling --- src/components/structures/ScrollPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 548dd70748..b81b3ebede 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -523,7 +523,7 @@ export default createReactClass({ scrollRelative: function(mult) { const scrollNode = this._getScrollNode(); const delta = mult * scrollNode.clientHeight * 0.5; - scrollNode.scrollTop = scrollNode.scrollTop + delta; + scrollNode.scrollBy(0, delta); this._saveScrollState(); }, From 5d6690f74bdcb4f543996e21c733c7c4d4db7905 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 3 Mar 2020 17:59:02 +0100 Subject: [PATCH 35/69] document scrollpanel and bacat scrolling --- docs/scrolling.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 docs/scrolling.md diff --git a/docs/scrolling.md b/docs/scrolling.md new file mode 100644 index 0000000000..71329e5c32 --- /dev/null +++ b/docs/scrolling.md @@ -0,0 +1,28 @@ +# ScrollPanel + +## Updates + +During an onscroll event, we check whether we're getting close to the top or bottom edge of the loaded content. If close enough, we fire a request to load more through the callback passed in the `onFillRequest` prop. This returns a promise is passed down from `TimelinePanel`, where it will call paginate on the `TimelineWindow` and once the events are received back, update its state with the new events. This update trickles down to the `MessagePanel`, which rerenders all tiles and passed that to `ScrollPanel`. ScrollPanels `componentDidUpdate` method gets called, and we do the scroll housekeeping there (read below). Once the rerender has completed, the `setState` callback is called and we resolve the promise returned by `onFillRequest`. Now we check the DOM to see if we need more fill requests. + +## Prevent Shrinking + +ScrollPanel supports a mode to prevent it shrinking. This is used to prevent a jump when at the bottom of the timeline and people start and stop typing. It gets cleared automatically when 200px above the bottom of the timeline. + + +## BACAT (Bottom-Aligned, Clipped-At-Top) scrolling + +BACAT scrolling implements a different way of restoring the scroll position in the timeline while tiles out of view are changing height or tiles are being added or removed. It was added in https://github.com/matrix-org/matrix-react-sdk/pull/2842. + +The motivation for the changes is having noticed that setting scrollTop while scrolling tends to not work well, with it interrupting ongoing scrolling and also querying scrollTop reporting outdated values and consecutive scroll adjustments cancelling each out previous ones. This seems to be worse on macOS than other platforms, presumably because of a higher resolution in scroll events there. Also see https://github.com/vector-im/riot-web/issues/528. The BACAT approach allows to only have to change the scroll offset when adding or removing tiles. + +The approach taken instead is to vertically align the timeline tiles to the bottom of the scroll container (using flexbox) and give the timeline inside the scroll container an explicit height, initially set to a multiple of the PAGE_SIZE (400px at time of writing) as needed by the content. When scrolled up, we can compensate for anything that grew below the viewport by changing the height of the timeline to maintain what's currently visible in the viewport without adjusting the scrollTop and hence without jumping. + +For anything above the viewport growing or shrinking, we don't need to do anything as the timeline is bottom-aligned. We do need to update the height manually to keep all content visible as more is loaded. To maintain scroll position after the portion above the viewport changes height, we need to set the scrollTop, as we cannot balance it out with more height changes. We do this 100ms after the user has stopped scrolling, so setting scrollTop has not nasty side-effects. + +As of https://github.com/matrix-org/matrix-react-sdk/pull/4166, we are scrolling to compensate for height changes by calling `scrollBy(0, x)` rather than reading and than setting `scrollTop`, as reading `scrollTop` can (again, especially on macOS) easily return values that are out of sync with what is on the screen, probably because scrolling can be done [off the main thread](https://wiki.mozilla.org/Platform/GFX/APZ) in some circumstances. This seems to further prevent jumps. + +### How does it work? + +`componentDidUpdate` is called when a tile in the timeline is updated (as we rerender the whole timeline) or tiles are added or removed (see Updates section before). From here, `checkScroll` is called, which calls `_restoreSavedScrollState`. Now, we increase the timeline height if something below the viewport grew by adjusting `this._bottomGrowth`. `bottomGrowth` is the height added to the timeline (on top of the height from the number of pages calculated at the last `_updateHeight` run) to compensate for growth below the viewport. This is cleared during the next run of `_updateHeight`. Remember that the tiles in the timeline are aligned to the bottom. + +From `_restoreSavedScrollState` we also call `_updateHeight` which waits until the user stops scrolling for 100ms and then recalculates the amount of pages of 400px the timeline should be sized to, to be able to show all of its (newly added) content. We have to adjust the scroll offset (which is why we wait until scrolling has stopped) now because the space above the viewport has likely changed. From 191dcaab82b41d5659dfa3ba74f74205fec37fc9 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Tue, 3 Mar 2020 17:41:28 +0000 Subject: [PATCH 36/69] Explain why not busy is ignored --- src/components/structures/InteractiveAuth.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js index 9521dd76ec..f4adb5751f 100644 --- a/src/components/structures/InteractiveAuth.js +++ b/src/components/structures/InteractiveAuth.js @@ -186,6 +186,12 @@ export default createReactClass({ stageErrorText: null, }); } + // The JS SDK eagerly reports itself as "not busy" right after any + // immediate work has completed, but that's not really what we want at + // the UI layer, so we ignore this signal and show a spinner until + // there's a new screen to show the user. This is implemented by setting + // `busy: false` in `_authStateUpdated`. + // See also https://github.com/vector-im/riot-web/issues/12546 }, _setFocus: function() { From 846170b3718a8748d57158b0b8842fc1a8b53493 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 13:33:07 -0700 Subject: [PATCH 37/69] Revert "Fix downloading files in electron not being sent into browser" This reverts commit d89b8b51484c68c6fe0b1325b5d59ee809cc2196. --- src/components/views/elements/ImageView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/ImageView.js b/src/components/views/elements/ImageView.js index f75b735043..e675e6b73f 100644 --- a/src/components/views/elements/ImageView.js +++ b/src/components/views/elements/ImageView.js @@ -216,7 +216,7 @@ export default class ImageView extends React.Component { { this.getName() } { eventMeta } - +
{ _t('Download this file') }
{ sizeRes } From 8234b4d656c9afce2c3211bddfbbd8ea9d6a3318 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:11:29 -0700 Subject: [PATCH 38/69] Wire up 'create account' to the SSO button when SSO is used For https://github.com/vector-im/riot-web/issues/12362 --- src/components/structures/auth/Login.js | 31 ++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 24e4726416..0e3792baf5 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -120,8 +120,8 @@ export default createReactClass({ 'm.login.password': this._renderPasswordStep, // CAS and SSO are the same thing, modulo the url we link to - 'm.login.cas': () => this._renderSsoStep(this._loginLogic.getSsoLoginUrl("cas")), - 'm.login.sso': () => this._renderSsoStep(this._loginLogic.getSsoLoginUrl("sso")), + 'm.login.cas': () => this._renderSsoStep(this._getSsoUrl('m.login.cas')), + 'm.login.sso': () => this._renderSsoStep(this._getSsoUrl('m.login.sso')), }; this._initLoginLogic(); @@ -150,6 +150,18 @@ export default createReactClass({ return this.state.busy || this.props.busy; }, + _isSsoStep: function() { + return this._getCurrentFlowStep() === 'm.login.sso' || this._getCurrentFlowStep() === 'm.login.cas'; + }, + + _getSsoUrl: function(kind) { + if (kind === 'm.login.cas') { + return this._loginLogic.getSsoLoginUrl("cas") + } else { + return this._loginLogic.getSsoLoginUrl("sso"); + } + }, + onPasswordLogin: async function(username, phoneCountry, phoneNumber, password) { if (!this.state.serverIsAlive) { this.setState({busy: true}); @@ -344,6 +356,19 @@ export default createReactClass({ this.props.onRegisterClick(); }, + onTryRegisterClick: function(ev) { + if (this._isSsoStep()) { + // If we're showing SSO it means that registration is also probably disabled, + // so intercept the click and instead pretend the user clicked 'Sign in with SSO'. + ev.preventDefault(); + ev.stopPropagation(); + window.location = this._getSsoUrl(this._getCurrentFlowStep()); + } else { + // Don't intercept - just go through to the register page + this.onRegisterClick(ev); + } + }, + async onServerDetailsNextPhaseClick() { this.setState({ phase: PHASE_LOGIN, @@ -654,7 +679,7 @@ export default createReactClass({ { serverDeadSection } { this.renderServerComponent() } { this.renderLoginComponentForStep() } -
+ { _t('Create account') } From 04c54dc5a0444266707a1883ca5722734337be84 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:19:36 -0700 Subject: [PATCH 39/69] Redirect registration requests to Login when the server supports SSO For https://github.com/vector-im/riot-web/issues/12362 --- .../structures/auth/Registration.js | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index 8593a4b1e2..7c6a3ea56f 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -31,6 +31,8 @@ import classNames from "classnames"; import * as Lifecycle from '../../../Lifecycle'; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import AuthPage from "../../views/auth/AuthPage"; +import Login from "../../../Login"; +import dis from "../../../dispatcher"; // Phases // Show controls to configure server details @@ -232,6 +234,13 @@ export default createReactClass({ serverRequiresIdServer, busy: false, }); + const showGenericError = (e) => { + this.setState({ + errorText: _t("Unable to query for supported registration methods."), + // add empty flows array to get rid of spinner + flows: [], + }); + }; try { await this._makeRegisterRequest({}); // This should never succeed since we specified an empty @@ -243,18 +252,32 @@ export default createReactClass({ flows: e.data.flows, }); } else if (e.httpStatus === 403 && e.errcode === "M_UNKNOWN") { - this.setState({ - errorText: _t("Registration has been disabled on this homeserver."), - // add empty flows array to get rid of spinner - flows: [], - }); + // At this point registration is pretty much disabled, but before we do that let's + // quickly check to see if the server supports SSO instead. If it does, we'll send + // the user off to the login page to figure their account out. + try { + const loginLogic = new Login(hsUrl, isUrl, null, { + defaultDeviceDisplayName: "riot login check", // We shouldn't ever be used + }); + const flows = await loginLogic.getFlows(); + const hasSsoFlow = flows.find(f => f.type === 'm.login.sso' || f.type === 'm.login.cas'); + if (hasSsoFlow) { + // Redirect to login page - server probably expects SSO only + dis.dispatch({action: 'start_login'}); + } else { + this.setState({ + errorText: _t("Registration has been disabled on this homeserver."), + // add empty flows array to get rid of spinner + flows: [], + }); + } + } catch (e) { + console.error("Failed to get login flows to check for SSO support", e); + showGenericError(e); + } } else { console.log("Unable to query for supported registration methods.", e); - this.setState({ - errorText: _t("Unable to query for supported registration methods."), - // add empty flows array to get rid of spinner - flows: [], - }); + showGenericError(e); } } }, From a12786c1711d2e61671b2b5b1769fd5a35530307 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:23:12 -0700 Subject: [PATCH 40/69] i18n --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 79b045dd34..67a43ae14f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2004,8 +2004,8 @@ "Failed to fetch avatar URL": "Failed to fetch avatar URL", "Set a display name:": "Set a display name:", "Upload an avatar:": "Upload an avatar:", - "Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.", "Unable to query for supported registration methods.": "Unable to query for supported registration methods.", + "Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.", "This server does not support authentication with a phone number.": "This server does not support authentication with a phone number.", "Your new account (%(newAccountId)s) is registered, but you're already logged into a different account (%(loggedInUserId)s).": "Your new account (%(newAccountId)s) is registered, but you're already logged into a different account (%(loggedInUserId)s).", "Continue with previous account": "Continue with previous account", From bcfe1fcac521378ecfaabd1273259eaca83f5f3b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:23:53 -0700 Subject: [PATCH 41/69] Wire up 'create account' to the SSO button when SSO is used For https://github.com/vector-im/riot-web/issues/12362 --- src/components/structures/auth/Login.js | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index b918334d79..873c9e0c35 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -151,6 +151,18 @@ export default createReactClass({ return this.state.busy || this.props.busy; }, + _isSsoStep: function() { + return this._getCurrentFlowStep() === 'm.login.sso' || this._getCurrentFlowStep() === 'm.login.cas'; + }, + + _getSsoUrl: function(kind) { + if (kind === 'm.login.cas') { + return this._loginLogic.getSsoLoginUrl("cas") + } else { + return this._loginLogic.getSsoLoginUrl("sso"); + } + }, + onPasswordLogin: async function(username, phoneCountry, phoneNumber, password) { if (!this.state.serverIsAlive) { this.setState({busy: true}); @@ -339,6 +351,19 @@ export default createReactClass({ this.props.onRegisterClick(); }, + onTryRegisterClick: function(ev) { + if (this._isSsoStep()) { + // If we're showing SSO it means that registration is also probably disabled, + // so intercept the click and instead pretend the user clicked 'Sign in with SSO'. + ev.preventDefault(); + ev.stopPropagation(); + window.location = this._getSsoUrl(this._getCurrentFlowStep()); + } else { + // Don't intercept - just go through to the register page + this.onRegisterClick(ev); + } + }, + async onServerDetailsNextPhaseClick() { this.setState({ phase: PHASE_LOGIN, @@ -652,7 +677,7 @@ export default createReactClass({ { serverDeadSection } { this.renderServerComponent() } { this.renderLoginComponentForStep() } - + { _t('Create account') } From e265c92b6e87a434a0633e7ca62624fd0faa5fb2 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:19:36 -0700 Subject: [PATCH 42/69] Redirect registration requests to Login when the server supports SSO For https://github.com/vector-im/riot-web/issues/12362 --- .../structures/auth/Registration.js | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/components/structures/auth/Registration.js b/src/components/structures/auth/Registration.js index 8593a4b1e2..7c6a3ea56f 100644 --- a/src/components/structures/auth/Registration.js +++ b/src/components/structures/auth/Registration.js @@ -31,6 +31,8 @@ import classNames from "classnames"; import * as Lifecycle from '../../../Lifecycle'; import {MatrixClientPeg} from "../../../MatrixClientPeg"; import AuthPage from "../../views/auth/AuthPage"; +import Login from "../../../Login"; +import dis from "../../../dispatcher"; // Phases // Show controls to configure server details @@ -232,6 +234,13 @@ export default createReactClass({ serverRequiresIdServer, busy: false, }); + const showGenericError = (e) => { + this.setState({ + errorText: _t("Unable to query for supported registration methods."), + // add empty flows array to get rid of spinner + flows: [], + }); + }; try { await this._makeRegisterRequest({}); // This should never succeed since we specified an empty @@ -243,18 +252,32 @@ export default createReactClass({ flows: e.data.flows, }); } else if (e.httpStatus === 403 && e.errcode === "M_UNKNOWN") { - this.setState({ - errorText: _t("Registration has been disabled on this homeserver."), - // add empty flows array to get rid of spinner - flows: [], - }); + // At this point registration is pretty much disabled, but before we do that let's + // quickly check to see if the server supports SSO instead. If it does, we'll send + // the user off to the login page to figure their account out. + try { + const loginLogic = new Login(hsUrl, isUrl, null, { + defaultDeviceDisplayName: "riot login check", // We shouldn't ever be used + }); + const flows = await loginLogic.getFlows(); + const hasSsoFlow = flows.find(f => f.type === 'm.login.sso' || f.type === 'm.login.cas'); + if (hasSsoFlow) { + // Redirect to login page - server probably expects SSO only + dis.dispatch({action: 'start_login'}); + } else { + this.setState({ + errorText: _t("Registration has been disabled on this homeserver."), + // add empty flows array to get rid of spinner + flows: [], + }); + } + } catch (e) { + console.error("Failed to get login flows to check for SSO support", e); + showGenericError(e); + } } else { console.log("Unable to query for supported registration methods.", e); - this.setState({ - errorText: _t("Unable to query for supported registration methods."), - // add empty flows array to get rid of spinner - flows: [], - }); + showGenericError(e); } } }, From e83a4ddbe5a0b23a5f0dbd10ff8ae72d2d18059c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:23:12 -0700 Subject: [PATCH 43/69] i18n --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 4ec9c1e281..2b1d44bbcd 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2007,8 +2007,8 @@ "Failed to fetch avatar URL": "Failed to fetch avatar URL", "Set a display name:": "Set a display name:", "Upload an avatar:": "Upload an avatar:", - "Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.", "Unable to query for supported registration methods.": "Unable to query for supported registration methods.", + "Registration has been disabled on this homeserver.": "Registration has been disabled on this homeserver.", "This server does not support authentication with a phone number.": "This server does not support authentication with a phone number.", "Your new account (%(newAccountId)s) is registered, but you're already logged into a different account (%(loggedInUserId)s).": "Your new account (%(newAccountId)s) is registered, but you're already logged into a different account (%(loggedInUserId)s).", "Continue with previous account": "Continue with previous account", From 3cff6d72394efe8c942841c49c0473459480f6bb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:26:20 -0700 Subject: [PATCH 44/69] Appease the linter --- src/components/structures/auth/Login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 873c9e0c35..cf80c99535 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -157,7 +157,7 @@ export default createReactClass({ _getSsoUrl: function(kind) { if (kind === 'm.login.cas') { - return this._loginLogic.getSsoLoginUrl("cas") + return this._loginLogic.getSsoLoginUrl("cas"); } else { return this._loginLogic.getSsoLoginUrl("sso"); } From 93c696f15e61ff75bceafaaf9cd841db45020961 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 3 Mar 2020 23:26:20 -0700 Subject: [PATCH 45/69] Appease the linter --- src/components/structures/auth/Login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 0e3792baf5..e04d311b62 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -156,7 +156,7 @@ export default createReactClass({ _getSsoUrl: function(kind) { if (kind === 'm.login.cas') { - return this._loginLogic.getSsoLoginUrl("cas") + return this._loginLogic.getSsoLoginUrl("cas"); } else { return this._loginLogic.getSsoLoginUrl("sso"); } From 91aa8d4a3afa1bb538b00891da8b4a2c9f35bb47 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 3 Mar 2020 15:42:22 +0100 Subject: [PATCH 46/69] use relative scrolling to compensate when changing height --- src/components/structures/ScrollPanel.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 5121dd3f9d..72d5330451 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -705,17 +705,15 @@ export default createReactClass({ // the currently filled piece of the timeline if (trackedNode) { const oldTop = trackedNode.offsetTop; - // changing the height might change the scrollTop - // if the new height is smaller than the scrollTop. - // We calculate the diff that needs to be applied - // ourselves, so be sure to measure the - // scrollTop before changing the height. - const preexistingScrollTop = sn.scrollTop; itemlist.style.height = `${newHeight}px`; const newTop = trackedNode.offsetTop; const topDiff = newTop - oldTop; - sn.scrollTop = preexistingScrollTop + topDiff; - debuglog("updateHeight to", {newHeight, topDiff, preexistingScrollTop}); + // important to scroll by a relative amount as + // reading scrollTop and then setting it might + // yield out of date values and cause a jump + // when setting it + sn.scrollBy(0, topDiff); + debuglog("updateHeight to", {newHeight, topDiff}); } } }, From 462c3411b296cbde217247ac5914c76528e24163 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 3 Mar 2020 15:42:44 +0100 Subject: [PATCH 47/69] add comment how offset from bottom is calculated --- src/components/structures/ScrollPanel.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 72d5330451..548dd70748 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -765,6 +765,7 @@ export default createReactClass({ }, _topFromBottom(node) { + // current capped height - distance from top = distance from bottom of container to top of tracked element return this._itemlist.current.clientHeight - node.offsetTop; }, From 070b43070205914430267e87aeab91aaf702d6db Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 3 Mar 2020 15:44:59 +0100 Subject: [PATCH 48/69] also use relative scrolling when eh ... doing relative scrolling --- src/components/structures/ScrollPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 548dd70748..b81b3ebede 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -523,7 +523,7 @@ export default createReactClass({ scrollRelative: function(mult) { const scrollNode = this._getScrollNode(); const delta = mult * scrollNode.clientHeight * 0.5; - scrollNode.scrollTop = scrollNode.scrollTop + delta; + scrollNode.scrollBy(0, delta); this._saveScrollState(); }, From fa79bc93cee5fea5a0cbe2a58b3c64c0c762d1fd Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 2 Mar 2020 17:48:38 +0000 Subject: [PATCH 49/69] Use bash for release script This fixes this repo to use bash for this script, matching the other repos. --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 3c28084bb7..1b99e870ac 100755 --- a/release.sh +++ b/release.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Script to perform a release of matrix-react-sdk. # From cdcf042f6b5ebb5c28614c0d8cf102b1fe0bf5bf Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 4 Mar 2020 11:30:35 +0000 Subject: [PATCH 50/69] Prepare changelog for v2.2.1 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88d1895691..8d436ca690 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +Changes in [2.2.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.1) (2020-03-04) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.0...v2.2.1) + + * Adjust scroll offset with relative scrolling + [\#4171](https://github.com/matrix-org/matrix-react-sdk/pull/4171) + * Disable registration flows on SSO servers + [\#4169](https://github.com/matrix-org/matrix-react-sdk/pull/4169) + Changes in [2.2.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v2.2.0) (2020-03-02) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v2.2.0-rc.1...v2.2.0) From ce879b95cfe27dc9282fc202ffb5eab091550d22 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 4 Mar 2020 11:30:35 +0000 Subject: [PATCH 51/69] v2.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5bd9ec19f..a450cb60f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "2.2.0", + "version": "2.2.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From b7d9f24625621f8e232371ae2b1990f59aa6c586 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 4 Mar 2020 11:53:01 +0000 Subject: [PATCH 52/69] Log packages when checking version --- release.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/release.sh b/release.sh index 1b99e870ac..23b8822041 100755 --- a/release.sh +++ b/release.sh @@ -11,6 +11,7 @@ cd `dirname $0` for i in matrix-js-sdk do + echo "Checking version of $i..." depver=`cat package.json | jq -r .dependencies[\"$i\"]` latestver=`yarn info -s $i dist-tags.next` if [ "$depver" != "$latestver" ] From 845656064e802054b3857c2a240aaaf88f94f740 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 4 Mar 2020 11:58:00 +0000 Subject: [PATCH 53/69] Reset matrix-js-sdk back to develop branch --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 87aeccd140..20580f26f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5655,7 +5655,7 @@ mathml-tag-names@^2.0.1: "matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "5.1.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/da96765020b632deb5b433077827a4f4a64e16e9" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/bc53f8fdec7222b6ca44a63cafbc7ae8c4cc396f" dependencies: "@babel/runtime" "^7.8.3" another-json "^0.2.0" From 7ad8eeb906ee53184d5c9b1a96642a09d47a2ba3 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 4 Mar 2020 14:35:01 +0000 Subject: [PATCH 54/69] Fix composer touch bar flickering on keypress in Chrome This changes our selection state handling to leave things alone if the browser's state already matches what we want. This avoids strange side effects like the touch bar flickering on each key press in Chrome. Fixes https://github.com/vector-im/riot-web/issues/9299 --- src/editor/caret.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/editor/caret.js b/src/editor/caret.js index ed4f1b2a2e..8c0090a6f1 100644 --- a/src/editor/caret.js +++ b/src/editor/caret.js @@ -38,12 +38,27 @@ function setDocumentRangeSelection(editor, model, range) { } export function setCaretPosition(editor, model, caretPosition) { - const sel = document.getSelection(); - sel.removeAllRanges(); const range = document.createRange(); const {node, offset} = getNodeAndOffsetForPosition(editor, model, caretPosition); range.setStart(node, offset); range.collapse(true); + + const sel = document.getSelection(); + if (sel.rangeCount === 1) { + const existingRange = sel.getRangeAt(0); + if ( + existingRange.startContainer === range.startContainer && + existingRange.startOffset === range.startOffset && + existingRange.collapsed === range.collapsed + ) { + // If the selection matches, it's important to leave it alone. + // Recreating the selection state in at least Chrome can cause + // strange side effects, like touch bar flickering on every key. + // See https://github.com/vector-im/riot-web/issues/9299 + return; + } + } + sel.removeAllRanges(); sel.addRange(range); } From 29af8add5d5fbfa607be40e74944b64cc4e46f35 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 4 Mar 2020 16:10:06 +0100 Subject: [PATCH 55/69] only show verify button if user has uploaded cross-signing keys --- src/components/views/right_panel/UserInfo.js | 44 ++++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index 44770d9ccc..f5b6548a83 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -136,6 +136,27 @@ function useIsEncrypted(cli, room) { return isEncrypted; } +function useHasCrossSigningKeys(cli, member, canVerify) { + const [waitingForCrossSigningKeys, setWaitingForCrossSigningKeys] = useState(false); + const [hasCrossSigningKeys, setHasCrossSigningKeys] = useState(false); + useEffect(() => { + if (canVerify) { + setWaitingForCrossSigningKeys(true); + (async () => { + try { + await cli.downloadKeys([member.userId]); + const xsi = cli.getStoredCrossSigningForUser(member.userId); + const key = xsi && xsi.getId(); + setHasCrossSigningKeys(!!key); + } finally { + setWaitingForCrossSigningKeys(false); + } + })(); + } + }, [canVerify, cli, member]); + return {waitingForCrossSigningKeys, hasCrossSigningKeys}; +} + async function verifyDevice(userId, device) { const cli = MatrixClientPeg.get(); const member = cli.getUser(userId); @@ -1324,20 +1345,27 @@ const BasicUserInfo = ({room, member, groupId, devices, isRoomEncrypted}) => { let verifyButton; const homeserverSupportsCrossSigning = useHomeserverSupportsCrossSigning(cli); - if ( - SettingsStore.isFeatureEnabled("feature_cross_signing") && - homeserverSupportsCrossSigning - ) { - const userTrust = cli.checkUserTrust(member.userId); - const userVerified = userTrust.isCrossSigningVerified(); - const isMe = member.userId === cli.getUserId(); - if (isRoomEncrypted && !userVerified && !isMe) { + const userTrust = cli.checkUserTrust(member.userId); + const userVerified = userTrust.isCrossSigningVerified(); + const isMe = member.userId === cli.getUserId(); + const canVerify = SettingsStore.isFeatureEnabled("feature_cross_signing") && + homeserverSupportsCrossSigning && + isRoomEncrypted && !userVerified && !isMe; + + const {hasCrossSigningKeys, waitingForCrossSigningKeys} = + useHasCrossSigningKeys(cli, member, canVerify); + + if (canVerify) { + if (hasCrossSigningKeys) { verifyButton = ( verifyUser(member)}> {_t("Verify")} ); + } else if (waitingForCrossSigningKeys) { + const Spinner = sdk.getComponent("elements.Spinner"); + verifyButton = ; } } From afc7273d1002fb69380299b392bd474cc2460644 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 4 Mar 2020 16:58:04 +0100 Subject: [PATCH 56/69] use pendingUpdateCount rather, so we don't show multiple spinners --- src/components/views/right_panel/UserInfo.js | 63 ++++++++++---------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index f5b6548a83..07b2248644 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -17,7 +17,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useCallback, useMemo, useState, useEffect, useContext} from 'react'; +import React, {useCallback, useMemo, useState, useEffect, useContext, useRef} from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import {Group, RoomMember, User} from 'matrix-js-sdk'; @@ -136,25 +136,28 @@ function useIsEncrypted(cli, room) { return isEncrypted; } -function useHasCrossSigningKeys(cli, member, canVerify) { - const [waitingForCrossSigningKeys, setWaitingForCrossSigningKeys] = useState(false); - const [hasCrossSigningKeys, setHasCrossSigningKeys] = useState(false); +function useHasCrossSigningKeys(cli, member, canVerify, setUpdating) { + // use a ref to setUpdating because we don't want to rerun + // the useAsyncMemo hook when it changes. + const updatingRef = useRef(); useEffect(() => { - if (canVerify) { - setWaitingForCrossSigningKeys(true); - (async () => { - try { - await cli.downloadKeys([member.userId]); - const xsi = cli.getStoredCrossSigningForUser(member.userId); - const key = xsi && xsi.getId(); - setHasCrossSigningKeys(!!key); - } finally { - setWaitingForCrossSigningKeys(false); - } - })(); + updatingRef.current = setUpdating; + }, [setUpdating]); + + return useAsyncMemo(async () => { + if (!canVerify) { + return false; } - }, [canVerify, cli, member]); - return {waitingForCrossSigningKeys, hasCrossSigningKeys}; + updatingRef.current(true); + try { + await cli.downloadKeys([member.userId]); + const xsi = cli.getStoredCrossSigningForUser(member.userId); + const key = xsi && xsi.getId(); + return !!key; + } finally { + updatingRef.current(false); + } + }, [cli, member, canVerify], false); } async function verifyDevice(userId, device) { @@ -1353,20 +1356,18 @@ const BasicUserInfo = ({room, member, groupId, devices, isRoomEncrypted}) => { homeserverSupportsCrossSigning && isRoomEncrypted && !userVerified && !isMe; - const {hasCrossSigningKeys, waitingForCrossSigningKeys} = - useHasCrossSigningKeys(cli, member, canVerify); + const setUpdating = useCallback((updating) => { + setPendingUpdateCount(pendingUpdateCount + (updating ? 1 : -1)); + }, [setPendingUpdateCount, pendingUpdateCount]); + const hasCrossSigningKeys = + useHasCrossSigningKeys(cli, member, canVerify, setUpdating ); - if (canVerify) { - if (hasCrossSigningKeys) { - verifyButton = ( - verifyUser(member)}> - {_t("Verify")} - - ); - } else if (waitingForCrossSigningKeys) { - const Spinner = sdk.getComponent("elements.Spinner"); - verifyButton = ; - } + if (canVerify && hasCrossSigningKeys) { + verifyButton = ( + verifyUser(member)}> + {_t("Verify")} + + ); } let devicesSection; From 8a964dbff0c789dc511bf8c445752ea632c1520e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 4 Mar 2020 17:19:06 +0100 Subject: [PATCH 57/69] avoid ref by getting count in setter callback --- src/components/views/right_panel/UserInfo.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index 07b2248644..e844018527 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -17,7 +17,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useCallback, useMemo, useState, useEffect, useContext, useRef} from 'react'; +import React, {useCallback, useMemo, useState, useEffect, useContext} from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import {Group, RoomMember, User} from 'matrix-js-sdk'; @@ -137,25 +137,18 @@ function useIsEncrypted(cli, room) { } function useHasCrossSigningKeys(cli, member, canVerify, setUpdating) { - // use a ref to setUpdating because we don't want to rerun - // the useAsyncMemo hook when it changes. - const updatingRef = useRef(); - useEffect(() => { - updatingRef.current = setUpdating; - }, [setUpdating]); - return useAsyncMemo(async () => { if (!canVerify) { return false; } - updatingRef.current(true); + setUpdating(true); try { await cli.downloadKeys([member.userId]); const xsi = cli.getStoredCrossSigningForUser(member.userId); const key = xsi && xsi.getId(); return !!key; } finally { - updatingRef.current(false); + setUpdating(false); } }, [cli, member, canVerify], false); } @@ -1356,9 +1349,9 @@ const BasicUserInfo = ({room, member, groupId, devices, isRoomEncrypted}) => { homeserverSupportsCrossSigning && isRoomEncrypted && !userVerified && !isMe; - const setUpdating = useCallback((updating) => { - setPendingUpdateCount(pendingUpdateCount + (updating ? 1 : -1)); - }, [setPendingUpdateCount, pendingUpdateCount]); + const setUpdating = (updating) => { + setPendingUpdateCount(count => count + (updating ? 1 : -1)); + }; const hasCrossSigningKeys = useHasCrossSigningKeys(cli, member, canVerify, setUpdating ); From 3842bce74dc25f242b0cf710efd6d5d6d61ec3f9 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 11:41:16 -0700 Subject: [PATCH 58/69] Fix SSO for new approach --- src/components/structures/auth/Login.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index cf80c99535..6cce8f4444 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -28,6 +28,7 @@ import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDisc import classNames from "classnames"; import AuthPage from "../../views/auth/AuthPage"; import SSOButton from "../../views/elements/SSOButton"; +import PlatformPeg from '../../../PlatformPeg'; // For validating phone numbers without country codes const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/; @@ -155,14 +156,6 @@ export default createReactClass({ return this._getCurrentFlowStep() === 'm.login.sso' || this._getCurrentFlowStep() === 'm.login.cas'; }, - _getSsoUrl: function(kind) { - if (kind === 'm.login.cas') { - return this._loginLogic.getSsoLoginUrl("cas"); - } else { - return this._loginLogic.getSsoLoginUrl("sso"); - } - }, - onPasswordLogin: async function(username, phoneCountry, phoneNumber, password) { if (!this.state.serverIsAlive) { this.setState({busy: true}); @@ -357,7 +350,8 @@ export default createReactClass({ // so intercept the click and instead pretend the user clicked 'Sign in with SSO'. ev.preventDefault(); ev.stopPropagation(); - window.location = this._getSsoUrl(this._getCurrentFlowStep()); + const ssoKind = this._getCurrentFlowStep() === 'm.login.sso' ? 'sso' : 'cas'; + PlatformPeg.get().startSingleSignOn(this._loginLogic.createTemporaryClient(), ssoKind); } else { // Don't intercept - just go through to the register page this.onRegisterClick(ev); From b06a82ee80b2aa656f1a0114c7fa2fab7fccc8dd Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 11:44:12 -0700 Subject: [PATCH 59/69] Use textForEvent to determine if an event is worth rendering --- src/components/structures/MessagePanel.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 0029090a94..a2ac93d282 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -28,6 +28,7 @@ import {MatrixClientPeg} from '../../MatrixClientPeg'; import SettingsStore from '../../settings/SettingsStore'; import {_t} from "../../languageHandler"; import {haveTileForEvent} from "../views/rooms/EventTile"; +import {textForEvent} from "../../TextForEvent"; const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes const continuedTypes = ['m.sticker', 'm.room.message']; @@ -963,15 +964,11 @@ class MemberGrouper { add(ev) { if (ev.getType() === 'm.room.member') { - // We'll just double check that it's worth our time to do so... - if (ev.getPrevContent()) { - const membershipChange = ev.getPrevContent()['membership'] !== ev.getContent()['membership']; - const displayNameChange = ev.getPrevContent()['displayname'] !== ev.getContent()['displayname']; - const avatarChange = ev.getPrevContent()['avatar_url'] !== ev.getContent()['avatar_url']; - if (!membershipChange && !displayNameChange && !avatarChange) { - return; // Not a substantial change - quietly ignore - } - } + // We'll just double check that it's worth our time to do so, through an + // ugly hack. If textForEvent returns something, we should group it for + // rendering but if it doesn't then we'll exclude it. + const renderText = textForEvent(ev); + if (!renderText || renderText.trim().length === 0) return; // quietly ignore } this.readMarker = this.readMarker || this.panel._readMarkerForEvent(ev.getId()); this.events.push(ev); From 80b44f0292ff36b87389c7b72a6b498de8c9b5bc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 12:05:47 -0700 Subject: [PATCH 60/69] Always calculate the category of a room All the update triggers for the RoomListStore go through the `setRoomCategory` function, so by returning early we're not actually calculating where a room should be in the list. --- src/stores/RoomListStore.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index 561d865b66..aec307d28e 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -479,12 +479,6 @@ class RoomListStore extends Store { _setRoomCategory(room, category) { if (!room) return; // This should only happen in tests - if (!this._state.orderImportantFirst) { - // XXX bail here early to avoid https://github.com/vector-im/riot-web/issues/9216 - // this may mean that category updates are missed whilst not ordering by importance first - return; - } - const listsClone = {}; // Micro optimization: Support lazily loading the last timestamp in a room From 8e3fea9d0fb1a6b097754b656c2c5e8d1dcdb7ae Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 12:09:05 -0700 Subject: [PATCH 61/69] Use an algorithmic comparator for room list ops Not all algorithms are timestamp based. --- src/stores/RoomListStore.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/stores/RoomListStore.js b/src/stores/RoomListStore.js index aec307d28e..89edc9a8ef 100644 --- a/src/stores/RoomListStore.js +++ b/src/stores/RoomListStore.js @@ -372,6 +372,14 @@ class RoomListStore extends Store { _slotRoomIntoList(room, category, tag, existingEntries, newList, lastTimestampFn) { const targetCategoryIndex = CATEGORY_ORDER.indexOf(category); + let categoryComparator = (a, b) => lastTimestampFn(a.room) >= lastTimestampFn(b.room); + const sortAlgorithm = getListAlgorithm(tag, this._state.algorithm); + if (sortAlgorithm === ALGO_RECENT) { + categoryComparator = (a, b) => this._recentsComparator(a, b, lastTimestampFn); + } else if (sortAlgorithm === ALGO_ALPHABETIC) { + categoryComparator = (a, b) => this._lexicographicalComparator(a, b); + } + // The slotting algorithm works by trying to position the room in the most relevant // category of the list (red > grey > etc). To accomplish this, we need to consider // a couple cases: the category existing in the list but having other rooms in it and @@ -449,7 +457,7 @@ class RoomListStore extends Store { // based on most recent timestamp. const changedBoundary = entryCategoryIndex > targetCategoryIndex; const currentCategory = entryCategoryIndex === targetCategoryIndex; - if (changedBoundary || (currentCategory && lastTimestampFn(room) >= lastTimestampFn(entry.room))) { + if (changedBoundary || (currentCategory && categoryComparator({room}, entry) <= 0)) { if (changedBoundary) { // If we changed a boundary, then we've gone too far - go to the top of the last // section instead. From 2204785026ceaf504ef29c4f0fe0f4c11979aa90 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 12:26:08 -0700 Subject: [PATCH 62/69] Simplify SSO step checking --- src/components/structures/auth/Login.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 6cce8f4444..bfabc34a62 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -152,10 +152,6 @@ export default createReactClass({ return this.state.busy || this.props.busy; }, - _isSsoStep: function() { - return this._getCurrentFlowStep() === 'm.login.sso' || this._getCurrentFlowStep() === 'm.login.cas'; - }, - onPasswordLogin: async function(username, phoneCountry, phoneNumber, password) { if (!this.state.serverIsAlive) { this.setState({busy: true}); @@ -345,12 +341,13 @@ export default createReactClass({ }, onTryRegisterClick: function(ev) { - if (this._isSsoStep()) { + const step = this._getCurrentFlowStep(); + if (step === 'm.login.sso' || step === 'm.login.cas') { // If we're showing SSO it means that registration is also probably disabled, // so intercept the click and instead pretend the user clicked 'Sign in with SSO'. ev.preventDefault(); ev.stopPropagation(); - const ssoKind = this._getCurrentFlowStep() === 'm.login.sso' ? 'sso' : 'cas'; + const ssoKind = step === 'm.login.sso' ? 'sso' : 'cas'; PlatformPeg.get().startSingleSignOn(this._loginLogic.createTemporaryClient(), ssoKind); } else { // Don't intercept - just go through to the register page From d820356990fc836bcdbfb65bc33d203f94f09e3a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 13:56:58 -0700 Subject: [PATCH 63/69] Convert alias links in room header topics to local permalinks Fixes https://github.com/vector-im/riot-web/issues/12605 --- src/linkify-matrix.js | 4 ++-- src/utils/permalinks/Permalinks.js | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js index 8870b2d431..2d2b9c62a5 100644 --- a/src/linkify-matrix.js +++ b/src/linkify-matrix.js @@ -16,7 +16,7 @@ limitations under the License. */ import {baseUrl} from "./utils/permalinks/SpecPermalinkConstructor"; -import {tryTransformPermalinkToLocalHref} from "./utils/permalinks/Permalinks"; +import {tryTransformEntityToPermalink, tryTransformPermalinkToLocalHref} from "./utils/permalinks/Permalinks"; function matrixLinkify(linkify) { // Text tokens @@ -221,7 +221,7 @@ matrixLinkify.options = { case 'userid': case 'groupid': default: { - return tryTransformPermalinkToLocalHref(href); + return tryTransformEntityToPermalink(href); } } }, diff --git a/src/utils/permalinks/Permalinks.js b/src/utils/permalinks/Permalinks.js index 1174e59da6..466d1ed57d 100644 --- a/src/utils/permalinks/Permalinks.js +++ b/src/utils/permalinks/Permalinks.js @@ -290,6 +290,25 @@ export function isPermalinkHost(host: string): boolean { return getPermalinkConstructor().isPermalinkHost(host); } +/** + * Transforms an entity (permalink, room alias, user ID, etc) into a local URL + * if possible. If the given entity is not found to be valid enough to be converted + * then a null value will be returned. + * @param {string} entity The entity to transform. + * @returns {string|null} The transformed permalink or null if unable. + */ +export function tryTransformEntityToPermalink(entity: string): string { + if (!entity) return null; + + // Check to see if it is a bare entity for starters + if (entity[0] === '#' || entity[0] === '!') return makeRoomPermalink(entity); + if (entity[0] === '@') return makeUserPermalink(entity); + if (entity[0] === '+') return makeGroupPermalink(entity); + + // Then try and merge it into a permalink + return tryTransformPermalinkToLocalHref(entity); +} + /** * Transforms a permalink (or possible permalink) into a local URL if possible. If * the given permalink is found to not be a permalink, it'll be returned unaltered. From c6af591c6e2aa49a9fadd765316226688706210b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 14:14:03 -0700 Subject: [PATCH 64/69] Ensure linkified topics in the room directory also work We weren't passing the options object down to linkifyString. Fixes https://github.com/vector-im/riot-web/issues/12606 --- src/HtmlUtils.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 7dd68e5c61..a58ea25c8a 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -23,7 +23,6 @@ import ReplyThread from "./components/views/elements/ReplyThread"; import React from 'react'; import sanitizeHtml from 'sanitize-html'; -import highlight from 'highlight.js'; import * as linkify from 'linkifyjs'; import linkifyMatrix from './linkify-matrix'; import _linkifyElement from 'linkifyjs/element'; @@ -467,11 +466,12 @@ export function bodyToHtml(content, highlights, opts={}) { /** * Linkifies the given string. This is a wrapper around 'linkifyjs/string'. * - * @param {string} str - * @returns {string} + * @param {string} str string to linkify + * @param {object} [options] Options for linkifyString. Default: linkifyMatrix.options + * @returns {string} Linkified string */ -export function linkifyString(str) { - return _linkifyString(str); +export function linkifyString(str, options = linkifyMatrix.options) { + return _linkifyString(str, options); } /** @@ -489,10 +489,11 @@ export function linkifyElement(element, options = linkifyMatrix.options) { * Linkify the given string and sanitize the HTML afterwards. * * @param {string} dirtyHtml The HTML string to sanitize and linkify + * @param {object} [options] Options for linkifyString. Default: linkifyMatrix.options * @returns {string} */ -export function linkifyAndSanitizeHtml(dirtyHtml) { - return sanitizeHtml(linkifyString(dirtyHtml), sanitizeHtmlParams); +export function linkifyAndSanitizeHtml(dirtyHtml, options = linkifyMatrix.options) { + return sanitizeHtml(linkifyString(dirtyHtml, options), sanitizeHtmlParams); } /** From 4a976acb84ff828f2ff5745a26b6841093290f54 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 4 Mar 2020 14:18:56 -0700 Subject: [PATCH 65/69] Add a null check to getUniqueRoomsWithIndividuals Fixes https://github.com/vector-im/riot-web/issues/12611 --- src/utils/DMRoomMap.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/DMRoomMap.js b/src/utils/DMRoomMap.js index 43ef0035fc..6ce92a0458 100644 --- a/src/utils/DMRoomMap.js +++ b/src/utils/DMRoomMap.js @@ -168,6 +168,7 @@ export default class DMRoomMap { } getUniqueRoomsWithIndividuals(): {[userId: string]: Room} { + if (!this.roomToUser) return {}; // No rooms means no map. return Object.keys(this.roomToUser) .map(r => ({userId: this.getUserIdForRoomId(r), room: this.matrixClient.getRoom(r)})) .filter(r => r.userId && r.room && r.room.getInvitedAndJoinedMemberCount() === 2) From a5cd0a7d5f120696277974a4e3ba64e7ce4419b5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 5 Mar 2020 11:09:45 +0100 Subject: [PATCH 66/69] indent by 4 spaces --- src/components/views/right_panel/UserInfo.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index e844018527..b8ba6968a4 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -1346,8 +1346,8 @@ const BasicUserInfo = ({room, member, groupId, devices, isRoomEncrypted}) => { const userVerified = userTrust.isCrossSigningVerified(); const isMe = member.userId === cli.getUserId(); const canVerify = SettingsStore.isFeatureEnabled("feature_cross_signing") && - homeserverSupportsCrossSigning && - isRoomEncrypted && !userVerified && !isMe; + homeserverSupportsCrossSigning && + isRoomEncrypted && !userVerified && !isMe; const setUpdating = (updating) => { setPendingUpdateCount(count => count + (updating ? 1 : -1)); From a6882cece188c95b988c1d815771088e36b946bd Mon Sep 17 00:00:00 2001 From: Ben Parsons Date: Thu, 5 Mar 2020 14:10:44 +0000 Subject: [PATCH 67/69] increase margin between Settings sections --- res/css/views/settings/tabs/_SettingsTab.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/css/views/settings/tabs/_SettingsTab.scss b/res/css/views/settings/tabs/_SettingsTab.scss index 794c8106be..9727946893 100644 --- a/res/css/views/settings/tabs/_SettingsTab.scss +++ b/res/css/views/settings/tabs/_SettingsTab.scss @@ -45,6 +45,10 @@ limitations under the License. margin: 10px 100px 10px 0; // Align with the rest of the view } +.mx_SettingsTab_section { + margin-bottom: 24px; +} + .mx_SettingsTab_section .mx_SettingsFlag { margin-right: 100px; margin-bottom: 10px; From ce849672257e395ee0cd21a7e05db86fcebc6ea6 Mon Sep 17 00:00:00 2001 From: Ben Parsons Date: Thu, 5 Mar 2020 14:18:12 +0000 Subject: [PATCH 68/69] update Security Disclosure Policy link text --- src/components/views/settings/tabs/user/HelpUserSettingsTab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js index 84403fe76e..8e7983970a 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js @@ -226,7 +226,7 @@ export default class HelpUserSettingsTab extends React.Component {
{ - _t( "To submit a security-related bug report, please read the Matrix.org " + + _t( "To report a Matrix-related security issue, please read the Matrix.org " + "Security Disclosure Policy.", {}, { 'a': (sub) => From d28d330b330dce39857678f033315f3814eb9dc0 Mon Sep 17 00:00:00 2001 From: Ben Parsons Date: Thu, 5 Mar 2020 14:33:40 +0000 Subject: [PATCH 69/69] run yarn i18n --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c0470af357..d3dc1f0652 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -725,7 +725,7 @@ "If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.", "Submit debug logs": "Submit debug logs", "Clear cache and reload": "Clear cache and reload", - "To submit a security-related bug report, please read the Matrix.org Security Disclosure Policy.": "To submit a security-related bug report, please read the Matrix.org Security Disclosure Policy.", + "To report a Matrix-related security issue, please read the Matrix.org Security Disclosure Policy.": "To report a Matrix-related security issue, please read the Matrix.org Security Disclosure Policy.", "FAQ": "FAQ", "Versions": "Versions", "riot-web version:": "riot-web version:",