Replace MSC3244 support with in-client room version checking (#9018)
* Replace MSC3244 support with in-client room version checking * Fix irrelevant ternary * It helps to use Jest correctly
This commit is contained in:
parent
bd8949872d
commit
644b841591
7 changed files with 120 additions and 37 deletions
|
@ -30,7 +30,6 @@ import RoomAliasField from "../elements/RoomAliasField";
|
|||
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||
import DialogButtons from "../elements/DialogButtons";
|
||||
import BaseDialog from "../dialogs/BaseDialog";
|
||||
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
||||
import JoinRuleDropdown from "../elements/JoinRuleDropdown";
|
||||
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
|
||||
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
||||
|
@ -66,7 +65,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.supportsRestricted = this.props.parentSpace && !!SpaceStore.instance.restrictedJoinRuleSupport?.preferred;
|
||||
this.supportsRestricted = !!this.props.parentSpace;
|
||||
|
||||
let joinRule = JoinRule.Invite;
|
||||
if (this.props.defaultPublic) {
|
||||
|
|
|
@ -26,7 +26,6 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
|||
import { BetaPill } from "../beta/BetaCard";
|
||||
import Field from "../elements/Field";
|
||||
import RoomAliasField from "../elements/RoomAliasField";
|
||||
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
||||
import { createSpace, SpaceCreateForm } from "../spaces/SpaceCreateMenu";
|
||||
import { SubspaceSelector } from "./AddExistingToSpaceDialog";
|
||||
import JoinRuleDropdown from "../elements/JoinRuleDropdown";
|
||||
|
@ -48,14 +47,10 @@ const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick
|
|||
const [avatar, setAvatar] = useState<File>(null);
|
||||
const [topic, setTopic] = useState<string>("");
|
||||
|
||||
const supportsRestricted = !!SpaceStore.instance.restrictedJoinRuleSupport?.preferred;
|
||||
|
||||
const spaceJoinRule = space.getJoinRule();
|
||||
let defaultJoinRule = JoinRule.Invite;
|
||||
let defaultJoinRule = JoinRule.Restricted;
|
||||
if (spaceJoinRule === JoinRule.Public) {
|
||||
defaultJoinRule = JoinRule.Public;
|
||||
} else if (supportsRestricted) {
|
||||
defaultJoinRule = JoinRule.Restricted;
|
||||
}
|
||||
const [joinRule, setJoinRule] = useState<JoinRule>(defaultJoinRule);
|
||||
|
||||
|
@ -150,7 +145,7 @@ const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick
|
|||
label={_t("Space visibility")}
|
||||
labelInvite={_t("Private space (invite only)")}
|
||||
labelPublic={_t("Public space")}
|
||||
labelRestricted={supportsRestricted ? _t("Visible to space members") : undefined}
|
||||
labelRestricted={_t("Visible to space members")}
|
||||
width={478}
|
||||
value={joinRule}
|
||||
onChange={setJoinRule}
|
||||
|
|
|
@ -35,6 +35,7 @@ import dis from "../../../dispatcher/dispatcher";
|
|||
import { ROOM_SECURITY_TAB } from "../dialogs/RoomSettingsDialog";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { doesRoomVersionSupport, PreferredRoomVersions } from "../../../utils/PreferredRoomVersions";
|
||||
|
||||
interface IProps {
|
||||
room: Room;
|
||||
|
@ -48,11 +49,9 @@ interface IProps {
|
|||
const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeChange, closeSettingsFn }: IProps) => {
|
||||
const cli = room.client;
|
||||
|
||||
const restrictedRoomCapabilities = SpaceStore.instance.restrictedJoinRuleSupport;
|
||||
const roomSupportsRestricted = Array.isArray(restrictedRoomCapabilities?.support)
|
||||
&& restrictedRoomCapabilities.support.includes(room.getVersion());
|
||||
const roomSupportsRestricted = doesRoomVersionSupport(room.getVersion(), PreferredRoomVersions.RestrictedRooms);
|
||||
const preferredRestrictionVersion = !roomSupportsRestricted && promptUpgrade
|
||||
? restrictedRoomCapabilities?.preferred
|
||||
? PreferredRoomVersions.RestrictedRooms
|
||||
: undefined;
|
||||
|
||||
const disabled = !room.currentState.mayClientSendStateEvent(EventType.RoomJoinRules, cli);
|
||||
|
|
|
@ -45,6 +45,7 @@ import { ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload";
|
|||
import { findDMForUser } from "./utils/direct-messages";
|
||||
import { privateShouldBeEncrypted } from "./utils/rooms";
|
||||
import { waitForMember } from "./utils/membership";
|
||||
import { PreferredRoomVersions } from "./utils/PreferredRoomVersions";
|
||||
|
||||
// we define a number of interfaces which take their names from the js-sdk
|
||||
/* eslint-disable camelcase */
|
||||
|
@ -191,20 +192,18 @@ export default async function createRoom(opts: IOpts): Promise<string | null> {
|
|||
}
|
||||
|
||||
if (opts.joinRule === JoinRule.Restricted) {
|
||||
if (SpaceStore.instance.restrictedJoinRuleSupport?.preferred) {
|
||||
createOpts.room_version = SpaceStore.instance.restrictedJoinRuleSupport.preferred;
|
||||
createOpts.room_version = PreferredRoomVersions.RestrictedRooms;
|
||||
|
||||
createOpts.initial_state.push({
|
||||
type: EventType.RoomJoinRules,
|
||||
content: {
|
||||
"join_rule": JoinRule.Restricted,
|
||||
"allow": [{
|
||||
"type": RestrictedAllowType.RoomMembership,
|
||||
"room_id": opts.parentSpace.roomId,
|
||||
}],
|
||||
},
|
||||
});
|
||||
}
|
||||
createOpts.initial_state.push({
|
||||
type: EventType.RoomJoinRules,
|
||||
content: {
|
||||
"join_rule": JoinRule.Restricted,
|
||||
"allow": [{
|
||||
"type": RestrictedAllowType.RoomMembership,
|
||||
"room_id": opts.parentSpace.roomId,
|
||||
}],
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import { ListIteratee, Many, sortBy } from "lodash";
|
|||
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
|
||||
import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { ClientEvent, IRoomCapability } from "matrix-js-sdk/src/client";
|
||||
import { ClientEvent } from "matrix-js-sdk/src/client";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||
|
@ -132,7 +132,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
private _suggestedRooms: ISuggestedRoom[] = [];
|
||||
private _invitedSpaces = new Set<Room>();
|
||||
private spaceOrderLocalEchoMap = new Map<string, string>();
|
||||
private _restrictedJoinRuleSupport?: IRoomCapability;
|
||||
// The following properties are set by onReady as they live in account_data
|
||||
private _allRoomsInHome = false;
|
||||
private _enabledMetaSpaces: MetaSpace[] = [];
|
||||
|
@ -210,10 +209,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
}
|
||||
}
|
||||
|
||||
public get restrictedJoinRuleSupport(): IRoomCapability {
|
||||
return this._restrictedJoinRuleSupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active space, updates room list filters,
|
||||
* optionally switches the user's room back to where they were when they last viewed that space.
|
||||
|
@ -1066,11 +1061,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
this.matrixClient.on(RoomStateEvent.Members, this.onRoomStateMembers);
|
||||
this.matrixClient.on(ClientEvent.AccountData, this.onAccountData);
|
||||
|
||||
this.matrixClient.getCapabilities().then(capabilities => {
|
||||
this._restrictedJoinRuleSupport = capabilities
|
||||
?.["m.room_versions"]?.["org.matrix.msc3244.room_capabilities"]?.["restricted"];
|
||||
});
|
||||
|
||||
const oldMetaSpaces = this._enabledMetaSpaces;
|
||||
const enabledMetaSpaces = SettingsStore.getValue("Spaces.enabledMetaSpaces");
|
||||
this._enabledMetaSpaces = metaSpaceOrder.filter(k => enabledMetaSpaces[k]);
|
||||
|
|
55
src/utils/PreferredRoomVersions.ts
Normal file
55
src/utils/PreferredRoomVersions.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The preferred room versions for various features within the app. The
|
||||
* room versions here are selected based on the client's support for the
|
||||
* possible room versions in combination with server support in the
|
||||
* ecosystem.
|
||||
*
|
||||
* Loosely follows https://spec.matrix.org/latest/rooms/#feature-matrix
|
||||
*/
|
||||
export class PreferredRoomVersions {
|
||||
/**
|
||||
* The room version to use when creating "restricted" rooms.
|
||||
*/
|
||||
public static readonly RestrictedRooms = "9";
|
||||
|
||||
private constructor() {
|
||||
// readonly, static, class
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a room version supports the given feature using heuristics
|
||||
* for how Matrix works.
|
||||
* @param roomVer The room version to check support within.
|
||||
* @param featureVer The room version of the feature. Should be from PreferredRoomVersions.
|
||||
* @see PreferredRoomVersions
|
||||
*/
|
||||
export function doesRoomVersionSupport(roomVer: string, featureVer: string): boolean {
|
||||
// Assumption: all unstable room versions don't support the feature. Calling code can check for unstable
|
||||
// room versions explicitly if it wants to. The spec reserves [0-9] and `.` for its room versions.
|
||||
if (!roomVer.match(/[\d.]+/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dev note: While the spec says room versions are not linear, we can make reasonable assumptions
|
||||
// until the room versions prove themselves to be non-linear in the spec. We should see this coming
|
||||
// from a mile away and can course-correct this function if needed.
|
||||
return Number(roomVer) >= Number(featureVer);
|
||||
}
|
||||
|
46
test/PreferredRoomVersions-test.ts
Normal file
46
test/PreferredRoomVersions-test.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { doesRoomVersionSupport, PreferredRoomVersions } from "../src/utils/PreferredRoomVersions";
|
||||
|
||||
describe("doesRoomVersionSupport", () => {
|
||||
it("should detect unstable as unsupported", () => {
|
||||
expect(doesRoomVersionSupport("org.example.unstable", "1")).toBe(false);
|
||||
expect(doesRoomVersionSupport("1.2-beta", "1")).toBe(false);
|
||||
});
|
||||
|
||||
it("should detect support properly", () => {
|
||||
expect(doesRoomVersionSupport("1", "2")).toBe(false); // older
|
||||
expect(doesRoomVersionSupport("2", "2")).toBe(true); // exact
|
||||
expect(doesRoomVersionSupport("3", "2")).toBe(true); // newer
|
||||
});
|
||||
|
||||
it("should handle decimal versions", () => {
|
||||
expect(doesRoomVersionSupport("1.1", "2.2")).toBe(false); // older
|
||||
expect(doesRoomVersionSupport("2.1", "2.2")).toBe(false); // exact-ish
|
||||
expect(doesRoomVersionSupport("2.2", "2.2")).toBe(true); // exact
|
||||
expect(doesRoomVersionSupport("2.3", "2.2")).toBe(true); // exact-ish
|
||||
expect(doesRoomVersionSupport("3.1", "2.2")).toBe(true); // newer
|
||||
});
|
||||
|
||||
it("should detect restricted rooms in v9 and v10", () => {
|
||||
// Dev note: we consider it a feature that v8 rooms have to upgrade considering the bug in v8.
|
||||
// https://spec.matrix.org/v1.3/rooms/v8/#redactions
|
||||
expect(doesRoomVersionSupport("8", PreferredRoomVersions.RestrictedRooms)).toBe(false);
|
||||
expect(doesRoomVersionSupport("9", PreferredRoomVersions.RestrictedRooms)).toBe(true);
|
||||
expect(doesRoomVersionSupport("10", PreferredRoomVersions.RestrictedRooms)).toBe(true);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue