Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Make CreateRoomDialog capable of creating restricted rooms in spaces
Browse files Browse the repository at this point in the history
  • Loading branch information
t3chguy committed Jul 6, 2021
1 parent c5ca98a commit eb9f4c6
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 38 deletions.
18 changes: 13 additions & 5 deletions res/css/views/dialogs/_CreateRoomDialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
}
}

117 changes: 90 additions & 27 deletions src/components/views/dialogs/CreateRoomDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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;
Expand All @@ -41,7 +43,7 @@ interface IProps {
}

interface IState {
isPublic: boolean;
joinRule: JoinRule;
isEncrypted: boolean;
name: string;
topic: string;
Expand All @@ -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: "",
Expand All @@ -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;
Expand All @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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">
Expand All @@ -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,
},
) }
&nbsp;
{ _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,
},
) }
&nbsp;
{ _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.",
) }
&nbsp;
{ _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) {
Expand Down Expand Up @@ -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
Expand All @@ -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 }
Expand Down
6 changes: 2 additions & 4 deletions src/createRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit eb9f4c6

Please sign in to comment.