2017-05-08 13:18:31 +03:00
/ *
2017-08-17 15:33:07 +03:00
Copyright 2017 Michael Telatynski < 7 t3chguy @ gmail . com >
2020-01-23 16:54:28 +03:00
Copyright 2020 The Matrix . org Foundation C . I . C .
2017-05-08 13:18:31 +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 .
* /
import React from 'react' ;
2019-08-24 13:59:46 +03:00
import createReactClass from 'create-react-class' ;
2017-12-26 04:03:18 +03:00
import PropTypes from 'prop-types' ;
2019-12-20 04:19:56 +03:00
import * as sdk from '../../../index' ;
2017-08-17 15:33:07 +03:00
import SdkConfig from '../../../SdkConfig' ;
2019-09-20 18:39:46 +03:00
import withValidation from '../elements/Validation' ;
2017-08-02 15:41:26 +03:00
import { _t } from '../../../languageHandler' ;
2019-12-21 00:13:46 +03:00
import { MatrixClientPeg } from '../../../MatrixClientPeg' ;
2019-10-09 21:59:11 +03:00
import { Key } from "../../../Keyboard" ;
2020-04-08 12:50:22 +03:00
import SettingsStore from "../../../settings/SettingsStore" ;
2017-05-08 13:18:31 +03:00
2019-08-24 13:59:46 +03:00
export default createReactClass ( {
2017-08-17 15:33:07 +03:00
displayName : 'CreateRoomDialog' ,
2017-05-08 13:18:31 +03:00
propTypes : {
2017-12-26 04:03:18 +03:00
onFinished : PropTypes . func . isRequired ,
2020-05-12 12:55:46 +03:00
defaultPublic : PropTypes . bool ,
2017-05-08 13:18:31 +03:00
} ,
2019-09-20 18:39:46 +03:00
getInitialState ( ) {
2017-08-17 15:33:07 +03:00
const config = SdkConfig . get ( ) ;
2019-09-20 18:39:46 +03:00
return {
2020-05-12 12:55:46 +03:00
isPublic : this . props . defaultPublic || false ,
2020-04-08 12:50:22 +03:00
isEncrypted : true ,
2019-09-20 18:39:46 +03:00
name : "" ,
2019-09-20 18:41:03 +03:00
topic : "" ,
2019-09-20 18:46:14 +03:00
alias : "" ,
2019-09-20 18:44:07 +03:00
detailsOpen : false ,
2019-09-20 18:39:46 +03:00
noFederate : config . default _federate === false ,
nameIsValid : false ,
} ;
2017-05-08 13:18:31 +03:00
} ,
2019-09-20 18:39:46 +03:00
_roomCreateOptions ( ) {
2020-01-23 16:54:28 +03:00
const opts = { } ;
const createOpts = opts . createOpts = { } ;
2019-09-20 18:39:46 +03:00
createOpts . name = this . state . name ;
2019-09-20 18:43:14 +03:00
if ( this . state . isPublic ) {
createOpts . visibility = "public" ;
createOpts . preset = "public_chat" ;
2020-01-23 16:54:28 +03:00
opts . guestAccess = false ;
2019-09-20 18:46:14 +03:00
const { alias } = this . state ;
const localPart = alias . substr ( 1 , alias . indexOf ( ":" ) - 1 ) ;
createOpts [ 'room_alias_name' ] = localPart ;
}
2019-09-20 18:41:03 +03:00
if ( this . state . topic ) {
createOpts . topic = this . state . topic ;
}
2019-09-20 18:39:46 +03:00
if ( this . state . noFederate ) {
createOpts . creation _content = { 'm.federate' : false } ;
}
2020-04-08 12:50:22 +03:00
2020-04-15 22:18:42 +03:00
if ( ! this . state . isPublic && SettingsStore . getValue ( "feature_cross_signing" ) ) {
2020-04-14 15:05:23 +03:00
opts . encryption = this . state . isEncrypted ;
2020-04-08 12:50:22 +03:00
}
2020-01-23 16:54:28 +03:00
return opts ;
2019-09-20 18:39:46 +03:00
} ,
componentDidMount ( ) {
this . _detailsRef . addEventListener ( "toggle" , this . onDetailsToggled ) ;
2019-09-25 16:08:48 +03:00
// move focus to first field when showing dialog
this . _nameFieldRef . focus ( ) ;
2019-09-20 18:39:46 +03:00
} ,
componentWillUnmount ( ) {
this . _detailsRef . removeEventListener ( "toggle" , this . onDetailsToggled ) ;
} ,
2019-10-02 17:26:52 +03:00
_onKeyDown : function ( event ) {
2019-10-09 21:59:11 +03:00
if ( event . key === Key . ENTER ) {
2019-10-02 17:26:52 +03:00
this . onOk ( ) ;
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
}
} ,
2019-09-20 18:39:46 +03:00
onOk : async function ( ) {
2019-09-20 18:46:47 +03:00
const activeElement = document . activeElement ;
if ( activeElement ) {
activeElement . blur ( ) ;
}
await this . _nameFieldRef . validate ( { allowEmpty : false } ) ;
if ( this . _aliasFieldRef ) {
await this . _aliasFieldRef . validate ( { allowEmpty : false } ) ;
}
// Validation and state updates are async, so we need to wait for them to complete
// first. Queue a `setState` callback and wait for it to resolve.
await new Promise ( resolve => this . setState ( { } , resolve ) ) ;
if ( this . state . nameIsValid && ( ! this . _aliasFieldRef || this . _aliasFieldRef . isValid ) ) {
2019-09-20 18:39:46 +03:00
this . props . onFinished ( true , this . _roomCreateOptions ( ) ) ;
2019-09-20 18:46:47 +03:00
} else {
let field ;
if ( ! this . state . nameIsValid ) {
field = this . _nameFieldRef ;
} else if ( this . _aliasFieldRef && ! this . _aliasFieldRef . isValid ) {
field = this . _aliasFieldRef ;
}
if ( field ) {
field . focus ( ) ;
field . validate ( { allowEmpty : false , focused : true } ) ;
}
}
2017-05-08 13:18:31 +03:00
} ,
onCancel : function ( ) {
this . props . onFinished ( false ) ;
} ,
2019-09-20 18:39:46 +03:00
onNameChange ( ev ) {
this . setState ( { name : ev . target . value } ) ;
} ,
2019-09-20 18:41:03 +03:00
onTopicChange ( ev ) {
this . setState ( { topic : ev . target . value } ) ;
} ,
2019-09-20 18:43:14 +03:00
onPublicChange ( isPublic ) {
this . setState ( { isPublic } ) ;
} ,
2020-04-08 12:50:22 +03:00
onEncryptedChange ( isEncrypted ) {
this . setState ( { isEncrypted } ) ;
} ,
2019-09-20 18:46:14 +03:00
onAliasChange ( alias ) {
this . setState ( { alias } ) ;
} ,
2019-09-20 18:39:46 +03:00
onDetailsToggled ( ev ) {
this . setState ( { detailsOpen : ev . target . open } ) ;
} ,
onNoFederateChange ( noFederate ) {
this . setState ( { noFederate } ) ;
} ,
collectDetailsRef ( ref ) {
this . _detailsRef = ref ;
} ,
async onNameValidate ( fieldState ) {
const result = await this . _validateRoomName ( fieldState ) ;
this . setState ( { nameIsValid : result . valid } ) ;
return result ;
} ,
_validateRoomName : withValidation ( {
rules : [
{
key : "required" ,
test : async ( { value } ) => ! ! value ,
invalid : ( ) => _t ( "Please enter a name for the room" ) ,
} ,
] ,
} ) ,
2017-05-08 13:18:31 +03:00
render : function ( ) {
const BaseDialog = sdk . getComponent ( 'views.dialogs.BaseDialog' ) ;
2017-12-23 03:42:44 +03:00
const DialogButtons = sdk . getComponent ( 'views.elements.DialogButtons' ) ;
2019-09-20 18:39:46 +03:00
const Field = sdk . getComponent ( 'views.elements.Field' ) ;
const LabelledToggleSwitch = sdk . getComponent ( 'views.elements.LabelledToggleSwitch' ) ;
2019-09-20 18:46:14 +03:00
const RoomAliasField = sdk . getComponent ( 'views.elements.RoomAliasField' ) ;
2020-04-08 15:47:15 +03:00
let publicPrivateLabel ;
2019-09-20 18:46:14 +03:00
let aliasField ;
2019-09-20 18:43:14 +03:00
if ( this . state . isPublic ) {
2020-04-14 12:06:57 +03:00
publicPrivateLabel = ( < p > { _t ( "Set a room address to easily share your room with other people." ) } < / p > ) ;
2019-09-20 18:46:14 +03:00
const domain = MatrixClientPeg . get ( ) . getDomain ( ) ;
aliasField = (
< div className = "mx_CreateRoomDialog_aliasContainer" >
2020-03-30 00:59:15 +03:00
< RoomAliasField ref = { ref => this . _aliasFieldRef = ref } onChange = { this . onAliasChange } domain = { domain } value = { this . state . alias } / >
2019-09-20 18:46:14 +03:00
< / d i v >
) ;
2019-09-20 18:43:14 +03:00
} else {
2020-04-08 15:47:15 +03:00
publicPrivateLabel = ( < p > { _t ( "This room is private, and can only be joined by invitation." ) } < / p > ) ;
2019-09-20 18:43:14 +03:00
}
2020-04-08 12:50:22 +03:00
let e2eeSection ;
2020-04-15 22:18:42 +03:00
if ( ! this . state . isPublic && SettingsStore . getValue ( "feature_cross_signing" ) ) {
2020-04-08 12:50:22 +03:00
e2eeSection = < React . Fragment >
2020-04-17 01:27:43 +03:00
< LabelledToggleSwitch
label = { _t ( "Enable end-to-end encryption" ) }
onChange = { this . onEncryptedChange }
value = { this . state . isEncrypted }
className = 'mx_CreateRoomDialog_e2eSwitch' // for end-to-end tests
/ >
2020-04-08 16:44:34 +03:00
< p > { _t ( "You can’ t disable this later. Bridges & most bots won’ t work yet." ) } < / p >
2020-04-08 12:50:22 +03:00
< / R e a c t . F r a g m e n t > ;
}
2019-09-20 18:43:14 +03:00
const title = this . state . isPublic ? _t ( 'Create a public room' ) : _t ( 'Create a private room' ) ;
2017-05-08 13:18:31 +03:00
return (
2017-08-17 15:33:07 +03:00
< BaseDialog className = "mx_CreateRoomDialog" onFinished = { this . props . onFinished }
2019-09-20 18:43:14 +03:00
title = { title }
2017-05-08 13:18:31 +03:00
>
2019-10-02 17:26:52 +03:00
< form onSubmit = { this . onOk } onKeyDown = { this . _onKeyDown } >
2017-12-03 23:38:21 +03:00
< div className = "mx_Dialog_content" >
2020-03-30 00:59:15 +03:00
< Field ref = { ref => this . _nameFieldRef = ref } label = { _t ( 'Name' ) } onChange = { this . onNameChange } onValidate = { this . onNameValidate } value = { this . state . name } className = "mx_CreateRoomDialog_name" / >
2020-04-08 15:47:15 +03:00
< Field label = { _t ( 'Topic (optional)' ) } onChange = { this . onTopicChange } value = { this . state . topic } className = "mx_CreateRoomDialog_topic" / >
2019-09-20 18:43:14 +03:00
< LabelledToggleSwitch label = { _t ( "Make this room public" ) } onChange = { this . onPublicChange } value = { this . state . isPublic } / >
2020-04-08 15:47:15 +03:00
{ publicPrivateLabel }
2020-04-08 12:50:22 +03:00
{ e2eeSection }
2019-09-20 18:46:14 +03:00
{ aliasField }
2019-09-20 18:39:46 +03:00
< details ref = { this . collectDetailsRef } className = "mx_CreateRoomDialog_details" >
< summary className = "mx_CreateRoomDialog_details_summary" > { this . state . detailsOpen ? _t ( 'Hide advanced' ) : _t ( 'Show advanced' ) } < / s u m m a r y >
< LabelledToggleSwitch label = { _t ( 'Block users on other matrix homeservers from joining this room (This setting cannot be changed later!)' ) } onChange = { this . onNoFederateChange } value = { this . state . noFederate } / >
2018-02-08 23:16:57 +03:00
< / d e t a i l s >
2017-12-03 23:38:21 +03:00
< / d i v >
< / f o r m >
2017-12-23 03:42:44 +03:00
< DialogButtons primaryButton = { _t ( 'Create Room' ) }
onPrimaryButtonClick = { this . onOk }
onCancel = { this . onCancel } / >
2017-05-08 13:18:31 +03:00
< / B a s e D i a l o g >
) ;
} ,
} ) ;