Merge pull request #2925 from matrix-org/bwindels/stylepreviewbar
Redesigned room preview barpull/21833/head
						commit
						0fbe10a816
					
				| 
						 | 
				
			
			@ -24,6 +24,7 @@ steps:
 | 
			
		|||
    plugins:
 | 
			
		||||
      - docker#v3.0.1:
 | 
			
		||||
          image: "matrixdotorg/riotweb-ci-e2etests-env:latest"
 | 
			
		||||
          propagate-environment: true
 | 
			
		||||
 | 
			
		||||
  - label: ":karma: Tests"
 | 
			
		||||
    agents:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -523,3 +523,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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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%;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,48 +15,112 @@ limitations under the License.
 | 
			
		|||
*/
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    height: 176px;
 | 
			
		||||
    background-color: $event-selected-color;
 | 
			
		||||
    flex: 0 0 auto;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    background-color: $preview-bar-bg-color;
 | 
			
		||||
    -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;
 | 
			
		||||
        flex: 0 0 auto;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar_wrapper {
 | 
			
		||||
.mx_RoomPreviewBar_dark {
 | 
			
		||||
    background-color: $tagpanel-bg-color;
 | 
			
		||||
    color: $accent-fg-color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar_invite_text {
 | 
			
		||||
    color: $primary-fg-color;
 | 
			
		||||
.mx_RoomPreviewBar_actions {
 | 
			
		||||
    display: flex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar_join_text {
 | 
			
		||||
    color: $warning-color;
 | 
			
		||||
.mx_RoomPreviewBar_message {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    align-items: stretch;
 | 
			
		||||
 | 
			
		||||
    p {
 | 
			
		||||
        overflow-wrap: break-word;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar_preview_text {
 | 
			
		||||
    margin-top: 25px;
 | 
			
		||||
    color: $settings-grey-fg-color;
 | 
			
		||||
.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;
 | 
			
		||||
 | 
			
		||||
        &>* {
 | 
			
		||||
            margin: 4px;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar_join_text a {
 | 
			
		||||
.mx_RoomPreviewBar_dialog {
 | 
			
		||||
    margin: auto;
 | 
			
		||||
    box-sizing: content;
 | 
			
		||||
    width: 400px;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    padding: 20px;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
 | 
			
		||||
    .mx_RoomPreviewBar_message {
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
 | 
			
		||||
        &>* {
 | 
			
		||||
            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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a.mx_RoomPreviewBar_inviter {
 | 
			
		||||
    text-decoration: underline;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar_warning {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    padding: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar_warningIcon {
 | 
			
		||||
    padding: 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mx_RoomPreviewBar_spinnerIntro {
 | 
			
		||||
    margin-top: 50px;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -565,6 +565,9 @@ export default React.createClass({
 | 
			
		|||
                    },
 | 
			
		||||
                });
 | 
			
		||||
                break;
 | 
			
		||||
            case 'view_user_info':
 | 
			
		||||
                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
 | 
			
		||||
                // known to be in (eg. user clicks on a room in the recents panel), supply the ID
 | 
			
		||||
| 
						 | 
				
			
			@ -919,6 +922,22 @@ export default React.createClass({
 | 
			
		|||
        this.notifyNewScreen('home');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _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 (subAction === '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, {
 | 
			
		||||
| 
						 | 
				
			
			@ -1612,19 +1631,10 @@ 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);
 | 
			
		||||
            dis.dispatch({
 | 
			
		||||
                action: 'view_user_info',
 | 
			
		||||
                userId: userId,
 | 
			
		||||
                subAction: params.action,
 | 
			
		||||
            });
 | 
			
		||||
        } else if (screen.indexOf('group/') == 0) {
 | 
			
		||||
            const groupId = screen.substring(6);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1511,16 +1511,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 (
 | 
			
		||||
                    <div className="mx_RoomView">
 | 
			
		||||
                        <Loader />
 | 
			
		||||
                        <RoomPreviewBar
 | 
			
		||||
                            canPreview={false}
 | 
			
		||||
                            error={this.state.roomLoadError}
 | 
			
		||||
                            loading={loading}
 | 
			
		||||
                            joining={this.state.joining}
 | 
			
		||||
                        />
 | 
			
		||||
                    </div>
 | 
			
		||||
                );
 | 
			
		||||
            } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1538,28 +1543,16 @@ module.exports = React.createClass({
 | 
			
		|||
                const roomAlias = this.state.roomAlias;
 | 
			
		||||
                return (
 | 
			
		||||
                    <div className="mx_RoomView">
 | 
			
		||||
                        <RoomHeader ref="header"
 | 
			
		||||
                        <RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
 | 
			
		||||
                            onForgetClick={this.onForgetClick}
 | 
			
		||||
                            onRejectClick={this.onRejectThreepidInviteButtonClicked}
 | 
			
		||||
                            canPreview={false} error={this.state.roomLoadError}
 | 
			
		||||
                            roomAlias={roomAlias}
 | 
			
		||||
                            joining={this.state.joining}
 | 
			
		||||
                            inviterName={inviterName}
 | 
			
		||||
                            invitedEmail={invitedEmail}
 | 
			
		||||
                            room={this.state.room}
 | 
			
		||||
                            oobData={this.props.oobData}
 | 
			
		||||
                            collapsedRhs={this.props.collapsedRhs}
 | 
			
		||||
                            e2eStatus={this.state.e2eStatus}
 | 
			
		||||
                        />
 | 
			
		||||
                        <div className="mx_RoomView_body">
 | 
			
		||||
                            <div className="mx_RoomView_auxPanel">
 | 
			
		||||
                                <RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
 | 
			
		||||
                                                onForgetClick={this.onForgetClick}
 | 
			
		||||
                                                onRejectClick={this.onRejectThreepidInviteButtonClicked}
 | 
			
		||||
                                                canPreview={false} error={this.state.roomLoadError}
 | 
			
		||||
                                                roomAlias={roomAlias}
 | 
			
		||||
                                                spinner={this.state.joining}
 | 
			
		||||
                                                spinnerState="joining"
 | 
			
		||||
                                                inviterName={inviterName}
 | 
			
		||||
                                                invitedEmail={invitedEmail}
 | 
			
		||||
                                                room={this.state.room}
 | 
			
		||||
                                />
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div className="mx_RoomView_messagePanel"></div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1569,9 +1562,12 @@ module.exports = React.createClass({
 | 
			
		|||
        if (myMembership == 'invite') {
 | 
			
		||||
            if (this.state.joining || this.state.rejecting) {
 | 
			
		||||
                return (
 | 
			
		||||
                    <div className="mx_RoomView">
 | 
			
		||||
                        <Loader />
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <RoomPreviewBar
 | 
			
		||||
                            canPreview={false}
 | 
			
		||||
                            error={this.state.roomLoadError}
 | 
			
		||||
                            joining={this.state.joining}
 | 
			
		||||
                            rejecting={this.state.rejecting}
 | 
			
		||||
                        />
 | 
			
		||||
                );
 | 
			
		||||
            } else {
 | 
			
		||||
                const myUserId = MatrixClientPeg.get().credentials.userId;
 | 
			
		||||
| 
						 | 
				
			
			@ -1586,26 +1582,14 @@ module.exports = React.createClass({
 | 
			
		|||
                // We have a regular invite for this room.
 | 
			
		||||
                return (
 | 
			
		||||
                    <div className="mx_RoomView">
 | 
			
		||||
                        <RoomHeader
 | 
			
		||||
                            ref="header"
 | 
			
		||||
                        <RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
 | 
			
		||||
                            onForgetClick={this.onForgetClick}
 | 
			
		||||
                            onRejectClick={this.onRejectButtonClicked}
 | 
			
		||||
                            inviterName={inviterName}
 | 
			
		||||
                            canPreview={false}
 | 
			
		||||
                            joining={this.state.joining}
 | 
			
		||||
                            room={this.state.room}
 | 
			
		||||
                            collapsedRhs={this.props.collapsedRhs}
 | 
			
		||||
                            e2eStatus={this.state.e2eStatus}
 | 
			
		||||
                        />
 | 
			
		||||
                        <div className="mx_RoomView_body">
 | 
			
		||||
                            <div className="mx_RoomView_auxPanel">
 | 
			
		||||
                                <RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
 | 
			
		||||
                                                onForgetClick={this.onForgetClick}
 | 
			
		||||
                                                onRejectClick={this.onRejectButtonClicked}
 | 
			
		||||
                                                inviterName={inviterName}
 | 
			
		||||
                                                canPreview={false}
 | 
			
		||||
                                                spinner={this.state.joining}
 | 
			
		||||
                                                spinnerState="joining"
 | 
			
		||||
                                                room={this.state.room}
 | 
			
		||||
                                />
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div className="mx_RoomView_messagePanel"></div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1661,7 +1645,9 @@ module.exports = React.createClass({
 | 
			
		|||
        const hiddenHighlightCount = this._getHiddenHighlightCount();
 | 
			
		||||
 | 
			
		||||
        let aux = null;
 | 
			
		||||
        let previewBar;
 | 
			
		||||
        let hideCancel = false;
 | 
			
		||||
        let hideRightPanel = false;
 | 
			
		||||
        if (this.state.forwardingEvent !== null) {
 | 
			
		||||
            aux = <ForwardMessage onCancelClick={this.onCancelClick} />;
 | 
			
		||||
        } else if (this.state.searching) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1688,18 +1674,26 @@ module.exports = React.createClass({
 | 
			
		|||
                invitedEmail = this.props.thirdPartyInvite.invitedEmail;
 | 
			
		||||
            }
 | 
			
		||||
            hideCancel = true;
 | 
			
		||||
            aux = (
 | 
			
		||||
            previewBar = (
 | 
			
		||||
                <RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
 | 
			
		||||
                                onForgetClick={this.onForgetClick}
 | 
			
		||||
                                onRejectClick={this.onRejectThreepidInviteButtonClicked}
 | 
			
		||||
                                spinner={this.state.joining}
 | 
			
		||||
                                spinnerState="joining"
 | 
			
		||||
                                joining={this.state.joining}
 | 
			
		||||
                                inviterName={inviterName}
 | 
			
		||||
                                invitedEmail={invitedEmail}
 | 
			
		||||
                                canPreview={this.state.canPeek}
 | 
			
		||||
                                room={this.state.room}
 | 
			
		||||
                />
 | 
			
		||||
            );
 | 
			
		||||
            if (!this.state.canPeek) {
 | 
			
		||||
                return (
 | 
			
		||||
                    <div className="mx_RoomView">
 | 
			
		||||
                        { previewBar }
 | 
			
		||||
                    </div>
 | 
			
		||||
                );
 | 
			
		||||
            } else {
 | 
			
		||||
                hideRightPanel = true;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (hiddenHighlightCount > 0) {
 | 
			
		||||
            aux = (
 | 
			
		||||
                <AccessibleButton element="div" className="mx_RoomView_auxPanel_hiddenHighlights"
 | 
			
		||||
| 
						 | 
				
			
			@ -1743,11 +1737,6 @@ module.exports = React.createClass({
 | 
			
		|||
                />;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (MatrixClientPeg.get().isGuest()) {
 | 
			
		||||
            const AuthButtons = sdk.getComponent('views.auth.AuthButtons');
 | 
			
		||||
            messageComposer = <AuthButtons />;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1875,14 +1864,16 @@ module.exports = React.createClass({
 | 
			
		|||
            },
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        const rightPanel = this.state.room ? <RightPanel roomId={this.state.room.roomId} resizeNotifier={this.props.resizeNotifier} /> : undefined;
 | 
			
		||||
        const rightPanel = !hideRightPanel && this.state.room &&
 | 
			
		||||
            <RightPanel roomId={this.state.room.roomId} resizeNotifier={this.props.resizeNotifier} />;
 | 
			
		||||
        const collapsedRhs = hideRightPanel || this.props.collapsedRhs;
 | 
			
		||||
 | 
			
		||||
        return (
 | 
			
		||||
            <main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref="roomView">
 | 
			
		||||
                <RoomHeader ref="header" room={this.state.room} searchInfo={searchInfo}
 | 
			
		||||
                    oobData={this.props.oobData}
 | 
			
		||||
                    inRoom={myMembership === 'join'}
 | 
			
		||||
                    collapsedRhs={this.props.collapsedRhs}
 | 
			
		||||
                    collapsedRhs={collapsedRhs}
 | 
			
		||||
                    onSearchClick={this.onSearchClick}
 | 
			
		||||
                    onSettingsClick={this.onSettingsClick}
 | 
			
		||||
                    onPinnedClick={this.onPinnedClick}
 | 
			
		||||
| 
						 | 
				
			
			@ -1893,7 +1884,7 @@ module.exports = React.createClass({
 | 
			
		|||
                />
 | 
			
		||||
                <MainSplit
 | 
			
		||||
                    panel={rightPanel}
 | 
			
		||||
                    collapsedRhs={this.props.collapsedRhs}
 | 
			
		||||
                    collapsedRhs={collapsedRhs}
 | 
			
		||||
                    resizeNotifier={this.props.resizeNotifier}
 | 
			
		||||
                >
 | 
			
		||||
                    <div className={fadableSectionClasses}>
 | 
			
		||||
| 
						 | 
				
			
			@ -1910,6 +1901,7 @@ module.exports = React.createClass({
 | 
			
		|||
                                { statusBar }
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        { previewBar }
 | 
			
		||||
                        { messageComposer }
 | 
			
		||||
                    </div>
 | 
			
		||||
                </MainSplit>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 = (
 | 
			
		||||
            <div className="mx_AuthButtons_loginButton_wrapper">
 | 
			
		||||
                <AccessibleButton className="mx_AuthButtons_loginButton" element="button" onClick={this.onLoginClick}>
 | 
			
		||||
                    { _t("Login") }
 | 
			
		||||
                </AccessibleButton>
 | 
			
		||||
                <AccessibleButton className="mx_AuthButtons_registerButton" element="button" onClick={this.onRegisterClick}>
 | 
			
		||||
                    { _t("Register") }
 | 
			
		||||
                </AccessibleButton>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return (
 | 
			
		||||
            <div className="mx_AuthButtons">
 | 
			
		||||
                { loginButton }
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -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 = <span>
 | 
			
		||||
            <span className={`mx_SenderProfile_name mx_SenderProfile_color${colorNumber}`}>
 | 
			
		||||
            <span className={`mx_SenderProfile_name ${colorClass}`}>
 | 
			
		||||
                { nameElem }
 | 
			
		||||
            </span>
 | 
			
		||||
            { flair }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,12 +17,29 @@ 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';
 | 
			
		||||
import {getUserNameColorClass} from '../../../utils/FormattingUtils';
 | 
			
		||||
 | 
			
		||||
const MessageCase = Object.freeze({
 | 
			
		||||
    NotLoggedIn: "NotLoggedIn",
 | 
			
		||||
    Joining: "Joining",
 | 
			
		||||
    Loading: "Loading",
 | 
			
		||||
    Rejecting: "Rejecting",
 | 
			
		||||
    Kicked: "Kicked",
 | 
			
		||||
    Banned: "Banned",
 | 
			
		||||
    OtherThreePIDError: "OtherThreePIDError",
 | 
			
		||||
    InvitedEmailMismatch: "InvitedEmailMismatch",
 | 
			
		||||
    Invite: "Invite",
 | 
			
		||||
    ViewingRoom: "ViewingRoom",
 | 
			
		||||
    RoomNotFound: "RoomNotFound",
 | 
			
		||||
    OtherError: "OtherError",
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = React.createClass({
 | 
			
		||||
    displayName: 'RoomPreviewBar',
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +48,6 @@ module.exports = React.createClass({
 | 
			
		|||
        onJoinClick: PropTypes.func,
 | 
			
		||||
        onRejectClick: PropTypes.func,
 | 
			
		||||
        onForgetClick: 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,
 | 
			
		||||
| 
						 | 
				
			
			@ -50,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).
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +78,6 @@ module.exports = React.createClass({
 | 
			
		|||
    getDefaultProps: function() {
 | 
			
		||||
        return {
 | 
			
		||||
            onJoinClick: function() {},
 | 
			
		||||
            canPreview: true,
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -72,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});
 | 
			
		||||
| 
						 | 
				
			
			@ -88,157 +105,334 @@ module.exports = React.createClass({
 | 
			
		|||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _roomNameElement: function() {
 | 
			
		||||
        return this.props.room ? this.props.room.name : (this.props.room_alias || "");
 | 
			
		||||
    _onInviterClick(evt) {
 | 
			
		||||
        evt.preventDefault();
 | 
			
		||||
        const member = this._getInviteMember();
 | 
			
		||||
        dis.dispatch({action: 'view_user_info', userId: member.userId});
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    render: function() {
 | 
			
		||||
        let joinBlock; let previewBlock;
 | 
			
		||||
    _getMessageCase() {
 | 
			
		||||
        const isGuest = MatrixClientPeg.get().isGuest();
 | 
			
		||||
 | 
			
		||||
        if (this.props.spinner || this.state.busy) {
 | 
			
		||||
            const Spinner = sdk.getComponent("elements.Spinner");
 | 
			
		||||
            let spinnerIntro = "";
 | 
			
		||||
            if (this.props.spinnerState === "joining") {
 | 
			
		||||
                spinnerIntro = _t("Joining room...");
 | 
			
		||||
            }
 | 
			
		||||
            return (<div className="mx_RoomPreviewBar">
 | 
			
		||||
                <p className="mx_RoomPreviewBar_spinnerIntro">{ spinnerIntro }</p>
 | 
			
		||||
                <Spinner />
 | 
			
		||||
            </div>);
 | 
			
		||||
        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) {
 | 
			
		||||
            return MessageCase.Rejecting;
 | 
			
		||||
        } else if (this.props.loading || this.state.busy) {
 | 
			
		||||
            return MessageCase.Loading;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.props.inviterName) {
 | 
			
		||||
            if (this.props.invitedEmail) {
 | 
			
		||||
                if (this.state.threePidFetchError) {
 | 
			
		||||
                    return MessageCase.OtherThreePIDError;
 | 
			
		||||
                } else if (this.state.invitedEmailMxid != MatrixClientPeg.get().getUserId()) {
 | 
			
		||||
                    return MessageCase.InvitedEmailMismatch;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return MessageCase.Invite;
 | 
			
		||||
        } 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;
 | 
			
		||||
        const kicked = myMember && myMember.isKicked();
 | 
			
		||||
        const banned = myMember && myMember && myMember.membership == 'ban';
 | 
			
		||||
        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};
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
        if (this.props.inviterName) {
 | 
			
		||||
            let emailMatchBlock;
 | 
			
		||||
            if (this.props.invitedEmail) {
 | 
			
		||||
                if (this.state.threePidFetchError) {
 | 
			
		||||
                    emailMatchBlock = <div className="error">
 | 
			
		||||
                        { _t("Unable to ascertain that the address this invite was sent to matches one associated with your account.") }
 | 
			
		||||
                    </div>;
 | 
			
		||||
                } else if (this.state.invitedEmailMxid != MatrixClientPeg.get().credentials.userId) {
 | 
			
		||||
                    emailMatchBlock =
 | 
			
		||||
                        <div className="mx_RoomPreviewBar_warning">
 | 
			
		||||
                            <div className="mx_RoomPreviewBar_warningIcon">
 | 
			
		||||
                                <img src={require("../../../../res/img/warning.svg")} width="24" height="23" title= "/!\\" alt="/!\\" />
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div className="mx_RoomPreviewBar_warningText">
 | 
			
		||||
                                { _t("This invitation was sent to an email address which is not associated with this account:") }
 | 
			
		||||
                                <b><span className="email">{ this.props.invitedEmail }</span></b>
 | 
			
		||||
                                <br />
 | 
			
		||||
                                { _t("You may wish to login with a different account, or add this email to this account.") }
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            joinBlock = (
 | 
			
		||||
                <div>
 | 
			
		||||
                    <div className="mx_RoomPreviewBar_invite_text">
 | 
			
		||||
                        { _t('You have been invited to join this room by %(inviterName)s', {inviterName: this.props.inviterName}) }
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className="mx_RoomPreviewBar_join_text">
 | 
			
		||||
                        { _t(
 | 
			
		||||
                            'Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?',
 | 
			
		||||
                            {},
 | 
			
		||||
                            {
 | 
			
		||||
                                'acceptText': (sub) => <a onClick={this.props.onJoinClick}>{ sub }</a>,
 | 
			
		||||
                                'declineText': (sub) => <a onClick={this.props.onRejectClick}>{ sub }</a>,
 | 
			
		||||
                            },
 | 
			
		||||
                        ) }
 | 
			
		||||
                    </div>
 | 
			
		||||
                    { emailMatchBlock }
 | 
			
		||||
                </div>
 | 
			
		||||
            );
 | 
			
		||||
        } 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 = <div>{ _t("Reason: %(reasonText)s", {reasonText: myMember.events.member.getContent().reason}) }</div>;
 | 
			
		||||
            }
 | 
			
		||||
            let rejoinBlock;
 | 
			
		||||
            if (!banned) {
 | 
			
		||||
                rejoinBlock = <div><a onClick={this.props.onJoinClick}><b>{ _t("Rejoin") }</b></a></div>;
 | 
			
		||||
    _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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
            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 = (
 | 
			
		||||
                <div>
 | 
			
		||||
                    <div className="mx_RoomPreviewBar_join_text">
 | 
			
		||||
                        { actionText }
 | 
			
		||||
                        <br />
 | 
			
		||||
                        { reason }
 | 
			
		||||
                        { rejoinBlock }
 | 
			
		||||
                        <a onClick={this.props.onForgetClick}><b>{ _t("Forget room") }</b></a>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            );
 | 
			
		||||
        } 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});
 | 
			
		||||
            } else {
 | 
			
		||||
                error = _t("%(roomName)s is not accessible at this time.", {roomName: name});
 | 
			
		||||
            }
 | 
			
		||||
            joinBlock = (
 | 
			
		||||
                <div>
 | 
			
		||||
                    <div className="mx_RoomPreviewBar_join_text">
 | 
			
		||||
                        { error }
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            );
 | 
			
		||||
    _roomName: function(atStart = false) {
 | 
			
		||||
        const name = this.props.room ? this.props.room.name : this.props.roomAlias;
 | 
			
		||||
        if (name) {
 | 
			
		||||
            return name;
 | 
			
		||||
        } else if (atStart) {
 | 
			
		||||
            return _t("This room");
 | 
			
		||||
        } else {
 | 
			
		||||
            const name = this._roomNameElement();
 | 
			
		||||
            joinBlock = (
 | 
			
		||||
                <div>
 | 
			
		||||
                    <div className="mx_RoomPreviewBar_join_text">
 | 
			
		||||
                        { name ? _t('You are trying to access %(roomName)s.', {roomName: name}) : _t('You are trying to access a room.') }
 | 
			
		||||
                        <br />
 | 
			
		||||
                        { _t("<a>Click here</a> to join the discussion!",
 | 
			
		||||
                            {},
 | 
			
		||||
                            { 'a': (sub) => <a onClick={this.props.onJoinClick}><b>{ sub }</b></a> },
 | 
			
		||||
                        ) }
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            return _t("this room");
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _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' });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onRegisterClick: function() {
 | 
			
		||||
        dis.dispatch({ action: 'start_registration' });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    render: function() {
 | 
			
		||||
        let showSpinner = false;
 | 
			
		||||
        let darkStyle = false;
 | 
			
		||||
        let title;
 | 
			
		||||
        let subTitle;
 | 
			
		||||
        let primaryActionHandler;
 | 
			
		||||
        let primaryActionLabel;
 | 
			
		||||
        let secondaryActionHandler;
 | 
			
		||||
        let secondaryActionLabel;
 | 
			
		||||
 | 
			
		||||
        const messageCase = this._getMessageCase();
 | 
			
		||||
        switch (messageCase) {
 | 
			
		||||
            case MessageCase.Joining: {
 | 
			
		||||
                title = _t("Joining room …");
 | 
			
		||||
                showSpinner = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Loading: {
 | 
			
		||||
                title = _t("Loading …");
 | 
			
		||||
                showSpinner = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Rejecting: {
 | 
			
		||||
                title = _t("Rejecting invite …");
 | 
			
		||||
                showSpinner = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.NotLoggedIn: {
 | 
			
		||||
                darkStyle = true;
 | 
			
		||||
                title = _t("Join the conversation with an account");
 | 
			
		||||
                primaryActionLabel = _t("Sign Up");
 | 
			
		||||
                primaryActionHandler = this.onRegisterClick;
 | 
			
		||||
                secondaryActionLabel = _t("Sign In");
 | 
			
		||||
                secondaryActionHandler = this.onLoginClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Kicked: {
 | 
			
		||||
                const {memberName, reason} = this._getKickOrBanInfo();
 | 
			
		||||
                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") {
 | 
			
		||||
                    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: {
 | 
			
		||||
                const {memberName, reason} = this._getKickOrBanInfo();
 | 
			
		||||
                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;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            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},
 | 
			
		||||
                );
 | 
			
		||||
                switch (joinRule) {
 | 
			
		||||
                    case "invite":
 | 
			
		||||
                        subTitle = [
 | 
			
		||||
                            _t("You can only join it with a working invite."),
 | 
			
		||||
                            errCodeMessage,
 | 
			
		||||
                        ];
 | 
			
		||||
                        break;
 | 
			
		||||
                    case "public":
 | 
			
		||||
                        subTitle = _t("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");
 | 
			
		||||
                const joinRule = this._joinRule();
 | 
			
		||||
                if (joinRule === "public") {
 | 
			
		||||
                    subTitle = _t("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;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.Invite: {
 | 
			
		||||
                const inviteMember = this._getInviteMember();
 | 
			
		||||
                let avatar;
 | 
			
		||||
                let inviterElement;
 | 
			
		||||
                if (inviteMember) {
 | 
			
		||||
                    const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar");
 | 
			
		||||
                    avatar = (<MemberAvatar member={inviteMember} onClick={this._onInviterClick} />);
 | 
			
		||||
                    const inviterClasses = [
 | 
			
		||||
                        "mx_RoomPreviewBar_inviter",
 | 
			
		||||
                        getUserNameColorClass(inviteMember.userId),
 | 
			
		||||
                    ].join(" ");
 | 
			
		||||
                    inviterElement = (
 | 
			
		||||
                        <a onClick={this._onInviterClick} className={inviterClasses}>
 | 
			
		||||
                            {inviteMember.name}
 | 
			
		||||
                        </a>
 | 
			
		||||
                    );
 | 
			
		||||
                } else {
 | 
			
		||||
                    inviterElement = (<span className="mx_RoomPreviewBar_inviter">{this.props.inviterName}</span>);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                title = _t("Do you want to join this room?");
 | 
			
		||||
                subTitle = [
 | 
			
		||||
                    avatar,
 | 
			
		||||
                    _t("<userName/> invited you", {}, {userName: () => inviterElement}),
 | 
			
		||||
                ];
 | 
			
		||||
 | 
			
		||||
                primaryActionLabel = _t("Accept");
 | 
			
		||||
                primaryActionHandler = this.props.onJoinClick;
 | 
			
		||||
                secondaryActionLabel = _t("Reject");
 | 
			
		||||
                secondaryActionHandler = this.props.onRejectClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case MessageCase.ViewingRoom: {
 | 
			
		||||
                if (this.props.canPreview) {
 | 
			
		||||
                    title = _t("You're previewing this room. Want to join it?");
 | 
			
		||||
                } else {
 | 
			
		||||
                    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(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(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 <issueLink>submit a bug report</issueLink>.",
 | 
			
		||||
                        { errcode: this.props.error.errcode },
 | 
			
		||||
                        { issueLink: label => <a href="https://github.com/vector-im/riot-web/issues/new/choose"
 | 
			
		||||
                            target="_blank" rel="noopener">{ label }</a> },
 | 
			
		||||
                    ),
 | 
			
		||||
                ];
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
 | 
			
		||||
        const Spinner = sdk.getComponent('elements.Spinner');
 | 
			
		||||
 | 
			
		||||
        let subTitleElements;
 | 
			
		||||
        if (subTitle) {
 | 
			
		||||
            if (!Array.isArray(subTitle)) {
 | 
			
		||||
                subTitle = [subTitle];
 | 
			
		||||
            }
 | 
			
		||||
            subTitleElements = subTitle.map((t, i) => <p key={`subTitle${i}`}>{t}</p>);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let titleElement;
 | 
			
		||||
        if (showSpinner) {
 | 
			
		||||
            titleElement = <h3 className="mx_RoomPreviewBar_spinnerTitle"><Spinner />{ title }</h3>;
 | 
			
		||||
        } else {
 | 
			
		||||
            titleElement = <h3>{ title }</h3>;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let primaryButton;
 | 
			
		||||
        if (primaryActionHandler) {
 | 
			
		||||
            primaryButton = (
 | 
			
		||||
                <AccessibleButton kind="primary" onClick={primaryActionHandler}>
 | 
			
		||||
                    { primaryActionLabel }
 | 
			
		||||
                </AccessibleButton>
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.props.canPreview) {
 | 
			
		||||
            previewBlock = (
 | 
			
		||||
                <div className="mx_RoomPreviewBar_preview_text">
 | 
			
		||||
                    { _t('This is a preview of this room. Room interactions have been disabled') }.
 | 
			
		||||
                </div>
 | 
			
		||||
        let secondaryButton;
 | 
			
		||||
        if (secondaryActionHandler) {
 | 
			
		||||
            secondaryButton = (
 | 
			
		||||
                <AccessibleButton kind="secondary" onClick={secondaryActionHandler}>
 | 
			
		||||
                    { secondaryActionLabel }
 | 
			
		||||
                </AccessibleButton>
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return (
 | 
			
		||||
            <div className="mx_RoomPreviewBar">
 | 
			
		||||
                <div className="mx_RoomPreviewBar_wrapper">
 | 
			
		||||
                    { joinBlock }
 | 
			
		||||
                    { previewBlock }
 | 
			
		||||
            <div className={classes}>
 | 
			
		||||
                <div className="mx_RoomPreviewBar_message">
 | 
			
		||||
                    { titleElement }
 | 
			
		||||
                    { subTitleElements }
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="mx_RoomPreviewBar_actions">
 | 
			
		||||
                    { secondaryButton }
 | 
			
		||||
                    { primaryButton }
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			@ -792,25 +792,36 @@
 | 
			
		|||
    "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 <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?": "Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> 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 …",
 | 
			
		||||
    "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 %(roomName)s by %(memberName)s": "You were kicked from %(roomName)s by %(memberName)s",
 | 
			
		||||
    "Reason: %(reason)s": "Reason: %(reason)s",
 | 
			
		||||
    "Forget this room": "Forget this room",
 | 
			
		||||
    "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.",
 | 
			
		||||
    "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.",
 | 
			
		||||
    "Do you want to join this room?": "Do you want to join this room?",
 | 
			
		||||
    "<userName/> invited you": "<userName/> 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?",
 | 
			
		||||
    "%(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.",
 | 
			
		||||
    "<a>Click here</a> to join the discussion!": "<a>Click here</a> 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.",
 | 
			
		||||
    "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please <issueLink>submit a bug report</issueLink>.": "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please <issueLink>submit a bug report</issueLink>.",
 | 
			
		||||
    "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.",
 | 
			
		||||
| 
						 | 
				
			
			@ -1245,7 +1256,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",
 | 
			
		||||
| 
						 | 
				
			
			@ -1279,7 +1289,6 @@
 | 
			
		|||
    "Hide": "Hide",
 | 
			
		||||
    "Home": "Home",
 | 
			
		||||
    "Sign in": "Sign in",
 | 
			
		||||
    "Login": "Login",
 | 
			
		||||
    "powered by Matrix": "powered by Matrix",
 | 
			
		||||
    "This homeserver would like to make sure you are not a robot.": "This homeserver would like to make sure you are not a robot.",
 | 
			
		||||
    "Custom Server Options": "Custom Server Options",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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}`;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue