;
} else if (this.state.joinRule === JoinRule.Invite) {
publicPrivateLabel =
- { _t(
- "Only people invited will be able to find and join this room.",
- ) }
+ { _t("Only people invited will be able to find and join this room.") }
+
+ { _t("You can change this at any time from room settings.") }
+
- { _t("Anyone can knock on this room to join.") }
+ { _t("This room type requires users to be granted access in order to join.") }
{ _t("You can change this at any time from room settings.") }
;
@@ -358,7 +356,7 @@ export default class CreateRoomDialog extends React.Component {
Learn more.": "Threads help keep conversations on-topic and easy to track. Learn more.",
@@ -2555,6 +2557,7 @@
"Anyone will be able to find and join this room, not just members of .": "Anyone will be able to find and join this room, not just members of .",
"Anyone will be able to find and join this room.": "Anyone will be able to find and join this room.",
"Only people invited will be able to find and join this room.": "Only people invited will be able to find and join this room.",
+ "This room type requires users to be granted access in order to join.": "This room type requires users to be granted access in order to join.",
"You can't disable this later. The room will be encrypted but the embedded call will not.": "You can't disable this later. The room will be encrypted but the embedded call will not.",
"You can't disable this later. Bridges & most bots won't work yet.": "You can't disable this later. Bridges & most bots won't work yet.",
"Your server requires encryption to be enabled in private rooms.": "Your server requires encryption to be enabled in private rooms.",
@@ -2568,7 +2571,7 @@
"Topic (optional)": "Topic (optional)",
"Room visibility": "Room visibility",
"Private room (invite only)": "Private room (invite only)",
- "Anyone can knock to join" : "Anyone can knock to join",
+ "Ask to join (Anyone can knock to join)": "Ask to join (Anyone can knock to join)",
"Visible to space members": "Visible to space members",
"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 video room": "Create video room",
From aaecd1850c775e11d31ce03204ce1956103e7d97 Mon Sep 17 00:00:00 2001
From: ankur12-1610
Date: Mon, 1 Aug 2022 12:33:18 +0530
Subject: [PATCH 5/8] Added `Ask to join` option in Room Settings
Signed-off-by: ankur12-1610
---
.../views/settings/JoinRuleSettings.tsx | 15 +++++++++++++++
src/i18n/strings/en_EN.json | 2 ++
src/utils/PreferredRoomVersions.ts | 5 +++++
3 files changed, 22 insertions(+)
diff --git a/src/components/views/settings/JoinRuleSettings.tsx b/src/components/views/settings/JoinRuleSettings.tsx
index 49295f0e83b..ea70085280a 100644
--- a/src/components/views/settings/JoinRuleSettings.tsx
+++ b/src/components/views/settings/JoinRuleSettings.tsx
@@ -24,6 +24,7 @@ import { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
import RoomAvatar from "../avatars/RoomAvatar";
import SpaceStore from "../../../stores/spaces/SpaceStore";
+import SettingsStore from "../../../settings/SettingsStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import Modal from "../../../Modal";
import ManageRestrictedJoinRuleDialog from "../dialogs/ManageRestrictedJoinRuleDialog";
@@ -49,6 +50,8 @@ interface IProps {
const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeChange, closeSettingsFn }: IProps) => {
const cli = room.client;
+ const roomSupportsKnocking = doesRoomVersionSupport(room.getVersion(), PreferredRoomVersions.KnockingRooms);
+
const roomSupportsRestricted = doesRoomVersionSupport(room.getVersion(), PreferredRoomVersions.RestrictedRooms);
const preferredRestrictionVersion = !roomSupportsRestricted && promptUpgrade
? PreferredRoomVersions.RestrictedRooms
@@ -56,6 +59,8 @@ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeCh
const disabled = !room.currentState.mayClientSendStateEvent(EventType.RoomJoinRules, cli);
+ const knockingEnabled = SettingsStore.getValue("feature_knocking");
+
const [content, setContent] = useLocalEcho(
() => room.currentState.getStateEvents(EventType.RoomJoinRules, "")?.getContent(),
content => cli.sendStateEvent(room.roomId, EventType.RoomJoinRules, content, ""),
@@ -89,6 +94,11 @@ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeCh
label: _t("Private (invite only)"),
description: _t("Only invited people can join."),
checked: joinRule === JoinRule.Invite || (joinRule === JoinRule.Restricted && !restrictedAllowRoomIds?.length),
+ }, {
+ value: JoinRule.Knock,
+ label: _t("Ask to join"),
+ description: _t("Requires users to be granted access in order to join"),
+ checked: joinRule === JoinRule.Knock && knockingEnabled && roomSupportsKnocking,
}, {
value: JoinRule.Public,
label: _t("Public"),
@@ -98,6 +108,11 @@ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeCh
>,
}];
+ if (!knockingEnabled || !roomSupportsKnocking) {
+ definitions.splice(1, 1); // removes the knock option if the room isn't compatible for the same
+ definitions[0].checked = true; //makes invite only room as default
+ }
+
if (roomSupportsRestricted || preferredRestrictionVersion || joinRule === JoinRule.Restricted) {
let upgradeRequiredPill;
if (preferredRestrictionVersion) {
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 4b25e821d51..e595283ee7b 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1328,6 +1328,8 @@
"Integration manager": "Integration manager",
"Private (invite only)": "Private (invite only)",
"Only invited people can join.": "Only invited people can join.",
+ "Ask to join": "Ask to join",
+ "Requires users to be granted access in order to join": "Requires users to be granted access in order to join",
"Anyone can find and join.": "Anyone can find and join.",
"Upgrade required": "Upgrade required",
"& %(count)s more|other": "& %(count)s more",
diff --git a/src/utils/PreferredRoomVersions.ts b/src/utils/PreferredRoomVersions.ts
index 2dc269da6c2..377c6dda100 100644
--- a/src/utils/PreferredRoomVersions.ts
+++ b/src/utils/PreferredRoomVersions.ts
@@ -28,6 +28,11 @@ export class PreferredRoomVersions {
*/
public static readonly RestrictedRooms = "9";
+ /**
+ * The room version to use when creating "knocking" rooms.
+ */
+ public static readonly KnockingRooms = "9";
+
private constructor() {
// readonly, static, class
}
From 23e9f63d4c0c33e8224bae6fde48b97b74edfd8a Mon Sep 17 00:00:00 2001
From: ankur12-1610
Date: Wed, 10 Aug 2022 13:17:24 +0530
Subject: [PATCH 6/8] Added iterative method to splice the definitions
---
src/components/views/settings/JoinRuleSettings.tsx | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/components/views/settings/JoinRuleSettings.tsx b/src/components/views/settings/JoinRuleSettings.tsx
index ea70085280a..3b156f3d955 100644
--- a/src/components/views/settings/JoinRuleSettings.tsx
+++ b/src/components/views/settings/JoinRuleSettings.tsx
@@ -109,7 +109,13 @@ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeCh
}];
if (!knockingEnabled || !roomSupportsKnocking) {
- definitions.splice(1, 1); // removes the knock option if the room isn't compatible for the same
+ // removes the knock option if the room isn't compatible for the same
+ for (let i = 0; i < definitions.length; i++) {
+ if (definitions[i].value === JoinRule.Knock) {
+ definitions.splice(i, 1);
+ break;
+ }
+ }
definitions[0].checked = true; //makes invite only room as default
}
From 82993af25a3e697f0b37978889c912df7a2ee803 Mon Sep 17 00:00:00 2001
From: ankur12-1610
Date: Tue, 16 Aug 2022 13:45:23 +0530
Subject: [PATCH 7/8] Added cypress test for the implemented milestone
---
cypress/e2e/knocking/knocking.spec.ts | 75 +++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
create mode 100644 cypress/e2e/knocking/knocking.spec.ts
diff --git a/cypress/e2e/knocking/knocking.spec.ts b/cypress/e2e/knocking/knocking.spec.ts
new file mode 100644
index 00000000000..800596bf179
--- /dev/null
+++ b/cypress/e2e/knocking/knocking.spec.ts
@@ -0,0 +1,75 @@
+/*
+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 { SynapseInstance } from "../../plugins/synapsedocker";
+import { MatrixClient } from "../../global";
+import Chainable = Cypress.Chainable;
+
+function openCreateRoomDialog(): Chainable> {
+ cy.get('[aria-label="Add room"]').click();
+ cy.get('.mx_ContextualMenu [aria-label="New room"]').click();
+ return cy.get(".mx_CreateRoomDialog");
+}
+
+describe("Knocking", () => {
+ let synapse: SynapseInstance;
+
+ beforeEach(() => {
+ cy.startSynapse("default").then(data => {
+ synapse = data;
+
+ cy.initTestUser(synapse, "Tom");
+ });
+ });
+
+ afterEach(() => {
+ cy.stopSynapse(synapse);
+ });
+
+ it("should be able to create a room with knock JoinRule", () => {
+ // Enables labs flag feature
+ cy.enableLabsFeature("feature_knocking");
+ const name = "Test room 1";
+ const topic = "This is a test room";
+
+ // Create a room with knock JoinRule
+ openCreateRoomDialog().within(() => {
+ cy.get('[label="Name"]').type(name);
+ cy.get('[label="Topic (optional)"]').type(topic);
+ cy.get(".mx_JoinRuleDropdown").click();
+ cy.get(".mx_JoinRuleDropdown_knock").click();
+ cy.startMeasuring("from-submit-to-room");
+ cy.get(".mx_Dialog_primary").click();
+ });
+
+ // Change room settings
+ cy.openRoomSettings("Security & Privacy");
+ cy.get(".mx_StyledRadioButton_content").contains("Ask to join").click();
+ cy.closeDialog();
+
+ //Check if the room settings are visible if labs flag is disabled
+ cy.openUserSettings("Labs").within(() => {
+ //disables labs flag feature
+ cy.get("[aria-label='Knocking']").click();
+ });
+ cy.closeDialog();
+ //the default joinRule is set to Private (invite only)
+ cy.openRoomSettings("Security & Privacy");
+
+ cy.stopMeasuring("from-submit-to-room");
+ cy.get(".mx_RoomHeader_nametext").contains(name);
+ cy.get(".mx_RoomHeader_topic").contains(topic);
+ });
+});
From 8e7b212f72becb27e11434f6f1dce2b249b655ba Mon Sep 17 00:00:00 2001
From: ankur12-1610
Date: Tue, 16 Aug 2022 13:51:17 +0530
Subject: [PATCH 8/8] Resolved linting errors
---
cypress/e2e/knocking/knocking.spec.ts | 12 ++++++++----
cypress/support/labs.ts | 8 ++++++++
src/TextForEvent.tsx | 4 ++++
src/components/views/dialogs/CreateRoomDialog.tsx | 3 +++
src/i18n/strings/en_EN.json | 1 +
5 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/cypress/e2e/knocking/knocking.spec.ts b/cypress/e2e/knocking/knocking.spec.ts
index 800596bf179..a2f9e9ea3bb 100644
--- a/cypress/e2e/knocking/knocking.spec.ts
+++ b/cypress/e2e/knocking/knocking.spec.ts
@@ -14,7 +14,6 @@ limitations under the License.
///
import { SynapseInstance } from "../../plugins/synapsedocker";
-import { MatrixClient } from "../../global";
import Chainable = Cypress.Chainable;
function openCreateRoomDialog(): Chainable> {
@@ -54,19 +53,24 @@ describe("Knocking", () => {
cy.get(".mx_Dialog_primary").click();
});
- // Change room settings
+ // The room settings initially are set to Ask to join
cy.openRoomSettings("Security & Privacy");
- cy.get(".mx_StyledRadioButton_content").contains("Ask to join").click();
cy.closeDialog();
//Check if the room settings are visible if labs flag is disabled
cy.openUserSettings("Labs").within(() => {
//disables labs flag feature
cy.get("[aria-label='Knocking']").click();
+ // cy.disableLabsFeature("feature_knocking");
});
cy.closeDialog();
- //the default joinRule is set to Private (invite only)
+
+ //the default joinRule is set to Private (invite only) when the labs flag is disabled
cy.openRoomSettings("Security & Privacy");
+ cy.closeDialog();
+
+ // Click the expand link button to get more detailed view
+ cy.get(".mx_GenericEventListSummary_toggle[aria-expanded=false]").click();
cy.stopMeasuring("from-submit-to-room");
cy.get(".mx_RoomHeader_nametext").contains(name);
diff --git a/cypress/support/labs.ts b/cypress/support/labs.ts
index 3fff154e140..16e6f038cde 100644
--- a/cypress/support/labs.ts
+++ b/cypress/support/labs.ts
@@ -28,6 +28,7 @@ declare global {
* @param feature labsFeature to enable (e.g. "feature_spotlight")
*/
enableLabsFeature(feature: string): Chainable;
+ disableLabsFeature(feature: string): Chainable;
}
}
}
@@ -38,5 +39,12 @@ Cypress.Commands.add("enableLabsFeature", (feature: string): Chainable =>
}).then(() => null);
});
+Cypress.Commands.add("disableLabsFeature", (feature: string): Chainable => {
+ return cy.window({ log: false }).then(win => {
+ win.localStorage.removeItem(`mx_labs_feature_${feature}`);
+ win.localStorage.setItem(`mx_labs_feature_${feature}`, "false");
+ }).then(() => null);
+});
+
// Needed to make this file a module
export { };
diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx
index 9310391e3e2..c4fefc1e851 100644
--- a/src/TextForEvent.tsx
+++ b/src/TextForEvent.tsx
@@ -235,6 +235,10 @@ function textForJoinRulesEvent(ev: MatrixEvent, allowJSX: boolean): () => Render
return () => _t('%(senderDisplayName)s made the room invite only.', {
senderDisplayName,
});
+ case JoinRule.Knock:
+ return () => _t('%(senderDisplayName)s made the room knock only.', {
+ senderDisplayName,
+ });
case JoinRule.Restricted:
if (allowJSX) {
return () =>
diff --git a/src/components/views/dialogs/CreateRoomDialog.tsx b/src/components/views/dialogs/CreateRoomDialog.tsx
index 7c4ae328289..53364d3f3be 100644
--- a/src/components/views/dialogs/CreateRoomDialog.tsx
+++ b/src/components/views/dialogs/CreateRoomDialog.tsx
@@ -123,6 +123,9 @@ export default class CreateRoomDialog extends React.Component {
opts.joinRule = JoinRule.Restricted;
}
+ if (this.state.joinRule === JoinRule.Knock) {
+ opts.joinRule = JoinRule.Knock;
+ }
return opts;
}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index e595283ee7b..06f9d4aa6d6 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -504,6 +504,7 @@
"%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s upgraded this room.",
"%(senderDisplayName)s made the room public to whoever knows the link.": "%(senderDisplayName)s made the room public to whoever knows the link.",
"%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s made the room invite only.",
+ "%(senderDisplayName)s made the room knock only.": "%(senderDisplayName)s made the room knock only.",
"%(senderDisplayName)s changed who can join this room. View settings.": "%(senderDisplayName)s changed who can join this room. View settings.",
"%(senderDisplayName)s changed who can join this room.": "%(senderDisplayName)s changed who can join this room.",
"%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s changed the join rule to %(rule)s",