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