@fishjam-cloud/react-client 0.28.2 → 0.29.0
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/hooks/internal/useCustomSourceManager.d.ts.map +1 -1
- package/dist/hooks/internal/useCustomSourceManager.js +55 -14
- package/dist/hooks/useCustomSource.d.ts +2 -0
- package/dist/hooks/useCustomSource.d.ts.map +1 -1
- package/dist/hooks/useCustomSource.js +2 -0
- package/dist/hooks/usePeers.d.ts.map +1 -1
- package/dist/hooks/usePeers.js +2 -0
- package/dist/types/public.d.ts +3 -1
- package/dist/types/public.d.ts.map +1 -1
- package/package.json +6 -3
- package/readme.md +1 -5
- package/dist/tests/useCurrentCallback.spec.d.ts +0 -2
- package/dist/tests/useCurrentCallback.spec.d.ts.map +0 -1
- package/dist/tests/useCurrentCallback.spec.js +0 -49
- package/dist/tests/useHandleTrackEnd.spec.d.ts +0 -2
- package/dist/tests/useHandleTrackEnd.spec.d.ts.map +0 -1
- package/dist/tests/useHandleTrackEnd.spec.js +0 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCustomSourceManager.d.ts","sourceRoot":"","sources":["../../../src/hooks/internal/useCustomSourceManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAsC,MAAM,0BAA0B,CAAC;AAG/G,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,KAAK,wBAAwB,GAAG;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC;CAChE,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,EACrC,aAAa,EACb,UAAU,EACV,MAAM,GACP,EAAE,wBAAwB,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"file":"useCustomSourceManager.d.ts","sourceRoot":"","sources":["../../../src/hooks/internal/useCustomSourceManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAsC,MAAM,0BAA0B,CAAC;AAG/G,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,KAAK,wBAAwB,GAAG;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC;CAChE,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,EACrC,aAAa,EACb,UAAU,EACV,MAAM,GACP,EAAE,wBAAwB,GAAG,mBAAmB,CAkKhD"}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { TrackTypeError } from "@fishjam-cloud/ts-client";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
export function useCustomSourceManager({ fishjamClient, peerStatus, logger, }) {
|
|
4
4
|
const [sources, setSources] = useState({});
|
|
5
|
+
// setStream reads the current sources synchronously (to diff against the old stream and to
|
|
6
|
+
// remove stale tracks), but must stay referentially stable so consumers can safely depend on
|
|
7
|
+
// it in effects. Reading through a ref keeps it out of the useCallback deps.
|
|
8
|
+
const sourcesRef = useRef(sources);
|
|
9
|
+
sourcesRef.current = sources;
|
|
10
|
+
// Replacing a source's stream issues two setStream calls in the same tick (unpublish the old,
|
|
11
|
+
// publish the new). Run concurrently they would read the same snapshot and race to remove the
|
|
12
|
+
// same track IDs — and when the publish call loses that race, the new stream is never
|
|
13
|
+
// published. This chain serializes the calls instead.
|
|
14
|
+
const setStreamQueue = useRef(Promise.resolve());
|
|
5
15
|
const pendingSources = useMemo(() => Object.entries(sources).filter(([_, source]) => source.trackIds === undefined), [sources]);
|
|
6
16
|
const getDisplayName = useCallback(() => {
|
|
7
17
|
const name = fishjamClient.getLocalPeer()?.metadata?.peer?.displayName;
|
|
@@ -50,36 +60,67 @@ export function useCustomSourceManager({ fishjamClient, peerStatus, logger, }) {
|
|
|
50
60
|
await Promise.all(promises);
|
|
51
61
|
}, [fishjamClient]);
|
|
52
62
|
const getSource = useCallback((sourceId) => sources[sourceId], [sources]);
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
// Updates both the state (what consumers render) and the ref (what queued setStream calls
|
|
64
|
+
// read synchronously, before React re-renders).
|
|
65
|
+
const updateSources = useCallback((update) => {
|
|
66
|
+
sourcesRef.current = update(sourcesRef.current);
|
|
67
|
+
setSources(update);
|
|
68
|
+
}, []);
|
|
69
|
+
const applySetStream = useCallback(async (sourceId, stream) => {
|
|
70
|
+
const oldSource = sourcesRef.current[sourceId];
|
|
55
71
|
if (stream === oldSource?.stream)
|
|
56
72
|
return;
|
|
57
73
|
if (oldSource?.trackIds)
|
|
58
74
|
await removeTracks(oldSource.trackIds);
|
|
59
75
|
if (stream !== null) {
|
|
60
|
-
|
|
61
|
-
return;
|
|
76
|
+
updateSources((old) => ({ ...old, [sourceId]: { stream } }));
|
|
62
77
|
}
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}, [
|
|
78
|
+
else if (oldSource) {
|
|
79
|
+
updateSources((old) => Object.fromEntries(Object.entries(old).filter(([id]) => id !== sourceId)));
|
|
80
|
+
}
|
|
81
|
+
}, [removeTracks, updateSources]);
|
|
82
|
+
const setStream = useCallback((sourceId, stream) => {
|
|
83
|
+
const run = setStreamQueue.current.then(() => applySetStream(sourceId, stream));
|
|
84
|
+
// Chain a never-rejecting link so one failed call cannot poison the queue; the caller
|
|
85
|
+
// still observes failures through the returned promise.
|
|
86
|
+
setStreamQueue.current = run.catch(() => undefined);
|
|
87
|
+
return run;
|
|
88
|
+
}, [applySetStream]);
|
|
67
89
|
useEffect(() => {
|
|
68
90
|
const onConnected = async () => {
|
|
69
91
|
if (pendingSources.length === 0)
|
|
70
92
|
return;
|
|
71
|
-
const
|
|
72
|
-
|
|
93
|
+
const results = await Promise.all(pendingSources.map(async ([id, source]) => [id, await startStreaming(source)]));
|
|
94
|
+
// While the tracks were being added, setStream may have unpublished the source or replaced
|
|
95
|
+
// its stream. Record track IDs only where the entry is still the one we started streaming
|
|
96
|
+
// (same stream, still no track IDs) — anything else must not be patched (it would resurrect
|
|
97
|
+
// an unpublished source or attach the IDs to a different stream), and the tracks we just
|
|
98
|
+
// added for it are orphans to unpublish again.
|
|
99
|
+
const isStillCurrent = ([id, started]) => {
|
|
100
|
+
const current = sourcesRef.current[id];
|
|
101
|
+
return current !== undefined && current.stream === started.stream && current.trackIds === undefined;
|
|
102
|
+
};
|
|
103
|
+
const patch = results.filter(isStillCurrent);
|
|
104
|
+
const orphans = results.filter((result) => !isStillCurrent(result));
|
|
105
|
+
if (patch.length > 0) {
|
|
106
|
+
updateSources((old) => ({ ...old, ...Object.fromEntries(patch) }));
|
|
107
|
+
}
|
|
108
|
+
for (const [, started] of orphans) {
|
|
109
|
+
if (started.trackIds)
|
|
110
|
+
await removeTracks(started.trackIds);
|
|
111
|
+
}
|
|
73
112
|
};
|
|
74
113
|
const onDisconnected = () => {
|
|
75
|
-
|
|
114
|
+
updateSources((old) => Object.fromEntries(Object.entries(old).map(([id, source]) => [id, { ...source, trackIds: undefined }])));
|
|
76
115
|
};
|
|
116
|
+
// addTrack can reject for reasons other than TrackTypeError (e.g. a disconnect mid-add);
|
|
117
|
+
// surface it instead of leaving an unhandled rejection.
|
|
77
118
|
if (peerStatus === "connected")
|
|
78
|
-
onConnected();
|
|
119
|
+
onConnected().catch((error) => logger.error("Failed to publish custom sources", error));
|
|
79
120
|
fishjamClient.on("disconnected", onDisconnected);
|
|
80
121
|
return () => {
|
|
81
122
|
fishjamClient.off("disconnected", onDisconnected);
|
|
82
123
|
};
|
|
83
|
-
}, [pendingSources, fishjamClient, peerStatus, startStreaming]);
|
|
124
|
+
}, [pendingSources, fishjamClient, peerStatus, startStreaming, removeTracks, updateSources, logger]);
|
|
84
125
|
return { setStream, getSource };
|
|
85
126
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCustomSource.d.ts","sourceRoot":"","sources":["../../src/hooks/useCustomSource.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"useCustomSource.d.ts","sourceRoot":"","sources":["../../src/hooks/useCustomSource.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC;IAczD;;;OAGG;2BARS,WAAW,GAAG,IAAI;IAU9B;;OAEG;;EAGN"}
|
|
@@ -2,6 +2,8 @@ import { useCallback, useContext, useMemo } from "react";
|
|
|
2
2
|
import { CustomSourceContext } from "../contexts/customSource";
|
|
3
3
|
/**
|
|
4
4
|
* This hook can register/deregister a custom MediaStream with Fishjam.
|
|
5
|
+
*
|
|
6
|
+
* @param sourceId - Stable id identifying this custom source.
|
|
5
7
|
* @group Hooks
|
|
6
8
|
*/
|
|
7
9
|
export function useCustomSource(sourceId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePeers.d.ts","sourceRoot":"","sources":["../../src/hooks/usePeers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"usePeers.d.ts","sourceRoot":"","sources":["../../src/hooks/usePeers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,QAAQ,EAIR,OAAO,EACR,MAAM,0BAA0B,CAAC;AAMlC,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAW,MAAM,iBAAiB,CAAC;AAE3E;;;;GAIG;AACH,MAAM,MAAM,cAAc,CAAC,YAAY,EAAE,cAAc,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK,IAAI;IAClF,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IAClD,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,WAAW,CAAC,EAAE,CAAC,CAAC;IAChB,eAAe,CAAC,EAAE,CAAC,CAAC;IACpB,qBAAqB,CAAC,EAAE,CAAC,CAAC;IAC1B,qBAAqB,CAAC,EAAE,CAAC,CAAC;IAC1B,iBAAiB,EAAE,CAAC,EAAE,CAAC;IACvB,iBAAiB,EAAE,CAAC,EAAE,CAAC;CACxB,CAAC;AA2EF;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IA0BrG;;;OAGG;IACH;;OAEG;IACH;;;;OAIG;;IAEH;;;;OAIG;yCAvBQ,MAAM,EAAE,WAAW,OAAO;EA0BxC"}
|
package/dist/hooks/usePeers.js
CHANGED
|
@@ -13,6 +13,8 @@ function trackContextToTrack(track) {
|
|
|
13
13
|
function trackContextToRemoteTrack(track, fishjamClient) {
|
|
14
14
|
return {
|
|
15
15
|
...trackContextToTrack(track),
|
|
16
|
+
encoding: track.encoding,
|
|
17
|
+
encodingReason: track.encodingReason,
|
|
16
18
|
setReceivedQuality: (encoding) => {
|
|
17
19
|
fishjamClient.setTargetTrackEncoding(track.trackId, encoding);
|
|
18
20
|
},
|
package/dist/types/public.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DataCallback, DataChannelOptions, SimulcastConfig, TrackMetadata, Variant } from "@fishjam-cloud/ts-client";
|
|
1
|
+
import type { DataCallback, DataChannelOptions, EncodingReason, SimulcastConfig, TrackMetadata, Variant } from "@fishjam-cloud/ts-client";
|
|
2
2
|
export type InitializeDevicesStatus = "initialized" | "failed" | "initialized_with_errors" | "already_initialized";
|
|
3
3
|
export type InitializeDevicesResult = {
|
|
4
4
|
status: InitializeDevicesStatus;
|
|
@@ -18,6 +18,8 @@ export type Track = {
|
|
|
18
18
|
track: MediaStreamTrack | null;
|
|
19
19
|
};
|
|
20
20
|
export type RemoteTrack = Track & {
|
|
21
|
+
encoding?: Variant;
|
|
22
|
+
encodingReason?: EncodingReason;
|
|
21
23
|
setReceivedQuality: (quality: Variant) => void;
|
|
22
24
|
};
|
|
23
25
|
export type MiddlewareResult = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/types/public.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/types/public.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,aAAa,EACb,OAAO,EACR,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG,QAAQ,GAAG,yBAAyB,GAAG,qBAAqB,CAAC;AAEnH,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,uBAAuB,CAAC;IAChC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE;QAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CACzE,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC/C,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE7C,MAAM,MAAM,KAAK,GAAG;IAClB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AACjF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,EAAE,gBAAgB,KAAK,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAC;AAEjH,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,CAC7B,UAAU,EAAE,gBAAgB,EAC5B,UAAU,EAAE,gBAAgB,GAAG,IAAI,KAChC,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvE,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,MAAM,yBAAyB,GAAG;IACtC,aAAa,EAAE,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,KAAK,eAAe,GAAG,IAAI,CAAC;IACzE,cAAc,EAAE,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,KAAK,IAAI,CAAC;CAChF,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IAAE,aAAa,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,CAAA;CAAE,CAAC;AAEjE,MAAM,MAAM,eAAe,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,wBAAwB,CAAA;CAAE,CAAC;AAE5F,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAE3C,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,sBAAsB,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAEhC,OAAO,CAAC,MAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AACnC,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,MAAM,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtE,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI;IAC3C,EAAE,EAAE,CAAC,CAAC;IACN,QAAQ,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC;;;;OAIG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACxE;;;;;;OAMG;IACH,aAAa,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,kBAAkB,KAAK,MAAM,IAAI,CAAC;IACnF;;;OAGG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,kBAAkB,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,gBAAgB,EAAE,KAAK,GAAG,IAAI,CAAC;CAChC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fishjam-cloud/react-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "React client library for Fishjam",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Fishjam Team",
|
|
@@ -32,9 +32,10 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
|
-
"build": "tsc",
|
|
35
|
+
"build": "tsc -p tsconfig.build.json",
|
|
36
36
|
"e2e": "NODE_OPTIONS=--dns-result-order=ipv4first playwright test",
|
|
37
37
|
"test": "vitest run",
|
|
38
|
+
"tsc": "tsc --noEmit",
|
|
38
39
|
"docs": "typedoc src src/experimental",
|
|
39
40
|
"format": "prettier --write . --ignore-path ./.eslintignore",
|
|
40
41
|
"format:check": "prettier --check . --ignore-path ./.eslintignore",
|
|
@@ -55,6 +56,8 @@
|
|
|
55
56
|
"@types/react": "19.1.0",
|
|
56
57
|
"fake-mediastreamtrack": "^2.0.0",
|
|
57
58
|
"jsdom": "^26.0.0",
|
|
59
|
+
"react": "19.1.0",
|
|
60
|
+
"react-dom": "19.1.0",
|
|
58
61
|
"typed-emitter": "^2.1.0",
|
|
59
62
|
"typedoc": "^0.28.2",
|
|
60
63
|
"typedoc-plugin-mdn-links": "^5.0.1",
|
|
@@ -62,7 +65,7 @@
|
|
|
62
65
|
"vitest": "^3.1.1"
|
|
63
66
|
},
|
|
64
67
|
"dependencies": {
|
|
65
|
-
"@fishjam-cloud/ts-client": "0.
|
|
68
|
+
"@fishjam-cloud/ts-client": "0.29.0",
|
|
66
69
|
"events": "3.3.0",
|
|
67
70
|
"lodash.isequal": "4.5.0"
|
|
68
71
|
},
|
package/readme.md
CHANGED
|
@@ -16,11 +16,7 @@ There is also [API documentation](https://docs.fishjam.io/api/web/) available.
|
|
|
16
16
|
|
|
17
17
|
# Examples
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- [Fishjam Chat](https://github.com/fishjam-cloud/web-client-sdk/tree/main/examples/react-client/fishjam-chat) - example video chat app
|
|
22
|
-
- [minimal-react](https://github.com/fishjam-cloud/web-client-sdk/tree/main/examples/react-client/minimal-react) - minimal example that shows how to connect and share your screen
|
|
23
|
-
- [broadcast](https://github.com/fishjam-cloud/web-client-sdk/tree/main/examples/react-client/broadcast) - minimal example showing how to consume a broadcast stream
|
|
19
|
+
Check out the [examples repository](https://github.com/fishjam-cloud/examples) for apps demonstrating the Fishjam SDKs, such as the [minimal-react example](https://github.com/fishjam-cloud/examples/tree/main/web-react/minimal-react) showing how to connect and share your screen.
|
|
24
20
|
|
|
25
21
|
## License
|
|
26
22
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useCurrentCallback.spec.d.ts","sourceRoot":"","sources":["../../src/tests/useCurrentCallback.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { renderHook } from "@testing-library/react";
|
|
2
|
-
import { describe, expect, it, vi } from "vitest";
|
|
3
|
-
import { useCurrentCallback } from "../hooks/internal/useCurrentCallback";
|
|
4
|
-
describe("useCurrentCallback", () => {
|
|
5
|
-
it("returns a stable function reference across re-renders", () => {
|
|
6
|
-
const { result, rerender } = renderHook((handler) => useCurrentCallback(handler), {
|
|
7
|
-
initialProps: () => undefined,
|
|
8
|
-
});
|
|
9
|
-
const firstRef = result.current;
|
|
10
|
-
rerender(() => undefined);
|
|
11
|
-
rerender(() => undefined);
|
|
12
|
-
expect(result.current).toBe(firstRef);
|
|
13
|
-
});
|
|
14
|
-
it("invokes the latest handler when called after a re-render", () => {
|
|
15
|
-
const first = vi.fn();
|
|
16
|
-
const second = vi.fn();
|
|
17
|
-
const { result, rerender } = renderHook((handler) => useCurrentCallback(handler), {
|
|
18
|
-
initialProps: first,
|
|
19
|
-
});
|
|
20
|
-
result.current();
|
|
21
|
-
expect(first).toHaveBeenCalledTimes(1);
|
|
22
|
-
expect(second).not.toHaveBeenCalled();
|
|
23
|
-
rerender(second);
|
|
24
|
-
result.current();
|
|
25
|
-
expect(first).toHaveBeenCalledTimes(1);
|
|
26
|
-
expect(second).toHaveBeenCalledTimes(1);
|
|
27
|
-
});
|
|
28
|
-
it("forwards arguments and returns the handler's value", () => {
|
|
29
|
-
const handler = vi.fn((a, b) => a + b);
|
|
30
|
-
const { result } = renderHook(() => useCurrentCallback(handler));
|
|
31
|
-
const sum = result.current(2, 3);
|
|
32
|
-
expect(handler).toHaveBeenCalledWith(2, 3);
|
|
33
|
-
expect(sum).toBe(5);
|
|
34
|
-
});
|
|
35
|
-
it("the wrapper captured before a re-render still calls the latest handler", () => {
|
|
36
|
-
const first = vi.fn(() => "first");
|
|
37
|
-
const second = vi.fn(() => "second");
|
|
38
|
-
const { result, rerender } = renderHook((handler) => useCurrentCallback(handler), {
|
|
39
|
-
initialProps: first,
|
|
40
|
-
});
|
|
41
|
-
// Simulates a consumer capturing the reference (e.g. inside a useEffect
|
|
42
|
-
// closure) before the handler closure has changed.
|
|
43
|
-
const captured = result.current;
|
|
44
|
-
rerender(second);
|
|
45
|
-
expect(captured()).toBe("second");
|
|
46
|
-
expect(second).toHaveBeenCalledTimes(1);
|
|
47
|
-
expect(first).not.toHaveBeenCalled();
|
|
48
|
-
});
|
|
49
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useHandleTrackEnd.spec.d.ts","sourceRoot":"","sources":["../../src/tests/useHandleTrackEnd.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { renderHook } from "@testing-library/react";
|
|
2
|
-
import { FakeMediaStreamTrack } from "fake-mediastreamtrack";
|
|
3
|
-
import { describe, expect, it, vi } from "vitest";
|
|
4
|
-
import { useHandleTrackEnd } from "../hooks/internal/devices/useHandleTrackEnd";
|
|
5
|
-
describe("useHandleTrackEnd", () => {
|
|
6
|
-
it("should clear stream on track ended event", () => {
|
|
7
|
-
const clearStream = vi.fn();
|
|
8
|
-
const track = new FakeMediaStreamTrack({ kind: "it literally doesn't matter" });
|
|
9
|
-
renderHook(() => useHandleTrackEnd(track, clearStream));
|
|
10
|
-
expect(track.onended).toBeDefined();
|
|
11
|
-
track.remoteStop();
|
|
12
|
-
expect(clearStream).toHaveBeenCalled();
|
|
13
|
-
});
|
|
14
|
-
});
|