This commit is contained in:
Timo K
2025-11-24 09:44:21 +01:00
parent 3331af1108
commit 28158bfc23
10 changed files with 172 additions and 18 deletions

0
godot/README.md Normal file
View File

76
godot/main.ts Normal file
View File

@@ -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<void> {
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
// <!DOCTYPE html>
// <html>
// <head>
// <title>My Template</title>
// <meta charset="UTF-8">
// </head>
// <body>
// <canvas id="canvas"></canvas>
// <script src="$GODOT_URL"></script>
// <script>
// var engine = new Engine($GODOT_CONFIG);
// engine.startGame();
// </script>
// </body>
// </html>

View File

@@ -40,6 +40,18 @@
<!-- The default class is: .no-theme {display: none}. It will be overwritten once the app is loaded. -->
<body class="no-theme">
<% if (packageType !== "full") { %>
<div id="root"></div>
<% } %>
<!-- Godot export -->
<% if (packageType === "godot") { %>
<canvas id="canvas"></canvas>
<script src="$GODOT_URL"></script>
<script>
var engine = new Engine($GODOT_CONFIG);
engine.startGame();
</script>
<% } %>
</body>
</html>

View File

@@ -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"

View File

@@ -358,7 +358,7 @@ export type InitResult = {
passwordlessUser: boolean;
};
async function loadClient(): Promise<InitResult | null> {
export async function loadClient(): Promise<InitResult | null> {
if (widget) {
// We're inside a widget, so let's engage *matryoshka mode*
logger.log("Using a matryoshka client");

View File

@@ -251,6 +251,8 @@ export interface CallViewModel {
participantCount$: Behavior<number>;
/** Participants sorted by livekit room so they can be used in the audio rendering */
audioParticipants$: Behavior<AudioLivekitItem[]>;
/** use the layout instead, this is just for the godot export. */
userMedia$: Behavior<UserMedia[]>;
/** List of participants raising their hand */
handsRaised$: Behavior<Record<string, RaisedHandInfo>>;
/** 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$,

View File

@@ -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"]
}

32
vite-godot.config.js Normal file
View File

@@ -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",
},
},
}),
),
);

View File

@@ -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,
},
},
},

View File

@@ -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"