mirror of https://github.com/vector-im/riot-web
				
				
				
			Make CreateRoomDialog capable of creating restricted rooms in spaces
							parent
							
								
									c5ca98a3ad
								
							
						
					
					
						commit
						eb9f4c609a
					
				|  | @ -65,7 +65,7 @@ limitations under the License. | |||
| .mx_CreateRoomDialog_aliasContainer { | ||||
|     display: flex; | ||||
|     // put margin on container so it can collapse with siblings | ||||
|     margin: 10px 0; | ||||
|     margin: 24px 0 10px; | ||||
| 
 | ||||
|     .mx_RoomAliasField { | ||||
|         margin: 0; | ||||
|  | @ -101,10 +101,6 @@ limitations under the License. | |||
|         margin-left: 30px; | ||||
|     } | ||||
| 
 | ||||
|     .mx_CreateRoomDialog_topic { | ||||
|         margin-bottom: 36px; | ||||
|     } | ||||
| 
 | ||||
|     .mx_Dialog_content > .mx_SettingsFlag { | ||||
|         margin-top: 24px; | ||||
|     } | ||||
|  | @ -113,5 +109,17 @@ limitations under the License. | |||
|         margin: 0 85px 0 0; | ||||
|         font-size: $font-12px; | ||||
|     } | ||||
| 
 | ||||
