@fishjam-cloud/react-client 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DeviceManager.d.ts +15 -10
- package/dist/DeviceManager.d.ts.map +1 -1
- package/dist/DeviceManager.js +29 -35
- package/dist/constraints.d.ts +2 -22
- package/dist/constraints.d.ts.map +1 -1
- package/dist/constraints.js +11 -16
- package/dist/fishjamProvider.d.ts +10 -8
- package/dist/fishjamProvider.d.ts.map +1 -1
- package/dist/fishjamProvider.js +47 -23
- package/dist/hooks/deviceManagers/useAudioDeviceManager.d.ts +6 -0
- package/dist/hooks/deviceManagers/useAudioDeviceManager.d.ts.map +1 -0
- package/dist/hooks/deviceManagers/useAudioDeviceManager.js +11 -0
- package/dist/hooks/deviceManagers/useDeviceManager.d.ts +4 -0
- package/dist/hooks/deviceManagers/useDeviceManager.d.ts.map +1 -0
- package/dist/hooks/deviceManagers/useDeviceManager.js +39 -0
- package/dist/hooks/deviceManagers/useVideoDeviceManager.d.ts +6 -0
- package/dist/hooks/deviceManagers/useVideoDeviceManager.d.ts.map +1 -0
- package/dist/hooks/deviceManagers/useVideoDeviceManager.js +11 -0
- package/dist/hooks/internal.d.ts +2 -0
- package/dist/hooks/internal.d.ts.map +1 -0
- package/dist/hooks/internal.js +1 -0
- package/dist/hooks/public.d.ts +6 -6
- package/dist/hooks/public.d.ts.map +1 -1
- package/dist/hooks/public.js +6 -6
- package/dist/hooks/useConnection.d.ts +12 -0
- package/dist/hooks/useConnection.d.ts.map +1 -0
- package/dist/hooks/useConnection.js +20 -0
- package/dist/hooks/useDevices.d.ts +19 -0
- package/dist/hooks/useDevices.d.ts.map +1 -0
- package/dist/hooks/useDevices.js +98 -0
- package/dist/hooks/useFishjamClientState.d.ts +10 -0
- package/dist/hooks/useFishjamClientState.d.ts.map +1 -0
- package/dist/hooks/{clientState.js → useFishjamClientState.js} +49 -34
- package/dist/hooks/useFishjamClient_DO_NOT_USE.d.ts +7 -0
- package/dist/hooks/useFishjamClient_DO_NOT_USE.d.ts.map +1 -0
- package/dist/hooks/useFishjamClient_DO_NOT_USE.js +11 -0
- package/dist/hooks/useFishjamContext.d.ts +20 -0
- package/dist/hooks/useFishjamContext.d.ts.map +1 -0
- package/dist/hooks/usePeerStatus.d.ts +8 -0
- package/dist/hooks/usePeerStatus.d.ts.map +1 -0
- package/dist/hooks/usePeerStatus.js +39 -0
- package/dist/hooks/usePeers.d.ts +10 -0
- package/dist/hooks/usePeers.d.ts.map +1 -0
- package/dist/hooks/usePeers.js +19 -0
- package/dist/hooks/useProcessedPreviewStream.d.ts +3 -0
- package/dist/hooks/useProcessedPreviewStream.d.ts.map +1 -0
- package/dist/hooks/useProcessedPreviewStream.js +17 -0
- package/dist/hooks/useReconnection.d.ts +7 -0
- package/dist/hooks/useReconnection.d.ts.map +1 -0
- package/dist/hooks/useReconnection.js +31 -0
- package/dist/hooks/useScreenShare.d.ts +7 -0
- package/dist/hooks/useScreenShare.d.ts.map +1 -0
- package/dist/hooks/{screenShare.js → useScreenShare.js} +53 -24
- package/dist/hooks/useStatus.d.ts +6 -0
- package/dist/hooks/useStatus.d.ts.map +1 -0
- package/dist/hooks/useStatus.js +8 -0
- package/dist/hooks/useTrackManager.d.ts +11 -0
- package/dist/hooks/useTrackManager.d.ts.map +1 -0
- package/dist/hooks/useTrackManager.js +176 -0
- package/dist/index.d.ts +3 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/mediaInitializer.d.ts +2 -2
- package/dist/mediaInitializer.d.ts.map +1 -1
- package/dist/types/internal.d.ts +129 -0
- package/dist/types/internal.d.ts.map +1 -0
- package/dist/types/public.d.ts +65 -0
- package/dist/types/public.d.ts.map +1 -0
- package/dist/utils/errors.d.ts +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/media.d.ts +3 -2
- package/dist/utils/media.d.ts.map +1 -1
- package/dist/utils/track.d.ts +2 -2
- package/dist/utils/track.d.ts.map +1 -1
- package/dist/utils/track.js +0 -2
- package/package.json +12 -15
- package/readme.md +20 -118
- package/dist/Client.d.ts +0 -198
- package/dist/Client.d.ts.map +0 -1
- package/dist/Client.js +0 -461
- package/dist/hooks/clientState.d.ts +0 -4
- package/dist/hooks/clientState.d.ts.map +0 -1
- package/dist/hooks/connection.d.ts +0 -6
- package/dist/hooks/connection.d.ts.map +0 -1
- package/dist/hooks/connection.js +0 -28
- package/dist/hooks/devices.d.ts +0 -4
- package/dist/hooks/devices.d.ts.map +0 -1
- package/dist/hooks/devices.js +0 -9
- package/dist/hooks/fishjamContext.d.ts +0 -4
- package/dist/hooks/fishjamContext.d.ts.map +0 -1
- package/dist/hooks/participants.d.ts +0 -6
- package/dist/hooks/participants.d.ts.map +0 -1
- package/dist/hooks/participants.js +0 -13
- package/dist/hooks/screenShare.d.ts +0 -3
- package/dist/hooks/screenShare.d.ts.map +0 -1
- package/dist/hooks/setupMedia.d.ts +0 -3
- package/dist/hooks/setupMedia.d.ts.map +0 -1
- package/dist/hooks/setupMedia.js +0 -200
- package/dist/hooks/state.d.ts +0 -6
- package/dist/hooks/state.d.ts.map +0 -1
- package/dist/hooks/state.js +0 -15
- package/dist/state.types.d.ts +0 -55
- package/dist/state.types.d.ts.map +0 -1
- package/dist/trackManager.d.ts +0 -9
- package/dist/trackManager.d.ts.map +0 -1
- package/dist/trackManager.js +0 -116
- package/dist/types.d.ts +0 -235
- package/dist/types.d.ts.map +0 -1
- /package/dist/hooks/{fishjamContext.js → useFishjamContext.js} +0 -0
- /package/dist/{state.types.js → types/internal.js} +0 -0
- /package/dist/{types.js → types/public.js} +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { useFishjamContext } from "./useFishjamContext";
|
|
2
|
+
import { useVideoDeviceManager } from "./deviceManagers/useVideoDeviceManager";
|
|
3
|
+
import { useAudioDeviceManager } from "./deviceManagers/useAudioDeviceManager";
|
|
4
|
+
import { useCallback } from "react";
|
|
5
|
+
import { getAvailableMedia, getCorrectedResult } from "../mediaInitializer";
|
|
6
|
+
import { useProcessedPreviewStream } from "./useProcessedPreviewStream";
|
|
7
|
+
import { prepareConstraints } from "../constraints";
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @category Devices
|
|
11
|
+
*/
|
|
12
|
+
export function useCamera() {
|
|
13
|
+
const { videoTrackManager } = useFishjamContext();
|
|
14
|
+
const { deviceState, status } = useVideoDeviceManager();
|
|
15
|
+
const { currentTrack, ...trackManager } = videoTrackManager;
|
|
16
|
+
const processedPreviewStream = useProcessedPreviewStream(videoTrackManager, deviceState.media?.track);
|
|
17
|
+
const stream = currentTrack?.stream ?? processedPreviewStream ?? deviceState.media?.stream ?? null;
|
|
18
|
+
const isStreaming = Boolean(currentTrack?.stream);
|
|
19
|
+
const track = stream?.getAudioTracks()[0] ?? null;
|
|
20
|
+
const trackId = currentTrack?.trackId ?? null;
|
|
21
|
+
const devices = deviceState.devices ?? [];
|
|
22
|
+
const activeDevice = deviceState.media?.deviceInfo ?? null;
|
|
23
|
+
return {
|
|
24
|
+
...trackManager,
|
|
25
|
+
status,
|
|
26
|
+
stream,
|
|
27
|
+
devices,
|
|
28
|
+
activeDevice,
|
|
29
|
+
isStreaming,
|
|
30
|
+
track,
|
|
31
|
+
trackId,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @category Devices
|
|
37
|
+
*/
|
|
38
|
+
export function useMicrophone() {
|
|
39
|
+
const { audioTrackManager } = useFishjamContext();
|
|
40
|
+
const { deviceState, status } = useAudioDeviceManager();
|
|
41
|
+
const { currentTrack, ...trackManager } = audioTrackManager;
|
|
42
|
+
const processedPreviewStream = useProcessedPreviewStream(audioTrackManager, deviceState.media?.track);
|
|
43
|
+
const stream = currentTrack?.stream ?? processedPreviewStream ?? deviceState.media?.stream ?? null;
|
|
44
|
+
const isStreaming = Boolean(currentTrack?.stream);
|
|
45
|
+
const track = stream?.getAudioTracks()[0] ?? null;
|
|
46
|
+
const trackId = currentTrack?.trackId ?? null;
|
|
47
|
+
const devices = deviceState.devices ?? [];
|
|
48
|
+
const activeDevice = deviceState.media?.deviceInfo ?? null;
|
|
49
|
+
const isAudioPlaying = currentTrack?.vadStatus === "speech";
|
|
50
|
+
return {
|
|
51
|
+
...trackManager,
|
|
52
|
+
status,
|
|
53
|
+
stream,
|
|
54
|
+
isStreaming,
|
|
55
|
+
track,
|
|
56
|
+
trackId,
|
|
57
|
+
devices,
|
|
58
|
+
activeDevice,
|
|
59
|
+
isAudioPlaying,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
* @category Devices
|
|
65
|
+
*/
|
|
66
|
+
export const useInitializeDevices = () => {
|
|
67
|
+
const { videoDeviceManagerRef, audioDeviceManagerRef, hasDevicesBeenInitializedRef } = useFishjamContext();
|
|
68
|
+
const initializeDevices = useCallback(async () => {
|
|
69
|
+
if (hasDevicesBeenInitializedRef.current)
|
|
70
|
+
return;
|
|
71
|
+
hasDevicesBeenInitializedRef.current = true;
|
|
72
|
+
const videoManager = videoDeviceManagerRef.current;
|
|
73
|
+
const audioManager = audioDeviceManagerRef.current;
|
|
74
|
+
const constraints = {
|
|
75
|
+
video: videoManager.getConstraints(),
|
|
76
|
+
audio: audioManager.getConstraints(),
|
|
77
|
+
};
|
|
78
|
+
const previousDevices = {
|
|
79
|
+
video: videoManager.getLastDevice(),
|
|
80
|
+
audio: audioManager.getLastDevice(),
|
|
81
|
+
};
|
|
82
|
+
// Attempt to start the last selected device to avoid an unnecessary restart.
|
|
83
|
+
// Without this, the first device will start, and `getCorrectedResult` will attempt to fix it.
|
|
84
|
+
let [stream, deviceErrors] = await getAvailableMedia({
|
|
85
|
+
video: prepareConstraints(previousDevices.video?.deviceId, constraints.video),
|
|
86
|
+
audio: prepareConstraints(previousDevices.audio?.deviceId, constraints.audio),
|
|
87
|
+
});
|
|
88
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
89
|
+
const videoDevices = devices.filter(({ kind }) => kind === "videoinput");
|
|
90
|
+
const audioDevices = devices.filter(({ kind }) => kind === "audioinput");
|
|
91
|
+
if (stream) {
|
|
92
|
+
[stream, deviceErrors] = await getCorrectedResult(stream, deviceErrors, devices, constraints, previousDevices);
|
|
93
|
+
}
|
|
94
|
+
videoManager.initialize(stream, stream?.getVideoTracks()?.[0] ?? null, videoDevices, !!constraints.video, deviceErrors.video);
|
|
95
|
+
audioManager.initialize(stream, stream?.getAudioTracks()?.[0] ?? null, audioDevices, !!constraints.audio, deviceErrors.audio);
|
|
96
|
+
}, [videoDeviceManagerRef, audioDeviceManagerRef, hasDevicesBeenInitializedRef]);
|
|
97
|
+
return { initializeDevices };
|
|
98
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FishjamClient } from "@fishjam-cloud/ts-client";
|
|
2
|
+
import type { PeerMetadata, PeerState, TrackMetadata } from "../types/internal";
|
|
3
|
+
export interface FishjamClientState {
|
|
4
|
+
peers: PeerState[];
|
|
5
|
+
components: PeerState[];
|
|
6
|
+
localPeer: PeerState | null;
|
|
7
|
+
isReconnecting: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function useFishjamClientState(fishjamClient: FishjamClient<PeerMetadata, TrackMetadata>): FishjamClientState;
|
|
10
|
+
//# sourceMappingURL=useFishjamClientState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFishjamClientState.d.ts","sourceRoot":"","sources":["../../src/hooks/useFishjamClientState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA0D,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACtH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAW,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA2CzF,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;CACzB;AAmCD,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC,GAAG,kBAAkB,CAyCnH"}
|
|
@@ -1,38 +1,29 @@
|
|
|
1
|
-
import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
1
|
+
import { useCallback, useMemo, useRef, useSyncExternalStore } from "react";
|
|
2
2
|
const eventNames = [
|
|
3
|
-
"socketOpen",
|
|
4
|
-
"socketError",
|
|
5
3
|
"socketClose",
|
|
4
|
+
"socketError",
|
|
5
|
+
"socketOpen",
|
|
6
6
|
"authSuccess",
|
|
7
7
|
"authError",
|
|
8
8
|
"disconnected",
|
|
9
|
-
"
|
|
10
|
-
"joinError",
|
|
11
|
-
"peerJoined",
|
|
12
|
-
"peerUpdated",
|
|
13
|
-
"peerLeft",
|
|
9
|
+
"reconnectionStarted",
|
|
14
10
|
"reconnected",
|
|
15
11
|
"reconnectionRetriesLimitReached",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"componentUpdated",
|
|
19
|
-
"componentRemoved",
|
|
12
|
+
"joined",
|
|
13
|
+
"joinError",
|
|
20
14
|
"trackReady",
|
|
21
15
|
"trackAdded",
|
|
22
16
|
"trackRemoved",
|
|
23
17
|
"trackUpdated",
|
|
18
|
+
"peerJoined",
|
|
19
|
+
"peerLeft",
|
|
20
|
+
"peerUpdated",
|
|
21
|
+
"componentAdded",
|
|
22
|
+
"componentRemoved",
|
|
23
|
+
"componentUpdated",
|
|
24
|
+
"connectionError",
|
|
25
|
+
"tracksPriorityChanged",
|
|
24
26
|
"bandwidthEstimationChanged",
|
|
25
|
-
"encodingChanged",
|
|
26
|
-
"voiceActivityChanged",
|
|
27
|
-
"deviceDisabled",
|
|
28
|
-
"deviceEnabled",
|
|
29
|
-
"managerInitialized",
|
|
30
|
-
"managerStarted",
|
|
31
|
-
"deviceStopped",
|
|
32
|
-
"deviceReady",
|
|
33
|
-
"devicesStarted",
|
|
34
|
-
"devicesReady",
|
|
35
|
-
"error",
|
|
36
27
|
"targetTrackEncodingRequested",
|
|
37
28
|
"localTrackAdded",
|
|
38
29
|
"localTrackRemoved",
|
|
@@ -47,7 +38,31 @@ const eventNames = [
|
|
|
47
38
|
"localTrackMetadataChanged",
|
|
48
39
|
"disconnectRequested",
|
|
49
40
|
];
|
|
50
|
-
|
|
41
|
+
function trackContextToTrack(track) {
|
|
42
|
+
return {
|
|
43
|
+
metadata: track.metadata,
|
|
44
|
+
trackId: track.trackId,
|
|
45
|
+
stream: track.stream,
|
|
46
|
+
simulcastConfig: track.simulcastConfig ?? null,
|
|
47
|
+
encoding: track.encoding ?? null,
|
|
48
|
+
vadStatus: track.vadStatus,
|
|
49
|
+
track: track.track,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function endpointToPeerState(peer) {
|
|
53
|
+
const tracks = [...peer.tracks].reduce((acc, [, track]) => ({ ...acc, [track.trackId]: trackContextToTrack(track) }), {});
|
|
54
|
+
return {
|
|
55
|
+
metadata: peer.metadata,
|
|
56
|
+
id: peer.id,
|
|
57
|
+
tracks,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/*
|
|
61
|
+
This is an internally used hook.
|
|
62
|
+
It is not meant to be used by the end user.
|
|
63
|
+
*/
|
|
64
|
+
export function useFishjamClientState(fishjamClient) {
|
|
65
|
+
const client = useMemo(() => fishjamClient, [fishjamClient]);
|
|
51
66
|
const mutationRef = useRef(false);
|
|
52
67
|
const subscribe = useCallback((subscribeCallback) => {
|
|
53
68
|
const callback = () => {
|
|
@@ -62,20 +77,20 @@ export const useClientState = (client) => {
|
|
|
62
77
|
const lastSnapshotRef = useRef(null);
|
|
63
78
|
const getSnapshot = useCallback(() => {
|
|
64
79
|
if (mutationRef.current || lastSnapshotRef.current === null) {
|
|
80
|
+
const peers = Object.values(client.getRemotePeers()).map(endpointToPeerState);
|
|
81
|
+
const components = Object.values(client.getRemoteComponents()).map(endpointToPeerState);
|
|
82
|
+
const localEndpoint = client.getLocalPeer();
|
|
83
|
+
const localPeer = localEndpoint ? endpointToPeerState(localEndpoint) : null;
|
|
84
|
+
const isReconnecting = client.isReconnecting();
|
|
65
85
|
lastSnapshotRef.current = {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
local: client.local,
|
|
71
|
-
status: client.status,
|
|
72
|
-
devices: client.devices,
|
|
73
|
-
client: client,
|
|
74
|
-
reconnectionStatus: client.reconnectionStatus,
|
|
86
|
+
peers,
|
|
87
|
+
components,
|
|
88
|
+
localPeer,
|
|
89
|
+
isReconnecting,
|
|
75
90
|
};
|
|
76
91
|
mutationRef.current = false;
|
|
77
92
|
}
|
|
78
93
|
return lastSnapshotRef.current;
|
|
79
94
|
}, [client]);
|
|
80
95
|
return useSyncExternalStore(subscribe, getSnapshot);
|
|
81
|
-
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @category Connection
|
|
4
|
+
* @deprecated
|
|
5
|
+
*/
|
|
6
|
+
export declare function useFishjamClient_DO_NOT_USE(): import("@fishjam-cloud/ts-client").FishjamClient<import("../types/internal").PeerMetadata, import("../types/internal").TrackMetadata>;
|
|
7
|
+
//# sourceMappingURL=useFishjamClient_DO_NOT_USE.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFishjamClient_DO_NOT_USE.d.ts","sourceRoot":"","sources":["../../src/hooks/useFishjamClient_DO_NOT_USE.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,2BAA2B,0IAI1C"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useFishjamContext } from "./useFishjamContext";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @category Connection
|
|
6
|
+
* @deprecated
|
|
7
|
+
*/
|
|
8
|
+
export function useFishjamClient_DO_NOT_USE() {
|
|
9
|
+
const client = useFishjamContext().fishjamClientRef.current;
|
|
10
|
+
return useMemo(() => client, [client]);
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FishjamClient } from "@fishjam-cloud/ts-client";
|
|
2
|
+
import { type MutableRefObject } from "react";
|
|
3
|
+
import type { PeerMetadata, TrackMetadata, ScreenShareState, TrackManager } from "../types/internal";
|
|
4
|
+
import type { DeviceManager } from "../DeviceManager";
|
|
5
|
+
import type { FishjamClientState } from "./useFishjamClientState";
|
|
6
|
+
import type { PeerStatus } from "../types/public";
|
|
7
|
+
export type FishjamContextType = {
|
|
8
|
+
fishjamClientRef: MutableRefObject<FishjamClient<PeerMetadata, TrackMetadata>>;
|
|
9
|
+
videoDeviceManagerRef: MutableRefObject<DeviceManager>;
|
|
10
|
+
audioDeviceManagerRef: MutableRefObject<DeviceManager>;
|
|
11
|
+
hasDevicesBeenInitializedRef: MutableRefObject<boolean>;
|
|
12
|
+
screenShareState: [ScreenShareState, React.Dispatch<React.SetStateAction<ScreenShareState>>];
|
|
13
|
+
peerStatus: PeerStatus;
|
|
14
|
+
videoTrackManager: TrackManager;
|
|
15
|
+
audioTrackManager: TrackManager;
|
|
16
|
+
clientState: FishjamClientState;
|
|
17
|
+
};
|
|
18
|
+
export declare const FishjamContext: import("react").Context<FishjamContextType | null>;
|
|
19
|
+
export declare function useFishjamContext(): FishjamContextType;
|
|
20
|
+
//# sourceMappingURL=useFishjamContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFishjamContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useFishjamContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAiB,KAAK,gBAAgB,EAAc,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACrG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,gBAAgB,CAAC,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;IAC/E,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACvD,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACvD,4BAA4B,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACxD,gBAAgB,EAAE,CAAC,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC7F,UAAU,EAAE,UAAU,CAAC;IACvB,iBAAiB,EAAE,YAAY,CAAC;IAChC,iBAAiB,EAAE,YAAY,CAAC;IAChC,WAAW,EAAE,kBAAkB,CAAC;CACjC,CAAC;AAEF,eAAO,MAAM,cAAc,oDAAiD,CAAC;AAE7E,wBAAgB,iBAAiB,IAGb,kBAAkB,CACrC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FishjamClient } from "@fishjam-cloud/ts-client";
|
|
2
|
+
import type { PeerMetadata, TrackMetadata } from "../types/internal";
|
|
3
|
+
import type { PeerStatus } from "../types/public";
|
|
4
|
+
export declare const usePeerStatus: (client: FishjamClient<PeerMetadata, TrackMetadata>) => {
|
|
5
|
+
readonly peerStatus: PeerStatus;
|
|
6
|
+
readonly getCurrentPeerStatus: () => PeerStatus;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=usePeerStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePeerStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/usePeerStatus.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,eAAO,MAAM,aAAa,WAAY,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC;;;CA8C/E,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
export const usePeerStatus = (client) => {
|
|
3
|
+
const [peerStatus, setPeerStatusState] = useState("idle");
|
|
4
|
+
const peerStatusRef = useRef("idle");
|
|
5
|
+
const setPeerStatus = useCallback((status) => {
|
|
6
|
+
peerStatusRef.current = status;
|
|
7
|
+
setPeerStatusState(status);
|
|
8
|
+
}, [setPeerStatusState]);
|
|
9
|
+
const getCurrentPeerStatus = useCallback(() => peerStatusRef.current, []);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const setConnecting = () => {
|
|
12
|
+
setPeerStatus("connecting");
|
|
13
|
+
};
|
|
14
|
+
const setError = () => {
|
|
15
|
+
setPeerStatus("error");
|
|
16
|
+
};
|
|
17
|
+
const setJoined = () => {
|
|
18
|
+
setPeerStatus("connected");
|
|
19
|
+
};
|
|
20
|
+
const setDisconnected = () => {
|
|
21
|
+
setPeerStatus("idle");
|
|
22
|
+
};
|
|
23
|
+
client.on("connectionStarted", setConnecting);
|
|
24
|
+
client.on("joined", setJoined);
|
|
25
|
+
client.on("authError", setError);
|
|
26
|
+
client.on("joinError", setError);
|
|
27
|
+
client.on("connectionError", setError);
|
|
28
|
+
client.on("disconnected", setDisconnected);
|
|
29
|
+
return () => {
|
|
30
|
+
client.off("connectionStarted", setConnecting);
|
|
31
|
+
client.off("joined", setJoined);
|
|
32
|
+
client.off("authError", setError);
|
|
33
|
+
client.off("joinError", setError);
|
|
34
|
+
client.off("connectionError", setError);
|
|
35
|
+
client.off("disconnected", setDisconnected);
|
|
36
|
+
};
|
|
37
|
+
}, [client, setPeerStatus]);
|
|
38
|
+
return { peerStatus, getCurrentPeerStatus };
|
|
39
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePeers.d.ts","sourceRoot":"","sources":["../../src/hooks/usePeers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AActD;;;GAGG;AACH,wBAAgB,QAAQ;;;EAOvB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useFishjamContext } from "./useFishjamContext";
|
|
2
|
+
function getPeerWithDistinguishedTracks(peerState) {
|
|
3
|
+
const peerTracks = Object.values(peerState.tracks ?? {});
|
|
4
|
+
const cameraTrack = peerTracks.find(({ metadata }) => metadata?.type === "camera");
|
|
5
|
+
const microphoneTrack = peerTracks.find(({ metadata }) => metadata?.type === "microphone");
|
|
6
|
+
const screenShareVideoTrack = peerTracks.find(({ metadata }) => metadata?.type === "screenShareVideo");
|
|
7
|
+
const screenShareAudioTrack = peerTracks.find(({ metadata }) => metadata?.type === "screenShareAudio");
|
|
8
|
+
return { ...peerState, cameraTrack, microphoneTrack, screenShareVideoTrack, screenShareAudioTrack };
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @category Connection
|
|
13
|
+
*/
|
|
14
|
+
export function usePeers() {
|
|
15
|
+
const { clientState } = useFishjamContext();
|
|
16
|
+
const localPeer = clientState.localPeer ? getPeerWithDistinguishedTracks(clientState.localPeer) : null;
|
|
17
|
+
const peers = Object.values(clientState.peers).map(getPeerWithDistinguishedTracks);
|
|
18
|
+
return { localPeer, peers };
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useProcessedPreviewStream.d.ts","sourceRoot":"","sources":["../../src/hooks/useProcessedPreviewStream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,sBAiBjD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
export function useProcessedPreviewStream(trackManager, deviceTrack) {
|
|
3
|
+
const [previewStream, setPreviewStream] = useState(null);
|
|
4
|
+
const { currentTrack, currentTrackMiddleware } = trackManager;
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
if (currentTrack || !deviceTrack)
|
|
7
|
+
return;
|
|
8
|
+
const result = currentTrackMiddleware?.(deviceTrack);
|
|
9
|
+
if (result?.track)
|
|
10
|
+
setPreviewStream(new MediaStream([result.track]));
|
|
11
|
+
return () => {
|
|
12
|
+
result?.onClear?.();
|
|
13
|
+
setPreviewStream(null);
|
|
14
|
+
};
|
|
15
|
+
}, [currentTrack, deviceTrack, currentTrackMiddleware]);
|
|
16
|
+
return previewStream;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useReconnection.d.ts","sourceRoot":"","sources":["../../src/hooks/useReconnection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAO,kBA6BlC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { useFishjamContext } from "./useFishjamContext";
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @category Connection
|
|
6
|
+
*/
|
|
7
|
+
export const useReconnection = () => {
|
|
8
|
+
const { fishjamClientRef } = useFishjamContext();
|
|
9
|
+
const [reconnectionStatus, setReconnectionStatus] = useState("idle");
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const client = fishjamClientRef.current;
|
|
12
|
+
const setReconnecting = () => {
|
|
13
|
+
setReconnectionStatus("reconnecting");
|
|
14
|
+
};
|
|
15
|
+
const setIdle = () => {
|
|
16
|
+
setReconnectionStatus("idle");
|
|
17
|
+
};
|
|
18
|
+
const setError = () => {
|
|
19
|
+
setReconnectionStatus("error");
|
|
20
|
+
};
|
|
21
|
+
client.on("reconnectionStarted", setReconnecting);
|
|
22
|
+
client.on("reconnected", setIdle);
|
|
23
|
+
client.on("reconnectionRetriesLimitReached", setError);
|
|
24
|
+
return () => {
|
|
25
|
+
client.off("reconnectionStarted", setReconnecting);
|
|
26
|
+
client.off("reconnected", setIdle);
|
|
27
|
+
client.off("reconnectionRetriesLimitReached", setError);
|
|
28
|
+
};
|
|
29
|
+
}, [fishjamClientRef]);
|
|
30
|
+
return reconnectionStatus;
|
|
31
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScreenShare.d.ts","sourceRoot":"","sources":["../../src/hooks/useScreenShare.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAQxE;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,cA0IjC,CAAC"}
|
|
@@ -1,24 +1,40 @@
|
|
|
1
|
-
import { useCallback, useEffect } from "react";
|
|
1
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
2
2
|
import { getRemoteOrLocalTrack } from "../utils/track";
|
|
3
|
-
import { useFishjamContext } from "./
|
|
3
|
+
import { useFishjamContext } from "./useFishjamContext";
|
|
4
4
|
const getTracks = (stream) => {
|
|
5
5
|
const video = stream.getVideoTracks()[0];
|
|
6
6
|
const audio = stream.getAudioTracks()[0] ?? null;
|
|
7
7
|
return [video, audio];
|
|
8
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @category Screenshare
|
|
12
|
+
*/
|
|
9
13
|
export const useScreenShare = () => {
|
|
10
14
|
const ctx = useFishjamContext();
|
|
11
|
-
const [state, setState] = ctx.
|
|
12
|
-
const
|
|
15
|
+
const [state, setState] = ctx.screenShareState;
|
|
16
|
+
const cleanMiddlewareFnRef = useRef(null);
|
|
17
|
+
const { fishjamClientRef } = useFishjamContext();
|
|
18
|
+
const tsClient = fishjamClientRef.current;
|
|
19
|
+
const stream = state.stream ?? null;
|
|
20
|
+
const [videoTrack, audioTrack] = stream ? getTracks(stream) : [null, null];
|
|
21
|
+
const getDisplayName = () => tsClient.getLocalPeer()?.metadata?.peer?.displayName;
|
|
13
22
|
const startStreaming = async (props) => {
|
|
14
23
|
const stream = await navigator.mediaDevices.getDisplayMedia({
|
|
15
24
|
video: props?.videoConstraints ?? true,
|
|
16
25
|
audio: props?.audioConstraints ?? true,
|
|
17
26
|
});
|
|
18
|
-
const
|
|
19
|
-
|
|
27
|
+
const displayName = getDisplayName();
|
|
28
|
+
let [video, audio] = getTracks(stream);
|
|
29
|
+
if (state.tracksMiddleware) {
|
|
30
|
+
const { videoTrack, audioTrack, onClear } = state.tracksMiddleware(video, audio);
|
|
31
|
+
video = videoTrack;
|
|
32
|
+
audio = audioTrack;
|
|
33
|
+
cleanMiddlewareFnRef.current = onClear;
|
|
34
|
+
}
|
|
35
|
+
const addTrackPromises = [tsClient.addTrack(video, { displayName, type: "screenShareVideo", paused: false })];
|
|
20
36
|
if (audio)
|
|
21
|
-
addTrackPromises.push(tsClient.addTrack(audio));
|
|
37
|
+
addTrackPromises.push(tsClient.addTrack(audio, { displayName, type: "screenShareAudio", paused: false }));
|
|
22
38
|
const [videoId, audioId] = await Promise.all(addTrackPromises);
|
|
23
39
|
setState({ stream, trackIds: { videoId, audioId } });
|
|
24
40
|
};
|
|
@@ -31,15 +47,25 @@ export const useScreenShare = () => {
|
|
|
31
47
|
}
|
|
32
48
|
await Promise.all(addTrackPromises);
|
|
33
49
|
};
|
|
50
|
+
const cleanMiddleware = useCallback(() => {
|
|
51
|
+
cleanMiddlewareFnRef.current?.();
|
|
52
|
+
cleanMiddlewareFnRef.current = null;
|
|
53
|
+
}, []);
|
|
34
54
|
const setTracksMiddleware = async (middleware) => {
|
|
35
55
|
if (!state?.stream)
|
|
36
56
|
return;
|
|
37
|
-
const [
|
|
38
|
-
|
|
39
|
-
|
|
57
|
+
const [video, audio] = getTracks(state.stream);
|
|
58
|
+
cleanMiddleware();
|
|
59
|
+
const { videoTrack, audioTrack, onClear } = middleware?.(video, audio) ?? {
|
|
60
|
+
videoTrack: video,
|
|
61
|
+
audioTrack: audio,
|
|
62
|
+
onClear: null,
|
|
63
|
+
};
|
|
64
|
+
cleanMiddlewareFnRef.current = onClear;
|
|
65
|
+
await replaceTracks(videoTrack, audioTrack);
|
|
40
66
|
};
|
|
41
67
|
const stopStreaming = useCallback(async () => {
|
|
42
|
-
if (!state) {
|
|
68
|
+
if (!state.stream) {
|
|
43
69
|
console.warn("No stream to stop");
|
|
44
70
|
return;
|
|
45
71
|
}
|
|
@@ -47,14 +73,16 @@ export const useScreenShare = () => {
|
|
|
47
73
|
video.stop();
|
|
48
74
|
if (audio)
|
|
49
75
|
audio.stop();
|
|
50
|
-
const
|
|
76
|
+
const client = fishjamClientRef.current;
|
|
77
|
+
const removeTrackPromises = [client.removeTrack(state.trackIds.videoId)];
|
|
51
78
|
if (state.trackIds.audioId)
|
|
52
|
-
removeTrackPromises.push(
|
|
79
|
+
removeTrackPromises.push(client.removeTrack(state.trackIds.audioId));
|
|
53
80
|
await Promise.all(removeTrackPromises);
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
cleanMiddleware();
|
|
82
|
+
setState(({ tracksMiddleware }) => ({ stream: null, trackIds: null, tracksMiddleware }));
|
|
83
|
+
}, [state, fishjamClientRef, setState, cleanMiddleware]);
|
|
56
84
|
useEffect(() => {
|
|
57
|
-
if (!state)
|
|
85
|
+
if (!state.stream)
|
|
58
86
|
return;
|
|
59
87
|
const [video, audio] = getTracks(state.stream);
|
|
60
88
|
const trackEndedHandler = () => {
|
|
@@ -68,18 +96,19 @@ export const useScreenShare = () => {
|
|
|
68
96
|
};
|
|
69
97
|
}, [state, stopStreaming]);
|
|
70
98
|
useEffect(() => {
|
|
99
|
+
const client = fishjamClientRef.current;
|
|
71
100
|
const onDisconnected = () => {
|
|
72
|
-
|
|
101
|
+
if (stream) {
|
|
102
|
+
stopStreaming();
|
|
103
|
+
}
|
|
73
104
|
};
|
|
74
|
-
|
|
105
|
+
client.on("disconnected", onDisconnected);
|
|
75
106
|
return () => {
|
|
76
|
-
|
|
107
|
+
client.removeListener("disconnected", onDisconnected);
|
|
77
108
|
};
|
|
78
|
-
}, [stopStreaming,
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
const videoBroadcast = state ? getRemoteOrLocalTrack(tsClient, state.trackIds.videoId) : null;
|
|
82
|
-
const audioBroadcast = state?.trackIds.audioId ? getRemoteOrLocalTrack(tsClient, state.trackIds.audioId) : null;
|
|
109
|
+
}, [stopStreaming, fishjamClientRef, stream]);
|
|
110
|
+
const videoBroadcast = state.stream ? getRemoteOrLocalTrack(tsClient, state.trackIds.videoId) : null;
|
|
111
|
+
const audioBroadcast = state.trackIds?.audioId ? getRemoteOrLocalTrack(tsClient, state.trackIds.audioId) : null;
|
|
83
112
|
return {
|
|
84
113
|
startStreaming,
|
|
85
114
|
stopStreaming,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useStatus.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,SAAS,4BAExB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FishjamClient } from "@fishjam-cloud/ts-client";
|
|
2
|
+
import type { MediaManager, PeerMetadata, TrackManager, TrackMetadata } from "../types/internal";
|
|
3
|
+
import type { PeerStatus } from "../types/public";
|
|
4
|
+
interface TrackManagerConfig {
|
|
5
|
+
mediaManager: MediaManager;
|
|
6
|
+
tsClient: FishjamClient<PeerMetadata, TrackMetadata>;
|
|
7
|
+
getCurrentPeerStatus: () => PeerStatus;
|
|
8
|
+
}
|
|
9
|
+
export declare const useTrackManager: ({ mediaManager, tsClient, getCurrentPeerStatus }: TrackManagerConfig) => TrackManager;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=useTrackManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTrackManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useTrackManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAwC,MAAM,0BAA0B,CAAC;AACpG,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGjG,OAAO,KAAK,EAAE,UAAU,EAA+B,MAAM,iBAAiB,CAAC;AAE/E,UAAU,kBAAkB;IAC1B,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IACrD,oBAAoB,EAAE,MAAM,UAAU,CAAC;CACxC;AAOD,eAAO,MAAM,eAAe,qDAAsD,kBAAkB,KAAG,YA2MtG,CAAC"}
|