Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
Update react client (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
kamil-stasiak authored May 15, 2024
1 parent 7e5aed0 commit c9f4f83
Show file tree
Hide file tree
Showing 12 changed files with 394 additions and 327 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
nodejs 18.14.2
nodejs v20.13.1
protoc 24.2
554 changes: 300 additions & 254 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"lint:check": "eslint . --ext .ts,.tsx"
},
"dependencies": {
"@jellyfish-dev/react-client-sdk": "^0.2.0",
"@jellyfish-dev/react-client-sdk": "^0.3.1",
"@types/chartist": "^1.0.0",
"@types/ramda": "^0.29.10",
"axios": "^1.6.7",
Expand Down
6 changes: 3 additions & 3 deletions src/components/DeviceTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const DeviceTile = ({ selectedId, setSelectedId, streamInfo, id }: Props)
const isVideo = streamInfo.stream.getVideoTracks().length > 0;
const [enabled, setEnabled] = useState<boolean>(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);

Expand Down Expand Up @@ -69,9 +69,9 @@ export const DeviceTile = ({ selectedId, setSelectedId, streamInfo, id }: Props)
</button>
<CloseButton
descripiton="STOP STREAM AND REMOVE TRACKS"
onClick={() => {
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);
Expand Down
8 changes: 4 additions & 4 deletions src/components/useConnectionToasts.tsx
Original file line number Diff line number Diff line change
@@ -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 = <P, T>(client: JellyfishClient<P, T> | null) => {
export const useConnectionToasts = <P, T>(client: Client<P, T> | null) => {
useEffect(() => {
if (!client) return;

Expand All @@ -19,8 +19,8 @@ export const useConnectionToasts = <P, T>(client: JellyfishClient<P, T> | null)
showToastError("Failed to join the room");
};

const onAuthError = () => {
showToastError("Failed to authenticate");
const onAuthError = (error: string) => {
showToastError(`Failed to authenticate: ${error}`);
};

client.on("socketError", onSocketError);
Expand Down
16 changes: 2 additions & 14 deletions src/components/useLogging.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -18,7 +18,7 @@ const onEncodingChangedAtom = settingsSelectorAtom("onEncodingChanged");
const onVoiceActivityChangedAtom = settingsSelectorAtom("onVoiceActivityChanged");

// TODO: refactor this
export const useLogging = <P, T>(client: JellyfishClient<P, T> | null) => {
export const useLogging = <P, T>(client: Client<P, T> | null) => {
const [onJoinErrorLog] = useAtom(onJoinErrorAtom);
const [onJoinSuccessLog] = useAtom(onJoinSuccessAtom);
const [onPeerJoinedLog] = useAtom(onPeerJoinedAtom);
Expand Down Expand Up @@ -111,16 +111,6 @@ export const useLogging = <P, T>(client: JellyfishClient<P, T> | null) => {
}
};

const onTracksPriorityChanged = (enabledTracks: any, disabledTracks: any) => {
if (onTracksPriorityChangedLog) {
console.log({
name: "onTracksPriorityChanged",
enabledTracks,
disabledTracks,
});
}
};

const onAuthError = () => {
console.log("onAuthError");
};
Expand All @@ -146,7 +136,6 @@ export const useLogging = <P, T>(client: JellyfishClient<P, T> | 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);
Expand All @@ -164,7 +153,6 @@ export const useLogging = <P, T>(client: JellyfishClient<P, T> | 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);
Expand Down
10 changes: 10 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { CreateConfig } from "@jellyfish-dev/react-client-sdk";

export const NEW_CLIENT_CREATE_CONFIG: CreateConfig<unknown, unknown> = {
reconnect: {
delay: 5000,
initialDelay: 0,
maxAttempts: 1,
addTracksOnReconnect: true,
},
};
48 changes: 31 additions & 17 deletions src/containers/Client.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -71,11 +72,25 @@ const prepareHlsButtonMessage = (hlsComponent?: ComponentHLS): string | null =>
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 <JellyfishContextProvider>{children}</JellyfishContextProvider>;
};

export const Client = ({
roomId,
peerId,
token,
id,
status,
refetchIfNeeded,
remove,
removeToken,
Expand All @@ -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, roomApi } = useServerSdk();
const [showClientState, setShowClientState] = useLocalStorageState(`show-client-state-json-${peerId}`);
const [attachClientMetadata, setAttachClientMetadata] = useLocalStorageState(`attach-client-metadata-${peerId}`);
Expand All @@ -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<string | null>(getStringValue("max-bandwidth"));
const [trackMetadata, setTrackMetadata] = useState<string | null>(getStringValue("track-metadata"));
const [attachMetadata, setAttachMetadata] = useState(getBooleanValue("attach-metadata", false));
Expand All @@ -124,7 +138,7 @@ export const Client = ({
const connectionErrorTimeoutId = useRef<NodeJS.Timeout | null>(null);

useEffect(() => {
if (!jellyfishClient) return;
if (!reactClient) return;

const cb = () => {
if (connectionErrorTimeoutId.current) {
Expand All @@ -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);
}
};

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -325,7 +339,7 @@ export const Client = ({
) : (
<button
className="btn btn-sm btn-success"
disabled={!token}
disabled={!token || status === "connected"}
onClick={() => {
if (!token) {
showToastError("Cannot connect to Jellyfish server because token is empty");
Expand Down Expand Up @@ -475,7 +489,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
Expand Down Expand Up @@ -511,7 +525,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,
Expand Down
62 changes: 35 additions & 27 deletions src/containers/Room.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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, Room as RoomAPI } from "../server-sdk";
import { useServerSdk } from "../components/ServerSdkContext";
Expand Down Expand Up @@ -153,15 +153,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
Expand Down Expand Up @@ -228,24 +233,27 @@ export const Room = ({ roomId, refetchIfNeeded, refetchRequested }: RoomProps) =
.map(({ id }) => {
if (!id) return null;
return (
<Client
key={id}
roomId={roomId}
peerId={id}
token={token[id] || null}
id={id}
refetchIfNeeded={refetchIfNeededInner}
remove={() => {
roomApi?.deletePeer(roomId, id);
}}
removeToken={() => {
removeToken(id);
}}
setToken={(token: string) => {
addToken(id, token);
}}
hlsComponent={hlsComponent}
/>
<ClientContextProvider key={id} roomId={roomId} peerId={id}>
<Client
key={id}
roomId={roomId}
peerId={id}
token={token[id] || null}
id={id}
status={roomState?.peers.find((peer) => peer.id === id)?.status}
refetchIfNeeded={refetchIfNeededInner}
remove={() => {
roomApi?.deletePeer(roomId, id);
}}
removeToken={() => {
removeToken(id);
}}
setToken={(token: string) => {
addToken(id, token);
}}
hlsComponent={hlsComponent}
/>
</ClientContextProvider>
);
})}
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/containers/RoomsContext.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<unknown, unknown>(),
client: prevPeers?.[peer.id]?.client || create<unknown, unknown>(NEW_CLIENT_CREATE_CONFIG),
tracks: prevPeers?.[peer.id]?.tracks || [],
}));

Expand Down
6 changes: 3 additions & 3 deletions src/containers/StreamedTrackCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<boolean>(simulcastTransfer);
const [expandedTrackId, setExpandedTrackId] = useState<boolean>(false);
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/containers/StreamingSettingsCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TrackEncoding } from "@jellyfish-dev/react-client-sdk/.";
import { TrackEncoding } from "@jellyfish-dev/react-client-sdk";
import { StreamingDeviceSelector } from "../components/StreamingDeviceSelector";
import { StreamingSettingsPanel } from "./StreamingSettingsPanel";
import { DeviceTile } from "../components/DeviceTile";
Expand Down

0 comments on commit c9f4f83

Please sign in to comment.