|     .mx_Dropdown { | ||||
|         margin-bottom: 8px; | ||||
|         font-weight: normal; | ||||
|         font-family: $font-family; | ||||
|         font-size: $font-14px; | ||||
|         color: $primary-fg-color; | ||||
| 
 | ||||
|         .mx_Dropdown_input { | ||||
|             border: 1px solid $input-border-color; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ limitations under the License. | |||
| 
 | ||||
| import React, { ChangeEvent, createRef, KeyboardEvent, SyntheticEvent } from "react"; | ||||
| import { Room } from "matrix-js-sdk/src/models/room"; | ||||
| import { JoinRule, Preset, Visibility } from "matrix-js-sdk/src/@types/partials"; | ||||
| 
 | ||||
| import SdkConfig from '../../../SdkConfig'; | ||||
| import withValidation, { IFieldState } from '../elements/Validation'; | ||||
|  | @ -31,7 +32,8 @@ import RoomAliasField from "../elements/RoomAliasField"; | |||
| import LabelledToggleSwitch from "../elements/LabelledToggleSwitch"; | ||||
| import DialogButtons from "../elements/DialogButtons"; | ||||
| import BaseDialog from "../dialogs/BaseDialog"; | ||||
| import { Preset, Visibility } from "matrix-js-sdk/src/@types/partials"; | ||||
| import Dropdown from "../elements/Dropdown"; | ||||
| import SpaceStore from "../../../stores/SpaceStore"; | ||||
| 
 | ||||
| interface IProps { | ||||
|     defaultPublic?: boolean; | ||||
|  | @ -41,7 +43,7 @@ interface IProps { | |||
| } | ||||
| 
 | ||||
| interface IState { | ||||
|     isPublic: boolean; | ||||
|     joinRule: JoinRule; | ||||
|     isEncrypted: boolean; | ||||
|     name: string; | ||||
|     topic: string; | ||||
|  | @ -54,15 +56,25 @@ interface IState { | |||
| 
 | ||||
| @replaceableComponent("views.dialogs.CreateRoomDialog") | ||||
| export default class CreateRoomDialog extends React.Component<IProps, IState> { | ||||
|     private readonly supportsRestricted: boolean; | ||||
|     private nameField = createRef<Field>(); | ||||
|     private aliasField = createRef<RoomAliasField>(); | ||||
| 
 | ||||
|     constructor(props) { | ||||
|         super(props); | ||||
| 
 | ||||
|         this.supportsRestricted = this.props.parentSpace && !!SpaceStore.instance.restrictedJoinRuleSupport?.preferred; | ||||
| 
 | ||||
|         let joinRule = JoinRule.Invite; | ||||
|         if (this.props.defaultPublic) { | ||||
|             joinRule = JoinRule.Public; | ||||
|         } else if (this.supportsRestricted) { | ||||
|             joinRule = JoinRule.Restricted; | ||||
|         } | ||||
| 
 | ||||
|         const config = SdkConfig.get(); | ||||
|         this.state = { | ||||
|             isPublic: this.props.defaultPublic || false, | ||||
|             joinRule, | ||||
|             isEncrypted: privateShouldBeEncrypted(), | ||||
|             name: this.props.defaultName || "", | ||||
|             topic: "", | ||||
|  | @ -81,7 +93,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> { | |||
|         const opts: IOpts = {}; | ||||
|         const createOpts: IOpts["createOpts"] = opts.createOpts = {}; | ||||
|         createOpts.name = this.state.name; | ||||
|         if (this.state.isPublic) { | ||||
|         if (this.state.joinRule === JoinRule.Public) { | ||||
|             createOpts.visibility = Visibility.Public; | ||||
|             createOpts.preset = Preset.PublicChat; | ||||
|             opts.guestAccess = false; | ||||
|  | @ -95,7 +107,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> { | |||
|             createOpts.creation_content = { 'm.federate': false }; | ||||
|         } | ||||
| 
 | ||||
|         if (!this.state.isPublic) { | ||||
|         if (this.state.joinRule !== JoinRule.Public) { | ||||
|             if (this.state.canChangeEncryption) { | ||||
|                 opts.encryption = this.state.isEncrypted; | ||||
|             } else { | ||||
|  | @ -109,8 +121,9 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> { | |||
|             opts.associatedWithCommunity = CommunityPrototypeStore.instance.getSelectedCommunityId(); | ||||
|         } | ||||
| 
 | ||||
|         if (this.props.parentSpace) { | ||||
|         if (this.props.parentSpace && this.state.joinRule === JoinRule.Restricted) { | ||||
|             opts.parentSpace = this.props.parentSpace; | ||||
|             opts.joinRule = JoinRule.Restricted; | ||||
|         } | ||||
| 
 | ||||
|         return opts; | ||||
|  | @ -172,8 +185,8 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> { | |||
|         this.setState({ topic: ev.target.value }); | ||||
|     }; | ||||
| 
 | ||||
|     private onPublicChange = (isPublic: boolean) => { | ||||
|         this.setState({ isPublic }); | ||||
|     private onJoinRuleChange = (joinRule: JoinRule) => { | ||||
|         this.setState({ joinRule }); | ||||
|     }; | ||||
| 
 | ||||
|     private onEncryptedChange = (isEncrypted: boolean) => { | ||||
|  | @ -210,7 +223,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> { | |||
| 
 | ||||
|     render() { | ||||
|         let aliasField; | ||||
|         if (this.state.isPublic) { | ||||
|         if (this.state.joinRule === JoinRule.Public) { | ||||
|             const domain = MatrixClientPeg.get().getDomain(); | ||||
|             aliasField = ( | ||||
|                 <div className="mx_CreateRoomDialog_aliasContainer"> | ||||
|  | @ -224,19 +237,46 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> { | |||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         let publicPrivateLabel = <p>{_t( | ||||
|             "Private rooms can be found and joined by invitation only. Public rooms can be " + | ||||
|             "found and joined by anyone.", | ||||
|         )}</p>; | ||||
|         let publicPrivateLabel: JSX.Element; | ||||
|         if (CommunityPrototypeStore.instance.getSelectedCommunityId()) { | ||||
|             publicPrivateLabel = <p>{_t( | ||||
|                 "Private rooms can be found and joined by invitation only. Public rooms can be " + | ||||
|                 "found and joined by anyone in this community.", | ||||
|             )}</p>; | ||||
|             publicPrivateLabel = <p> | ||||
|                 { _t( | ||||
|                     "Private rooms can be found and joined by invitation only. Public rooms can be " + | ||||
|                     "found and joined by anyone in this community.", | ||||
|                 ) } | ||||
|             </p>; | ||||
|         } else if (this.state.joinRule === JoinRule.Restricted) { | ||||
|             publicPrivateLabel = <p> | ||||
|                 { _t( | ||||
|                     "Everyone in <SpaceName/> will be able to find and join this room.", {}, { | ||||
|                         SpaceName: () => this.props.parentSpace.name, | ||||
|                     }, | ||||
|                 ) } | ||||
|                   | ||||
|                 { _t("You can change this at any time from room settings.") } | ||||
|             </p>; | ||||
|         } else if (this.state.joinRule === JoinRule.Public) { | ||||
|             publicPrivateLabel = <p> | ||||
|                 { _t( | ||||
|                     "Anyone will be able to find and join this room, not just members of <SpaceName/>.", {}, { | ||||
|                         SpaceName: () => this.props.parentSpace.name, | ||||
|                     }, | ||||
|                 ) } | ||||
|                   | ||||
|                 { _t("You can change this at any time from room settings.") } | ||||
|             </p>; | ||||
|         } else if (this.state.joinRule === JoinRule.Invite) { | ||||
|             publicPrivateLabel = <p> | ||||
|                 { _t( | ||||
|                     "Only people invited will be able to find and join this room.", | ||||
|                 ) } | ||||
|                   | ||||
|                 { _t("You can change this at any time from room settings.") } | ||||
|             </p>; | ||||
|         } | ||||
| 
 | ||||
|         let e2eeSection; | ||||
|         if (!this.state.isPublic) { | ||||
|         if (this.state.joinRule !== JoinRule.Public) { | ||||
|             let microcopy; | ||||
|             if (privateShouldBeEncrypted()) { | ||||
|                 if (this.state.canChangeEncryption) { | ||||
|  | @ -273,15 +313,31 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> { | |||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         let title = this.state.isPublic ? _t('Create a public room') : _t('Create a private room'); | ||||
|         let title = _t("Create a room"); | ||||
|         if (CommunityPrototypeStore.instance.getSelectedCommunityId()) { | ||||
|             const name = CommunityPrototypeStore.instance.getSelectedCommunityName(); | ||||
|             title = _t("Create a room in %(communityName)s", { communityName: name }); | ||||
|         } else if (!this.props.parentSpace) { | ||||
|             title = this.state.joinRule === JoinRule.Public ? _t('Create a public room') : _t('Create a private room'); | ||||
|         } | ||||
| 
 | ||||
|         const options = [ | ||||
|             <div key={JoinRule.Invite} className=""> | ||||
|                 { _t("Private room (invite only)") } | ||||
|             </div>, | ||||
|             <div key={JoinRule.Public} className=""> | ||||
|                 { _t("Public room") } | ||||
|             </div>, | ||||
|         ]; | ||||
| 
 | ||||
|         if (this.supportsRestricted) { | ||||
|             options.unshift(<div key={JoinRule.Restricted} className=""> | ||||
|                 { _t("Visible to space members") } | ||||
|             </div>); | ||||
|         } | ||||
| 
 | ||||
|         return ( | ||||
|             <BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished} | ||||
|                 title={title} | ||||
|             > | ||||
|             <BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished} title={title}> | ||||
|                 <form onSubmit={this.onOk} onKeyDown={this.onKeyDown}> | ||||
|                     <div className="mx_Dialog_content"> | ||||
|                         <Field | ||||
|  | @ -298,11 +354,18 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> { | |||
|                             value={this.state.topic} | ||||
|                             className="mx_CreateRoomDialog_topic" | ||||
|                         /> | ||||
|                         <LabelledToggleSwitch | ||||
|                             label={_t("Make this room public")} | ||||
|                             onChange={this.onPublicChange} | ||||
|                             value={this.state.isPublic} | ||||
|                         /> | ||||
| 
 | ||||
|                         <Dropdown | ||||
|                             id="mx_CreateRoomDialog_typeDropdown" | ||||
|                             className="mx_CreateRoomDialog_typeDropdown" | ||||
|                             onOptionChange={this.onJoinRuleChange} | ||||
|                             menuWidth={448} | ||||
|                             value={this.state.joinRule} | ||||
|                             label={_t("Room visibility")} | ||||
|                         > | ||||
|                             { options } | ||||
|                         </Dropdown> | ||||
| 
 | ||||
|                         { publicPrivateLabel } | ||||
|                         { e2eeSection } | ||||
|                         { aliasField } | ||||
|  |  | |||
|  | @ -153,10 +153,8 @@ export default async function createRoom(opts: IOpts): Promise<string | null> { | |||
|         }); | ||||
| 
 | ||||
|         if (opts.joinRule === JoinRule.Restricted) { | ||||
|             const serverCapabilities = await client.getCapabilities(); | ||||
|             const roomCapabilities = serverCapabilities?.["m.room_versions"]?.["org.matrix.msc3244.room_capabilities"]; | ||||
|             if (roomCapabilities?.["restricted"]?.preferred) { | ||||
|                 opts.createOpts.room_version = roomCapabilities?.["restricted"].preferred; | ||||
|             if (SpaceStore.instance.restrictedJoinRuleSupport?.preferred) { | ||||
|                 opts.createOpts.room_version = SpaceStore.instance.restrictedJoinRuleSupport.preferred; | ||||
| 
 | ||||
|                 opts.createOpts.initial_state.push({ | ||||
|                     type: EventType.RoomJoinRules, | ||||
|  |  | |||
|  | @ -2200,11 +2200,15 @@ | |||
|     "Enable end-to-end encryption": "Enable end-to-end encryption", | ||||
|     "You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.": "You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.", | ||||
|     "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This cannot be changed later.": "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This cannot be changed later.", | ||||
|     "Create a room": "Create a room", | ||||
|     "Create a room in %(communityName)s": "Create a room in %(communityName)s", | ||||
|     "Create a public room": "Create a public room", | ||||
|     "Create a private room": "Create a private room", | ||||
|     "Create a room in %(communityName)s": "Create a room in %(communityName)s", | ||||
|     "Private room (invite only)": "Private room (invite only)", | ||||
|     "Public room": "Public room", | ||||
|     "Visible to space members": "Visible to space members", | ||||
|     "Topic (optional)": "Topic (optional)", | ||||
|     "Make this room public": "Make this room public", | ||||
|     "Room visibility": "Room visibility", | ||||
|     "Block anyone not part of %(serverName)s from ever joining this room.": "Block anyone not part of %(serverName)s from ever joining this room.", | ||||
|     "Create Room": "Create Room", | ||||
|     "Sign out": "Sign out", | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Michael Telatynski
						Michael Telatynski