From dcbf8e45516fcaf7c8fa6673e6e7ae1e811874b2 Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Thu, 28 Mar 2024 14:43:02 +0100 Subject: [PATCH 1/6] Update react client --- package-lock.json | 84 ++++++++++++-------------- package.json | 2 +- src/components/DeviceTile.tsx | 6 +- src/components/useConnectionToasts.tsx | 4 +- src/components/useLogging.tsx | 6 +- src/config.ts | 10 +++ src/containers/Client.tsx | 57 +++++++++++------ src/containers/Room.tsx | 62 ++++++++++--------- src/containers/RoomsContext.tsx | 5 +- src/containers/StreamedTrackCard.tsx | 6 +- 10 files changed, 137 insertions(+), 105 deletions(-) create mode 100644 src/config.ts diff --git a/package-lock.json b/package-lock.json index 4424dc5..7d3e883 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.3", "license": "Apache-2.0", "dependencies": { - "@jellyfish-dev/react-client-sdk": "^0.2.0", + "@jellyfish-dev/react-client-sdk": "file:../react-client-sdk", "@types/chartist": "^1.0.0", "@types/ramda": "^0.29.10", "axios": "^1.6.7", @@ -58,11 +58,10 @@ }, "../react-client-sdk": { "name": "@jellyfish-dev/react-client-sdk", - "version": "0.1.9", - "extraneous": true, + "version": "0.2.1", "license": "Apache-2.0", "dependencies": { - "@jellyfish-dev/ts-client-sdk": "^0.3.0", + "@jellyfish-dev/ts-client-sdk": "file:../ts-client-sdk", "events": "3.3.0", "lodash.isequal": "4.5.0" }, @@ -1154,36 +1153,9 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@jellyfish-dev/membrane-webrtc-js": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@jellyfish-dev/membrane-webrtc-js/-/membrane-webrtc-js-0.7.0.tgz", - "integrity": "sha512-FEYpL52W1QekhPiv88hJY/0mlZwGu6cWWH/xvjgf1pehCXiyqYv6icIBRsYqRLdgmivVFTaUbQTLIv4Yn7RKYw==", - "dependencies": { - "events": "^3.3.0", - "typed-emitter": "^2.1.0", - "uuid": "^9.0.1" - } - }, "node_modules/@jellyfish-dev/react-client-sdk": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@jellyfish-dev/react-client-sdk/-/react-client-sdk-0.2.0.tgz", - "integrity": "sha512-/4j0fzKntOpKMei/HdlmZNRClm1eiAm1VhmYXgWLa4UINYKBfQnnCbLKmwu3hd2R2himr6OZy9zDYDwSdU5oew==", - "dependencies": { - "@jellyfish-dev/ts-client-sdk": "^0.3.0", - "events": "3.3.0", - "lodash.isequal": "4.5.0" - } - }, - "node_modules/@jellyfish-dev/ts-client-sdk": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@jellyfish-dev/ts-client-sdk/-/ts-client-sdk-0.3.0.tgz", - "integrity": "sha512-PoDpalc5sWWxgGYLt7wIMQDudaLs7nzh4Li6UNS8kPq8kzKPXUSqLLU6S23pzRdR+3DSwo/BwmyHgperVrsKjw==", - "dependencies": { - "@jellyfish-dev/membrane-webrtc-js": "^0.7.0", - "events": "^3.3.0", - "ts-proto": "^1.165.0", - "typed-emitter": "^2.1.0" - } + "resolved": "../react-client-sdk", + "link": true }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", @@ -1568,27 +1540,32 @@ "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "dev": true }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "dev": true }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dev": true, "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -1597,27 +1574,32 @@ "node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "dev": true }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "dev": true }, "node_modules/@remix-run/router": { "version": "1.15.2", @@ -1851,7 +1833,8 @@ "node_modules/@types/node": { "version": "20.5.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", - "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==" + "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", + "devOptional": true }, "node_modules/@types/phoenix": { "version": "1.6.4", @@ -2715,6 +2698,7 @@ "version": "2.1.13", "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz", "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==", + "dev": true, "engines": { "node": ">=12.13" }, @@ -3106,6 +3090,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -3151,6 +3136,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz", "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==", + "dev": true, "dependencies": { "detect-libc": "^1.0.3" } @@ -4276,7 +4262,8 @@ "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "dev": true }, "node_modules/loose-envify": { "version": "1.4.0", @@ -4867,6 +4854,7 @@ "version": "7.2.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "dev": true, "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -5204,7 +5192,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "devOptional": true, + "dev": true, "dependencies": { "tslib": "^2.1.0" } @@ -5631,6 +5619,7 @@ "version": "6.7.0", "resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.7.0.tgz", "integrity": "sha512-A0wvFtpkTCWPw7ftTIwbEH+L+7ul4CU0x3jXKQ+kCnmEQIAOwhpUaBmcAYKxZCxHae9/MUl4LbyTqw25BpzW5Q==", + "dev": true, "dependencies": { "dprint-node": "^1.0.8" } @@ -5639,6 +5628,7 @@ "version": "1.167.9", "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-1.167.9.tgz", "integrity": "sha512-zqZ15CzqvupSpoTl/fzOs5gG7SFvj1ENmWeKMgD4Yl2BSx8I5F+qgYkr9EZYMu7Ho7u+QtwzfudROo+/jwM2pg==", + "dev": true, "dependencies": { "case-anything": "^2.1.13", "protobufjs": "^7.2.4", @@ -5653,6 +5643,7 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-1.15.0.tgz", "integrity": "sha512-TYyJ7+H+7Jsqawdv+mfsEpZPTIj9siDHS6EMCzG/z3b/PZiphsX+mWtqFfFVe5/N0Th6V3elK9lQqjnrgTOfrg==", + "dev": true, "dependencies": { "long": "^5.2.3", "protobufjs": "^7.2.4" @@ -5667,7 +5658,7 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "devOptional": true + "dev": true }, "node_modules/type-check": { "version": "0.4.0", @@ -5697,6 +5688,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", + "dev": true, "optionalDependencies": { "rxjs": "*" } diff --git a/package.json b/package.json index 762742b..bdd086b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "lint:check": "eslint . --ext .ts,.tsx" }, "dependencies": { - "@jellyfish-dev/react-client-sdk": "^0.2.0", + "@jellyfish-dev/react-client-sdk": "file:../react-client-sdk", "@types/chartist": "^1.0.0", "@types/ramda": "^0.29.10", "axios": "^1.6.7", diff --git a/src/components/DeviceTile.tsx b/src/components/DeviceTile.tsx index 3e09705..14db6d3 100644 --- a/src/components/DeviceTile.tsx +++ b/src/components/DeviceTile.tsx @@ -21,7 +21,7 @@ export const DeviceTile = ({ selectedId, setSelectedId, streamInfo, id }: Props) const isVideo = streamInfo.stream.getVideoTracks().length > 0; const [enabled, setEnabled] = useState(true); const peer = state.rooms[state.selectedRoom || ""].peers[id]; - const api = peer.client.useSelector((state) => state.connectivity.api); + const reactClient = peer.client.useSelector((state) => state.client); const track = peer.tracks[streamInfo.id]; const setActiveLocalCameras = useSetAtom(activeLocalCamerasAtom); @@ -69,9 +69,9 @@ export const DeviceTile = ({ selectedId, setSelectedId, streamInfo, id }: Props) { + onClick={async () => { if (track.serverId) { - api?.removeTrack(track.serverId); + await reactClient?.removeTrack(track.serverId); } if (track.source === "navigator" && track.type === "video") { setActiveLocalCameras((prev) => prev - 1); diff --git a/src/components/useConnectionToasts.tsx b/src/components/useConnectionToasts.tsx index acab04d..831a17a 100644 --- a/src/components/useConnectionToasts.tsx +++ b/src/components/useConnectionToasts.tsx @@ -1,9 +1,9 @@ -import { JellyfishClient } from "@jellyfish-dev/react-client-sdk"; +import { Client } from "@jellyfish-dev/react-client-sdk"; import { useEffect } from "react"; import { showToastError } from "./Toasts"; -export const useConnectionToasts = (client: JellyfishClient | null) => { +export const useConnectionToasts = (client: Client | null) => { useEffect(() => { if (!client) return; diff --git a/src/components/useLogging.tsx b/src/components/useLogging.tsx index 0fbc5d6..47ab89c 100644 --- a/src/components/useLogging.tsx +++ b/src/components/useLogging.tsx @@ -1,4 +1,4 @@ -import { JellyfishClient } from "@jellyfish-dev/react-client-sdk"; +import { Client } from "@jellyfish-dev/react-client-sdk"; import { useEffect } from "react"; import { settingsSelectorAtom } from "./LogSelector"; import { useAtom } from "jotai"; @@ -18,7 +18,7 @@ const onEncodingChangedAtom = settingsSelectorAtom("onEncodingChanged"); const onVoiceActivityChangedAtom = settingsSelectorAtom("onVoiceActivityChanged"); // TODO: refactor this -export const useLogging = (client: JellyfishClient | null) => { +export const useLogging = (client: Client | null) => { const [onJoinErrorLog] = useAtom(onJoinErrorAtom); const [onJoinSuccessLog] = useAtom(onJoinSuccessAtom); const [onPeerJoinedLog] = useAtom(onPeerJoinedAtom); @@ -146,7 +146,6 @@ export const useLogging = (client: JellyfishClient | null) => { client.on("trackRemoved", onTrackRemoved); client.on("trackUpdated", onTrackUpdated); client.on("bandwidthEstimationChanged", onBandwidthEstimationChanged); - client.on("tracksPriorityChanged", onTracksPriorityChanged); client.on("authError", onAuthError); client.on("connectionError", onConnectionError); @@ -164,7 +163,6 @@ export const useLogging = (client: JellyfishClient | null) => { client.off("trackRemoved", onTrackRemoved); client.off("trackUpdated", onTrackUpdated); client.off("bandwidthEstimationChanged", onBandwidthEstimationChanged); - client.off("tracksPriorityChanged", onTracksPriorityChanged); client.off("authError", onAuthError); client.off("connectionError", onConnectionError); diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..397899f --- /dev/null +++ b/src/config.ts @@ -0,0 +1,10 @@ +import { CreateConfig } from "@jellyfish-dev/react-client-sdk"; + +export const NEW_CLIENT_CREATE_CONFIG: CreateConfig = { + reconnect: { + delay: 5000, + initialDelay: 0, + maxAttempts: 1, + addTracksOnReconnect: false, + }, +} diff --git a/src/containers/Client.tsx b/src/containers/Client.tsx index 1a99b38..300b40f 100644 --- a/src/containers/Client.tsx +++ b/src/containers/Client.tsx @@ -1,4 +1,4 @@ -import { Fragment, useEffect, useRef, useState } from "react"; +import { Fragment, ReactNode, useEffect, useRef, useState } from "react"; import { JsonComponent } from "../components/JsonComponent"; import { getArrayValue, getStringValue, useLocalStorageState } from "../components/LogSelector"; import { CloseButton } from "../components/CloseButton"; @@ -26,6 +26,7 @@ type ClientProps = { peerId: string; token: string | null; id: string; + status?: "disconnected" | "connected"; refetchIfNeeded: () => void; remove: (roomId: string) => void; setToken: (token: string) => void; @@ -71,11 +72,25 @@ const prepareHlsButtonMessage = (hlsMode?: ComponentOptionsHLSSubscribeModeEnum) else return null; }; +type ClientContextProviderProps = { + roomId: string; + peerId: string; + children: ReactNode; +}; + +export const ClientContextProvider = ({ roomId, peerId, children }: ClientContextProviderProps) => { + const { state } = useStore(); + const JellyfishContextProvider = state.rooms[roomId].peers[peerId].client.JellyfishContextProvider; + + return {children}; +}; + export const Client = ({ roomId, peerId, token, id, + status, refetchIfNeeded, remove, removeToken, @@ -96,8 +111,7 @@ export const Client = ({ tracks: snapshot.tracks, })); - const api = client.useSelector((snapshot) => snapshot.connectivity.api); - const jellyfishClient = client.useSelector((snapshot) => snapshot.connectivity.client); + const reactClient = client.useSelector((snapshot) => snapshot.client); const { signalingHost, signalingPath, signalingURISchema, hlsApi } = useServerSdk(); const [showClientState, setShowClientState] = useLocalStorageState(`show-client-state-json-${peerId}`); const [attachClientMetadata, setAttachClientMetadata] = useLocalStorageState(`attach-client-metadata-${peerId}`); @@ -110,8 +124,8 @@ export const Client = ({ statusRef.current = fullState?.status; const isThereAnyTrack = Object.keys(fullState?.tracks || {}).length > 0; - useLogging(jellyfishClient); - useConnectionToasts(jellyfishClient); + useLogging(reactClient); + useConnectionToasts(reactClient); const [maxBandwidth, setMaxBandwidth] = useState(getStringValue("max-bandwidth")); const [trackMetadata, setTrackMetadata] = useState(getStringValue("track-metadata")); const [attachMetadata, setAttachMetadata] = useState(getBooleanValue("attach-metadata", false)); @@ -124,7 +138,7 @@ export const Client = ({ const connectionErrorTimeoutId = useRef(null); useEffect(() => { - if (!jellyfishClient) return; + if (!reactClient) return; const cb = () => { if (connectionErrorTimeoutId.current) { @@ -133,24 +147,24 @@ export const Client = ({ connectionErrorTimeoutId.current = null; }; - jellyfishClient.on("joined", cb); + reactClient.on("joined", cb); return () => { - jellyfishClient?.removeListener("joined", cb); + reactClient?.removeListener("joined", cb); }; - }, [jellyfishClient]); + }, [reactClient]); const changeEncodingReceived = (trackId: string, encoding: TrackEncoding) => { if (!fullState) return; - api?.setTargetTrackEncoding(trackId, encoding); + reactClient?.setTargetTrackEncoding(trackId, encoding); }; const changeEncoding = (trackId: string, encoding: TrackEncoding, desiredState: boolean) => { if (!trackId) return; if (desiredState) { - api?.enableTrackEncoding(trackId, encoding); + reactClient?.enableTrackEncoding(trackId, encoding); } else { - api?.disableTrackEncoding(trackId, encoding); + reactClient?.disableTrackEncoding(trackId, encoding); } }; @@ -222,7 +236,7 @@ export const Client = ({ ? JSON.parse(trackMetadata?.trim() || createDefaultTrackMetadata(trackInfo.type)) : undefined; - const trackId = await api?.addTrack( + const trackId = await reactClient?.addTrack( track, trackInfo.stream, metadata, @@ -251,7 +265,7 @@ export const Client = ({ const addAudioTrack = async (trackInfo: DeviceInfo) => { const track: MediaStreamTrack = trackInfo.stream?.getAudioTracks()[0]; if (!trackInfo.stream || !track) return; - const trackId = await api?.addTrack( + const trackId = await reactClient?.addTrack( track, trackInfo.stream, attachMetadata ? JSON.parse(trackMetadata?.trim() || createDefaultTrackMetadata(trackInfo.type)) : undefined, @@ -325,7 +339,7 @@ export const Client = ({ ) : ( )} + +
{token ? (
@@ -474,7 +497,7 @@ export const Client = ({ disabled={!isClientMetadataCorrect || fullState.status !== "joined"} onClick={() => { const metadata = checkJSON(clientMetadata) ? JSON.parse(clientMetadata) : null; - api?.updatePeerMetadata(metadata); + reactClient?.updatePeerMetadata(metadata); }} > Update @@ -510,7 +533,7 @@ export const Client = ({ trackMetadata={trackMetadata ?? ""} removeTrack={(trackId) => { if (!trackId) return; - api?.removeTrack(tracks[trackId].serverId || ""); + reactClient?.removeTrack(tracks[trackId].serverId || ""); dispatch({ type: "SET_TRACK_STREAMED", roomId: roomId, diff --git a/src/containers/Room.tsx b/src/containers/Room.tsx index 7cfa43f..ba35693 100644 --- a/src/containers/Room.tsx +++ b/src/containers/Room.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; import { useLocalStorageState } from "../components/LogSelector"; import { REFETCH_ON_SUCCESS } from "./JellyfishInstance"; import { JsonComponent } from "../components/JsonComponent"; -import { Client } from "./Client"; +import { Client, ClientContextProvider } from "./Client"; import { CopyToClipboardButton } from "../components/CopyButton"; import { ComponentHLS, ComponentOptionsHLSSubscribeModeEnum, Room as RoomAPI } from "../server-sdk"; import { useServerSdk } from "../components/ServerSdkContext"; @@ -157,15 +157,20 @@ export const Room = ({ roomId, refetchIfNeeded, refetchRequested }: RoomProps) = const currentPeerCounter = peerCounter; setPeerCounter((prev) => (prev >= Number.MAX_SAFE_INTEGER ? 0 : prev + 1)); - roomApi?.addPeer(roomId, { type: "webrtc", options: { enableSimulcast: true } }).then((response) => { - addToken(response.data.data.peer.id, response.data.data.token); - setPeerOrder((prev) => { - const copy = { ...prev }; - copy[response.data.data.peer.id] = currentPeerCounter; - return copy; + roomApi + ?.addPeer(roomId, { + type: "webrtc", + options: { enableSimulcast: true }, + }) + .then((response) => { + addToken(response.data.data.peer.id, response.data.data.token); + setPeerOrder((prev) => { + const copy = { ...prev }; + copy[response.data.data.peer.id] = currentPeerCounter; + return copy; + }); + refetchIfNeededInner(); }); - refetchIfNeededInner(); - }); }} > Create peer @@ -232,24 +237,27 @@ export const Room = ({ roomId, refetchIfNeeded, refetchRequested }: RoomProps) = .map(({ id }) => { if (!id) return null; return ( - { - roomApi?.deletePeer(roomId, id); - }} - removeToken={() => { - removeToken(id); - }} - setToken={(token: string) => { - addToken(id, token); - }} - hlsMode={hlsMode} - /> + + peer.id === id)?.status} + refetchIfNeeded={refetchIfNeededInner} + remove={() => { + roomApi?.deletePeer(roomId, id); + }} + removeToken={() => { + removeToken(id); + }} + setToken={(token: string) => { + addToken(id, token); + }} + hlsMode={hlsMode} + /> + ); })}
diff --git a/src/containers/RoomsContext.tsx b/src/containers/RoomsContext.tsx index c57df9f..37cc28b 100644 --- a/src/containers/RoomsContext.tsx +++ b/src/containers/RoomsContext.tsx @@ -1,8 +1,9 @@ import { createContext, ReactNode, useContext, useReducer } from "react"; import { groupBy } from "rambda"; import { Peer as PeerApi, Room as RoomAPI } from "../server-sdk"; -import { create, CreateJellyfishClient } from "@jellyfish-dev/react-client-sdk/experimental"; +import { create, CreateJellyfishClient } from "@jellyfish-dev/react-client-sdk"; import { LocalTrack } from "./Client"; +import { NEW_CLIENT_CREATE_CONFIG } from "../config"; export type RoomContext = { state: AppStore; @@ -118,7 +119,7 @@ const roomReducer: Reducer = (state, action) => { const peersList: PeerState[] = action.room.peers.map((peer) => ({ id: peer.id, peerStatus: peer, - client: prevPeers?.[peer.id]?.client || create(), + client: prevPeers?.[peer.id]?.client || create(NEW_CLIENT_CREATE_CONFIG), tracks: prevPeers?.[peer.id]?.tracks || [], })); diff --git a/src/containers/StreamedTrackCard.tsx b/src/containers/StreamedTrackCard.tsx index 8f29ef9..4751bf5 100644 --- a/src/containers/StreamedTrackCard.tsx +++ b/src/containers/StreamedTrackCard.tsx @@ -38,8 +38,8 @@ export const StreamedTrackCard = ({ trackInfo.encodings?.includes("h") || false, ]); - const client = state.rooms[roomId].peers[peerId].client; - const api = client.useSelector((s) => s.connectivity.api); + const createReactClientResult = state.rooms[roomId].peers[peerId].client; + const reactClient = createReactClientResult.useSelector((s) => s.client); const simulcast = useState(simulcastTransfer); const [expandedTrackId, setExpandedTrackId] = useState(false); @@ -52,7 +52,7 @@ export const StreamedTrackCard = ({ const metadata = checkJSON(newTrackMetadata) ? JSON.parse(newTrackMetadata) : null; const trackId = trackInfo.serverId; if (!trackId) throw new Error("Server id is not present!"); - api?.updateTrackMetadata(trackId, metadata); + reactClient?.updateTrackMetadata(trackId, metadata); setUserTracksMetadata((prev) => ({ ...(prev ? prev : {}), [trackId]: metadata, From c1514c6f6d1b0f092f2f01d7e9f7825e1323980d Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Tue, 16 Apr 2024 15:18:19 +0200 Subject: [PATCH 2/6] POC --- package-lock.json | 22 +++++++++++----------- src/config.ts | 2 +- src/containers/Client.tsx | 1 + src/containers/StreamingSettingsCard.tsx | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7d3e883..d85c3c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,24 +66,24 @@ "lodash.isequal": "4.5.0" }, "devDependencies": { - "@playwright/test": "^1.41.2", + "@playwright/test": "^1.42.1", "@types/events": "^3.0.3", "@types/lodash.isequal": "^4.5.8", - "@types/node": "^20.11.18", - "@types/react": "18.2.55", - "@typescript-eslint/eslint-plugin": "^7.0.1", - "eslint": "^8.56.0", + "@types/node": "^20.11.27", + "@types/react": "18.2.65", + "@typescript-eslint/eslint-plugin": "^7.2.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", + "eslint-plugin-react-refresh": "^0.4.6", "prettier": "3.2.5", - "prettier-plugin-tailwindcss": "0.5.11", + "prettier-plugin-tailwindcss": "0.5.12", "react": "^18.2.0", - "testcontainers": "^10.7.1", + "testcontainers": "^10.7.2", "typed-emitter": "^2.1.0", - "typedoc": "^0.25.8", - "typedoc-plugin-mdn-links": "^3.1.16", - "typescript": "5.3.3" + "typedoc": "^0.25.12", + "typedoc-plugin-mdn-links": "^3.1.18", + "typescript": "5.4.2" } }, "node_modules/@aashutoshrathi/word-wrap": { diff --git a/src/config.ts b/src/config.ts index 397899f..b8ff51b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -5,6 +5,6 @@ export const NEW_CLIENT_CREATE_CONFIG: CreateConfig = { delay: 5000, initialDelay: 0, maxAttempts: 1, - addTracksOnReconnect: false, + addTracksOnReconnect: true, }, } diff --git a/src/containers/Client.tsx b/src/containers/Client.tsx index 300b40f..22ee139 100644 --- a/src/containers/Client.tsx +++ b/src/containers/Client.tsx @@ -378,6 +378,7 @@ export const Client = ({