diff --git a/src/components/views/auth/LoginWithQR.tsx b/src/components/views/auth/LoginWithQR.tsx index 7c7175b9678..2cc9300119e 100644 --- a/src/components/views/auth/LoginWithQR.tsx +++ b/src/components/views/auth/LoginWithQR.tsx @@ -153,9 +153,11 @@ export default class LoginWithQR extends React.Component { private generateCode = async (): Promise => { let rendezvous: MSC3906Rendezvous; try { + const fallbackRzServer = this.props.client.getClientWellKnown()?.["io.element.rendezvous"]?.server; const transport = new MSC3886SimpleHttpRendezvousTransport({ onFailure: this.onFailure, client: this.props.client, + fallbackRzServer, }); const channel = new MSC3903ECDHv2RendezvousChannel( diff --git a/src/components/views/settings/devices/LoginWithQRSection.tsx b/src/components/views/settings/devices/LoginWithQRSection.tsx index 3d63729ed19..5db5246bb4d 100644 --- a/src/components/views/settings/devices/LoginWithQRSection.tsx +++ b/src/components/views/settings/devices/LoginWithQRSection.tsx @@ -20,6 +20,7 @@ import { IServerVersions, UNSTABLE_MSC3882_CAPABILITY, Capabilities, + IClientWellKnown, } from "matrix-js-sdk/src/matrix"; import { _t } from "../../../../languageHandler"; @@ -30,6 +31,7 @@ interface IProps { onShowQr: () => void; versions?: IServerVersions; capabilities?: Capabilities; + wellKnown?: IClientWellKnown; } export default class LoginWithQRSection extends React.Component { @@ -43,7 +45,9 @@ export default class LoginWithQRSection extends React.Component { const capability = UNSTABLE_MSC3882_CAPABILITY.findIn(this.props.capabilities); const msc3882Supported = !!this.props.versions?.unstable_features?.["org.matrix.msc3882"] || !!capability?.enabled; - const msc3886Supported = !!this.props.versions?.unstable_features?.["org.matrix.msc3886"]; + const msc3886Supported = + !!this.props.versions?.unstable_features?.["org.matrix.msc3886"] || + this.props.wellKnown?.["io.element.rendezvous"]?.server; const offerShowQr = msc3882Supported && msc3886Supported; // don't show anything if no method is available diff --git a/src/components/views/settings/tabs/user/SessionManagerTab.tsx b/src/components/views/settings/tabs/user/SessionManagerTab.tsx index 391c01489a7..cc88cb27e83 100644 --- a/src/components/views/settings/tabs/user/SessionManagerTab.tsx +++ b/src/components/views/settings/tabs/user/SessionManagerTab.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { useCallback, useContext, useEffect, useRef, useState } from "react"; +import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; @@ -180,6 +180,7 @@ const SessionManagerTab: React.FC = () => { const currentUserMember = (userId && matrixClient?.getUser(userId)) || undefined; const clientVersions = useAsyncMemo(() => matrixClient.getVersions(), [matrixClient]); const capabilities = useAsyncMemo(async () => matrixClient?.getCapabilities(), [matrixClient]); + const wellKnown = useMemo(() => matrixClient?.getClientWellKnown(), [matrixClient]); const onDeviceExpandToggle = (deviceId: ExtendedDevice["device_id"]): void => { if (expandedDeviceIds.includes(deviceId)) { @@ -329,7 +330,12 @@ const SessionManagerTab: React.FC = () => { /> )} - + ); diff --git a/test/components/views/settings/devices/LoginWithQR-test.tsx b/test/components/views/settings/devices/LoginWithQR-test.tsx index af9ab74175e..188997745d2 100644 --- a/test/components/views/settings/devices/LoginWithQR-test.tsx +++ b/test/components/views/settings/devices/LoginWithQR-test.tsx @@ -51,6 +51,7 @@ function makeClient() { currentState: { on: jest.fn(), }, + getClientWellKnown: jest.fn().mockReturnValue({}), } as unknown as MatrixClient); } diff --git a/test/components/views/settings/devices/LoginWithQRSection-test.tsx b/test/components/views/settings/devices/LoginWithQRSection-test.tsx index 3f3957eeb20..0787345cd11 100644 --- a/test/components/views/settings/devices/LoginWithQRSection-test.tsx +++ b/test/components/views/settings/devices/LoginWithQRSection-test.tsx @@ -16,13 +16,13 @@ limitations under the License. import { render } from "@testing-library/react"; import { mocked } from "jest-mock"; -import { IServerVersions, MatrixClient, UNSTABLE_MSC3882_CAPABILITY } from "matrix-js-sdk/src/matrix"; +import { IClientWellKnown, IServerVersions, MatrixClient, UNSTABLE_MSC3882_CAPABILITY } from "matrix-js-sdk/src/matrix"; import React from "react"; import LoginWithQRSection from "../../../../../src/components/views/settings/devices/LoginWithQRSection"; import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg"; -function makeClient() { +function makeClient(wellKnown: IClientWellKnown) { return mocked({ getUser: jest.fn(), isGuest: jest.fn().mockReturnValue(false), @@ -37,6 +37,7 @@ function makeClient() { currentState: { on: jest.fn(), }, + getClientWellKnown: jest.fn().mockReturnValue(wellKnown), } as unknown as MatrixClient); } @@ -49,12 +50,13 @@ function makeVersions(unstableFeatures: Record): IServerVersion describe("", () => { beforeAll(() => { - jest.spyOn(MatrixClientPeg, "get").mockReturnValue(makeClient()); + jest.spyOn(MatrixClientPeg, "get").mockReturnValue(makeClient({})); }); const defaultProps = { onShowQr: () => {}, versions: makeVersions({}), + wellKnown: {}, }; const getComponent = (props = {}) => ; @@ -114,5 +116,22 @@ describe("", () => { ); expect(container).toMatchSnapshot(); }); + + it("MSC3882 r1 + .well-known", async () => { + const wellKnown = { + "io.element.rendezvous": { + server: "https://rz.local", + }, + }; + jest.spyOn(MatrixClientPeg, "get").mockReturnValue(makeClient(wellKnown)); + const { container } = render( + getComponent({ + versions: makeVersions({}), + capabilities: { [UNSTABLE_MSC3882_CAPABILITY.name]: { enabled: true } }, + wellKnown, + }), + ); + expect(container).toMatchSnapshot(); + }); }); }); diff --git a/test/components/views/settings/devices/__snapshots__/LoginWithQRSection-test.tsx.snap b/test/components/views/settings/devices/__snapshots__/LoginWithQRSection-test.tsx.snap index 90af812e592..5bb4cbb7a40 100644 --- a/test/components/views/settings/devices/__snapshots__/LoginWithQRSection-test.tsx.snap +++ b/test/components/views/settings/devices/__snapshots__/LoginWithQRSection-test.tsx.snap @@ -46,6 +46,44 @@ exports[` should render panel MSC3882 + MSC3886 1`] = ` `; +exports[` should render panel MSC3882 r1 + .well-known 1`] = ` +
+
+
+

+ Sign in with QR code +

+
+
+
+

+ You can use this device to sign in a new device with a QR code. You will need to scan the QR code shown on this device with your device that's signed out. +

+
+ Show QR code +
+
+
+
+
+`; + exports[` should render panel MSC3882 r1 + MSC3886 1`] = `