2016-01-12 14:11:15 +00:00
/ *
Copyright 2015 , 2016 OpenMarket Ltd
2017-02-17 15:50:30 +00:00
Copyright 2017 Vector Creations Ltd
2016-01-12 14:11:15 +00:00
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' ;
2019-04-15 15:52:17 +00:00
import React from 'react' ;
2017-12-26 01:03:18 +00:00
import PropTypes from 'prop-types' ;
2019-04-15 15:52:17 +00:00
import sdk from '../../../index' ;
import MatrixClientPeg from '../../../MatrixClientPeg' ;
import dis from '../../../dispatcher' ;
2019-04-12 10:54:13 +00:00
import classNames from 'classnames' ;
2017-11-13 19:19:33 +00:00
import { _t } from '../../../languageHandler' ;
2017-05-23 14:16:31 +00:00
2019-04-12 12:40:31 +00:00
const MessageCase = Object . freeze ( {
NotLoggedIn : "NotLoggedIn" ,
Joining : "Joining" ,
Busy : "Busy" ,
Kicked : "Kicked" ,
Banned : "Banned" ,
OtherThreePIDError : "OtherThreePIDError" ,
2019-04-15 12:43:37 +00:00
InvitedEmailMismatch : "InvitedEmailMismatch" ,
2019-04-12 12:40:31 +00:00
Invite : "Invite" ,
ViewingRoom : "ViewingRoom" ,
RoomNotFound : "RoomNotFound" ,
OtherError : "OtherError" ,
} ) ;
2016-01-12 14:11:15 +00:00
module . exports = React . createClass ( {
displayName : 'RoomPreviewBar' ,
propTypes : {
2017-12-26 01:03:18 +00:00
onJoinClick : PropTypes . func ,
onRejectClick : PropTypes . func ,
onForgetClick : PropTypes . func ,
2019-04-12 12:40:31 +00:00
onSignInClick : PropTypes . func ,
onSignUpClick : PropTypes . func ,
2016-03-10 17:43:20 +00:00
// if inviterName is specified, the preview bar will shown an invite to the room.
// You should also specify onRejectClick if specifiying inviterName
2017-12-26 01:03:18 +00:00
inviterName : PropTypes . string ,
2016-03-17 18:38:25 +00:00
// If invited by 3rd party invite, the email address the invite was sent to
2017-12-26 01:03:18 +00:00
invitedEmail : PropTypes . string ,
2016-06-24 14:34:07 +00:00
// A standard client/server API error object. If supplied, indicates that the
// caller was unable to fetch details about the room for the given reason.
2017-12-26 01:03:18 +00:00
error : PropTypes . object ,
2016-06-24 14:34:07 +00:00
2017-12-26 01:03:18 +00:00
canPreview : PropTypes . bool ,
room : PropTypes . object ,
2016-06-28 13:59:45 +00:00
2018-10-17 19:53:12 +00:00
// When a spinner is present, a spinnerState can be specified to indicate the
// purpose of the spinner.
spinner : PropTypes . bool ,
spinnerState : PropTypes . oneOf ( [ "joining" ] ) ,
2016-06-28 13:59:45 +00:00
// The alias that was used to access this room, if appropriate
2016-06-28 16:11:47 +00:00
// If given, this will be how the room is referred to (eg.
// in error messages).
2017-12-26 01:03:18 +00:00
roomAlias : PropTypes . string ,
2016-01-12 14:11:15 +00:00
} ,
getDefaultProps : function ( ) {
return {
onJoinClick : function ( ) { } ,
} ;
} ,
2016-03-18 15:30:27 +00:00
getInitialState : function ( ) {
return {
2017-10-11 16:56:17 +00:00
busy : false ,
2017-01-20 14:22:27 +00:00
} ;
2016-03-18 15:30:27 +00:00
} ,
componentWillMount : function ( ) {
// If this is an invite and we've been told what email
2019-04-12 12:40:31 +00:00
// address was invited, fetch the user's list of Threepids
2016-03-18 15:30:27 +00:00
// so we can check them against the one that was invited
if ( this . props . inviterName && this . props . invitedEmail ) {
this . setState ( { busy : true } ) ;
MatrixClientPeg . get ( ) . lookupThreePid (
2017-10-11 16:56:17 +00:00
'email' , this . props . invitedEmail ,
2016-03-18 15:30:27 +00:00
) . finally ( ( ) => {
this . setState ( { busy : false } ) ;
} ) . done ( ( result ) => {
this . setState ( { invitedEmailMxid : result . mxid } ) ;
} , ( err ) => {
this . setState ( { threePidFetchError : err } ) ;
} ) ;
}
} ,
2019-04-12 12:40:31 +00:00
_getMessageCase ( ) {
if ( this . props . spinner || this . state . busy ) {
if ( this . props . spinnerState === "joining" ) {
return MessageCase . Joining ;
} else {
return MessageCase . Busy ;
}
}
2019-04-15 15:52:17 +00:00
const isGuest = MatrixClientPeg . get ( ) . isGuest ( ) ;
const myMember = ! isGuest && this . props . room ?
2019-04-12 12:40:31 +00:00
this . props . room . getMember ( MatrixClientPeg . get ( ) . getUserId ( ) ) :
null ;
2019-04-15 15:52:17 +00:00
if ( isGuest ) {
return MessageCase . NotLoggedIn ;
} else if ( this . props . inviterName ) {
2019-04-12 12:40:31 +00:00
if ( this . props . invitedEmail ) {
if ( this . state . threePidFetchError ) {
return MessageCase . OtherThreePIDError ;
} else if ( this . state . invitedEmailMxid != MatrixClientPeg . get ( ) . credentials . userId ) {
2019-04-15 12:43:37 +00:00
return MessageCase . InvitedEmailMismatch ;
2019-04-12 12:40:31 +00:00
}
}
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 } ;
} ,
2019-04-15 13:16:50 +00:00
_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 ;
}
}
2017-02-17 15:50:30 +00:00
} ,
2019-04-15 13:16:50 +00:00
_roomName : function ( ) {
return this . props . room ? this . props . room . name : ( this . props . room _alias || _t ( "This room" ) ) ;
} ,
2019-04-15 12:43:37 +00:00
2019-04-15 15:52:17 +00:00
onLoginClick : function ( ) {
dis . dispatch ( { action : 'start_login' } ) ;
} ,
onRegisterClick : function ( ) {
dis . dispatch ( { action : 'start_registration' } ) ;
} ,
2019-04-15 13:16:50 +00:00
render : function ( ) {
2019-04-12 12:40:31 +00:00
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" ) ;
2019-04-15 15:52:17 +00:00
primaryActionHandler = this . onRegisterClick ;
2019-04-12 12:40:31 +00:00
secondaryActionLabel = _t ( "Sign In" ) ;
2019-04-15 15:52:17 +00:00
secondaryActionHandler = this . onLoginClick ;
2019-04-12 12:40:31 +00:00
break ;
}
case MessageCase . Kicked : {
2019-04-15 12:43:37 +00:00
const { memberName , reason } = this . _getKickOrBanInfo ( ) ;
title = _t ( "You were kicked from this room by %(memberName)s" , { memberName } ) ;
subTitle = _t ( "Reason: %(reason)s" , { reason } ) ;
2019-04-12 12:40:31 +00:00
primaryActionLabel = _t ( "Re-join" ) ;
2019-04-15 12:43:37 +00:00
primaryActionHandler = this . props . onJoinClick ;
2019-04-12 12:40:31 +00:00
secondaryActionLabel = _t ( "Forget this room" ) ;
2019-04-15 12:43:37 +00:00
secondaryActionHandler = this . props . onForgetClick ;
2019-04-12 12:40:31 +00:00
break ;
}
case MessageCase . Banned : {
2019-04-15 12:43:37 +00:00
const { memberName , reason } = this . _getKickOrBanInfo ( ) ;
title = _t ( "You were banned from this room by %(memberName)s" , { memberName } ) ;
subTitle = _t ( "Reason: %(reason)s" , { reason } ) ;
2019-04-12 12:40:31 +00:00
primaryActionLabel = _t ( "Forget this room" ) ;
2019-04-15 12:43:37 +00:00
primaryActionHandler = this . props . onForgetClick ;
2019-04-12 12:40:31 +00:00
break ;
}
case MessageCase . OtherThreePIDError : {
2019-04-15 13:16:50 +00:00
title = _t ( "Something went wrong with your invite to this room" ) ;
const joinRule = this . _joinRule ( ) ;
2019-04-15 15:11:17 +00:00
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." ,
2019-04-15 13:25:34 +00:00
{ errcode : this . state . threePidFetchError . errcode } ,
) ;
2019-04-15 13:16:50 +00:00
switch ( joinRule ) {
case "invite" :
subTitle = [
2019-04-15 15:11:17 +00:00
_t ( "You can only join it with a working invite." ) ,
2019-04-15 13:22:08 +00:00
errCodeMessage ,
2019-04-15 13:16:50 +00:00
] ;
break ;
case "public" :
2019-04-15 15:11:17 +00:00
subTitle = _t ( "You can still join it because this is a public room." ) ;
2019-04-15 13:16:50 +00:00
primaryActionLabel = _t ( "Join the discussion" ) ;
primaryActionHandler = this . props . onJoinClick ;
break ;
default :
subTitle = errCodeMessage ;
primaryActionLabel = _t ( "Try to join anyway" ) ;
primaryActionHandler = this . props . onJoinClick ;
break ;
}
2019-04-12 12:40:31 +00:00
break ;
}
2019-04-15 12:43:37 +00:00
case MessageCase . InvitedEmailMismatch : {
2019-04-12 12:40:31 +00:00
title = _t ( "The room invite wasn't sent to your account" ) ;
2019-04-15 13:16:50 +00:00
const joinRule = this . _joinRule ( ) ;
2019-04-15 13:22:08 +00:00
if ( joinRule === "public" ) {
2019-04-15 15:11:17 +00:00
subTitle = _t ( "You can still join it because this is a public room." ) ;
2019-04-15 13:22:08 +00:00
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" ) ;
2019-04-15 13:16:50 +00:00
primaryActionHandler = this . props . onJoinClick ;
2019-04-15 13:22:08 +00:00
}
2019-04-15 13:16:50 +00:00
}
2019-04-12 12:40:31 +00:00
break ;
}
case MessageCase . Invite : {
2019-04-15 12:43:37 +00:00
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 } ) ;
}
2019-04-12 12:40:31 +00:00
primaryActionLabel = _t ( "Accept" ) ;
2019-04-15 12:43:37 +00:00
primaryActionHandler = this . props . onJoinClick ;
2019-04-12 12:40:31 +00:00
secondaryActionLabel = _t ( "Reject" ) ;
2019-04-15 12:43:37 +00:00
secondaryActionHandler = this . props . onRejectClick ;
2019-04-12 12:40:31 +00:00
break ;
}
case MessageCase . ViewingRoom : {
if ( this . props . canPreview ) {
2019-04-15 12:43:37 +00:00
title = _t ( "You're previewing this room. Want to join it?" ) ;
2019-04-12 12:40:31 +00:00
} else {
title = _t ( "This room can't be previewed. Do you want to join it?" ) ;
}
2019-04-15 12:43:37 +00:00
primaryActionLabel = _t ( "Join the discussion" ) ;
primaryActionHandler = this . props . onJoinClick ;
2019-04-12 12:40:31 +00:00
break ;
}
case MessageCase . RoomNotFound : {
2019-04-15 13:16:50 +00:00
title = _t ( "%(roomName)s does not exist." , { roomName : this . _roomName ( ) } ) ;
2019-04-15 12:43:37 +00:00
subTitle = _t ( "This room doesn't exist. Are you sure you're at the right place?" ) ;
2019-04-12 12:40:31 +00:00
break ;
}
case MessageCase . OtherError : {
2019-04-15 13:16:50 +00:00
title = _t ( "%(roomName)s is not accessible at this time." , { roomName : this . _roomName ( ) } ) ;
2019-04-15 15:11:17 +00:00
subTitle = [
2019-04-15 13:22:08 +00:00
_t ( "Try again later, or ask a room admin to check if you have access." ) ,
2019-04-15 15:11:17 +00:00
_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 > }
) ,
] ;
2019-04-12 12:40:31 +00:00
break ;
}
}
2019-04-15 12:43:37 +00:00
const AccessibleButton = sdk . getComponent ( 'elements.AccessibleButton' ) ;
2019-04-15 15:11:17 +00:00
const Spinner = sdk . getComponent ( 'elements.Spinner' ) ;
2017-02-17 15:50:30 +00:00
2019-04-15 12:43:37 +00:00
let subTitleElements ;
if ( subTitle ) {
2019-04-15 13:22:08 +00:00
if ( ! Array . isArray ( subTitle ) ) {
subTitle = [ subTitle ] ;
2016-06-24 14:34:07 +00:00
}
2019-04-15 13:22:08 +00:00
subTitleElements = subTitle . map ( ( t , i ) => < p key = { ` subTitle ${ i } ` } > { t } < / p > ) ;
2016-01-18 17:39:23 +00:00
}
2019-04-12 10:54:13 +00:00
const classes = classNames ( "mx_RoomPreviewBar" , "dark-panel" , {
"mx_RoomPreviewBar_panel" : this . props . canPreview ,
"mx_RoomPreviewBar_dialog" : ! this . props . canPreview ,
2019-04-15 15:11:17 +00:00
"mx_RoomPreviewBar_dark" : darkStyle ,
2019-04-12 10:54:13 +00:00
} ) ;
2019-04-15 15:11:17 +00:00
let titleElement ;
if ( showSpinner ) {
titleElement = < h3 className = "mx_RoomPreviewBar_spinnerTitle" > < Spinner / > { title } < / h 3 > ;
} else {
titleElement = < h3 > { title } < / h 3 > ;
}
2016-01-18 17:39:23 +00:00
return (
2019-04-12 10:54:13 +00:00
< div className = { classes } >
2019-04-15 12:43:37 +00:00
< div className = "mx_RoomPreviewBar_message" >
2019-04-15 15:11:17 +00:00
{ titleElement }
2019-04-15 12:43:37 +00:00
{ subTitleElements }
< / d i v >
< div className = "mx_RoomPreviewBar_actions" >
{ secondaryActionHandler ? < AccessibleButton kind = "secondary" onClick = { secondaryActionHandler } > { secondaryActionLabel } < / A c c e s s i b l e B u t t o n > : u n d e f i n e d }
{ primaryActionHandler ? < AccessibleButton kind = "primary" onClick = { primaryActionHandler } > { primaryActionLabel } < / A c c e s s i b l e B u t t o n > : u n d e f i n e d }
2016-01-18 19:56:56 +00:00
< / d i v >
2016-01-12 14:11:15 +00:00
< / d i v >
) ;
2019-04-15 12:43:37 +00:00
2017-10-11 16:56:17 +00:00
} ,
2016-01-12 14:11:15 +00:00
} ) ;