From 28158bfc232a18e490683791b86d223c507b1f56 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 24 Nov 2025 09:44:21 +0100 Subject: [PATCH 01/12] temp --- godot/README.md | 0 godot/main.ts | 76 ++++++++++++++++++++++++ index.html | 12 ++++ package.json | 3 + src/ClientContext.tsx | 2 +- src/state/CallViewModel/CallViewModel.ts | 3 + tsconfig.json | 7 ++- vite-godot.config.js | 32 ++++++++++ vite.config.ts | 42 ++++++++----- yarn.lock | 13 ++++ 10 files changed, 172 insertions(+), 18 deletions(-) create mode 100644 godot/README.md create mode 100644 godot/main.ts create mode 100644 vite-godot.config.js diff --git a/godot/README.md b/godot/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/godot/main.ts b/godot/main.ts new file mode 100644 index 000000000..8ba85b532 --- /dev/null +++ b/godot/main.ts @@ -0,0 +1,76 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ +import { of } from "rxjs"; + +import { loadClient } from "../src/ClientContext.tsx"; +import { createCallViewModel$ } from "../src/state/CallViewModel/CallViewModel.ts"; +import { MuteStates } from "../src/state/MuteStates.ts"; +import { ObservableScope } from "../src/state/ObservableScope.ts"; +import { getUrlParams } from "../src/UrlParams.ts"; +import { MediaDevices } from "../src/state/MediaDevices"; +import { constant } from "../src/state/Behavior.ts"; +import { E2eeType } from "../src/e2ee/e2eeType.ts"; + +console.log("test Godot EC export"); + +export async function start(): Promise { + const initResults = await loadClient(); + if (initResults === null) { + console.error("could not init client"); + return; + } + const { client } = initResults; + const scope = new ObservableScope(); + const { roomId } = getUrlParams(); + if (roomId === null) { + console.error("could not get roomId from url params"); + return; + } + const room = client.getRoom(roomId); + if (room === null) { + console.error("could not get room from client"); + return; + } + const mediaDevices = new MediaDevices(scope); + const muteStates = new MuteStates(scope, mediaDevices, constant(true)); + const callViewModel = createCallViewModel$( + scope, + client.matrixRTC.getRoomSession(room), + room, + mediaDevices, + muteStates, + { encryptionSystem: { kind: E2eeType.PER_PARTICIPANT } }, + of({}), + of({}), + constant({ supported: false, processor: undefined }), + ); + callViewModel.join(); + // callViewModel.audioParticipants$.pipe( + // switchMap((lkRooms) => { + // for (const item of lkRooms) { + // item.livekitRoom.registerTextStreamHandler; + // } + // }), + // ); +} +// Example default godot export + +// +// +// +// My Template +// +// +// +// +// +// +// +// diff --git a/index.html b/index.html index f17c73c0b..2043b2aab 100644 --- a/index.html +++ b/index.html @@ -40,6 +40,18 @@ + <% if (packageType !== "full") { %>
+ <% } %> + + + <% if (packageType === "godot") { %> + + + + <% } %> diff --git a/package.json b/package.json index 62ea9f4fb..31ae40d33 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "build:embedded": "yarn build:full --config vite-embedded.config.js", "build:embedded:production": "yarn build:embedded", "build:embedded:development": "yarn build:embedded --mode development", + "build:godot": "yarn build:full --config vite-godot.config.js", + "build:godot:development": "yarn build:godot --mode development", "serve": "vite preview", "prettier:check": "prettier -c .", "prettier:format": "prettier -w .", @@ -133,6 +135,7 @@ "vite": "^7.0.0", "vite-plugin-generate-file": "^0.3.0", "vite-plugin-html": "^3.2.2", + "vite-plugin-singlefile": "^2.3.0", "vite-plugin-svgr": "^4.0.0", "vitest": "^3.0.0", "vitest-axe": "^1.0.0-pre.3" diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx index 1488965ac..518aa38eb 100644 --- a/src/ClientContext.tsx +++ b/src/ClientContext.tsx @@ -358,7 +358,7 @@ export type InitResult = { passwordlessUser: boolean; }; -async function loadClient(): Promise { +export async function loadClient(): Promise { if (widget) { // We're inside a widget, so let's engage *matryoshka mode* logger.log("Using a matryoshka client"); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 506eca1b8..4d214714d 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -251,6 +251,8 @@ export interface CallViewModel { participantCount$: Behavior; /** Participants sorted by livekit room so they can be used in the audio rendering */ audioParticipants$: Behavior; + /** use the layout instead, this is just for the godot export. */ + userMedia$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ @@ -1495,6 +1497,7 @@ export function createCallViewModel$( spotlight$: spotlight$, pip$: pip$, layout$: layout$, + userMedia$, tileStoreGeneration$: tileStoreGeneration$, showSpotlightIndicators$: showSpotlightIndicators$, showSpeakingIndicators$: showSpeakingIndicators$, diff --git a/tsconfig.json b/tsconfig.json index e864ecfc9..7c13dfc76 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -50,6 +50,11 @@ "plugins": [{ "name": "typescript-eslint-language-service" }] }, - "include": ["./src/**/*.ts", "./src/**/*.tsx", "./playwright/**/*.ts"], + "include": [ + "./src/**/*.ts", + "./src/**/*.tsx", + "./playwright/**/*.ts", + "./godot/**/*.ts" + ], "exclude": ["**.test.ts"] } diff --git a/vite-godot.config.js b/vite-godot.config.js new file mode 100644 index 000000000..f17a8d3f3 --- /dev/null +++ b/vite-godot.config.js @@ -0,0 +1,32 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { defineConfig, mergeConfig } from "vite"; +import { viteSingleFile } from "vite-plugin-singlefile"; +import fullConfig from "./vite.config"; + +const base = "./"; + +// Config for embedded deployments (possibly hosted under a non-root path) +export default defineConfig((env) => + mergeConfig( + fullConfig({ ...env, packageType: "godot" }), + defineConfig({ + base, // Use relative URLs to allow the app to be hosted under any path + // publicDir: false, // Don't serve the public directory which only contains the favicon + build: { + manifest: true, + lib: { + entry: "./godot/main.ts", + name: "matrixrtc-ec-godot", + // the proper extensions will be added + fileName: "matrixrtc-ec-godot", + }, + }, + }), + ), +); diff --git a/vite.config.ts b/vite.config.ts index a0bb9de55..970cb5926 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,14 +7,17 @@ Please see LICENSE in the repository root for full details. import { loadEnv, + PluginOption, searchForWorkspaceRoot, type ConfigEnv, type UserConfig, } from "vite"; import svgrPlugin from "vite-plugin-svgr"; import { createHtmlPlugin } from "vite-plugin-html"; + import { codecovVitePlugin } from "@codecov/vite-plugin"; import { sentryVitePlugin } from "@sentry/vite-plugin"; + import react from "@vitejs/plugin-react"; import { realpathSync } from "fs"; import * as fs from "node:fs"; @@ -24,14 +27,14 @@ import * as fs from "node:fs"; export default ({ mode, packageType, -}: ConfigEnv & { packageType?: "full" | "embedded" }): UserConfig => { +}: ConfigEnv & { packageType?: "full" | "embedded" | "godot" }): UserConfig => { const env = loadEnv(mode, process.cwd()); // Environment variables with the VITE_ prefix are accessible at runtime. // So, we set this to allow for build/package specific behavior. // In future we might be able to do what is needed via code splitting at // build time. process.env.VITE_PACKAGE = packageType ?? "full"; - const plugins = [ + const plugins: PluginOption[] = [ react(), svgrPlugin({ svgrOptions: { @@ -41,16 +44,6 @@ export default ({ }, }), - createHtmlPlugin({ - entry: "src/main.tsx", - inject: { - data: { - brand: env.VITE_PRODUCT_NAME || "Element Call", - packageType: process.env.VITE_PACKAGE, - }, - }, - }), - codecovVitePlugin({ enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined, bundleName: "element-call", @@ -73,6 +66,18 @@ export default ({ ); } + plugins.push( + createHtmlPlugin({ + entry: packageType === "godot" ? "godot/main.ts" : "src/main.tsx", + inject: { + data: { + brand: env.VITE_PRODUCT_NAME || "Element Call", + packageType: process.env.VITE_PACKAGE, + }, + }, + }), + ); + // The crypto WASM module is imported dynamically. Since it's common // for developers to use a linked copy of matrix-js-sdk or Rust // crypto (which could reside anywhere on their file system), Vite @@ -120,10 +125,15 @@ export default ({ // Default naming fallback return "assets/[name]-[hash][extname]"; }, - manualChunks: { - // we should be able to remove this one https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands - "matrix-sdk-crypto-wasm": ["@matrix-org/matrix-sdk-crypto-wasm"], - }, + manualChunks: + packageType !== "godot" + ? { + // we should be able to remove this one https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands + "matrix-sdk-crypto-wasm": [ + "@matrix-org/matrix-sdk-crypto-wasm", + ], + } + : undefined, }, }, }, diff --git a/yarn.lock b/yarn.lock index 97ca19859..61af02ac6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7571,6 +7571,7 @@ __metadata: vite: "npm:^7.0.0" vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" + vite-plugin-singlefile: "npm:^2.3.0" vite-plugin-svgr: "npm:^4.0.0" vitest: "npm:^3.0.0" vitest-axe: "npm:^1.0.0-pre.3" @@ -13966,6 +13967,18 @@ __metadata: languageName: node linkType: hard +"vite-plugin-singlefile@npm:^2.3.0": + version: 2.3.0 + resolution: "vite-plugin-singlefile@npm:2.3.0" + dependencies: + micromatch: "npm:^4.0.8" + peerDependencies: + rollup: ^4.44.1 + vite: ^5.4.11 || ^6.0.0 || ^7.0.0 + checksum: 10c0/d6ebb545d749b228bbd8fd8746a954f09d000dd69d200a651358e74136947b932f7f869536e1698e0d81e2f0694357c8bec3a957101a7e77d0d3c40193eb4cf1 + languageName: node + linkType: hard + "vite-plugin-svgr@npm:^4.0.0": version: 4.3.0 resolution: "vite-plugin-svgr@npm:4.3.0" From 2d8ffc0ccda249aafa57a4c361714ff6fd4a79f6 Mon Sep 17 00:00:00 2001 From: Timo K Date: Sun, 30 Nov 2025 20:31:21 +0100 Subject: [PATCH 02/12] almost mvp --- godot/README.md | 14 + godot/favicon.ico | Bin 0 -> 2439 bytes godot/helper.ts | 51 ++ godot/index.html | 45 ++ godot/main.ts | 238 +++++-- package.json | 2 + src/room/InCallView.tsx | 2 +- src/state/CallViewModel/CallViewModel.ts | 27 +- src/widget.ts | 19 +- vite-godot.config.js | 3 +- yarn.lock | 845 ++++++++++++++++++++++- 11 files changed, 1145 insertions(+), 101 deletions(-) create mode 100644 godot/favicon.ico create mode 100644 godot/helper.ts create mode 100644 godot/index.html diff --git a/godot/README.md b/godot/README.md index e69de29bb..7f00df247 100644 --- a/godot/README.md +++ b/godot/README.md @@ -0,0 +1,14 @@ +## url parameters +widgetId = $matrix_widget_id +perParticipantE2EE = true +userId = $matrix_user_id +deviceId = $org.matrix.msc3819.matrix_device_id +baseUrl = $org.matrix.msc4039.matrix_base_url + +parentUrl = // will be inserted automatically + +http://localhost?widgetId=&perParticipantE2EE=true&userId=&deviceId=&baseUrl=&roomId= + +-> + +http://localhost:3000?widgetId=$matrix_widget_id&perParticipantE2EE=true&userId=$matrix_user_id&deviceId=$org.matrix.msc3819.matrix_device_id&baseUrl=$org.matrix.msc4039.matrix_base_url&roomId=$matrix_room_id diff --git a/godot/favicon.ico b/godot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e531e6f274fb3efb29316f441b7057f745758ee3 GIT binary patch literal 2439 zcmV;233&F2P)Z$GcPbOEG;=TH6tA!@bK^{BqcdBG?S8&>FMb?FE2SUFU3Q#V=xG9ka78TU#cFhb(k-UtL`c-rg}yO*KbGH9$WU z($gQMqzLQkBcGooii#Y(yDNHmDr#vv5D=G@mOK|3q{gO@000PrNklX?LPZ z5I|*V5jQ}Eh+9n5?29HbW|_SF|9|y@CI*$Is@oY-r0>_snIrdf7u8h-6bcfFL?V$$ zBoc{4B9TZW63LosXV9%o`c`j=)t^+lgH9>yU-k2-4l2{3X*echy7r0AnCTeiu>aqn zn)UDdF;vHsq3bYBiKeVG#~qFaa)}ihN7jd^a*U`o8gtBP_g62lQr9xfxD~Z4%yg#X zgRFmZMsy}7+|&x)(MOG}e|H89EQ8@ptzd5dFzes`j~Vm~U&J#WD;j7ip)ws)#SuEPxk)5_WD zx}gguS2ep9`)_QRt1#cemKV11E@yw@ZRtvm(s^-L*Q)yB$NzhdY&C>k-Kna2<0brs zrsQNNR%6TSKx+3NuGIT_(%P zL9_i@6guW?xKgiDQ_?SVE9>j#;Yg^A+5J-{WHnwCUd6D zGIAggv0A6wuGEBPMFbkLr6q7HjBur*7S>19qIE;$R;Ad_yRK#}-2b7G%C#=I!@Ga8 z>ngDe7Kuw~a;wkVfA(J^T&d6Slyn6nRADaho(h|{QLfZGSji!5D{BRCx}4#?`6tqq z`iB0W+>5LofU)?F(B5UVtJE&oE{x0^Qk8EP1_KR|q<6t~F|(EcWz4k;mjexv0J>m1 zxK!%PXFT`9TC6Ko<7g3)xgYW*S+$3gI9CgNe5X^W>2SzOa0TpwZPTVPgT#?Id=7s^ z1MGrr;m}APCg|!+U0cMvQZLadX#o2#YY!msuDm2yDn82!(56{?fKbBDf|R{klB?M} zmn_B2S_A}ad@nZ>T_L()o3ts6)F4yRvY+fqeSP=1f)g?*~-m{w? zHZwKHS(^ZW%HPX&nyV!z^T*d?-*46s9WfHO!ycyOu-T+fW^w*>S@ZpmO$ky)qVRwT zSzAqdh_RQ`>!$4k@>CLqctqxaceUapj6t&ctWBhI0G74Wq{jd_136i%NT&*x^}gMt z#{ekHw}1WvDh+6vRLIpeU>g#sJ3wWP4|CICRnSzgm_-aWsdjXfcz+DIIvfhC$^-Sd6#^65OWS+U6@ zW&)5zi3ZaNE7m;QKfZmOC$tU2t}suTktqJ5hq}wbro2xNV^=6wG|I|+GcKmzfIl}U7h3hphBd{THu?JtjEu1eK1G6()(F^0D&J2 z3GkB6i*p-2&qm^A$UCc?bOxH?T~Qf1;*0RD_{?GEbIeH+sK76Acx2h}u9_UP4rE>) z!ZUzdiA@6_qE#*5E4f{?5E4xJe&@L!tT}2KPoNd%GWYBjAeK+f@p z1-MdUhf5BqfredZCGX!rUj<)(2)Vivb7fLG6^4PP58*D@73XuSpOB31D}XPe4wW2U z-i2PrOsAS00c<0NUSuw|uIO&U0N9sNynVUSsr0|1=|Cn-zus;%=XsAx7?Z-_Oak3> zTi)rHE3tT`v}sjlBABG!675wNZ1!Fh4DLDjETokZpu1a16?9z$i>|r&HAvZ;8u?Qx;9Zc$Je6s}%~3#Lv(*AGrq_a_B0>mObYlXb8Fb z`A>j>NwVd=&N&Af*5vG?tW_mG%6q=x9%Q}T?7z1$}D4F)I!SMbZ*yD*LB2b=&@dqN*B+QseXEVOS>X$yY(H;iuNbPImb8SZUy zxfb#A6@VjWFG&PrIbT*Qs%PSRQ8z}pO4<`Rv)H}sXUudBy?53 { + logger.info("try making sticky MatrixRTCSdk"); + void widget.api + .setAlwaysOnScreen(true) + .then(() => { + logger.info("sticky MatrixRTCSdk"); + }) + .catch((error) => { + logger.error("failed to make sticky MatrixRTCSdk", error); + }); +}; +export const TEXT_LK_TOPIC = "matrixRTC"; +/** + * simple helper operator to combine the last emitted and the current emitted value of a rxjs observable + * + * I think there should be a builtin for this but i did not find it... + */ +export const currentAndPrev = scan< + LivekitRoomItem[], + { + prev: LivekitRoomItem[]; + current: LivekitRoomItem[]; + } +>( + ({ current: lastCurrentVal }, items) => ({ + prev: lastCurrentVal, + current: items, + }), + { + prev: [], + current: [], + }, +); diff --git a/godot/index.html b/godot/index.html new file mode 100644 index 000000000..ff654748d --- /dev/null +++ b/godot/index.html @@ -0,0 +1,45 @@ + + + + Godot MatrixRTC Widget + + + + + + + +
+ + + diff --git a/godot/main.ts b/godot/main.ts index 8ba85b532..98bb49722 100644 --- a/godot/main.ts +++ b/godot/main.ts @@ -4,42 +4,57 @@ Copyright 2025 New Vector Ltd. SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { of } from "rxjs"; -import { loadClient } from "../src/ClientContext.tsx"; -import { createCallViewModel$ } from "../src/state/CallViewModel/CallViewModel.ts"; -import { MuteStates } from "../src/state/MuteStates.ts"; -import { ObservableScope } from "../src/state/ObservableScope.ts"; -import { getUrlParams } from "../src/UrlParams.ts"; +// import { type InitResult } from "../src/ClientContext"; +import { map, type Observable, of, Subject, switchMap } from "rxjs"; +import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc"; +import { type TextStreamInfo } from "livekit-client/dist/src/room/types"; +import { + type Room as LivekitRoom, + type TextStreamReader, +} from "livekit-client"; + +import { type Behavior, constant } from "../src/state/Behavior"; +import { createCallViewModel$ } from "../src/state/CallViewModel/CallViewModel"; +import { ObservableScope } from "../src/state/ObservableScope"; +import { getUrlParams } from "../src/UrlParams"; +import { MuteStates } from "../src/state/MuteStates"; import { MediaDevices } from "../src/state/MediaDevices"; -import { constant } from "../src/state/Behavior.ts"; -import { E2eeType } from "../src/e2ee/e2eeType.ts"; - -console.log("test Godot EC export"); - -export async function start(): Promise { - const initResults = await loadClient(); - if (initResults === null) { - console.error("could not init client"); - return; - } - const { client } = initResults; +import { E2eeType } from "../src/e2ee/e2eeType"; +import { type LocalMemberConnectionState } from "../src/state/CallViewModel/localMember/LocalMembership"; +import { + currentAndPrev, + logger, + TEXT_LK_TOPIC, + tryMakeSticky, + widget, +} from "./helper"; +import { ElementWidgetActions } from "../src/widget"; + +interface MatrixRTCSdk { + join: () => LocalMemberConnectionState; + /** @throws on leave errors */ + leave: () => void; + data$: Observable<{ sender: string; data: string }>; + sendData?: (data: Record) => Promise; +} +export async function createMatrixRTCSdk(): Promise { + logger.info("Hello"); + const client = await widget.client; + logger.info("client created"); const scope = new ObservableScope(); const { roomId } = getUrlParams(); - if (roomId === null) { - console.error("could not get roomId from url params"); - return; - } + if (roomId === null) throw Error("could not get roomId from url params"); + const room = client.getRoom(roomId); - if (room === null) { - console.error("could not get room from client"); - return; - } + if (room === null) throw Error("could not get room from client"); + const mediaDevices = new MediaDevices(scope); const muteStates = new MuteStates(scope, mediaDevices, constant(true)); + const rtcSession = client.matrixRTC.getRoomSession(room); const callViewModel = createCallViewModel$( scope, - client.matrixRTC.getRoomSession(room), + rtcSession, room, mediaDevices, muteStates, @@ -48,29 +63,148 @@ export async function start(): Promise { of({}), constant({ supported: false, processor: undefined }), ); - callViewModel.join(); - // callViewModel.audioParticipants$.pipe( - // switchMap((lkRooms) => { - // for (const item of lkRooms) { - // item.livekitRoom.registerTextStreamHandler; - // } - // }), - // ); + logger.info("CallViewModelCreated"); + // create data listener + const data$ = new Subject<{ sender: string; data: string }>(); + + // const lkTextStreamHandlerFunction = async ( + // reader: TextStreamReader, + // participantInfo: { identity: string }, + // livekitRoom: LivekitRoom, + // ): Promise => { + // const info = reader.info; + // console.log( + // `Received text stream from ${participantInfo.identity}\n` + + // ` Topic: ${info.topic}\n` + + // ` Timestamp: ${info.timestamp}\n` + + // ` ID: ${info.id}\n` + + // ` Size: ${info.size}`, // Optional, only available if the stream was sent with `sendText` + // ); + + // const participants = callViewModel.livekitRoomItems$.value.find( + // (i) => i.livekitRoom === livekitRoom, + // )?.participants; + // if (participants && participants.includes(participantInfo.identity)) { + // const text = await reader.readAll(); + // console.log(`Received text: ${text}`); + // data$.next({ sender: participantInfo.identity, data: text }); + // } else { + // logger.warn( + // "Received text from unknown participant", + // participantInfo.identity, + // ); + // } + // }; + + // const livekitRoomItemsSub = callViewModel.livekitRoomItems$ + // .pipe(currentAndPrev) + // .subscribe({ + // next: ({ prev, current }) => { + // const prevRooms = prev.map((i) => i.livekitRoom); + // const currentRooms = current.map((i) => i.livekitRoom); + // const addedRooms = currentRooms.filter((r) => !prevRooms.includes(r)); + // const removedRooms = prevRooms.filter((r) => !currentRooms.includes(r)); + // addedRooms.forEach((r) => + // r.registerTextStreamHandler( + // TEXT_LK_TOPIC, + // (reader, participantInfo) => + // void lkTextStreamHandlerFunction(reader, participantInfo, r), + // ), + // ); + // removedRooms.forEach((r) => + // r.unregisterTextStreamHandler(TEXT_LK_TOPIC), + // ); + // }, + // complete: () => { + // logger.info("Livekit room items subscription completed"); + // for (const item of callViewModel.livekitRoomItems$.value) { + // logger.info("unregistering room item from room", item.url); + // item.livekitRoom.unregisterTextStreamHandler(TEXT_LK_TOPIC); + // } + // }, + // }); + + // create sendData function + // const sendFn: Behavior<(data: string) => Promise> = + // scope.behavior( + // callViewModel.localMatrixLivekitMember$.pipe( + // switchMap((m) => { + // if (!m) + // return of((data: string): never => { + // throw Error("local membership not yet ready."); + // }); + // return m.participant$.pipe( + // map((p) => { + // if (p === null) { + // return (data: string): never => { + // throw Error("local participant not yet ready to send data."); + // }; + // } else { + // return async (data: string): Promise => + // p.sendText(data, { topic: TEXT_LK_TOPIC }); + // } + // }), + // ); + // }), + // ), + // ); + + // const sendData = async (data: Record): Promise => { + // const dataString = JSON.stringify(data); + // try { + // const info = await sendFn.value(dataString); + // logger.info(`Sent text with stream ID: ${info.id}`); + // } catch (e) { + // console.error("failed sending: ", dataString, e); + // } + // }; + + // after hangup gets called + const leaveSubs = callViewModel.leave$.subscribe(() => { + const scheduleWidgetCloseOnLeave = async (): Promise => { + const leaveResolver = Promise.withResolvers(); + logger.info("waiting for RTC leave"); + rtcSession.on(MatrixRTCSessionEvent.JoinStateChanged, (isJoined) => { + logger.info("received RTC join update: ", isJoined); + if (!isJoined) leaveResolver.resolve(); + }); + await leaveResolver.promise; + logger.info("send Unstick"); + await widget.api + .setAlwaysOnScreen(false) + .catch((e) => + logger.error( + "Failed to set call widget `alwaysOnScreen` to false", + e, + ), + ); + logger.info("send Close"); + await widget.api.transport + .send(ElementWidgetActions.Close, {}) + .catch((e) => logger.error("Failed to send close action", e)); + }; + + // schedule close first and then leave (scope.end) + void scheduleWidgetCloseOnLeave(); + + // actual hangup (ending scope will send the leave event.. its kinda odd. since you might end up closing the widget too fast) + scope.end(); + }); + + logger.info("createMatrixRTCSdk done"); + + return { + join: (): LocalMemberConnectionState => { + // first lets try making the widget sticky + tryMakeSticky(); + return callViewModel.join(); + }, + leave: (): void => { + callViewModel.hangup(); + leaveSubs.unsubscribe(); + // livekitRoomItemsSub.unsubscribe(); + }, + data$, + // sendData, + }; } -// Example default godot export - -// -// -// -// My Template -// -// -// -// -// -// -// -// diff --git a/package.json b/package.json index 31ae40d33..c87d5b01c 100644 --- a/package.json +++ b/package.json @@ -113,6 +113,7 @@ "loglevel": "^1.9.1", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/sticky-events&commit=e7f5bec51b6f70501a025b79fe5021c933385b21", "matrix-widget-api": "^1.13.0", + "node-stdlib-browser": "^1.3.1", "normalize.css": "^8.0.1", "observable-hooks": "^4.2.3", "pako": "^2.0.4", @@ -135,6 +136,7 @@ "vite": "^7.0.0", "vite-plugin-generate-file": "^0.3.0", "vite-plugin-html": "^3.2.2", + "vite-plugin-node-stdlib-browser": "^0.2.1", "vite-plugin-singlefile": "^2.3.0", "vite-plugin-svgr": "^4.0.0", "vitest": "^3.0.0", diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index b17d3aaee..bed9afae0 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -251,7 +251,7 @@ export const InCallView: FC = ({ () => void toggleRaisedHand(), ); - const audioParticipants = useBehavior(vm.audioParticipants$); + const audioParticipants = useBehavior(vm.livekitRoomItems$); const participantCount = useBehavior(vm.participantCount$); const reconnecting = useBehavior(vm.reconnecting$); const windowMode = useBehavior(vm.windowMode$); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 4d214714d..253eb05ed 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -12,6 +12,7 @@ import { ExternalE2EEKeyProvider, type Room as LivekitRoom, type RoomOptions, + type LocalParticipant as LocalLivekitParticipant, } from "livekit-client"; import { type Room as MatrixRoom } from "matrix-js-sdk"; import { @@ -174,12 +175,19 @@ interface LayoutScanState { } type MediaItem = UserMedia | ScreenShare; -type AudioLivekitItem = { +export type LivekitRoomItem = { livekitRoom: LivekitRoom; participants: string[]; url: string; }; +export type LocalMatrixLivekitMember = Pick< + MatrixLivekitMember, + "userId" | "membership$" | "connection$" +> & { + participant$: Behavior; +}; + /** * The return of createCallViewModel$ * this interface represents the root source of data for the call view. @@ -197,8 +205,11 @@ export interface CallViewModel { callPickupState$: Behavior< "unknown" | "ringing" | "timeout" | "decline" | "success" | null >; + /** Observable that emits when the user should leave the call (hangup pressed, widget action, error). + * THIS DOES NOT LEAVE THE CALL YET. The only way to leave the call (send the hangup event) is by ending the scope. + */ leave$: Observable<"user" | AutoLeaveReason>; - /** Call to initiate hangup. Use in conbination with connectino state track the async hangup process. */ + /** Call to initiate hangup. Use in conbination with reconnectino state track the async hangup process. */ hangup: () => void; // joining @@ -250,9 +261,10 @@ export interface CallViewModel { */ participantCount$: Behavior; /** Participants sorted by livekit room so they can be used in the audio rendering */ - audioParticipants$: Behavior; + livekitRoomItems$: Behavior; /** use the layout instead, this is just for the godot export. */ userMedia$: Behavior; + localMatrixLivekitMember$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ @@ -503,14 +515,14 @@ export function createCallViewModel$( userId: userId, }; - const localMatrixLivekitMember$: Behavior = + const localMatrixLivekitMember$: Behavior = scope.behavior( localRtcMembership$.pipe( switchMap((membership) => { if (!membership) return of(null); return of( // casting is save here since we know that localRtcMembership$ is !== null since we reached this case. - localMatrixLivekitMemberUninitialized as MatrixLivekitMember, + localMatrixLivekitMemberUninitialized as LocalMatrixLivekitMember, ); }), ), @@ -621,7 +633,7 @@ export function createCallViewModel$( return a$; }), map((members) => - members.reduce((acc, curr) => { + members.reduce((acc, curr) => { if (!curr) return acc; const existing = acc.find((item) => item.url === curr.url); @@ -1477,7 +1489,7 @@ export function createCallViewModel$( ), participantCount$: participantCount$, - audioParticipants$: audioParticipants$, + livekitRoomItems$: audioParticipants$, handsRaised$: handsRaised$, reactions$: reactions$, @@ -1498,6 +1510,7 @@ export function createCallViewModel$( pip$: pip$, layout$: layout$, userMedia$, + localMatrixLivekitMember$, tileStoreGeneration$: tileStoreGeneration$, showSpotlightIndicators$: showSpotlightIndicators$, showSpeakingIndicators$: showSpeakingIndicators$, diff --git a/src/widget.ts b/src/widget.ts index 60163c7cd..7862df33c 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -64,6 +64,12 @@ export const widget = ((): WidgetHelpers | null => { try { const { widgetId, parentUrl } = getUrlParams(); + const { roomId, userId, deviceId, baseUrl, e2eEnabled, allowIceFallback } = + getUrlParams(); + if (!roomId) throw new Error("Room ID must be supplied"); + if (!userId) throw new Error("User ID must be supplied"); + if (!deviceId) throw new Error("Device ID must be supplied"); + if (!baseUrl) throw new Error("Base URL must be supplied"); if (widgetId && parentUrl) { const parentOrigin = new URL(parentUrl).origin; logger.info("Widget API is available"); @@ -92,19 +98,6 @@ export const widget = ((): WidgetHelpers | null => { // We need to do this now rather than later because it has capabilities to // request, and is responsible for starting the transport (should it be?) - const { - roomId, - userId, - deviceId, - baseUrl, - e2eEnabled, - allowIceFallback, - } = getUrlParams(); - if (!roomId) throw new Error("Room ID must be supplied"); - if (!userId) throw new Error("User ID must be supplied"); - if (!deviceId) throw new Error("Device ID must be supplied"); - if (!baseUrl) throw new Error("Base URL must be supplied"); - // These are all the event types the app uses const sendEvent = [ EventType.CallNotify, // Sent as a deprecated fallback diff --git a/vite-godot.config.js b/vite-godot.config.js index f17a8d3f3..5fdba09eb 100644 --- a/vite-godot.config.js +++ b/vite-godot.config.js @@ -6,8 +6,8 @@ Please see LICENSE in the repository root for full details. */ import { defineConfig, mergeConfig } from "vite"; -import { viteSingleFile } from "vite-plugin-singlefile"; import fullConfig from "./vite.config"; +import nodePolyfills from "vite-plugin-node-stdlib-browser"; const base = "./"; @@ -27,6 +27,7 @@ export default defineConfig((env) => fileName: "matrixrtc-ec-godot", }, }, + plugins: [nodePolyfills()], }), ), ); diff --git a/yarn.lock b/yarn.lock index 61af02ac6..5ec8f55b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2711,6 +2711,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" @@ -4479,6 +4486,22 @@ __metadata: languageName: node linkType: hard +"@rollup/plugin-inject@npm:^5.0.3": + version: 5.0.5 + resolution: "@rollup/plugin-inject@npm:5.0.5" + dependencies: + "@rollup/pluginutils": "npm:^5.0.1" + estree-walker: "npm:^2.0.2" + magic-string: "npm:^0.30.3" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/22d10cf44fa56a6683d5ac4df24a9003379b3dcaae9897f5c30c844afc2ebca83cfaa5557f13a1399b1c8a0d312c3217bcacd508b7ebc4b2cbee401bd1ec8be2 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^4.2.0": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" @@ -4489,6 +4512,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.0.1": + version: 5.3.0 + resolution: "@rollup/pluginutils@npm:5.3.0" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/001834bf62d7cf5bac424d2617c113f7f7d3b2bf3c1778cbcccb72cdc957b68989f8e7747c782c2b911f1dde8257f56f8ac1e779e29e74e638e3f1e2cac2bcd0 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^5.1.3": version: 5.1.3 resolution: "@rollup/pluginutils@npm:5.1.3" @@ -6128,6 +6167,30 @@ __metadata: languageName: node linkType: hard +"asn1.js@npm:^4.10.1": + version: 4.10.1 + resolution: "asn1.js@npm:4.10.1" + dependencies: + bn.js: "npm:^4.0.0" + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + checksum: 10c0/afa7f3ab9e31566c80175a75b182e5dba50589dcc738aa485be42bdd787e2a07246a4b034d481861123cbe646a7656f318f4f1cad2e9e5e808a210d5d6feaa88 + languageName: node + linkType: hard + +"assert@npm:^2.0.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: "npm:^1.0.2" + is-nan: "npm:^1.3.2" + object-is: "npm:^1.1.5" + object.assign: "npm:^4.1.4" + util: "npm:^0.12.5" + checksum: 10c0/7271a5da883c256a1fa690677bf1dd9d6aa882139f2bed1cd15da4f9e7459683e1da8e32a203d6cc6767e5e0f730c77a9532a87b896b4b0af0dd535f668775f0 + languageName: node + linkType: hard + "assertion-error@npm:^2.0.1": version: 2.0.1 resolution: "assertion-error@npm:2.0.1" @@ -6318,6 +6381,20 @@ __metadata: languageName: node linkType: hard +"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9": + version: 4.12.2 + resolution: "bn.js@npm:4.12.2" + checksum: 10c0/09a249faa416a9a1ce68b5f5ec8bbca87fe54e5dd4ef8b1cc8a4969147b80035592bddcb1e9cc814c3ba79e573503d5c5178664b722b509fb36d93620dba9b57 + languageName: node + linkType: hard + +"bn.js@npm:^5.2.1, bn.js@npm:^5.2.2": + version: 5.2.2 + resolution: "bn.js@npm:5.2.2" + checksum: 10c0/cb97827d476aab1a0194df33cd84624952480d92da46e6b4a19c32964aa01553a4a613502396712704da2ec8f831cf98d02e74ca03398404bd78a037ba93f2ab + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -6393,6 +6470,96 @@ __metadata: languageName: node linkType: hard +"brorand@npm:^1.0.1, brorand@npm:^1.1.0": + version: 1.1.0 + resolution: "brorand@npm:1.1.0" + checksum: 10c0/6f366d7c4990f82c366e3878492ba9a372a73163c09871e80d82fb4ae0d23f9f8924cb8a662330308206e6b3b76ba1d528b4601c9ef73c2166b440b2ea3b7571 + languageName: node + linkType: hard + +"browser-resolve@npm:^2.0.0": + version: 2.0.0 + resolution: "browser-resolve@npm:2.0.0" + dependencies: + resolve: "npm:^1.17.0" + checksum: 10c0/06c43adf3cb1939825ab9a4ac355b23272820ee421a20d04f62e0dabd9ea305e497b97f3ac027f87d53c366483aafe8673bbe1aaa5e41cd69eeafa65ac5fda6e + languageName: node + linkType: hard + +"browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": + version: 1.2.0 + resolution: "browserify-aes@npm:1.2.0" + dependencies: + buffer-xor: "npm:^1.0.3" + cipher-base: "npm:^1.0.0" + create-hash: "npm:^1.1.0" + evp_bytestokey: "npm:^1.0.3" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/967f2ae60d610b7b252a4cbb55a7a3331c78293c94b4dd9c264d384ca93354c089b3af9c0dd023534efdc74ffbc82510f7ad4399cf82bc37bc07052eea485f18 + languageName: node + linkType: hard + +"browserify-cipher@npm:^1.0.1": + version: 1.0.1 + resolution: "browserify-cipher@npm:1.0.1" + dependencies: + browserify-aes: "npm:^1.0.4" + browserify-des: "npm:^1.0.0" + evp_bytestokey: "npm:^1.0.0" + checksum: 10c0/aa256dcb42bc53a67168bbc94ab85d243b0a3b56109dee3b51230b7d010d9b78985ffc1fb36e145c6e4db151f888076c1cfc207baf1525d3e375cbe8187fe27d + languageName: node + linkType: hard + +"browserify-des@npm:^1.0.0": + version: 1.0.2 + resolution: "browserify-des@npm:1.0.2" + dependencies: + cipher-base: "npm:^1.0.1" + des.js: "npm:^1.0.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/943eb5d4045eff80a6cde5be4e5fbb1f2d5002126b5a4789c3c1aae3cdddb1eb92b00fb92277f512288e5c6af330730b1dbabcf7ce0923e749e151fcee5a074d + languageName: node + linkType: hard + +"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.1": + version: 4.1.1 + resolution: "browserify-rsa@npm:4.1.1" + dependencies: + bn.js: "npm:^5.2.1" + randombytes: "npm:^2.1.0" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/b650ee1192e3d7f3d779edc06dd96ed8720362e72ac310c367b9d7fe35f7e8dbb983c1829142b2b3215458be8bf17c38adc7224920843024ed8cf39e19c513c0 + languageName: node + linkType: hard + +"browserify-sign@npm:^4.2.3": + version: 4.2.5 + resolution: "browserify-sign@npm:4.2.5" + dependencies: + bn.js: "npm:^5.2.2" + browserify-rsa: "npm:^4.1.1" + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + elliptic: "npm:^6.6.1" + inherits: "npm:^2.0.4" + parse-asn1: "npm:^5.1.9" + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6192f9696934bbba58932d098face34c2ab9cac09feed826618b86b8c00a897dab7324cd9aa7d6cb1597064f197264ad72fa5418d4d52bf3c8f9b9e0e124655e + languageName: node + linkType: hard + +"browserify-zlib@npm:^0.2.0": + version: 0.2.0 + resolution: "browserify-zlib@npm:0.2.0" + dependencies: + pako: "npm:~1.0.5" + checksum: 10c0/9ab10b6dc732c6c5ec8ebcbe5cb7fe1467f97402c9b2140113f47b5f187b9438f93a8e065d8baf8b929323c18324fbf1105af479ee86d9d36cab7d7ef3424ad9 + languageName: node + linkType: hard + "browserslist@npm:^4.24.0, browserslist@npm:^4.24.3, browserslist@npm:^4.24.4": version: 4.24.4 resolution: "browserslist@npm:4.24.4" @@ -6437,6 +6604,23 @@ __metadata: languageName: node linkType: hard +"buffer-xor@npm:^1.0.3": + version: 1.0.3 + resolution: "buffer-xor@npm:1.0.3" + checksum: 10c0/fd269d0e0bf71ecac3146187cfc79edc9dbb054e2ee69b4d97dfb857c6d997c33de391696d04bdd669272751fa48e7872a22f3a6c7b07d6c0bc31dbe02a4075c + languageName: node + linkType: hard + +"buffer@npm:^5.7.1": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.1.13" + checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e + languageName: node + linkType: hard + "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -6454,6 +6638,13 @@ __metadata: languageName: node linkType: hard +"builtin-status-codes@npm:^3.0.0": + version: 3.0.0 + resolution: "builtin-status-codes@npm:3.0.0" + checksum: 10c0/c37bbba11a34c4431e56bd681b175512e99147defbe2358318d8152b3a01df7bf25e0305873947e5b350073d5ef41a364a22b37e48f1fb6d2fe6d5286a0f348c + languageName: node + linkType: hard + "bytesish@npm:^0.4.1": version: 0.4.4 resolution: "bytesish@npm:0.4.4" @@ -6508,7 +6699,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -6722,6 +6913,17 @@ __metadata: languageName: node linkType: hard +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": + version: 1.0.7 + resolution: "cipher-base@npm:1.0.7" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.2" + checksum: 10c0/53c5046a9d9b60c586479b8f13fde263c3f905e13f11e8e04c7a311ce399c91d9c3ec96642332e0de077d356e1014ee12bba96f74fbaad0de750f49122258836 + languageName: node + linkType: hard + "classnames@npm:^2.3.1, classnames@npm:^2.5.1": version: 2.5.1 resolution: "classnames@npm:2.5.1" @@ -6885,6 +7087,20 @@ __metadata: languageName: node linkType: hard +"console-browserify@npm:^1.1.0": + version: 1.2.0 + resolution: "console-browserify@npm:1.2.0" + checksum: 10c0/89b99a53b7d6cee54e1e64fa6b1f7ac24b844b4019c5d39db298637e55c1f4ffa5c165457ad984864de1379df2c8e1886cbbdac85d9dbb6876a9f26c3106f226 + languageName: node + linkType: hard + +"constants-browserify@npm:^1.0.0": + version: 1.0.0 + resolution: "constants-browserify@npm:1.0.0" + checksum: 10c0/ab49b1d59a433ed77c964d90d19e08b2f77213fb823da4729c0baead55e3c597f8f97ebccfdfc47bd896d43854a117d114c849a6f659d9986420e97da0f83ac5 + languageName: node + linkType: hard + "content-type@npm:^1.0.4": version: 1.0.5 resolution: "content-type@npm:1.0.5" @@ -6957,6 +7173,50 @@ __metadata: languageName: node linkType: hard +"create-ecdh@npm:^4.0.4": + version: 4.0.4 + resolution: "create-ecdh@npm:4.0.4" + dependencies: + bn.js: "npm:^4.1.0" + elliptic: "npm:^6.5.3" + checksum: 10c0/77b11a51360fec9c3bce7a76288fc0deba4b9c838d5fb354b3e40c59194d23d66efe6355fd4b81df7580da0661e1334a235a2a5c040b7569ba97db428d466e7f + languageName: node + linkType: hard + +"create-hash@npm:^1.1.0, create-hash@npm:^1.2.0": + version: 1.2.0 + resolution: "create-hash@npm:1.2.0" + dependencies: + cipher-base: "npm:^1.0.1" + inherits: "npm:^2.0.1" + md5.js: "npm:^1.3.4" + ripemd160: "npm:^2.0.1" + sha.js: "npm:^2.4.0" + checksum: 10c0/d402e60e65e70e5083cb57af96d89567954d0669e90550d7cec58b56d49c4b193d35c43cec8338bc72358198b8cbf2f0cac14775b651e99238e1cf411490f915 + languageName: node + linkType: hard + +"create-hmac@npm:^1.1.7": + version: 1.1.7 + resolution: "create-hmac@npm:1.1.7" + dependencies: + cipher-base: "npm:^1.0.3" + create-hash: "npm:^1.1.0" + inherits: "npm:^2.0.1" + ripemd160: "npm:^2.0.0" + safe-buffer: "npm:^5.0.1" + sha.js: "npm:^2.4.8" + checksum: 10c0/24332bab51011652a9a0a6d160eed1e8caa091b802335324ae056b0dcb5acbc9fcf173cf10d128eba8548c3ce98dfa4eadaa01bd02f44a34414baee26b651835 + languageName: node + linkType: hard + +"create-require@npm:^1.1.1": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.2": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -6979,6 +7239,26 @@ __metadata: languageName: node linkType: hard +"crypto-browserify@npm:^3.12.1": + version: 3.12.1 + resolution: "crypto-browserify@npm:3.12.1" + dependencies: + browserify-cipher: "npm:^1.0.1" + browserify-sign: "npm:^4.2.3" + create-ecdh: "npm:^4.0.4" + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + diffie-hellman: "npm:^5.0.3" + hash-base: "npm:~3.0.4" + inherits: "npm:^2.0.4" + pbkdf2: "npm:^3.1.2" + public-encrypt: "npm:^4.0.3" + randombytes: "npm:^2.1.0" + randomfill: "npm:^1.0.4" + checksum: 10c0/184a2def7b16628e79841243232ab5497f18d8e158ac21b7ce90ab172427d0a892a561280adc08f9d4d517bce8db2a5b335dc21abb970f787f8e874bd7b9db7d + languageName: node + linkType: hard + "css-blank-pseudo@npm:^7.0.1": version: 7.0.1 resolution: "css-blank-pseudo@npm:7.0.1" @@ -7267,6 +7547,16 @@ __metadata: languageName: node linkType: hard +"des.js@npm:^1.0.0": + version: 1.1.0 + resolution: "des.js@npm:1.1.0" + dependencies: + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + checksum: 10c0/671354943ad67493e49eb4c555480ab153edd7cee3a51c658082fcde539d2690ed2a4a0b5d1f401f9cde822edf3939a6afb2585f32c091f2d3a1b1665cd45236 + languageName: node + linkType: hard + "detect-libc@npm:^1.0.3": version: 1.0.3 resolution: "detect-libc@npm:1.0.3" @@ -7283,6 +7573,17 @@ __metadata: languageName: node linkType: hard +"diffie-hellman@npm:^5.0.3": + version: 5.0.3 + resolution: "diffie-hellman@npm:5.0.3" + dependencies: + bn.js: "npm:^4.1.0" + miller-rabin: "npm:^4.0.0" + randombytes: "npm:^2.0.0" + checksum: 10c0/ce53ccafa9ca544b7fc29b08a626e23a9b6562efc2a98559a0c97b4718937cebaa9b5d7d0a05032cc9c1435e9b3c1532b9e9bf2e0ede868525922807ad6e1ecf + languageName: node + linkType: hard + "dijkstrajs@npm:^1.0.1": version: 1.0.3 resolution: "dijkstrajs@npm:1.0.3" @@ -7353,6 +7654,13 @@ __metadata: languageName: node linkType: hard +"domain-browser@npm:4.22.0": + version: 4.22.0 + resolution: "domain-browser@npm:4.22.0" + checksum: 10c0/2ef7eda6d2161038fda0c9aa4c9e18cc7a0baa89ea6be975d449527c2eefd4b608425db88508e2859acc472f46f402079274b24bd75e3fb506f28c5dba203129 + languageName: node + linkType: hard + "domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0, domelementtype@npm:^2.3.0": version: 2.3.0 resolution: "domelementtype@npm:2.3.0" @@ -7549,6 +7857,7 @@ __metadata: loglevel: "npm:^1.9.1" matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/sticky-events&commit=e7f5bec51b6f70501a025b79fe5021c933385b21" matrix-widget-api: "npm:^1.13.0" + node-stdlib-browser: "npm:^1.3.1" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" pako: "npm:^2.0.4" @@ -7571,6 +7880,7 @@ __metadata: vite: "npm:^7.0.0" vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" + vite-plugin-node-stdlib-browser: "npm:^0.2.1" vite-plugin-singlefile: "npm:^2.3.0" vite-plugin-svgr: "npm:^4.0.0" vitest: "npm:^3.0.0" @@ -7578,6 +7888,21 @@ __metadata: languageName: unknown linkType: soft +"elliptic@npm:^6.5.3, elliptic@npm:^6.6.1": + version: 6.6.1 + resolution: "elliptic@npm:6.6.1" + dependencies: + bn.js: "npm:^4.11.9" + brorand: "npm:^1.1.0" + hash.js: "npm:^1.0.0" + hmac-drbg: "npm:^1.0.1" + inherits: "npm:^2.0.4" + minimalistic-assert: "npm:^1.0.1" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -8389,13 +8714,24 @@ __metadata: languageName: node linkType: hard -"events@npm:^3.2.0, events@npm:^3.3.0": +"events@npm:^3.0.0, events@npm:^3.2.0, events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 languageName: node linkType: hard +"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": + version: 1.0.3 + resolution: "evp_bytestokey@npm:1.0.3" + dependencies: + md5.js: "npm:^1.3.4" + node-gyp: "npm:latest" + safe-buffer: "npm:^5.1.1" + checksum: 10c0/77fbe2d94a902a80e9b8f5a73dcd695d9c14899c5e82967a61b1fc6cbbb28c46552d9b127cff47c45fcf684748bdbcfa0a50410349109de87ceb4b199ef6ee99 + languageName: node + linkType: hard + "expect-type@npm:^1.2.1": version: 1.2.1 resolution: "expect-type@npm:1.2.1" @@ -8791,6 +9127,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10c0/8a9f59df0f01cfefafdb3b451b80555e5cf6d76487095db91ac461a0e682e4ff7a9dbce15f4ecec191e53586d59eece01949e05a4b4492879600bbbe8e28d6b8 + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9093,6 +9436,38 @@ __metadata: languageName: node linkType: hard +"hash-base@npm:^3.0.0, hash-base@npm:^3.1.2": + version: 3.1.2 + resolution: "hash-base@npm:3.1.2" + dependencies: + inherits: "npm:^2.0.4" + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.1" + checksum: 10c0/f3b7fae1853b31340048dd659f40f5260ca6f3ff53b932f807f4ab701ee09039f6e9dbe1841723ff61e20f3f69d6387a352e4ccc5f997dedb0d375c7d88bc15e + languageName: node + linkType: hard + +"hash-base@npm:~3.0.4": + version: 3.0.5 + resolution: "hash-base@npm:3.0.5" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6dc185b79bad9b6d525cd132a588e4215380fdc36fec6f7a8a58c5db8e3b642557d02ad9c367f5e476c7c3ad3ccffa3607f308b124e1ed80e3b80a1b254db61e + languageName: node + linkType: hard + +"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": + version: 1.1.7 + resolution: "hash.js@npm:1.1.7" + dependencies: + inherits: "npm:^2.0.3" + minimalistic-assert: "npm:^1.0.1" + checksum: 10c0/41ada59494eac5332cfc1ce6b7ebdd7b88a3864a6d6b08a3ea8ef261332ed60f37f10877e0c825aaa4bddebf164fbffa618286aeeec5296675e2671cbfa746c4 + languageName: node + linkType: hard + "hasown@npm:^2.0.0, hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" @@ -9130,6 +9505,17 @@ __metadata: languageName: node linkType: hard +"hmac-drbg@npm:^1.0.1": + version: 1.0.1 + resolution: "hmac-drbg@npm:1.0.1" + dependencies: + hash.js: "npm:^1.0.3" + minimalistic-assert: "npm:^1.0.0" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/f3d9ba31b40257a573f162176ac5930109816036c59a09f901eb2ffd7e5e705c6832bedfff507957125f2086a0ab8f853c0df225642a88bf1fcaea945f20600d + languageName: node + linkType: hard + "hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" @@ -9217,6 +9603,13 @@ __metadata: languageName: node linkType: hard +"https-browserify@npm:^1.0.0": + version: 1.0.0 + resolution: "https-browserify@npm:1.0.0" + checksum: 10c0/e17b6943bc24ea9b9a7da5714645d808670af75a425f29baffc3284962626efdc1eb3aa9bbffaa6e64028a6ad98af5b09fabcb454a8f918fb686abfdc9e9b8ae + languageName: node + linkType: hard + "https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" @@ -9296,7 +9689,7 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.2.1": +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb @@ -9358,7 +9751,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -9386,6 +9779,16 @@ __metadata: languageName: node linkType: hard +"is-arguments@npm:^1.0.4": + version: 1.2.0 + resolution: "is-arguments@npm:1.2.0" + dependencies: + call-bound: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/6377344b31e9fcb707c6751ee89b11f132f32338e6a782ec2eac9393b0cbd32235dad93052998cda778ee058754860738341d8114910d50ada5615912bb929fc + languageName: node + linkType: hard + "is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": version: 3.0.5 resolution: "is-array-buffer@npm:3.0.5" @@ -9525,6 +9928,19 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.7": + version: 1.1.2 + resolution: "is-generator-function@npm:1.1.2" + dependencies: + call-bound: "npm:^1.0.4" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/83da102e89c3e3b71d67b51d47c9f9bc862bceb58f87201727e27f7fa19d1d90b0ab223644ecaee6fc6e3d2d622bb25c966fbdaf87c59158b01ce7c0fe2fa372 + languageName: node + linkType: hard + "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -9541,6 +9957,16 @@ __metadata: languageName: node linkType: hard +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: "npm:^1.0.0" + define-properties: "npm:^1.1.3" + checksum: 10c0/8bfb286f85763f9c2e28ea32e9127702fe980ffd15fa5d63ade3be7786559e6e21355d3625dd364c769c033c5aedf0a2ed3d4025d336abf1b9241e3d9eddc5b0 + languageName: node + linkType: hard + "is-negated-glob@npm:^1.0.0": version: 1.0.0 resolution: "is-negated-glob@npm:1.0.0" @@ -9663,7 +10089,7 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15": +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15, is-typed-array@npm:^1.1.3": version: 1.1.15 resolution: "is-typed-array@npm:1.1.15" dependencies: @@ -9742,6 +10168,13 @@ __metadata: languageName: node linkType: hard +"isomorphic-timers-promises@npm:^1.0.1": + version: 1.0.1 + resolution: "isomorphic-timers-promises@npm:1.0.1" + checksum: 10c0/3b4761d0012ebe6b6382246079fc667f3513f36fe4042638f2bfb7db1557e4f1acd33a9c9907706c04270890ec6434120f132f3f300161a42a7dd8628926c8a4 + languageName: node + linkType: hard + "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" @@ -10290,6 +10723,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.3": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + languageName: node + linkType: hard + "magicast@npm:^0.3.5": version: 0.3.5 resolution: "magicast@npm:0.3.5" @@ -10385,6 +10827,17 @@ __metadata: languageName: node linkType: hard +"md5.js@npm:^1.3.4": + version: 1.3.5 + resolution: "md5.js@npm:1.3.5" + dependencies: + hash-base: "npm:^3.0.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/b7bd75077f419c8e013fc4d4dada48be71882e37d69a44af65a2f2804b91e253441eb43a0614423a1c91bb830b8140b0dc906bc797245e2e275759584f4efcc5 + languageName: node + linkType: hard + "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -10402,6 +10855,18 @@ __metadata: languageName: node linkType: hard +"miller-rabin@npm:^4.0.0": + version: 4.0.1 + resolution: "miller-rabin@npm:4.0.1" + dependencies: + bn.js: "npm:^4.0.0" + brorand: "npm:^1.0.1" + bin: + miller-rabin: bin/miller-rabin + checksum: 10c0/26b2b96f6e49dbcff7faebb78708ed2f5f9ae27ac8cbbf1d7c08f83cf39bed3d418c0c11034dce997da70d135cc0ff6f3a4c15dc452f8e114c11986388a64346 + languageName: node + linkType: hard + "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -10425,6 +10890,20 @@ __metadata: languageName: node linkType: hard +"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-assert@npm:1.0.1" + checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd + languageName: node + linkType: hard + +"minimalistic-crypto-utils@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-crypto-utils@npm:1.0.1" + checksum: 10c0/790ecec8c5c73973a4fbf2c663d911033e8494d5fb0960a4500634766ab05d6107d20af896ca2132e7031741f19888154d44b2408ada0852446705441383e9f8 + languageName: node + linkType: hard + "minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -10675,6 +11154,41 @@ __metadata: languageName: node linkType: hard +"node-stdlib-browser@npm:^1.3.1": + version: 1.3.1 + resolution: "node-stdlib-browser@npm:1.3.1" + dependencies: + assert: "npm:^2.0.0" + browser-resolve: "npm:^2.0.0" + browserify-zlib: "npm:^0.2.0" + buffer: "npm:^5.7.1" + console-browserify: "npm:^1.1.0" + constants-browserify: "npm:^1.0.0" + create-require: "npm:^1.1.1" + crypto-browserify: "npm:^3.12.1" + domain-browser: "npm:4.22.0" + events: "npm:^3.0.0" + https-browserify: "npm:^1.0.0" + isomorphic-timers-promises: "npm:^1.0.1" + os-browserify: "npm:^0.3.0" + path-browserify: "npm:^1.0.1" + pkg-dir: "npm:^5.0.0" + process: "npm:^0.11.10" + punycode: "npm:^1.4.1" + querystring-es3: "npm:^0.2.1" + readable-stream: "npm:^3.6.0" + stream-browserify: "npm:^3.0.0" + stream-http: "npm:^3.2.0" + string_decoder: "npm:^1.0.0" + timers-browserify: "npm:^2.0.4" + tty-browserify: "npm:0.0.1" + url: "npm:^0.11.4" + util: "npm:^0.12.4" + vm-browserify: "npm:^1.0.1" + checksum: 10c0/5b0cb5d4499b1b1c73f54db3e9e69b2a3a8aebe2ead2e356b0a03c1dfca6b5c5d2f6516e24301e76dc7b68999b9d0ae3da6c3f1dec421eed80ad6cb9eec0f356 + languageName: node + linkType: hard + "nopt@npm:^8.0.0": version: 8.1.0 resolution: "nopt@npm:8.1.0" @@ -10765,6 +11279,16 @@ __metadata: languageName: node linkType: hard +"object-is@npm:^1.1.5": + version: 1.1.6 + resolution: "object-is@npm:1.1.6" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + checksum: 10c0/506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 + languageName: node + linkType: hard + "object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" @@ -10876,6 +11400,13 @@ __metadata: languageName: node linkType: hard +"os-browserify@npm:^0.3.0": + version: 0.3.0 + resolution: "os-browserify@npm:0.3.0" + checksum: 10c0/6ff32cb1efe2bc6930ad0fd4c50e30c38010aee909eba8d65be60af55efd6cbb48f0287e3649b4e3f3a63dce5a667b23c187c4293a75e557f0d5489d735bcf52 + languageName: node + linkType: hard + "own-keys@npm:^1.0.1": version: 1.0.1 resolution: "own-keys@npm:1.0.1" @@ -11008,6 +11539,13 @@ __metadata: languageName: node linkType: hard +"pako@npm:~1.0.5": + version: 1.0.11 + resolution: "pako@npm:1.0.11" + checksum: 10c0/86dd99d8b34c3930345b8bbeb5e1cd8a05f608eeb40967b293f72fe469d0e9c88b783a8777e4cc7dc7c91ce54c5e93d88ff4b4f060e6ff18408fd21030d9ffbe + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -11027,6 +11565,19 @@ __metadata: languageName: node linkType: hard +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.9": + version: 5.1.9 + resolution: "parse-asn1@npm:5.1.9" + dependencies: + asn1.js: "npm:^4.10.1" + browserify-aes: "npm:^1.2.0" + evp_bytestokey: "npm:^1.0.3" + pbkdf2: "npm:^3.1.5" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6dfe27c121be3d63ebbf95f03d2ae0a07dd716d44b70b0bd3458790a822a80de05361c62147271fd7b845dcc2d37755d9c9c393064a3438fe633779df0bc07e7 + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -11077,6 +11628,13 @@ __metadata: languageName: node linkType: hard +"path-browserify@npm:^1.0.1": + version: 1.0.1 + resolution: "path-browserify@npm:1.0.1" + checksum: 10c0/8b8c3fd5c66bd340272180590ae4ff139769e9ab79522e2eb82e3d571a89b8117c04147f65ad066dccfb42fcad902e5b7d794b3d35e0fd840491a8ddbedf8c66 + languageName: node + linkType: hard + "path-exists@npm:^4.0.0": version: 4.0.0 resolution: "path-exists@npm:4.0.0" @@ -11150,6 +11708,20 @@ __metadata: languageName: node linkType: hard +"pbkdf2@npm:^3.1.2, pbkdf2@npm:^3.1.5": + version: 3.1.5 + resolution: "pbkdf2@npm:3.1.5" + dependencies: + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + ripemd160: "npm:^2.0.3" + safe-buffer: "npm:^5.2.1" + sha.js: "npm:^2.4.12" + to-buffer: "npm:^1.2.1" + checksum: 10c0/ea42e8695e49417eefabb19a08ab19a602cc6cc72d2df3f109c39309600230dee3083a6f678d5d42fe035d6ae780038b80ace0e68f9792ee2839bf081fe386f3 + languageName: node + linkType: hard + "picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" @@ -11178,6 +11750,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^5.0.0": + version: 5.0.0 + resolution: "pkg-dir@npm:5.0.0" + dependencies: + find-up: "npm:^5.0.0" + checksum: 10c0/793a496d685dc55bbbdbbb22d884535c3b29241e48e3e8d37e448113a71b9e42f5481a61fdc672d7322de12fbb2c584dd3a68bf89b18fffce5c48a390f911bc5 + languageName: node + linkType: hard + "playwright-core@npm:1.56.1": version: 1.56.1 resolution: "playwright-core@npm:1.56.1" @@ -11674,6 +12255,13 @@ __metadata: languageName: node linkType: hard +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 + languageName: node + linkType: hard + "progress@npm:^2.0.3": version: 2.0.3 resolution: "progress@npm:2.0.3" @@ -11746,6 +12334,27 @@ __metadata: languageName: node linkType: hard +"public-encrypt@npm:^4.0.3": + version: 4.0.3 + resolution: "public-encrypt@npm:4.0.3" + dependencies: + bn.js: "npm:^4.1.0" + browserify-rsa: "npm:^4.0.0" + create-hash: "npm:^1.1.0" + parse-asn1: "npm:^5.0.0" + randombytes: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/6c2cc19fbb554449e47f2175065d6b32f828f9b3badbee4c76585ac28ae8641aafb9bb107afc430c33c5edd6b05dbe318df4f7d6d7712b1093407b11c4280700 + languageName: node + linkType: hard + +"punycode@npm:^1.4.1": + version: 1.4.1 + resolution: "punycode@npm:1.4.1" + checksum: 10c0/354b743320518aef36f77013be6e15da4db24c2b4f62c5f1eb0529a6ed02fbaf1cb52925785f6ab85a962f2b590d9cd5ad730b70da72b5f180e2556b8bd3ca08 + languageName: node + linkType: hard + "punycode@npm:^2.1.0, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -11766,6 +12375,22 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.12.3": + version: 6.14.0 + resolution: "qs@npm:6.14.0" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c + languageName: node + linkType: hard + +"querystring-es3@npm:^0.2.1": + version: 0.2.1 + resolution: "querystring-es3@npm:0.2.1" + checksum: 10c0/476938c1adb45c141f024fccd2ffd919a3746e79ed444d00e670aad68532977b793889648980e7ca7ff5ffc7bfece623118d0fbadcaf217495eeb7059ae51580 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -11784,6 +12409,25 @@ __metadata: languageName: node linkType: hard +"randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: "npm:^5.1.0" + checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 + languageName: node + linkType: hard + +"randomfill@npm:^1.0.4": + version: 1.0.4 + resolution: "randomfill@npm:1.0.4" + dependencies: + randombytes: "npm:^2.0.5" + safe-buffer: "npm:^5.1.0" + checksum: 10c0/11aeed35515872e8f8a2edec306734e6b74c39c46653607f03c68385ab8030e2adcc4215f76b5e4598e028c4750d820afd5c65202527d831d2a5f207fe2bc87c + languageName: node + linkType: hard + "react-dom@npm:19": version: 19.1.0 resolution: "react-dom@npm:19.1.0" @@ -11978,18 +12622,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.4.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 - languageName: node - linkType: hard - -"readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.3.8, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -12004,6 +12637,17 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + "readdirp@npm:^4.0.1": version: 4.1.2 resolution: "readdirp@npm:4.1.2" @@ -12220,6 +12864,19 @@ __metadata: languageName: node linkType: hard +"resolve@npm:^1.17.0": + version: 1.22.11 + resolution: "resolve@npm:1.22.11" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/f657191507530f2cbecb5815b1ee99b20741ea6ee02a59c57028e9ec4c2c8d7681afcc35febbd554ac0ded459db6f2d8153382c53a2f266cee2575e512674409 + languageName: node + linkType: hard + "resolve@npm:^1.22.10": version: 1.22.10 resolution: "resolve@npm:1.22.10" @@ -12259,6 +12916,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^1.17.0#optional!builtin": + version: 1.22.11 + resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/ee5b182f2e37cb1165465e58c6abc797fec0a80b5ba3231607beb4677db0c9291ac010c47cf092b6daa2b7f518d69a0e21888e7e2b633f68d501a874212a8c63 + languageName: node + linkType: hard + "resolve@patch:resolve@npm%3A^1.22.10#optional!builtin": version: 1.22.10 resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" @@ -12332,6 +13002,16 @@ __metadata: languageName: node linkType: hard +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.3": + version: 2.0.3 + resolution: "ripemd160@npm:2.0.3" + dependencies: + hash-base: "npm:^3.1.2" + inherits: "npm:^2.0.4" + checksum: 10c0/3f472fb453241cfe692a77349accafca38dbcdc9d96d5848c088b2932ba41eb968630ecff7b175d291c7487a4945aee5a81e30c064d1f94e36070f7e0c37ed6c + languageName: node + linkType: hard + "rollup@npm:^4.43.0": version: 4.50.1 resolution: "rollup@npm:4.50.1" @@ -12479,6 +13159,13 @@ __metadata: languageName: node linkType: hard +"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + "safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": version: 5.1.2 resolution: "safe-buffer@npm:5.1.2" @@ -12486,13 +13173,6 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - "safe-push-apply@npm:^1.0.0": version: 1.0.0 resolution: "safe-push-apply@npm:1.0.0" @@ -12657,6 +13337,26 @@ __metadata: languageName: node linkType: hard +"setimmediate@npm:^1.0.4": + version: 1.0.5 + resolution: "setimmediate@npm:1.0.5" + checksum: 10c0/5bae81bfdbfbd0ce992893286d49c9693c82b1bcc00dcaaf3a09c8f428fdeacf4190c013598b81875dfac2b08a572422db7df779a99332d0fce186d15a3e4d49 + languageName: node + linkType: hard + +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": + version: 2.4.12 + resolution: "sha.js@npm:2.4.12" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.0" + bin: + sha.js: bin.js + checksum: 10c0/9d36bdd76202c8116abbe152a00055ccd8a0099cb28fc17c01fa7bb2c8cffb9ca60e2ab0fe5f274ed6c45dc2633d8c39cf7ab050306c231904512ba9da4d8ab1 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -12901,6 +13601,16 @@ __metadata: languageName: node linkType: hard +"stream-browserify@npm:^3.0.0": + version: 3.0.0 + resolution: "stream-browserify@npm:3.0.0" + dependencies: + inherits: "npm:~2.0.4" + readable-stream: "npm:^3.5.0" + checksum: 10c0/ec3b975a4e0aa4b3dc5e70ffae3fc8fd29ac725353a14e72f213dff477b00330140ad014b163a8cbb9922dfe90803f81a5ea2b269e1bbfd8bd71511b88f889ad + languageName: node + linkType: hard + "stream-composer@npm:^1.0.2": version: 1.0.2 resolution: "stream-composer@npm:1.0.2" @@ -12910,6 +13620,18 @@ __metadata: languageName: node linkType: hard +"stream-http@npm:^3.2.0": + version: 3.2.0 + resolution: "stream-http@npm:3.2.0" + dependencies: + builtin-status-codes: "npm:^3.0.0" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.6.0" + xtend: "npm:^4.0.2" + checksum: 10c0/f128fb8076d60cd548f229554b6a1a70c08a04b7b2afd4dbe7811d20f27f7d4112562eb8bce86d72a8691df3b50573228afcf1271e55e81f981536c67498bc41 + languageName: node + linkType: hard + "streamx@npm:^2.12.0, streamx@npm:^2.12.5, streamx@npm:^2.13.2, streamx@npm:^2.14.0": version: 2.22.0 resolution: "streamx@npm:2.22.0" @@ -13026,7 +13748,7 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:^1.1.1": +"string_decoder@npm:^1.0.0, string_decoder@npm:^1.1.1": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" dependencies: @@ -13228,6 +13950,15 @@ __metadata: languageName: node linkType: hard +"timers-browserify@npm:^2.0.4": + version: 2.0.12 + resolution: "timers-browserify@npm:2.0.12" + dependencies: + setimmediate: "npm:^1.0.4" + checksum: 10c0/98e84db1a685bc8827c117a8bc62aac811ad56a995d07938fc7ed8cdc5bf3777bfe2d4e5da868847194e771aac3749a20f6cdd22091300fe889a76fe214a4641 + languageName: node + linkType: hard + "tinybench@npm:^2.9.0": version: 2.9.0 resolution: "tinybench@npm:2.9.0" @@ -13301,6 +14032,17 @@ __metadata: languageName: node linkType: hard +"to-buffer@npm:^1.2.0, to-buffer@npm:^1.2.1, to-buffer@npm:^1.2.2": + version: 1.2.2 + resolution: "to-buffer@npm:1.2.2" + dependencies: + isarray: "npm:^2.0.5" + safe-buffer: "npm:^5.2.1" + typed-array-buffer: "npm:^1.0.3" + checksum: 10c0/56bc56352f14a2c4a0ab6277c5fc19b51e9534882b98eb068b39e14146591e62fa5b06bf70f7fed1626230463d7e60dca81e815096656e5e01c195c593873d12 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -13438,6 +14180,13 @@ __metadata: languageName: node linkType: hard +"tty-browserify@npm:0.0.1": + version: 0.0.1 + resolution: "tty-browserify@npm:0.0.1" + checksum: 10c0/5e34883388eb5f556234dae75b08e069b9e62de12bd6d87687f7817f5569430a6dfef550b51dbc961715ae0cd0eb5a059e6e3fc34dc127ea164aa0f9b5bb033d + languageName: node + linkType: hard + "tunnel@npm:^0.0.6": version: 0.0.6 resolution: "tunnel@npm:0.0.6" @@ -13772,6 +14521,16 @@ __metadata: languageName: node linkType: hard +"url@npm:^0.11.4": + version: 0.11.4 + resolution: "url@npm:0.11.4" + dependencies: + punycode: "npm:^1.4.1" + qs: "npm:^6.12.3" + checksum: 10c0/cc93405ae4a9b97a2aa60ca67f1cb1481c0221cb4725a7341d149be5e2f9cfda26fd432d64dbbec693d16593b68b8a46aad8e5eab21f814932134c9d8620c662 + languageName: node + linkType: hard + "use-callback-ref@npm:^1.3.3": version: 1.3.3 resolution: "use-callback-ref@npm:1.3.3" @@ -13821,6 +14580,19 @@ __metadata: languageName: node linkType: hard +"util@npm:^0.12.4, util@npm:^0.12.5": + version: 0.12.5 + resolution: "util@npm:0.12.5" + dependencies: + inherits: "npm:^2.0.3" + is-arguments: "npm:^1.0.4" + is-generator-function: "npm:^1.0.7" + is-typed-array: "npm:^1.1.3" + which-typed-array: "npm:^1.1.2" + checksum: 10c0/c27054de2cea2229a66c09522d0fa1415fb12d861d08523a8846bf2e4cbf0079d4c3f725f09dcb87493549bcbf05f5798dce1688b53c6c17201a45759e7253f3 + languageName: node + linkType: hard + "uuid@npm:13": version: 13.0.0 resolution: "uuid@npm:13.0.0" @@ -13967,6 +14739,18 @@ __metadata: languageName: node linkType: hard +"vite-plugin-node-stdlib-browser@npm:^0.2.1": + version: 0.2.1 + resolution: "vite-plugin-node-stdlib-browser@npm:0.2.1" + dependencies: + "@rollup/plugin-inject": "npm:^5.0.3" + peerDependencies: + node-stdlib-browser: ^1.2.0 + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 + checksum: 10c0/4686bde59d0396d8684433e1a14ddce868dc422f80e306a0c1cb5e86564d9f7c38a67865ca339e4ff57784ec4bada149034038cad6911a2dfcac8debfc9bd20a + languageName: node + linkType: hard + "vite-plugin-singlefile@npm:^2.3.0": version: 2.3.0 resolution: "vite-plugin-singlefile@npm:2.3.0" @@ -14117,6 +14901,13 @@ __metadata: languageName: node linkType: hard +"vm-browserify@npm:^1.0.1": + version: 1.1.2 + resolution: "vm-browserify@npm:1.1.2" + checksum: 10c0/0cc1af6e0d880deb58bc974921320c187f9e0a94f25570fca6b1bd64e798ce454ab87dfd797551b1b0cc1849307421aae0193cedf5f06bdb5680476780ee344b + languageName: node + linkType: hard + "void-elements@npm:3.1.0": version: 3.1.0 resolution: "void-elements@npm:3.1.0" @@ -14316,7 +15107,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.19": +"which-typed-array@npm:^1.1.19, which-typed-array@npm:^1.1.2": version: 1.1.19 resolution: "which-typed-array@npm:1.1.19" dependencies: @@ -14441,7 +15232,7 @@ __metadata: languageName: node linkType: hard -"xtend@npm:~4.0.1": +"xtend@npm:^4.0.2, xtend@npm:~4.0.1": version: 4.0.2 resolution: "xtend@npm:4.0.2" checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e From 284a52c23cbbed7b43f9aa4a46836751f675d1e8 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 1 Dec 2025 12:43:17 +0100 Subject: [PATCH 03/12] mvp --- godot/index.html | 6 +- godot/main.ts | 204 ++++++++++-------- src/state/CallViewModel/CallViewModel.ts | 24 ++- .../CallViewModel/localMember/Publisher.ts | 33 ++- .../remoteMembers/Connection.test.ts | 28 ++- .../CallViewModel/remoteMembers/Connection.ts | 29 +-- .../remoteMembers/ConnectionFactory.ts | 2 +- .../remoteMembers/ConnectionManager.test.ts | 52 ++--- .../remoteMembers/ConnectionManager.ts | 39 ++-- .../MatrixLivekitMembers.test.ts | 121 ++++++----- .../remoteMembers/MatrixLivekitMembers.ts | 11 +- .../remoteMembers/integration.test.ts | 4 +- 12 files changed, 299 insertions(+), 254 deletions(-) diff --git a/godot/index.html b/godot/index.html index ff654748d..7d5f96c01 100644 --- a/godot/index.html +++ b/godot/index.html @@ -20,7 +20,7 @@ await window.matrixRTCSdk.join(); console.info("matrixRTCSdk joined "); - // sdk.data$.subscribe((data) => { + // window.matrixRTCSdk.data$.subscribe((data) => { // console.log(data); // const div = document.getElementById("data"); // div.appendChild(document.createTextNode(data)); @@ -36,9 +36,9 @@ - +
diff --git a/godot/main.ts b/godot/main.ts index 98bb49722..ede612cbc 100644 --- a/godot/main.ts +++ b/godot/main.ts @@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details. */ // import { type InitResult } from "../src/ClientContext"; -import { map, type Observable, of, Subject, switchMap } from "rxjs"; +import { map, type Observable, of, Subject, switchMap, tap } from "rxjs"; import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc"; import { type TextStreamInfo } from "livekit-client/dist/src/room/types"; import { @@ -36,7 +36,7 @@ interface MatrixRTCSdk { /** @throws on leave errors */ leave: () => void; data$: Observable<{ sender: string; data: string }>; - sendData?: (data: Record) => Promise; + sendData?: (data: unknown) => Promise; } export async function createMatrixRTCSdk(): Promise { logger.info("Hello"); @@ -67,97 +67,115 @@ export async function createMatrixRTCSdk(): Promise { // create data listener const data$ = new Subject<{ sender: string; data: string }>(); - // const lkTextStreamHandlerFunction = async ( - // reader: TextStreamReader, - // participantInfo: { identity: string }, - // livekitRoom: LivekitRoom, - // ): Promise => { - // const info = reader.info; - // console.log( - // `Received text stream from ${participantInfo.identity}\n` + - // ` Topic: ${info.topic}\n` + - // ` Timestamp: ${info.timestamp}\n` + - // ` ID: ${info.id}\n` + - // ` Size: ${info.size}`, // Optional, only available if the stream was sent with `sendText` - // ); - - // const participants = callViewModel.livekitRoomItems$.value.find( - // (i) => i.livekitRoom === livekitRoom, - // )?.participants; - // if (participants && participants.includes(participantInfo.identity)) { - // const text = await reader.readAll(); - // console.log(`Received text: ${text}`); - // data$.next({ sender: participantInfo.identity, data: text }); - // } else { - // logger.warn( - // "Received text from unknown participant", - // participantInfo.identity, - // ); - // } - // }; - - // const livekitRoomItemsSub = callViewModel.livekitRoomItems$ - // .pipe(currentAndPrev) - // .subscribe({ - // next: ({ prev, current }) => { - // const prevRooms = prev.map((i) => i.livekitRoom); - // const currentRooms = current.map((i) => i.livekitRoom); - // const addedRooms = currentRooms.filter((r) => !prevRooms.includes(r)); - // const removedRooms = prevRooms.filter((r) => !currentRooms.includes(r)); - // addedRooms.forEach((r) => - // r.registerTextStreamHandler( - // TEXT_LK_TOPIC, - // (reader, participantInfo) => - // void lkTextStreamHandlerFunction(reader, participantInfo, r), - // ), - // ); - // removedRooms.forEach((r) => - // r.unregisterTextStreamHandler(TEXT_LK_TOPIC), - // ); - // }, - // complete: () => { - // logger.info("Livekit room items subscription completed"); - // for (const item of callViewModel.livekitRoomItems$.value) { - // logger.info("unregistering room item from room", item.url); - // item.livekitRoom.unregisterTextStreamHandler(TEXT_LK_TOPIC); - // } - // }, - // }); + const lkTextStreamHandlerFunction = async ( + reader: TextStreamReader, + participantInfo: { identity: string }, + livekitRoom: LivekitRoom, + ): Promise => { + const info = reader.info; + logger.info( + `Received text stream from ${participantInfo.identity}\n` + + ` Topic: ${info.topic}\n` + + ` Timestamp: ${info.timestamp}\n` + + ` ID: ${info.id}\n` + + ` Size: ${info.size}`, // Optional, only available if the stream was sent with `sendText` + ); + + const participants = callViewModel.livekitRoomItems$.value.find( + (i) => i.livekitRoom === livekitRoom, + )?.participants; + if (participants && participants.includes(participantInfo.identity)) { + const text = await reader.readAll(); + logger.info(`Received text: ${text}`); + data$.next({ sender: participantInfo.identity, data: text }); + } else { + logger.warn( + "Received text from unknown participant", + participantInfo.identity, + ); + } + }; + + const livekitRoomItemsSub = callViewModel.livekitRoomItems$ + .pipe( + tap((beforecurrentAndPrev) => { + logger.info( + `LiveKit room items updated: ${beforecurrentAndPrev.length}`, + beforecurrentAndPrev, + ); + }), + currentAndPrev, + tap((aftercurrentAndPrev) => { + logger.info( + `LiveKit room items updated: ${aftercurrentAndPrev.current.length}, ${aftercurrentAndPrev.prev.length}`, + aftercurrentAndPrev, + ); + }), + ) + .subscribe({ + next: ({ prev, current }) => { + const prevRooms = prev.map((i) => i.livekitRoom); + const currentRooms = current.map((i) => i.livekitRoom); + const addedRooms = currentRooms.filter((r) => !prevRooms.includes(r)); + const removedRooms = prevRooms.filter((r) => !currentRooms.includes(r)); + addedRooms.forEach((r) => { + logger.info(`Registering text stream handler for room `); + r.registerTextStreamHandler( + TEXT_LK_TOPIC, + (reader, participantInfo) => + void lkTextStreamHandlerFunction(reader, participantInfo, r), + ); + }); + removedRooms.forEach((r) => { + logger.info(`Unregistering text stream handler for room `); + r.unregisterTextStreamHandler(TEXT_LK_TOPIC); + }); + }, + complete: () => { + logger.info("Livekit room items subscription completed"); + for (const item of callViewModel.livekitRoomItems$.value) { + logger.info("unregistering room item from room", item.url); + item.livekitRoom.unregisterTextStreamHandler(TEXT_LK_TOPIC); + } + }, + }); // create sendData function - // const sendFn: Behavior<(data: string) => Promise> = - // scope.behavior( - // callViewModel.localMatrixLivekitMember$.pipe( - // switchMap((m) => { - // if (!m) - // return of((data: string): never => { - // throw Error("local membership not yet ready."); - // }); - // return m.participant$.pipe( - // map((p) => { - // if (p === null) { - // return (data: string): never => { - // throw Error("local participant not yet ready to send data."); - // }; - // } else { - // return async (data: string): Promise => - // p.sendText(data, { topic: TEXT_LK_TOPIC }); - // } - // }), - // ); - // }), - // ), - // ); - - // const sendData = async (data: Record): Promise => { - // const dataString = JSON.stringify(data); - // try { - // const info = await sendFn.value(dataString); - // logger.info(`Sent text with stream ID: ${info.id}`); - // } catch (e) { - // console.error("failed sending: ", dataString, e); - // } - // }; + const sendFn: Behavior<(data: string) => Promise> = + scope.behavior( + callViewModel.localmatrixLivekitMembers$.pipe( + switchMap((m) => { + if (!m) + return of((data: string): never => { + throw Error("local membership not yet ready."); + }); + return m.participant$.pipe( + map((p) => { + if (p === null) { + return (data: string): never => { + throw Error("local participant not yet ready to send data."); + }; + } else { + return async (data: string): Promise => + p.sendText(data, { topic: TEXT_LK_TOPIC }); + } + }), + ); + }), + ), + ); + + const sendData = async (data: unknown): Promise => { + const dataString = JSON.stringify(data); + logger.info("try sending: ", dataString); + try { + await Promise.resolve(); + const info = await sendFn.value(dataString); + logger.info(`Sent text with stream ID: ${info.id}`); + } catch (e) { + logger.error("failed sending: ", dataString, e); + } + }; // after hangup gets called const leaveSubs = callViewModel.leave$.subscribe(() => { @@ -202,9 +220,9 @@ export async function createMatrixRTCSdk(): Promise { leave: (): void => { callViewModel.hangup(); leaveSubs.unsubscribe(); - // livekitRoomItemsSub.unsubscribe(); + livekitRoomItemsSub.unsubscribe(); }, data$, - // sendData, + sendData, }; } diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 253eb05ed..a4738f77f 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -264,7 +264,7 @@ export interface CallViewModel { livekitRoomItems$: Behavior; /** use the layout instead, this is just for the godot export. */ userMedia$: Behavior; - localMatrixLivekitMember$: Behavior; + localmatrixLivekitMembers$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ @@ -449,7 +449,7 @@ export function createCallViewModel$( logger: logger, }); - const matrixLivekitMembers$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: scope, membershipsWithTransport$: membershipsAndTransports.membershipsWithTransport$, @@ -515,7 +515,7 @@ export function createCallViewModel$( userId: userId, }; - const localMatrixLivekitMember$: Behavior = + const localmatrixLivekitMembers$: Behavior = scope.behavior( localRtcMembership$.pipe( switchMap((membership) => { @@ -607,8 +607,11 @@ export function createCallViewModel$( const reconnecting$ = localMembership.reconnecting$; const pretendToBeDisconnected$ = reconnecting$; - const audioParticipants$ = scope.behavior( + const livekitRoomItems$ = scope.behavior( matrixLivekitMembers$.pipe( + tap((val) => { + logger.debug("matrixLivekitMembers$ updated", val.value); + }), switchMap((membersWithEpoch) => { const members = membersWithEpoch.value; const a$ = combineLatest( @@ -649,6 +652,12 @@ export function createCallViewModel$( return acc; }, []), ), + tap((val) => { + logger.debug( + "livekitRoomItems$ updated", + val.map((v) => v.url), + ); + }), ), [], ); @@ -676,7 +685,7 @@ export function createCallViewModel$( */ const userMedia$ = scope.behavior( combineLatest([ - localMatrixLivekitMember$, + localmatrixLivekitMembers$, matrixLivekitMembers$, duplicateTiles.value$, ]).pipe( @@ -1489,8 +1498,7 @@ export function createCallViewModel$( ), participantCount$: participantCount$, - livekitRoomItems$: audioParticipants$, - + livekitRoomItems$, handsRaised$: handsRaised$, reactions$: reactions$, joinSoundEffect$: joinSoundEffect$, @@ -1510,7 +1518,7 @@ export function createCallViewModel$( pip$: pip$, layout$: layout$, userMedia$, - localMatrixLivekitMember$, + localmatrixLivekitMembers$, tileStoreGeneration$: tileStoreGeneration$, showSpotlightIndicators$: showSpotlightIndicators$, showSpeakingIndicators$: showSpeakingIndicators$, diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 11f35424a..2508637ee 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -56,15 +56,15 @@ export class Publisher { devices: MediaDevices, private readonly muteStates: MuteStates, trackerProcessorState$: Behavior, - private logger?: Logger, + private logger: Logger, ) { - this.logger?.info("[PublishConnection] Create LiveKit room"); + this.logger.info("[PublishConnection] Create LiveKit room"); const { controlledAudioDevices } = getUrlParams(); const room = connection.livekitRoom; room.setE2EEEnabled(room.options.e2ee !== undefined)?.catch((e: Error) => { - this.logger?.error("Failed to set E2EE enabled on room", e); + this.logger.error("Failed to set E2EE enabled on room", e); }); // Setup track processor syncing (blur) @@ -74,7 +74,7 @@ export class Publisher { this.workaroundRestartAudioInputTrackChrome(devices, scope); this.scope.onEnd(() => { - this.logger?.info( + this.logger.info( "[PublishConnection] Scope ended -> stop publishing all tracks", ); void this.stopPublishing(); @@ -132,13 +132,14 @@ export class Publisher { video, }) .catch((error) => { - this.logger?.error("Failed to create tracks", error); + this.logger.error("Failed to create tracks", error); })) ?? []; } return this.tracks; } public async startPublishing(): Promise { + this.logger.info("Start publishing"); const lkRoom = this.connection.livekitRoom; const { promise, resolve, reject } = Promise.withResolvers(); const sub = this.connection.state$.subscribe((s) => { @@ -150,7 +151,7 @@ export class Publisher { reject(new Error("Failed to connect to LiveKit server")); break; default: - this.logger?.info("waiting for connection: ", s.state); + this.logger.info("waiting for connection: ", s.state); } }); try { @@ -160,12 +161,14 @@ export class Publisher { } finally { sub.unsubscribe(); } + this.logger.info("publish ", this.tracks.length, "tracks"); for (const track of this.tracks) { // TODO: handle errors? Needs the signaling connection to be up, but it has some retries internally // with a timeout. await lkRoom.localParticipant.publishTrack(track).catch((error) => { - this.logger?.error("Failed to publish track", error); + this.logger.error("Failed to publish track", error); }); + this.logger.info("published track ", track.kind, track.id); // TODO: check if the connection is still active? and break the loop if not? } @@ -229,7 +232,7 @@ export class Publisher { .getTrackPublication(Track.Source.Microphone) ?.audioTrack?.restartTrack() .catch((e) => { - this.logger?.error(`Failed to restart audio device track`, e); + this.logger.error(`Failed to restart audio device track`, e); }); } }); @@ -249,7 +252,7 @@ export class Publisher { selected$.pipe(scope.bind()).subscribe((device) => { if (lkRoom.state != LivekitConnectionState.Connected) return; // if (this.connectionState$.value !== ConnectionState.Connected) return; - this.logger?.info( + this.logger.info( "[LivekitRoom] syncDevice room.getActiveDevice(kind) !== d.id :", lkRoom.getActiveDevice(kind), " !== ", @@ -262,7 +265,7 @@ export class Publisher { lkRoom .switchActiveDevice(kind, device.id) .catch((e: Error) => - this.logger?.error( + this.logger.error( `Failed to sync ${kind} device with LiveKit`, e, ), @@ -287,10 +290,7 @@ export class Publisher { try { await lkRoom.localParticipant.setMicrophoneEnabled(desired); } catch (e) { - this.logger?.error( - "Failed to update LiveKit audio input mute state", - e, - ); + this.logger.error("Failed to update LiveKit audio input mute state", e); } return lkRoom.localParticipant.isMicrophoneEnabled; }); @@ -298,10 +298,7 @@ export class Publisher { try { await lkRoom.localParticipant.setCameraEnabled(desired); } catch (e) { - this.logger?.error( - "Failed to update LiveKit video input mute state", - e, - ); + this.logger.error("Failed to update LiveKit video input mute state", e); } return lkRoom.localParticipant.isCameraEnabled; }); diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 3f58bcf6d..f719e86bf 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -382,17 +382,15 @@ describe("Publishing participants observations", () => { const bobIsAPublisher = Promise.withResolvers(); const danIsAPublisher = Promise.withResolvers(); const observedPublishers: PublishingParticipant[][] = []; - const s = connection.remoteParticipantsWithTracks$.subscribe( - (publishers) => { - observedPublishers.push(publishers); - if (publishers.some((p) => p.identity === "@bob:example.org:DEV111")) { - bobIsAPublisher.resolve(); - } - if (publishers.some((p) => p.identity === "@dan:example.org:DEV333")) { - danIsAPublisher.resolve(); - } - }, - ); + const s = connection.remoteParticipants$.subscribe((publishers) => { + observedPublishers.push(publishers); + if (publishers.some((p) => p.identity === "@bob:example.org:DEV111")) { + bobIsAPublisher.resolve(); + } + if (publishers.some((p) => p.identity === "@dan:example.org:DEV333")) { + danIsAPublisher.resolve(); + } + }); onTestFinished(() => s.unsubscribe()); // The publishingParticipants$ observable is derived from the current members of the // livekitRoom and the rtc membership in order to publish the members that are publishing @@ -437,11 +435,9 @@ describe("Publishing participants observations", () => { const connection = setupRemoteConnection(); let observedPublishers: PublishingParticipant[][] = []; - const s = connection.remoteParticipantsWithTracks$.subscribe( - (publishers) => { - observedPublishers.push(publishers); - }, - ); + const s = connection.remoteParticipants$.subscribe((publishers) => { + observedPublishers.push(publishers); + }); onTestFinished(() => s.unsubscribe()); let participants: RemoteParticipant[] = [ diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index c17fae2b6..fd75e5512 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -19,7 +19,7 @@ import { RoomEvent, } from "livekit-client"; import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; -import { BehaviorSubject, map, type Observable } from "rxjs"; +import { BehaviorSubject, type Observable } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { @@ -146,6 +146,10 @@ export class Connection { transport: this.transport, livekitConnectionState$: connectionStateObserver(this.livekitRoom), }); + this.logger.info( + "Connected to LiveKit room", + this.transport.livekit_service_url, + ); } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); this._state$.next({ @@ -189,9 +193,7 @@ export class Connection { * This is derived from `participantsIncludingSubscribers$` and `remoteTransports$`. * It filters the participants to only those that are associated with a membership that claims to publish on this connection. */ - public readonly remoteParticipantsWithTracks$: Behavior< - PublishingParticipant[] - >; + public readonly remoteParticipants$: Behavior; /** * The media transport to connect to. @@ -213,7 +215,7 @@ export class Connection { public constructor(opts: ConnectionOpts, logger: Logger) { this.logger = logger.getChild("[Connection]"); this.logger.info( - `[Connection] Creating new connection to ${opts.transport.livekit_service_url} ${opts.transport.livekit_alias}`, + `Creating new connection to ${opts.transport.livekit_service_url} ${opts.transport.livekit_alias}`, ); const { transport, client, scope } = opts; @@ -223,20 +225,21 @@ export class Connection { // REMOTE participants with track!!! // this.remoteParticipantsWithTracks$ - this.remoteParticipantsWithTracks$ = scope.behavior( + this.remoteParticipants$ = scope.behavior( // only tracks remote participants connectedParticipantsObserver(this.livekitRoom, { additionalRoomEvents: [ RoomEvent.TrackPublished, RoomEvent.TrackUnpublished, ], - }).pipe( - map((participants) => { - return participants.filter( - (participant) => participant.getTrackPublications().length > 0, - ); - }), - ), + }), + // .pipe( + // map((participants) => { + // return participants.filter( + // (participant) => participant.getTrackPublications().length > 0, + // ); + // }), + // ) [], ); diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index f58fcb764..0fb0b5a79 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -13,7 +13,7 @@ import { type BaseKeyProvider, } from "livekit-client"; import { type Logger } from "matrix-js-sdk/lib/logger"; -import E2EEWorker from "livekit-client/e2ee-worker?worker"; +import E2EEWorker from "livekit-client/e2ee-worker?worker&inline"; import { type ObservableScope } from "../../ObservableScope.ts"; import { Connection } from "./Connection.ts"; diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts index 484a44e74..b50762854 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts @@ -289,47 +289,47 @@ describe("connectionManagerData$ stream", () => { a: expect.toSatisfy((e) => { const data: ConnectionManagerData = e.value; expect(data.getConnections().length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_1).length).toBe(0); - expect(data.getParticipantForTransport(TRANSPORT_2).length).toBe(0); + expect(data.getParticipantsForTransport(TRANSPORT_1).length).toBe(0); + expect(data.getParticipantsForTransport(TRANSPORT_2).length).toBe(0); return true; }), b: expect.toSatisfy((e) => { const data: ConnectionManagerData = e.value; expect(data.getConnections().length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_1).length).toBe(1); - expect(data.getParticipantForTransport(TRANSPORT_2).length).toBe(0); - expect(data.getParticipantForTransport(TRANSPORT_1)[0].identity).toBe( - "user1A", - ); + expect(data.getParticipantsForTransport(TRANSPORT_1).length).toBe(1); + expect(data.getParticipantsForTransport(TRANSPORT_2).length).toBe(0); + expect( + data.getParticipantsForTransport(TRANSPORT_1)[0].identity, + ).toBe("user1A"); return true; }), c: expect.toSatisfy((e) => { const data: ConnectionManagerData = e.value; expect(data.getConnections().length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_1).length).toBe(1); - expect(data.getParticipantForTransport(TRANSPORT_2).length).toBe(1); - expect(data.getParticipantForTransport(TRANSPORT_1)[0].identity).toBe( - "user1A", - ); - expect(data.getParticipantForTransport(TRANSPORT_2)[0].identity).toBe( - "user2A", - ); + expect(data.getParticipantsForTransport(TRANSPORT_1).length).toBe(1); + expect(data.getParticipantsForTransport(TRANSPORT_2).length).toBe(1); + expect( + data.getParticipantsForTransport(TRANSPORT_1)[0].identity, + ).toBe("user1A"); + expect( + data.getParticipantsForTransport(TRANSPORT_2)[0].identity, + ).toBe("user2A"); return true; }), d: expect.toSatisfy((e) => { const data: ConnectionManagerData = e.value; expect(data.getConnections().length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_1).length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_2).length).toBe(1); - expect(data.getParticipantForTransport(TRANSPORT_1)[0].identity).toBe( - "user1A", - ); - expect(data.getParticipantForTransport(TRANSPORT_1)[1].identity).toBe( - "user1B", - ); - expect(data.getParticipantForTransport(TRANSPORT_2)[0].identity).toBe( - "user2A", - ); + expect(data.getParticipantsForTransport(TRANSPORT_1).length).toBe(2); + expect(data.getParticipantsForTransport(TRANSPORT_2).length).toBe(1); + expect( + data.getParticipantsForTransport(TRANSPORT_1)[0].identity, + ).toBe("user1A"); + expect( + data.getParticipantsForTransport(TRANSPORT_1)[1].identity, + ).toBe("user1B"); + expect( + data.getParticipantsForTransport(TRANSPORT_2)[0].identity, + ).toBe("user2A"); return true; }), }); diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index d9a0380ea..bd07cfa13 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -24,7 +24,10 @@ import { type ConnectionFactory } from "./ConnectionFactory.ts"; export class ConnectionManagerData { private readonly store: Map< string, - [Connection, (LocalParticipant | RemoteParticipant)[]] + { + connection: Connection; + participants: (LocalParticipant | RemoteParticipant)[]; + } > = new Map(); public constructor() {} @@ -36,9 +39,9 @@ export class ConnectionManagerData { const key = this.getKey(connection.transport); const existing = this.store.get(key); if (!existing) { - this.store.set(key, [connection, participants]); + this.store.set(key, { connection, participants }); } else { - existing[1].push(...participants); + existing.participants.push(...participants); } } @@ -47,25 +50,26 @@ export class ConnectionManagerData { } public getConnections(): Connection[] { - return Array.from(this.store.values()).map(([connection]) => connection); + return Array.from(this.store.values()).map(({ connection }) => connection); } public getConnectionForTransport( transport: LivekitTransport, ): Connection | null { - return this.store.get(this.getKey(transport))?.[0] ?? null; + return this.store.get(this.getKey(transport))?.connection ?? null; } - public getParticipantForTransport( + public getParticipantsForTransport( transport: LivekitTransport, ): (LocalParticipant | RemoteParticipant)[] { const key = transport.livekit_service_url + "|" + transport.livekit_alias; const existing = this.store.get(key); if (existing) { - return existing[1]; + return existing.participants; } return []; } + /** * Get all connections where the given participant is publishing. * In theory, there could be several connections where the same participant is publishing but with @@ -76,8 +80,12 @@ export class ConnectionManagerData { participantId: ParticipantId, ): Connection[] { const connections: Connection[] = []; - for (const [connection, participants] of this.store.values()) { - if (participants.some((p) => p.identity === participantId)) { + for (const { connection, participants } of this.store.values()) { + if ( + participants.some( + (participant) => participant?.identity === participantId, + ) + ) { connections.push(connection); } } @@ -183,23 +191,24 @@ export function createConnectionManager$({ const epoch = connections.epoch; // Map the connections to list of {connection, participants}[] - const listOfConnectionsWithPublishingParticipants = - connections.value.map((connection) => { - return connection.remoteParticipantsWithTracks$.pipe( + const listOfConnectionsWithParticipants = connections.value.map( + (connection) => { + return connection.remoteParticipants$.pipe( map((participants) => ({ connection, participants, })), ); - }); + }, + ); // probably not required - if (listOfConnectionsWithPublishingParticipants.length === 0) { + if (listOfConnectionsWithParticipants.length === 0) { return of(new Epoch(new ConnectionManagerData(), epoch)); } // combineLatest the several streams into a single stream with the ConnectionManagerData - return combineLatest(listOfConnectionsWithPublishingParticipants).pipe( + return combineLatest(listOfConnectionsWithParticipants).pipe( map( (lists) => new Epoch( diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index e675f7230..7547a68be 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -91,7 +91,7 @@ test("should signal participant not yet connected to livekit", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -99,21 +99,24 @@ test("should signal participant not yet connected to livekit", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: null, - }); - expectObservable(data[0].connection$).toBe("a", { - a: null, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant$).toBe("a", { + a: null, + }); + expectObservable(data[0].connection$).toBe("a", { + a: null, + }); + return true; + }), + }, + ); }); }); @@ -171,7 +174,7 @@ test("should signal participant on a connection that is publishing", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -179,25 +182,28 @@ test("should signal participant on a connection that is publishing", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: expect.toSatisfy((participant) => { - expect(participant).toBeDefined(); - expect(participant!.identity).toEqual(bobParticipantId); - return true; - }), - }); - expectObservable(data[0].connection$).toBe("a", { - a: connection, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant$).toBe("a", { + a: expect.toSatisfy((participant) => { + expect(participant).toBeDefined(); + expect(participant!.identity).toEqual(bobParticipantId); + return true; + }), + }); + expectObservable(data[0].connection$).toBe("a", { + a: connection, + }); + return true; + }), + }, + ); }); }); @@ -222,7 +228,7 @@ test("should signal participant on a connection that is not publishing", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -230,21 +236,24 @@ test("should signal participant on a connection that is not publishing", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: null, - }); - expectObservable(data[0].connection$).toBe("a", { - a: connection, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant$).toBe("a", { + a: null, + }); + expectObservable(data[0].connection$).toBe("a", { + a: connection, + }); + return true; + }), + }, + ); }); }); @@ -283,7 +292,7 @@ describe("Publication edge case", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior( membershipsWithTransport$, @@ -293,7 +302,7 @@ describe("Publication edge case", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( "a", { a: expect.toSatisfy((data: MatrixLivekitMember[]) => { @@ -349,7 +358,7 @@ describe("Publication edge case", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior( membershipsWithTransport$, @@ -359,7 +368,7 @@ describe("Publication edge case", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( "a", { a: expect.toSatisfy((data: MatrixLivekitMember[]) => { diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 2f1526308..72e2883a2 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -61,12 +61,12 @@ export function createMatrixLivekitMembers$({ scope, membershipsWithTransport$, connectionManager, -}: Props): Behavior> { +}: Props): { matrixLivekitMembers$: Behavior> } { /** * Stream of all the call members and their associated livekit data (if available). */ - return scope.behavior( + const matrixLivekitMembers$ = scope.behavior( combineLatest([ membershipsWithTransport$, connectionManager.connectionManagerData$, @@ -91,7 +91,7 @@ export function createMatrixLivekitMembers$({ const participantId = /*membership.membershipID*/ `${membership.userId}:${membership.deviceId}`; const participants = transport - ? managerData.getParticipantForTransport(transport) + ? managerData.getParticipantsForTransport(transport) : []; const participant = participants.find((p) => p.identity == participantId) ?? null; @@ -121,6 +121,11 @@ export function createMatrixLivekitMembers$({ ), ), ); + return { + matrixLivekitMembers$, + // TODO add only publishing participants... maybe. disucss at least + // scope.behavior(matrixLivekitMembers$.pipe(map((items) => items.value.map((i)=>{ i.})))) + }; } // TODO add back in the callviewmodel pauseWhen(this.pretendToBeDisconnected$) diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index e3aa6be8d..cafffb384 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -124,14 +124,14 @@ test("bob, carl, then bob joining no tracks yet", () => { logger: logger, }); - const matrixLivekitItems$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: membershipsAndTransports.membershipsWithTransport$, connectionManager, }); - expectObservable(matrixLivekitItems$).toBe(vMarble, { + expectObservable(matrixLivekitMembers$).toBe(vMarble, { a: expect.toSatisfy((e: Epoch) => { const items = e.value; expect(items.length).toBe(1); From 0664af0f1b3ef694c7733881bcca1195f197c0c9 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 1 Dec 2025 13:49:33 +0100 Subject: [PATCH 04/12] log cleanup and expose members$ --- godot/index.html | 39 ++++++++++++++++--- godot/main.ts | 5 ++- src/state/CallViewModel/CallViewModel.ts | 23 ++++++++--- .../CallViewModel/localMember/Publisher.ts | 6 +-- .../remoteMembers/ConnectionFactory.ts | 1 + 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/godot/index.html b/godot/index.html index 7d5f96c01..39bcf4842 100644 --- a/godot/index.html +++ b/godot/index.html @@ -4,6 +4,7 @@ Godot MatrixRTC Widget + @@ -39,6 +65,7 @@ +
diff --git a/godot/main.ts b/godot/main.ts index ede612cbc..c5ee29a83 100644 --- a/godot/main.ts +++ b/godot/main.ts @@ -30,12 +30,14 @@ import { widget, } from "./helper"; import { ElementWidgetActions } from "../src/widget"; +import { type MatrixLivekitMember } from "../src/state/CallViewModel/remoteMembers/MatrixLivekitMembers"; interface MatrixRTCSdk { join: () => LocalMemberConnectionState; /** @throws on leave errors */ leave: () => void; data$: Observable<{ sender: string; data: string }>; + members$: Behavior; sendData?: (data: unknown) => Promise; } export async function createMatrixRTCSdk(): Promise { @@ -143,7 +145,7 @@ export async function createMatrixRTCSdk(): Promise { // create sendData function const sendFn: Behavior<(data: string) => Promise> = scope.behavior( - callViewModel.localmatrixLivekitMembers$.pipe( + callViewModel.localMatrixLivekitMember$.pipe( switchMap((m) => { if (!m) return of((data: string): never => { @@ -223,6 +225,7 @@ export async function createMatrixRTCSdk(): Promise { livekitRoomItemsSub.unsubscribe(); }, data$, + members$: callViewModel.matrixLivekitMembers$, sendData, }; } diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index a4738f77f..86def81e0 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -264,7 +264,8 @@ export interface CallViewModel { livekitRoomItems$: Behavior; /** use the layout instead, this is just for the godot export. */ userMedia$: Behavior; - localmatrixLivekitMembers$: Behavior; + matrixLivekitMembers$: Behavior; + localMatrixLivekitMember$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ @@ -446,7 +447,7 @@ export function createCallViewModel$( }, ), ), - logger: logger, + logger, }); const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ @@ -488,6 +489,9 @@ export function createCallViewModel$( mediaDevices, muteStates, trackProcessorState$, + logger.getChild( + "[Publisher " + connection.transport.livekit_service_url + "]", + ), ); }, connectionManager: connectionManager, @@ -515,7 +519,7 @@ export function createCallViewModel$( userId: userId, }; - const localmatrixLivekitMembers$: Behavior = + const localMatrixLivekitMember$: Behavior = scope.behavior( localRtcMembership$.pipe( switchMap((membership) => { @@ -685,7 +689,7 @@ export function createCallViewModel$( */ const userMedia$ = scope.behavior( combineLatest([ - localmatrixLivekitMembers$, + localMatrixLivekitMember$, matrixLivekitMembers$, duplicateTiles.value$, ]).pipe( @@ -1518,7 +1522,16 @@ export function createCallViewModel$( pip$: pip$, layout$: layout$, userMedia$, - localmatrixLivekitMembers$, + localMatrixLivekitMember$, + matrixLivekitMembers$: scope.behavior( + matrixLivekitMembers$.pipe( + // TODO flatten this so its not a obs of obs. + map((members) => members.value), + tap((v) => { + logger.debug("matrixLivekitMembers$ updated (exported)", v); + }), + ), + ), tileStoreGeneration$: tileStoreGeneration$, showSpotlightIndicators$: showSpotlightIndicators$, showSpeakingIndicators$: showSpeakingIndicators$, diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 2508637ee..51082f384 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -58,7 +58,7 @@ export class Publisher { trackerProcessorState$: Behavior, private logger: Logger, ) { - this.logger.info("[PublishConnection] Create LiveKit room"); + this.logger.info("Create LiveKit room"); const { controlledAudioDevices } = getUrlParams(); const room = connection.livekitRoom; @@ -74,9 +74,7 @@ export class Publisher { this.workaroundRestartAudioInputTrackChrome(devices, scope); this.scope.onEnd(() => { - this.logger.info( - "[PublishConnection] Scope ended -> stop publishing all tracks", - ); + this.logger.info("Scope ended -> stop publishing all tracks"); void this.stopPublishing(); }); } diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index 0fb0b5a79..4d4a23cbb 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -13,6 +13,7 @@ import { type BaseKeyProvider, } from "livekit-client"; import { type Logger } from "matrix-js-sdk/lib/logger"; +// imported as inline to support worker when loaded from a cdn (cross domain) import E2EEWorker from "livekit-client/e2ee-worker?worker&inline"; import { type ObservableScope } from "../../ObservableScope.ts"; From 1490359e4c29743916c065c90f9a3267b0383ad2 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 1 Dec 2025 14:05:41 +0100 Subject: [PATCH 05/12] cleanup changes `godot`->`sdk` add docs --- godot/README.md | 14 --------- godot/favicon.ico | Bin 2439 -> 0 bytes index.html | 10 ------ package.json | 4 +-- sdk/README.md | 35 +++++++++++++++++++++ {godot => sdk}/helper.ts | 4 +++ {godot => sdk}/index.html | 4 +-- {godot => sdk}/main.ts | 15 ++++++++- src/state/CallViewModel/CallViewModel.ts | 2 +- tsconfig.json | 2 +- vite-godot.config.js => vite-sdk.config.js | 8 ++--- vite.config.ts | 6 ++-- 12 files changed, 66 insertions(+), 38 deletions(-) delete mode 100644 godot/README.md delete mode 100644 godot/favicon.ico create mode 100644 sdk/README.md rename {godot => sdk}/helper.ts (94%) rename {godot => sdk}/index.html (95%) rename {godot => sdk}/main.ts (94%) rename vite-godot.config.js => vite-sdk.config.js (83%) diff --git a/godot/README.md b/godot/README.md deleted file mode 100644 index 7f00df247..000000000 --- a/godot/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## url parameters -widgetId = $matrix_widget_id -perParticipantE2EE = true -userId = $matrix_user_id -deviceId = $org.matrix.msc3819.matrix_device_id -baseUrl = $org.matrix.msc4039.matrix_base_url - -parentUrl = // will be inserted automatically - -http://localhost?widgetId=&perParticipantE2EE=true&userId=&deviceId=&baseUrl=&roomId= - --> - -http://localhost:3000?widgetId=$matrix_widget_id&perParticipantE2EE=true&userId=$matrix_user_id&deviceId=$org.matrix.msc3819.matrix_device_id&baseUrl=$org.matrix.msc4039.matrix_base_url&roomId=$matrix_room_id diff --git a/godot/favicon.ico b/godot/favicon.ico deleted file mode 100644 index e531e6f274fb3efb29316f441b7057f745758ee3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2439 zcmV;233&F2P)Z$GcPbOEG;=TH6tA!@bK^{BqcdBG?S8&>FMb?FE2SUFU3Q#V=xG9ka78TU#cFhb(k-UtL`c-rg}yO*KbGH9$WU z($gQMqzLQkBcGooii#Y(yDNHmDr#vv5D=G@mOK|3q{gO@000PrNklX?LPZ z5I|*V5jQ}Eh+9n5?29HbW|_SF|9|y@CI*$Is@oY-r0>_snIrdf7u8h-6bcfFL?V$$ zBoc{4B9TZW63LosXV9%o`c`j=)t^+lgH9>yU-k2-4l2{3X*echy7r0AnCTeiu>aqn zn)UDdF;vHsq3bYBiKeVG#~qFaa)}ihN7jd^a*U`o8gtBP_g62lQr9xfxD~Z4%yg#X zgRFmZMsy}7+|&x)(MOG}e|H89EQ8@ptzd5dFzes`j~Vm~U&J#WD;j7ip)ws)#SuEPxk)5_WD zx}gguS2ep9`)_QRt1#cemKV11E@yw@ZRtvm(s^-L*Q)yB$NzhdY&C>k-Kna2<0brs zrsQNNR%6TSKx+3NuGIT_(%P zL9_i@6guW?xKgiDQ_?SVE9>j#;Yg^A+5J-{WHnwCUd6D zGIAggv0A6wuGEBPMFbkLr6q7HjBur*7S>19qIE;$R;Ad_yRK#}-2b7G%C#=I!@Ga8 z>ngDe7Kuw~a;wkVfA(J^T&d6Slyn6nRADaho(h|{QLfZGSji!5D{BRCx}4#?`6tqq z`iB0W+>5LofU)?F(B5UVtJE&oE{x0^Qk8EP1_KR|q<6t~F|(EcWz4k;mjexv0J>m1 zxK!%PXFT`9TC6Ko<7g3)xgYW*S+$3gI9CgNe5X^W>2SzOa0TpwZPTVPgT#?Id=7s^ z1MGrr;m}APCg|!+U0cMvQZLadX#o2#YY!msuDm2yDn82!(56{?fKbBDf|R{klB?M} zmn_B2S_A}ad@nZ>T_L()o3ts6)F4yRvY+fqeSP=1f)g?*~-m{w? zHZwKHS(^ZW%HPX&nyV!z^T*d?-*46s9WfHO!ycyOu-T+fW^w*>S@ZpmO$ky)qVRwT zSzAqdh_RQ`>!$4k@>CLqctqxaceUapj6t&ctWBhI0G74Wq{jd_136i%NT&*x^}gMt z#{ekHw}1WvDh+6vRLIpeU>g#sJ3wWP4|CICRnSzgm_-aWsdjXfcz+DIIvfhC$^-Sd6#^65OWS+U6@ zW&)5zi3ZaNE7m;QKfZmOC$tU2t}suTktqJ5hq}wbro2xNV^=6wG|I|+GcKmzfIl}U7h3hphBd{THu?JtjEu1eK1G6()(F^0D&J2 z3GkB6i*p-2&qm^A$UCc?bOxH?T~Qf1;*0RD_{?GEbIeH+sK76Acx2h}u9_UP4rE>) z!ZUzdiA@6_qE#*5E4f{?5E4xJe&@L!tT}2KPoNd%GWYBjAeK+f@p z1-MdUhf5BqfredZCGX!rUj<)(2)Vivb7fLG6^4PP58*D@73XuSpOB31D}XPe4wW2U z-i2PrOsAS00c<0NUSuw|uIO&U0N9sNynVUSsr0|1=|Cn-zus;%=XsAx7?Z-_Oak3> zTi)rHE3tT`v}sjlBABG!675wNZ1!Fh4DLDjETokZpu1a16?9z$i>|r&HAvZ;8u?Qx;9Zc$Je6s}%~3#Lv(*AGrq_a_B0>mObYlXb8Fb z`A>j>NwVd=&N&Af*5vG?tW_mG%6q=x9%Q}T?7z1$}D4F)I!SMbZ*yD*LB2b=&@dqN*B+QseXEVOS>X$yY(H;iuNbPImb8SZUy zxfb#A6@VjWFG&PrIbT*Qs%PSRQ8z}pO4<`Rv)H}sXUudBy?53
<% } %> - - - <% if (packageType === "godot") { %> - - - - <% } %> diff --git a/package.json b/package.json index c87d5b01c..0b598e97c 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "build:embedded": "yarn build:full --config vite-embedded.config.js", "build:embedded:production": "yarn build:embedded", "build:embedded:development": "yarn build:embedded --mode development", - "build:godot": "yarn build:full --config vite-godot.config.js", - "build:godot:development": "yarn build:godot --mode development", + "build:sdk": "yarn build:full --config vite-sdk.config.js", + "build:sdk:development": "yarn build:sdk --mode development", "serve": "vite preview", "prettier:check": "prettier -c .", "prettier:format": "prettier -w .", diff --git a/sdk/README.md b/sdk/README.md new file mode 100644 index 000000000..03801b836 --- /dev/null +++ b/sdk/README.md @@ -0,0 +1,35 @@ +# SDK mode + +EC can be build in sdk mode. This will result in a compiled js file that can be imported in very simple webapps. + +It allows to use matrixRTC in combination with livekit without relying on element call. + +This is done by instantiating the call view model and exposing some useful behaviors (observables) and methods. + +This folder contains an example index.html file that showcases the sdk in use (hosted on localhost:8123 with a webserver ellowing cors (for example `npx serve -l 81234 --cors`)) as a godot engine HTML export template. + +## Widgets + +The sdk mode is particularly interesting to be used in widgets where you do not need to pay attention to matrix login/cs api ... +To create a widget see the example index.html file in this folder. And add it to EW via: +`/addwidget ` (see **url parameters** for more details on ``) + +### url parameters + +``` +widgetId = $matrix_widget_id +perParticipantE2EE = true +userId = $matrix_user_id +deviceId = $org.matrix.msc3819.matrix_device_id +baseUrl = $org.matrix.msc4039.matrix_base_url +``` + +`parentUrl = // will be inserted automatically` + +Full template use as ``: + +``` +http://localhost:3000?widgetId=$matrix_widget_id&perParticipantE2EE=true&userId=$matrix_user_id&deviceId=$org.matrix.msc3819.matrix_device_id&baseUrl=$org.matrix.msc4039.matrix_base_url&roomId=$matrix_room_id +``` + +the `$` prefixed variables will be replaced by EW on widget instantiation. (e.g. `$matrix_user_id` -> `@user:example.com` (url encoding will also be applied automatically by EW) -> `%40user%3Aexample.com`) diff --git a/godot/helper.ts b/sdk/helper.ts similarity index 94% rename from godot/helper.ts rename to sdk/helper.ts index 8f5c710e5..7dc2138aa 100644 --- a/godot/helper.ts +++ b/sdk/helper.ts @@ -5,6 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ +/** + * This file contains helper functions and types for the MatrixRTC SDK. + */ + import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { scan } from "rxjs"; diff --git a/godot/index.html b/sdk/index.html similarity index 95% rename from godot/index.html rename to sdk/index.html index 39bcf4842..c66274ff2 100644 --- a/godot/index.html +++ b/sdk/index.html @@ -4,8 +4,8 @@ Godot MatrixRTC Widget +
- -
-
+
+
+ + +
+
+
diff --git a/sdk/main.ts b/sdk/main.ts index 9c81ab2f2..205ec0600 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -18,12 +18,25 @@ Please see LICENSE in the repository root for full details. * - setting up encryption and scharing keys */ -import { map, type Observable, of, Subject, switchMap, tap } from "rxjs"; -import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc"; -import { type TextStreamInfo } from "livekit-client/dist/src/room/types"; +import { + combineLatest, + map, + type Observable, + of, + shareReplay, + Subject, + switchMap, + tap, +} from "rxjs"; +import { + type CallMembership, + MatrixRTCSessionEvent, +} from "matrix-js-sdk/lib/matrixrtc"; import { type Room as LivekitRoom, type TextStreamReader, + type LocalParticipant, + type RemoteParticipant, } from "livekit-client"; import { type Behavior, constant } from "../src/state/Behavior"; @@ -42,14 +55,23 @@ import { widget, } from "./helper"; import { ElementWidgetActions } from "../src/widget"; -import { type MatrixLivekitMember } from "../src/state/CallViewModel/remoteMembers/MatrixLivekitMembers"; +import { type Connection } from "../src/state/CallViewModel/remoteMembers/Connection"; interface MatrixRTCSdk { join: () => LocalMemberConnectionState; /** @throws on leave errors */ leave: () => void; data$: Observable<{ sender: string; data: string }>; - members$: Behavior; + /** + * flattened list of members + */ + members$: Behavior< + { + connection: Connection | null; + membership: CallMembership; + participant: LocalParticipant | RemoteParticipant | null; + }[] + >; /** Use the LocalMemberConnectionState returned from `join` for a more detailed connection state */ connected$: Behavior; sendData?: (data: unknown) => Promise; @@ -242,7 +264,30 @@ export async function createMatrixRTCSdk(): Promise { }, data$, connected$: callViewModel.connected$, - members$: callViewModel.matrixLivekitMembers$, + members$: scope.behavior( + callViewModel.matrixLivekitMembers$.pipe( + switchMap((members) => { + const listOfMemberObservables = members.map((member) => + combineLatest([ + member.connection$, + member.membership$, + member.participant$, + ]).pipe( + map(([connection, membership, participant]) => ({ + connection, + membership, + participant, + })), + // using shareReplay instead of a Behavior here because the behavior would need + // a tricky scope.end() setup. + shareReplay({ bufferSize: 1, refCount: true }), + ), + ); + return combineLatest(listOfMemberObservables); + }), + ), + [], + ), sendData, }; } diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index ba83203cb..4fb1c35af 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -1519,7 +1519,6 @@ export function createCallViewModel$( localMatrixLivekitMember$, matrixLivekitMembers$: scope.behavior( matrixLivekitMembers$.pipe( - // TODO flatten this so its not a obs of obs. map((members) => members.value), tap((v) => { logger.debug("matrixLivekitMembers$ updated (exported)", v); diff --git a/vite-sdk.config.js b/vite-sdk.config.js index 13b46bd6f..ac1e4de31 100644 --- a/vite-sdk.config.js +++ b/vite-sdk.config.js @@ -6,26 +6,27 @@ Please see LICENSE in the repository root for full details. */ import { defineConfig, mergeConfig } from "vite"; -import fullConfig from "./vite.config"; +import nodePolyfills from "vite-plugin-node-stdlib-browser"; const base = "./"; // Config for embedded deployments (possibly hosted under a non-root path) -export default defineConfig((env) => +export default defineConfig(() => mergeConfig( - fullConfig({ ...env, packageType: "sdk" }), defineConfig({ + worker: { format: "es" }, base, // Use relative URLs to allow the app to be hosted under any path - // publicDir: false, // Don't serve the public directory which only contains the favicon build: { + sourcemap: true, manifest: true, lib: { + formats: ["es"], entry: "./sdk/main.ts", - name: "matrixrtc-sdk", - // the proper extensions will be added + name: "MatrixrtcSdk", fileName: "matrixrtc-sdk", }, }, + plugins: [nodePolyfills()], }), ), ); diff --git a/vite.config.ts b/vite.config.ts index 2f8c72c11..97d643ec4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -27,7 +27,7 @@ import * as fs from "node:fs"; export default ({ mode, packageType, -}: ConfigEnv & { packageType?: "full" | "embedded" | "sdk" }): UserConfig => { +}: ConfigEnv & { packageType?: "full" | "embedded" }): UserConfig => { const env = loadEnv(mode, process.cwd()); // Environment variables with the VITE_ prefix are accessible at runtime. // So, we set this to allow for build/package specific behavior. @@ -68,7 +68,7 @@ export default ({ plugins.push( createHtmlPlugin({ - entry: packageType === "sdk" ? "sdk/main.ts" : "src/main.tsx", + entry: "src/main.tsx", inject: { data: { brand: env.VITE_PRODUCT_NAME || "Element Call", @@ -125,15 +125,10 @@ export default ({ // Default naming fallback return "assets/[name]-[hash][extname]"; }, - manualChunks: - packageType !== "sdk" - ? { - // we should be able to remove this one https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands - "matrix-sdk-crypto-wasm": [ - "@matrix-org/matrix-sdk-crypto-wasm", - ], - } - : undefined, + manualChunks: { + // we should be able to remove this one https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands + "matrix-sdk-crypto-wasm": ["@matrix-org/matrix-sdk-crypto-wasm"], + }, }, }, }, diff --git a/yarn.lock b/yarn.lock index 94b731302..4e5eff653 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2711,6 +2711,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" @@ -4479,6 +4486,22 @@ __metadata: languageName: node linkType: hard +"@rollup/plugin-inject@npm:^5.0.3": + version: 5.0.5 + resolution: "@rollup/plugin-inject@npm:5.0.5" + dependencies: + "@rollup/pluginutils": "npm:^5.0.1" + estree-walker: "npm:^2.0.2" + magic-string: "npm:^0.30.3" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/22d10cf44fa56a6683d5ac4df24a9003379b3dcaae9897f5c30c844afc2ebca83cfaa5557f13a1399b1c8a0d312c3217bcacd508b7ebc4b2cbee401bd1ec8be2 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^4.2.0": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" @@ -4489,6 +4512,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.0.1": + version: 5.3.0 + resolution: "@rollup/pluginutils@npm:5.3.0" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/001834bf62d7cf5bac424d2617c113f7f7d3b2bf3c1778cbcccb72cdc957b68989f8e7747c782c2b911f1dde8257f56f8ac1e779e29e74e638e3f1e2cac2bcd0 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^5.1.3": version: 5.1.3 resolution: "@rollup/pluginutils@npm:5.1.3" @@ -6128,6 +6167,30 @@ __metadata: languageName: node linkType: hard +"asn1.js@npm:^4.10.1": + version: 4.10.1 + resolution: "asn1.js@npm:4.10.1" + dependencies: + bn.js: "npm:^4.0.0" + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + checksum: 10c0/afa7f3ab9e31566c80175a75b182e5dba50589dcc738aa485be42bdd787e2a07246a4b034d481861123cbe646a7656f318f4f1cad2e9e5e808a210d5d6feaa88 + languageName: node + linkType: hard + +"assert@npm:^2.0.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: "npm:^1.0.2" + is-nan: "npm:^1.3.2" + object-is: "npm:^1.1.5" + object.assign: "npm:^4.1.4" + util: "npm:^0.12.5" + checksum: 10c0/7271a5da883c256a1fa690677bf1dd9d6aa882139f2bed1cd15da4f9e7459683e1da8e32a203d6cc6767e5e0f730c77a9532a87b896b4b0af0dd535f668775f0 + languageName: node + linkType: hard + "assertion-error@npm:^2.0.1": version: 2.0.1 resolution: "assertion-error@npm:2.0.1" @@ -6318,6 +6381,20 @@ __metadata: languageName: node linkType: hard +"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9": + version: 4.12.2 + resolution: "bn.js@npm:4.12.2" + checksum: 10c0/09a249faa416a9a1ce68b5f5ec8bbca87fe54e5dd4ef8b1cc8a4969147b80035592bddcb1e9cc814c3ba79e573503d5c5178664b722b509fb36d93620dba9b57 + languageName: node + linkType: hard + +"bn.js@npm:^5.2.1, bn.js@npm:^5.2.2": + version: 5.2.2 + resolution: "bn.js@npm:5.2.2" + checksum: 10c0/cb97827d476aab1a0194df33cd84624952480d92da46e6b4a19c32964aa01553a4a613502396712704da2ec8f831cf98d02e74ca03398404bd78a037ba93f2ab + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -6393,6 +6470,96 @@ __metadata: languageName: node linkType: hard +"brorand@npm:^1.0.1, brorand@npm:^1.1.0": + version: 1.1.0 + resolution: "brorand@npm:1.1.0" + checksum: 10c0/6f366d7c4990f82c366e3878492ba9a372a73163c09871e80d82fb4ae0d23f9f8924cb8a662330308206e6b3b76ba1d528b4601c9ef73c2166b440b2ea3b7571 + languageName: node + linkType: hard + +"browser-resolve@npm:^2.0.0": + version: 2.0.0 + resolution: "browser-resolve@npm:2.0.0" + dependencies: + resolve: "npm:^1.17.0" + checksum: 10c0/06c43adf3cb1939825ab9a4ac355b23272820ee421a20d04f62e0dabd9ea305e497b97f3ac027f87d53c366483aafe8673bbe1aaa5e41cd69eeafa65ac5fda6e + languageName: node + linkType: hard + +"browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": + version: 1.2.0 + resolution: "browserify-aes@npm:1.2.0" + dependencies: + buffer-xor: "npm:^1.0.3" + cipher-base: "npm:^1.0.0" + create-hash: "npm:^1.1.0" + evp_bytestokey: "npm:^1.0.3" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/967f2ae60d610b7b252a4cbb55a7a3331c78293c94b4dd9c264d384ca93354c089b3af9c0dd023534efdc74ffbc82510f7ad4399cf82bc37bc07052eea485f18 + languageName: node + linkType: hard + +"browserify-cipher@npm:^1.0.1": + version: 1.0.1 + resolution: "browserify-cipher@npm:1.0.1" + dependencies: + browserify-aes: "npm:^1.0.4" + browserify-des: "npm:^1.0.0" + evp_bytestokey: "npm:^1.0.0" + checksum: 10c0/aa256dcb42bc53a67168bbc94ab85d243b0a3b56109dee3b51230b7d010d9b78985ffc1fb36e145c6e4db151f888076c1cfc207baf1525d3e375cbe8187fe27d + languageName: node + linkType: hard + +"browserify-des@npm:^1.0.0": + version: 1.0.2 + resolution: "browserify-des@npm:1.0.2" + dependencies: + cipher-base: "npm:^1.0.1" + des.js: "npm:^1.0.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/943eb5d4045eff80a6cde5be4e5fbb1f2d5002126b5a4789c3c1aae3cdddb1eb92b00fb92277f512288e5c6af330730b1dbabcf7ce0923e749e151fcee5a074d + languageName: node + linkType: hard + +"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.1": + version: 4.1.1 + resolution: "browserify-rsa@npm:4.1.1" + dependencies: + bn.js: "npm:^5.2.1" + randombytes: "npm:^2.1.0" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/b650ee1192e3d7f3d779edc06dd96ed8720362e72ac310c367b9d7fe35f7e8dbb983c1829142b2b3215458be8bf17c38adc7224920843024ed8cf39e19c513c0 + languageName: node + linkType: hard + +"browserify-sign@npm:^4.2.3": + version: 4.2.5 + resolution: "browserify-sign@npm:4.2.5" + dependencies: + bn.js: "npm:^5.2.2" + browserify-rsa: "npm:^4.1.1" + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + elliptic: "npm:^6.6.1" + inherits: "npm:^2.0.4" + parse-asn1: "npm:^5.1.9" + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6192f9696934bbba58932d098face34c2ab9cac09feed826618b86b8c00a897dab7324cd9aa7d6cb1597064f197264ad72fa5418d4d52bf3c8f9b9e0e124655e + languageName: node + linkType: hard + +"browserify-zlib@npm:^0.2.0": + version: 0.2.0 + resolution: "browserify-zlib@npm:0.2.0" + dependencies: + pako: "npm:~1.0.5" + checksum: 10c0/9ab10b6dc732c6c5ec8ebcbe5cb7fe1467f97402c9b2140113f47b5f187b9438f93a8e065d8baf8b929323c18324fbf1105af479ee86d9d36cab7d7ef3424ad9 + languageName: node + linkType: hard + "browserslist@npm:^4.24.0, browserslist@npm:^4.24.3, browserslist@npm:^4.24.4": version: 4.24.4 resolution: "browserslist@npm:4.24.4" @@ -6437,6 +6604,23 @@ __metadata: languageName: node linkType: hard +"buffer-xor@npm:^1.0.3": + version: 1.0.3 + resolution: "buffer-xor@npm:1.0.3" + checksum: 10c0/fd269d0e0bf71ecac3146187cfc79edc9dbb054e2ee69b4d97dfb857c6d997c33de391696d04bdd669272751fa48e7872a22f3a6c7b07d6c0bc31dbe02a4075c + languageName: node + linkType: hard + +"buffer@npm:^5.7.1": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.1.13" + checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e + languageName: node + linkType: hard + "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -6454,6 +6638,13 @@ __metadata: languageName: node linkType: hard +"builtin-status-codes@npm:^3.0.0": + version: 3.0.0 + resolution: "builtin-status-codes@npm:3.0.0" + checksum: 10c0/c37bbba11a34c4431e56bd681b175512e99147defbe2358318d8152b3a01df7bf25e0305873947e5b350073d5ef41a364a22b37e48f1fb6d2fe6d5286a0f348c + languageName: node + linkType: hard + "bytesish@npm:^0.4.1": version: 0.4.4 resolution: "bytesish@npm:0.4.4" @@ -6508,7 +6699,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -6571,24 +6762,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001701 - resolution: "caniuse-lite@npm:1.0.30001701" - checksum: 10c0/a814bd4dd8b49645ca51bc6ee42120660a36394bb54eb6084801d3f2bbb9471e5e1a9a8a25f44f83086a032d46e66b33031e2aa345f699b90a7e84a9836b819c - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001702": - version: 1.0.30001720 - resolution: "caniuse-lite@npm:1.0.30001720" - checksum: 10c0/ba9f963364ec4bfc8359d15d7e2cf365185fa1fddc90b4f534c71befedae9b3dd0cd2583a25ffc168a02d7b61b6c18b59bda0a1828ea2a5250fd3e35c2c049e9 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001726": - version: 1.0.30001726 - resolution: "caniuse-lite@npm:1.0.30001726" - checksum: 10c0/2c5f91da7fd9ebf8c6b432818b1498ea28aca8de22b30dafabe2a2a6da1e014f10e67e14f8e68e872a0867b6b4cd6001558dde04e3ab9770c9252ca5c8849d0e +"caniuse-lite@npm:^1.0.30001688, caniuse-lite@npm:^1.0.30001702, caniuse-lite@npm:^1.0.30001726": + version: 1.0.30001757 + resolution: "caniuse-lite@npm:1.0.30001757" + checksum: 10c0/3ccb71fa2bf1f8c96ff1bf9b918b08806fed33307e20a3ce3259155fda131eaf96cfcd88d3d309c8fd7f8285cc71d89a3b93648a1c04814da31c301f98508d42 languageName: node linkType: hard @@ -6722,6 +6899,17 @@ __metadata: languageName: node linkType: hard +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": + version: 1.0.7 + resolution: "cipher-base@npm:1.0.7" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.2" + checksum: 10c0/53c5046a9d9b60c586479b8f13fde263c3f905e13f11e8e04c7a311ce399c91d9c3ec96642332e0de077d356e1014ee12bba96f74fbaad0de750f49122258836 + languageName: node + linkType: hard + "classnames@npm:^2.3.1, classnames@npm:^2.5.1": version: 2.5.1 resolution: "classnames@npm:2.5.1" @@ -6885,6 +7073,20 @@ __metadata: languageName: node linkType: hard +"console-browserify@npm:^1.1.0": + version: 1.2.0 + resolution: "console-browserify@npm:1.2.0" + checksum: 10c0/89b99a53b7d6cee54e1e64fa6b1f7ac24b844b4019c5d39db298637e55c1f4ffa5c165457ad984864de1379df2c8e1886cbbdac85d9dbb6876a9f26c3106f226 + languageName: node + linkType: hard + +"constants-browserify@npm:^1.0.0": + version: 1.0.0 + resolution: "constants-browserify@npm:1.0.0" + checksum: 10c0/ab49b1d59a433ed77c964d90d19e08b2f77213fb823da4729c0baead55e3c597f8f97ebccfdfc47bd896d43854a117d114c849a6f659d9986420e97da0f83ac5 + languageName: node + linkType: hard + "content-type@npm:^1.0.4": version: 1.0.5 resolution: "content-type@npm:1.0.5" @@ -6957,6 +7159,50 @@ __metadata: languageName: node linkType: hard +"create-ecdh@npm:^4.0.4": + version: 4.0.4 + resolution: "create-ecdh@npm:4.0.4" + dependencies: + bn.js: "npm:^4.1.0" + elliptic: "npm:^6.5.3" + checksum: 10c0/77b11a51360fec9c3bce7a76288fc0deba4b9c838d5fb354b3e40c59194d23d66efe6355fd4b81df7580da0661e1334a235a2a5c040b7569ba97db428d466e7f + languageName: node + linkType: hard + +"create-hash@npm:^1.1.0, create-hash@npm:^1.2.0": + version: 1.2.0 + resolution: "create-hash@npm:1.2.0" + dependencies: + cipher-base: "npm:^1.0.1" + inherits: "npm:^2.0.1" + md5.js: "npm:^1.3.4" + ripemd160: "npm:^2.0.1" + sha.js: "npm:^2.4.0" + checksum: 10c0/d402e60e65e70e5083cb57af96d89567954d0669e90550d7cec58b56d49c4b193d35c43cec8338bc72358198b8cbf2f0cac14775b651e99238e1cf411490f915 + languageName: node + linkType: hard + +"create-hmac@npm:^1.1.7": + version: 1.1.7 + resolution: "create-hmac@npm:1.1.7" + dependencies: + cipher-base: "npm:^1.0.3" + create-hash: "npm:^1.1.0" + inherits: "npm:^2.0.1" + ripemd160: "npm:^2.0.0" + safe-buffer: "npm:^5.0.1" + sha.js: "npm:^2.4.8" + checksum: 10c0/24332bab51011652a9a0a6d160eed1e8caa091b802335324ae056b0dcb5acbc9fcf173cf10d128eba8548c3ce98dfa4eadaa01bd02f44a34414baee26b651835 + languageName: node + linkType: hard + +"create-require@npm:^1.1.1": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.2": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -6979,6 +7225,26 @@ __metadata: languageName: node linkType: hard +"crypto-browserify@npm:^3.12.1": + version: 3.12.1 + resolution: "crypto-browserify@npm:3.12.1" + dependencies: + browserify-cipher: "npm:^1.0.1" + browserify-sign: "npm:^4.2.3" + create-ecdh: "npm:^4.0.4" + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + diffie-hellman: "npm:^5.0.3" + hash-base: "npm:~3.0.4" + inherits: "npm:^2.0.4" + pbkdf2: "npm:^3.1.2" + public-encrypt: "npm:^4.0.3" + randombytes: "npm:^2.1.0" + randomfill: "npm:^1.0.4" + checksum: 10c0/184a2def7b16628e79841243232ab5497f18d8e158ac21b7ce90ab172427d0a892a561280adc08f9d4d517bce8db2a5b335dc21abb970f787f8e874bd7b9db7d + languageName: node + linkType: hard + "css-blank-pseudo@npm:^7.0.1": version: 7.0.1 resolution: "css-blank-pseudo@npm:7.0.1" @@ -7267,6 +7533,16 @@ __metadata: languageName: node linkType: hard +"des.js@npm:^1.0.0": + version: 1.1.0 + resolution: "des.js@npm:1.1.0" + dependencies: + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + checksum: 10c0/671354943ad67493e49eb4c555480ab153edd7cee3a51c658082fcde539d2690ed2a4a0b5d1f401f9cde822edf3939a6afb2585f32c091f2d3a1b1665cd45236 + languageName: node + linkType: hard + "detect-libc@npm:^1.0.3": version: 1.0.3 resolution: "detect-libc@npm:1.0.3" @@ -7283,6 +7559,17 @@ __metadata: languageName: node linkType: hard +"diffie-hellman@npm:^5.0.3": + version: 5.0.3 + resolution: "diffie-hellman@npm:5.0.3" + dependencies: + bn.js: "npm:^4.1.0" + miller-rabin: "npm:^4.0.0" + randombytes: "npm:^2.0.0" + checksum: 10c0/ce53ccafa9ca544b7fc29b08a626e23a9b6562efc2a98559a0c97b4718937cebaa9b5d7d0a05032cc9c1435e9b3c1532b9e9bf2e0ede868525922807ad6e1ecf + languageName: node + linkType: hard + "dijkstrajs@npm:^1.0.1": version: 1.0.3 resolution: "dijkstrajs@npm:1.0.3" @@ -7353,6 +7640,13 @@ __metadata: languageName: node linkType: hard +"domain-browser@npm:4.22.0": + version: 4.22.0 + resolution: "domain-browser@npm:4.22.0" + checksum: 10c0/2ef7eda6d2161038fda0c9aa4c9e18cc7a0baa89ea6be975d449527c2eefd4b608425db88508e2859acc472f46f402079274b24bd75e3fb506f28c5dba203129 + languageName: node + linkType: hard + "domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0, domelementtype@npm:^2.3.0": version: 2.3.0 resolution: "domelementtype@npm:2.3.0" @@ -7549,6 +7843,7 @@ __metadata: loglevel: "npm:^1.9.1" matrix-js-sdk: "npm:^39.2.0" matrix-widget-api: "npm:^1.14.0" + node-stdlib-browser: "npm:^1.3.1" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" pako: "npm:^2.0.4" @@ -7571,12 +7866,29 @@ __metadata: vite: "npm:^7.0.0" vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" + vite-plugin-node-stdlib-browser: "npm:^0.2.1" + vite-plugin-singlefile: "npm:^2.3.0" vite-plugin-svgr: "npm:^4.0.0" vitest: "npm:^3.0.0" vitest-axe: "npm:^1.0.0-pre.3" languageName: unknown linkType: soft +"elliptic@npm:^6.5.3, elliptic@npm:^6.6.1": + version: 6.6.1 + resolution: "elliptic@npm:6.6.1" + dependencies: + bn.js: "npm:^4.11.9" + brorand: "npm:^1.1.0" + hash.js: "npm:^1.0.0" + hmac-drbg: "npm:^1.0.1" + inherits: "npm:^2.0.4" + minimalistic-assert: "npm:^1.0.1" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -8388,13 +8700,24 @@ __metadata: languageName: node linkType: hard -"events@npm:^3.2.0, events@npm:^3.3.0": +"events@npm:^3.0.0, events@npm:^3.2.0, events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 languageName: node linkType: hard +"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": + version: 1.0.3 + resolution: "evp_bytestokey@npm:1.0.3" + dependencies: + md5.js: "npm:^1.3.4" + node-gyp: "npm:latest" + safe-buffer: "npm:^5.1.1" + checksum: 10c0/77fbe2d94a902a80e9b8f5a73dcd695d9c14899c5e82967a61b1fc6cbbb28c46552d9b127cff47c45fcf684748bdbcfa0a50410349109de87ceb4b199ef6ee99 + languageName: node + linkType: hard + "expect-type@npm:^1.2.1": version: 1.2.1 resolution: "expect-type@npm:1.2.1" @@ -8790,6 +9113,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10c0/8a9f59df0f01cfefafdb3b451b80555e5cf6d76487095db91ac461a0e682e4ff7a9dbce15f4ecec191e53586d59eece01949e05a4b4492879600bbbe8e28d6b8 + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9092,6 +9422,38 @@ __metadata: languageName: node linkType: hard +"hash-base@npm:^3.0.0, hash-base@npm:^3.1.2": + version: 3.1.2 + resolution: "hash-base@npm:3.1.2" + dependencies: + inherits: "npm:^2.0.4" + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.1" + checksum: 10c0/f3b7fae1853b31340048dd659f40f5260ca6f3ff53b932f807f4ab701ee09039f6e9dbe1841723ff61e20f3f69d6387a352e4ccc5f997dedb0d375c7d88bc15e + languageName: node + linkType: hard + +"hash-base@npm:~3.0.4": + version: 3.0.5 + resolution: "hash-base@npm:3.0.5" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6dc185b79bad9b6d525cd132a588e4215380fdc36fec6f7a8a58c5db8e3b642557d02ad9c367f5e476c7c3ad3ccffa3607f308b124e1ed80e3b80a1b254db61e + languageName: node + linkType: hard + +"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": + version: 1.1.7 + resolution: "hash.js@npm:1.1.7" + dependencies: + inherits: "npm:^2.0.3" + minimalistic-assert: "npm:^1.0.1" + checksum: 10c0/41ada59494eac5332cfc1ce6b7ebdd7b88a3864a6d6b08a3ea8ef261332ed60f37f10877e0c825aaa4bddebf164fbffa618286aeeec5296675e2671cbfa746c4 + languageName: node + linkType: hard + "hasown@npm:^2.0.0, hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" @@ -9129,6 +9491,17 @@ __metadata: languageName: node linkType: hard +"hmac-drbg@npm:^1.0.1": + version: 1.0.1 + resolution: "hmac-drbg@npm:1.0.1" + dependencies: + hash.js: "npm:^1.0.3" + minimalistic-assert: "npm:^1.0.0" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/f3d9ba31b40257a573f162176ac5930109816036c59a09f901eb2ffd7e5e705c6832bedfff507957125f2086a0ab8f853c0df225642a88bf1fcaea945f20600d + languageName: node + linkType: hard + "hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" @@ -9216,6 +9589,13 @@ __metadata: languageName: node linkType: hard +"https-browserify@npm:^1.0.0": + version: 1.0.0 + resolution: "https-browserify@npm:1.0.0" + checksum: 10c0/e17b6943bc24ea9b9a7da5714645d808670af75a425f29baffc3284962626efdc1eb3aa9bbffaa6e64028a6ad98af5b09fabcb454a8f918fb686abfdc9e9b8ae + languageName: node + linkType: hard + "https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" @@ -9295,7 +9675,7 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.2.1": +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb @@ -9357,7 +9737,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -9385,6 +9765,16 @@ __metadata: languageName: node linkType: hard +"is-arguments@npm:^1.0.4": + version: 1.2.0 + resolution: "is-arguments@npm:1.2.0" + dependencies: + call-bound: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/6377344b31e9fcb707c6751ee89b11f132f32338e6a782ec2eac9393b0cbd32235dad93052998cda778ee058754860738341d8114910d50ada5615912bb929fc + languageName: node + linkType: hard + "is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": version: 3.0.5 resolution: "is-array-buffer@npm:3.0.5" @@ -9524,6 +9914,19 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.7": + version: 1.1.2 + resolution: "is-generator-function@npm:1.1.2" + dependencies: + call-bound: "npm:^1.0.4" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/83da102e89c3e3b71d67b51d47c9f9bc862bceb58f87201727e27f7fa19d1d90b0ab223644ecaee6fc6e3d2d622bb25c966fbdaf87c59158b01ce7c0fe2fa372 + languageName: node + linkType: hard + "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -9540,6 +9943,16 @@ __metadata: languageName: node linkType: hard +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: "npm:^1.0.0" + define-properties: "npm:^1.1.3" + checksum: 10c0/8bfb286f85763f9c2e28ea32e9127702fe980ffd15fa5d63ade3be7786559e6e21355d3625dd364c769c033c5aedf0a2ed3d4025d336abf1b9241e3d9eddc5b0 + languageName: node + linkType: hard + "is-negated-glob@npm:^1.0.0": version: 1.0.0 resolution: "is-negated-glob@npm:1.0.0" @@ -9662,7 +10075,7 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15": +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15, is-typed-array@npm:^1.1.3": version: 1.1.15 resolution: "is-typed-array@npm:1.1.15" dependencies: @@ -9741,6 +10154,13 @@ __metadata: languageName: node linkType: hard +"isomorphic-timers-promises@npm:^1.0.1": + version: 1.0.1 + resolution: "isomorphic-timers-promises@npm:1.0.1" + checksum: 10c0/3b4761d0012ebe6b6382246079fc667f3513f36fe4042638f2bfb7db1557e4f1acd33a9c9907706c04270890ec6434120f132f3f300161a42a7dd8628926c8a4 + languageName: node + linkType: hard + "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" @@ -10289,6 +10709,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.3": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + languageName: node + linkType: hard + "magicast@npm:^0.3.5": version: 0.3.5 resolution: "magicast@npm:0.3.5" @@ -10384,6 +10813,17 @@ __metadata: languageName: node linkType: hard +"md5.js@npm:^1.3.4": + version: 1.3.5 + resolution: "md5.js@npm:1.3.5" + dependencies: + hash-base: "npm:^3.0.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/b7bd75077f419c8e013fc4d4dada48be71882e37d69a44af65a2f2804b91e253441eb43a0614423a1c91bb830b8140b0dc906bc797245e2e275759584f4efcc5 + languageName: node + linkType: hard + "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -10401,6 +10841,18 @@ __metadata: languageName: node linkType: hard +"miller-rabin@npm:^4.0.0": + version: 4.0.1 + resolution: "miller-rabin@npm:4.0.1" + dependencies: + bn.js: "npm:^4.0.0" + brorand: "npm:^1.0.1" + bin: + miller-rabin: bin/miller-rabin + checksum: 10c0/26b2b96f6e49dbcff7faebb78708ed2f5f9ae27ac8cbbf1d7c08f83cf39bed3d418c0c11034dce997da70d135cc0ff6f3a4c15dc452f8e114c11986388a64346 + languageName: node + linkType: hard + "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -10424,6 +10876,20 @@ __metadata: languageName: node linkType: hard +"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-assert@npm:1.0.1" + checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd + languageName: node + linkType: hard + +"minimalistic-crypto-utils@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-crypto-utils@npm:1.0.1" + checksum: 10c0/790ecec8c5c73973a4fbf2c663d911033e8494d5fb0960a4500634766ab05d6107d20af896ca2132e7031741f19888154d44b2408ada0852446705441383e9f8 + languageName: node + linkType: hard + "minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -10674,6 +11140,41 @@ __metadata: languageName: node linkType: hard +"node-stdlib-browser@npm:^1.3.1": + version: 1.3.1 + resolution: "node-stdlib-browser@npm:1.3.1" + dependencies: + assert: "npm:^2.0.0" + browser-resolve: "npm:^2.0.0" + browserify-zlib: "npm:^0.2.0" + buffer: "npm:^5.7.1" + console-browserify: "npm:^1.1.0" + constants-browserify: "npm:^1.0.0" + create-require: "npm:^1.1.1" + crypto-browserify: "npm:^3.12.1" + domain-browser: "npm:4.22.0" + events: "npm:^3.0.0" + https-browserify: "npm:^1.0.0" + isomorphic-timers-promises: "npm:^1.0.1" + os-browserify: "npm:^0.3.0" + path-browserify: "npm:^1.0.1" + pkg-dir: "npm:^5.0.0" + process: "npm:^0.11.10" + punycode: "npm:^1.4.1" + querystring-es3: "npm:^0.2.1" + readable-stream: "npm:^3.6.0" + stream-browserify: "npm:^3.0.0" + stream-http: "npm:^3.2.0" + string_decoder: "npm:^1.0.0" + timers-browserify: "npm:^2.0.4" + tty-browserify: "npm:0.0.1" + url: "npm:^0.11.4" + util: "npm:^0.12.4" + vm-browserify: "npm:^1.0.1" + checksum: 10c0/5b0cb5d4499b1b1c73f54db3e9e69b2a3a8aebe2ead2e356b0a03c1dfca6b5c5d2f6516e24301e76dc7b68999b9d0ae3da6c3f1dec421eed80ad6cb9eec0f356 + languageName: node + linkType: hard + "nopt@npm:^8.0.0": version: 8.1.0 resolution: "nopt@npm:8.1.0" @@ -10764,6 +11265,16 @@ __metadata: languageName: node linkType: hard +"object-is@npm:^1.1.5": + version: 1.1.6 + resolution: "object-is@npm:1.1.6" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + checksum: 10c0/506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 + languageName: node + linkType: hard + "object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" @@ -10875,6 +11386,13 @@ __metadata: languageName: node linkType: hard +"os-browserify@npm:^0.3.0": + version: 0.3.0 + resolution: "os-browserify@npm:0.3.0" + checksum: 10c0/6ff32cb1efe2bc6930ad0fd4c50e30c38010aee909eba8d65be60af55efd6cbb48f0287e3649b4e3f3a63dce5a667b23c187c4293a75e557f0d5489d735bcf52 + languageName: node + linkType: hard + "own-keys@npm:^1.0.1": version: 1.0.1 resolution: "own-keys@npm:1.0.1" @@ -11007,6 +11525,13 @@ __metadata: languageName: node linkType: hard +"pako@npm:~1.0.5": + version: 1.0.11 + resolution: "pako@npm:1.0.11" + checksum: 10c0/86dd99d8b34c3930345b8bbeb5e1cd8a05f608eeb40967b293f72fe469d0e9c88b783a8777e4cc7dc7c91ce54c5e93d88ff4b4f060e6ff18408fd21030d9ffbe + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -11026,6 +11551,19 @@ __metadata: languageName: node linkType: hard +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.9": + version: 5.1.9 + resolution: "parse-asn1@npm:5.1.9" + dependencies: + asn1.js: "npm:^4.10.1" + browserify-aes: "npm:^1.2.0" + evp_bytestokey: "npm:^1.0.3" + pbkdf2: "npm:^3.1.5" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6dfe27c121be3d63ebbf95f03d2ae0a07dd716d44b70b0bd3458790a822a80de05361c62147271fd7b845dcc2d37755d9c9c393064a3438fe633779df0bc07e7 + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -11076,6 +11614,13 @@ __metadata: languageName: node linkType: hard +"path-browserify@npm:^1.0.1": + version: 1.0.1 + resolution: "path-browserify@npm:1.0.1" + checksum: 10c0/8b8c3fd5c66bd340272180590ae4ff139769e9ab79522e2eb82e3d571a89b8117c04147f65ad066dccfb42fcad902e5b7d794b3d35e0fd840491a8ddbedf8c66 + languageName: node + linkType: hard + "path-exists@npm:^4.0.0": version: 4.0.0 resolution: "path-exists@npm:4.0.0" @@ -11149,6 +11694,20 @@ __metadata: languageName: node linkType: hard +"pbkdf2@npm:^3.1.2, pbkdf2@npm:^3.1.5": + version: 3.1.5 + resolution: "pbkdf2@npm:3.1.5" + dependencies: + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + ripemd160: "npm:^2.0.3" + safe-buffer: "npm:^5.2.1" + sha.js: "npm:^2.4.12" + to-buffer: "npm:^1.2.1" + checksum: 10c0/ea42e8695e49417eefabb19a08ab19a602cc6cc72d2df3f109c39309600230dee3083a6f678d5d42fe035d6ae780038b80ace0e68f9792ee2839bf081fe386f3 + languageName: node + linkType: hard + "picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" @@ -11177,6 +11736,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^5.0.0": + version: 5.0.0 + resolution: "pkg-dir@npm:5.0.0" + dependencies: + find-up: "npm:^5.0.0" + checksum: 10c0/793a496d685dc55bbbdbbb22d884535c3b29241e48e3e8d37e448113a71b9e42f5481a61fdc672d7322de12fbb2c584dd3a68bf89b18fffce5c48a390f911bc5 + languageName: node + linkType: hard + "playwright-core@npm:1.56.1": version: 1.56.1 resolution: "playwright-core@npm:1.56.1" @@ -11673,6 +12241,13 @@ __metadata: languageName: node linkType: hard +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 + languageName: node + linkType: hard + "progress@npm:^2.0.3": version: 2.0.3 resolution: "progress@npm:2.0.3" @@ -11745,6 +12320,27 @@ __metadata: languageName: node linkType: hard +"public-encrypt@npm:^4.0.3": + version: 4.0.3 + resolution: "public-encrypt@npm:4.0.3" + dependencies: + bn.js: "npm:^4.1.0" + browserify-rsa: "npm:^4.0.0" + create-hash: "npm:^1.1.0" + parse-asn1: "npm:^5.0.0" + randombytes: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/6c2cc19fbb554449e47f2175065d6b32f828f9b3badbee4c76585ac28ae8641aafb9bb107afc430c33c5edd6b05dbe318df4f7d6d7712b1093407b11c4280700 + languageName: node + linkType: hard + +"punycode@npm:^1.4.1": + version: 1.4.1 + resolution: "punycode@npm:1.4.1" + checksum: 10c0/354b743320518aef36f77013be6e15da4db24c2b4f62c5f1eb0529a6ed02fbaf1cb52925785f6ab85a962f2b590d9cd5ad730b70da72b5f180e2556b8bd3ca08 + languageName: node + linkType: hard + "punycode@npm:^2.1.0, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -11765,6 +12361,22 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.12.3": + version: 6.14.0 + resolution: "qs@npm:6.14.0" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c + languageName: node + linkType: hard + +"querystring-es3@npm:^0.2.1": + version: 0.2.1 + resolution: "querystring-es3@npm:0.2.1" + checksum: 10c0/476938c1adb45c141f024fccd2ffd919a3746e79ed444d00e670aad68532977b793889648980e7ca7ff5ffc7bfece623118d0fbadcaf217495eeb7059ae51580 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -11783,6 +12395,25 @@ __metadata: languageName: node linkType: hard +"randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: "npm:^5.1.0" + checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 + languageName: node + linkType: hard + +"randomfill@npm:^1.0.4": + version: 1.0.4 + resolution: "randomfill@npm:1.0.4" + dependencies: + randombytes: "npm:^2.0.5" + safe-buffer: "npm:^5.1.0" + checksum: 10c0/11aeed35515872e8f8a2edec306734e6b74c39c46653607f03c68385ab8030e2adcc4215f76b5e4598e028c4750d820afd5c65202527d831d2a5f207fe2bc87c + languageName: node + linkType: hard + "react-dom@npm:19": version: 19.1.0 resolution: "react-dom@npm:19.1.0" @@ -11977,18 +12608,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.4.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 - languageName: node - linkType: hard - -"readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.3.8, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -12003,6 +12623,17 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + "readdirp@npm:^4.0.1": version: 4.1.2 resolution: "readdirp@npm:4.1.2" @@ -12219,6 +12850,19 @@ __metadata: languageName: node linkType: hard +"resolve@npm:^1.17.0": + version: 1.22.11 + resolution: "resolve@npm:1.22.11" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/f657191507530f2cbecb5815b1ee99b20741ea6ee02a59c57028e9ec4c2c8d7681afcc35febbd554ac0ded459db6f2d8153382c53a2f266cee2575e512674409 + languageName: node + linkType: hard + "resolve@npm:^1.22.10": version: 1.22.10 resolution: "resolve@npm:1.22.10" @@ -12258,6 +12902,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^1.17.0#optional!builtin": + version: 1.22.11 + resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/ee5b182f2e37cb1165465e58c6abc797fec0a80b5ba3231607beb4677db0c9291ac010c47cf092b6daa2b7f518d69a0e21888e7e2b633f68d501a874212a8c63 + languageName: node + linkType: hard + "resolve@patch:resolve@npm%3A^1.22.10#optional!builtin": version: 1.22.10 resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" @@ -12331,6 +12988,16 @@ __metadata: languageName: node linkType: hard +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.3": + version: 2.0.3 + resolution: "ripemd160@npm:2.0.3" + dependencies: + hash-base: "npm:^3.1.2" + inherits: "npm:^2.0.4" + checksum: 10c0/3f472fb453241cfe692a77349accafca38dbcdc9d96d5848c088b2932ba41eb968630ecff7b175d291c7487a4945aee5a81e30c064d1f94e36070f7e0c37ed6c + languageName: node + linkType: hard + "rollup@npm:^4.43.0": version: 4.50.1 resolution: "rollup@npm:4.50.1" @@ -12478,6 +13145,13 @@ __metadata: languageName: node linkType: hard +"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + "safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": version: 5.1.2 resolution: "safe-buffer@npm:5.1.2" @@ -12485,13 +13159,6 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - "safe-push-apply@npm:^1.0.0": version: 1.0.0 resolution: "safe-push-apply@npm:1.0.0" @@ -12665,6 +13332,26 @@ __metadata: languageName: node linkType: hard +"setimmediate@npm:^1.0.4": + version: 1.0.5 + resolution: "setimmediate@npm:1.0.5" + checksum: 10c0/5bae81bfdbfbd0ce992893286d49c9693c82b1bcc00dcaaf3a09c8f428fdeacf4190c013598b81875dfac2b08a572422db7df779a99332d0fce186d15a3e4d49 + languageName: node + linkType: hard + +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": + version: 2.4.12 + resolution: "sha.js@npm:2.4.12" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.0" + bin: + sha.js: bin.js + checksum: 10c0/9d36bdd76202c8116abbe152a00055ccd8a0099cb28fc17c01fa7bb2c8cffb9ca60e2ab0fe5f274ed6c45dc2633d8c39cf7ab050306c231904512ba9da4d8ab1 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -12909,6 +13596,16 @@ __metadata: languageName: node linkType: hard +"stream-browserify@npm:^3.0.0": + version: 3.0.0 + resolution: "stream-browserify@npm:3.0.0" + dependencies: + inherits: "npm:~2.0.4" + readable-stream: "npm:^3.5.0" + checksum: 10c0/ec3b975a4e0aa4b3dc5e70ffae3fc8fd29ac725353a14e72f213dff477b00330140ad014b163a8cbb9922dfe90803f81a5ea2b269e1bbfd8bd71511b88f889ad + languageName: node + linkType: hard + "stream-composer@npm:^1.0.2": version: 1.0.2 resolution: "stream-composer@npm:1.0.2" @@ -12918,6 +13615,18 @@ __metadata: languageName: node linkType: hard +"stream-http@npm:^3.2.0": + version: 3.2.0 + resolution: "stream-http@npm:3.2.0" + dependencies: + builtin-status-codes: "npm:^3.0.0" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.6.0" + xtend: "npm:^4.0.2" + checksum: 10c0/f128fb8076d60cd548f229554b6a1a70c08a04b7b2afd4dbe7811d20f27f7d4112562eb8bce86d72a8691df3b50573228afcf1271e55e81f981536c67498bc41 + languageName: node + linkType: hard + "streamx@npm:^2.12.0, streamx@npm:^2.12.5, streamx@npm:^2.13.2, streamx@npm:^2.14.0": version: 2.22.0 resolution: "streamx@npm:2.22.0" @@ -13034,7 +13743,7 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:^1.1.1": +"string_decoder@npm:^1.0.0, string_decoder@npm:^1.1.1": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" dependencies: @@ -13236,6 +13945,15 @@ __metadata: languageName: node linkType: hard +"timers-browserify@npm:^2.0.4": + version: 2.0.12 + resolution: "timers-browserify@npm:2.0.12" + dependencies: + setimmediate: "npm:^1.0.4" + checksum: 10c0/98e84db1a685bc8827c117a8bc62aac811ad56a995d07938fc7ed8cdc5bf3777bfe2d4e5da868847194e771aac3749a20f6cdd22091300fe889a76fe214a4641 + languageName: node + linkType: hard + "tinybench@npm:^2.9.0": version: 2.9.0 resolution: "tinybench@npm:2.9.0" @@ -13309,6 +14027,17 @@ __metadata: languageName: node linkType: hard +"to-buffer@npm:^1.2.0, to-buffer@npm:^1.2.1, to-buffer@npm:^1.2.2": + version: 1.2.2 + resolution: "to-buffer@npm:1.2.2" + dependencies: + isarray: "npm:^2.0.5" + safe-buffer: "npm:^5.2.1" + typed-array-buffer: "npm:^1.0.3" + checksum: 10c0/56bc56352f14a2c4a0ab6277c5fc19b51e9534882b98eb068b39e14146591e62fa5b06bf70f7fed1626230463d7e60dca81e815096656e5e01c195c593873d12 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -13446,6 +14175,13 @@ __metadata: languageName: node linkType: hard +"tty-browserify@npm:0.0.1": + version: 0.0.1 + resolution: "tty-browserify@npm:0.0.1" + checksum: 10c0/5e34883388eb5f556234dae75b08e069b9e62de12bd6d87687f7817f5569430a6dfef550b51dbc961715ae0cd0eb5a059e6e3fc34dc127ea164aa0f9b5bb033d + languageName: node + linkType: hard + "tunnel@npm:^0.0.6": version: 0.0.6 resolution: "tunnel@npm:0.0.6" @@ -13780,6 +14516,16 @@ __metadata: languageName: node linkType: hard +"url@npm:^0.11.4": + version: 0.11.4 + resolution: "url@npm:0.11.4" + dependencies: + punycode: "npm:^1.4.1" + qs: "npm:^6.12.3" + checksum: 10c0/cc93405ae4a9b97a2aa60ca67f1cb1481c0221cb4725a7341d149be5e2f9cfda26fd432d64dbbec693d16593b68b8a46aad8e5eab21f814932134c9d8620c662 + languageName: node + linkType: hard + "use-callback-ref@npm:^1.3.3": version: 1.3.3 resolution: "use-callback-ref@npm:1.3.3" @@ -13829,6 +14575,19 @@ __metadata: languageName: node linkType: hard +"util@npm:^0.12.4, util@npm:^0.12.5": + version: 0.12.5 + resolution: "util@npm:0.12.5" + dependencies: + inherits: "npm:^2.0.3" + is-arguments: "npm:^1.0.4" + is-generator-function: "npm:^1.0.7" + is-typed-array: "npm:^1.1.3" + which-typed-array: "npm:^1.1.2" + checksum: 10c0/c27054de2cea2229a66c09522d0fa1415fb12d861d08523a8846bf2e4cbf0079d4c3f725f09dcb87493549bcbf05f5798dce1688b53c6c17201a45759e7253f3 + languageName: node + linkType: hard + "uuid@npm:13": version: 13.0.0 resolution: "uuid@npm:13.0.0" @@ -13975,6 +14734,30 @@ __metadata: languageName: node linkType: hard +"vite-plugin-node-stdlib-browser@npm:^0.2.1": + version: 0.2.1 + resolution: "vite-plugin-node-stdlib-browser@npm:0.2.1" + dependencies: + "@rollup/plugin-inject": "npm:^5.0.3" + peerDependencies: + node-stdlib-browser: ^1.2.0 + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 + checksum: 10c0/4686bde59d0396d8684433e1a14ddce868dc422f80e306a0c1cb5e86564d9f7c38a67865ca339e4ff57784ec4bada149034038cad6911a2dfcac8debfc9bd20a + languageName: node + linkType: hard + +"vite-plugin-singlefile@npm:^2.3.0": + version: 2.3.0 + resolution: "vite-plugin-singlefile@npm:2.3.0" + dependencies: + micromatch: "npm:^4.0.8" + peerDependencies: + rollup: ^4.44.1 + vite: ^5.4.11 || ^6.0.0 || ^7.0.0 + checksum: 10c0/d6ebb545d749b228bbd8fd8746a954f09d000dd69d200a651358e74136947b932f7f869536e1698e0d81e2f0694357c8bec3a957101a7e77d0d3c40193eb4cf1 + languageName: node + linkType: hard + "vite-plugin-svgr@npm:^4.0.0": version: 4.3.0 resolution: "vite-plugin-svgr@npm:4.3.0" @@ -14113,6 +14896,13 @@ __metadata: languageName: node linkType: hard +"vm-browserify@npm:^1.0.1": + version: 1.1.2 + resolution: "vm-browserify@npm:1.1.2" + checksum: 10c0/0cc1af6e0d880deb58bc974921320c187f9e0a94f25570fca6b1bd64e798ce454ab87dfd797551b1b0cc1849307421aae0193cedf5f06bdb5680476780ee344b + languageName: node + linkType: hard + "void-elements@npm:3.1.0": version: 3.1.0 resolution: "void-elements@npm:3.1.0" @@ -14312,7 +15102,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.19": +"which-typed-array@npm:^1.1.19, which-typed-array@npm:^1.1.2": version: 1.1.19 resolution: "which-typed-array@npm:1.1.19" dependencies: @@ -14437,7 +15227,7 @@ __metadata: languageName: node linkType: hard -"xtend@npm:~4.0.1": +"xtend@npm:^4.0.2, xtend@npm:~4.0.1": version: 4.0.2 resolution: "xtend@npm:4.0.2" checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e From 8110d22c8bd9d00df76d3bfa1b6b3b70618810c4 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 3 Dec 2025 10:27:30 +0100 Subject: [PATCH 09/12] fix lint --- sdk/main.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/main.ts b/sdk/main.ts index 205ec0600..c9a46df9d 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -39,6 +39,9 @@ import { type RemoteParticipant, } from "livekit-client"; +// TODO how can this get fixed? to just be part of `livekit-client` +// Can this be done in the tsconfig.json +import { type TextStreamInfo } from "../node_modules/livekit-client/dist/src/room/types"; import { type Behavior, constant } from "../src/state/Behavior"; import { createCallViewModel$ } from "../src/state/CallViewModel/CallViewModel"; import { ObservableScope } from "../src/state/ObservableScope"; From b34a75d99078394955a50c6470c0b25a00754adf Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 3 Dec 2025 13:08:51 +0100 Subject: [PATCH 10/12] fix knip --- index.html | 2 -- package.json | 1 - vite-sdk.config.js | 32 -------------------------------- vite-sdk.config.ts | 28 ++++++++++++++++++++++++++++ yarn.lock | 13 ------------- 5 files changed, 28 insertions(+), 48 deletions(-) delete mode 100644 vite-sdk.config.js create mode 100644 vite-sdk.config.ts diff --git a/index.html b/index.html index 2cf11d1aa..f17c73c0b 100644 --- a/index.html +++ b/index.html @@ -40,8 +40,6 @@ - <% if (packageType !== "full") { %>
- <% } %> diff --git a/package.json b/package.json index 578525ae6..a1a67c050 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,6 @@ "vite-plugin-generate-file": "^0.3.0", "vite-plugin-html": "^3.2.2", "vite-plugin-node-stdlib-browser": "^0.2.1", - "vite-plugin-singlefile": "^2.3.0", "vite-plugin-svgr": "^4.0.0", "vitest": "^3.0.0", "vitest-axe": "^1.0.0-pre.3" diff --git a/vite-sdk.config.js b/vite-sdk.config.js deleted file mode 100644 index ac1e4de31..000000000 --- a/vite-sdk.config.js +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright 2025 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { defineConfig, mergeConfig } from "vite"; -import nodePolyfills from "vite-plugin-node-stdlib-browser"; - -const base = "./"; - -// Config for embedded deployments (possibly hosted under a non-root path) -export default defineConfig(() => - mergeConfig( - defineConfig({ - worker: { format: "es" }, - base, // Use relative URLs to allow the app to be hosted under any path - build: { - sourcemap: true, - manifest: true, - lib: { - formats: ["es"], - entry: "./sdk/main.ts", - name: "MatrixrtcSdk", - fileName: "matrixrtc-sdk", - }, - }, - plugins: [nodePolyfills()], - }), - ), -); diff --git a/vite-sdk.config.ts b/vite-sdk.config.ts new file mode 100644 index 000000000..dfa0c023c --- /dev/null +++ b/vite-sdk.config.ts @@ -0,0 +1,28 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { defineConfig, mergeConfig } from "vite"; +import nodePolyfills from "vite-plugin-node-stdlib-browser"; + +const base = "./"; + +// Config for embedded deployments (possibly hosted under a non-root path) +export default defineConfig(() => ({ + worker: { format: "es" as const }, + base, // Use relative URLs to allow the app to be hosted under any path + build: { + sourcemap: true, + manifest: true, + lib: { + formats: ["es" as const], + entry: "./sdk/main.ts", + name: "MatrixrtcSdk", + fileName: "matrixrtc-sdk", + }, + }, + plugins: [nodePolyfills()], +})); diff --git a/yarn.lock b/yarn.lock index 4e5eff653..d775322c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7867,7 +7867,6 @@ __metadata: vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" vite-plugin-node-stdlib-browser: "npm:^0.2.1" - vite-plugin-singlefile: "npm:^2.3.0" vite-plugin-svgr: "npm:^4.0.0" vitest: "npm:^3.0.0" vitest-axe: "npm:^1.0.0-pre.3" @@ -14746,18 +14745,6 @@ __metadata: languageName: node linkType: hard -"vite-plugin-singlefile@npm:^2.3.0": - version: 2.3.0 - resolution: "vite-plugin-singlefile@npm:2.3.0" - dependencies: - micromatch: "npm:^4.0.8" - peerDependencies: - rollup: ^4.44.1 - vite: ^5.4.11 || ^6.0.0 || ^7.0.0 - checksum: 10c0/d6ebb545d749b228bbd8fd8746a954f09d000dd69d200a651358e74136947b932f7f869536e1698e0d81e2f0694357c8bec3a957101a7e77d0d3c40193eb4cf1 - languageName: node - linkType: hard - "vite-plugin-svgr@npm:^4.0.0": version: 4.3.0 resolution: "vite-plugin-svgr@npm:4.3.0" From e4fee457cf8972713b86758c3743dbfdf9207b3b Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 8 Dec 2025 09:41:01 +0100 Subject: [PATCH 11/12] allow to use custom applications --- sdk/index.html | 4 +++- sdk/main.ts | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/sdk/index.html b/sdk/index.html index f90312f10..51110ebd7 100644 --- a/sdk/index.html +++ b/sdk/index.html @@ -8,7 +8,9 @@ import { createMatrixRTCSdk } from "http://localhost:8123/matrixrtc-sdk.js"; try { - window.matrixRTCSdk = await createMatrixRTCSdk(); + window.matrixRTCSdk = await createMatrixRTCSdk( + "com.github.toger5.godot-game", + ); console.info("createMatrixRTCSdk was created!"); } catch (e) { console.error("createMatrixRTCSdk", e); diff --git a/sdk/main.ts b/sdk/main.ts index c9a46df9d..1dfbbcbfa 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -30,7 +30,9 @@ import { } from "rxjs"; import { type CallMembership, + MatrixRTCSession, MatrixRTCSessionEvent, + SlotDescription, } from "matrix-js-sdk/lib/matrixrtc"; import { type Room as LivekitRoom, @@ -80,7 +82,10 @@ interface MatrixRTCSdk { sendData?: (data: unknown) => Promise; } -export async function createMatrixRTCSdk(): Promise { +export async function createMatrixRTCSdk( + application: string = "m.call", + id: string = "", +): Promise { logger.info("Hello"); const client = await widget.client; logger.info("client created"); @@ -93,7 +98,10 @@ export async function createMatrixRTCSdk(): Promise { const mediaDevices = new MediaDevices(scope); const muteStates = new MuteStates(scope, mediaDevices, constant(true)); - const rtcSession = client.matrixRTC.getRoomSession(room); + const rtcSession = new MatrixRTCSession(client, room, { + application, + id, + }); const callViewModel = createCallViewModel$( scope, rtcSession, From c1c73b0f02a8c1e6ee6e4fec4b567a2a0e0b29a4 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 15:04:07 +0100 Subject: [PATCH 12/12] lint --- sdk/main.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sdk/main.ts b/sdk/main.ts index 1dfbbcbfa..d26832778 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -32,7 +32,6 @@ import { type CallMembership, MatrixRTCSession, MatrixRTCSessionEvent, - SlotDescription, } from "matrix-js-sdk/lib/matrixrtc"; import { type Room as LivekitRoom, @@ -98,10 +97,13 @@ export async function createMatrixRTCSdk( const mediaDevices = new MediaDevices(scope); const muteStates = new MuteStates(scope, mediaDevices, constant(true)); - const rtcSession = new MatrixRTCSession(client, room, { - application, - id, - }); + const slot = { application, id }; + const rtcSession = new MatrixRTCSession( + client, + room, + MatrixRTCSession.sessionMembershipsForSlot(room, slot), + slot, + ); const callViewModel = createCallViewModel$( scope, rtcSession,