Compare commits
3 Commits
develop
...
hs/invite-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d213a226b0 | ||
|
|
794695a8c7 | ||
|
|
a1d72ea2ed |
20
src/@types/matrix-js-sdk.d.ts
vendored
20
src/@types/matrix-js-sdk.d.ts
vendored
@@ -15,6 +15,8 @@ import type { EmptyObject } from "matrix-js-sdk/src/matrix";
|
||||
import type { DeviceClientInformation } from "../utils/device/types.ts";
|
||||
import type { UserWidget } from "../utils/WidgetUtils-types.ts";
|
||||
|
||||
type InviteConfigAccountDataRule = "allow" | "block";
|
||||
|
||||
// Extend Matrix JS SDK types via Typescript declaration merging to support unspecced event fields and types
|
||||
declare module "matrix-js-sdk/src/types" {
|
||||
export interface FileInfo {
|
||||
@@ -60,6 +62,21 @@ declare module "matrix-js-sdk/src/types" {
|
||||
};
|
||||
}
|
||||
|
||||
export interface InviteConfigAccountData {
|
||||
/**
|
||||
* Rule exceptions for users. Takes priority over `default` and `server_exceptions`.
|
||||
*/
|
||||
user_exceptions: Record<string, InviteConfigAccountDataRule>;
|
||||
/**
|
||||
* Rule exceptions for users. Takes priority over `default`.
|
||||
*/
|
||||
server_exceptions: Record<string, InviteConfigAccountDataRule>;
|
||||
/**
|
||||
* The default rule for invite handling when no exceptions match.
|
||||
*/
|
||||
default: InviteConfigAccountDataRule;
|
||||
}
|
||||
|
||||
export interface AccountDataEvents {
|
||||
// Analytics account data event
|
||||
"im.vector.analytics": {
|
||||
@@ -87,6 +104,9 @@ declare module "matrix-js-sdk/src/types" {
|
||||
"m.accepted_terms": {
|
||||
accepted: string[];
|
||||
};
|
||||
|
||||
// MSC4155: Invite filtering
|
||||
"org.matrix.msc4155.invite_permission_config": InviteConfigAccountData;
|
||||
}
|
||||
|
||||
export interface AudioContent {
|
||||
|
||||
62
src/components/views/settings/InviteControlsPanel.tsx
Normal file
62
src/components/views/settings/InviteControlsPanel.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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<AccountDataEvents["org.matrix.msc4155.invite_permission_config"]>(
|
||||
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<ChangeEventHandler<HTMLInputElement>>(
|
||||
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 (
|
||||
<SettingsSubsection heading={_t("settings|invite_controls|title")}>
|
||||
<Root>
|
||||
<InlineField
|
||||
name="default"
|
||||
control={<ToggleInput disabled={busy} onChange={setValue} checked={isOn} />}
|
||||
>
|
||||
<Label>{_t("settings|invite_controls|default_label")}</Label>
|
||||
{hasError && <ErrorMessage>{_t("settings|invite_controls|error_message")}</ErrorMessage>}
|
||||
</InlineField>
|
||||
</Root>
|
||||
</SettingsSubsection>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2024,2025 New Vector Ltd.
|
||||
Copyright 2019-2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
@@ -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<IProps, ISt
|
||||
<CryptographyPanel />
|
||||
</SettingsSection>
|
||||
<SettingsSection heading={_t("common|privacy")}>
|
||||
{SettingsStore.getValue("feature_invite_controls") ? <InviteControlsPanel /> : null}
|
||||
<DiscoverySettings />
|
||||
{posthogSection}
|
||||
</SettingsSection>
|
||||
|
||||
@@ -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).",
|
||||
|
||||
@@ -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<boolean>;
|
||||
"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,
|
||||
|
||||
Reference in New Issue
Block a user