2015-11-27 13:42:03 +03:00
/ *
2016-01-07 07:06:39 +03:00
Copyright 2015 , 2016 OpenMarket Ltd
2017-02-14 21:10:40 +03:00
Copyright 2017 Vector Creations Ltd
2015-11-27 13:42:03 +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 .
* /
2017-07-12 15:58:14 +03:00
import Promise from 'bluebird' ;
2017-02-14 20:06:16 +03:00
import React from 'react' ;
2017-06-08 16:08:51 +03:00
import { _t , _tJsx } from '../../../languageHandler' ;
2017-02-15 21:58:59 +03:00
import MatrixClientPeg from '../../../MatrixClientPeg' ;
2017-02-14 20:06:16 +03:00
import SdkConfig from '../../../SdkConfig' ;
import sdk from '../../../index' ;
import Modal from '../../../Modal' ;
import ObjectUtils from '../../../ObjectUtils' ;
import dis from '../../../dispatcher' ;
import UserSettingsStore from '../../../UserSettingsStore' ;
import AccessibleButton from '../elements/AccessibleButton' ;
2017-01-22 00:49:29 +03:00
2015-11-27 13:42:03 +03:00
2016-06-23 12:36:16 +03:00
// parse a string as an integer; if the input is undefined, or cannot be parsed
// as an integer, return a default.
function parseIntWithDefault ( val , def ) {
var res = parseInt ( val ) ;
return isNaN ( res ) ? def : res ;
}
2017-02-15 21:58:59 +03:00
const BannedUser = React . createClass ( {
2017-02-14 20:54:57 +03:00
propTypes : {
2017-07-06 14:51:55 +03:00
canUnban : React . PropTypes . bool ,
2017-02-15 22:01:00 +03:00
member : React . PropTypes . object . isRequired , // js-sdk RoomMember
2017-06-10 18:30:46 +03:00
reason : React . PropTypes . string ,
2017-02-14 20:54:57 +03:00
} ,
_onUnbanClick : function ( ) {
const ConfirmUserActionDialog = sdk . getComponent ( "dialogs.ConfirmUserActionDialog" ) ;
2017-07-27 19:19:18 +03:00
Modal . createTrackedDialog ( 'Confirm User Action Dialog' , 'onUnbanClick' , ConfirmUserActionDialog , {
2017-02-14 20:54:57 +03:00
member : this . props . member ,
2017-06-08 16:08:51 +03:00
action : _t ( 'Unban' ) ,
2017-02-14 20:54:57 +03:00
danger : false ,
onFinished : ( proceed ) => {
if ( ! proceed ) return ;
2017-02-15 21:58:59 +03:00
MatrixClientPeg . get ( ) . unban (
2017-02-14 20:54:57 +03:00
this . props . member . roomId , this . props . member . userId ,
) . catch ( ( err ) => {
const ErrorDialog = sdk . getComponent ( "dialogs.ErrorDialog" ) ;
2017-03-13 01:59:41 +03:00
console . error ( "Failed to unban: " + err ) ;
2017-08-10 15:49:11 +03:00
Modal . createTrackedDialog ( 'Failed to unban' , '' , ErrorDialog , {
2017-05-23 17:16:31 +03:00
title : _t ( 'Error' ) ,
description : _t ( 'Failed to unban' ) ,
2017-02-14 20:54:57 +03:00
} ) ;
} ) . done ( ) ;
} ,
} ) ;
} ,
render : function ( ) {
2017-07-06 14:51:55 +03:00
let unbanButton ;
if ( this . props . canUnban ) {
unbanButton = < AccessibleButton className = "mx_RoomSettings_unbanButton" onClick = { this . _onUnbanClick } >
{ _t ( 'Unban' ) }
< / A c c e s s i b l e B u t t o n > ;
}
2017-02-14 20:54:57 +03:00
return (
< li >
2017-07-06 14:51:55 +03:00
{ unbanButton }
2017-06-11 09:13:50 +03:00
< strong > { this . props . member . name } < / s t r o n g > { t h i s . p r o p s . m e m b e r . u s e r I d }
2017-06-10 18:30:46 +03:00
{ this . props . reason ? " " + _t ( 'Reason' ) + ": " + this . props . reason : "" }
2017-02-14 20:54:57 +03:00
< / l i >
) ;
2017-06-10 18:30:46 +03:00
} ,
2017-02-15 21:58:59 +03:00
} ) ;
2017-02-14 20:54:57 +03:00
2017-02-15 21:58:59 +03:00
module . exports = React . createClass ( {
2015-11-27 13:42:03 +03:00
displayName : 'RoomSettings' ,
propTypes : {
room : React . PropTypes . object . isRequired ,
2016-01-17 06:59:31 +03:00
onSaveClick : React . PropTypes . func ,
2015-11-27 13:42:03 +03:00
} ,
getInitialState : function ( ) {
2016-01-17 08:13:16 +03:00
var tags = { } ;
Object . keys ( this . props . room . tags ) . forEach ( function ( tagName ) {
2016-05-31 23:44:11 +03:00
tags [ tagName ] = [ 'yep' ] ;
2016-01-17 08:13:16 +03:00
} ) ;
2015-11-27 13:42:03 +03:00
return {
2016-02-04 18:26:12 +03:00
name : this . _yankValueFromEvent ( "m.room.name" , "name" ) ,
topic : this . _yankValueFromEvent ( "m.room.topic" , "topic" ) ,
join _rule : this . _yankValueFromEvent ( "m.room.join_rules" , "join_rule" ) ,
history _visibility : this . _yankValueFromEvent ( "m.room.history_visibility" , "history_visibility" ) ,
guest _access : this . _yankValueFromEvent ( "m.room.guest_access" , "guest_access" ) ,
2016-01-08 06:22:38 +03:00
power _levels _changed : false ,
2016-01-17 08:13:16 +03:00
tags _changed : false ,
tags : tags ,
2016-07-18 17:22:08 +03:00
// isRoomPublished is loaded async in componentWillMount so when the component
// inits, the saved value will always be undefined, however getInitialState()
// is also called from the saving code so we must return the correct value here
// if we have it (although this could race if the user saves before we load whether
2016-07-18 17:36:19 +03:00
// the room is published or not).
2016-08-03 20:23:38 +03:00
// Default to false if it's undefined, otherwise react complains about changing
// components from uncontrolled to controlled
isRoomPublished : this . _originalIsRoomPublished || false ,
2015-11-27 13:42:03 +03:00
} ;
} ,
2016-03-22 03:57:40 +03:00
componentWillMount : function ( ) {
2017-02-15 21:58:59 +03:00
MatrixClientPeg . get ( ) . on ( "RoomMember.membership" , this . _onRoomMemberMembership ) ;
2017-02-14 20:54:57 +03:00
2017-02-15 21:58:59 +03:00
MatrixClientPeg . get ( ) . getRoomDirectoryVisibility (
2016-03-22 03:57:40 +03:00
this . props . room . roomId
) . done ( ( result ) => {
2016-03-22 15:10:58 +03:00
this . setState ( { isRoomPublished : result . visibility === "public" } ) ;
2016-04-12 03:27:12 +03:00
this . _originalIsRoomPublished = result . visibility === "public" ;
2016-03-22 03:57:40 +03:00
} , ( err ) => {
console . error ( "Failed to get room visibility: " + err ) ;
} ) ;
2016-04-12 19:18:32 +03:00
dis . dispatch ( {
action : 'ui_opacity' ,
sideOpacity : 0.3 ,
middleOpacity : 0.3 ,
} ) ;
} ,
componentWillUnmount : function ( ) {
2017-02-15 22:01:00 +03:00
const cli = MatrixClientPeg . get ( ) ;
if ( cli ) {
cli . removeListener ( "RoomMember.membership" , this . _onRoomMemberMembership ) ;
}
2017-02-14 20:54:57 +03:00
2016-04-12 19:18:32 +03:00
dis . dispatch ( {
action : 'ui_opacity' ,
sideOpacity : 1.0 ,
middleOpacity : 1.0 ,
} ) ;
2016-03-22 03:57:40 +03:00
} ,
2016-04-12 03:27:12 +03:00
2016-02-04 18:26:12 +03:00
setName : function ( name ) {
this . setState ( {
name : name
} ) ;
} ,
2016-04-12 03:27:12 +03:00
2016-02-04 18:26:12 +03:00
setTopic : function ( topic ) {
this . setState ( {
topic : topic
} ) ;
} ,
2016-04-12 03:27:12 +03:00
2017-07-12 17:15:59 +03:00
/ * *
* Returns a promise which resolves once all of the save operations have completed or failed .
*
* The result is a list of promise state snapshots , each with the form
* ` { state: "fulfilled", value: v } ` or ` { state: "rejected", reason: r } ` .
* /
2016-02-04 18:26:12 +03:00
save : function ( ) {
2017-07-12 16:04:20 +03:00
var stateWasSetDefer = Promise . defer ( ) ;
2016-02-04 18:26:12 +03:00
// the caller may have JUST called setState on stuff, so we need to re-render before saving
// else we won't use the latest values of things.
// We can be a bit cheeky here and set a loading flag, and listen for the callback on that
// to know when things have been set.
this . setState ( { _loading : true } , ( ) => {
stateWasSetDefer . resolve ( ) ;
this . setState ( { _loading : false } ) ;
} ) ;
2016-04-12 03:27:12 +03:00
2017-07-12 17:15:59 +03:00
function mapPromiseToSnapshot ( p ) {
return p . then ( ( r ) => {
return { state : "fulfilled" , value : r } ;
} , ( e ) => {
return { state : "rejected" , reason : e } ;
} ) ;
}
2016-02-04 18:26:12 +03:00
return stateWasSetDefer . promise . then ( ( ) => {
2017-07-12 17:15:59 +03:00
return Promise . all (
this . _calcSavePromises ( ) . map ( mapPromiseToSnapshot ) ,
) ;
2016-02-04 18:26:12 +03:00
} ) ;
} ,
2016-09-15 02:43:30 +03:00
_calcSavePromises : function ( ) {
2016-02-04 18:26:12 +03:00
const roomId = this . props . room . roomId ;
var promises = this . saveAliases ( ) ; // returns Promise[]
var originalState = this . getInitialState ( ) ;
2016-02-05 14:59:19 +03:00
2016-02-04 18:26:12 +03:00
// diff between original state and this.state to work out what has been changed
console . log ( "Original: %s" , JSON . stringify ( originalState ) ) ;
console . log ( "New: %s" , JSON . stringify ( this . state ) ) ;
2016-02-05 14:59:19 +03:00
// name and topic
2016-02-05 14:27:11 +03:00
if ( this . _hasDiff ( this . state . name , originalState . name ) ) {
2017-02-15 21:58:59 +03:00
promises . push ( MatrixClientPeg . get ( ) . setRoomName ( roomId , this . state . name ) ) ;
2016-02-04 18:26:12 +03:00
}
2016-02-05 14:27:11 +03:00
if ( this . _hasDiff ( this . state . topic , originalState . topic ) ) {
2017-02-15 21:58:59 +03:00
promises . push ( MatrixClientPeg . get ( ) . setRoomTopic ( roomId , this . state . topic ) ) ;
2016-02-04 18:26:12 +03:00
}
2016-02-05 14:59:19 +03:00
2016-02-05 17:38:28 +03:00
if ( this . state . history _visibility !== originalState . history _visibility ) {
2017-02-15 21:58:59 +03:00
promises . push ( MatrixClientPeg . get ( ) . sendStateEvent (
2016-02-05 17:38:28 +03:00
roomId , "m.room.history_visibility" ,
{ history _visibility : this . state . history _visibility } ,
""
) ) ;
}
2016-03-22 03:57:40 +03:00
if ( this . state . isRoomPublished !== originalState . isRoomPublished ) {
2017-02-15 21:58:59 +03:00
promises . push ( MatrixClientPeg . get ( ) . setRoomDirectoryVisibility (
2016-04-12 03:27:12 +03:00
roomId ,
2016-03-22 03:57:40 +03:00
this . state . isRoomPublished ? "public" : "private"
) ) ;
}
2016-02-05 17:38:28 +03:00
if ( this . state . join _rule !== originalState . join _rule ) {
2017-02-15 21:58:59 +03:00
promises . push ( MatrixClientPeg . get ( ) . sendStateEvent (
2016-02-05 17:38:28 +03:00
roomId , "m.room.join_rules" ,
{ join _rule : this . state . join _rule } ,
""
) ) ;
}
if ( this . state . guest _access !== originalState . guest _access ) {
2017-02-15 21:58:59 +03:00
promises . push ( MatrixClientPeg . get ( ) . sendStateEvent (
2016-02-05 17:38:28 +03:00
roomId , "m.room.guest_access" ,
{ guest _access : this . state . guest _access } ,
""
) ) ;
}
2016-02-05 14:59:19 +03:00
2016-02-04 18:26:12 +03:00
// power levels
2016-02-05 14:59:19 +03:00
var powerLevels = this . _getPowerLevels ( ) ;
if ( powerLevels ) {
2017-02-15 21:58:59 +03:00
promises . push ( MatrixClientPeg . get ( ) . sendStateEvent (
2016-02-05 14:59:19 +03:00
roomId , "m.room.power_levels" , powerLevels , ""
) ) ;
}
2016-02-04 18:26:12 +03:00
// tags
2016-02-05 14:59:19 +03:00
if ( this . state . tags _changed ) {
var tagDiffs = ObjectUtils . getKeyValueArrayDiffs ( originalState . tags , this . state . tags ) ;
2016-05-31 23:44:11 +03:00
// [ {place: add, key: "m.favourite", val: ["yep"]} ]
2016-02-05 14:59:19 +03:00
tagDiffs . forEach ( function ( diff ) {
switch ( diff . place ) {
case "add" :
promises . push (
2017-02-15 21:58:59 +03:00
MatrixClientPeg . get ( ) . setRoomTag ( roomId , diff . key , { } )
2016-02-05 14:59:19 +03:00
) ;
break ;
case "del" :
promises . push (
2017-02-15 21:58:59 +03:00
MatrixClientPeg . get ( ) . deleteRoomTag ( roomId , diff . key )
2016-02-05 14:59:19 +03:00
) ;
break ;
default :
console . error ( "Unknown tag operation: %s" , diff . place ) ;
break ;
}
} ) ;
}
2016-02-05 14:27:11 +03:00
2016-02-04 18:26:12 +03:00
// color scheme
2016-09-15 02:43:30 +03:00
var p ;
p = this . saveColor ( ) ;
2017-07-14 16:24:35 +03:00
if ( ! p . isFulfilled ( ) ) {
2016-09-15 02:43:30 +03:00
promises . push ( p ) ;
}
2016-04-12 03:27:12 +03:00
2016-07-20 14:03:13 +03:00
// url preview settings
2016-09-15 02:43:30 +03:00
var ps = this . saveUrlPreviewSettings ( ) ;
if ( ps . length > 0 ) {
2016-09-15 02:49:10 +03:00
promises . push ( ps ) ;
2016-09-15 02:43:30 +03:00
}
2016-07-20 14:03:13 +03:00
2016-06-23 14:21:31 +03:00
// encryption
2017-01-21 20:39:31 +03:00
p = this . saveEnableEncryption ( ) ;
2017-07-14 16:24:35 +03:00
if ( ! p . isFulfilled ( ) ) {
2016-09-15 02:43:30 +03:00
promises . push ( p ) ;
}
2016-06-23 14:21:31 +03:00
2017-01-21 20:39:31 +03:00
this . saveBlacklistUnverifiedDevicesPerRoom ( ) ;
2016-07-20 14:03:13 +03:00
console . log ( "Performing %s operations: %s" , promises . length , JSON . stringify ( promises ) ) ;
2016-09-15 02:43:30 +03:00
return promises ;
2016-02-04 18:26:12 +03:00
} ,
2015-11-27 13:42:03 +03:00
2016-02-02 15:46:14 +03:00
saveAliases : function ( ) {
2017-07-12 16:02:00 +03:00
if ( ! this . refs . alias _settings ) { return [ Promise . resolve ( ) ] ; }
2016-02-02 15:46:14 +03:00
return this . refs . alias _settings . saveSettings ( ) ;
} ,
2016-02-05 14:27:11 +03:00
saveColor : function ( ) {
2017-07-12 16:02:00 +03:00
if ( ! this . refs . color _settings ) { return Promise . resolve ( ) ; }
2016-02-05 14:27:11 +03:00
return this . refs . color _settings . saveSettings ( ) ;
} ,
2016-07-20 14:03:13 +03:00
saveUrlPreviewSettings : function ( ) {
2017-07-12 16:02:00 +03:00
if ( ! this . refs . url _preview _settings ) { return Promise . resolve ( ) ; }
2016-07-20 14:03:13 +03:00
return this . refs . url _preview _settings . saveSettings ( ) ;
} ,
2017-01-21 20:39:31 +03:00
saveEnableEncryption : function ( ) {
2017-07-12 16:02:00 +03:00
if ( ! this . refs . encrypt ) { return Promise . resolve ( ) ; }
2016-06-23 14:21:31 +03:00
var encrypt = this . refs . encrypt . checked ;
2017-07-12 16:02:00 +03:00
if ( ! encrypt ) { return Promise . resolve ( ) ; }
2016-06-23 14:21:31 +03:00
var roomId = this . props . room . roomId ;
2017-02-15 21:58:59 +03:00
return MatrixClientPeg . get ( ) . sendStateEvent (
2016-06-23 14:21:31 +03:00
roomId , "m.room.encryption" ,
2016-09-03 20:42:54 +03:00
{ algorithm : "m.megolm.v1.aes-sha2" }
2016-06-23 14:21:31 +03:00
) ;
} ,
2017-01-21 20:39:31 +03:00
saveBlacklistUnverifiedDevicesPerRoom : function ( ) {
if ( ! this . refs . blacklistUnverified ) return ;
if ( this . _isRoomBlacklistUnverified ( ) !== this . refs . blacklistUnverified . checked ) {
this . _setRoomBlacklistUnverified ( this . refs . blacklistUnverified . checked ) ;
}
} ,
_isRoomBlacklistUnverified : function ( ) {
var blacklistUnverifiedDevicesPerRoom = UserSettingsStore . getLocalSettings ( ) . blacklistUnverifiedDevicesPerRoom ;
if ( blacklistUnverifiedDevicesPerRoom ) {
return blacklistUnverifiedDevicesPerRoom [ this . props . room . roomId ] ;
}
return false ;
} ,
_setRoomBlacklistUnverified : function ( value ) {
2017-01-22 00:49:29 +03:00
var blacklistUnverifiedDevicesPerRoom = UserSettingsStore . getLocalSettings ( ) . blacklistUnverifiedDevicesPerRoom || { } ;
2017-01-21 20:39:31 +03:00
blacklistUnverifiedDevicesPerRoom [ this . props . room . roomId ] = value ;
2017-01-22 00:49:29 +03:00
UserSettingsStore . setLocalSetting ( 'blacklistUnverifiedDevicesPerRoom' , blacklistUnverifiedDevicesPerRoom ) ;
2017-01-21 20:39:31 +03:00
this . props . room . setBlacklistUnverifiedDevices ( value ) ;
} ,
2016-02-05 14:27:11 +03:00
_hasDiff : function ( strA , strB ) {
// treat undefined as an empty string because other components may blindly
// call setName("") when there has been no diff made to the name!
strA = strA || "" ;
strB = strB || "" ;
return strA !== strB ;
} ,
2016-02-05 14:59:19 +03:00
_getPowerLevels : function ( ) {
2015-11-27 13:42:03 +03:00
if ( ! this . state . power _levels _changed ) return undefined ;
2016-02-05 18:48:04 +03:00
var powerLevels = this . props . room . currentState . getStateEvents ( 'm.room.power_levels' , '' ) ;
powerLevels = powerLevels ? powerLevels . getContent ( ) : { } ;
2015-11-27 13:42:03 +03:00
2017-09-29 23:02:31 +03:00
for ( let key of Object . keys ( this . refs ) . filter ( k => k . startsWith ( "event_levels_" ) ) ) {
const eventType = key . substring ( "event_levels_" . length ) ;
powerLevels . events [ eventType ] = parseInt ( this . refs [ key ] . getValue ( ) ) ;
}
2016-02-05 18:48:04 +03:00
var newPowerLevels = {
2016-01-17 05:48:55 +03:00
ban : parseInt ( this . refs . ban . getValue ( ) ) ,
kick : parseInt ( this . refs . kick . getValue ( ) ) ,
redact : parseInt ( this . refs . redact . getValue ( ) ) ,
invite : parseInt ( this . refs . invite . getValue ( ) ) ,
events _default : parseInt ( this . refs . events _default . getValue ( ) ) ,
state _default : parseInt ( this . refs . state _default . getValue ( ) ) ,
users _default : parseInt ( this . refs . users _default . getValue ( ) ) ,
2016-02-05 18:48:04 +03:00
users : powerLevels . users ,
events : powerLevels . events ,
2015-11-27 13:42:03 +03:00
} ;
2016-02-05 18:48:04 +03:00
return newPowerLevels ;
2015-11-27 13:42:03 +03:00
} ,
onPowerLevelsChanged : function ( ) {
this . setState ( {
power _levels _changed : true
} ) ;
} ,
2016-06-23 12:36:16 +03:00
2016-02-04 18:26:12 +03:00
_yankValueFromEvent : function ( stateEventType , keyName , defaultValue ) {
// E.g.("m.room.name","name") would yank the "name" content key from "m.room.name"
var event = this . props . room . currentState . getStateEvents ( stateEventType , '' ) ;
if ( ! event ) {
return defaultValue ;
}
return event . getContent ( ) [ keyName ] || defaultValue ;
} ,
2016-02-05 17:38:28 +03:00
_onHistoryRadioToggle : function ( ev ) {
2016-03-20 01:32:44 +03:00
var self = this ;
var QuestionDialog = sdk . getComponent ( "dialogs.QuestionDialog" ) ;
// cancel the click unless the user confirms it
ev . preventDefault ( ) ;
2016-03-25 04:12:16 +03:00
var value = ev . target . value ;
2016-03-20 01:32:44 +03:00
2017-07-27 19:19:18 +03:00
Modal . createTrackedDialog ( 'Privacy warning' , '' , QuestionDialog , {
2017-05-23 17:16:31 +03:00
title : _t ( 'Privacy warning' ) ,
2016-03-20 01:32:44 +03:00
description :
< div >
2017-05-23 17:16:31 +03:00
{ _t ( 'Changes to who can read history will only apply to future messages in this room' ) } . < br / >
{ _t ( 'The visibility of existing history will be unchanged' ) } .
2016-03-20 01:32:44 +03:00
< / d i v > ,
2017-05-23 17:16:31 +03:00
button : _t ( 'Continue' ) ,
2016-03-20 01:32:44 +03:00
onFinished : function ( confirmed ) {
if ( confirmed ) {
self . setState ( {
2016-03-25 04:12:16 +03:00
history _visibility : value
2016-03-20 01:32:44 +03:00
} ) ;
}
} ,
2016-02-05 17:38:28 +03:00
} ) ;
} ,
2016-06-23 12:36:16 +03:00
2016-03-22 03:57:40 +03:00
_onRoomAccessRadioToggle : function ( ev ) {
2016-03-22 15:10:58 +03:00
// join_rule
// INVITE | PUBLIC
// ----------------------+----------------
// guest CAN_JOIN | inv_only | pub_with_guest
// access ----------------------+----------------
// FORBIDDEN | inv_only | pub_no_guest
// ----------------------+----------------
2016-03-22 03:57:40 +03:00
switch ( ev . target . value ) {
case "invite_only" :
2016-03-22 15:10:58 +03:00
this . setState ( {
2016-03-22 03:57:40 +03:00
join _rule : "invite" ,
2016-03-22 15:26:38 +03:00
// we always set guests can_join here as it makes no sense to have
// an invite-only room that guests can't join. If you explicitly
// invite them, you clearly want them to join, whether they're a
// guest or not. In practice, guest_access should probably have
// been implemented as part of the join_rules enum.
2016-03-22 03:57:40 +03:00
guest _access : "can_join" ,
} ) ;
break ;
case "public_no_guests" :
2016-03-22 15:10:58 +03:00
this . setState ( {
2016-03-22 03:57:40 +03:00
join _rule : "public" ,
guest _access : "forbidden" ,
} ) ;
break ;
case "public_with_guests" :
2016-03-22 15:10:58 +03:00
this . setState ( {
2016-03-22 03:57:40 +03:00
join _rule : "public" ,
guest _access : "can_join" ,
} ) ;
break ;
}
} ,
2016-02-04 19:18:59 +03:00
_onToggle : function ( keyName , checkedValue , uncheckedValue , ev ) {
2016-02-04 18:26:12 +03:00
console . log ( "Checkbox toggle: %s %s" , keyName , ev . target . checked ) ;
var state = { } ;
2016-02-04 19:18:59 +03:00
state [ keyName ] = ev . target . checked ? checkedValue : uncheckedValue ;
2016-02-04 18:26:12 +03:00
this . setState ( state ) ;
} ,
2016-01-08 06:22:38 +03:00
2016-02-05 14:59:19 +03:00
_onTagChange : function ( tagName , event ) {
2016-01-17 08:13:16 +03:00
if ( event . target . checked ) {
if ( tagName === 'm.favourite' ) {
delete this . state . tags [ 'm.lowpriority' ] ;
}
else if ( tagName === 'm.lowpriority' ) {
delete this . state . tags [ 'm.favourite' ] ;
}
2016-02-05 14:59:19 +03:00
this . state . tags [ tagName ] = this . state . tags [ tagName ] || [ "yep" ] ;
2016-01-17 08:13:16 +03:00
}
else {
delete this . state . tags [ tagName ] ;
}
this . setState ( {
tags : this . state . tags ,
tags _changed : true
} ) ;
} ,
2016-03-22 15:26:38 +03:00
mayChangeRoomAccess : function ( ) {
2017-02-15 21:58:59 +03:00
var cli = MatrixClientPeg . get ( ) ;
2016-03-22 15:26:38 +03:00
var roomState = this . props . room . currentState ;
return ( roomState . mayClientSendStateEvent ( "m.room.join_rules" , cli ) &&
2017-01-20 17:22:27 +03:00
roomState . mayClientSendStateEvent ( "m.room.guest_access" , cli ) ) ;
2016-03-22 15:26:38 +03:00
} ,
2016-08-28 02:00:22 +03:00
onLeaveClick ( ) {
dis . dispatch ( {
action : 'leave_room' ,
room _id : this . props . room . roomId ,
} ) ;
} ,
onForgetClick ( ) {
// FIXME: duplicated with RoomTagContextualMenu (and dead code in RoomView)
2017-02-15 21:58:59 +03:00
MatrixClientPeg . get ( ) . forget ( this . props . room . roomId ) . done ( function ( ) {
2016-08-28 02:00:22 +03:00
dis . dispatch ( { action : 'view_next_room' } ) ;
} , function ( err ) {
2017-05-23 17:16:31 +03:00
var errCode = err . errcode || _t ( 'unknown error code' ) ;
2016-08-28 02:00:22 +03:00
var ErrorDialog = sdk . getComponent ( "dialogs.ErrorDialog" ) ;
2017-08-10 15:49:11 +03:00
Modal . createTrackedDialog ( 'Failed to forget room' , '' , ErrorDialog , {
2017-05-23 17:16:31 +03:00
title : _t ( 'Error' ) ,
description : _t ( "Failed to forget room %(errCode)s" , { errCode : errCode } ) ,
2016-08-28 02:00:22 +03:00
} ) ;
} ) ;
} ,
2016-09-14 04:07:37 +03:00
onEnableEncryptionClick ( ) {
2016-09-17 23:56:10 +03:00
if ( ! this . refs . encrypt . checked ) return ;
2016-09-14 04:07:37 +03:00
var QuestionDialog = sdk . getComponent ( "dialogs.QuestionDialog" ) ;
2017-07-27 19:19:18 +03:00
Modal . createTrackedDialog ( 'E2E Enable Warning' , '' , QuestionDialog , {
2017-05-25 20:20:48 +03:00
title : _t ( 'Warning!' ) ,
2016-09-14 04:07:37 +03:00
description : (
< div >
2017-05-23 17:16:31 +03:00
< p > { _t ( 'End-to-end encryption is in beta and may not be reliable' ) } . < / p >
2017-05-25 22:04:28 +03:00
< p > { _t ( 'You should not yet trust it to secure data' ) } . < / p >
< p > { _t ( 'Devices will not yet be able to decrypt history from before they joined the room' ) } . < / p >
< p > { _t ( 'Once encryption is enabled for a room it cannot be turned off again (for now)' ) } . < / p >
2017-05-23 17:16:31 +03:00
< p > { _t ( 'Encrypted messages will not be visible on clients that do not yet implement encryption' ) } . < / p >
2016-09-14 04:07:37 +03:00
< / d i v >
) ,
onFinished : confirm => {
if ( ! confirm ) {
this . refs . encrypt . checked = false ;
}
} ,
} ) ;
} ,
2017-02-14 20:54:57 +03:00
_onRoomMemberMembership : function ( ) {
// Update, since our banned user list may have changed
this . forceUpdate ( ) ;
} ,
2016-06-23 14:21:31 +03:00
_renderEncryptionSection : function ( ) {
2017-02-15 21:58:59 +03:00
var cli = MatrixClientPeg . get ( ) ;
2016-06-23 14:21:31 +03:00
var roomState = this . props . room . currentState ;
var isEncrypted = cli . isRoomEncrypted ( this . props . room . roomId ) ;
2017-01-21 20:39:31 +03:00
var isGlobalBlacklistUnverified = UserSettingsStore . getLocalSettings ( ) . blacklistUnverifiedDevices ;
var isRoomBlacklistUnverified = this . _isRoomBlacklistUnverified ( ) ;
var settings =
< label >
< input type = "checkbox" ref = "blacklistUnverified"
2017-01-22 00:49:29 +03:00
defaultChecked = { isGlobalBlacklistUnverified || isRoomBlacklistUnverified }
disabled = { isGlobalBlacklistUnverified || ( this . refs . encrypt && ! this . refs . encrypt . checked ) } / >
2017-05-23 17:16:31 +03:00
{ _t ( 'Never send encrypted messages to unverified devices in this room from this device' ) } .
2017-01-21 20:39:31 +03:00
< / l a b e l > ;
2016-06-23 14:21:31 +03:00
2017-06-10 02:08:40 +03:00
if ( ! isEncrypted && roomState . mayClientSendStateEvent ( "m.room.encryption" , cli ) ) {
2016-09-14 04:07:37 +03:00
return (
2017-01-21 20:43:46 +03:00
< div >
< label >
< input type = "checkbox" ref = "encrypt" onClick = { this . onEnableEncryptionClick } / >
2017-06-10 02:08:40 +03:00
< img className = "mx_RoomSettings_e2eIcon mx_filterFlipColor" src = "img/e2e-unencrypted.svg" width = "12" height = "12" / >
2017-05-23 17:16:31 +03:00
{ _t ( 'Enable encryption' ) } { _t ( '(warning: cannot be disabled again!)' ) }
2017-01-21 20:43:46 +03:00
< / l a b e l >
{ settings }
< / d i v >
2016-06-23 14:21:31 +03:00
) ;
2017-06-10 02:08:40 +03:00
} else {
2016-09-14 04:07:37 +03:00
return (
2017-01-21 20:43:46 +03:00
< div >
< label >
{ isEncrypted
2017-06-13 19:39:20 +03:00
? < img className = "mx_RoomSettings_e2eIcon" src = "img/e2e-verified.svg" width = "10" height = "12" / >
2017-06-10 02:08:40 +03:00
: < img className = "mx_RoomSettings_e2eIcon mx_filterFlipColor" src = "img/e2e-unencrypted.svg" width = "12" height = "12" / >
2017-01-21 20:43:46 +03:00
}
2017-06-08 16:08:51 +03:00
{ isEncrypted ? _t ( "Encryption is enabled in this room" ) : _t ( "Encryption is not enabled in this room" ) } .
2017-01-21 20:43:46 +03:00
< / l a b e l >
{ settings }
< / d i v >
2016-09-14 04:07:37 +03:00
) ;
}
2016-06-23 14:21:31 +03:00
} ,
2015-11-27 13:42:03 +03:00
render : function ( ) {
2016-01-13 16:15:13 +03:00
// TODO: go through greying out things you don't have permission to change
// (or turning them into informative stuff)
2016-02-02 15:46:14 +03:00
var AliasSettings = sdk . getComponent ( "room_settings.AliasSettings" ) ;
2016-02-05 14:27:11 +03:00
var ColorSettings = sdk . getComponent ( "room_settings.ColorSettings" ) ;
2016-07-18 03:35:42 +03:00
var UrlPreviewSettings = sdk . getComponent ( "room_settings.UrlPreviewSettings" ) ;
2016-01-13 16:15:13 +03:00
var EditableText = sdk . getComponent ( 'elements.EditableText' ) ;
var PowerSelector = sdk . getComponent ( 'elements.PowerSelector' ) ;
2017-01-20 17:22:27 +03:00
var Loader = sdk . getComponent ( "elements.Spinner" ) ;
2015-11-27 13:42:03 +03:00
2017-02-15 21:58:59 +03:00
var cli = MatrixClientPeg . get ( ) ;
2016-03-16 15:17:07 +03:00
var roomState = this . props . room . currentState ;
2016-03-16 15:09:26 +03:00
var user _id = cli . credentials . userId ;
2016-01-13 16:15:13 +03:00
2016-06-23 12:36:16 +03:00
var power _level _event = roomState . getStateEvents ( 'm.room.power_levels' , '' ) ;
var power _levels = power _level _event ? power _level _event . getContent ( ) : { } ;
var events _levels = power _levels . events || { } ;
var user _levels = power _levels . users || { } ;
var ban _level = parseIntWithDefault ( power _levels . ban , 50 ) ;
var kick _level = parseIntWithDefault ( power _levels . kick , 50 ) ;
var redact _level = parseIntWithDefault ( power _levels . redact , 50 ) ;
var invite _level = parseIntWithDefault ( power _levels . invite , 50 ) ;
var send _level = parseIntWithDefault ( power _levels . events _default , 0 ) ;
var state _level = power _level _event ? parseIntWithDefault ( power _levels . state _default , 50 ) : 0 ;
var default _user _level = parseIntWithDefault ( power _levels . users _default , 0 ) ;
var current _user _level = user _levels [ user _id ] ;
if ( current _user _level === undefined ) {
current _user _level = default _user _level ;
2015-11-27 13:42:03 +03:00
}
2016-06-23 12:36:16 +03:00
var can _change _levels = roomState . mayClientSendStateEvent ( "m.room.power_levels" , cli ) ;
2016-01-17 06:59:31 +03:00
2016-03-16 15:09:26 +03:00
var canSetTag = ! cli . isGuest ( ) ;
2016-01-17 08:13:16 +03:00
2016-01-08 06:22:38 +03:00
var self = this ;
2016-02-05 18:48:04 +03:00
var userLevelsSection ;
2016-01-20 20:12:55 +03:00
if ( Object . keys ( user _levels ) . length ) {
2016-02-05 18:48:04 +03:00
userLevelsSection =
2016-01-21 01:47:42 +03:00
< div >
2017-05-23 17:16:31 +03:00
< h3 > { _t ( 'Privileged Users' ) } < / h 3 >
2016-01-21 01:47:42 +03:00
< ul className = "mx_RoomSettings_userLevels" >
{ Object . keys ( user _levels ) . map ( function ( user , i ) {
return (
< li className = "mx_RoomSettings_userLevel" key = { user } >
2017-06-08 16:08:51 +03:00
{ _t ( "%(user)s is a" , { user : user } ) } < PowerSelector value = { user _levels [ user ] } disabled = { true } / >
2016-01-21 01:47:42 +03:00
< / l i >
) ;
} ) }
< / u l >
< / d i v > ;
2016-01-08 06:22:38 +03:00
}
2016-01-17 05:48:55 +03:00
else {
2017-05-23 17:16:31 +03:00
userLevelsSection = < div > { _t ( 'No users have specific privileges in this room' ) } . < / d i v > ;
2016-01-17 05:48:55 +03:00
}
2016-01-08 06:22:38 +03:00
2017-06-10 18:30:46 +03:00
const banned = this . props . room . getMembersWithMembership ( "ban" ) ;
let bannedUsersSection ;
2016-01-08 06:22:38 +03:00
if ( banned . length ) {
2017-07-06 14:51:55 +03:00
const canBanUsers = current _user _level >= ban _level ;
2016-02-05 18:48:04 +03:00
bannedUsersSection =
2016-01-08 06:22:38 +03:00
< div >
2017-05-23 17:16:31 +03:00
< h3 > { _t ( 'Banned users' ) } < / h 3 >
2016-01-21 01:47:42 +03:00
< ul className = "mx_RoomSettings_banned" >
2017-02-14 20:54:57 +03:00
{ banned . map ( function ( member ) {
2017-06-10 18:30:46 +03:00
const banEvent = member . events . member . getContent ( ) ;
2016-01-08 06:22:38 +03:00
return (
2017-07-06 14:51:55 +03:00
< BannedUser key = { member . userId } canUnban = { canBanUsers } member = { member } reason = { banEvent . reason } / >
2016-01-08 06:22:38 +03:00
) ;
} ) }
2016-01-21 01:47:42 +03:00
< / u l >
2016-01-08 06:22:38 +03:00
< / d i v > ;
}
2016-02-05 18:48:04 +03:00
var unfederatableSection ;
if ( this . _yankValueFromEvent ( "m.room.create" , "m.federate" ) === false ) {
unfederatableSection = (
< div className = "mx_RoomSettings_powerLevel" >
2017-05-23 17:16:31 +03:00
{ _t ( 'This room is not accessible by remote Matrix servers' ) } .
2016-02-05 18:48:04 +03:00
< / d i v >
) ;
2016-01-15 17:22:17 +03:00
}
2016-08-28 02:00:22 +03:00
var leaveButton = null ;
var myMember = this . props . room . getMember ( user _id ) ;
if ( myMember ) {
if ( myMember . membership === "join" ) {
leaveButton = (
2017-02-14 20:06:16 +03:00
< AccessibleButton className = "mx_RoomSettings_leaveButton" onClick = { this . onLeaveClick } >
2017-05-23 17:16:31 +03:00
{ _t ( 'Leave room' ) }
2017-02-14 20:06:16 +03:00
< / A c c e s s i b l e B u t t o n >
2016-08-28 02:00:22 +03:00
) ;
}
else if ( myMember . membership === "leave" ) {
leaveButton = (
2017-02-14 20:06:16 +03:00
< AccessibleButton className = "mx_RoomSettings_leaveButton" onClick = { this . onForgetClick } >
2017-05-23 17:16:31 +03:00
{ _t ( 'Forget room' ) }
2017-02-14 20:06:16 +03:00
< / A c c e s s i b l e B u t t o n >
2016-08-28 02:00:22 +03:00
) ;
}
}
2016-01-13 16:15:13 +03:00
// TODO: support editing custom events_levels
// TODO: support editing custom user_levels
2016-01-17 08:13:16 +03:00
var tags = [
2017-05-23 17:16:31 +03:00
{ name : "m.favourite" , label : _t ( 'Favourite' ) , ref : "tag_favourite" } ,
{ name : "m.lowpriority" , label : _t ( 'Low priority' ) , ref : "tag_lowpriority" } ,
2016-01-17 08:13:16 +03:00
] ;
Object . keys ( this . state . tags ) . sort ( ) . forEach ( function ( tagName ) {
if ( tagName !== 'm.favourite' && tagName !== 'm.lowpriority' ) {
tags . push ( { name : tagName , label : tagName } ) ;
}
} ) ;
2016-03-22 16:47:38 +03:00
var tagsSection = null ;
if ( canSetTag || self . state . tags ) {
2016-06-23 12:36:16 +03:00
var tagsSection =
2016-03-22 16:47:38 +03:00
< div className = "mx_RoomSettings_tags" >
2017-06-02 12:18:31 +03:00
{ _t ( "Tagged as: " ) } { canSetTag ?
2016-03-22 16:47:38 +03:00
( tags . map ( function ( tag , i ) {
return ( < label key = { i } >
< input type = "checkbox"
ref = { tag . ref }
checked = { tag . name in self . state . tags }
onChange = { self . _onTagChange . bind ( self , tag . name ) } / >
{ tag . label }
< / l a b e l > ) ;
} ) ) : ( self . state . tags && self . state . tags . join ) ? self . state . tags . join ( ", " ) : ""
}
2017-01-20 17:22:27 +03:00
< / d i v > ;
2016-03-22 16:47:38 +03:00
}
2016-01-17 08:13:16 +03:00
2016-02-05 17:38:28 +03:00
// If there is no history_visibility, it is assumed to be 'shared'.
// http://matrix.org/docs/spec/r0.0.0/client_server.html#id31
var historyVisibility = this . state . history _visibility || "shared" ;
2016-03-22 03:57:40 +03:00
var addressWarning ;
var aliasEvents = this . props . room . currentState . getStateEvents ( 'm.room.aliases' ) || [ ] ;
var aliasCount = 0 ;
aliasEvents . forEach ( ( event ) => {
aliasCount += event . getContent ( ) . aliases . length ;
} ) ;
if ( this . state . join _rule === "public" && aliasCount == 0 ) {
addressWarning =
< div className = "mx_RoomSettings_warning" >
2017-06-08 16:45:59 +03:00
{ _tJsx (
2017-06-08 16:08:51 +03:00
'To link to a room it must have <a>an address</a>.' ,
/<a>(.*?)<\/a>/ ,
( sub ) => < a href = "#addresses" > { sub } < / a >
) }
2017-01-20 17:22:27 +03:00
< / d i v > ;
2016-03-22 03:57:40 +03:00
}
2016-03-22 15:10:58 +03:00
var inviteGuestWarning ;
if ( this . state . join _rule !== "public" && this . state . guest _access === "forbidden" ) {
inviteGuestWarning =
< div className = "mx_RoomSettings_warning" >
2017-05-27 20:20:35 +03:00
{ _t ( 'Guests cannot join this room even if explicitly invited.' ) } < a href = "#" onClick = { ( e ) => {
2016-03-22 15:10:58 +03:00
this . setState ( { join _rule : "invite" , guest _access : "can_join" } ) ;
e . preventDefault ( ) ;
2017-05-23 17:16:31 +03:00
} } > { _t ( 'Click here to fix' ) } < / a > .
2017-01-20 17:22:27 +03:00
< / d i v > ;
2016-03-22 15:10:58 +03:00
}
2015-11-27 13:42:03 +03:00
return (
< div className = "mx_RoomSettings" >
2016-01-08 06:22:38 +03:00
2016-08-28 02:00:22 +03:00
{ leaveButton }
2016-02-05 18:48:04 +03:00
{ tagsSection }
2016-01-17 08:13:16 +03:00
2016-01-18 22:56:38 +03:00
< div className = "mx_RoomSettings_toggles" >
2016-03-22 03:57:40 +03:00
< div className = "mx_RoomSettings_settings" >
2017-05-23 17:16:31 +03:00
< h3 > { _t ( 'Who can access this room?' ) } < / h 3 >
2016-03-22 15:10:58 +03:00
{ inviteGuestWarning }
2016-03-22 03:57:40 +03:00
< label >
< input type = "radio" name = "roomVis" value = "invite_only"
2016-03-22 15:26:38 +03:00
disabled = { ! this . mayChangeRoomAccess ( ) }
2016-03-22 03:57:40 +03:00
onChange = { this . _onRoomAccessRadioToggle }
2016-03-22 15:10:58 +03:00
checked = { this . state . join _rule !== "public" } / >
2017-05-23 17:16:31 +03:00
{ _t ( 'Only people who have been invited' ) }
2016-03-22 03:57:40 +03:00
< / l a b e l >
< label >
< input type = "radio" name = "roomVis" value = "public_no_guests"
2016-03-22 15:26:38 +03:00
disabled = { ! this . mayChangeRoomAccess ( ) }
2016-03-22 03:57:40 +03:00
onChange = { this . _onRoomAccessRadioToggle }
2016-03-22 15:10:58 +03:00
checked = { this . state . join _rule === "public" && this . state . guest _access !== "can_join" } / >
2017-05-23 17:16:31 +03:00
{ _t ( 'Anyone who knows the room\'s link, apart from guests' ) }
2016-03-22 03:57:40 +03:00
< / l a b e l >
< label >
< input type = "radio" name = "roomVis" value = "public_with_guests"
2016-03-22 15:26:38 +03:00
disabled = { ! this . mayChangeRoomAccess ( ) }
2016-03-22 03:57:40 +03:00
onChange = { this . _onRoomAccessRadioToggle }
2016-03-22 15:10:58 +03:00
checked = { this . state . join _rule === "public" && this . state . guest _access === "can_join" } / >
2017-05-23 17:16:31 +03:00
{ _t ( 'Anyone who knows the room\'s link, including guests' ) }
2016-03-22 03:57:40 +03:00
< / l a b e l >
{ addressWarning }
< br / >
2016-09-14 04:07:37 +03:00
{ this . _renderEncryptionSection ( ) }
2016-03-22 03:57:40 +03:00
< label >
< input type = "checkbox" disabled = { ! roomState . mayClientSendStateEvent ( "m.room.aliases" , cli ) }
onChange = { this . _onToggle . bind ( this , "isRoomPublished" , true , false ) }
checked = { this . state . isRoomPublished } / >
2017-08-17 21:10:45 +03:00
{ _t ( "Publish this room to the public in %(domain)s's room directory?" , { domain : MatrixClientPeg . get ( ) . getDomain ( ) } ) }
2016-03-22 03:57:40 +03:00
< / l a b e l >
< / d i v >
2016-02-05 17:38:28 +03:00
< div className = "mx_RoomSettings_settings" >
2017-05-23 17:16:31 +03:00
< h3 > { _t ( 'Who can read history?' ) } < / h 3 >
2016-03-22 03:57:40 +03:00
< label >
< input type = "radio" name = "historyVis" value = "world_readable"
2016-03-16 16:10:45 +03:00
disabled = { ! roomState . mayClientSendStateEvent ( "m.room.history_visibility" , cli ) }
2016-03-20 01:32:44 +03:00
checked = { historyVisibility === "world_readable" }
2016-02-05 17:38:28 +03:00
onChange = { this . _onHistoryRadioToggle } / >
2017-06-02 12:18:31 +03:00
{ _t ( "Anyone" ) }
2016-02-05 17:38:28 +03:00
< / l a b e l >
2016-03-22 03:57:40 +03:00
< label >
< input type = "radio" name = "historyVis" value = "shared"
2016-03-16 16:10:45 +03:00
disabled = { ! roomState . mayClientSendStateEvent ( "m.room.history_visibility" , cli ) }
2016-03-20 01:32:44 +03:00
checked = { historyVisibility === "shared" }
2016-02-05 17:38:28 +03:00
onChange = { this . _onHistoryRadioToggle } / >
2017-05-23 17:16:31 +03:00
{ _t ( 'Members only' ) } ( { _t ( 'since the point in time of selecting this option' ) } )
2016-02-05 17:38:28 +03:00
< / l a b e l >
2016-03-22 03:57:40 +03:00
< label >
< input type = "radio" name = "historyVis" value = "invited"
2016-03-16 16:10:45 +03:00
disabled = { ! roomState . mayClientSendStateEvent ( "m.room.history_visibility" , cli ) }
2016-03-20 01:32:44 +03:00
checked = { historyVisibility === "invited" }
2016-02-05 17:38:28 +03:00
onChange = { this . _onHistoryRadioToggle } / >
2017-05-23 17:16:31 +03:00
{ _t ( 'Members only' ) } ( { _t ( 'since they were invited' ) } )
2016-02-05 17:38:28 +03:00
< / l a b e l >
2016-03-22 03:57:40 +03:00
< label >
< input type = "radio" name = "historyVis" value = "joined"
2016-03-16 16:10:45 +03:00
disabled = { ! roomState . mayClientSendStateEvent ( "m.room.history_visibility" , cli ) }
2016-03-20 01:32:44 +03:00
checked = { historyVisibility === "joined" }
2016-02-05 17:38:28 +03:00
onChange = { this . _onHistoryRadioToggle } / >
2017-05-23 17:16:31 +03:00
{ _t ( 'Members only' ) } ( { _t ( 'since they joined' ) } )
2016-02-05 17:38:28 +03:00
< / l a b e l >
< / d i v >
2016-01-18 22:56:38 +03:00
< / d i v >
2016-02-05 14:27:11 +03:00
< div >
2017-05-23 17:16:31 +03:00
< h3 > { _t ( 'Room Colour' ) } < / h 3 >
2016-02-05 14:27:11 +03:00
< ColorSettings ref = "color_settings" room = { this . props . room } / >
< / d i v >
2015-11-27 13:42:03 +03:00
2016-03-22 03:57:40 +03:00
< a id = "addresses" / >
2016-02-02 15:46:14 +03:00
< AliasSettings ref = "alias_settings"
roomId = { this . props . room . roomId }
2016-03-16 16:10:45 +03:00
canSetCanonicalAlias = { roomState . mayClientSendStateEvent ( "m.room.canonical_alias" , cli ) }
2016-09-28 01:39:25 +03:00
canSetAliases = {
2016-11-21 13:25:48 +03:00
true
2016-09-28 01:39:25 +03:00
/* Originally, we arbitrarily restricted creating aliases to room admins: roomState.mayClientSendStateEvent("m.room.aliases", cli) */
}
2016-02-02 15:46:14 +03:00
canonicalAliasEvent = { this . props . room . currentState . getStateEvents ( 'm.room.canonical_alias' , '' ) }
aliasEvents = { this . props . room . currentState . getStateEvents ( 'm.room.aliases' ) } / >
2016-01-13 16:15:13 +03:00
2016-07-18 03:35:42 +03:00
< UrlPreviewSettings ref = "url_preview_settings" room = { this . props . room } / >
2017-05-23 17:16:31 +03:00
< h3 > { _t ( 'Permissions' ) } < / h 3 >
2016-01-08 06:22:38 +03:00
< div className = "mx_RoomSettings_powerLevels mx_RoomSettings_settings" >
2016-01-13 16:15:13 +03:00
< div className = "mx_RoomSettings_powerLevel" >
2017-05-23 17:16:31 +03:00
< span className = "mx_RoomSettings_powerLevelKey" > { _t ( 'The default role for new room members is' ) } < / s p a n >
2016-03-22 20:17:40 +03:00
< PowerSelector ref = "users_default" value = { default _user _level } controlled = { false } disabled = { ! can _change _levels || current _user _level < default _user _level } onChange = { this . onPowerLevelsChanged } / >
2015-11-27 13:42:03 +03:00
< / d i v >
2016-01-13 16:15:13 +03:00
< div className = "mx_RoomSettings_powerLevel" >
2017-09-29 23:35:49 +03:00
< span className = "mx_RoomSettings_powerLevelKey" > { _t ( 'To send messages, you must be a' ) } < / s p a n >
2016-03-22 20:17:40 +03:00
< PowerSelector ref = "events_default" value = { send _level } controlled = { false } disabled = { ! can _change _levels || current _user _level < send _level } onChange = { this . onPowerLevelsChanged } / >
2015-11-27 13:42:03 +03:00
< / d i v >
2016-01-13 16:15:13 +03:00
< div className = "mx_RoomSettings_powerLevel" >
2017-09-29 23:35:49 +03:00
< span className = "mx_RoomSettings_powerLevelKey" > { _t ( 'To invite users into the room, you must be a' ) } < / s p a n >
2016-03-22 20:17:40 +03:00
< PowerSelector ref = "invite" value = { invite _level } controlled = { false } disabled = { ! can _change _levels || current _user _level < invite _level } onChange = { this . onPowerLevelsChanged } / >
2015-11-27 13:42:03 +03:00
< / d i v >
2016-01-13 16:15:13 +03:00
< div className = "mx_RoomSettings_powerLevel" >
2017-09-29 23:35:49 +03:00
< span className = "mx_RoomSettings_powerLevelKey" > { _t ( 'To configure the room, you must be a' ) } < / s p a n >
2016-03-22 20:17:40 +03:00
< PowerSelector ref = "state_default" value = { state _level } controlled = { false } disabled = { ! can _change _levels || current _user _level < state _level } onChange = { this . onPowerLevelsChanged } / >
2015-11-27 13:42:03 +03:00
< / d i v >
2016-01-13 16:15:13 +03:00
< div className = "mx_RoomSettings_powerLevel" >
2017-09-29 23:35:49 +03:00
< span className = "mx_RoomSettings_powerLevelKey" > { _t ( 'To kick users, you must be a' ) } < / s p a n >
2016-03-22 20:17:40 +03:00
< PowerSelector ref = "kick" value = { kick _level } controlled = { false } disabled = { ! can _change _levels || current _user _level < kick _level } onChange = { this . onPowerLevelsChanged } / >
2015-11-27 13:42:03 +03:00
< / d i v >
2016-01-13 16:15:13 +03:00
< div className = "mx_RoomSettings_powerLevel" >
2017-09-29 23:35:49 +03:00
< span className = "mx_RoomSettings_powerLevelKey" > { _t ( 'To ban users, you must be a' ) } < / s p a n >
2016-03-22 20:17:40 +03:00
< PowerSelector ref = "ban" value = { ban _level } controlled = { false } disabled = { ! can _change _levels || current _user _level < ban _level } onChange = { this . onPowerLevelsChanged } / >
2015-11-27 13:42:03 +03:00
< / d i v >
2016-01-13 16:15:13 +03:00
< div className = "mx_RoomSettings_powerLevel" >
2017-09-29 23:35:49 +03:00
< span className = "mx_RoomSettings_powerLevelKey" > { _t ( 'To remove other users\' messages, you must be a' ) } < / s p a n >
2016-03-22 20:17:40 +03:00
< PowerSelector ref = "redact" value = { redact _level } controlled = { false } disabled = { ! can _change _levels || current _user _level < redact _level } onChange = { this . onPowerLevelsChanged } / >
2015-11-27 13:42:03 +03:00
< / d i v >
2016-01-13 16:15:13 +03:00
{ Object . keys ( events _levels ) . map ( function ( event _type , i ) {
2015-11-27 13:42:03 +03:00
return (
2016-01-13 16:15:13 +03:00
< div className = "mx_RoomSettings_powerLevel" key = { event _type } >
2017-09-29 23:35:49 +03:00
< span className = "mx_RoomSettings_powerLevelKey" > { _tJsx ( "To send events of type <eventType/>, you must be a" , /<eventType\/>/ , ( ) => < code > { event _type } < / c o d e > ) } < / s p a n >
2017-09-29 23:02:31 +03:00
< PowerSelector ref = { "event_levels_" + event _type } value = { events _levels [ event _type ] } onChange = { self . onPowerLevelsChanged }
controlled = { false } disabled = { ! can _change _levels || current _user _level < events _levels [ event _type ] } / >
2015-11-27 13:42:03 +03:00
< / d i v >
) ;
} ) }
2016-01-15 19:33:50 +03:00
2016-02-05 18:48:04 +03:00
{ unfederatableSection }
2015-11-27 13:42:03 +03:00
< / d i v >
2016-02-05 18:48:04 +03:00
{ userLevelsSection }
2016-01-13 16:15:13 +03:00
2016-02-05 18:48:04 +03:00
{ bannedUsersSection }
2016-01-13 16:15:13 +03:00
2017-05-23 17:16:31 +03:00
< h3 > { _t ( 'Advanced' ) } < / h 3 >
2016-01-17 05:48:55 +03:00
< div className = "mx_RoomSettings_settings" >
2017-05-23 17:16:31 +03:00
{ _t ( 'This room\'s internal ID is' ) } < code > { this . props . room . roomId } < / c o d e >
2016-01-17 05:48:55 +03:00
< / d i v >
2015-11-27 13:42:03 +03:00
< / d i v >
) ;
}
2017-02-15 21:58:59 +03:00
} ) ;