cleanup vite.configs and simplify exported sdk props.

This commit is contained in:
Timo K
2025-12-02 11:31:56 +01:00
parent f76a6cb599
commit 93de12d79c
8 changed files with 933 additions and 88 deletions

View File

@@ -9,7 +9,7 @@ import { type KnipConfig } from "knip";
export default { export default {
vite: { vite: {
config: ["vite.config.ts", "vite-embedded.config.ts"], config: ["vite.config.ts", "vite-embedded.config.ts", "vite-sdk.config.ts"],
}, },
entry: ["src/main.tsx", "i18next-parser.config.ts"], entry: ["src/main.tsx", "i18next-parser.config.ts"],
ignoreBinaries: [ ignoreBinaries: [

View File

@@ -113,6 +113,7 @@
"loglevel": "^1.9.1", "loglevel": "^1.9.1",
"matrix-js-sdk": "^39.2.0", "matrix-js-sdk": "^39.2.0",
"matrix-widget-api": "^1.14.0", "matrix-widget-api": "^1.14.0",
"node-stdlib-browser": "^1.3.1",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"observable-hooks": "^4.2.3", "observable-hooks": "^4.2.3",
"pako": "^2.0.4", "pako": "^2.0.4",
@@ -135,6 +136,8 @@
"vite": "^7.0.0", "vite": "^7.0.0",
"vite-plugin-generate-file": "^0.3.0", "vite-plugin-generate-file": "^0.3.0",
"vite-plugin-html": "^3.2.2", "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", "vite-plugin-svgr": "^4.0.0",
"vitest": "^3.0.0", "vitest": "^3.0.0",
"vitest-axe": "^1.0.0-pre.3" "vitest-axe": "^1.0.0-pre.3"

View File

@@ -13,11 +13,21 @@
} catch (e) { } catch (e) {
console.error("createMatrixRTCSdk", e); console.error("createMatrixRTCSdk", e);
} }
const sdk = window.matrixRTCSdk; const sdk = window.matrixRTCSdk;
// This is the main bridging interface to godot
window.matrixRTCSdkGodot = {
dataObs: sdk.data$,
memberObs: sdk.members$,
// join: sdk.join, // lets stick with autojoin for now
sendData: sdk.sendData,
leave: sdk.leave,
connectedObs: sdk.connected$,
};
console.info("matrixRTCSdk join ", sdk); console.info("matrixRTCSdk join ", sdk);
await sdk.join(); const connectionState = sdk.join();
console.info("matrixRTCSdk joined "); console.info("matrixRTCSdk joined");
const div = document.getElementById("data"); const div = document.getElementById("data");
div.innerHTML = "<h3>Data:</h3>"; div.innerHTML = "<h3>Data:</h3>";
@@ -30,14 +40,12 @@
}); });
sdk.members$.subscribe((memberObjects) => { sdk.members$.subscribe((memberObjects) => {
console.info("members changed", memberObjects);
// reset div // reset div
const div = document.getElementById("members"); const div = document.getElementById("members");
div.innerHTML = "<h3>Members:</h3>"; div.innerHTML = "<h3>Members:</h3>";
// create member list // create member list
const members = memberObjects.map((member) => member.userId); const members = memberObjects.map((member) => member.membership.sender);
console.info("members changed", members); console.info("members changed", members);
for (const m of members) { for (const m of members) {
console.info("member", m); console.info("member", m);
@@ -45,29 +53,33 @@
child.innerHTML = m; child.innerHTML = m;
div.appendChild(child); div.appendChild(child);
} }
// TODO forward to godot
}); });
sdk.connected$.subscribe((connected) => { sdk.connected$.subscribe((connected) => {
console.info("connected changed", connected); console.info("connected changed", connected);
const div = document.getElementById("connect_status"); const div = document.getElementById("connect_status");
div.innerHTML = connected ? "Connected" : "Disconnected"; div.innerHTML = connected ? "Connected" : "Disconnected";
}); });
// TODO use it as godot HTML template let engine = new Engine($GODOT_CONFIG);
// var engine = new Engine($GODOT_CONFIG); engine.startGame();
// engine.startGame();
</script> </script>
<!--// TODO use it as godot HTML template--> <!--// TODO use it as godot HTML template-->
<!--<script src="$GODOT_URL"></script>--> <script src="$GODOT_URL"></script>
</head> </head>
<body> <body>
<div id="connect_status"></div>
<button onclick="window.matrixRTCSdk.leave();">Leave</button>
<button onclick="window.matrixRTCSdk.sendData({prop: 'Hello, world!'});">
Send Text
</button>
<div id="members"></div>
<div id="data"></div>
<canvas id="canvas"></canvas> <canvas id="canvas"></canvas>
<div
id="overlay"
style="position: absolute; top: 0; right: 0; background-color: #ffffff10"
>
<div id="connect_status"></div>
<button onclick="window.matrixRTCSdk.leave();">Leave</button>
<button onclick="window.matrixRTCSdk.sendData({prop: 'Hello, world!'});">
Send Text
</button>
<div id="members"></div>
<div id="data"></div>
</div>
</body> </body>
</html> </html>

View File

