From a1d72ea2ed621b7e9342973676a71021601b1b44 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 27 Mar 2025 14:18:49 +0000 Subject: [PATCH] Add settings for MSC4155 --- .../views/settings/InviteControlsPanel.tsx | 61 +++++++++++++++++++ .../tabs/user/SecurityUserSettingsTab.tsx | 2 + src/i18n/strings/en_EN.json | 7 +++ src/settings/Settings.tsx | 16 +++++ 4 files changed, 86 insertions(+) create mode 100644 src/components/views/settings/InviteControlsPanel.tsx diff --git a/src/components/views/settings/InviteControlsPanel.tsx b/src/components/views/settings/InviteControlsPanel.tsx new file mode 100644 index 0000000000..ba26571a44 --- /dev/null +++ b/src/components/views/settings/InviteControlsPanel.tsx @@ -0,0 +1,61 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import React, { type ChangeEventHandler, type FC, useCallback, useState } from "react"; +import { type AccountDataEvents } from "matrix-js-sdk/src/types"; +import { ErrorMessage, InlineField, Label, Root, ToggleInput } from "@vector-im/compound-web"; +import { logger } from "matrix-js-sdk/src/logger"; + +import { SettingsSubsection } from "./shared/SettingsSubsection"; +import { _t } from "../../../languageHandler"; +import { useAccountData } from "../../../hooks/useAccountData"; +import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; + +export const InviteControlsPanel: FC = () => { + const client = useMatrixClientContext(); + const inviteState = useAccountData( + client, + "org.matrix.msc4155.invite_permission_config", + ); + const isOn = inviteState.default !== "block"; + const [hasError, setHasError] = useState(false); + const [busy, setBusy] = useState(false); + + const setValue = useCallback>( + async (e) => { + setHasError(false); + setBusy(true); + try { + await client.setAccountData("org.matrix.msc4155.invite_permission_config", { + // Don't remove any other state set by other clients. + ...inviteState, + default: e.target.checked ? "allow" : "block", + }); + } catch (ex) { + logger.error("Could not change input config", ex); + setHasError(true); + } finally { + setBusy(false); + } + }, + [client, inviteState, isOn], + ); + + return ( + + + } + > + + {hasError && {_t("settings|invite_controls|error_message")}} + + + + ); +}; diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index 813576c757..3d5e6c9166 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -35,6 +35,7 @@ import { SettingsSubsection, SettingsSubsectionText } from "../../shared/Setting import { useOwnDevices } from "../../devices/useOwnDevices"; import { DiscoverySettings } from "../../discovery/DiscoverySettings"; import SetIntegrationManager from "../../SetIntegrationManager"; +import { InviteControlsPanel } from "../../InviteControlsPanel"; interface IIgnoredUserProps { userId: string; @@ -372,6 +373,7 @@ export default class SecurityUserSettingsTab extends React.Component + {SettingsStore.getValue("feature_invite_controls") ? : null} {posthogSection} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b7339fd9f4..ae85e69529 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1509,6 +1509,8 @@ "group_widgets": "Widgets", "hidebold": "Hide notification dot (only display counters badges)", "html_topic": "Show HTML representation of room topics", + "invite_controls": "Control who is allowed to invite you to rooms", + "invite_controls_msc_support": "Requires your server to support MSC4155", "join_beta": "Join the beta", "join_beta_reload": "Joining the beta will reload %(brand)s.", "jump_to_date": "Jump to date (adds /jumptodate and jump to date headers)", @@ -2684,6 +2686,11 @@ "inline_url_previews_room_account": "Enable URL previews for this room (only affects you)", "insert_trailing_colon_mentions": "Insert a trailing colon after user mentions at the start of a message", "invite_avatars": "Show avatars of rooms you have been invited to", + "invite_controls": { + "default_label": "Allow users to invite you to rooms", + "error_message": "An error occured while trying to change this setting", + "title": "Invite controls" + }, "jump_to_bottom_on_send": "Jump to the bottom of the timeline when you send a message", "key_backup": { "backup_in_progress": "Your keys are being backed up (the first backup could take a few minutes).", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 6984932fd9..cc2c8838fe 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -198,6 +198,7 @@ export interface Settings { "feature_html_topic": IFeature; "feature_bridge_state": IFeature; "feature_jump_to_date": IFeature; + "feature_invite_controls": IFeature; "feature_sliding_sync": IBaseSetting; "feature_simplified_sliding_sync": IFeature; "feature_element_call_video_rooms": IFeature; @@ -522,6 +523,21 @@ export const SETTINGS: Settings = { _td("labs|jump_to_date_msc_support"), ), }, + "feature_invite_controls": { + isFeature: true, + labsGroup: LabGroup.Rooms, + displayName: _td("labs|invite_controls"), + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED, + supportedLevelsAreOrdered: true, + default: false, + controller: new ServerSupportUnstableFeatureController( + "feature_invite_controls", + defaultWatchManager, + [["org.matrix.msc4155"]], + "v1.6", + _td("labs|invite_controls_msc_support"), + ), + }, "RoomList.backgroundImage": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, default: null,