From 4e8b3c34c0f61d22d78ec3567c9f6088ec68e223 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 10 Apr 2019 17:49:45 +0200 Subject: [PATCH 01/32] move room preview bar below timeline --- src/components/structures/RoomView.js | 50 +++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 92775f75b3..2da21bbef7 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1530,21 +1530,20 @@ module.exports = React.createClass({ e2eStatus={this.state.e2eStatus} />
-
- -
+
+ ); } @@ -1578,19 +1577,18 @@ module.exports = React.createClass({ e2eStatus={this.state.e2eStatus} />
-
- -
+
+ ); } @@ -1646,6 +1644,7 @@ module.exports = React.createClass({ const hiddenHighlightCount = this._getHiddenHighlightCount(); let aux = null; + let previewBar; let hideCancel = false; if (this.state.forwardingEvent !== null) { aux = ; @@ -1673,7 +1672,7 @@ module.exports = React.createClass({ invitedEmail = this.props.thirdPartyInvite.invitedEmail; } hideCancel = true; - aux = ( + previewBar = ( + { previewBar } { messageComposer } From 0553a6f1d647b703a8a083da9e0f9e37f2a8abe3 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 11 Apr 2019 13:07:54 +0200 Subject: [PATCH 02/32] some style changes --- res/css/views/rooms/_RoomPreviewBar.scss | 17 ++++++----------- src/components/views/rooms/RoomPreviewBar.js | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/res/css/views/rooms/_RoomPreviewBar.scss b/res/css/views/rooms/_RoomPreviewBar.scss index 8196740499..cc3263bef3 100644 --- a/res/css/views/rooms/_RoomPreviewBar.scss +++ b/res/css/views/rooms/_RoomPreviewBar.scss @@ -15,24 +15,19 @@ limitations under the License. */ .mx_RoomPreviewBar { + flex: 0 0 auto; + margin: 15px; + padding: 10px; + border-radius: 4px; + border: 1px solid $panel-divider-color; text-align: center; - height: 176px; - background-color: $event-selected-color; align-items: center; flex-direction: column; justify-content: center; display: flex; - background-color: $preview-bar-bg-color; -webkit-align-items: center; } -.mx_RoomPreviewBar_wrapper { -} - -.mx_RoomPreviewBar_invite_text { - color: $primary-fg-color; -} - .mx_RoomPreviewBar_join_text { color: $warning-color; } @@ -59,4 +54,4 @@ limitations under the License. .mx_RoomPreviewBar_spinnerIntro { margin-top: 50px; -} \ No newline at end of file +} diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index dbe409d6d7..95cecf32d9 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -235,7 +235,7 @@ module.exports = React.createClass({ } return ( -
+
{ joinBlock } { previewBlock } From 16ed06cebb1e336888840a923784e53b4189771a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 12 Apr 2019 12:47:52 +0200 Subject: [PATCH 03/32] dont show room header and timeline when room cant be peeked (just preview bar) --- src/components/structures/RoomView.js | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 2da21bbef7..3ff72b4e5b 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1523,16 +1523,6 @@ module.exports = React.createClass({ const roomAlias = this.state.roomAlias; return (
- -
-
-
-
- -
-
-
-
); + if (!this.state.canPeek) { + return ( +
+ { previewBar } +
+ ); + } } else if (hiddenHighlightCount > 0) { aux = ( Date: Fri, 12 Apr 2019 12:54:13 +0200 Subject: [PATCH 04/32] differentiate style based on preview or not --- res/css/views/rooms/_RoomPreviewBar.scss | 4 ++++ src/components/views/rooms/RoomPreviewBar.js | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_RoomPreviewBar.scss b/res/css/views/rooms/_RoomPreviewBar.scss index cc3263bef3..e62f488bfa 100644 --- a/res/css/views/rooms/_RoomPreviewBar.scss +++ b/res/css/views/rooms/_RoomPreviewBar.scss @@ -28,6 +28,10 @@ limitations under the License. -webkit-align-items: center; } +.mx_RoomPreviewBar_dialog { + margin: auto; +} + .mx_RoomPreviewBar_join_text { color: $warning-color; } diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 95cecf32d9..f331f07f03 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -21,6 +21,7 @@ const React = require('react'); import PropTypes from 'prop-types'; const sdk = require('../../../index'); const MatrixClientPeg = require('../../../MatrixClientPeg'); +import classNames from 'classnames'; import { _t } from '../../../languageHandler'; @@ -234,8 +235,13 @@ module.exports = React.createClass({ ); } + const classes = classNames("mx_RoomPreviewBar", "dark-panel", { + "mx_RoomPreviewBar_panel": this.props.canPreview, + "mx_RoomPreviewBar_dialog": !this.props.canPreview, + }); + return ( -
+
{ joinBlock } { previewBlock } From b67152d98eb45c08e21fce2dd06b899ba1d18ecc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 12 Apr 2019 14:40:31 +0200 Subject: [PATCH 05/32] WIP --- src/components/views/rooms/RoomPreviewBar.js | 156 ++++++++++++++++++- 1 file changed, 154 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index f331f07f03..9d1ed44127 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -25,6 +25,20 @@ import classNames from 'classnames'; import { _t } from '../../../languageHandler'; +const MessageCase = Object.freeze({ + NotLoggedIn: "NotLoggedIn", + Joining: "Joining", + Busy: "Busy", + Kicked: "Kicked", + Banned: "Banned", + OtherThreePIDError: "OtherThreePIDError", + MismatchThreePIDInvite: "MismatchThreePIDInvite", + Invite: "Invite", + ViewingRoom: "ViewingRoom", + RoomNotFound: "RoomNotFound", + OtherError: "OtherError", +}); + module.exports = React.createClass({ displayName: 'RoomPreviewBar', @@ -32,6 +46,8 @@ module.exports = React.createClass({ onJoinClick: PropTypes.func, onRejectClick: PropTypes.func, onForgetClick: PropTypes.func, + onSignInClick: PropTypes.func, + onSignUpClick: PropTypes.func, // if inviterName is specified, the preview bar will shown an invite to the room. // You should also specify onRejectClick if specifiying inviterName @@ -73,7 +89,7 @@ module.exports = React.createClass({ componentWillMount: function() { // If this is an invite and we've been told what email - // address was invited, fetch the user's list of 3pids + // address was invited, fetch the user's list of Threepids // so we can check them against the one that was invited if (this.props.inviterName && this.props.invitedEmail) { this.setState({busy: true}); @@ -89,15 +105,151 @@ module.exports = React.createClass({ } }, + _getMessageCase() { + if (this.props.spinner || this.state.busy) { + if (this.props.spinnerState === "joining") { + return MessageCase.Joining; + } else { + return MessageCase.Busy; + } + } + const myMember = this.props.room ? + this.props.room.getMember(MatrixClientPeg.get().getUserId()) : + null; + + if (this.props.inviterName) { + if (this.props.invitedEmail) { + if (this.state.threePidFetchError) { + return MessageCase.OtherThreePIDError; + } else if (this.state.invitedEmailMxid != MatrixClientPeg.get().credentials.userId) { + return MessageCase.MismatchThreePIDInvite; + } + } + return MessageCase.Invite; + } else if (myMember && myMember.isKicked()) { + return MessageCase.Kicked; + } else if (myMember && myMember && myMember.membership == 'ban') { + return MessageCase.Banned; + } else if (this.props.error) { + if (this.props.error.errcode == 'M_NOT_FOUND') { + return MessageCase.RoomNotFound; + } else { + return MessageCase.OtherError; + } + } else { + return MessageCase.ViewingRoom; + } + }, + + _getKickOrBanInfo() { + const myMember = this.props.room ? + this.props.room.getMember(MatrixClientPeg.get().getUserId()) : + null; + if (!myMember) { + return {}; + } + const kickerMember = this.props.room.currentState.getMember( + myMember.events.member.getSender(), + ); + const memberName = kickerMember ? + kickerMember.name : myMember.events.member.getSender(); + const reason = myMember.events.member.getContent().reason; + return {memberName, reason}; + }, + _roomNameElement: function() { return this.props.room ? this.props.room.name : (this.props.room_alias || ""); }, render: function() { + let showSpinner = false; + let darkStyle = false; + let title; + let subTitle; + let primaryActionHandler; + let primaryActionLabel; + let secondaryActionHandler; + let secondaryActionLabel; + + switch (this._getMessageCase()) { + case MessageCase.Joining: { + title = _t("Joining room..."); + showSpinner = true; + break; + } + case MessageCase.Busy: { + title = _t("In progress ..."); + showSpinner = true; + break; + } + case MessageCase.NotLoggedIn: { + darkStyle = true; + title = _t("Join the conversation with an account"); + primaryActionLabel = _t("Sign Up"); + primaryActionLabel = this.props.onSignUpClick; + secondaryActionLabel = _t("Sign In"); + secondaryActionLabel = this.props.onSignInClick; + break; + } + case MessageCase.Kicked: { + const info = this._getKickOrBanInfo(); + title = _t("You were kicked from this room by %(memberName)", info); + subTitle = _t("Reason: %(reason)", info); + primaryActionLabel = _t("Re-join"); + primaryActionLabel = this.props.onJoinClick; + secondaryActionLabel = _t("Forget this room"); + secondaryActionLabel = this.props.onForgetClick; + break; + } + case MessageCase.Banned: { + const info = this._getKickOrBanInfo(); + title = _t("You were banned from this room by %(memberName)", info); + subTitle = _t("Reason: %(reason)", info); + primaryActionLabel = _t("Forget this room"); + primaryActionLabel = this.props.onForgetClick; + break; + } + case MessageCase.OtherThreePIDError: { + break; + } + case MessageCase.MismatchThreePIDInvite: { + title = _t("The room invite wasn't sent to your account"); + subTitle = _t("Sign in with a different account, ask for another invite, or add the e-mail address %(email) to this account.", {email: this.props.invitedEmail}); + break; + } + case MessageCase.Invite: { + title = _t("%(memberName) invited you to this room", {memberName: this.props.inviterName}); + primaryActionLabel = _t("Accept"); + primaryActionLabel = this.props.onJoinClick; + secondaryActionLabel = _t("Reject"); + secondaryActionLabel = this.props.onRejectClick; + break; + } + case MessageCase.ViewingRoom: { + if (this.props.canPreview) { + title = _t("You are previewing this room. Want to join it?"); + } else { + title = _t("This room can't be previewed. Do you want to join it?"); + } + + title = _t("%(memberName) invited you to this room", {memberName: this.props.inviterName}); + primaryActionLabel = _t("Accept"); + primaryActionLabel = this.props.onJoinClick; + secondaryActionLabel = _t("Reject"); + secondaryActionLabel = this.props.onRejectClick; + break; + } + case MessageCase.RoomNotFound: { + break; + } + case MessageCase.OtherError: { + break; + } + } + let joinBlock; let previewBlock; if (this.props.spinner || this.state.busy) { - const Spinner = sdk.getComponent("elements.Spinner"); let spinnerIntro = ""; if (this.props.spinnerState === "joining") { spinnerIntro = _t("Joining room..."); From b09c7f97e965fe7ca9d2576bd843f32486faa4c9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 14:43:37 +0200 Subject: [PATCH 06/32] implement most of new messages --- src/components/views/rooms/RoomPreviewBar.js | 218 +++++-------------- src/i18n/strings/en_EN.json | 39 ++-- 2 files changed, 77 insertions(+), 180 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 9d1ed44127..850fb0d32d 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -32,7 +32,7 @@ const MessageCase = Object.freeze({ Kicked: "Kicked", Banned: "Banned", OtherThreePIDError: "OtherThreePIDError", - MismatchThreePIDInvite: "MismatchThreePIDInvite", + InvitedEmailMismatch: "InvitedEmailMismatch", Invite: "Invite", ViewingRoom: "ViewingRoom", RoomNotFound: "RoomNotFound", @@ -122,7 +122,7 @@ module.exports = React.createClass({ if (this.state.threePidFetchError) { return MessageCase.OtherThreePIDError; } else if (this.state.invitedEmailMxid != MatrixClientPeg.get().credentials.userId) { - return MessageCase.MismatchThreePIDInvite; + return MessageCase.InvitedEmailMismatch; } } return MessageCase.Invite; @@ -162,6 +162,8 @@ module.exports = React.createClass({ }, render: function() { + const name = this.props.roomAlias || _t("This room"); + let showSpinner = false; let darkStyle = false; let title; @@ -186,205 +188,89 @@ module.exports = React.createClass({ darkStyle = true; title = _t("Join the conversation with an account"); primaryActionLabel = _t("Sign Up"); - primaryActionLabel = this.props.onSignUpClick; + primaryActionHandler = this.props.onSignUpClick; secondaryActionLabel = _t("Sign In"); - secondaryActionLabel = this.props.onSignInClick; + secondaryActionHandler = this.props.onSignInClick; break; } case MessageCase.Kicked: { - const info = this._getKickOrBanInfo(); - title = _t("You were kicked from this room by %(memberName)", info); - subTitle = _t("Reason: %(reason)", info); + const {memberName, reason} = this._getKickOrBanInfo(); + title = _t("You were kicked from this room by %(memberName)s", {memberName}); + subTitle = _t("Reason: %(reason)s", {reason}); primaryActionLabel = _t("Re-join"); - primaryActionLabel = this.props.onJoinClick; + primaryActionHandler = this.props.onJoinClick; secondaryActionLabel = _t("Forget this room"); - secondaryActionLabel = this.props.onForgetClick; + secondaryActionHandler = this.props.onForgetClick; break; } case MessageCase.Banned: { - const info = this._getKickOrBanInfo(); - title = _t("You were banned from this room by %(memberName)", info); - subTitle = _t("Reason: %(reason)", info); + const {memberName, reason} = this._getKickOrBanInfo(); + title = _t("You were banned from this room by %(memberName)s", {memberName}); + subTitle = _t("Reason: %(reason)s", {reason}); primaryActionLabel = _t("Forget this room"); - primaryActionLabel = this.props.onForgetClick; + primaryActionHandler = this.props.onForgetClick; break; } case MessageCase.OtherThreePIDError: { + // "Unable to ascertain that the address this invite was sent to matches one associated with your account." + // need to show invited by "name", join buttons here? break; } - case MessageCase.MismatchThreePIDInvite: { + case MessageCase.InvitedEmailMismatch: { title = _t("The room invite wasn't sent to your account"); - subTitle = _t("Sign in with a different account, ask for another invite, or add the e-mail address %(email) to this account.", {email: this.props.invitedEmail}); + subTitle = _t("Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", {email: this.props.invitedEmail}); break; } case MessageCase.Invite: { - title = _t("%(memberName) invited you to this room", {memberName: this.props.inviterName}); + if (this.props.canPreview) { + title = _t("%(memberName)s invited you to this room", {memberName: this.props.inviterName}); + } else { + title = _t("Do you want to join this room?"); + subTitle = _t("%(memberName)s invited you", {memberName: this.props.inviterName}); + } primaryActionLabel = _t("Accept"); - primaryActionLabel = this.props.onJoinClick; + primaryActionHandler = this.props.onJoinClick; secondaryActionLabel = _t("Reject"); - secondaryActionLabel = this.props.onRejectClick; + secondaryActionHandler = this.props.onRejectClick; break; } case MessageCase.ViewingRoom: { if (this.props.canPreview) { - title = _t("You are previewing this room. Want to join it?"); + title = _t("You're previewing this room. Want to join it?"); } else { title = _t("This room can't be previewed. Do you want to join it?"); } - - title = _t("%(memberName) invited you to this room", {memberName: this.props.inviterName}); - primaryActionLabel = _t("Accept"); - primaryActionLabel = this.props.onJoinClick; - secondaryActionLabel = _t("Reject"); - secondaryActionLabel = this.props.onRejectClick; + primaryActionLabel = _t("Join the discussion"); + primaryActionHandler = this.props.onJoinClick; break; } case MessageCase.RoomNotFound: { + title = _t("%(roomName)s does not exist.", {roomName: name}); + subTitle = _t("This room doesn't exist. Are you sure you're at the right place?"); break; } case MessageCase.OtherError: { + title = _t("%(roomName)s is not accessible at this time.", {roomName: name}); + subTitle = ([ +

{ _t("Try again later, or ask a room admin to check if you have access.") }

, +

{ _t("If you think you're seeing this message in error, please submit a bug report.", {}, { + issueLink: label => { label }, + }) }

, + ]); break; } } - let joinBlock; let previewBlock; + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - if (this.props.spinner || this.state.busy) { - let spinnerIntro = ""; - if (this.props.spinnerState === "joining") { - spinnerIntro = _t("Joining room..."); - } - return (
-

{ spinnerIntro }

- -
); - } - - const myMember = this.props.room ? - this.props.room.getMember(MatrixClientPeg.get().getUserId()) : - null; - const kicked = myMember && myMember.isKicked(); - const banned = myMember && myMember && myMember.membership == 'ban'; - - if (this.props.inviterName) { - let emailMatchBlock; - if (this.props.invitedEmail) { - if (this.state.threePidFetchError) { - emailMatchBlock =
- { _t("Unable to ascertain that the address this invite was sent to matches one associated with your account.") } -
; - } else if (this.state.invitedEmailMxid != MatrixClientPeg.get().credentials.userId) { - emailMatchBlock = -
-
- /!\\ -
-
- { _t("This invitation was sent to an email address which is not associated with this account:") } - { this.props.invitedEmail } -
- { _t("You may wish to login with a different account, or add this email to this account.") } -
-
; - } - } - joinBlock = ( -
-
- { _t('You have been invited to join this room by %(inviterName)s', {inviterName: this.props.inviterName}) } -
-
- { _t( - 'Would you like to accept or decline this invitation?', - {}, - { - 'acceptText': (sub) => { sub }, - 'declineText': (sub) => { sub }, - }, - ) } -
- { emailMatchBlock } -
- ); - } else if (kicked || banned) { - const roomName = this._roomNameElement(); - const kickerMember = this.props.room.currentState.getMember( - myMember.events.member.getSender(), - ); - const kickerName = kickerMember ? - kickerMember.name : myMember.events.member.getSender(); - let reason; - if (myMember.events.member.getContent().reason) { - reason =
{ _t("Reason: %(reasonText)s", {reasonText: myMember.events.member.getContent().reason}) }
; - } - let rejoinBlock; - if (!banned) { - rejoinBlock = ; - } - - let actionText; - if (kicked) { - if (roomName) { - actionText = _t("You have been kicked from %(roomName)s by %(userName)s.", {roomName: roomName, userName: kickerName}); - } else { - actionText = _t("You have been kicked from this room by %(userName)s.", {userName: kickerName}); - } - } else if (banned) { - if (roomName) { - actionText = _t("You have been banned from %(roomName)s by %(userName)s.", {roomName: roomName, userName: kickerName}); - } else { - actionText = _t("You have been banned from this room by %(userName)s.", {userName: kickerName}); - } - } // no other options possible due to the kicked || banned check above. - - joinBlock = ( -
-
- { actionText } -
- { reason } - { rejoinBlock } - { _t("Forget room") } -
-
- ); - } else if (this.props.error) { - const name = this.props.roomAlias || _t("This room"); - let error; - if (this.props.error.errcode == 'M_NOT_FOUND') { - error = _t("%(roomName)s does not exist.", {roomName: name}); + let subTitleElements; + if (subTitle) { + if (Array.isArray(subTitle)) { + subTitleElements = subTitle; } else { - error = _t("%(roomName)s is not accessible at this time.", {roomName: name}); + subTitleElements = [

{ subTitle }

]; } - joinBlock = ( -
-
- { error } -
-
- ); - } else { - const name = this._roomNameElement(); - joinBlock = ( -
-
- { name ? _t('You are trying to access %(roomName)s.', {roomName: name}) : _t('You are trying to access a room.') } -
- { _t("Click here to join the discussion!", - {}, - { 'a': (sub) => { sub } }, - ) } -
-
- ); - } - - if (this.props.canPreview) { - previewBlock = ( -
- { _t('This is a preview of this room. Room interactions have been disabled') }. -
- ); } const classes = classNames("mx_RoomPreviewBar", "dark-panel", { @@ -394,11 +280,17 @@ module.exports = React.createClass({ return (
-
- { joinBlock } - { previewBlock } +
+

{ title }

+ { subTitleElements } +
+
+ { secondaryActionHandler ? { secondaryActionLabel } : undefined } + { primaryActionHandler ? { primaryActionLabel } : undefined }
); + + }, }); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8e3f0d9f6e..a58601f319 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -789,25 +789,31 @@ "Low priority": "Low priority", "Historical": "Historical", "System Alerts": "System Alerts", - "Joining room...": "Joining room...", - "Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Unable to ascertain that the address this invite was sent to matches one associated with your account.", - "This invitation was sent to an email address which is not associated with this account:": "This invitation was sent to an email address which is not associated with this account:", - "You may wish to login with a different account, or add this email to this account.": "You may wish to login with a different account, or add this email to this account.", - "You have been invited to join this room by %(inviterName)s": "You have been invited to join this room by %(inviterName)s", - "Would you like to accept or decline this invitation?": "Would you like to accept or decline this invitation?", - "Reason: %(reasonText)s": "Reason: %(reasonText)s", - "Rejoin": "Rejoin", - "You have been kicked from %(roomName)s by %(userName)s.": "You have been kicked from %(roomName)s by %(userName)s.", - "You have been kicked from this room by %(userName)s.": "You have been kicked from this room by %(userName)s.", - "You have been banned from %(roomName)s by %(userName)s.": "You have been banned from %(roomName)s by %(userName)s.", - "You have been banned from this room by %(userName)s.": "You have been banned from this room by %(userName)s.", "This room": "This room", + "Joining room...": "Joining room...", + "In progress ...": "In progress ...", + "Join the conversation with an account": "Join the conversation with an account", + "Sign Up": "Sign Up", + "Sign In": "Sign In", + "You were kicked from this room by %(memberName)s": "You were kicked from this room by %(memberName)s", + "Reason: %(reason)s": "Reason: %(reason)s", + "Re-join": "Re-join", + "Forget this room": "Forget this room", + "You were banned from this room by %(memberName)s": "You were banned from this room by %(memberName)s", + "The room invite wasn't sent to your account": "The room invite wasn't sent to your account", + "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.": "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", + "%(memberName)s invited you to this room": "%(memberName)s invited you to this room", + "Do you want to join this room?": "Do you want to join this room?", + "%(memberName)s invited you": "%(memberName)s invited you", + "Reject": "Reject", + "You're previewing this room. Want to join it?": "You're previewing this room. Want to join it?", + "This room can't be previewed. Do you want to join it?": "This room can't be previewed. Do you want to join it?", + "Join the discussion": "Join the discussion", "%(roomName)s does not exist.": "%(roomName)s does not exist.", + "This room doesn't exist. Are you sure you're at the right place?": "This room doesn't exist. Are you sure you're at the right place?", "%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.", - "You are trying to access %(roomName)s.": "You are trying to access %(roomName)s.", - "You are trying to access a room.": "You are trying to access a room.", - "Click here to join the discussion!": "Click here to join the discussion!", - "This is a preview of this room. Room interactions have been disabled": "This is a preview of this room. Room interactions have been disabled", + "Try again later, or ask a room admin to check if you have access.": "Try again later, or ask a room admin to check if you have access.", + "If you think you're seeing this message in error, please submit a bug report.": "If you think you're seeing this message in error, please submit a bug report.", "Use Key Backup": "Use Key Backup", "Never lose encrypted messages": "Never lose encrypted messages", "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.", @@ -1242,7 +1248,6 @@ "Reject invitation": "Reject invitation", "Are you sure you want to reject the invitation?": "Are you sure you want to reject the invitation?", "Unable to reject invite": "Unable to reject invite", - "Reject": "Reject", "You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)", "Resend": "Resend", "Cancel Sending": "Cancel Sending", From 942669ae65215f4be3c34a675998fba616cdc9bf Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 15:16:50 +0200 Subject: [PATCH 07/32] look at join rules to see if join button should still be shown in some error cases --- src/components/views/rooms/RoomPreviewBar.js | 62 ++++++++++++++++---- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 850fb0d32d..0e2cc53f9b 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -157,13 +157,21 @@ module.exports = React.createClass({ return {memberName, reason}; }, - _roomNameElement: function() { - return this.props.room ? this.props.room.name : (this.props.room_alias || ""); + _joinRule: function() { + const room = this.props.room; + if (room) { + const joinRules = room.currentState.getStateEvents('m.room.join_rules', ''); + if (joinRules) { + return joinRules.getContent().join_rule; + } + } + }, + + _roomName: function() { + return this.props.room ? this.props.room.name : (this.props.room_alias || _t("This room")); }, render: function() { - const name = this.props.roomAlias || _t("This room"); - let showSpinner = false; let darkStyle = false; let title; @@ -212,13 +220,46 @@ module.exports = React.createClass({ break; } case MessageCase.OtherThreePIDError: { - // "Unable to ascertain that the address this invite was sent to matches one associated with your account." - // need to show invited by "name", join buttons here? + title = _t("Something went wrong with your invite to this room"); + const joinRule = this._joinRule(); + const errCodeMessage = _t("%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", {errcode: this.state.threePidFetchError.errcode}); + switch (joinRule) { + case "invite": + subTitle = [ +

{_t("Sadly, you can only join it with a working invite.")}

, +

{ errCodeMessage }

, + ]; + break; + case "public": + subTitle = _t("Luckily, you can still join it because this is a public room."); + primaryActionLabel = _t("Join the discussion"); + primaryActionHandler = this.props.onJoinClick; + break; + default: + subTitle = errCodeMessage; + primaryActionLabel = _t("Try to join anyway"); + primaryActionHandler = this.props.onJoinClick; + break; + } break; } case MessageCase.InvitedEmailMismatch: { title = _t("The room invite wasn't sent to your account"); - subTitle = _t("Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", {email: this.props.invitedEmail}); + const joinRule = this._joinRule(); + switch (joinRule) { + case "public": + subTitle = _t("Luckily, you can still join it because this is a public room."); + primaryActionLabel = _t("Join the discussion"); + primaryActionHandler = this.props.onJoinClick; + break; + default: + subTitle = _t("Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", {email: this.props.invitedEmail}); + if (joinRule !== "invite") { + primaryActionLabel = _t("Try to join anyway"); + primaryActionHandler = this.props.onJoinClick; + } + break; + } break; } case MessageCase.Invite: { @@ -245,15 +286,16 @@ module.exports = React.createClass({ break; } case MessageCase.RoomNotFound: { - title = _t("%(roomName)s does not exist.", {roomName: name}); + title = _t("%(roomName)s does not exist.", {roomName: this._roomName()}); subTitle = _t("This room doesn't exist. Are you sure you're at the right place?"); break; } case MessageCase.OtherError: { - title = _t("%(roomName)s is not accessible at this time.", {roomName: name}); + title = _t("%(roomName)s is not accessible at this time.", {roomName: this._roomName()}); subTitle = ([

{ _t("Try again later, or ask a room admin to check if you have access.") }

, -

{ _t("If you think you're seeing this message in error, please submit a bug report.", {}, { +

{ _t("%(errcode)s was returned when trying to access the room.", {errcode: this.props.error.errcode}) }

, +

{ _t("If you think you're seeing this message in error, please submit a bug report.", {}, { issueLink: label => { label }, }) }

, From 1b2fba3fe234fc0e517788b7a4ffb543f4719c64 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 15:22:08 +0200 Subject: [PATCH 08/32] move p tags for subtitles out of switch --- src/components/views/rooms/RoomPreviewBar.js | 40 +++++++++----------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 0e2cc53f9b..2f22ff1513 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -226,8 +226,8 @@ module.exports = React.createClass({ switch (joinRule) { case "invite": subTitle = [ -

{_t("Sadly, you can only join it with a working invite.")}

, -

{ errCodeMessage }

, + _t("Sadly, you can only join it with a working invite."), + errCodeMessage, ]; break; case "public": @@ -246,19 +246,16 @@ module.exports = React.createClass({ case MessageCase.InvitedEmailMismatch: { title = _t("The room invite wasn't sent to your account"); const joinRule = this._joinRule(); - switch (joinRule) { - case "public": - subTitle = _t("Luckily, you can still join it because this is a public room."); - primaryActionLabel = _t("Join the discussion"); + if (joinRule === "public") { + subTitle = _t("Luckily, you can still join it because this is a public room."); + primaryActionLabel = _t("Join the discussion"); + primaryActionHandler = this.props.onJoinClick; + } else { + subTitle = _t("Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", {email: this.props.invitedEmail}); + if (joinRule !== "invite") { + primaryActionLabel = _t("Try to join anyway"); primaryActionHandler = this.props.onJoinClick; - break; - default: - subTitle = _t("Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", {email: this.props.invitedEmail}); - if (joinRule !== "invite") { - primaryActionLabel = _t("Try to join anyway"); - primaryActionHandler = this.props.onJoinClick; - } - break; + } } break; } @@ -293,12 +290,12 @@ module.exports = React.createClass({ case MessageCase.OtherError: { title = _t("%(roomName)s is not accessible at this time.", {roomName: this._roomName()}); subTitle = ([ -

{ _t("Try again later, or ask a room admin to check if you have access.") }

, -

{ _t("%(errcode)s was returned when trying to access the room.", {errcode: this.props.error.errcode}) }

, -

{ _t("If you think you're seeing this message in error, please submit a bug report.", {}, { + _t("Try again later, or ask a room admin to check if you have access."), + _t("%(errcode)s was returned when trying to access the room.", {errcode: this.props.error.errcode}), + _t("If you think you're seeing this message in error, please submit a bug report.", {}, { issueLink: label => { label }, - }) }

, + }), ]); break; } @@ -308,11 +305,10 @@ module.exports = React.createClass({ let subTitleElements; if (subTitle) { - if (Array.isArray(subTitle)) { - subTitleElements = subTitle; - } else { - subTitleElements = [

{ subTitle }

]; + if (!Array.isArray(subTitle)) { + subTitle = [subTitle]; } + subTitleElements = subTitle.map((t, i) =>

{t}

); } const classes = classNames("mx_RoomPreviewBar", "dark-panel", { From 6bc659c93b6f4ce1fa6140ea381d14f744698466 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 15:25:34 +0200 Subject: [PATCH 09/32] layout for error codes --- src/components/views/rooms/RoomPreviewBar.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 2f22ff1513..883bdb3be8 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -222,7 +222,10 @@ module.exports = React.createClass({ case MessageCase.OtherThreePIDError: { title = _t("Something went wrong with your invite to this room"); const joinRule = this._joinRule(); - const errCodeMessage = _t("%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", {errcode: this.state.threePidFetchError.errcode}); + const errCodeMessage = _t("%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", + {errcode: this.state.threePidFetchError.errcode}, + {code: label => {label}} + ); switch (joinRule) { case "invite": subTitle = [ @@ -291,10 +294,11 @@ module.exports = React.createClass({ title = _t("%(roomName)s is not accessible at this time.", {roomName: this._roomName()}); subTitle = ([ _t("Try again later, or ask a room admin to check if you have access."), - _t("%(errcode)s was returned when trying to access the room.", {errcode: this.props.error.errcode}), + _t("%(errcode)s was returned while trying to access the room.", {errcode: this.props.error.errcode}), _t("If you think you're seeing this message in error, please submit a bug report.", {}, { issueLink: label => { label }, + code: label => {label}, }), ]); break; From 1d0c40209395176cf1297cce9d2a415b94db5615 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 17:11:17 +0200 Subject: [PATCH 10/32] improve error messages, etc --- src/components/views/rooms/RoomPreviewBar.js | 36 ++++++++++++-------- src/i18n/strings/en_EN.json | 9 +++-- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 883bdb3be8..b21f1a503d 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -77,7 +77,6 @@ module.exports = React.createClass({ getDefaultProps: function() { return { onJoinClick: function() {}, - canPreview: true, }; }, @@ -222,19 +221,18 @@ module.exports = React.createClass({ case MessageCase.OtherThreePIDError: { title = _t("Something went wrong with your invite to this room"); const joinRule = this._joinRule(); - const errCodeMessage = _t("%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", + const errCodeMessage = _t("%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", {errcode: this.state.threePidFetchError.errcode}, - {code: label => {label}} ); switch (joinRule) { case "invite": subTitle = [ - _t("Sadly, you can only join it with a working invite."), + _t("You can only join it with a working invite."), errCodeMessage, ]; break; case "public": - subTitle = _t("Luckily, you can still join it because this is a public room."); + subTitle = _t("You can still join it because this is a public room."); primaryActionLabel = _t("Join the discussion"); primaryActionHandler = this.props.onJoinClick; break; @@ -250,7 +248,7 @@ module.exports = React.createClass({ title = _t("The room invite wasn't sent to your account"); const joinRule = this._joinRule(); if (joinRule === "public") { - subTitle = _t("Luckily, you can still join it because this is a public room."); + subTitle = _t("You can still join it because this is a public room."); primaryActionLabel = _t("Join the discussion"); primaryActionHandler = this.props.onJoinClick; } else { @@ -292,20 +290,20 @@ module.exports = React.createClass({ } case MessageCase.OtherError: { title = _t("%(roomName)s is not accessible at this time.", {roomName: this._roomName()}); - subTitle = ([ + subTitle = [ _t("Try again later, or ask a room admin to check if you have access."), - _t("%(errcode)s was returned while trying to access the room.", {errcode: this.props.error.errcode}), - _t("If you think you're seeing this message in error, please submit a bug report.", {}, { - issueLink: label => { label }, - code: label => {label}, - }), - ]); + _t("%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.", + { errcode: this.props.error.errcode }, + { issueLink: label => { label } } + ), + ]; break; } } const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const Spinner = sdk.getComponent('elements.Spinner'); let subTitleElements; if (subTitle) { @@ -318,12 +316,20 @@ module.exports = React.createClass({ const classes = classNames("mx_RoomPreviewBar", "dark-panel", { "mx_RoomPreviewBar_panel": this.props.canPreview, "mx_RoomPreviewBar_dialog": !this.props.canPreview, + "mx_RoomPreviewBar_dark": darkStyle, }); + let titleElement; + if (showSpinner) { + titleElement =

{ title }

; + } else { + titleElement =

{ title }

; + } + return (
-

{ title }

+ { titleElement } { subTitleElements }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a58601f319..1b6228f949 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -800,6 +800,12 @@ "Re-join": "Re-join", "Forget this room": "Forget this room", "You were banned from this room by %(memberName)s": "You were banned from this room by %(memberName)s", + "Something went wrong with your invite to this room": "Something went wrong with your invite to this room", + "%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.": "%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", + "You can only join it with a working invite.": "You can only join it with a working invite.", + "You can still join it because this is a public room.": "You can still join it because this is a public room.", + "Join the discussion": "Join the discussion", + "Try to join anyway": "Try to join anyway", "The room invite wasn't sent to your account": "The room invite wasn't sent to your account", "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.": "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", "%(memberName)s invited you to this room": "%(memberName)s invited you to this room", @@ -808,12 +814,11 @@ "Reject": "Reject", "You're previewing this room. Want to join it?": "You're previewing this room. Want to join it?", "This room can't be previewed. Do you want to join it?": "This room can't be previewed. Do you want to join it?", - "Join the discussion": "Join the discussion", "%(roomName)s does not exist.": "%(roomName)s does not exist.", "This room doesn't exist. Are you sure you're at the right place?": "This room doesn't exist. Are you sure you're at the right place?", "%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.", "Try again later, or ask a room admin to check if you have access.": "Try again later, or ask a room admin to check if you have access.", - "If you think you're seeing this message in error, please submit a bug report.": "If you think you're seeing this message in error, please submit a bug report.", + "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.": "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.", "Use Key Backup": "Use Key Backup", "Never lose encrypted messages": "Never lose encrypted messages", "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.", From c1ff5f2fba73a90d8b5be868bd2c55df559f8abc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 17:11:26 +0200 Subject: [PATCH 11/32] implement style --- res/css/views/elements/_AccessibleButton.scss | 6 + res/css/views/rooms/_RoomPreviewBar.scss | 104 +++++++++++++----- 2 files changed, 82 insertions(+), 28 deletions(-) diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index 25ad51a3fb..fe1f283009 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -37,6 +37,12 @@ limitations under the License. .mx_AccessibleButton_kind_primary { color: $button-primary-fg-color; background-color: $button-primary-bg-color; + font-weight: 600; +} + +.mx_AccessibleButton_kind_secondary { + color: $accent-color; + font-weight: 600; } .mx_AccessibleButton_kind_primary.mx_AccessibleButton_disabled { diff --git a/res/css/views/rooms/_RoomPreviewBar.scss b/res/css/views/rooms/_RoomPreviewBar.scss index e62f488bfa..914fcbbb1a 100644 --- a/res/css/views/rooms/_RoomPreviewBar.scss +++ b/res/css/views/rooms/_RoomPreviewBar.scss @@ -16,46 +16,94 @@ limitations under the License. .mx_RoomPreviewBar { flex: 0 0 auto; - margin: 15px; - padding: 10px; - border-radius: 4px; - border: 1px solid $panel-divider-color; text-align: center; align-items: center; flex-direction: column; justify-content: center; display: flex; -webkit-align-items: center; + + h3 { + font-size: 18px; + font-weight: 600; + + &.mx_RoomPreviewBar_spinnerTitle { + display: flex; + flex-direction: row; + align-items: center; + } + } + + .mx_Spinner { + width: auto; + height: auto; + margin: 10px 10px 10px 0; + } +} + +.mx_RoomPreviewBar_dark { + background-color: $tagpanel-bg-color; + color: $accent-fg-color; +} + +.mx_RoomPreviewBar_actions { + display: flex; +} + +.mx_RoomPreviewBar_message { + display: flex; +} + +.mx_RoomPreviewBar_panel { + padding: 8px 8px 8px 20px; + border-top: 1px solid $panel-divider-color; + + flex-direction: row; + + .mx_RoomPreviewBar_actions { + flex: 0 0 auto; + flex-direction: row; + padding: 3px 8px; + + &>* { + margin-left: 12px; + } + } + + .mx_RoomPreviewBar_message { + flex: 1 0 0; + min-width: 0; + display: flex; + flex-direction: column; + align-items: start; + + &>* { + margin: 4px; + } + } } .mx_RoomPreviewBar_dialog { margin: auto; -} + box-sizing: content; + width: 400px; + border-radius: 4px; + flex-direction: column; + padding: 20px; -.mx_RoomPreviewBar_join_text { - color: $warning-color; -} + .mx_RoomPreviewBar_message { + flex-direction: column; -.mx_RoomPreviewBar_preview_text { - margin-top: 25px; - color: $settings-grey-fg-color; -} + &>* { + margin: 10px; + } + } -.mx_RoomPreviewBar_join_text a { - text-decoration: underline; - cursor: pointer; -} + .mx_RoomPreviewBar_actions { + flex-direction: column-reverse; -.mx_RoomPreviewBar_warning { - display: flex; - align-items: center; - padding: 8px; -} - -.mx_RoomPreviewBar_warningIcon { - padding: 12px; -} - -.mx_RoomPreviewBar_spinnerIntro { - margin-top: 50px; + &>* { + margin-top: 12px; + } + } } From fd6c594a8f4b9df96ddb89b86a61ba341197a9d7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 17:52:17 +0200 Subject: [PATCH 12/32] put auth buttons in preview bar --- src/components/structures/RoomView.js | 5 -- src/components/views/auth/AuthButtons.js | 57 -------------------- src/components/views/rooms/RoomPreviewBar.js | 27 +++++++--- 3 files changed, 19 insertions(+), 70 deletions(-) delete mode 100644 src/components/views/auth/AuthButtons.js diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 3ff72b4e5b..44ab922df4 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1714,11 +1714,6 @@ module.exports = React.createClass({ />; } - if (MatrixClientPeg.get().isGuest()) { - const AuthButtons = sdk.getComponent('views.auth.AuthButtons'); - messageComposer = ; - } - // TODO: Why aren't we storing the term/scope/count in this format // in this.state if this is what RoomHeader desires? if (this.state.searchResults) { diff --git a/src/components/views/auth/AuthButtons.js b/src/components/views/auth/AuthButtons.js deleted file mode 100644 index 35bfabbbca..0000000000 --- a/src/components/views/auth/AuthButtons.js +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd -Copyright 2018, 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. -*/ - -'use strict'; - -const React = require('react'); -import { _t } from '../../../languageHandler'; -const dis = require('../../../dispatcher'); -const AccessibleButton = require('../elements/AccessibleButton'); - -module.exports = React.createClass({ - displayName: 'AuthButtons', - - propTypes: { - }, - - onLoginClick: function() { - dis.dispatch({ action: 'start_login' }); - }, - - onRegisterClick: function() { - dis.dispatch({ action: 'start_registration' }); - }, - - render: function() { - const loginButton = ( -
- - { _t("Login") } - - - { _t("Register") } - -
- ); - - return ( -
- { loginButton } -
- ); - }, -}); diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index b21f1a503d..b4737cab42 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -17,12 +17,12 @@ limitations under the License. 'use strict'; -const React = require('react'); +import React from 'react'; import PropTypes from 'prop-types'; -const sdk = require('../../../index'); -const MatrixClientPeg = require('../../../MatrixClientPeg'); +import sdk from '../../../index'; +import MatrixClientPeg from '../../../MatrixClientPeg'; +import dis from '../../../dispatcher'; import classNames from 'classnames'; - import { _t } from '../../../languageHandler'; const MessageCase = Object.freeze({ @@ -112,11 +112,14 @@ module.exports = React.createClass({ return MessageCase.Busy; } } - const myMember = this.props.room ? + const isGuest = MatrixClientPeg.get().isGuest(); + const myMember = !isGuest && this.props.room ? this.props.room.getMember(MatrixClientPeg.get().getUserId()) : null; - if (this.props.inviterName) { + if (isGuest) { + return MessageCase.NotLoggedIn; + } else if (this.props.inviterName) { if (this.props.invitedEmail) { if (this.state.threePidFetchError) { return MessageCase.OtherThreePIDError; @@ -170,6 +173,14 @@ module.exports = React.createClass({ return this.props.room ? this.props.room.name : (this.props.room_alias || _t("This room")); }, + onLoginClick: function() { + dis.dispatch({ action: 'start_login' }); + }, + + onRegisterClick: function() { + dis.dispatch({ action: 'start_registration' }); + }, + render: function() { let showSpinner = false; let darkStyle = false; @@ -195,9 +206,9 @@ module.exports = React.createClass({ darkStyle = true; title = _t("Join the conversation with an account"); primaryActionLabel = _t("Sign Up"); - primaryActionHandler = this.props.onSignUpClick; + primaryActionHandler = this.onRegisterClick; secondaryActionLabel = _t("Sign In"); - secondaryActionHandler = this.props.onSignInClick; + secondaryActionHandler = this.onLoginClick; break; } case MessageCase.Kicked: { From 7459e19f061cbbec6497a37975cf452097b1b714 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 17:56:36 +0200 Subject: [PATCH 13/32] fix lint --- src/components/views/rooms/RoomPreviewBar.js | 38 ++++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index b4737cab42..242e99896a 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -306,7 +306,7 @@ module.exports = React.createClass({ _t("%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.", { errcode: this.props.error.errcode }, { issueLink: label => { label } } + target="_blank" rel="noopener">{ label } }, ), ]; break; @@ -324,12 +324,6 @@ module.exports = React.createClass({ subTitleElements = subTitle.map((t, i) =>

{t}

); } - const classes = classNames("mx_RoomPreviewBar", "dark-panel", { - "mx_RoomPreviewBar_panel": this.props.canPreview, - "mx_RoomPreviewBar_dialog": !this.props.canPreview, - "mx_RoomPreviewBar_dark": darkStyle, - }); - let titleElement; if (showSpinner) { titleElement =

{ title }

; @@ -337,6 +331,30 @@ module.exports = React.createClass({ titleElement =

{ title }

; } + let primaryButton; + if (primaryActionHandler) { + primaryButton = ( + + { primaryActionLabel } + + ); + } + + let secondaryButton; + if (secondaryActionHandler) { + secondaryButton = ( + + { secondaryActionLabel } + + ); + } + + const classes = classNames("mx_RoomPreviewBar", "dark-panel", { + "mx_RoomPreviewBar_panel": this.props.canPreview, + "mx_RoomPreviewBar_dialog": !this.props.canPreview, + "mx_RoomPreviewBar_dark": darkStyle, + }); + return (
@@ -344,12 +362,10 @@ module.exports = React.createClass({ { subTitleElements }
- { secondaryActionHandler ? { secondaryActionLabel } : undefined } - { primaryActionHandler ? { primaryActionLabel } : undefined } + { secondaryButton } + { primaryButton }
); - - }, }); From 36951dd7b7806684661be4677eac5938928565a9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 15 Apr 2019 18:49:00 +0200 Subject: [PATCH 14/32] cleanup spinner props and use always preview bar when room operation is in progress --- src/components/structures/RoomView.js | 29 ++++++++++++-------- src/components/views/rooms/RoomPreviewBar.js | 26 +++++++++++------- src/i18n/strings/en_EN.json | 6 ++-- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 44ab922df4..85bfd10bcc 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1496,16 +1496,21 @@ module.exports = React.createClass({ const ScrollPanel = sdk.getComponent("structures.ScrollPanel"); const TintableSvg = sdk.getComponent("elements.TintableSvg"); const RoomPreviewBar = sdk.getComponent("rooms.RoomPreviewBar"); - const Loader = sdk.getComponent("elements.Spinner"); const TimelinePanel = sdk.getComponent("structures.TimelinePanel"); const RoomUpgradeWarningBar = sdk.getComponent("rooms.RoomUpgradeWarningBar"); const RoomRecoveryReminder = sdk.getComponent("rooms.RoomRecoveryReminder"); if (!this.state.room) { - if (this.state.roomLoading || this.state.peekLoading) { + const loading = this.state.roomLoading || this.state.peekLoading; + if (loading) { return (
- +
); } else { @@ -1528,8 +1533,7 @@ module.exports = React.createClass({ onRejectClick={this.onRejectThreepidInviteButtonClicked} canPreview={false} error={this.state.roomLoadError} roomAlias={roomAlias} - spinner={this.state.joining} - spinnerState="joining" + joining={this.state.joining} inviterName={inviterName} invitedEmail={invitedEmail} room={this.state.room} @@ -1543,9 +1547,12 @@ module.exports = React.createClass({ if (myMembership == 'invite') { if (this.state.joining || this.state.rejecting) { return ( -
- -
+ ); } else { const myUserId = MatrixClientPeg.get().credentials.userId; @@ -1565,8 +1572,7 @@ module.exports = React.createClass({ onRejectClick={this.onRejectButtonClicked} inviterName={inviterName} canPreview={false} - spinner={this.state.joining} - spinnerState="joining" + joining={this.state.joining} room={this.state.room} />
@@ -1656,8 +1662,7 @@ module.exports = React.createClass({ Date: Tue, 16 Apr 2019 16:19:50 +0200 Subject: [PATCH 15/32] make sure long subtitles dont overflow --- res/css/views/rooms/_RoomPreviewBar.scss | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/res/css/views/rooms/_RoomPreviewBar.scss b/res/css/views/rooms/_RoomPreviewBar.scss index 914fcbbb1a..a119ada0dc 100644 --- a/res/css/views/rooms/_RoomPreviewBar.scss +++ b/res/css/views/rooms/_RoomPreviewBar.scss @@ -16,7 +16,6 @@ limitations under the License. .mx_RoomPreviewBar { flex: 0 0 auto; - text-align: center; align-items: center; flex-direction: column; justify-content: center; @@ -38,6 +37,7 @@ limitations under the License. width: auto; height: auto; margin: 10px 10px 10px 0; + flex: 0 0 auto; } } @@ -52,6 +52,11 @@ limitations under the License. .mx_RoomPreviewBar_message { display: flex; + align-items: stretch; + + p { + overflow-wrap: break-word; + } } .mx_RoomPreviewBar_panel { @@ -75,7 +80,6 @@ limitations under the License. min-width: 0; display: flex; flex-direction: column; - align-items: start; &>* { margin: 4px; @@ -90,6 +94,7 @@ limitations under the License. border-radius: 4px; flex-direction: column; padding: 20px; + text-align: center; .mx_RoomPreviewBar_message { flex-direction: column; From 523311b50c631d1d9ef58427b6db133cd5a97698 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 16 Apr 2019 17:23:01 +0200 Subject: [PATCH 16/32] saner order for message case detection (can't be joining when kicked) --- src/components/views/rooms/RoomPreviewBar.js | 29 ++++++++++++-------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index dfa4d2fa31..189df5e696 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -106,6 +106,23 @@ module.exports = React.createClass({ }, _getMessageCase() { + const isGuest = MatrixClientPeg.get().isGuest(); + + if (isGuest) { + return MessageCase.NotLoggedIn; + } + + const myMember = this.props.room && + this.props.room.getMember(MatrixClientPeg.get().getUserId()); + + if (myMember) { + if (myMember.isKicked()) { + return MessageCase.Kicked; + } else if (myMember.membership === "ban") { + return MessageCase.Banned; + } + } + if (this.props.joining) { return MessageCase.Joining; } else if (this.props.rejecting) { @@ -113,14 +130,8 @@ module.exports = React.createClass({ } else if (this.props.loading) { return MessageCase.Loading; } - const isGuest = MatrixClientPeg.get().isGuest(); - const myMember = !isGuest && this.props.room ? - this.props.room.getMember(MatrixClientPeg.get().getUserId()) : - null; - if (isGuest) { - return MessageCase.NotLoggedIn; - } else if (this.props.inviterName) { + if (this.props.inviterName) { if (this.props.invitedEmail) { if (this.state.threePidFetchError) { return MessageCase.OtherThreePIDError; @@ -129,10 +140,6 @@ module.exports = React.createClass({ } } return MessageCase.Invite; - } else if (myMember && myMember.isKicked()) { - return MessageCase.Kicked; - } else if (myMember && myMember && myMember.membership == 'ban') { - return MessageCase.Banned; } else if (this.props.error) { if (this.props.error.errcode == 'M_NOT_FOUND') { return MessageCase.RoomNotFound; From dbb73439e44ee943b62fda3df3696866af09cba1 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 16 Apr 2019 17:23:24 +0200 Subject: [PATCH 17/32] also return Joining when internally busy looking something up --- src/components/views/rooms/RoomPreviewBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 189df5e696..cba33a3b0e 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -127,7 +127,7 @@ module.exports = React.createClass({ return MessageCase.Joining; } else if (this.props.rejecting) { return MessageCase.Rejecting; - } else if (this.props.loading) { + } else if (this.props.loading || this.state.busy) { return MessageCase.Loading; } From eeb9b4b2e3afe6b99c448cf729ecd795884a9243 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 16 Apr 2019 17:23:45 +0200 Subject: [PATCH 18/32] don't show re-join upon kicked when we know you can't --- src/components/views/rooms/RoomPreviewBar.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index cba33a3b0e..47dbd0c178 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -228,10 +228,16 @@ module.exports = React.createClass({ const {memberName, reason} = this._getKickOrBanInfo(); title = _t("You were kicked from this room by %(memberName)s", {memberName}); subTitle = _t("Reason: %(reason)s", {reason}); - primaryActionLabel = _t("Re-join"); - primaryActionHandler = this.props.onJoinClick; - secondaryActionLabel = _t("Forget this room"); - secondaryActionHandler = this.props.onForgetClick; + + if (this._joinRule() === "invite") { + primaryActionLabel = _t("Forget this room"); + primaryActionHandler = this.props.onForgetClick; + } else { + primaryActionLabel = _t("Re-join"); + primaryActionHandler = this.props.onJoinClick; + secondaryActionLabel = _t("Forget this room"); + secondaryActionHandler = this.props.onForgetClick; + } break; } case MessageCase.Banned: { From f9a2b76966e2f7762840d8bef87269ccaef41e56 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 16 Apr 2019 17:50:20 +0200 Subject: [PATCH 19/32] show room name where available when header isn't visible (no preview) --- src/components/views/rooms/RoomPreviewBar.js | 24 ++++++++++++++------ src/i18n/strings/en_EN.json | 9 ++++---- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 47dbd0c178..a9805f9f18 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -177,8 +177,15 @@ module.exports = React.createClass({ } }, - _roomName: function() { - return this.props.room ? this.props.room.name : (this.props.room_alias || _t("This room")); + _roomName: function(atStart = false) { + const name = this.props.room ? this.props.room.name : this.props.room_alias; + if (name) { + return name; + } else if (atStart) { + return _t("This room"); + } else { + return _t("this room"); + } }, onLoginClick: function() { @@ -226,7 +233,8 @@ module.exports = React.createClass({ } case MessageCase.Kicked: { const {memberName, reason} = this._getKickOrBanInfo(); - title = _t("You were kicked from this room by %(memberName)s", {memberName}); + title = _t("You were kicked from %(roomName)s by %(memberName)s", + {memberName, roomName: this._roomName()}); subTitle = _t("Reason: %(reason)s", {reason}); if (this._joinRule() === "invite") { @@ -242,7 +250,8 @@ module.exports = React.createClass({ } case MessageCase.Banned: { const {memberName, reason} = this._getKickOrBanInfo(); - title = _t("You were banned from this room by %(memberName)s", {memberName}); + title = _t("You were banned from %(roomName)s by %(memberName)s", + {memberName, roomName: this._roomName()}); subTitle = _t("Reason: %(reason)s", {reason}); primaryActionLabel = _t("Forget this room"); primaryActionHandler = this.props.onForgetClick; @@ -307,19 +316,20 @@ module.exports = React.createClass({ if (this.props.canPreview) { title = _t("You're previewing this room. Want to join it?"); } else { - title = _t("This room can't be previewed. Do you want to join it?"); + title = _t("%(roomName)s can't be previewed. Do you want to join it?", + {roomName: this._roomName(true)}); } primaryActionLabel = _t("Join the discussion"); primaryActionHandler = this.props.onJoinClick; break; } case MessageCase.RoomNotFound: { - title = _t("%(roomName)s does not exist.", {roomName: this._roomName()}); + title = _t("%(roomName)s does not exist.", {roomName: this._roomName(true)}); subTitle = _t("This room doesn't exist. Are you sure you're at the right place?"); break; } case MessageCase.OtherError: { - title = _t("%(roomName)s is not accessible at this time.", {roomName: this._roomName()}); + title = _t("%(roomName)s is not accessible at this time.", {roomName: this._roomName(true)}); subTitle = [ _t("Try again later, or ask a room admin to check if you have access."), _t("%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.", diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2686012029..c156da40bc 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -790,17 +790,18 @@ "Historical": "Historical", "System Alerts": "System Alerts", "This room": "This room", + "this room": "this room", "Joining room …": "Joining room …", "Loading …": "Loading …", "Rejecting invite …": "Rejecting invite …", "Join the conversation with an account": "Join the conversation with an account", "Sign Up": "Sign Up", "Sign In": "Sign In", - "You were kicked from this room by %(memberName)s": "You were kicked from this room by %(memberName)s", + "You were kicked from %(roomName)s by %(memberName)s": "You were kicked from %(roomName)s by %(memberName)s", "Reason: %(reason)s": "Reason: %(reason)s", - "Re-join": "Re-join", "Forget this room": "Forget this room", - "You were banned from this room by %(memberName)s": "You were banned from this room by %(memberName)s", + "Re-join": "Re-join", + "You were banned from %(roomName)s by %(memberName)s": "You were banned from %(roomName)s by %(memberName)s", "Something went wrong with your invite to this room": "Something went wrong with your invite to this room", "%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.": "%(errcode)s was returned while trying to valide your invite. You could try to pass this information on to a room admin.", "You can only join it with a working invite.": "You can only join it with a working invite.", @@ -814,7 +815,7 @@ "%(memberName)s invited you": "%(memberName)s invited you", "Reject": "Reject", "You're previewing this room. Want to join it?": "You're previewing this room. Want to join it?", - "This room can't be previewed. Do you want to join it?": "This room can't be previewed. Do you want to join it?", + "%(roomName)s can't be previewed. Do you want to join it?": "%(roomName)s can't be previewed. Do you want to join it?", "%(roomName)s does not exist.": "%(roomName)s does not exist.", "This room doesn't exist. Are you sure you're at the right place?": "This room doesn't exist. Are you sure you're at the right place?", "%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.", From 56ade1ead56d55da3cd075c83ac76d210aa67e0d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 16 Apr 2019 18:48:47 +0200 Subject: [PATCH 20/32] WIP on showing inviter avatar --- src/components/views/rooms/RoomPreviewBar.js | 32 ++++++++++++++++++-- src/i18n/strings/en_EN.json | 4 +-- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index a9805f9f18..0fb66abc00 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -135,7 +135,7 @@ module.exports = React.createClass({ if (this.props.invitedEmail) { if (this.state.threePidFetchError) { return MessageCase.OtherThreePIDError; - } else if (this.state.invitedEmailMxid != MatrixClientPeg.get().credentials.userId) { + } else if (this.state.invitedEmailMxid != MatrixClientPeg.get().getUserId()) { return MessageCase.InvitedEmailMismatch; } } @@ -188,6 +188,20 @@ module.exports = React.createClass({ } }, + _getInviteMember: function() { + const {room} = this.props; + if (!room) { + return; + } + const myUserId = MatrixClientPeg.get().getUserId(); + const inviteEvent = room.currentState.getMember(myUserId); + if (!inviteEvent) { + return; + } + const inviterUserId = inviteEvent.events.member.getSender(); + return room.currentState.getMember(inviterUserId); + }, + onLoginClick: function() { dis.dispatch({ action: 'start_login' }); }, @@ -300,12 +314,24 @@ module.exports = React.createClass({ break; } case MessageCase.Invite: { + const inviteMember = this._getInviteMember(); + let avatar; + let memberName; + if (inviteMember) { + const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar"); + avatar = (); + memberName = inviteMember.name; + } else { + memberName = this.props.inviterName; + } + if (this.props.canPreview) { - title = _t("%(memberName)s invited you to this room", {memberName: this.props.inviterName}); + title = {avatar}{_t(" invited you to this room", {}, {userName: name => {memberName}})}; } else { title = _t("Do you want to join this room?"); - subTitle = _t("%(memberName)s invited you", {memberName: this.props.inviterName}); + subTitle = {avatar}{_t(" invited you", {}, {userName: name => {memberName}})}; } + primaryActionLabel = _t("Accept"); primaryActionHandler = this.props.onJoinClick; secondaryActionLabel = _t("Reject"); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c156da40bc..5b80ae731d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -810,9 +810,9 @@ "Try to join anyway": "Try to join anyway", "The room invite wasn't sent to your account": "The room invite wasn't sent to your account", "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.": "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", - "%(memberName)s invited you to this room": "%(memberName)s invited you to this room", + " invited you to this room": " invited you to this room", "Do you want to join this room?": "Do you want to join this room?", - "%(memberName)s invited you": "%(memberName)s invited you", + " invited you": " invited you", "Reject": "Reject", "You're previewing this room. Want to join it?": "You're previewing this room. Want to join it?", "%(roomName)s can't be previewed. Do you want to join it?": "%(roomName)s can't be previewed. Do you want to join it?", From eeaa7143acecc34ae1938f7e60ff91d7ecf93fdb Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 10:21:30 +0200 Subject: [PATCH 21/32] move name coloring out of sender profile so we can reuse it in room preview bar --- res/css/_common.scss | 35 +++++++++++++++++++ res/css/views/messages/_SenderProfile.scss | 33 ----------------- .../views/messages/SenderProfile.js | 6 ++-- src/utils/FormattingUtils.js | 5 +++ 4 files changed, 43 insertions(+), 36 deletions(-) diff --git a/res/css/_common.scss b/res/css/_common.scss index 4a9c2945f5..9ed5c65d4a 100644 --- a/res/css/_common.scss +++ b/res/css/_common.scss @@ -517,3 +517,38 @@ textarea { opacity: 0; cursor: pointer; } + +// username colors +// used by SenderProfile & RoomPreviewBar +.mx_Username_color1 { + color: $username-variant1-color; +} + +.mx_Username_color2 { + color: $username-variant2-color; +} + +.mx_Username_color3 { + color: $username-variant3-color; +} + +.mx_Username_color4 { + color: $username-variant4-color; +} + +.mx_Username_color5 { + color: $username-variant5-color; +} + +.mx_Username_color6 { + color: $username-variant6-color; +} + +.mx_Username_color7 { + color: $username-variant7-color; +} + +.mx_Username_color8 { + color: $username-variant8-color; +} + diff --git a/res/css/views/messages/_SenderProfile.scss b/res/css/views/messages/_SenderProfile.scss index a4a2aba11f..655cb39489 100644 --- a/res/css/views/messages/_SenderProfile.scss +++ b/res/css/views/messages/_SenderProfile.scss @@ -18,36 +18,3 @@ limitations under the License. font-weight: 600; } -.mx_SenderProfile_color1 { - color: $username-variant1-color; -} - -.mx_SenderProfile_color2 { - color: $username-variant2-color; -} - -.mx_SenderProfile_color3 { - color: $username-variant3-color; -} - -.mx_SenderProfile_color4 { - color: $username-variant4-color; -} - -.mx_SenderProfile_color5 { - color: $username-variant5-color; -} - -.mx_SenderProfile_color6 { - color: $username-variant6-color; -} - -.mx_SenderProfile_color7 { - color: $username-variant7-color; -} - -.mx_SenderProfile_color8 { - color: $username-variant8-color; -} - - diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.js index 0d47de4266..75898736f1 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -23,7 +23,7 @@ import sdk from '../../../index'; import Flair from '../elements/Flair.js'; import FlairStore from '../../../stores/FlairStore'; import { _t } from '../../../languageHandler'; -import {hashCode} from '../../../utils/FormattingUtils'; +import {getUserNameColorClass} from '../../../utils/FormattingUtils'; export default React.createClass({ displayName: 'SenderProfile', @@ -97,7 +97,7 @@ export default React.createClass({ render() { const EmojiText = sdk.getComponent('elements.EmojiText'); const {mxEvent} = this.props; - const colorNumber = (hashCode(mxEvent.getSender()) % 8) + 1; + const colorClass = getUserNameColorClass(mxEvent.getSender()); const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); const {msgtype} = mxEvent.getContent(); @@ -121,7 +121,7 @@ export default React.createClass({ // Name + flair const nameFlair = - + { nameElem } { flair } diff --git a/src/utils/FormattingUtils.js b/src/utils/FormattingUtils.js index 435b33ac5d..b461d22079 100644 --- a/src/utils/FormattingUtils.js +++ b/src/utils/FormattingUtils.js @@ -58,3 +58,8 @@ export function hashCode(str) { } return Math.abs(hash); } + +export function getUserNameColorClass(userId) { + const colorNumber = (hashCode(userId) % 8) + 1; + return `mx_Username_color${colorNumber}`; +} From 8a371080d74c742b7eacc489080da2ca6049b42e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 10:22:35 +0200 Subject: [PATCH 22/32] colored inviter name and layout --- res/css/views/rooms/_RoomPreviewBar.scss | 9 ++++++++- src/components/views/rooms/RoomPreviewBar.js | 21 ++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/res/css/views/rooms/_RoomPreviewBar.scss b/res/css/views/rooms/_RoomPreviewBar.scss index a119ada0dc..e75047a77f 100644 --- a/res/css/views/rooms/_RoomPreviewBar.scss +++ b/res/css/views/rooms/_RoomPreviewBar.scss @@ -100,15 +100,22 @@ limitations under the License. flex-direction: column; &>* { - margin: 10px; + margin: 5px 0 20px 0; } } .mx_RoomPreviewBar_actions { flex-direction: column-reverse; + .mx_AccessibleButton { + padding: 7px 50px;//extra wide + } &>* { margin-top: 12px; } } } + +.mx_RoomPreviewBar_inviter { + font-weight: 600; +} diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 0fb66abc00..c25fbd580d 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -24,6 +24,7 @@ import MatrixClientPeg from '../../../MatrixClientPeg'; import dis from '../../../dispatcher'; import classNames from 'classnames'; import { _t } from '../../../languageHandler'; +import {getUserNameColorClass} from '../../../utils/FormattingUtils'; const MessageCase = Object.freeze({ NotLoggedIn: "NotLoggedIn", @@ -316,21 +317,21 @@ module.exports = React.createClass({ case MessageCase.Invite: { const inviteMember = this._getInviteMember(); let avatar; - let memberName; + let inviterElement; if (inviteMember) { const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar"); - avatar = (); - memberName = inviteMember.name; + avatar = (); + const colorClass = getUserNameColorClass(inviteMember.userId); + inviterElement = ({inviteMember.name}); } else { - memberName = this.props.inviterName; + inviterElement = this.props.inviterName; } - if (this.props.canPreview) { - title = {avatar}{_t(" invited you to this room", {}, {userName: name => {memberName}})}; - } else { - title = _t("Do you want to join this room?"); - subTitle = {avatar}{_t(" invited you", {}, {userName: name => {memberName}})}; - } + title = _t("Do you want to join this room?"); + subTitle = [ + avatar, + _t(" invited you", {}, {userName: () => inviterElement}), + ]; primaryActionLabel = _t("Accept"); primaryActionHandler = this.props.onJoinClick; From 86620839ae01d5da7c6e2f913b3aa1c0dd6dd542 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 10:57:45 +0200 Subject: [PATCH 23/32] make username clickable --- res/css/views/rooms/_RoomPreviewBar.scss | 2 ++ src/components/structures/MatrixChat.js | 37 ++++++++++++-------- src/components/views/rooms/RoomPreviewBar.js | 19 ++++++++-- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/res/css/views/rooms/_RoomPreviewBar.scss b/res/css/views/rooms/_RoomPreviewBar.scss index e75047a77f..4440972712 100644 --- a/res/css/views/rooms/_RoomPreviewBar.scss +++ b/res/css/views/rooms/_RoomPreviewBar.scss @@ -118,4 +118,6 @@ limitations under the License. .mx_RoomPreviewBar_inviter { font-weight: 600; + text-decoration: underline; + cursor: pointer; } diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 387f2ca69d..b9530cdbd6 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -579,6 +579,12 @@ export default React.createClass({ }, 0); } break; + // different from view_user, + // this show the user panel outside of the context + // of a room, like a /user/ url + case 'view_user_info': + this._viewUser(payload.userId); + break; 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 @@ -933,6 +939,22 @@ export default React.createClass({ this.notifyNewScreen('home'); }, + _viewUser: function(userId, action) { + // Wait for the first sync so that `getRoom` gives us a room object if it's + // in the sync response + const waitFor = this.firstSyncPromise ? + this.firstSyncPromise.promise : Promise.resolve(); + waitFor.then(() => { + if (action === 'chat') { + this._chatCreateOrReuse(userId); + return; + } + this.notifyNewScreen('user/' + userId); + this.setState({currentUserId: userId}); + this._setPage(PageTypes.UserView); + }); + }, + _setMxId: function(payload) { const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); const close = Modal.createTrackedDialog('Set MXID', '', SetMxIdDialog, { @@ -1626,20 +1648,7 @@ export default React.createClass({ dis.dispatch(payload); } else if (screen.indexOf('user/') == 0) { const userId = screen.substring(5); - - // Wait for the first sync so that `getRoom` gives us a room object if it's - // in the sync response - const waitFor = this.firstSyncPromise ? - this.firstSyncPromise.promise : Promise.resolve(); - waitFor.then(() => { - if (params.action === 'chat') { - this._chatCreateOrReuse(userId); - return; - } - this.notifyNewScreen('user/' + userId); - this.setState({currentUserId: userId}); - this._setPage(PageTypes.UserView); - }); + this._viewUser(userId, params.action); } else if (screen.indexOf('group/') == 0) { const groupId = screen.substring(6); diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index c25fbd580d..6b03d5fef3 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -106,6 +106,12 @@ module.exports = React.createClass({ } }, + _onInviterClick(evt) { + evt.preventDefault(); + const member = this._getInviteMember(); + dis.dispatch({action: 'view_user_info', userId: member.userId}); + }, + _getMessageCase() { const isGuest = MatrixClientPeg.get().isGuest(); @@ -320,9 +326,16 @@ module.exports = React.createClass({ let inviterElement; if (inviteMember) { const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar"); - avatar = (); - const colorClass = getUserNameColorClass(inviteMember.userId); - inviterElement = ({inviteMember.name}); + avatar = (); + const inviterClasses = [ + "mx_RoomPreviewBar_inviter", + getUserNameColorClass(inviteMember.userId), + ].join(" "); + inviterElement = ( + + {inviteMember.name} + + ); } else { inviterElement = this.props.inviterName; } From 1100320351a1c7c333b2a52b9ee33c3322045b11 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 11:02:58 +0200 Subject: [PATCH 24/32] make non-member inviter name also bold --- res/css/views/rooms/_RoomPreviewBar.scss | 3 +++ src/components/views/rooms/RoomPreviewBar.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_RoomPreviewBar.scss b/res/css/views/rooms/_RoomPreviewBar.scss index 4440972712..ea3b787971 100644 --- a/res/css/views/rooms/_RoomPreviewBar.scss +++ b/res/css/views/rooms/_RoomPreviewBar.scss @@ -118,6 +118,9 @@ limitations under the License. .mx_RoomPreviewBar_inviter { font-weight: 600; +} + +a.mx_RoomPreviewBar_inviter { text-decoration: underline; cursor: pointer; } diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 6b03d5fef3..8fff835534 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -337,7 +337,7 @@ module.exports = React.createClass({ ); } else { - inviterElement = this.props.inviterName; + inviterElement = ({this.props.inviterName}); } title = _t("Do you want to join this room?"); From 8e750e18d7a6781cb91b9bc2a113cf03015c78d3 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 11:46:04 +0200 Subject: [PATCH 25/32] add class for message case for e2e tests --- src/components/views/rooms/RoomPreviewBar.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 8fff835534..edcd9805c7 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -227,7 +227,8 @@ module.exports = React.createClass({ let secondaryActionHandler; let secondaryActionLabel; - switch (this._getMessageCase()) { + const messageCase = this._getMessageCase(); + switch (messageCase) { case MessageCase.Joining: { title = _t("Joining room …"); showSpinner = true; @@ -418,7 +419,7 @@ module.exports = React.createClass({ ); } - const classes = classNames("mx_RoomPreviewBar", "dark-panel", { + const classes = classNames("mx_RoomPreviewBar", "dark-panel", `mx_RoomPreviewBar_${messageCase}`, { "mx_RoomPreviewBar_panel": this.props.canPreview, "mx_RoomPreviewBar_dialog": !this.props.canPreview, "mx_RoomPreviewBar_dark": darkStyle, From 66e10e904d889e311e7a15784527e231d1a6d91d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 11:46:20 +0200 Subject: [PATCH 26/32] remove obsolete translations --- src/i18n/strings/en_EN.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2b74b9f8ae..2b50fd9ad3 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -601,7 +601,7 @@ "This room is not accessible by remote Matrix servers": "This room is not accessible by remote Matrix servers", "Upgrade this room to the recommended room version": "Upgrade this room to the recommended room version", "this room": "this room", - "View older messages in %(roomName)s": "View older messages in %(roomName)s", + "View older messages in %(roomName)s.": "View older messages in %(roomName)s.", "Room information": "Room information", "Internal room ID:": "Internal room ID:", "Room version": "Room version", @@ -793,7 +793,6 @@ "Historical": "Historical", "System Alerts": "System Alerts", "This room": "This room", - "this room": "this room", "Joining room …": "Joining room …", "Loading …": "Loading …", "Rejecting invite …": "Rejecting invite …", @@ -813,7 +812,6 @@ "Try to join anyway": "Try to join anyway", "The room invite wasn't sent to your account": "The room invite wasn't sent to your account", "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.": "Sign in with a different account, ask for another invite, or add the e-mail address %(email)s to this account.", - " invited you to this room": " invited you to this room", "Do you want to join this room?": "Do you want to join this room?", " invited you": " invited you", "Reject": "Reject", From c5986395ef19429aef14fbebe92154e0c6ea0050 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 14:13:12 +0200 Subject: [PATCH 27/32] propagate env to e2e tests so they can get correct branch of e2e tests --- .buildkite/pipeline.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.buildkite/pipeline.yaml b/.buildkite/pipeline.yaml index 60964de469..ac05da02e3 100644 --- a/.buildkite/pipeline.yaml +++ b/.buildkite/pipeline.yaml @@ -24,6 +24,7 @@ steps: plugins: - docker#v3.0.1: image: "matrixdotorg/riotweb-ci-e2etests-env:latest" + propagate-environment: true - label: ":karma: Tests" agents: From d5cc835a931de3106c7afcb327a59d890e252cbc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 18:23:49 +0200 Subject: [PATCH 28/32] PR feedback --- src/components/structures/MatrixChat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 2a206276dc..d96f349e21 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -925,9 +925,9 @@ export default React.createClass({ _viewUser: function(userId, action) { // Wait for the first sync so that `getRoom` gives us a room object if it's // in the sync response - const waitFor = this.firstSyncPromise ? + const waitForSync = this.firstSyncPromise ? this.firstSyncPromise.promise : Promise.resolve(); - waitFor.then(() => { + waitForSync.then(() => { if (action === 'chat') { this._chatCreateOrReuse(userId); return; From 190143ca6ca74a04f51ad7af43dd2cafee73b6e5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 18:26:07 +0200 Subject: [PATCH 29/32] dispatch for user screen --- src/components/structures/MatrixChat.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index d96f349e21..33f1bac090 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -566,7 +566,7 @@ export default React.createClass({ }); break; case 'view_user_info': - this._viewUser(payload.userId); + this._viewUser(payload.userId, payload.subAction); break; case 'view_room': // Takes either a room ID or room alias: if switching to a room the client is already @@ -922,13 +922,13 @@ export default React.createClass({ this.notifyNewScreen('home'); }, - _viewUser: function(userId, action) { + _viewUser: function(userId, subAction) { // Wait for the first sync so that `getRoom` gives us a room object if it's // in the sync response const waitForSync = this.firstSyncPromise ? this.firstSyncPromise.promise : Promise.resolve(); waitForSync.then(() => { - if (action === 'chat') { + if (subAction === 'chat') { this._chatCreateOrReuse(userId); return; } @@ -1631,7 +1631,11 @@ export default React.createClass({ dis.dispatch(payload); } else if (screen.indexOf('user/') == 0) { const userId = screen.substring(5); - this._viewUser(userId, params.action); + dis.dispatch({ + action: 'view_user_info', + userId: userId, + subAction: params.action, + }); } else if (screen.indexOf('group/') == 0) { const groupId = screen.substring(6); From 0a463472b33414a186f09e63080c16c696f7d681 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 19:05:52 +0200 Subject: [PATCH 30/32] update prop types (and fix typo) --- src/components/views/rooms/RoomPreviewBar.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index edcd9805c7..55c39d3947 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -48,9 +48,6 @@ module.exports = React.createClass({ onJoinClick: PropTypes.func, onRejectClick: PropTypes.func, onForgetClick: PropTypes.func, - onSignInClick: PropTypes.func, - onSignUpClick: PropTypes.func, - // if inviterName is specified, the preview bar will shown an invite to the room. // You should also specify onRejectClick if specifiying inviterName inviterName: PropTypes.string, @@ -69,7 +66,9 @@ module.exports = React.createClass({ // purpose of the spinner. spinner: PropTypes.bool, spinnerState: PropTypes.oneOf(["joining"]), - + loading: PropTypes.bool, + joining: PropTypes.bool, + rejecting: PropTypes.bool, // The alias that was used to access this room, if appropriate // If given, this will be how the room is referred to (eg. // in error messages). @@ -185,7 +184,7 @@ module.exports = React.createClass({ }, _roomName: function(atStart = false) { - const name = this.props.room ? this.props.room.name : this.props.room_alias; + const name = this.props.room ? this.props.room.name : this.props.roomAlias; if (name) { return name; } else if (atStart) { From dd911d18cb2209a8db603732919e602528f25f68 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 17 Apr 2019 19:29:39 +0200 Subject: [PATCH 31/32] dont show right panel when previewing a room without invite, as its empty --- src/components/structures/RoomView.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 96d915e9de..99f13dcd35 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1647,6 +1647,7 @@ module.exports = React.createClass({ let aux = null; let previewBar; let hideCancel = false; + let hideRightPanel = false; if (this.state.forwardingEvent !== null) { aux = ; } else if (this.state.searching) { @@ -1690,6 +1691,8 @@ module.exports = React.createClass({ { previewBar }
); + } else { + hideRightPanel = true; } } else if (hiddenHighlightCount > 0) { aux = ( @@ -1861,14 +1864,16 @@ module.exports = React.createClass({ }, ); - const rightPanel = this.state.room ? : undefined; + const rightPanel = !hideRightPanel && this.state.room && + ; + const collapsedRhs = hideRightPanel || this.props.collapsedRhs; return (
From faecceb3b42159ab72ee9e5dda94ccf96511e375 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 18 Apr 2019 09:20:26 +0200 Subject: [PATCH 32/32] remove manual order so component order follows markup order --- res/css/structures/_RoomView.scss | 9 --------- 1 file changed, 9 deletions(-) diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index cead3f4672..50d412ad58 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -163,15 +163,6 @@ limitations under the License. height: 1px; } - -.mx_RoomView_body .mx_RoomView_statusArea { - order: 3; -} - -.mx_RoomView_body .mx_MessageComposer { - order: 4; -} - .mx_RoomView_messageListWrapper { min-height: 100%;