Make CreateRoomDialog capable of creating restricted rooms in spaces
This commit is contained in:
parent
c5ca98a3ad
commit
eb9f4c609a
4 changed files with 111 additions and 38 deletions
|
@ -65,7 +65,7 @@ limitations under the License.
|
||||||
.mx_CreateRoomDialog_aliasContainer {
|
.mx_CreateRoomDialog_aliasContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
// put margin on container so it can collapse with siblings
|
// put margin on container so it can collapse with siblings
|
||||||
margin: 10px 0;
|
margin: 24px 0 10px;
|
||||||
|
|
||||||
.mx_RoomAliasField {
|
.mx_RoomAliasField {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -101,10 +101,6 @@ limitations under the License.
|
||||||
margin-left: 30px;
|
margin-left: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_CreateRoomDialog_topic {
|
|
||||||
margin-bottom: 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_Dialog_content > .mx_SettingsFlag {
|
.mx_Dialog_content > .mx_SettingsFlag {
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
@ -113,5 +109,17 @@ limitations under the License.
|
||||||
margin: 0 85px 0 0;
|
margin: 0 85px 0 0;
|
||||||
font-size: $font-12px;
|
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 React, { ChangeEvent, createRef, KeyboardEvent, SyntheticEvent } from "react";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
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 SdkConfig from '../../../SdkConfig';
|
||||||
import withValidation, { IFieldState } from '../elements/Validation';
|
import withValidation, { IFieldState } from '../elements/Validation';
|
||||||
|
@ -31,7 +32,8 @@ import RoomAliasField from "../elements/RoomAliasField";
|
||||||
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||||
import DialogButtons from "../elements/DialogButtons";
|
import DialogButtons from "../elements/DialogButtons";
|
||||||
import BaseDialog from "../dialogs/BaseDialog";
|
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 {
|
interface IProps {
|
||||||
defaultPublic?: boolean;
|
defaultPublic?: boolean;
|
||||||
|
@ -41,7 +43,7 @@ interface IProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
isPublic: boolean;
|
joinRule: JoinRule;
|
||||||
isEncrypted: boolean;
|
isEncrypted: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
topic: string;
|
topic: string;
|
||||||
|
@ -54,15 +56,25 @@ interface IState {
|
||||||
|
|
||||||
@replaceableComponent("views.dialogs.CreateRoomDialog")
|
@replaceableComponent("views.dialogs.CreateRoomDialog")
|
||||||
export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
|
private readonly supportsRestricted: boolean;
|
||||||
private nameField = createRef<Field>();
|
private nameField = createRef<Field>();
|
||||||
private aliasField = createRef<RoomAliasField>();
|
private aliasField = createRef<RoomAliasField>();
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(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();
|
const config = SdkConfig.get();
|
||||||
this.state = {
|
this.state = {
|
||||||
isPublic: this.props.defaultPublic || false,
|
joinRule,
|
||||||
isEncrypted: privateShouldBeEncrypted(),
|
isEncrypted: privateShouldBeEncrypted(),
|
||||||
name: this.props.defaultName || "",
|
name: this.props.defaultName || "",
|
||||||
topic: "",
|
topic: "",
|
||||||
|
@ -81,7 +93,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
const opts: IOpts = {};
|
const opts: IOpts = {};
|
||||||
const createOpts: IOpts["createOpts"] = opts.createOpts = {};
|
const createOpts: IOpts["createOpts"] = opts.createOpts = {};
|
||||||
createOpts.name = this.state.name;
|
createOpts.name = this.state.name;
|
||||||
if (this.state.isPublic) {
|
if (this.state.joinRule === JoinRule.Public) {
|
||||||
createOpts.visibility = Visibility.Public;
|
createOpts.visibility = Visibility.Public;
|
||||||
createOpts.preset = Preset.PublicChat;
|
createOpts.preset = Preset.PublicChat;
|
||||||
opts.guestAccess = false;
|
opts.guestAccess = false;
|
||||||
|
@ -95,7 +107,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
createOpts.creation_content = { 'm.federate': false };
|
createOpts.creation_content = { 'm.federate': false };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.isPublic) {
|
if (this.state.joinRule !== JoinRule.Public) {
|
||||||
if (this.state.canChangeEncryption) {
|
if (this.state.canChangeEncryption) {
|
||||||
opts.encryption = this.state.isEncrypted;
|
opts.encryption = this.state.isEncrypted;
|
||||||
} else {
|
} else {
|
||||||
|
@ -109,8 +121,9 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
opts.associatedWithCommunity = CommunityPrototypeStore.instance.getSelectedCommunityId();
|
opts.associatedWithCommunity = CommunityPrototypeStore.instance.getSelectedCommunityId();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.parentSpace) {
|
if (this.props.parentSpace && this.state.joinRule === JoinRule.Restricted) {
|
||||||
opts.parentSpace = this.props.parentSpace;
|
opts.parentSpace = this.props.parentSpace;
|
||||||
|
opts.joinRule = JoinRule.Restricted;
|
||||||
}
|
}
|
||||||
|
|
||||||
return opts;
|
return opts;
|
||||||
|
@ -172,8 +185,8 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
this.setState({ topic: ev.target.value });
|
this.setState({ topic: ev.target.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
private onPublicChange = (isPublic: boolean) => {
|
private onJoinRuleChange = (joinRule: JoinRule) => {
|
||||||
this.setState({ isPublic });
|
this.setState({ joinRule });
|
||||||
};
|
};
|
||||||
|
|
||||||
private onEncryptedChange = (isEncrypted: boolean) => {
|
private onEncryptedChange = (isEncrypted: boolean) => {
|
||||||
|
@ -210,7 +223,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let aliasField;
|
let aliasField;
|
||||||
if (this.state.isPublic) {
|
if (this.state.joinRule === JoinRule.Public) {
|
||||||
const domain = MatrixClientPeg.get().getDomain();
|
const domain = MatrixClientPeg.get().getDomain();
|
||||||
aliasField = (
|
aliasField = (
|
||||||
<div className="mx_CreateRoomDialog_aliasContainer">
|
<div className="mx_CreateRoomDialog_aliasContainer">
|
||||||
|
@ -224,19 +237,46 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let publicPrivateLabel = <p>{_t(
|
let publicPrivateLabel: JSX.Element;
|
||||||
"Private rooms can be found and joined by invitation only. Public rooms can be " +
|
|
||||||
"found and joined by anyone.",
|
|
||||||
)}</p>;
|
|
||||||
if (CommunityPrototypeStore.instance.getSelectedCommunityId()) {
|
if (CommunityPrototypeStore.instance.getSelectedCommunityId()) {
|
||||||
publicPrivateLabel = <p>{_t(
|
publicPrivateLabel = <p>
|
||||||
"Private rooms can be found and joined by invitation only. Public rooms can be " +
|
{ _t(
|
||||||
"found and joined by anyone in this community.",
|
"Private rooms can be found and joined by invitation only. Public rooms can be " +
|
||||||
)}</p>;
|
"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;
|
let e2eeSection;
|
||||||
if (!this.state.isPublic) {
|
if (this.state.joinRule !== JoinRule.Public) {
|
||||||
let microcopy;
|
let microcopy;
|
||||||
if (privateShouldBeEncrypted()) {
|
if (privateShouldBeEncrypted()) {
|
||||||
if (this.state.canChangeEncryption) {
|
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()) {
|
if (CommunityPrototypeStore.instance.getSelectedCommunityId()) {
|
||||||
const name = CommunityPrototypeStore.instance.getSelectedCommunityName();
|
const name = CommunityPrototypeStore.instance.getSelectedCommunityName();
|
||||||
title = _t("Create a room in %(communityName)s", { communityName: name });
|
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 (
|
return (
|
||||||
<BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished}
|
<BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished} title={title}>
|
||||||
title={title}
|
|
||||||
>
|
|
||||||
<form onSubmit={this.onOk} onKeyDown={this.onKeyDown}>
|
<form onSubmit={this.onOk} onKeyDown={this.onKeyDown}>
|
||||||
<div className="mx_Dialog_content">
|
<div className="mx_Dialog_content">
|
||||||
<Field
|
<Field
|
||||||
|
@ -298,11 +354,18 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
value={this.state.topic}
|
value={this.state.topic}
|
||||||
className="mx_CreateRoomDialog_topic"
|
className="mx_CreateRoomDialog_topic"
|
||||||
/>
|
/>
|
||||||
<LabelledToggleSwitch
|
|
||||||
label={_t("Make this room public")}
|
<Dropdown
|
||||||
onChange={this.onPublicChange}
|
id="mx_CreateRoomDialog_typeDropdown"
|
||||||
value={this.state.isPublic}
|
className="mx_CreateRoomDialog_typeDropdown"
|
||||||
/>
|
onOptionChange={this.onJoinRuleChange}
|
||||||
|
menuWidth={448}
|
||||||
|
value={this.state.joinRule}
|
||||||
|
label={_t("Room visibility")}
|
||||||
|
>
|
||||||
|
{ options }
|
||||||
|
</Dropdown>
|
||||||
|
|
||||||
{ publicPrivateLabel }
|
{ publicPrivateLabel }
|
||||||
{ e2eeSection }
|
{ e2eeSection }
|
||||||
{ aliasField }
|
{ aliasField }
|
||||||
|
|
|
@ -153,10 +153,8 @@ export default async function createRoom(opts: IOpts): Promise<string | null> {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (opts.joinRule === JoinRule.Restricted) {
|
if (opts.joinRule === JoinRule.Restricted) {
|
||||||
const serverCapabilities = await client.getCapabilities();
|
if (SpaceStore.instance.restrictedJoinRuleSupport?.preferred) {
|
||||||
const roomCapabilities = serverCapabilities?.["m.room_versions"]?.["org.matrix.msc3244.room_capabilities"];
|
opts.createOpts.room_version = SpaceStore.instance.restrictedJoinRuleSupport.preferred;
|
||||||
if (roomCapabilities?.["restricted"]?.preferred) {
|
|
||||||
opts.createOpts.room_version = roomCapabilities?.["restricted"].preferred;
|
|
||||||
|
|
||||||
opts.createOpts.initial_state.push({
|
opts.createOpts.initial_state.push({
|
||||||
type: EventType.RoomJoinRules,
|
type: EventType.RoomJoinRules,
|
||||||
|
|
|
@ -2200,11 +2200,15 @@
|
||||||
"Enable end-to-end encryption": "Enable end-to-end encryption",
|
"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 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.",
|
"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 public room": "Create a public room",
|
||||||
"Create a private room": "Create a private 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)",
|
"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.",
|
"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",
|
"Create Room": "Create Room",
|
||||||
"Sign out": "Sign out",
|
"Sign out": "Sign out",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue