Add UIFeature to hide public space and room creation (#30708)
* Add settings to hide public room & space creation. * Add space changes. * Add room changes. * lint * Add playwright tests * don't specialcase 1 join rule * Ensure mocks get cleared * Fixup test * Add SpaceCreateMenu component unit-tests * Fixup create room test asserts * fix import
This commit is contained in:
@@ -85,6 +85,7 @@ interface IState {
|
||||
export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||
private readonly askToJoinEnabled: boolean;
|
||||
private readonly advancedSettingsEnabled: boolean;
|
||||
private readonly allowCreatingPublicRooms: boolean;
|
||||
private readonly supportsRestricted: boolean;
|
||||
private nameField = createRef<Field>();
|
||||
private aliasField = createRef<RoomAliasField>();
|
||||
@@ -94,11 +95,13 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||
|
||||
this.askToJoinEnabled = SettingsStore.getValue("feature_ask_to_join");
|
||||
this.advancedSettingsEnabled = SettingsStore.getValue(UIFeature.AdvancedSettings);
|
||||
this.allowCreatingPublicRooms = SettingsStore.getValue(UIFeature.AllowCreatingPublicRooms);
|
||||
|
||||
this.supportsRestricted = !!this.props.parentSpace;
|
||||
const defaultPublic = this.allowCreatingPublicRooms && this.props.defaultPublic;
|
||||
|
||||
let joinRule = JoinRule.Invite;
|
||||
if (this.props.defaultPublic) {
|
||||
if (defaultPublic) {
|
||||
joinRule = JoinRule.Public;
|
||||
} else if (this.supportsRestricted) {
|
||||
joinRule = JoinRule.Restricted;
|
||||
@@ -106,7 +109,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
this.state = {
|
||||
isPublicKnockRoom: this.props.defaultPublic || false,
|
||||
isPublicKnockRoom: defaultPublic || false,
|
||||
isEncrypted: this.props.defaultEncrypted ?? privateShouldBeEncrypted(cli),
|
||||
joinRule,
|
||||
name: this.props.defaultName || "",
|
||||
@@ -419,7 +422,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||
labelKnock={
|
||||
this.askToJoinEnabled ? _t("room_settings|security|join_rule_knock") : undefined
|
||||
}
|
||||
labelPublic={_t("common|public_room")}
|
||||
labelPublic={this.allowCreatingPublicRooms ? _t("common|public_room") : undefined}
|
||||
labelRestricted={
|
||||
this.supportsRestricted ? _t("create_room|join_rule_restricted") : undefined
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ interface IProps {
|
||||
width?: number;
|
||||
labelInvite: string;
|
||||
labelKnock?: string;
|
||||
labelPublic: string;
|
||||
labelPublic?: string;
|
||||
labelRestricted?: string; // if omitted then this option will be hidden, e.g if unsupported
|
||||
onChange(value: JoinRule): void;
|
||||
}
|
||||
@@ -38,11 +38,18 @@ const JoinRuleDropdown: React.FC<IProps> = ({
|
||||
<div key={JoinRule.Invite} className="mx_JoinRuleDropdown_invite">
|
||||
{labelInvite}
|
||||
</div>,
|
||||
<div key={JoinRule.Public} className="mx_JoinRuleDropdown_public">
|
||||
{labelPublic}
|
||||
</div>,
|
||||
] as NonEmptyArray<ReactElement & { key: string }>;
|
||||
|
||||
if (labelPublic) {
|
||||
options.push(
|
||||
(
|
||||
<div key={JoinRule.Public} className="mx_JoinRuleDropdown_public">
|
||||
{labelPublic}
|
||||
</div>
|
||||
) as ReactElement & { key: string },
|
||||
);
|
||||
}
|
||||
|
||||
if (labelKnock) {
|
||||
options.unshift(
|
||||
(
|
||||
@@ -72,6 +79,7 @@ const JoinRuleDropdown: React.FC<IProps> = ({
|
||||
menuWidth={width}
|
||||
value={value}
|
||||
label={label}
|
||||
disabled={options.length === 1}
|
||||
>
|
||||
{options}
|
||||
</Dropdown>
|
||||
|
||||
@@ -45,6 +45,8 @@ import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
import { Filter } from "../dialogs/spotlight/Filter";
|
||||
import { type OpenSpotlightPayload } from "../../../dispatcher/payloads/OpenSpotlightPayload.ts";
|
||||
import { useSettingValue } from "../../../hooks/useSettings.ts";
|
||||
import { UIFeature } from "../../../settings/UIFeature.ts";
|
||||
|
||||
export const createSpace = async (
|
||||
client: MatrixClient,
|
||||
@@ -212,7 +214,10 @@ const SpaceCreateMenu: React.FC<{
|
||||
onFinished(): void;
|
||||
}> = ({ onFinished }) => {
|
||||
const cli = useMatrixClientContext();
|
||||
const [visibility, setVisibility] = useState<Visibility | null>(null);
|
||||
const settingAllowPublicSpaces = useSettingValue(UIFeature.AllowCreatingPublicSpaces);
|
||||
const [visibility, setVisibility] = useState<Visibility | null>(
|
||||
settingAllowPublicSpaces === false ? Visibility.Private : null,
|
||||
);
|
||||
const [busy, setBusy] = useState<boolean>(false);
|
||||
|
||||
const [name, setName] = useState("");
|
||||
@@ -303,16 +308,20 @@ const SpaceCreateMenu: React.FC<{
|
||||
} else {
|
||||
body = (
|
||||
<React.Fragment>
|
||||
<AccessibleButton
|
||||
className="mx_SpaceCreateMenu_back"
|
||||
onClick={() => setVisibility(null)}
|
||||
title={_t("action|go_back")}
|
||||
/>
|
||||
{settingAllowPublicSpaces && (
|
||||
<AccessibleButton
|
||||
className="mx_SpaceCreateMenu_back"
|
||||
onClick={() => setVisibility(null)}
|
||||
title={_t("action|go_back")}
|
||||
/>
|
||||
)}
|
||||
|
||||
<h2>
|
||||
{visibility === Visibility.Public
|
||||
? _t("create_space|public_heading")
|
||||
: _t("create_space|private_heading")}
|
||||
: settingAllowPublicSpaces
|
||||
? _t("create_space|private_heading")
|
||||
: _t("create_space|private_only_heading")}
|
||||
</h2>
|
||||
<p>
|
||||
{_t("create_space|add_details_prompt")} {_t("create_space|add_details_prompt_2")}
|
||||
|
||||
@@ -718,6 +718,7 @@
|
||||
"personal_space_description": "A private space to organise your rooms",
|
||||
"private_description": "Invite only, best for yourself or teams",
|
||||
"private_heading": "Your private space",
|
||||
"private_only_heading": "Your space",
|
||||
"private_personal_description": "Make sure the right people have access to %(name)s",
|
||||
"private_personal_heading": "Who are you working with?",
|
||||
"private_space": "Me and my teammates",
|
||||
|
||||
@@ -1425,6 +1425,14 @@ export const SETTINGS: Settings = {
|
||||
supportedLevels: LEVELS_UI_FEATURE,
|
||||
default: true,
|
||||
},
|
||||
[UIFeature.AllowCreatingPublicSpaces]: {
|
||||
supportedLevels: LEVELS_UI_FEATURE,
|
||||
default: true,
|
||||
},
|
||||
[UIFeature.AllowCreatingPublicRooms]: {
|
||||
supportedLevels: LEVELS_UI_FEATURE,
|
||||
default: true,
|
||||
},
|
||||
|
||||
// Electron-specific settings, they are stored by Electron and set/read over an IPC.
|
||||
// We store them over there are they are necessary to know before the renderer process launches.
|
||||
|
||||
@@ -25,6 +25,8 @@ export const enum UIFeature {
|
||||
RoomHistorySettings = "UIFeature.roomHistorySettings",
|
||||
TimelineEnableRelativeDates = "UIFeature.timelineEnableRelativeDates",
|
||||
BulkUnverifiedSessionsReminder = "UIFeature.BulkUnverifiedSessionsReminder",
|
||||
AllowCreatingPublicRooms = "UIFeature.allowCreatingPublicRooms",
|
||||
AllowCreatingPublicSpaces = "UIFeature.allowCreatingPublicSpaces",
|
||||
}
|
||||
|
||||
export enum UIComponent {
|
||||
|
||||
Reference in New Issue
Block a user