2021-07-28 22:15:52 +09:00
import React , { useState , useRef } from 'react' ;
import PropTypes from 'prop-types' ;
2021-08-31 22:13:31 +09:00
import './CreateRoom.scss' ;
2021-07-28 22:15:52 +09:00
import initMatrix from '../../../client/initMatrix' ;
import { isRoomAliasAvailable } from '../../../util/matrixUtil' ;
import * as roomActions from '../../../client/action/room' ;
2021-10-29 18:29:16 +09:00
import { selectRoom } from '../../../client/action/navigation' ;
2021-07-28 22:15:52 +09:00
import Text from '../../atoms/text/Text' ;
import Button from '../../atoms/button/Button' ;
import Toggle from '../../atoms/button/Toggle' ;
import IconButton from '../../atoms/button/IconButton' ;
import Input from '../../atoms/input/Input' ;
import Spinner from '../../atoms/spinner/Spinner' ;
2021-10-29 18:29:16 +09:00
import SegmentControl from '../../atoms/segmented-controls/SegmentedControls' ;
2021-07-28 22:15:52 +09:00
import PopupWindow from '../../molecules/popup-window/PopupWindow' ;
import SettingTile from '../../molecules/setting-tile/SettingTile' ;
import HashPlusIC from '../../../../public/res/ic/outlined/hash-plus.svg' ;
import CrossIC from '../../../../public/res/ic/outlined/cross.svg' ;
2021-08-31 22:13:31 +09:00
function CreateRoom ( { isOpen , onRequestClose } ) {
2021-07-28 22:15:52 +09:00
const [ isPublic , togglePublic ] = useState ( false ) ;
const [ isEncrypted , toggleEncrypted ] = useState ( true ) ;
const [ isValidAddress , updateIsValidAddress ] = useState ( null ) ;
const [ isCreatingRoom , updateIsCreatingRoom ] = useState ( false ) ;
const [ creatingError , updateCreatingError ] = useState ( null ) ;
const [ titleValue , updateTitleValue ] = useState ( undefined ) ;
const [ topicValue , updateTopicValue ] = useState ( undefined ) ;
const [ addressValue , updateAddressValue ] = useState ( undefined ) ;
2021-10-29 18:29:16 +09:00
const [ roleIndex , setRoleIndex ] = useState ( 0 ) ;
2021-07-28 22:15:52 +09:00
const addressRef = useRef ( null ) ;
const topicRef = useRef ( null ) ;
const nameRef = useRef ( null ) ;
const userId = initMatrix . matrixClient . getUserId ( ) ;
const hsString = userId . slice ( userId . indexOf ( ':' ) ) ;
function resetForm ( ) {
togglePublic ( false ) ;
toggleEncrypted ( true ) ;
updateIsValidAddress ( null ) ;
updateIsCreatingRoom ( false ) ;
updateCreatingError ( null ) ;
updateTitleValue ( undefined ) ;
updateTopicValue ( undefined ) ;
updateAddressValue ( undefined ) ;
2021-10-29 18:29:16 +09:00
setRoleIndex ( 0 ) ;
2021-07-28 22:15:52 +09:00
}
async function createRoom ( ) {
if ( isCreatingRoom ) return ;
updateIsCreatingRoom ( true ) ;
updateCreatingError ( null ) ;
const name = nameRef . current . value ;
let topic = topicRef . current . value ;
if ( topic . trim ( ) === '' ) topic = undefined ;
let roomAlias ;
if ( isPublic ) {
roomAlias = addressRef ? . current ? . value ;
if ( roomAlias . trim ( ) === '' ) roomAlias = undefined ;
}
2021-10-29 18:29:16 +09:00
const powerLevel = roleIndex === 1 ? 101 : undefined ;
2021-07-28 22:15:52 +09:00
try {
2021-10-29 18:29:16 +09:00
const result = await roomActions . create ( {
name , topic , isPublic , roomAlias , isEncrypted , powerLevel ,
2021-07-28 22:15:52 +09:00
} ) ;
resetForm ( ) ;
2021-10-29 18:29:16 +09:00
selectRoom ( result . room _id ) ;
2021-07-28 22:15:52 +09:00
onRequestClose ( ) ;
} catch ( e ) {
if ( e . message === 'M_UNKNOWN: Invalid characters in room alias' ) {
2021-08-31 22:13:31 +09:00
updateCreatingError ( 'ERROR: Invalid characters in room address' ) ;
2021-07-28 22:15:52 +09:00
updateIsValidAddress ( false ) ;
} else if ( e . message === 'M_ROOM_IN_USE: Room alias already taken' ) {
2021-08-31 22:13:31 +09:00
updateCreatingError ( 'ERROR: Room address is already in use' ) ;
2021-07-28 22:15:52 +09:00
updateIsValidAddress ( false ) ;
} else updateCreatingError ( e . message ) ;
}
updateIsCreatingRoom ( false ) ;
}
function validateAddress ( e ) {
const myAddress = e . target . value ;
updateIsValidAddress ( null ) ;
updateAddressValue ( e . target . value ) ;
updateCreatingError ( null ) ;
setTimeout ( async ( ) => {
if ( myAddress !== addressRef . current . value ) return ;
const roomAlias = addressRef . current . value ;
if ( roomAlias === '' ) return ;
const roomAddress = ` # ${ roomAlias } ${ hsString } ` ;
if ( await isRoomAliasAvailable ( roomAddress ) ) {
updateIsValidAddress ( true ) ;
} else {
updateIsValidAddress ( false ) ;
}
} , 1000 ) ;
}
function handleTitleChange ( e ) {
if ( e . target . value . trim ( ) === '' ) updateTitleValue ( undefined ) ;
updateTitleValue ( e . target . value ) ;
}
function handleTopicChange ( e ) {
if ( e . target . value . trim ( ) === '' ) updateTopicValue ( undefined ) ;
updateTopicValue ( e . target . value ) ;
}
return (
< PopupWindow
isOpen = { isOpen }
2021-08-31 22:13:31 +09:00
title = "Create room"
2021-07-28 22:15:52 +09:00
contentOptions = { < IconButton src = { CrossIC } onClick = { onRequestClose } tooltip = "Close" / > }
onRequestClose = { onRequestClose }
>
2021-08-31 22:13:31 +09:00
< div className = "create-room" >
< form className = "create-room__form" onSubmit = { ( e ) => { e . preventDefault ( ) ; createRoom ( ) ; } } >
2021-07-28 22:15:52 +09:00
< SettingTile
2021-08-31 22:13:31 +09:00
title = "Make room public"
2021-07-28 22:15:52 +09:00
options = { < Toggle isActive = { isPublic } onToggle = { togglePublic } / > }
2021-08-31 22:13:31 +09:00
content = { < Text variant = "b3" > Public room can be joined by anyone . < / Text > }
2021-07-28 22:15:52 +09:00
/ >
{ isPublic && (
< div >
2021-08-31 22:13:31 +09:00
< Text className = "create-room__address__label" variant = "b2" > Room address < / Text >
< div className = "create-room__address" >
2021-07-28 22:15:52 +09:00
< Text variant = "b1" > # < / Text >
< Input value = { addressValue } onChange = { validateAddress } state = { ( isValidAddress === false ) ? 'error' : 'normal' } forwardRef = { addressRef } placeholder = "my_room" required / >
< Text variant = "b1" > { hsString } < / Text >
< / div >
2021-08-31 22:13:31 +09:00
{ isValidAddress === false && < Text className = "create-room__address__tip" variant = "b3" > < span style = { { color : 'var(--bg-danger)' } } > { ` # ${ addressValue } ${ hsString } is already in use ` } < / span > < / Text > }
2021-07-28 22:15:52 +09:00
< / div >
) }
{ ! isPublic && (
< SettingTile
title = "Enable end-to-end encryption"
options = { < Toggle isActive = { isEncrypted } onToggle = { toggleEncrypted } / > }
content = { < Text variant = "b3" > You can ’ t disable this later . Bridges & most bots won ’ t work yet . < / Text > }
/ >
) }
2021-10-29 18:29:16 +09:00
< SettingTile
title = "Select your role"
options = { (
< SegmentControl
selected = { roleIndex }
segments = { [ { text : 'Admin' } , { text : 'Founder' } ] }
onSelect = { setRoleIndex }
/ >
) }
content = { (
< Text variant = "b3" > Override the default ( 100 ) power level . < / Text >
) }
/ >
2021-07-28 22:15:52 +09:00
< Input value = { topicValue } onChange = { handleTopicChange } forwardRef = { topicRef } minHeight = { 174 } resizable label = "Topic (optional)" / >
2021-08-31 22:13:31 +09:00
< div className = "create-room__name-wrapper" >
< Input value = { titleValue } onChange = { handleTitleChange } forwardRef = { nameRef } label = "Room name" required / >
2021-07-28 22:15:52 +09:00
< Button disabled = { isValidAddress === false || isCreatingRoom } iconSrc = { HashPlusIC } type = "submit" variant = "primary" > Create < / Button >
< / div >
{ isCreatingRoom && (
2021-08-31 22:13:31 +09:00
< div className = "create-room__loading" >
2021-07-28 22:15:52 +09:00
< Spinner size = "small" / >
2021-08-31 22:13:31 +09:00
< Text > Creating room ... < / Text >
2021-07-28 22:15:52 +09:00
< / div >
) }
2021-08-31 22:13:31 +09:00
{ typeof creatingError === 'string' && < Text className = "create-room__error" variant = "b3" > { creatingError } < / Text > }
2021-07-28 22:15:52 +09:00
< / form >
< / div >
< / PopupWindow >
) ;
}
2021-08-31 22:13:31 +09:00
CreateRoom . propTypes = {
2021-07-28 22:15:52 +09:00
isOpen : PropTypes . bool . isRequired ,
onRequestClose : PropTypes . func . isRequired ,
} ;
2021-08-31 22:13:31 +09:00
export default CreateRoom ;