From 9e2cdecb9be6d42049fcc9e0ffe56398181513c7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 1 Sep 2019 18:04:24 -0600 Subject: [PATCH 01/36] Add a button to MemberInfo to deactivate a user Part of https://github.com/vector-im/riot-web/issues/4125 --- src/components/views/rooms/MemberInfo.js | 50 +++++++++++++++++++++--- src/i18n/strings/en_EN.json | 3 ++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 3c098b3d7a..8d9e5dfe39 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -45,6 +45,7 @@ import MultiInviter from "../../../utils/MultiInviter"; import SettingsStore from "../../../settings/SettingsStore"; import E2EIcon from "./E2EIcon"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; +import MatrixClientPeg from "../../../MatrixClientPeg"; module.exports = withMatrixClient(React.createClass({ displayName: 'MemberInfo', @@ -61,6 +62,7 @@ module.exports = withMatrixClient(React.createClass({ ban: false, mute: false, modifyLevel: false, + synapseDeactivate: false, }, muted: false, isTargetMod: false, @@ -211,8 +213,8 @@ module.exports = withMatrixClient(React.createClass({ } }, - _updateStateForNewMember: function(member) { - const newState = this._calculateOpsPermissions(member); + _updateStateForNewMember: async function(member) { + const newState = await this._calculateOpsPermissions(member); newState.devicesLoading = true; newState.devices = null; this.setState(newState); @@ -460,6 +462,25 @@ module.exports = withMatrixClient(React.createClass({ }); }, + onSynapseDeactivate: function() { + const QuestionDialog = sdk.getComponent('views.dialogs.QuestionDialog'); + Modal.createTrackedDialog('Synapse User Deactivation', '', QuestionDialog, { + title: _t("Deactivate user?"), + description: +
{ _t( + "Deactivating this user will log them out and prevent them from logging back in. Additionally, " + + "they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to " + + "deactivate this user?" + ) }
, + button: _t("Deactivate user"), + danger: true, + onFinished: (accepted) => { + if (!accepted) return; + this.context.matrixClient.deactivateSynapseUser(this.props.member.userId); + }, + }); + }, + _applyPowerChange: function(roomId, target, powerLevel, powerLevelEvent) { this.setState({ updating: this.state.updating + 1 }); this.props.matrixClient.setPowerLevel(roomId, target, parseInt(powerLevel), powerLevelEvent).then( @@ -544,7 +565,7 @@ module.exports = withMatrixClient(React.createClass({ }); }, - _calculateOpsPermissions: function(member) { + _calculateOpsPermissions: async function(member) { const defaultPerms = { can: {}, muted: false, @@ -560,7 +581,7 @@ module.exports = withMatrixClient(React.createClass({ const them = member; return { - can: this._calculateCanPermissions( + can: await this._calculateCanPermissions( me, them, powerLevels.getContent(), ), muted: this._isMuted(them, powerLevels.getContent()), @@ -568,7 +589,7 @@ module.exports = withMatrixClient(React.createClass({ }; }, - _calculateCanPermissions: function(me, them, powerLevels) { + _calculateCanPermissions: async function(me, them, powerLevels) { const isMe = me.userId === them.userId; const can = { kick: false, @@ -577,6 +598,10 @@ module.exports = withMatrixClient(React.createClass({ modifyLevel: false, modifyLevelMax: 0, }; + + // Calculate permissions for Synapse before doing the PL checks + can.synapseDeactivate = await this.context.matrixClient.isSynapseAdministrator(); + const canAffectUser = them.powerLevel < me.powerLevel || isMe; if (!canAffectUser) { //console.log("Cannot affect user: %s >= %s", them.powerLevel, me.powerLevel); @@ -782,6 +807,7 @@ module.exports = withMatrixClient(React.createClass({ let banButton; let muteButton; let giveModButton; + let synapseDeactivateButton; let spinner; if (this.props.member.userId !== this.props.matrixClient.credentials.userId) { @@ -886,8 +912,19 @@ module.exports = withMatrixClient(React.createClass({ ; } + // We don't need a perfect check here, just something to pass as "probably not our homeserver". If + // someone does figure out how to bypass this check the worst that happens is an error. + const sameHomeserver = this.props.member.userId.endsWith(`:${MatrixClientPeg.getHomeserverName()}`); + if (this.state.can.synapseDeactivate && sameHomeserver) { + synapseDeactivateButton = ( + + {_t("Deactivate user")} + + ); + } + let adminTools; - if (kickButton || banButton || muteButton || giveModButton) { + if (kickButton || banButton || muteButton || giveModButton || synapseDeactivateButton) { adminTools =

{ _t("Admin Tools") }

@@ -897,6 +934,7 @@ module.exports = withMatrixClient(React.createClass({ { kickButton } { banButton } { giveModButton } + { synapseDeactivateButton }
; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9ad20bf56c..12765de198 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -729,6 +729,9 @@ "Demote": "Demote", "Failed to mute user": "Failed to mute user", "Failed to toggle moderator status": "Failed to toggle moderator status", + "Deactivate user?": "Deactivate user?", + "Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?": "Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?", + "Deactivate user": "Deactivate user", "Failed to change power level": "Failed to change power level", "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.", "No devices with registered encryption keys": "No devices with registered encryption keys", From 4ffa8c7b4aa876cd8b438ab672b0751ad11ace76 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Sep 2019 10:53:55 +0200 Subject: [PATCH 02/36] add explore button next to filter field --- res/css/structures/_LeftPanel.scss | 41 +++++++++++ res/css/structures/_SearchBox.scss | 21 +++--- res/css/views/rooms/_RoomList.scss | 4 -- res/img/explore.svg | 97 ++++++++++++++++++++++++++ src/components/structures/LeftPanel.js | 15 +++- src/i18n/strings/en_EN.json | 1 + 6 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 res/img/explore.svg diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index a8d8669285..351e7e0a1b 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -125,3 +125,44 @@ limitations under the License. margin-top: 12px; } } + +.mx_LeftPanel_exploreAndFilterRow { + display: flex; + + .mx_SearchBox { + flex: 1 1 0; + min-width: 0; + } +} + +.mx_LeftPanel_explore { + flex: 0 0 40%; + overflow: hidden; + box-sizing: border-box; + + .mx_AccessibleButton { + font-size: 14px; + margin: 9px; + margin-right: 0; + padding: 9px; + padding-left: 42px; + font-weight: 600; + color: $notice-secondary-color; + position: relative; + border-radius: 4px; + + &::before { + cursor: pointer; + mask: url('$(res)/img/explore.svg'); + mask-repeat: no-repeat; + mask-position: center center; + content: ""; + left: 14px; + top: 10px; + width: 16px; + height: 16px; + background-color: $notice-secondary-color; + position: absolute; + } + } +} diff --git a/res/css/structures/_SearchBox.scss b/res/css/structures/_SearchBox.scss index 9434d93bd2..7d13405478 100644 --- a/res/css/structures/_SearchBox.scss +++ b/res/css/structures/_SearchBox.scss @@ -14,12 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_SearchBox_closeButton { - cursor: pointer; - background-image: url('$(res)/img/icons-close.svg'); - background-repeat: no-repeat; - width: 16px; - height: 16px; - background-position: center; - padding: 9px; +.mx_SearchBox { + flex: 1 1 0; + min-width: 0; + + .mx_SearchBox_closeButton { + cursor: pointer; + background-image: url('$(res)/img/icons-close.svg'); + background-repeat: no-repeat; + width: 16px; + height: 16px; + background-position: center; + padding: 9px; + } } diff --git a/res/css/views/rooms/_RoomList.scss b/res/css/views/rooms/_RoomList.scss index b51d720e4d..5ed22f997d 100644 --- a/res/css/views/rooms/_RoomList.scss +++ b/res/css/views/rooms/_RoomList.scss @@ -27,10 +27,6 @@ limitations under the License. position: relative; } -.mx_SearchBox { - flex: none; -} - /* hide resize handles next to collapsed / empty sublists */ .mx_RoomList .mx_RoomSubList:not(.mx_RoomSubList_nonEmpty) + .mx_ResizeHandle { display: none; diff --git a/res/img/explore.svg b/res/img/explore.svg new file mode 100644 index 0000000000..3956e912ac --- /dev/null +++ b/res/img/explore.svg @@ -0,0 +1,97 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 2581319d75..a15bf33645 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -218,6 +218,7 @@ const LeftPanel = React.createClass({ const TopLeftMenuButton = sdk.getComponent('structures.TopLeftMenuButton'); const SearchBox = sdk.getComponent('structures.SearchBox'); const CallPreview = sdk.getComponent('voip.CallPreview'); + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const tagPanelEnabled = SettingsStore.getValue("TagPanel.enableTagPanel"); let tagPanelContainer; @@ -241,6 +242,15 @@ const LeftPanel = React.createClass({ }, ); + let exploreButton; + if (!this.props.collapsed) { + exploreButton = ( +
+ dis.dispatch({action: 'view_room_directory'})}>{_t("Explore")} +
+ ); + } + const searchBox = ( { breadcrumbs } - { searchBox } +
+ { exploreButton } + { searchBox } +
Date: Tue, 10 Sep 2019 10:57:25 +0200 Subject: [PATCH 03/36] hide explore button when focusing filter field --- res/css/structures/_LeftPanel.scss | 5 +++++ src/components/structures/LeftPanel.js | 13 +++++++++++++ src/components/structures/SearchBox.js | 10 ++++++++++ 3 files changed, 28 insertions(+) diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 351e7e0a1b..8d8028c457 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -138,8 +138,13 @@ limitations under the License. .mx_LeftPanel_explore { flex: 0 0 40%; overflow: hidden; + transition: flex-basis 0.2s; box-sizing: border-box; + &.mx_LeftPanel_explore_hidden { + flex-basis: 0; + } + .mx_AccessibleButton { font-size: 14px; margin: 9px; diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index a15bf33645..fcae8bf4e6 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -82,6 +82,9 @@ const LeftPanel = React.createClass({ if (this.state.searchFilter !== nextState.searchFilter) { return true; } + if (this.state.searchFocused !== nextState.searchFocused) { + return true; + } return false; }, @@ -210,6 +213,14 @@ const LeftPanel = React.createClass({ this._roomList = ref; }, + _onSearchFocus: function() { + this.setState({searchFocused: true}); + }, + + _onSearchBlur: function() { + this.setState({searchFocused: false}); + }, + render: function() { const RoomList = sdk.getComponent('rooms.RoomList'); const RoomBreadcrumbs = sdk.getComponent('rooms.RoomBreadcrumbs'); @@ -256,6 +267,8 @@ const LeftPanel = React.createClass({ placeholder={ _t('Filter room names') } onSearch={ this.onSearch } onCleared={ this.onSearchCleared } + onFocus={this._onSearchFocus} + onBlur={this._onSearchBlur} collapsed={this.props.collapsed} />); let breadcrumbs; diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index a66cfb17b6..e2421e68f4 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -94,6 +94,15 @@ module.exports = React.createClass({ _onFocus: function(ev) { ev.target.select(); + if (this.props.onFocus) { + this.props.onFocus(ev); + } + }, + + _onBlur: function(ev) { + if (this.props.onBlur) { + this.props.onBlur(ev); + } }, _clearSearch: function(source) { @@ -131,6 +140,7 @@ module.exports = React.createClass({ onChange={ this.onChange } onKeyDown={ this._onKeyDown } placeholder={ this.props.placeholder } + onBlur={this._onBlur} /> { clearButton } From b328fcb7e3741bb0968e6e4b5e438f21066fc629 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Sep 2019 10:58:11 +0200 Subject: [PATCH 04/36] show shorter placeholder for filter feed when not focused --- src/components/structures/LeftPanel.js | 3 ++- src/components/structures/SearchBox.js | 12 +++++++++++- src/i18n/strings/en_EN.json | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index fcae8bf4e6..4e8217f5fa 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -264,7 +264,8 @@ const LeftPanel = React.createClass({ const searchBox = ( {this._clearSearch("button"); } }> ) : undefined; + // show a shorter placeholder when blurred, if requested + // this is used for the room filter field that has + // the explore button next to it when blurred + const placeholder = this.state.blurred ? + (this.props.blurredPlaceholder || this.props.placeholder) : + this.props.placeholder; const className = this.props.className || ""; return (
@@ -139,8 +149,8 @@ module.exports = React.createClass({ onFocus={ this._onFocus } onChange={ this.onChange } onKeyDown={ this._onKeyDown } - placeholder={ this.props.placeholder } onBlur={this._onBlur} + placeholder={ placeholder } /> { clearButton }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8dba563b9d..ca19fb8fe1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1473,8 +1473,9 @@ "Community %(groupId)s not found": "Community %(groupId)s not found", "This homeserver does not support communities": "This homeserver does not support communities", "Failed to load %(groupId)s": "Failed to load %(groupId)s", - "Filter room names": "Filter room names", "Explore": "Explore", + "Filter": "Filter", + "Filter rooms…": "Filter rooms…", "Failed to reject invitation": "Failed to reject invitation", "This room is not public. You will not be able to rejoin without an invite.": "This room is not public. You will not be able to rejoin without an invite.", "Are you sure you want to leave the room '%(roomName)s'?": "Are you sure you want to leave the room '%(roomName)s'?", From 31682b61ce8686548f3b258de25ccd7925570e4a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Sep 2019 10:58:44 +0200 Subject: [PATCH 05/36] make filter feed transparent when not focussed --- res/css/structures/_SearchBox.scss | 4 ++++ src/components/structures/SearchBox.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/res/css/structures/_SearchBox.scss b/res/css/structures/_SearchBox.scss index 7d13405478..23ee06f7b3 100644 --- a/res/css/structures/_SearchBox.scss +++ b/res/css/structures/_SearchBox.scss @@ -18,6 +18,10 @@ limitations under the License. flex: 1 1 0; min-width: 0; + &.mx_SearchBox_blurred:not(:hover) { + background-color: transparent; + } + .mx_SearchBox_closeButton { cursor: pointer; background-image: url('$(res)/img/icons-close.svg'); diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index 34efb5b50f..a95cb74a8d 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -139,7 +139,7 @@ module.exports = React.createClass({ this.props.placeholder; const className = this.props.className || ""; return ( -
+
Date: Tue, 10 Sep 2019 10:59:22 +0200 Subject: [PATCH 06/36] make explore button white on hover --- res/css/structures/_LeftPanel.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 8d8028c457..19b8907a28 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -156,6 +156,10 @@ limitations under the License. position: relative; border-radius: 4px; + &:hover { + background-color: $primary-bg-color; + } + &::before { cursor: pointer; mask: url('$(res)/img/explore.svg'); From 0a31c2662add05d9a76945cc8e08e4cf33f77e20 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Sep 2019 10:59:36 +0200 Subject: [PATCH 07/36] make input fields on a dark panel have a white background (filter field) --- res/css/_common.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/_common.scss b/res/css/_common.scss index d6c61b48d1..5d7829c162 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -171,7 +171,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { :not(.mx_textinput):not(.mx_Field):not(.mx_no_textinput) > input[type=search], .mx_textinput { color: $input-darker-fg-color; - background-color: $input-darker-bg-color; + background-color: $primary-bg-color; border: none; } } From b9421e4269328b5121036c3a322d9fb6056acda8 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Sep 2019 11:59:59 +0200 Subject: [PATCH 08/36] make add room button go to create room dialog instead of room directory --- src/components/structures/RoomDirectory.js | 11 ----------- src/components/views/rooms/RoomList.js | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index 8d8ad96ff6..83827acfae 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -322,11 +322,6 @@ module.exports = React.createClass({ } }, - onCreateRoomClicked: function() { - this.props.onFinished(); - dis.dispatch({action: 'view_create_room'}); - }, - onJoinClick: function(alias) { // If we don't have a particular instance id selected, just show that rooms alias if (!this.state.instanceId) { @@ -603,17 +598,11 @@ module.exports = React.createClass({
; } - const createRoomButton = ({_t("Create new room")}); - return (
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index ef7d0ed5fb..c47eb54bca 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -758,7 +758,7 @@ module.exports = React.createClass({ headerItems: this._getHeaderItems('im.vector.fake.recent'), order: "recent", incomingCall: incomingCallIfTaggedAs('im.vector.fake.recent'), - onAddRoom: () => {dis.dispatch({action: 'view_room_directory'})}, + onAddRoom: () => {dis.dispatch({action: 'view_create_room'});}, }, ]; const tagSubLists = Object.keys(this.state.lists) From ea7cbbc0eeccef8cf27debb9eac383d1ae045587 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 11 Sep 2019 13:46:18 +0200 Subject: [PATCH 09/36] keep filter field expanded if it has text in it --- src/components/structures/LeftPanel.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 4e8217f5fa..04702d9139 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -82,7 +82,7 @@ const LeftPanel = React.createClass({ if (this.state.searchFilter !== nextState.searchFilter) { return true; } - if (this.state.searchFocused !== nextState.searchFocused) { + if (this.state.searchExpanded !== nextState.searchExpanded) { return true; } @@ -207,6 +207,7 @@ const LeftPanel = React.createClass({ if (source === "keyboard") { dis.dispatch({action: 'focus_composer'}); } + this.setState({searchExpanded: false}); }, collectRoomList: function(ref) { @@ -214,11 +215,13 @@ const LeftPanel = React.createClass({ }, _onSearchFocus: function() { - this.setState({searchFocused: true}); + this.setState({searchExpanded: true}); }, - _onSearchBlur: function() { - this.setState({searchFocused: false}); + _onSearchBlur: function(event) { + if (event.target.value.length === 0) { + this.setState({searchExpanded: false}); + } }, render: function() { @@ -256,7 +259,7 @@ const LeftPanel = React.createClass({ let exploreButton; if (!this.props.collapsed) { exploreButton = ( -
+
dis.dispatch({action: 'view_room_directory'})}>{_t("Explore")}
); From cf8ca176e28d5f40389fa706858e044e9527f4c2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Sep 2019 16:07:01 +0200 Subject: [PATCH 10/36] remove labels and add join/view & preview button instead in directory --- src/components/structures/RoomDirectory.js | 159 ++++++++++++--------- src/i18n/strings/en_EN.json | 2 + 2 files changed, 93 insertions(+), 68 deletions(-) diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index 83827acfae..82b0e84bd6 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -322,7 +322,7 @@ module.exports = React.createClass({ } }, - onJoinClick: function(alias) { + onJoinFromSearchClick: function(alias) { // If we don't have a particular instance id selected, just show that rooms alias if (!this.state.instanceId) { // If the user specified an alias without a domain, add on whichever server is selected @@ -364,6 +364,34 @@ module.exports = React.createClass({ } }, + onPreviewClick: function(room) { + this.props.onFinished(); + dis.dispatch({ + action: 'view_room', + room_id: room.room_id, + should_peek: true, + }); + }, + + onViewClick: function(room) { + this.props.onFinished(); + dis.dispatch({ + action: 'view_room', + room_id: room.room_id, + should_peek: false, + }); + }, + + onJoinClick: function(room) { + this.props.onFinished(); + MatrixClientPeg.get().joinRoom(room.room_id); + dis.dispatch({ + action: 'view_room', + room_id: room.room_id, + joining: true, + }); + }, + showRoomAlias: function(alias, autoJoin=false) { this.showRoom(null, alias, autoJoin); }, @@ -408,74 +436,69 @@ module.exports = React.createClass({ dis.dispatch(payload); }, - getRows: function() { + getRow(room) { + const client = MatrixClientPeg.get(); + const clientRoom = client.getRoom(room.room_id); + const hasJoinedRoom = clientRoom && clientRoom.getMyMembership() === "join"; + const isGuest = client.isGuest(); const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + let previewButton; + let joinOrViewButton; - if (!this.state.publicRooms) return []; - - const rooms = this.state.publicRooms; - const rows = []; - const self = this; - let guestRead; let guestJoin; let perms; - for (let i = 0; i < rooms.length; i++) { - guestRead = null; - guestJoin = null; - - if (rooms[i].world_readable) { - guestRead = ( -
{ _t('World readable') }
- ); - } - if (rooms[i].guest_can_join) { - guestJoin = ( -
{ _t('Guests can join') }
- ); - } - - perms = null; - if (guestRead || guestJoin) { - perms =
{guestRead}{guestJoin}
; - } - - let name = rooms[i].name || get_display_alias_for_room(rooms[i]) || _t('Unnamed room'); - if (name.length > MAX_NAME_LENGTH) { - name = `${name.substring(0, MAX_NAME_LENGTH)}...`; - } - - let topic = rooms[i].topic || ''; - if (topic.length > MAX_TOPIC_LENGTH) { - topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`; - } - topic = linkifyAndSanitizeHtml(topic); - - rows.push( - {ev.preventDefault();}} - > - - - - -
{ name }
  - { perms } -
-
{ get_display_alias_for_room(rooms[i]) }
- - - { rooms[i].num_joined_members } - - , + if (room.world_readable && !hasJoinedRoom) { + previewButton = ( + this.onPreviewClick(room)}>{_t("Preview")} ); } - return rows; + if (hasJoinedRoom) { + joinOrViewButton = ( + this.onViewClick(room)}>{_t("View")} + ); + } else if (!isGuest || room.guest_can_join) { + joinOrViewButton = ( + this.onJoinClick(room)}>{_t("Join")} + ); + } + + let name = room.name || get_display_alias_for_room(room) || _t('Unnamed room'); + if (name.length > MAX_NAME_LENGTH) { + name = `${name.substring(0, MAX_NAME_LENGTH)}...`; + } + + let topic = room.topic || ''; + if (topic.length > MAX_TOPIC_LENGTH) { + topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`; + } + topic = linkifyAndSanitizeHtml(topic); + + return ( + this.onRoomClicked(room)} + // cancel onMouseDown otherwise shift-clicking highlights text + onMouseDown={(ev) => {ev.preventDefault();}} + > + + + + +
{ name }
  +
+
{ get_display_alias_for_room(room) }
+ + + { room.num_joined_members } + + {previewButton} + {joinOrViewButton} + + ); }, collectScrollPanel: function(element) { @@ -529,7 +552,7 @@ module.exports = React.createClass({ } else if (this.state.protocolsLoading || this.state.loading) { content = ; } else { - const rows = this.getRows(); + const rows = (this.state.publicRooms || []).map(room => this.getRow(room)); // we still show the scrollpanel, at least for now, because // otherwise we don't fetch more because we don't get a fill // request from the scrollpanel because there isn't one @@ -539,7 +562,7 @@ module.exports = React.createClass({ } else { scrollpanel_content = - { this.getRows() } + { rows }
; } @@ -591,7 +614,7 @@ module.exports = React.createClass({ listHeader =
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ca19fb8fe1..02bf52a2a4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1512,6 +1512,8 @@ "Couldn't find a matching Matrix room": "Couldn't find a matching Matrix room", "Fetching third party location failed": "Fetching third party location failed", "Unable to look up room ID from server": "Unable to look up room ID from server", + "Preview": "Preview", + "View": "View", "Search for a room": "Search for a room", "Search for a room like #example": "Search for a room like #example", "Message not sent due to unknown devices being present": "Message not sent due to unknown devices being present", From 810977a9162f1e88b4242e74af069187919ea423 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Sep 2019 16:07:27 +0200 Subject: [PATCH 11/36] basic styling to make it look ok before applying new design --- res/css/structures/_RoomDirectory.scss | 9 +++++++++ res/css/views/elements/_AccessibleButton.scss | 1 + 2 files changed, 10 insertions(+) diff --git a/res/css/structures/_RoomDirectory.scss b/res/css/structures/_RoomDirectory.scss index 1df0a61a2b..6989c3b0b0 100644 --- a/res/css/structures/_RoomDirectory.scss +++ b/res/css/structures/_RoomDirectory.scss @@ -135,4 +135,13 @@ limitations under the License. .mx_RoomDirectory_table tr { padding-bottom: 10px; cursor: pointer; + + .mx_RoomDirectory_roomDescription { + width: 50%; + } + + .mx_RoomDirectory_join, .mx_RoomDirectory_preview { + width: 80px; + text-align: center; + } } diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index 0c081ec0d5..5ca5d002ba 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -16,6 +16,7 @@ limitations under the License. .mx_AccessibleButton { cursor: pointer; + white-space: nowrap; } .mx_AccessibleButton:focus { From 13a3cf3afe4ea164c6e10ef14e867816d56892cc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 11 Sep 2019 14:15:46 +0000 Subject: [PATCH 12/36] consistent naming Co-Authored-By: Travis Ralston --- src/components/structures/RoomDirectory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index 82b0e84bd6..364b910b46 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -488,7 +488,7 @@ module.exports = React.createClass({
{ name }
 
{ ev.stopPropagation(); } } dangerouslySetInnerHTML={{ __html: topic }} />
{ get_display_alias_for_room(room) }
From 9866efabe537ed8053845d40c97a379a8bd58cf7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 11 Sep 2019 16:18:34 +0200 Subject: [PATCH 13/36] pr feedback --- src/components/structures/RoomDirectory.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index 364b910b46..c62882d097 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -471,7 +471,10 @@ module.exports = React.createClass({ topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`; } topic = linkifyAndSanitizeHtml(topic); - + const avatarUrl = ContentRepo.getHttpUriForMxc( + MatrixClientPeg.get().getHomeserverUrl(), + room.avatar_url, 24, 24, "crop", + ); return ( this.onRoomClicked(room)} @@ -481,15 +484,13 @@ module.exports = React.createClass({ + url={ avatarUrl } />
{ name }
 
{ ev.stopPropagation(); } } - dangerouslySetInnerHTML={{ __html: topic }} /> + onClick={ (ev) => { ev.stopPropagation(); } } + dangerouslySetInnerHTML={{ __html: topic }} />
{ get_display_alias_for_room(room) }
From b67a2492b319452e0eb75d2923bf192dfc5f51e2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 11 Sep 2019 15:36:29 +0200 Subject: [PATCH 14/36] adapt design of room list in directory --- res/css/structures/_RoomDirectory.scss | 82 +++++++++++----------- src/components/structures/RoomDirectory.js | 26 +++++-- src/i18n/strings/en_EN.json | 6 +- 3 files changed, 65 insertions(+), 49 deletions(-) diff --git a/res/css/structures/_RoomDirectory.scss b/res/css/structures/_RoomDirectory.scss index 6989c3b0b0..6b7a4ff0c7 100644 --- a/res/css/structures/_RoomDirectory.scss +++ b/res/css/structures/_RoomDirectory.scss @@ -17,7 +17,6 @@ limitations under the License. .mx_RoomDirectory_dialogWrapper > .mx_Dialog { max-width: 960px; height: 100%; - padding: 20px; } .mx_RoomDirectory_dialog { @@ -35,17 +34,6 @@ limitations under the License. flex: 1; } -.mx_RoomDirectory_createRoom { - background-color: $button-bg-color; - border-radius: 4px; - padding: 8px; - color: $button-fg-color; - font-weight: 600; - position: absolute; - top: 0; - left: 0; -} - .mx_RoomDirectory_list { flex: 1; display: flex; @@ -84,9 +72,8 @@ limitations under the License. } .mx_RoomDirectory_roomAvatar { - width: 24px; - padding-left: 12px; - padding-right: 24px; + width: 32px; + padding-right: 14px; vertical-align: top; } @@ -94,6 +81,34 @@ limitations under the License. padding-bottom: 16px; } +.mx_RoomDirectory_roomMemberCount { + color: $light-fg-color; + width: 60px; + padding: 0 10px; + text-align: center; + + &::before { + background-color: $light-fg-color; + display: inline-block; + vertical-align: text-top; + margin-right: 2px; + content: ""; + mask: url('$(res)/img/feather-customised/user.svg'); + mask-repeat: no-repeat; + mask-position: center; + // scale it down and make the size slightly bigger (16 instead of 14px) + // to avoid rendering artifacts + mask-size: 80%; + width: 16px; + height: 16px; + } +} + +.mx_RoomDirectory_join, .mx_RoomDirectory_preview { + width: 80px; + text-align: center; +} + .mx_RoomDirectory_name { display: inline-block; font-weight: 600; @@ -103,22 +118,9 @@ limitations under the License. display: inline-block; } -.mx_RoomDirectory_perm { - display: inline; - padding-left: 5px; - padding-right: 5px; - margin-right: 5px; - height: 15px; - border-radius: 11px; - background-color: $plinth-bg-color; - text-transform: uppercase; - font-weight: 600; - font-size: 11px; - color: $accent-color; -} - .mx_RoomDirectory_topic { cursor: initial; + color: $light-fg-color; } .mx_RoomDirectory_alias { @@ -126,22 +128,20 @@ limitations under the License. color: $settings-grey-fg-color; } -.mx_RoomDirectory_roomMemberCount { - text-align: right; - width: 100px; - padding-right: 10px; -} - .mx_RoomDirectory_table tr { padding-bottom: 10px; cursor: pointer; +} - .mx_RoomDirectory_roomDescription { - width: 50%; - } +.mx_RoomDirectory .mx_RoomView_MessageList { + padding: 0; +} - .mx_RoomDirectory_join, .mx_RoomDirectory_preview { - width: 80px; - text-align: center; +.mx_RoomDirectory p { + font-size: 14px; + margin-top: 0; + + .mx_AccessibleButton { + padding: 0; } } diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index c62882d097..45e6a5b2b7 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -392,6 +392,11 @@ module.exports = React.createClass({ }); }, + onCreateRoomClick: function(room) { + this.props.onFinished(); + dis.dispatch({action: 'view_create_room'}); + }, + showRoomAlias: function(alias, autoJoin=false) { this.showRoom(null, alias, autoJoin); }, @@ -473,7 +478,7 @@ module.exports = React.createClass({ topic = linkifyAndSanitizeHtml(topic); const avatarUrl = ContentRepo.getHttpUriForMxc( MatrixClientPeg.get().getHomeserverUrl(), - room.avatar_url, 24, 24, "crop", + room.avatar_url, 32, 32, "crop", ); return ( {ev.preventDefault();}} > - @@ -596,10 +601,9 @@ module.exports = React.createClass({ instance_expected_field_type = this.protocols[protocolName].field_types[last_field]; } - - let placeholder = _t('Search for a room'); + let placeholder = _t('Find a room…'); if (!this.state.instanceId) { - placeholder = _t('Search for a room like #example') + ':' + this.state.roomServer; + placeholder = _t("Find a room… (e.g. %(exampleRoom)s)", {exampleRoom: "#example:" + this.state.roomServer}); } else if (instance_expected_field_type) { placeholder = instance_expected_field_type.placeholder; } @@ -621,15 +625,25 @@ module.exports = React.createClass({
; } + const explanation = + _t("If you can't find the room you're looking for, ask for an invite or Create a new room.", null, + {a: sub => { + return ({sub}); + }}, + ); return (
+

{explanation}

{listHeader} {content} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 02bf52a2a4..797a5327cf 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1514,8 +1514,10 @@ "Unable to look up room ID from server": "Unable to look up room ID from server", "Preview": "Preview", "View": "View", - "Search for a room": "Search for a room", - "Search for a room like #example": "Search for a room like #example", + "Find a room…": "Find a room…", + "Find a room… (e.g. %(exampleRoom)s)": "Find a room… (e.g. %(exampleRoom)s)", + "If you can't find the room you're looking for, ask for an invite or Create a new room.": "If you can't find the room you're looking for, ask for an invite or Create a new room.", + "Explore rooms": "Explore rooms", "Message not sent due to unknown devices being present": "Message not sent due to unknown devices being present", "Show devices, send anyway or cancel.": "Show devices, send anyway or cancel.", "You can't send any messages until you review and agree to our terms and conditions.": "You can't send any messages until you review and agree to our terms and conditions.", From 86d7389b645f9bb40ce6aaf1b799c366a82b1d27 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 11 Sep 2019 15:36:59 +0200 Subject: [PATCH 15/36] reduce padding on dialogs, as in design --- res/css/_common.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/_common.scss b/res/css/_common.scss index 5d7829c162..c42aeac931 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -330,7 +330,7 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus { .mx_Dialog_header { position: relative; - margin-bottom: 20px; + margin-bottom: 10px; } .mx_Dialog_title { From 0cba5da03d89fe0952b3efbdfcfb0a60a7d6e53e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 9 Sep 2019 15:10:50 +0200 Subject: [PATCH 16/36] add redact recent messages button in member info --- src/components/views/rooms/MemberInfo.js | 86 +++++++++++++++++++++++- src/i18n/strings/en_EN.json | 7 ++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 8d9e5dfe39..8eee2f72b5 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -46,6 +46,8 @@ import SettingsStore from "../../../settings/SettingsStore"; import E2EIcon from "./E2EIcon"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import MatrixClientPeg from "../../../MatrixClientPeg"; +import Matrix from "matrix-js-sdk"; +const EventTimeline = Matrix.EventTimeline; module.exports = withMatrixClient(React.createClass({ displayName: 'MemberInfo', @@ -63,6 +65,7 @@ module.exports = withMatrixClient(React.createClass({ mute: false, modifyLevel: false, synapseDeactivate: false, + redactMessages: false, }, muted: false, isTargetMod: false, @@ -351,6 +354,73 @@ module.exports = withMatrixClient(React.createClass({ }); }, + onRedactAllMessages: async function() { + const {roomId, userId} = this.props.member; + const room = this.context.matrixClient.getRoom(roomId); + if (!room) { + return; + } + let timeline = room.getLiveTimeline(); + let eventsToRedact = []; + while (timeline) { + eventsToRedact = timeline.getEvents().reduce((events, event) => { + if (event.getSender() === userId && !event.isRedacted()) { + return events.concat(event); + } else { + return events; + } + }, eventsToRedact); + timeline = timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS); + } + + const count = eventsToRedact.length; + const user = this.props.member.name; + + if (count === 0) { + const InfoDialog = sdk.getComponent("dialogs.InfoDialog"); + Modal.createTrackedDialog('No user messages found to remove', '', InfoDialog, { + title: _t("No recent messages by %(user)s found", {user}), + description: +
+

{ _t("Try scrolling up in the timeline to see if there are any earlier ones.") }

+
, + }); + } else { + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + const confirmed = await new Promise((resolve) => { + Modal.createTrackedDialog('Remove recent messages by user', '', QuestionDialog, { + title: _t("Remove recent messages by %(user)s", {user}), + description: +
+

{ _t("You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?", {count, user}) }

+

{ _t("For large amount of messages, this might take some time. Please don't refresh your client in the meantime.") }

+
, + button: _t("Remove %(count)s messages", {count}), + onFinished: resolve, + }); + }); + + if (!confirmed) { + return; + } + + // Submitting a large number of redactions freezes the UI, + // so first wait 200ms to allow to rerender after closing the dialog. + await new Promise(resolve => setTimeout(resolve, 200)); + + await Promise.all(eventsToRedact.map(async event => { + try { + await this.context.matrixClient.redactEvent(roomId, event.getId()); + } catch (err) { + // log and swallow errors + console.error("Could not redact", event.getId()); + console.error(err); + } + })); + console.log("Done redacting recent messages!"); + } + }, + _warnSelfDemote: function() { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); return new Promise((resolve) => { @@ -597,6 +667,7 @@ module.exports = withMatrixClient(React.createClass({ mute: false, modifyLevel: false, modifyLevelMax: 0, + redactMessages: false, }; // Calculate permissions for Synapse before doing the PL checks @@ -618,6 +689,7 @@ module.exports = withMatrixClient(React.createClass({ can.mute = me.powerLevel >= editPowerLevel; can.modifyLevel = me.powerLevel >= editPowerLevel && (isMe || me.powerLevel > them.powerLevel); can.modifyLevelMax = me.powerLevel; + can.redactMessages = me.powerLevel >= powerLevels.redact; return can; }, @@ -807,6 +879,7 @@ module.exports = withMatrixClient(React.createClass({ let banButton; let muteButton; let giveModButton; + let redactButton; let synapseDeactivateButton; let spinner; @@ -884,6 +957,16 @@ module.exports = withMatrixClient(React.createClass({ ); } + + + if (this.state.can.redactMessages) { + redactButton = ( + + { _t("Remove recent messages") } + + ); + } + if (this.state.can.ban) { let label = _t("Ban"); if (this.props.member.membership === 'ban') { @@ -924,7 +1007,7 @@ module.exports = withMatrixClient(React.createClass({ } let adminTools; - if (kickButton || banButton || muteButton || giveModButton || synapseDeactivateButton) { + if (kickButton || banButton || muteButton || giveModButton || synapseDeactivateButton || redactButton) { adminTools =

{ _t("Admin Tools") }

@@ -933,6 +1016,7 @@ module.exports = withMatrixClient(React.createClass({ { muteButton } { kickButton } { banButton } + { redactButton } { giveModButton } { synapseDeactivateButton }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 797a5327cf..6c748018b9 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -724,6 +724,12 @@ "Unban this user?": "Unban this user?", "Ban this user?": "Ban this user?", "Failed to ban user": "Failed to ban user", + "No recent messages by %(user)s found": "No recent messages by %(user)s found", + "Try scrolling up in the timeline to see if there are any earlier ones.": "Try scrolling up in the timeline to see if there are any earlier ones.", + "Remove recent messages by %(user)s": "Remove recent messages by %(user)s", + "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?", + "For large amount of messages, this might take some time. Please don't refresh your client in the meantime.": "For large amount of messages, this might take some time. Please don't refresh your client in the meantime.", + "Remove %(count)s messages|other": "Remove %(count)s messages", "Demote yourself?": "Demote yourself?", "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.", "Demote": "Demote", @@ -742,6 +748,7 @@ "Share Link to User": "Share Link to User", "User Options": "User Options", "Direct chats": "Direct chats", + "Remove recent messages": "Remove recent messages", "Unmute": "Unmute", "Mute": "Mute", "Revoke Moderator": "Revoke Moderator", From ac65b28954f9b967e06bff46edfa783bac0077c9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 9 Sep 2019 16:19:10 +0200 Subject: [PATCH 17/36] PR feedback --- src/components/views/rooms/MemberInfo.js | 13 ++++++------- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 8eee2f72b5..867e50ba0d 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -46,8 +46,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import E2EIcon from "./E2EIcon"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import MatrixClientPeg from "../../../MatrixClientPeg"; -import Matrix from "matrix-js-sdk"; -const EventTimeline = Matrix.EventTimeline; +import {EventTimeline} from "matrix-js-sdk"; module.exports = withMatrixClient(React.createClass({ displayName: 'MemberInfo', @@ -393,7 +392,7 @@ module.exports = withMatrixClient(React.createClass({ description:

{ _t("You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?", {count, user}) }

-

{ _t("For large amount of messages, this might take some time. Please don't refresh your client in the meantime.") }

+

{ _t("For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.") }

, button: _t("Remove %(count)s messages", {count}), onFinished: resolve, @@ -405,9 +404,10 @@ module.exports = withMatrixClient(React.createClass({ } // Submitting a large number of redactions freezes the UI, - // so first wait 200ms to allow to rerender after closing the dialog. - await new Promise(resolve => setTimeout(resolve, 200)); + // so first yield to allow to rerender after closing the dialog. + await Promise.resolve(); + console.info(`Started redacting recent ${count} messages for ${user} in ${roomId}`); await Promise.all(eventsToRedact.map(async event => { try { await this.context.matrixClient.redactEvent(roomId, event.getId()); @@ -417,7 +417,7 @@ module.exports = withMatrixClient(React.createClass({ console.error(err); } })); - console.log("Done redacting recent messages!"); + console.info(`Finished redacting recent ${count} messages for ${user} in ${roomId}`); } }, @@ -958,7 +958,6 @@ module.exports = withMatrixClient(React.createClass({ ); } - if (this.state.can.redactMessages) { redactButton = ( diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 6c748018b9..2311a9219e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -728,7 +728,7 @@ "Try scrolling up in the timeline to see if there are any earlier ones.": "Try scrolling up in the timeline to see if there are any earlier ones.", "Remove recent messages by %(user)s": "Remove recent messages by %(user)s", "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?", - "For large amount of messages, this might take some time. Please don't refresh your client in the meantime.": "For large amount of messages, this might take some time. Please don't refresh your client in the meantime.", + "For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.": "For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.", "Remove %(count)s messages|other": "Remove %(count)s messages", "Demote yourself?": "Demote yourself?", "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.", From c26d71b5aa2e056c318245d4305123c280cb0472 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 10:49:58 +0100 Subject: [PATCH 18/36] Login: don't assume supported flows, prevent login flash on SSO servers Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/auth/Login.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 31cb92d982..4fe0a37c66 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -94,7 +94,7 @@ module.exports = React.createClass({ // Phase of the overall login dialog. phase: PHASE_LOGIN, // The current login flow, such as password, SSO, etc. - currentFlow: "m.login.password", + currentFlow: null, // we need to load the flows from the server // We perform liveliness checks later, but for now suppress the errors. // We also track the server dead errors independently of the regular errors so @@ -373,6 +373,7 @@ module.exports = React.createClass({ this.setState({ busy: true, + currentFlow: null, // reset flow loginIncorrect: false, }); From 4719084af2e5bf4ff91e5711fbd6a26ab20a8823 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 11:01:06 +0100 Subject: [PATCH 19/36] fix test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/components/structures/auth/Login-test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/components/structures/auth/Login-test.js b/test/components/structures/auth/Login-test.js index 74451b922f..e79cf037d0 100644 --- a/test/components/structures/auth/Login-test.js +++ b/test/components/structures/auth/Login-test.js @@ -75,6 +75,11 @@ describe('Login', function() { const root = render(); + // Set non-empty flows & matrixClient to get past the loading spinner + root.setState({ + currentFlow: "m.login.password", + }); + const form = ReactTestUtils.findRenderedComponentWithType( root, sdk.getComponent('auth.PasswordLogin'), From 95e7e366edb82b1f977329742d3a81f99215e012 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 11:20:03 +0100 Subject: [PATCH 20/36] Fix other test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- test/components/structures/auth/Login-test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/components/structures/auth/Login-test.js b/test/components/structures/auth/Login-test.js index e79cf037d0..6a7982dd47 100644 --- a/test/components/structures/auth/Login-test.js +++ b/test/components/structures/auth/Login-test.js @@ -55,6 +55,11 @@ describe('Login', function() { it('should show form with change server link', function() { const root = render(); + // Set non-empty flows & matrixClient to get past the loading spinner + root.setState({ + currentFlow: "m.login.password", + }); + const form = ReactTestUtils.findRenderedComponentWithType( root, sdk.getComponent('auth.PasswordLogin'), From 7ddac8d475e913600412f44ae64a81a65d6e261e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 12:20:36 +0100 Subject: [PATCH 21/36] Login: Add way to change HS from SSO Homeserver Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/auth/Login.js | 8 ++- src/components/views/auth/PasswordLogin.js | 35 ++---------- src/components/views/auth/SignInToText.js | 62 ++++++++++++++++++++++ 3 files changed, 72 insertions(+), 33 deletions(-) create mode 100644 src/components/views/auth/SignInToText.js diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 4fe0a37c66..7b8fd0db4f 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -567,6 +567,7 @@ module.exports = React.createClass({ }, _renderSsoStep: function(url) { + const SignInToText = sdk.getComponent('views.auth.SignInToText'); // XXX: This link does *not* have a target="_blank" because single sign-on relies on // redirecting the user back to a URI once they're logged in. On the web, this means // we use the same window and redirect back to riot. On electron, this actually @@ -575,9 +576,12 @@ module.exports = React.createClass({ // If this bug gets fixed, it will break SSO since it will open the SSO page in the // user's browser, let them log into their SSO provider, then redirect their browser // to vector://vector which, of course, will not work. - return ( + return ; }, render: function() { diff --git a/src/components/views/auth/PasswordLogin.js b/src/components/views/auth/PasswordLogin.js index 59acf0a034..63e77a938d 100644 --- a/src/components/views/auth/PasswordLogin.js +++ b/src/components/views/auth/PasswordLogin.js @@ -31,6 +31,7 @@ export default class PasswordLogin extends React.Component { static propTypes = { onSubmit: PropTypes.func.isRequired, // fn(username, password) onError: PropTypes.func, + onEditServerDetailsClick: PropTypes.func, onForgotPasswordClick: PropTypes.func, // fn() initialUsername: PropTypes.string, initialPhoneCountry: PropTypes.string, @@ -257,6 +258,7 @@ export default class PasswordLogin extends React.Component { render() { const Field = sdk.getComponent('elements.Field'); + const SignInToText = sdk.getComponent('views.auth.SignInToText'); let forgotPasswordJsx; @@ -273,33 +275,6 @@ export default class PasswordLogin extends React.Component { ; } - let signInToText = _t('Sign in to your Matrix account on %(serverName)s', { - serverName: this.props.serverConfig.hsName, - }); - if (this.props.serverConfig.hsNameIsDifferent) { - const TextWithTooltip = sdk.getComponent("elements.TextWithTooltip"); - - signInToText = _t('Sign in to your Matrix account on ', {}, { - 'underlinedServerName': () => { - return ; - }, - }); - } - - let editLink = null; - if (this.props.onEditServerDetailsClick) { - editLink = - {_t('Change')} - ; - } - const pwFieldClass = classNames({ error: this.props.loginIncorrect && !this.isLoginEmpty(), // only error password if error isn't top field }); @@ -342,10 +317,8 @@ export default class PasswordLogin extends React.Component { return (
-

- {signInToText} - {editLink} -

+
{loginType} {loginField} diff --git a/src/components/views/auth/SignInToText.js b/src/components/views/auth/SignInToText.js new file mode 100644 index 0000000000..edbe2fd661 --- /dev/null +++ b/src/components/views/auth/SignInToText.js @@ -0,0 +1,62 @@ +/* +Copyright 2019 New Vector Ltd + +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 {_t} from "../../../languageHandler"; +import sdk from "../../../index"; +import PropTypes from "prop-types"; +import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; + +export default class SignInToText extends React.PureComponent { + static propTypes = { + serverConfig: PropTypes.instanceOf(ValidatedServerConfig).isRequired, + onEditServerDetailsClick: PropTypes.func, + }; + + render() { + let signInToText = _t('Sign in to your Matrix account on %(serverName)s', { + serverName: this.props.serverConfig.hsName, + }); + if (this.props.serverConfig.hsNameIsDifferent) { + const TextWithTooltip = sdk.getComponent("elements.TextWithTooltip"); + + signInToText = _t('Sign in to your Matrix account on ', {}, { + 'underlinedServerName': () => { + return ; + }, + }); + } + + let editLink = null; + if (this.props.onEditServerDetailsClick) { + editLink = + {_t('Change')} + ; + } + + return

+ {signInToText} + {editLink} +

; + } +} From 7c5e6ef2c5a7272090888b89cadab0366cda6043 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 13:57:19 +0100 Subject: [PATCH 22/36] regen 18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2311a9219e..90edd32660 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1393,9 +1393,6 @@ "Username": "Username", "Phone": "Phone", "Not sure of your password? Set a new one": "Not sure of your password? Set a new one", - "Sign in to your Matrix account on %(serverName)s": "Sign in to your Matrix account on %(serverName)s", - "Sign in to your Matrix account on ": "Sign in to your Matrix account on ", - "Change": "Change", "Sign in with": "Sign in with", "If you don't specify an email address, you won't be able to reset your password. Are you sure?": "If you don't specify an email address, you won't be able to reset your password. Are you sure?", "Use an email address to recover your account": "Use an email address to recover your account", @@ -1417,6 +1414,7 @@ "Phone (optional)": "Phone (optional)", "Create your Matrix account on %(serverName)s": "Create your Matrix account on %(serverName)s", "Create your Matrix account on ": "Create your Matrix account on ", + "Change": "Change", "Use an email address to recover your account.": "Use an email address to recover your account.", "Other users can invite you to rooms using your contact details.": "Other users can invite you to rooms using your contact details.", "Other servers": "Other servers", @@ -1429,6 +1427,8 @@ "Premium hosting for organisations Learn more": "Premium hosting for organisations Learn more", "Other": "Other", "Find other public servers or use a custom server": "Find other public servers or use a custom server", + "Sign in to your Matrix account on %(serverName)s": "Sign in to your Matrix account on %(serverName)s", + "Sign in to your Matrix account on ": "Sign in to your Matrix account on ", "Sorry, your browser is not able to run Riot.": "Sorry, your browser is not able to run Riot.", "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.", "Please install Chrome, Firefox, or Safari for the best experience.": "Please install Chrome, Firefox, or Safari for the best experience.", From 9c1fb13d5f23bd0c838557ed9282afae5e7f0c1a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 17:34:29 +0100 Subject: [PATCH 23/36] Apply PR feedback Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/auth/Login.js | 12 +++++++----- src/components/views/auth/SignInToText.js | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index 7b8fd0db4f..c68bedecc3 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -576,12 +576,14 @@ module.exports = React.createClass({ // If this bug gets fixed, it will break SSO since it will open the SSO page in the // user's browser, let them log into their SSO provider, then redirect their browser // to vector://vector which, of course, will not work. - return + ); }, render: function() { diff --git a/src/components/views/auth/SignInToText.js b/src/components/views/auth/SignInToText.js index edbe2fd661..a7acdc6705 100644 --- a/src/components/views/auth/SignInToText.js +++ b/src/components/views/auth/SignInToText.js @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 491087c1cfbb67914756cb2b2a3f1fc1838e3f06 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 11 Sep 2019 18:43:30 +0100 Subject: [PATCH 24/36] js-sdk rc.1 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3765d6aedf..190177b1f5 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "linkifyjs": "^2.1.6", "lodash": "^4.17.14", "lolex": "2.3.2", - "matrix-js-sdk": "2.3.0-rc.1", + "matrix-js-sdk": "2.3.1-rc.1", "optimist": "^0.6.1", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index fc21dcffc2..b29ff14849 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4958,10 +4958,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@2.3.0-rc.1: - version "2.3.0-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-2.3.0-rc.1.tgz#fe90e3c60f17dacea6454786269a1ba497d8d401" - integrity sha512-lxk/aBNrTklG5Ya8vhc8kbBL2jrPU1vvDZ87GXVMGL3L1Cg3oNnClJXqyf/MwnY8egfqHWLrMsQRSerOPVgnEQ== +matrix-js-sdk@2.3.1-rc.1: + version "2.3.1-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-2.3.1-rc.1.tgz#520555cae49a88c11dbe6e445b62d1893286fbe6" + integrity sha512-rPsteIs/rTfTra+Tjve6e5H8HgVhREiA4bi1wb8TN/MK97z6p2LU1nniayoyn8kNz8FbTkXOavgPWZd9VsfkPQ== dependencies: another-json "^0.2.0" babel-runtime "^6.26.0" From 455f493c5d3753be29cac9e32ed8a417c7dc6936 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 11 Sep 2019 18:46:12 +0100 Subject: [PATCH 25/36] Prepare changelog for v1.5.2-rc.1 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eac5efc98..ebb586b45b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [1.5.2-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.2-rc.1) (2019-09-11) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.1...v1.5.2-rc.1) + + * Merge first pass of First Time User Experience to release branch + [\#3420](https://github.com/matrix-org/matrix-react-sdk/pull/3420) + Changes in [1.5.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.1) (2019-08-05) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.0-rc.1...v1.5.1) From 77ae78ad24d331bc088851aff3e953044dfb07ed Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 11 Sep 2019 18:46:13 +0100 Subject: [PATCH 26/36] v1.5.2-rc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 190177b1f5..2cdcd1bdb8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "1.5.1", + "version": "1.5.2-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 8eb8b00460fe6b1e44c686cf92ea7324ef7139dd Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 11:52:39 +0100 Subject: [PATCH 27/36] RoomDirectory: show spinner if loading more results Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomDirectory.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index 45e6a5b2b7..9a21cad0e0 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -1,6 +1,7 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> +Copyright 2019 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -141,6 +142,10 @@ module.exports = React.createClass({ getMoreRooms: function() { if (!MatrixClientPeg.get()) return Promise.resolve(); + this.setState({ + loading: true, + }); + const my_filter_string = this.state.filterString; const my_server = this.state.roomServer; // remember the next batch token when we sent the request @@ -555,15 +560,21 @@ module.exports = React.createClass({ let content; if (this.state.error) { content = this.state.error; - } else if (this.state.protocolsLoading || this.state.loading) { + } else if (this.state.protocolsLoading) { content = ; } else { const rows = (this.state.publicRooms || []).map(room => this.getRow(room)); // we still show the scrollpanel, at least for now, because // otherwise we don't fetch more because we don't get a fill // request from the scrollpanel because there isn't one + + let spinner; + if (this.state.loading) { + spinner = ; + } + let scrollpanel_content; - if (rows.length == 0) { + if (rows.length === 0 && !this.state.loading) { scrollpanel_content = { _t('No rooms to show') }; } else { scrollpanel_content = @@ -580,6 +591,7 @@ module.exports = React.createClass({ startAtBottom={false} > { scrollpanel_content } + { spinner } ; } From 5091658dc7054219ca5ccc0da4ec5c8feb15e350 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 16:02:37 +0100 Subject: [PATCH 28/36] Update Copyright --- src/components/structures/RoomDirectory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index 9a21cad0e0..19db128ba3 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -1,7 +1,7 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> -Copyright 2019 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 7c54359d3a7e31e11fd6f5ad96d3072c36490670 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 11 Sep 2019 23:02:52 +0100 Subject: [PATCH 29/36] Hide the change HS url button on SSO login flow if custom urls disabled Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/auth/Login.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/structures/auth/Login.js b/src/components/structures/auth/Login.js index c68bedecc3..3308daf366 100644 --- a/src/components/structures/auth/Login.js +++ b/src/components/structures/auth/Login.js @@ -568,6 +568,12 @@ module.exports = React.createClass({ _renderSsoStep: function(url) { const SignInToText = sdk.getComponent('views.auth.SignInToText'); + + let onEditServerDetailsClick = null; + // If custom URLs are allowed, wire up the server details edit link. + if (PHASES_ENABLED && !SdkConfig.get()['disable_custom_urls']) { + onEditServerDetailsClick = this.onEditServerDetailsClick; + } // XXX: This link does *not* have a target="_blank" because single sign-on relies on // redirecting the user back to a URI once they're logged in. On the web, this means // we use the same window and redirect back to riot. On electron, this actually @@ -579,7 +585,7 @@ module.exports = React.createClass({ return (
+ onEditServerDetailsClick={onEditServerDetailsClick} /> { _t('Sign in with single sign-on') }
From c70736fe004c088ed29b840baaae3aac506c526c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 12 Sep 2019 11:11:32 +0200 Subject: [PATCH 30/36] make explore button and filter field equal width --- res/css/structures/_LeftPanel.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 19b8907a28..8ea41d7740 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -136,7 +136,7 @@ limitations under the License. } .mx_LeftPanel_explore { - flex: 0 0 40%; + flex: 0 0 50%; overflow: hidden; transition: flex-basis 0.2s; box-sizing: border-box; From 122e15156a055f8fbbb383792048ab2a358e2f6c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 12 Sep 2019 11:12:06 +0200 Subject: [PATCH 31/36] always show clear button in search box when focused --- src/components/structures/SearchBox.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index a95cb74a8d..007ac88db2 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -125,7 +125,7 @@ module.exports = React.createClass({ if (this.props.collapsed) { return null; } - const clearButton = this.state.searchTerm.length > 0 ? + const clearButton = !this.state.blurred ? ( {this._clearSearch("button"); } }> From e4a452e4bdce10fb6b0dc43a6276aefb64667aa6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 12 Sep 2019 11:27:20 +0200 Subject: [PATCH 32/36] reduce vertical padding around explore/filter --- res/css/structures/_LeftPanel.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 8ea41d7740..b58467317d 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -132,6 +132,7 @@ limitations under the License. .mx_SearchBox { flex: 1 1 0; min-width: 0; + margin: 4px 9px 1px 9px; } } @@ -147,8 +148,7 @@ limitations under the License. .mx_AccessibleButton { font-size: 14px; - margin: 9px; - margin-right: 0; + margin: 4px 0 1px 9px; padding: 9px; padding-left: 42px; font-weight: 600; From d67a8d5ccd37a586cdf4cf886943b56e10b967a9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 12 Sep 2019 12:24:05 +0200 Subject: [PATCH 33/36] undo whitespace setting, accessible button is used in too many places to make this a safe assumption --- res/css/views/elements/_AccessibleButton.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index 5ca5d002ba..0c081ec0d5 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -16,7 +16,6 @@ limitations under the License. .mx_AccessibleButton { cursor: pointer; - white-space: nowrap; } .mx_AccessibleButton:focus { From bdcaaa95f8d96144f759a4e10feb12c661702963 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 12 Sep 2019 12:53:33 +0100 Subject: [PATCH 34/36] Released js-sdk --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2cdcd1bdb8..669eb11ae0 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "linkifyjs": "^2.1.6", "lodash": "^4.17.14", "lolex": "2.3.2", - "matrix-js-sdk": "2.3.1-rc.1", + "matrix-js-sdk": "2.3.1", "optimist": "^0.6.1", "pako": "^1.0.5", "png-chunks-extract": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index b29ff14849..b8abf285f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4958,10 +4958,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@2.3.1-rc.1: - version "2.3.1-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-2.3.1-rc.1.tgz#520555cae49a88c11dbe6e445b62d1893286fbe6" - integrity sha512-rPsteIs/rTfTra+Tjve6e5H8HgVhREiA4bi1wb8TN/MK97z6p2LU1nniayoyn8kNz8FbTkXOavgPWZd9VsfkPQ== +matrix-js-sdk@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-2.3.1.tgz#c0ebe90d43611cf28422317ec0c04f5d41acb2ad" + integrity sha512-lf2pGHp0o4bDVrSZ5ReLAkMMiX9PngGMxNAtzztdDvQ20lfYZvhwif9PUbi3tt8kwXlfs7s34eWxz5Rg37mdGg== dependencies: another-json "^0.2.0" babel-runtime "^6.26.0" From 1e77f5f171fa0f50816b5a7d1473176dac1a9c96 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 12 Sep 2019 12:57:22 +0100 Subject: [PATCH 35/36] Prepare changelog for v1.5.2 --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebb586b45b..ed52ca52a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +Changes in [1.5.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.2) (2019-09-12) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.2-rc.1...v1.5.2) + + * Fix register page selector buttons growing too wide + [\#3427](https://github.com/matrix-org/matrix-react-sdk/pull/3427) + * Left panel: visual fixes + [\#3426](https://github.com/matrix-org/matrix-react-sdk/pull/3426) + * Hide the change HS url button on SSO login flow if custom urls disabled + [\#3425](https://github.com/matrix-org/matrix-react-sdk/pull/3425) + * RoomDirectory: show spinner if loading more results + [\#3424](https://github.com/matrix-org/matrix-react-sdk/pull/3424) + Changes in [1.5.2-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v1.5.2-rc.1) (2019-09-11) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v1.5.1...v1.5.2-rc.1) From 3f316664090efa204adf318a2f129994b770643f Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Thu, 12 Sep 2019 12:57:22 +0100 Subject: [PATCH 36/36] v1.5.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 669eb11ae0..93e9f4ecc7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "1.5.2-rc.1", + "version": "1.5.2", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": {