From daa77c4e2702f820d4bf4ccc7299c77ad37167b6 Mon Sep 17 00:00:00 2001 From: talksik Date: Wed, 1 Apr 2026 08:50:56 -0700 Subject: [PATCH] simple huddle implementation with streams --- js/package.json | 3 + js/src/api/client.ts | 7 + js/src/api/types.ts | 8 + js/src/electron.d.ts | 5 +- .../features/compose/controls-indicator.tsx | 5 +- js/src/features/particles/stream-view.tsx | 32 +++- js/src/huddle/HuddleApp.tsx | 47 ------ js/src/huddle_window/HuddleApp.tsx | 39 +++++ js/src/huddle_window/renderer.tsx | 2 +- js/src/main.ts | 10 +- js/src/preload.ts | 10 +- js/yarn.lock | 149 +++++++++++++++++- 12 files changed, 252 insertions(+), 65 deletions(-) delete mode 100644 js/src/huddle/HuddleApp.tsx create mode 100644 js/src/huddle_window/HuddleApp.tsx diff --git a/js/package.json b/js/package.json index 197bddf..8da7e0d 100644 --- a/js/package.json +++ b/js/package.json @@ -49,11 +49,14 @@ "vite": "^5.4.21" }, "dependencies": { + "@livekit/components-react": "^2.9.20", + "@livekit/components-styles": "^1.2.0", "@tanstack/react-query": "^5.90.21", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "electron-squirrel-startup": "^1.0.1", "firebase": "^12.10.0", + "livekit-client": "^2.18.0", "lucide-react": "^0.575.0", "next-themes": "^0.4.6", "radix-ui": "^1.4.3", diff --git a/js/src/api/client.ts b/js/src/api/client.ts index 0adcd26..a8ab07a 100644 --- a/js/src/api/client.ts +++ b/js/src/api/client.ts @@ -2,6 +2,7 @@ import { useSessionStore } from "@/stores/session-store"; import type { z } from "zod"; import { DepotObjectSchema, + GetLivekitTokenResponseSchema, HumanSchema, ListInvitationsResponseSchema, ListNetworksResponseSchema, @@ -211,6 +212,12 @@ class ApiClient { async revokeInvitation(networkId: string, data: RevokeInvitationRequest): Promise { await this.requestVoid("DELETE", `/networks/${networkId}/invitations`, data); } + + // --- LiveKit --- + + async getLivekitToken(roomId: string) { + return this.request(GetLivekitTokenResponseSchema, "POST", "/livekit/token", { room_id: roomId }); + } } export const apiClient = new ApiClient({ diff --git a/js/src/api/types.ts b/js/src/api/types.ts index 61edebf..df346e5 100644 --- a/js/src/api/types.ts +++ b/js/src/api/types.ts @@ -209,6 +209,14 @@ export function isContainerType(type: ParticleType): boolean { return CONTAINER_TYPES.has(type); } +// --- LiveKit types --- + +export const GetLivekitTokenResponseSchema = z.object({ + token: z.string(), + server_url: z.string(), +}); +export type GetLivekitTokenResponse = z.infer; + // --- Auth types --- const RequestCodeRequestSchema = z.object({ diff --git a/js/src/electron.d.ts b/js/src/electron.d.ts index af2a989..5a9499e 100644 --- a/js/src/electron.d.ts +++ b/js/src/electron.d.ts @@ -8,9 +8,12 @@ declare global { maximize: () => void; fullscreen: () => void; close: () => void; - openHuddle: () => void; + openHuddle: (data: { token: string; serverUrl: string }) => void; closeHuddle: () => void; }; + electronHuddle: { + onConnect: (callback: (data: { token: string; serverUrl: string }) => void) => () => void; + }; electronAutoplay: { play: (payload: AutoplayPayload) => void; dismiss: () => void; diff --git a/js/src/features/compose/controls-indicator.tsx b/js/src/features/compose/controls-indicator.tsx index 6a40622..81bde3d 100644 --- a/js/src/features/compose/controls-indicator.tsx +++ b/js/src/features/compose/controls-indicator.tsx @@ -1,5 +1,6 @@ import { Video, Mic, Paperclip } from "lucide-react"; import { useMediaSettingsStore } from "@/stores/media-settings-store"; +import { PropsWithChildren } from "react"; interface ControlsIndicatorProps { type: "reply" | "new"; @@ -12,7 +13,8 @@ export default function ControlsIndicator({ attachmentCount = 0, showEscape = false, onOpenAttachments, -}: ControlsIndicatorProps) { + children +}: PropsWithChildren) { const recordingMode = useMediaSettingsStore((s) => s.recordingMode); const setRecordingMode = useMediaSettingsStore((s) => s.setRecordingMode); @@ -82,6 +84,7 @@ export default function ControlsIndicator({ {attachmentCount} {attachmentCount === 1 ? "attachment" : "attachments"} )} + {children} ); } diff --git a/js/src/features/particles/stream-view.tsx b/js/src/features/particles/stream-view.tsx index 60e59a6..466a884 100644 --- a/js/src/features/particles/stream-view.tsx +++ b/js/src/features/particles/stream-view.tsx @@ -1,6 +1,7 @@ import { useState, useEffect, useEffectEvent, useCallback } from "react"; import { useNavigate } from "react-router-dom"; import { useAuthStore } from "@/stores/auth-store"; +import { apiClient } from "@/api/client"; import type { Particle } from "@/api/types"; import { parseParticlePath, type ParticlePath } from "@/lib/particle-path"; import { ComposeOverlay } from "@/features/compose/compose-overlay"; @@ -170,12 +171,20 @@ export function StreamView({ path, streamParticle }: StreamViewProps) { e.preventDefault(); navigate(`/${networkId}`); break; + case "h": { + e.preventDefault(); + const roomId = streamParticle.id; + apiClient.getLivekitToken(roomId).then(({ token, server_url }) => { + window.electronWindow.openHuddle({ token, serverUrl: server_url }); + }); + break; + } } } window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, - [composeActive, next, prev, navigate, networkId], + [composeActive, next, prev, navigate, networkId, streamParticle.id], ); // Click-to-navigate: left 30% = prev, right 70% = next @@ -204,7 +213,14 @@ export function StreamView({ path, streamParticle }: StreamViewProps) {

No particles in this stream yet

- + + + + H + {" "} + huddle + + - + + + + H + {" "} + huddle + + ); diff --git a/js/src/huddle/HuddleApp.tsx b/js/src/huddle/HuddleApp.tsx deleted file mode 100644 index 414206a..0000000 --- a/js/src/huddle/HuddleApp.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { Mic, MicOff, Video, VideoOff, PhoneOff } from 'lucide-react'; -import { useState } from 'react'; - -export function HuddleApp() { - const [micOn, setMicOn] = useState(true); - const [videoOn, setVideoOn] = useState(true); - - const handleLeave = () => { - window.electronWindow.closeHuddle(); - }; - - return ( -
- {/* Video grid */} -
-
- You -
-
- Participant -
-
- - {/* Controls bar */} -
- - - -
-
- ); -} diff --git a/js/src/huddle_window/HuddleApp.tsx b/js/src/huddle_window/HuddleApp.tsx new file mode 100644 index 0000000..57bda59 --- /dev/null +++ b/js/src/huddle_window/HuddleApp.tsx @@ -0,0 +1,39 @@ +import '@livekit/components-styles'; + +import { LiveKitRoom, VideoConference } from '@livekit/components-react'; +import { useState, useEffect } from 'react'; + +export function HuddleApp() { + const [connection, setConnection] = useState<{ token: string; serverUrl: string } | null>(null); + + useEffect(() => { + return window.electronHuddle.onConnect((data) => { + setConnection(data); + }); + }, []); + + const handleDisconnected = () => { + window.electronWindow.closeHuddle(); + }; + + if (!connection) { + return ( +
+

Connecting to huddle...

+
+ ); + } + + return ( + + + + ); +} diff --git a/js/src/huddle_window/renderer.tsx b/js/src/huddle_window/renderer.tsx index 49ee87c..771a288 100644 --- a/js/src/huddle_window/renderer.tsx +++ b/js/src/huddle_window/renderer.tsx @@ -1,5 +1,5 @@ import { createRoot } from 'react-dom/client'; -import { HuddleApp } from '@/huddle/HuddleApp'; +import { HuddleApp } from './HuddleApp'; import '@/styles/globals.css'; const root = createRoot(document.getElementById('root')!); diff --git a/js/src/main.ts b/js/src/main.ts index a513c3c..f8fa678 100644 --- a/js/src/main.ts +++ b/js/src/main.ts @@ -141,8 +141,16 @@ ipcMain.on('window:fullscreen', (event) => { }); // Secondary window IPC handlers -ipcMain.on('window:open-huddle', () => { +ipcMain.on('window:open-huddle', (_event, data: { token: string; serverUrl: string }) => { createHuddleWindow(); + // Send connection data once the huddle window is ready + huddleWindow?.webContents.once('did-finish-load', () => { + huddleWindow?.webContents.send('huddle:connect', data); + }); + // If already loaded, send immediately + if (!huddleWindow?.webContents.isLoading()) { + huddleWindow?.webContents.send('huddle:connect', data); + } }); ipcMain.on('window:close-huddle', () => { huddleWindow?.close(); diff --git a/js/src/preload.ts b/js/src/preload.ts index 3eb5c94..a9b72b4 100644 --- a/js/src/preload.ts +++ b/js/src/preload.ts @@ -7,10 +7,18 @@ contextBridge.exposeInMainWorld('electronWindow', { maximize: () => ipcRenderer.send('window:maximize'), fullscreen: () => ipcRenderer.send('window:fullscreen'), close: () => ipcRenderer.send('window:close'), - openHuddle: () => ipcRenderer.send('window:open-huddle'), + openHuddle: (data: { token: string; serverUrl: string }) => ipcRenderer.send('window:open-huddle', data), closeHuddle: () => ipcRenderer.send('window:close-huddle'), }); +contextBridge.exposeInMainWorld('electronHuddle', { + onConnect: (callback: (data: { token: string; serverUrl: string }) => void) => { + const handler = (_event: Electron.IpcRendererEvent, data: { token: string; serverUrl: string }) => callback(data); + ipcRenderer.on('huddle:connect', handler); + return () => { ipcRenderer.removeListener('huddle:connect', handler); }; + }, +}); + contextBridge.exposeInMainWorld('electronAutoplay', { play: (payload: unknown) => ipcRenderer.send('autoplay:play', payload), dismiss: () => ipcRenderer.send('autoplay:dismiss'), diff --git a/js/yarn.lock b/js/yarn.lock index 9cc740c..8d756f1 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -273,6 +273,11 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" +"@bufbuild/protobuf@^1.10.0": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-1.10.1.tgz#1d76d15290c0212076c15ede94d15157ba0c6344" + integrity sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ== + "@dotenvx/dotenvx@^1.48.4": version "1.52.0" resolved "https://registry.yarnpkg.com/@dotenvx/dotenvx/-/dotenvx-1.52.0.tgz#39cb1a70eead336171d9de4cc9de4aa23b709547" @@ -1262,6 +1267,13 @@ resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.5.tgz#39cf5a600450cb42f1f0b507cc385459bf103b27" integrity sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw== +"@floating-ui/core@^1.7.3": + version "1.7.5" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.5.tgz#d4af157a03330af5a60e69da7a4692507ada0622" + integrity sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ== + dependencies: + "@floating-ui/utils" "^0.2.11" + "@floating-ui/core@^1.7.4": version "1.7.4" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.4.tgz#4a006a6e01565c0f87ba222c317b056a2cffd2f4" @@ -1269,6 +1281,14 @@ dependencies: "@floating-ui/utils" "^0.2.10" +"@floating-ui/dom@1.7.4": + version "1.7.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.4.tgz#ee667549998745c9c3e3e84683b909c31d6c9a77" + integrity sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA== + dependencies: + "@floating-ui/core" "^1.7.3" + "@floating-ui/utils" "^0.2.10" + "@floating-ui/dom@^1.7.5": version "1.7.5" resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.5.tgz#60bfc83a4d1275b2a90db76bf42ca2a5f2c231c2" @@ -1289,6 +1309,11 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c" integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ== +"@floating-ui/utils@^0.2.11": + version "0.2.11" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.11.tgz#a269e055e40e2f45873bae9d1a2fdccbd314ea3f" + integrity sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg== + "@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -1601,6 +1626,43 @@ dependencies: "@inquirer/type" "^1.5.5" +"@livekit/components-core@0.12.13": + version "0.12.13" + resolved "https://registry.yarnpkg.com/@livekit/components-core/-/components-core-0.12.13.tgz#83d935719453c6831086daffebfc434137ea6497" + integrity sha512-DQmi84afHoHjZ62wm8y+XPNIDHTwFHAltjd3lmyXj8UZHOY7wcza4vFt1xnghJOD5wLRY58L1dkAgAw59MgWvw== + dependencies: + "@floating-ui/dom" "1.7.4" + loglevel "1.9.1" + rxjs "7.8.2" + +"@livekit/components-react@^2.9.20": + version "2.9.20" + resolved "https://registry.yarnpkg.com/@livekit/components-react/-/components-react-2.9.20.tgz#d01ecff4ed2440f2443894bd709accb3086cb1a9" + integrity sha512-hjkYOsJj9Jbghb7wM5cI8HoVisKeL6Zcy1VnRWTLm0sqVbto8GJp/17T4Udx85mCPY6Jgh8I1Cv0yVzgz7CQtg== + dependencies: + "@livekit/components-core" "0.12.13" + clsx "2.1.1" + events "^3.3.0" + jose "^6.0.12" + usehooks-ts "3.1.1" + +"@livekit/components-styles@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@livekit/components-styles/-/components-styles-1.2.0.tgz#eaff70405910a428ad580dc19910fa97b5019fef" + integrity sha512-74/rt0lDh6aHmOPmWAeDE9C4OrNW9RIdmhX/YRbovQBVNGNVWojRjl3FgQZ5LPFXO6l1maKB4JhXcBFENVxVvw== + +"@livekit/mutex@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@livekit/mutex/-/mutex-1.1.1.tgz#72492b611d55be8130ba2271b7a436d94b1bc6d4" + integrity sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw== + +"@livekit/protocol@1.44.0": + version "1.44.0" + resolved "https://registry.yarnpkg.com/@livekit/protocol/-/protocol-1.44.0.tgz#f94a34690dc7dcf1a808f0095f2e480c471747d9" + integrity sha512-/vfhDUGcUKO8Q43r6i+5FrDhl5oZjm/X3U4x2Iciqvgn5C8qbj+57YPcWSJ1kyIZm5Cm6AV2nAPjMm3ETD/iyg== + dependencies: + "@bufbuild/protobuf" "^1.10.0" + "@malept/cross-spawn-promise@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d" @@ -3850,7 +3912,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== -clsx@^2.1.1: +clsx@2.1.1, clsx@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== @@ -4719,7 +4781,7 @@ eventemitter3@^5.0.1: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.4.tgz#a86d66170433712dde814707ac52b5271ceb1feb" integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw== -events@^3.2.0: +events@^3.2.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -6070,6 +6132,11 @@ jiti@^2.4.2, jiti@^2.6.1: resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92" integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== +jose@^6.0.12, jose@^6.1.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.2.2.tgz#d6b5279b89b3e88d531c202e3fbe351f39a44aac" + integrity sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ== + jose@^6.1.3: version "6.1.3" resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.3.tgz#8453d7be88af7bb7d64a0481d6a35a0145ba3ea5" @@ -6300,6 +6367,21 @@ listr2@^7.0.2: rfdc "^1.3.0" wrap-ansi "^8.1.0" +livekit-client@^2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/livekit-client/-/livekit-client-2.18.0.tgz#7c9793ba70a55ebf664146f3a448c05652193365" + integrity sha512-wjH4y0rw5fnkPmmaxutPhD4XcAq6goQszS8lw9PEpGXVwiRE6sI/ZH+mOT/s8AHJnEC3tjmfiMZ4MQt8BlaWew== + dependencies: + "@livekit/mutex" "1.1.1" + "@livekit/protocol" "1.44.0" + events "^3.3.0" + jose "^6.1.0" + loglevel "^1.9.2" + sdp-transform "^2.15.0" + tslib "2.8.1" + typed-emitter "^2.1.0" + webrtc-adapter "^9.0.1" + load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -6335,6 +6417,11 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + lodash.get@^4.0.0: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -6377,6 +6464,16 @@ log-update@^5.0.1: strip-ansi "^7.0.1" wrap-ansi "^8.0.1" +loglevel@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7" + integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg== + +loglevel@^1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.2.tgz#c2e028d6c757720107df4e64508530db6621ba08" + integrity sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg== + long@^5.0.0: version "5.3.2" resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83" @@ -7737,6 +7834,13 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@7.8.2, rxjs@^7.5.2: + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + dependencies: + tslib "^2.1.0" + safe-array-concat@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" @@ -7790,6 +7894,16 @@ schema-utils@^4.3.0, schema-utils@^4.3.3: ajv-formats "^2.1.1" ajv-keywords "^5.1.0" +sdp-transform@^2.15.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/sdp-transform/-/sdp-transform-2.15.0.tgz#79d37a2481916f36a0534e07b32ceaa87f71df42" + integrity sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw== + +sdp@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/sdp/-/sdp-3.2.1.tgz#a2f79eecd7c5adb90d54e1bc9812775d80f3c06c" + integrity sha512-lwsAIzOPlH8/7IIjjz3K0zYBk7aBVVcvjMwt3M4fLxpjMYyy7i3I97SLHebgn4YBjirkzfp3RvRDWSKsh/+WFw== + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -8494,16 +8608,16 @@ tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@2.8.1, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -8604,6 +8718,13 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" +typed-emitter@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-2.1.0.tgz#ca78e3d8ef1476f228f548d62e04e3d4d3fd77fb" + integrity sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA== + optionalDependencies: + rxjs "^7.5.2" + typescript@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" @@ -8721,6 +8842,13 @@ use-sync-external-store@^1.5.0: resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz#b174bfa65cb2b526732d9f2ac0a408027876f32d" integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== +usehooks-ts@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/usehooks-ts/-/usehooks-ts-3.1.1.tgz#0bb7f38f36f8219ee4509cc5e944ae610fb97656" + integrity sha512-I4diPp9Cq6ieSUH2wu+fDAVQO43xwtulo+fKEidHUwZPnYImbtkTjzIJYcDcJqxgmX31GVqNFURodvcgHcW0pA== + dependencies: + lodash.debounce "^4.0.8" + username@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/username/-/username-5.1.0.tgz#a7f9325adce2d0166448cdd55d4985b1360f2508" @@ -8839,6 +8967,13 @@ webpack@^5.69.1: watchpack "^2.5.1" webpack-sources "^3.3.3" +webrtc-adapter@^9.0.1: + version "9.0.4" + resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-9.0.4.tgz#8456a5388e4947093611332e09337dedd28b1522" + integrity sha512-5ZZY1+lGq8LEKuDlg9M2RPJHlH3R7OVwyHqMcUsLKCgd9Wvf+QrFTCItkXXYPmrJn8H6gRLXbSgxLLdexiqHxw== + dependencies: + sdp "^3.2.0" + websocket-driver@>=0.5.1: version "0.7.4" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"