This commit is contained in:
Robin Townsend 2022-06-27 17:41:07 -04:00
commit d5e638c8f7
5 changed files with 121 additions and 30 deletions

View file

@ -39,6 +39,7 @@
"color-hash": "^2.0.1",
"events": "^3.3.0",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#ebcb26f1b3b9e2d709615fde03f9ce6ac77871f1",
"matrix-widget-api": "^0.1.0-beta.18",
"mermaid": "^8.13.8",
"normalize.css": "^8.0.1",
"pako": "^2.0.4",

View file

@ -26,9 +26,10 @@ import React, {
import { useHistory } from "react-router-dom";
import { MatrixClient, ClientEvent } from "matrix-js-sdk/src/client";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { logger } from "matrix-js-sdk/src/logger";
import { ErrorView } from "./FullScreenView";
import { initClient, defaultHomeserver } from "./matrix-utils";
import { initClient, initMatroskaClient, defaultHomeserver } from "./matrix-utils";
declare global {
interface Window {
@ -86,37 +87,52 @@ export const ClientProvider: FC = ({ children }) => {
});
useEffect(() => {
const restore = async (): Promise<
const init = async (): Promise<
Pick<ClientProviderState, "client" | "isPasswordlessUser">
> => {
try {
const session = loadSession();
const query = new URLSearchParams(window.location.search);
const widgetId = query.get("widgetId");
const parentUrl = query.get("parentUrl");
if (session) {
/* eslint-disable camelcase */
const { user_id, device_id, access_token, passwordlessUser } =
session;
if (widgetId && parentUrl) {
// We're inside a widget, so let's engage *Matroska mode*
logger.log("Using a Matroska client");
const client = await initClient({
baseUrl: defaultHomeserver,
accessToken: access_token,
userId: user_id,
deviceId: device_id,
});
/* eslint-enable camelcase */
return {
client: await initMatroskaClient(widgetId, parentUrl),
isPasswordlessUser: false,
};
} else {
// We're running as a standalone application
try {
const session = loadSession();
return { client, isPasswordlessUser: passwordlessUser };
if (session) {
/* eslint-disable camelcase */
const { user_id, device_id, access_token, passwordlessUser } =
session;
logger.log("Using a standalone client");
const client = await initClient({
baseUrl: defaultHomeserver,
accessToken: access_token,
userId: user_id,
deviceId: device_id,
});
/* eslint-enable camelcase */
return { client, isPasswordlessUser: passwordlessUser };
}
return { client: undefined, isPasswordlessUser: false };
} catch (err) {
clearSession();
throw err;
}
return { client: undefined, isPasswordlessUser: false };
} catch (err) {
console.error(err);
clearSession();
throw err;
}
};
restore()
init()
.then(({ client, isPasswordlessUser }) => {
setState({
client,
@ -126,7 +142,8 @@ export const ClientProvider: FC = ({ children }) => {
userName: client?.getUserIdLocalpart(),
});
})
.catch(() => {
.catch((err) => {
logger.error(err);
setState({
client: undefined,
loading: false,

View file

@ -5,15 +5,17 @@ import { MemoryStore } from "matrix-js-sdk/src/store/memory";
import { IndexedDBCryptoStore } from "matrix-js-sdk/src/crypto/store/indexeddb-crypto-store";
import { LocalStorageCryptoStore } from "matrix-js-sdk/src/crypto/store/localStorage-crypto-store";
import { MemoryCryptoStore } from "matrix-js-sdk/src/crypto/store/memory-crypto-store";
import { createClient, MatrixClient } from "matrix-js-sdk/src/matrix";
import { createClient, createRoomWidgetClient, MatrixClient } from "matrix-js-sdk/src/matrix";
import { ICreateClientOpts } from "matrix-js-sdk/src/matrix";
import { ClientEvent } from "matrix-js-sdk/src/client";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { Visibility, Preset } from "matrix-js-sdk/src/@types/partials";
import {
GroupCallIntent,
GroupCallType,
} from "matrix-js-sdk/src/webrtc/groupCall";
import { ISyncStateData, SyncState } from "matrix-js-sdk/src/sync";
import { WidgetApi } from "matrix-widget-api";
import IndexedDBWorker from "./IndexedDBWorker?worker";
@ -42,6 +44,63 @@ function waitForSync(client: MatrixClient) {
});
}
// The event types that the app needs to be able to send/receive in Matroska
// mode in order to function
const SEND_RECV_STATE = [
{ eventType: EventType.RoomMember },
{ eventType: EventType.GroupCallPrefix },
{ eventType: EventType.GroupCallMemberPrefix },
];
const SEND_RECV_TO_DEVICE = [
EventType.CallInvite,
EventType.CallCandidates,
EventType.CallAnswer,
EventType.CallHangup,
EventType.CallReject,
EventType.CallSelectAnswer,
EventType.CallNegotiate,
EventType.CallSDPStreamMetadataChanged,
EventType.CallSDPStreamMetadataChangedPrefix,
EventType.CallReplaces,
"org.matrix.call_duplicate_session",
];
export async function initMatroskaClient(
widgetId: string, parentUrl: string,
): Promise<MatrixClient> {
// In this mode, we use a special client which routes all requests through
// the host application via the widget API
// The rest of the data we need is encoded in the fragment so as to avoid
// leaking it to the server
const fragmentQueryStart = window.location.hash.indexOf("?");
const roomId = window.location.hash.substring(0, fragmentQueryStart);
const fragmentQuery = new URLSearchParams(window.location.hash.substring(fragmentQueryStart));
// Since all data should be coming from the host application, there's no
// need to persist anything, and therefore we can use the default stores
// We don't even need to set up crypto!
const client = createRoomWidgetClient(
new WidgetApi(widgetId, new URL(parentUrl).origin),
{
sendState: SEND_RECV_STATE,
receiveState: SEND_RECV_STATE,
sendToDevice: SEND_RECV_TO_DEVICE,
receiveToDevice: SEND_RECV_TO_DEVICE,
},
roomId,
{
baseUrl: "",
userId: fragmentQuery.get("userId"),
deviceId: fragmentQuery.get("deviceId"),
timelineSupport: true,
},
);
await client.startClient();
return client;
}
export async function initClient(
clientOptions: ICreateClientOpts
): Promise<MatrixClient> {
@ -83,7 +142,7 @@ export async function initClient(
...storeOpts,
...clientOptions,
useAuthorizationHeader: true,
// Use a relatively low timeout for API calls: this is a realtime application
// Use a relatively low timeout for API calls: this is a realtime app
// so we don't want API calls taking ages, we'd rather they just fail.
localTimeoutMs: 5000,
});

View file

@ -23,7 +23,8 @@ async function fetchGroupCall(
viaServers = undefined,
timeout = 5000
) {
const { roomId } = await client.joinRoom(roomIdOrAlias, { viaServers });
//const { roomId } = await client.joinRoom(roomIdOrAlias, { viaServers });
const roomId = roomIdOrAlias;
return new Promise((resolve, reject) => {
let timeoutId;

View file

@ -2868,6 +2868,11 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83"
integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==
"@types/events@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
"@types/glob@*", "@types/glob@^7.1.1", "@types/glob@^7.1.3":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
@ -8602,9 +8607,9 @@ matrix-events-sdk@^0.0.1-beta.7:
resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1-beta.7.tgz#5ffe45eba1f67cc8d7c2377736c728b322524934"
integrity sha512-9jl4wtWanUFSy2sr2lCjErN/oC8KTAtaeaozJtrgot1JiQcEI4Rda9OLgQ7nLKaqb4Z/QUx/fR3XpDzm5Jy1JA==
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#404f8e130e44a78b0159c55902df1b129b3816d1":
version "17.2.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/404f8e130e44a78b0159c55902df1b129b3816d1"
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#ebcb26f1b3b9e2d709615fde03f9ce6ac77871f1":
version "18.1.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ebcb26f1b3b9e2d709615fde03f9ce6ac77871f1"
dependencies:
"@babel/runtime" "^7.12.5"
another-json "^0.2.0"
@ -8618,6 +8623,14 @@ matrix-events-sdk@^0.0.1-beta.7:
request "^2.88.2"
unhomoglyph "^1.0.6"
matrix-widget-api@^0.1.0-beta.18:
version "0.1.0-beta.18"
resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-0.1.0-beta.18.tgz#4efd30edec3eeb4211285985464c062fcab59795"
integrity sha512-kCpcs6rrB94Mmr2/1gBJ+6auWyZ5UvOMOn5K2VFafz2/NDMzZg9OVWj9KFYnNAuwwBE5/tCztYEj6OQ+hgbwOQ==
dependencies:
"@types/events" "^3.0.0"
events "^3.2.0"
md5.js@^1.3.4:
version "1.3.5"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"