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

Commit 732b982

Browse files
Event emitters (#73)
1 parent 747df0a commit 732b982

40 files changed

+4910
-3225
lines changed

.tool-versions

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nodejs 18.14.2
1+
nodejs v20.13.1

examples/minimal-react/package-lock.json

Lines changed: 14 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/minimal-react/src/components/App.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import VideoPlayer from "./VideoPlayer";
2-
import { JellyfishClient, SCREEN_SHARING_MEDIA_CONSTRAINTS } from "@jellyfish-dev/react-client-sdk";
2+
import { SCREEN_SHARING_MEDIA_CONSTRAINTS, Client } from "@jellyfish-dev/react-client-sdk";
33
import { useState } from "react";
4-
import { useConnect, useDisconnect, useApi, useStatus, useTracks, useSelector } from "./client";
4+
import { useConnect, useDisconnect, useClient, useStatus, useTracks } from "./client";
55

66
// Example metadata types for peer and track
77
// You can define your own metadata types just make sure they are serializable
@@ -18,14 +18,14 @@ export const App = () => {
1818

1919
const connect = useConnect();
2020
const disconnect = useDisconnect();
21-
const api = useApi();
21+
const client = useClient();
2222
const status = useStatus();
2323
const tracks = useTracks();
2424

2525
{
2626
// for e2e test
27-
const client = useSelector((s) => s.connectivity.client);
28-
(window as unknown as { client: JellyfishClient<PeerMetadata, TrackMetadata> }).client = client!;
27+
const client = useClient();
28+
(window as unknown as { client: Client<PeerMetadata, TrackMetadata> }).client = client!;
2929
}
3030

3131
return (
@@ -58,7 +58,7 @@ export const App = () => {
5858
// Get screen sharing MediaStream
5959
navigator.mediaDevices.getDisplayMedia(SCREEN_SHARING_MEDIA_CONSTRAINTS).then((screenStream) => {
6060
// Add local MediaStream to webrtc
61-
screenStream.getTracks().forEach((track) => api.addTrack(track, screenStream, { type: "screen" }));
61+
screenStream.getTracks().forEach((track) => client.addTrack(track, screenStream, { type: "screen" }));
6262
});
6363
}}
6464
>

examples/minimal-react/src/components/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import { PeerMetadata, TrackMetadata } from "./App";
33

44
// Create a Membrane client instance
55
// remember to use JellyfishContextProvider
6-
export const { useApi, useTracks, useStatus, useConnect, useDisconnect, useSelector, JellyfishContextProvider } =
6+
export const { useClient, useTracks, useStatus, useConnect, useDisconnect, useSelector, JellyfishContextProvider } =
77
create<PeerMetadata, TrackMetadata>();

examples/use-camera-and-microphone-example/package-lock.json

Lines changed: 14 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/use-camera-and-microphone-example/src/AdditionalControls.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ export const AdditionalControls = () => {
4343
<h3>Local:</h3>
4444
<div className="max-w-[500px]">
4545
{camera?.track?.kind === "video" && <VideoPlayer stream={camera?.stream} />}
46-
{microphone?.track?.kind === "audio" && <AudioVisualizer stream={microphone?.stream} />}
46+
{microphone?.track?.kind === "audio" && (
47+
<AudioVisualizer stream={microphone?.stream} trackId={microphone?.track.id} />
48+
)}
4749
</div>
4850
</div>
4951
</div>

examples/use-camera-and-microphone-example/src/AudioVisualizer.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { useEffect, useRef, useState } from "react";
22

33
type Props = {
44
stream: MediaStream | null | undefined;
5+
trackId: string | null;
56
};
67

7-
export const AudioVisualizer = ({ stream }: Props) => {
8+
export const AudioVisualizer = ({ stream, trackId }: Props) => {
89
const canvasRef = useRef<HTMLCanvasElement>(null);
910
const canvasParentRef = useRef<HTMLDivElement>(null);
11+
const idRef = useRef<number | null>(null);
1012
const [canvasWidth, setCanvasWidth] = useState<number>(400);
1113

1214
useEffect(() => {
@@ -34,9 +36,10 @@ export const AudioVisualizer = ({ stream }: Props) => {
3436
const dataArray = new Uint8Array(bufferLength);
3537

3638
function renderFrame() {
37-
const id = requestAnimationFrame(renderFrame);
39+
idRef.current = requestAnimationFrame(renderFrame);
40+
3841
if (!canvasRef.current) {
39-
cancelAnimationFrame(id);
42+
cancelAnimationFrame(idRef.current);
4043
return;
4144
}
4245

@@ -58,7 +61,11 @@ export const AudioVisualizer = ({ stream }: Props) => {
5861
}
5962

6063
renderFrame();
61-
}, [stream]);
64+
65+
return () => {
66+
idRef.current && cancelAnimationFrame(idRef.current);
67+
};
68+
}, [stream, trackId]);
6269

6370
return (
6471
<div ref={canvasParentRef} className="flex flex-row flex-nowrap justify-center border-4">

examples/use-camera-and-microphone-example/src/DeviceControls.tsx

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { PeerStatus, UseScreenshareResult } from "@jellyfish-dev/react-client-sdk";
2-
import { UseMicrophoneResult, UseCameraResult } from "@jellyfish-dev/react-client-sdk";
1+
import {
2+
PeerStatus,
3+
UseMicrophoneResult,
4+
UseCameraResult,
5+
UseScreenShareResult,
6+
} from "@jellyfish-dev/react-client-sdk";
37
import { TrackMetadata } from "./jellyfishSetup";
48

59
type DeviceControlsProps = {
@@ -15,7 +19,7 @@ type DeviceControlsProps = {
1519
type: "video";
1620
}
1721
| {
18-
device: UseScreenshareResult<TrackMetadata>;
22+
device: UseScreenShareResult<TrackMetadata>;
1923
type: "screenshare";
2024
}
2125
);
@@ -25,36 +29,36 @@ export const DeviceControls = ({ device, type, status, metadata }: DeviceControl
2529
<div className="flex flex-col gap-2">
2630
<button
2731
className="btn btn-success btn-sm"
28-
disabled={!!device.stream}
32+
disabled={!!device?.stream}
2933
onClick={() => {
30-
device.start();
34+
device?.start();
3135
}}
3236
>
3337
Start {type} device
3438
</button>
3539
<button
3640
className="btn btn-error btn-sm"
37-
disabled={!device.stream}
41+
disabled={!device?.stream}
3842
onClick={() => {
39-
device.stop();
43+
device?.stop();
4044
}}
4145
>
4246
Stop {type} device
4347
</button>
4448
<button
4549
className="btn btn-success btn-sm"
46-
disabled={!device.stream || device.enabled}
50+
disabled={!device?.stream || device?.enabled}
4751
onClick={() => {
48-
device.setEnable(true);
52+
device?.setEnable(true);
4953
}}
5054
>
5155
Enable {type} track
5256
</button>
5357
<button
5458
className="btn btn-error btn-sm"
55-
disabled={!device.enabled}
59+
disabled={!device?.enabled}
5660
onClick={() => {
57-
device.setEnable(false);
61+
device?.setEnable(false);
5862
}}
5963
>
6064
Disable {type} track
@@ -63,7 +67,7 @@ export const DeviceControls = ({ device, type, status, metadata }: DeviceControl
6367
className="btn btn-success btn-sm"
6468
disabled={status !== "joined" || !device?.stream || !!device?.broadcast?.trackId}
6569
onClick={() => {
66-
device.addTrack(metadata);
70+
device?.addTrack(metadata);
6771
}}
6872
>
6973
Stream {type} track
@@ -72,7 +76,7 @@ export const DeviceControls = ({ device, type, status, metadata }: DeviceControl
7276
className="btn btn-error btn-sm"
7377
disabled={status !== "joined" || !device?.stream || !device?.broadcast?.trackId}
7478
onClick={() => {
75-
device.removeTrack();
79+
device?.removeTrack();
7680
}}
7781
>
7882
Stop {type} track stream

examples/use-camera-and-microphone-example/src/DeviceSelector.tsx

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,41 @@ type Props = {
55
defaultOptionText: string;
66
devices: MediaDeviceInfo[] | null;
77
setInput: (value: string | null) => void;
8-
// inputValue: string | null;
8+
activeDevice: string | null;
99
};
1010

11-
export const DeviceSelector = ({ name, devices, setInput, defaultOptionText }: Props) => {
11+
export const DeviceSelector = ({ name, devices, setInput, defaultOptionText, activeDevice }: Props) => {
1212
const [selectedDevice, setSelectedDevice] = useState<string | null>(null);
1313

1414
const onOptionChangeHandler = (event: ChangeEvent<HTMLSelectElement>) => {
1515
setSelectedDevice(event?.target?.value);
1616
};
1717

1818
return (
19-
<div className="flex flex-row items-center gap-2">
20-
<span>{name}</span>
21-
<select className="select w-full max-w-xs" onChange={onOptionChangeHandler} defaultValue={defaultOptionText}>
22-
<option disabled>{defaultOptionText}</option>
23-
{(devices || []).map(({ deviceId, label }) => (
24-
<option key={deviceId} value={deviceId}>
25-
{label}
26-
</option>
27-
))}
28-
</select>
29-
<button
30-
className="btn btn-error btn-sm"
31-
disabled={!selectedDevice}
32-
onClick={() => {
33-
setInput(selectedDevice);
34-
}}
35-
>
36-
Change device!
37-
</button>
19+
<div className="flex flex-col gap-2">
20+
<div className="flex flex-row">
21+
<span>Selected: {activeDevice}</span>
22+
</div>
23+
<div className="flex flex-row items-center gap-2">
24+
<span>{name}</span>
25+
<select className="select w-full max-w-xs" onChange={onOptionChangeHandler} defaultValue={defaultOptionText}>
26+
<option disabled>{defaultOptionText}</option>
27+
{(devices || []).map(({ deviceId, label }) => (
28+
<option key={deviceId} value={deviceId}>
29+
{label}
30+
</option>
31+
))}
32+
</select>
33+
<button
34+
className="btn btn-error btn-sm"
35+
disabled={!selectedDevice}
36+
onClick={() => {
37+
setInput(selectedDevice);
38+
}}
39+
>
40+
Change device!
41+
</button>
42+
</div>
3843
</div>
3944
);
4045
};

0 commit comments

Comments
 (0)