@@ -18,12 +18,25 @@ Please see LICENSE in the repository root for full details.
* - setting up encryption and scharing keys * - setting up encryption and scharing keys
*/ */
import { map, type Observable, of, Subject, switchMap, tap } from "rxjs"; import {
import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc"; combineLatest,
import { type TextStreamInfo } from "livekit-client/dist/src/room/types"; map,
type Observable,
of,
shareReplay,
Subject,
switchMap,
tap,
} from "rxjs";
import {
type CallMembership,
MatrixRTCSessionEvent,
} from "matrix-js-sdk/lib/matrixrtc";
import { import {
type Room as LivekitRoom, type Room as LivekitRoom,
type TextStreamReader, type TextStreamReader,
type LocalParticipant,
type RemoteParticipant,
} from "livekit-client"; } from "livekit-client";
import { type Behavior, constant } from "../src/state/Behavior"; import { type Behavior, constant } from "../src/state/Behavior";
@@ -42,14 +55,23 @@ import {
widget, widget,
} from "./helper"; } from "./helper";
import { ElementWidgetActions } from "../src/widget"; 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 { interface MatrixRTCSdk {
join: () => LocalMemberConnectionState; join: () => LocalMemberConnectionState;
/** @throws on leave errors */ /** @throws on leave errors */
leave: () => void; leave: () => void;
data$: Observable<{ sender: string; data: string }>; data$: Observable<{ sender: string; data: string }>;
members$: Behavior<MatrixLivekitMember[]>; /**
* 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 */ /** Use the LocalMemberConnectionState returned from `join` for a more detailed connection state */
connected$: Behavior<boolean>; connected$: Behavior<boolean>;
sendData?: (data: unknown) => Promise<void>; sendData?: (data: unknown) => Promise<void>;
@@ -242,7 +264,30 @@ export async function createMatrixRTCSdk(): Promise<MatrixRTCSdk> {
}, },
data$, data$,
connected$: callViewModel.connected$, 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, sendData,
}; };
} }

View File

@@ -1519,7 +1519,6 @@ export function createCallViewModel$(
localMatrixLivekitMember$, localMatrixLivekitMember$,
matrixLivekitMembers$: scope.behavior( matrixLivekitMembers$: scope.behavior(
matrixLivekitMembers$.pipe( matrixLivekitMembers$.pipe(
// TODO flatten this so its not a obs of obs.
map((members) => members.value), map((members) => members.value),
tap((v) => { tap((v) => {
logger.debug("matrixLivekitMembers$ updated (exported)", v); logger.debug("matrixLivekitMembers$ updated (exported)", v);

View File

@@ -6,26 +6,27 @@ Please see LICENSE in the repository root for full details.
*/ */
import { defineConfig, mergeConfig } from "vite"; import { defineConfig, mergeConfig } from "vite";
import fullConfig from "./vite.config"; import nodePolyfills from "vite-plugin-node-stdlib-browser";
const base = "./"; const base = "./";
// Config for embedded deployments (possibly hosted under a non-root path) // Config for embedded deployments (possibly hosted under a non-root path)
export default defineConfig((env) => export default defineConfig(() =>
mergeConfig( mergeConfig(
fullConfig({ ...env, packageType: "sdk" }),
defineConfig({ defineConfig({
worker: { format: "es" },
base, // Use relative URLs to allow the app to be hosted under any path 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: { build: {
sourcemap: true,
manifest: true, manifest: true,
lib: { lib: {
formats: ["es"],
entry: "./sdk/main.ts", entry: "./sdk/main.ts",
name: "matrixrtc-sdk", name: "MatrixrtcSdk",
// the proper extensions will be added
fileName: "matrixrtc-sdk", fileName: "matrixrtc-sdk",
}, },
}, },
plugins: [nodePolyfills()],
}), }),
), ),
); );

View File

@@ -27,7 +27,7 @@ import * as fs from "node:fs";
export default ({ export default ({
mode, mode,
packageType, packageType,
}: ConfigEnv & { packageType?: "full" | "embedded" | "sdk" }): UserConfig => { }: ConfigEnv & { packageType?: "full" | "embedded" }): UserConfig => {
const env = loadEnv(mode, process.cwd()); const env = loadEnv(mode, process.cwd());
// Environment variables with the VITE_ prefix are accessible at runtime. // Environment variables with the VITE_ prefix are accessible at runtime.
// So, we set this to allow for build/package specific behavior. // So, we set this to allow for build/package specific behavior.
@@ -68,7 +68,7 @@ export default ({
plugins.push( plugins.push(
createHtmlPlugin({ createHtmlPlugin({
entry: packageType === "sdk" ? "sdk/main.ts" : "src/main.tsx", entry: "src/main.tsx",
inject: { inject: {
data: { data: {
brand: env.VITE_PRODUCT_NAME || "Element Call", brand: env.VITE_PRODUCT_NAME || "Element Call",
@@ -125,15 +125,10 @@ export default ({
// Default naming fallback // Default naming fallback
return "assets/[name]-[hash][extname]"; return "assets/[name]-[hash][extname]";
}, },
manualChunks: 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"],
// 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,
}, },
}, },
}, },

880
yarn.lock

File diff suppressed because it is too large Load Diff