@fishjam-cloud/react-native-client 0.1.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/.eslintignore +7 -0
- package/.eslintrc +6 -0
- package/.prettierrc +9 -0
- package/.watchmanconfig +1 -0
- package/android/.editorconfig +9 -0
- package/android/build.gradle +89 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/org/membraneframework/reactnative/AudioDeviceKind.kt +34 -0
- package/android/src/main/java/org/membraneframework/reactnative/AudioSwitchManager.kt +61 -0
- package/android/src/main/java/org/membraneframework/reactnative/EmitableEvents.kt +14 -0
- package/android/src/main/java/org/membraneframework/reactnative/Errors.kt +31 -0
- package/android/src/main/java/org/membraneframework/reactnative/RNFishjamClient.kt +866 -0
- package/android/src/main/java/org/membraneframework/reactnative/RNFishjamClientModule.kt +294 -0
- package/android/src/main/java/org/membraneframework/reactnative/Utils.kt +11 -0
- package/android/src/main/java/org/membraneframework/reactnative/VideoPreviewView.kt +40 -0
- package/android/src/main/java/org/membraneframework/reactnative/VideoPreviewViewModule.kt +17 -0
- package/android/src/main/java/org/membraneframework/reactnative/VideoRendererView.kt +58 -0
- package/android/src/main/java/org/membraneframework/reactnative/VideoRendererViewModule.kt +25 -0
- package/android/src/main/java/org/membraneframework/reactnative/VideoView.kt +77 -0
- package/app.plugin.js +1 -0
- package/babel.config.js +2 -0
- package/build/RNFishjamClientModule.d.ts +47 -0
- package/build/RNFishjamClientModule.d.ts.map +1 -0
- package/build/RNFishjamClientModule.js +4 -0
- package/build/RNFishjamClientModule.js.map +1 -0
- package/build/common/client.d.ts +19 -0
- package/build/common/client.d.ts.map +1 -0
- package/build/common/client.js +8 -0
- package/build/common/client.js.map +1 -0
- package/build/common/eventEmitter.d.ts +16 -0
- package/build/common/eventEmitter.d.ts.map +1 -0
- package/build/common/eventEmitter.js +17 -0
- package/build/common/eventEmitter.js.map +1 -0
- package/build/common/metadata.d.ts +7 -0
- package/build/common/metadata.d.ts.map +1 -0
- package/build/common/metadata.js +9 -0
- package/build/common/metadata.js.map +1 -0
- package/build/common/webRTC.d.ts +19 -0
- package/build/common/webRTC.d.ts.map +1 -0
- package/build/common/webRTC.js +22 -0
- package/build/common/webRTC.js.map +1 -0
- package/build/components/VideoPreviewView.d.ts +21 -0
- package/build/components/VideoPreviewView.d.ts.map +1 -0
- package/build/components/VideoPreviewView.js +7 -0
- package/build/components/VideoPreviewView.js.map +1 -0
- package/build/components/VideoRendererView.d.ts +19 -0
- package/build/components/VideoRendererView.d.ts.map +1 -0
- package/build/components/VideoRendererView.js +7 -0
- package/build/components/VideoRendererView.js.map +1 -0
- package/build/hooks/useAudioSettings.d.ts +23 -0
- package/build/hooks/useAudioSettings.d.ts.map +1 -0
- package/build/hooks/useAudioSettings.js +72 -0
- package/build/hooks/useAudioSettings.js.map +1 -0
- package/build/hooks/useBandwidthEstimation.d.ts +12 -0
- package/build/hooks/useBandwidthEstimation.d.ts.map +1 -0
- package/build/hooks/useBandwidthEstimation.js +16 -0
- package/build/hooks/useBandwidthEstimation.js.map +1 -0
- package/build/hooks/useCamera.d.ts +80 -0
- package/build/hooks/useCamera.d.ts.map +1 -0
- package/build/hooks/useCamera.js +140 -0
- package/build/hooks/useCamera.js.map +1 -0
- package/build/hooks/useMicrophone.d.ts +8 -0
- package/build/hooks/useMicrophone.d.ts.map +1 -0
- package/build/hooks/useMicrophone.js +27 -0
- package/build/hooks/useMicrophone.js.map +1 -0
- package/build/hooks/useParticipants.d.ts +62 -0
- package/build/hooks/useParticipants.d.ts.map +1 -0
- package/build/hooks/useParticipants.js +32 -0
- package/build/hooks/useParticipants.js.map +1 -0
- package/build/hooks/useReconnection.d.ts +5 -0
- package/build/hooks/useReconnection.d.ts.map +1 -0
- package/build/hooks/useReconnection.js +23 -0
- package/build/hooks/useReconnection.js.map +1 -0
- package/build/hooks/useScreencast.d.ts +38 -0
- package/build/hooks/useScreencast.d.ts.map +1 -0
- package/build/hooks/useScreencast.js +81 -0
- package/build/hooks/useScreencast.js.map +1 -0
- package/build/index.d.ts +24 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +14 -0
- package/build/index.js.map +1 -0
- package/build/protos/fishjam/peer_notifications.d.ts +63 -0
- package/build/protos/fishjam/peer_notifications.d.ts.map +1 -0
- package/build/protos/fishjam/peer_notifications.js +235 -0
- package/build/protos/fishjam/peer_notifications.js.map +1 -0
- package/build/stats/types.d.ts +55 -0
- package/build/stats/types.d.ts.map +1 -0
- package/build/stats/types.js +2 -0
- package/build/stats/types.js.map +1 -0
- package/build/stats/useRTCStatistics.d.ts +8 -0
- package/build/stats/useRTCStatistics.d.ts.map +1 -0
- package/build/stats/useRTCStatistics.js +78 -0
- package/build/stats/useRTCStatistics.js.map +1 -0
- package/build/types.d.ts +43 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/expo-module.config.json +17 -0
- package/ios/Events.swift +13 -0
- package/ios/RNFishjamClient.podspec +30 -0
- package/ios/RNFishjamClient.swift +836 -0
- package/ios/RNFishjamClientModule.swift +220 -0
- package/ios/Utils.swift +43 -0
- package/ios/VideoPreviewView.swift +64 -0
- package/ios/VideoPreviewViewModule.swift +21 -0
- package/ios/VideoRendererView.swift +84 -0
- package/ios/VideoRendererViewModule.swift +17 -0
- package/ios/swift-format-config.json +56 -0
- package/package.json +89 -0
- package/plugin/broadcastExtensionFiles/Info.plist +27 -0
- package/plugin/broadcastExtensionFiles/MembraneBroadcastSampleHandler.swift +50 -0
- package/plugin/broadcastExtensionFiles/MembraneScreenBroadcastExtension.entitlements +10 -0
- package/plugin/src/withMembrane.ts +310 -0
- package/plugin/tsconfig.json +9 -0
- package/scripts/lint.sh +18 -0
- package/scripts/lint_check.sh +14 -0
- package/src/RNFishjamClientModule.ts +73 -0
- package/src/__tests__/index.test.tsx +199 -0
- package/src/common/client.ts +33 -0
- package/src/common/eventEmitter.ts +21 -0
- package/src/common/metadata.ts +12 -0
- package/src/common/webRTC.ts +31 -0
- package/src/components/VideoPreviewView.tsx +33 -0
- package/src/components/VideoRendererView.tsx +31 -0
- package/src/hooks/useAudioSettings.ts +115 -0
- package/src/hooks/useBandwidthEstimation.ts +24 -0
- package/src/hooks/useCamera.ts +270 -0
- package/src/hooks/useMicrophone.ts +38 -0
- package/src/hooks/useParticipants.ts +118 -0
- package/src/hooks/useReconnection.ts +41 -0
- package/src/hooks/useScreencast.ts +146 -0
- package/src/index.tsx +63 -0
- package/src/protos/fishjam/peer_notifications.ts +299 -0
- package/src/stats/types.ts +56 -0
- package/src/stats/useRTCStatistics.ts +97 -0
- package/src/types.ts +49 -0
- package/tsconfig.json +9 -0
- package/typedoc.json +5 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import RNFishjamClientModule from '../RNFishjamClientModule';
|
|
3
|
+
import { ReceivableEvents, eventEmitter } from '../common/eventEmitter';
|
|
4
|
+
/**
|
|
5
|
+
* This hook can toggle microphone on/off and provides current microphone state.
|
|
6
|
+
*/
|
|
7
|
+
export function useMicrophone() {
|
|
8
|
+
const [isMicrophoneOn, setIsMicrophoneOn] = useState(RNFishjamClientModule.isMicrophoneOn);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const eventListener = eventEmitter.addListener(ReceivableEvents.IsMicrophoneOn, (event) => setIsMicrophoneOn(event.IsMicrophoneOn));
|
|
11
|
+
setIsMicrophoneOn(RNFishjamClientModule.isMicrophoneOn);
|
|
12
|
+
return () => eventListener.remove();
|
|
13
|
+
}, []);
|
|
14
|
+
/**
|
|
15
|
+
* Function to toggle microphone on/off
|
|
16
|
+
*/
|
|
17
|
+
const toggleMicrophone = useCallback(async () => {
|
|
18
|
+
const status = await RNFishjamClientModule.toggleMicrophone();
|
|
19
|
+
await RNFishjamClientModule.updateAudioTrackMetadata({
|
|
20
|
+
active: status,
|
|
21
|
+
type: 'audio',
|
|
22
|
+
});
|
|
23
|
+
setIsMicrophoneOn(status);
|
|
24
|
+
}, []);
|
|
25
|
+
return { isMicrophoneOn, toggleMicrophone };
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=useMicrophone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMicrophone.js","sourceRoot":"","sources":["../../src/hooks/useMicrophone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,qBAAqB,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAIxE;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAClD,qBAAqB,CAAC,cAAc,CACrC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,aAAa,GAAG,YAAY,CAAC,WAAW,CAC5C,gBAAgB,CAAC,cAAc,EAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,cAAc,CAAC,CACnD,CAAC;QACF,iBAAiB,CAAC,qBAAqB,CAAC,cAAc,CAAC,CAAC;QACxD,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;IACtC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP;;OAEG;IACH,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC9C,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;QAC9D,MAAM,qBAAqB,CAAC,wBAAwB,CAAC;YACnD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QACH,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC;AAC9C,CAAC","sourcesContent":["import { useCallback, useEffect, useState } from 'react';\n\nimport RNFishjamClientModule from '../RNFishjamClientModule';\nimport { ReceivableEvents, eventEmitter } from '../common/eventEmitter';\n\ntype IsMicrophoneOnEvent = { IsMicrophoneOn: boolean };\n\n/**\n * This hook can toggle microphone on/off and provides current microphone state.\n */\nexport function useMicrophone() {\n const [isMicrophoneOn, setIsMicrophoneOn] = useState<boolean>(\n RNFishjamClientModule.isMicrophoneOn,\n );\n\n useEffect(() => {\n const eventListener = eventEmitter.addListener<IsMicrophoneOnEvent>(\n ReceivableEvents.IsMicrophoneOn,\n (event) => setIsMicrophoneOn(event.IsMicrophoneOn),\n );\n setIsMicrophoneOn(RNFishjamClientModule.isMicrophoneOn);\n return () => eventListener.remove();\n }, []);\n\n /**\n * Function to toggle microphone on/off\n */\n const toggleMicrophone = useCallback(async () => {\n const status = await RNFishjamClientModule.toggleMicrophone();\n await RNFishjamClientModule.updateAudioTrackMetadata({\n active: status,\n type: 'audio',\n });\n setIsMicrophoneOn(status);\n }, []);\n\n return { isMicrophoneOn, toggleMicrophone };\n}\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { GenericMetadata, TrackEncoding } from '../types';
|
|
2
|
+
export type TrackType = 'Audio' | 'Video';
|
|
3
|
+
/**
|
|
4
|
+
* Type describing Voice Activity Detection statuses.
|
|
5
|
+
*
|
|
6
|
+
* speech - voice activity has been detected
|
|
7
|
+
* silence - lack of voice activity has been detected
|
|
8
|
+
*/
|
|
9
|
+
export type VadStatus = 'silence' | 'speech';
|
|
10
|
+
type TrackBase = {
|
|
11
|
+
id: string;
|
|
12
|
+
type: TrackType;
|
|
13
|
+
isActive: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type AudioTrack = TrackBase & {
|
|
16
|
+
type: 'Audio';
|
|
17
|
+
vadStatus: VadStatus | undefined;
|
|
18
|
+
};
|
|
19
|
+
export type VideoTrack = TrackBase & {
|
|
20
|
+
type: 'Video';
|
|
21
|
+
encoding: TrackEncoding | null;
|
|
22
|
+
encodingReason: EncodingReason | null;
|
|
23
|
+
};
|
|
24
|
+
export type Track = VideoTrack | AudioTrack;
|
|
25
|
+
/**
|
|
26
|
+
* Type describing possible reasons of currently selected encoding.
|
|
27
|
+
*
|
|
28
|
+
* - other - the exact reason couldn't be determined
|
|
29
|
+
* - encoding_inactive - previously selected encoding became inactive
|
|
30
|
+
* - low_bandwidth - there is no longer enough bandwidth to maintain previously selected encoding
|
|
31
|
+
*/
|
|
32
|
+
export type EncodingReason = 'other' | 'encoding_inactive' | 'low_bandwidth';
|
|
33
|
+
export type Participant<ParticipantMetadata extends GenericMetadata = GenericMetadata> = {
|
|
34
|
+
/**
|
|
35
|
+
* id used to identify a participant
|
|
36
|
+
*/
|
|
37
|
+
id: string;
|
|
38
|
+
/**
|
|
39
|
+
* whether the participant is local or remote
|
|
40
|
+
*/
|
|
41
|
+
isLocal: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* a map indexed by strings, containing participant metadata from the server
|
|
44
|
+
*/
|
|
45
|
+
metadata: ParticipantMetadata;
|
|
46
|
+
/**
|
|
47
|
+
* a list of participants's video and audio tracks
|
|
48
|
+
*/
|
|
49
|
+
tracks: Track[];
|
|
50
|
+
};
|
|
51
|
+
export type ParticipantsUpdateEvent<ParticipantMetadata extends GenericMetadata = GenericMetadata> = {
|
|
52
|
+
PeersUpdate: Participant<ParticipantMetadata>[];
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* This hook provides live updates of room participants.
|
|
56
|
+
* @returns An array of room participants.
|
|
57
|
+
*/
|
|
58
|
+
export declare function useParticipants<ParticipantMetadata extends GenericMetadata = GenericMetadata>(): {
|
|
59
|
+
participants: Participant<ParticipantMetadata>[];
|
|
60
|
+
};
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=useParticipants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useParticipants.d.ts","sourceRoot":"","sources":["../../src/hooks/useParticipants.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAiB,MAAM,UAAU,CAAC;AAIzE,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7C,KAAK,SAAS,GAAG;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IACnC,IAAI,EAAE,OAAO,CAAC;IAEd,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAE/B,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;AAC5C;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,mBAAmB,GAAG,eAAe,CAAC;AAE7E,MAAM,MAAM,WAAW,CACrB,mBAAmB,SAAS,eAAe,GAAG,eAAe,IAC3D;IACF;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,QAAQ,EAAE,mBAAmB,CAAC;IAC9B;;OAEG;IACH,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,uBAAuB,CACjC,mBAAmB,SAAS,eAAe,GAAG,eAAe,IAC3D;IACF,WAAW,EAAE,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAAC;CACjD,CAAC;AAgBF;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,mBAAmB,SAAS,eAAe,GAAG,eAAe;;EA0B9D"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import RNFishjamClientModule from '../RNFishjamClientModule';
|
|
3
|
+
import { ReceivableEvents, eventEmitter } from '../common/eventEmitter';
|
|
4
|
+
function addIsActiveToTracks(participants) {
|
|
5
|
+
return participants.map((participant) => ({
|
|
6
|
+
...participant,
|
|
7
|
+
tracks: participant.tracks.map((track) => ({
|
|
8
|
+
...track,
|
|
9
|
+
isActive: track?.metadata?.active ?? true,
|
|
10
|
+
})),
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* This hook provides live updates of room participants.
|
|
15
|
+
* @returns An array of room participants.
|
|
16
|
+
*/
|
|
17
|
+
export function useParticipants() {
|
|
18
|
+
const [participants, setParticipants] = useState([]);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
async function updateParticipants() {
|
|
21
|
+
const participants = await RNFishjamClientModule.getPeers();
|
|
22
|
+
setParticipants(addIsActiveToTracks(participants));
|
|
23
|
+
}
|
|
24
|
+
const eventListener = eventEmitter.addListener(ReceivableEvents.PeersUpdate, (event) => {
|
|
25
|
+
setParticipants(addIsActiveToTracks(event.PeersUpdate));
|
|
26
|
+
});
|
|
27
|
+
updateParticipants();
|
|
28
|
+
return () => eventListener.remove();
|
|
29
|
+
}, []);
|
|
30
|
+
return { participants };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=useParticipants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useParticipants.js","sourceRoot":"","sources":["../../src/hooks/useParticipants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAG5C,OAAO,qBAAqB,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAoExE,SAAS,mBAAmB,CAG1B,YAA6D;IAE7D,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACxC,GAAG,WAAW;QACd,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACzC,GAAG,KAAK;YACR,QAAQ,EACL,KAAsC,EAAE,QAAQ,EAAE,MAAM,IAAI,IAAI;SACpE,CAAC,CAAC;KACJ,CAAC,CAAC,CAAC;AACN,CAAC;AACD;;;GAGG;AACH,MAAM,UAAU,eAAe;IAG7B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAE9C,EAAE,CAAC,CAAC;IAEN,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,UAAU,kBAAkB;YAC/B,MAAM,YAAY,GAChB,MAAM,qBAAqB,CAAC,QAAQ,EAAuB,CAAC;YAC9D,eAAe,CAAC,mBAAmB,CAAsB,YAAY,CAAC,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,aAAa,GAAG,YAAY,CAAC,WAAW,CAE5C,gBAAgB,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YACxC,eAAe,CACb,mBAAmB,CAAsB,KAAK,CAAC,WAAW,CAAC,CAC5D,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,kBAAkB,EAAE,CAAC;QACrB,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;IACtC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1B,CAAC","sourcesContent":["import { useEffect, useState } from 'react';\n\nimport { GenericMetadata, TrackEncoding, TrackMetadata } from '../types';\nimport RNFishjamClientModule from '../RNFishjamClientModule';\nimport { ReceivableEvents, eventEmitter } from '../common/eventEmitter';\n\nexport type TrackType = 'Audio' | 'Video';\n\n/**\n * Type describing Voice Activity Detection statuses.\n *\n * speech - voice activity has been detected\n * silence - lack of voice activity has been detected\n */\nexport type VadStatus = 'silence' | 'speech';\n\ntype TrackBase = {\n id: string;\n type: TrackType;\n isActive: boolean;\n};\n\nexport type AudioTrack = TrackBase & {\n type: 'Audio';\n vadStatus: VadStatus | undefined;\n};\n\nexport type VideoTrack = TrackBase & {\n type: 'Video';\n // Encoding that is currently received. Only present for remote tracks.\n encoding: TrackEncoding | null;\n // The reason of currently selected encoding. Only present for remote tracks.\n encodingReason: EncodingReason | null;\n};\n\nexport type Track = VideoTrack | AudioTrack;\n/**\n * Type describing possible reasons of currently selected encoding.\n *\n * - other - the exact reason couldn't be determined\n * - encoding_inactive - previously selected encoding became inactive\n * - low_bandwidth - there is no longer enough bandwidth to maintain previously selected encoding\n */\nexport type EncodingReason = 'other' | 'encoding_inactive' | 'low_bandwidth';\n\nexport type Participant<\n ParticipantMetadata extends GenericMetadata = GenericMetadata,\n> = {\n /**\n * id used to identify a participant\n */\n id: string;\n /**\n * whether the participant is local or remote\n */\n isLocal: boolean;\n /**\n * a map indexed by strings, containing participant metadata from the server\n */\n metadata: ParticipantMetadata;\n /**\n * a list of participants's video and audio tracks\n */\n tracks: Track[];\n};\n\nexport type ParticipantsUpdateEvent<\n ParticipantMetadata extends GenericMetadata = GenericMetadata,\n> = {\n PeersUpdate: Participant<ParticipantMetadata>[];\n};\n\nfunction addIsActiveToTracks<\n ParticipantMetadata extends GenericMetadata = GenericMetadata,\n>(\n participants: ReadonlyArray<Participant<ParticipantMetadata>>,\n): Participant<ParticipantMetadata>[] {\n return participants.map((participant) => ({\n ...participant,\n tracks: participant.tracks.map((track) => ({\n ...track,\n isActive:\n (track as { metadata?: TrackMetadata })?.metadata?.active ?? true,\n })),\n }));\n}\n/**\n * This hook provides live updates of room participants.\n * @returns An array of room participants.\n */\nexport function useParticipants<\n ParticipantMetadata extends GenericMetadata = GenericMetadata,\n>() {\n const [participants, setParticipants] = useState<\n Participant<ParticipantMetadata>[]\n >([]);\n\n useEffect(() => {\n async function updateParticipants() {\n const participants =\n await RNFishjamClientModule.getPeers<ParticipantMetadata>();\n setParticipants(addIsActiveToTracks<ParticipantMetadata>(participants));\n }\n\n const eventListener = eventEmitter.addListener<\n ParticipantsUpdateEvent<ParticipantMetadata>\n >(ReceivableEvents.PeersUpdate, (event) => {\n setParticipants(\n addIsActiveToTracks<ParticipantMetadata>(event.PeersUpdate),\n );\n });\n\n updateParticipants();\n return () => eventListener.remove();\n }, []);\n\n return { participants };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useReconnection.d.ts","sourceRoot":"","sources":["../../src/hooks/useReconnection.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,cAAc,GAAG,OAAO,CAAC;AAEnE,wBAAgB,eAAe;;EAmC9B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { ReceivableEvents, eventEmitter } from '../common/eventEmitter';
|
|
3
|
+
export function useReconnection() {
|
|
4
|
+
const [reconnectionStatus, setReconnectionStatus] = useState('idle');
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const reconnectedEventListener = eventEmitter.addListener(ReceivableEvents.Reconnected, () => {
|
|
7
|
+
setReconnectionStatus('idle');
|
|
8
|
+
});
|
|
9
|
+
const reconnectionStartedEventListener = eventEmitter.addListener(ReceivableEvents.ReconnectionStarted, () => {
|
|
10
|
+
setReconnectionStatus('reconnecting');
|
|
11
|
+
});
|
|
12
|
+
const reconnectionRetriesLimitReachedEventListener = eventEmitter.addListener(ReceivableEvents.ReconnectionRetriesLimitReached, () => {
|
|
13
|
+
setReconnectionStatus('error');
|
|
14
|
+
});
|
|
15
|
+
return () => {
|
|
16
|
+
reconnectedEventListener.remove();
|
|
17
|
+
reconnectionStartedEventListener.remove();
|
|
18
|
+
reconnectionRetriesLimitReachedEventListener.remove();
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
return { reconnectionStatus };
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=useReconnection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useReconnection.js","sourceRoot":"","sources":["../../src/hooks/useReconnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAIxE,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAC/C,QAAQ,CAAqB,MAAM,CAAC,CAAC;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,wBAAwB,GAAG,YAAY,CAAC,WAAW,CACvD,gBAAgB,CAAC,WAAW,EAC5B,GAAG,EAAE;YACH,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC,CACF,CAAC;QAEF,MAAM,gCAAgC,GAAG,YAAY,CAAC,WAAW,CAC/D,gBAAgB,CAAC,mBAAmB,EACpC,GAAG,EAAE;YACH,qBAAqB,CAAC,cAAc,CAAC,CAAC;QACxC,CAAC,CACF,CAAC;QAEF,MAAM,4CAA4C,GAChD,YAAY,CAAC,WAAW,CACtB,gBAAgB,CAAC,+BAA+B,EAChD,GAAG,EAAE;YACH,qBAAqB,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC,CACF,CAAC;QAEJ,OAAO,GAAG,EAAE;YACV,wBAAwB,CAAC,MAAM,EAAE,CAAC;YAClC,gCAAgC,CAAC,MAAM,EAAE,CAAC;YAC1C,4CAA4C,CAAC,MAAM,EAAE,CAAC;QACxD,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAChC,CAAC","sourcesContent":["import { useEffect, useState } from 'react';\nimport { ReceivableEvents, eventEmitter } from '../common/eventEmitter';\n\nexport type ReconnectionStatus = 'idle' | 'reconnecting' | 'error';\n\nexport function useReconnection() {\n const [reconnectionStatus, setReconnectionStatus] =\n useState<ReconnectionStatus>('idle');\n\n useEffect(() => {\n const reconnectedEventListener = eventEmitter.addListener(\n ReceivableEvents.Reconnected,\n () => {\n setReconnectionStatus('idle');\n },\n );\n\n const reconnectionStartedEventListener = eventEmitter.addListener(\n ReceivableEvents.ReconnectionStarted,\n () => {\n setReconnectionStatus('reconnecting');\n },\n );\n\n const reconnectionRetriesLimitReachedEventListener =\n eventEmitter.addListener(\n ReceivableEvents.ReconnectionRetriesLimitReached,\n () => {\n setReconnectionStatus('error');\n },\n );\n\n return () => {\n reconnectedEventListener.remove();\n reconnectionStartedEventListener.remove();\n reconnectionRetriesLimitReachedEventListener.remove();\n };\n });\n\n return { reconnectionStatus };\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BandwidthLimit, SimulcastConfig, TrackBandwidthLimit, TrackEncoding, TrackMetadata } from '../types';
|
|
2
|
+
export type ScreencastQuality = 'VGA' | 'HD5' | 'HD15' | 'FHD15' | 'FHD30';
|
|
3
|
+
export type ScreencastOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* Resolution + fps of screencast track, one of: `VGA`, `HD5`, `HD15`, `FHD15`, `FHD30`.
|
|
6
|
+
* Note that quality might be worse than specified due to device capabilities, internet
|
|
7
|
+
* connection etc.
|
|
8
|
+
* @default `HD15``
|
|
9
|
+
*/
|
|
10
|
+
quality: ScreencastQuality;
|
|
11
|
+
/**
|
|
12
|
+
* bandwidth limit of a screencast track. By default there is no bandwidth limit.
|
|
13
|
+
*/
|
|
14
|
+
maxBandwidth: TrackBandwidthLimit;
|
|
15
|
+
};
|
|
16
|
+
export type ScreencastOptionsInternal = {
|
|
17
|
+
screencastMetadata: TrackMetadata & {
|
|
18
|
+
displayName?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* SimulcastConfig of a screencast track. By default simulcast is disabled.
|
|
22
|
+
*/
|
|
23
|
+
simulcastConfig: SimulcastConfig;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* This hook can toggle screen sharing on/off and provides current screencast state.
|
|
27
|
+
* @returns An object with functions to manage screencast.
|
|
28
|
+
*/
|
|
29
|
+
export declare function useScreencast(): {
|
|
30
|
+
isScreencastOn: boolean;
|
|
31
|
+
toggleScreencast: (screencastOptions?: Partial<ScreencastOptions>) => Promise<void>;
|
|
32
|
+
toggleScreencastTrackEncoding: (encoding: TrackEncoding) => Promise<void>;
|
|
33
|
+
simulcastConfig: SimulcastConfig;
|
|
34
|
+
setScreencastTrackEncodingBandwidth: (encoding: TrackEncoding, bandwidth: BandwidthLimit) => Promise<void>;
|
|
35
|
+
setScreencastTrackBandwidth: (bandwidth: BandwidthLimit) => Promise<void>;
|
|
36
|
+
handleScreencastPermission: () => Promise<"granted" | "denied">;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=useScreencast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScreencast.d.ts","sourceRoot":"","sources":["../../src/hooks/useScreencast.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,aAAa,EACd,MAAM,UAAU,CAAC;AAOlB,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAE3E,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;OAKG;IACH,OAAO,EAAE,iBAAiB,CAAC;IAC3B;;OAEG;IACH,YAAY,EAAE,mBAAmB,CAAC;CACnC,CAAC;AACF,MAAM,MAAM,yBAAyB,GAAG;IACtC,kBAAkB,EAAE,aAAa,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D;;OAEG;IACH,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AASF;;;GAGG;AACH,wBAAgB,aAAa;;2CAsBC,OAAO,CAAC,iBAAiB,CAAC;8CAqBnC,aAAa;;oDAcb,aAAa,aAAa,cAAc;6CAiBvC,cAAc;;EAsBnC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import RNFishjamClientModule from '../RNFishjamClientModule';
|
|
3
|
+
import { ReceivableEvents, eventEmitter } from '../common/eventEmitter';
|
|
4
|
+
import { Platform } from 'react-native';
|
|
5
|
+
const defaultSimulcastConfig = () => ({
|
|
6
|
+
enabled: false,
|
|
7
|
+
activeEncodings: [],
|
|
8
|
+
});
|
|
9
|
+
let screencastSimulcastConfig = defaultSimulcastConfig();
|
|
10
|
+
/**
|
|
11
|
+
* This hook can toggle screen sharing on/off and provides current screencast state.
|
|
12
|
+
* @returns An object with functions to manage screencast.
|
|
13
|
+
*/
|
|
14
|
+
export function useScreencast() {
|
|
15
|
+
const [isScreencastOn, setIsScreencastOn] = useState(RNFishjamClientModule.isScreencastOn);
|
|
16
|
+
const [simulcastConfig, setSimulcastConfig] = useState(screencastSimulcastConfig);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const eventListener = eventEmitter.addListener(ReceivableEvents.IsScreencastOn, (event) => setIsScreencastOn(event.IsScreencastOn));
|
|
19
|
+
setIsScreencastOn(RNFishjamClientModule.isScreencastOn);
|
|
20
|
+
return () => eventListener.remove();
|
|
21
|
+
}, []);
|
|
22
|
+
/**
|
|
23
|
+
* Toggles the screencast on/off
|
|
24
|
+
*/
|
|
25
|
+
const toggleScreencast = useCallback(async (screencastOptions = {}) => {
|
|
26
|
+
const options = {
|
|
27
|
+
...screencastOptions,
|
|
28
|
+
screencastMetadata: {
|
|
29
|
+
displayName: 'presenting',
|
|
30
|
+
type: 'screensharing',
|
|
31
|
+
active: !isScreencastOn,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
await RNFishjamClientModule.toggleScreencast(options);
|
|
35
|
+
screencastSimulcastConfig = defaultSimulcastConfig(); //to do: sync with camera settings
|
|
36
|
+
setSimulcastConfig(screencastSimulcastConfig);
|
|
37
|
+
}, [isScreencastOn]);
|
|
38
|
+
/**
|
|
39
|
+
* Toggles simulcast encoding of a screencast track on/off
|
|
40
|
+
* @param encoding encoding to toggle
|
|
41
|
+
*/
|
|
42
|
+
const toggleScreencastTrackEncoding = useCallback(async (encoding) => {
|
|
43
|
+
screencastSimulcastConfig =
|
|
44
|
+
await RNFishjamClientModule.toggleScreencastTrackEncoding(encoding);
|
|
45
|
+
setSimulcastConfig(screencastSimulcastConfig);
|
|
46
|
+
}, []);
|
|
47
|
+
/**
|
|
48
|
+
* updates maximum bandwidth for the given simulcast encoding of the screencast track
|
|
49
|
+
* @param encoding encoding to update
|
|
50
|
+
* @param bandwidth BandwidthLimit to set
|
|
51
|
+
*/
|
|
52
|
+
const setScreencastTrackEncodingBandwidth = useCallback(async (encoding, bandwidth) => {
|
|
53
|
+
await RNFishjamClientModule.setScreencastTrackEncodingBandwidth(encoding, bandwidth);
|
|
54
|
+
}, []);
|
|
55
|
+
/**
|
|
56
|
+
* updates maximum bandwidth for the screencast track. This value directly translates
|
|
57
|
+
* to quality of the stream and the amount of RTP packets being sent. In case simulcast
|
|
58
|
+
* is enabled bandwidth is split between all of the variant streams proportionally to
|
|
59
|
+
* their resolution
|
|
60
|
+
* @param bandwidth BandwidthLimit to set
|
|
61
|
+
*/
|
|
62
|
+
const setScreencastTrackBandwidth = useCallback(async (bandwidth) => {
|
|
63
|
+
await RNFishjamClientModule.setScreencastTrackBandwidth(bandwidth);
|
|
64
|
+
}, []);
|
|
65
|
+
const handleScreencastPermission = useCallback(async () => {
|
|
66
|
+
if (Platform.OS == 'android') {
|
|
67
|
+
return await RNFishjamClientModule.handleScreencastPermission();
|
|
68
|
+
}
|
|
69
|
+
return 'denied';
|
|
70
|
+
}, []);
|
|
71
|
+
return {
|
|
72
|
+
isScreencastOn,
|
|
73
|
+
toggleScreencast,
|
|
74
|
+
toggleScreencastTrackEncoding,
|
|
75
|
+
simulcastConfig,
|
|
76
|
+
setScreencastTrackEncodingBandwidth,
|
|
77
|
+
setScreencastTrackBandwidth,
|
|
78
|
+
handleScreencastPermission,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=useScreencast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScreencast.js","sourceRoot":"","sources":["../../src/hooks/useScreencast.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useState } from 'react';\n\nimport {\n BandwidthLimit,\n SimulcastConfig,\n TrackBandwidthLimit,\n TrackEncoding,\n TrackMetadata,\n} from '../types';\nimport RNFishjamClientModule from '../RNFishjamClientModule';\nimport { ReceivableEvents, eventEmitter } from '../common/eventEmitter';\nimport { Platform } from 'react-native';\n\ntype IsScreencastOnEvent = { IsScreencastOn: boolean };\n\nexport type ScreencastQuality = 'VGA' | 'HD5' | 'HD15' | 'FHD15' | 'FHD30';\n\nexport type ScreencastOptions = {\n /**\n * Resolution + fps of screencast track, one of: `VGA`, `HD5`, `HD15`, `FHD15`, `FHD30`.\n * Note that quality might be worse than specified due to device capabilities, internet\n * connection etc.\n * @default `HD15``\n */\n quality: ScreencastQuality;\n /**\n * bandwidth limit of a screencast track. By default there is no bandwidth limit.\n */\n maxBandwidth: TrackBandwidthLimit;\n};\nexport type ScreencastOptionsInternal = {\n screencastMetadata: TrackMetadata & { displayName?: string };\n /**\n * SimulcastConfig of a screencast track. By default simulcast is disabled.\n */\n simulcastConfig: SimulcastConfig;\n};\n\nconst defaultSimulcastConfig = () => ({\n enabled: false,\n activeEncodings: [],\n});\n\nlet screencastSimulcastConfig: SimulcastConfig = defaultSimulcastConfig();\n\n/**\n * This hook can toggle screen sharing on/off and provides current screencast state.\n * @returns An object with functions to manage screencast.\n */\nexport function useScreencast() {\n const [isScreencastOn, setIsScreencastOn] = useState<boolean>(\n RNFishjamClientModule.isScreencastOn,\n );\n\n const [simulcastConfig, setSimulcastConfig] = useState<SimulcastConfig>(\n screencastSimulcastConfig,\n );\n\n useEffect(() => {\n const eventListener = eventEmitter.addListener<IsScreencastOnEvent>(\n ReceivableEvents.IsScreencastOn,\n (event) => setIsScreencastOn(event.IsScreencastOn),\n );\n setIsScreencastOn(RNFishjamClientModule.isScreencastOn);\n return () => eventListener.remove();\n }, []);\n\n /**\n * Toggles the screencast on/off\n */\n const toggleScreencast = useCallback(\n async (screencastOptions: Partial<ScreencastOptions> = {}) => {\n const options = {\n ...screencastOptions,\n screencastMetadata: {\n displayName: 'presenting',\n type: 'screensharing' as const,\n active: !isScreencastOn,\n },\n };\n await RNFishjamClientModule.toggleScreencast(options);\n screencastSimulcastConfig = defaultSimulcastConfig(); //to do: sync with camera settings\n setSimulcastConfig(screencastSimulcastConfig);\n },\n [isScreencastOn],\n );\n\n /**\n * Toggles simulcast encoding of a screencast track on/off\n * @param encoding encoding to toggle\n */\n const toggleScreencastTrackEncoding = useCallback(\n async (encoding: TrackEncoding) => {\n screencastSimulcastConfig =\n await RNFishjamClientModule.toggleScreencastTrackEncoding(encoding);\n setSimulcastConfig(screencastSimulcastConfig);\n },\n [],\n );\n\n /**\n * updates maximum bandwidth for the given simulcast encoding of the screencast track\n * @param encoding encoding to update\n * @param bandwidth BandwidthLimit to set\n */\n const setScreencastTrackEncodingBandwidth = useCallback(\n async (encoding: TrackEncoding, bandwidth: BandwidthLimit) => {\n await RNFishjamClientModule.setScreencastTrackEncodingBandwidth(\n encoding,\n bandwidth,\n );\n },\n [],\n );\n\n /**\n * updates maximum bandwidth for the screencast track. This value directly translates\n * to quality of the stream and the amount of RTP packets being sent. In case simulcast\n * is enabled bandwidth is split between all of the variant streams proportionally to\n * their resolution\n * @param bandwidth BandwidthLimit to set\n */\n const setScreencastTrackBandwidth = useCallback(\n async (bandwidth: BandwidthLimit) => {\n await RNFishjamClientModule.setScreencastTrackBandwidth(bandwidth);\n },\n [],\n );\n\n const handleScreencastPermission = useCallback(async () => {\n if (Platform.OS == 'android') {\n return await RNFishjamClientModule.handleScreencastPermission();\n }\n return 'denied';\n }, []);\n\n return {\n isScreencastOn,\n toggleScreencast,\n toggleScreencastTrackEncoding,\n simulcastConfig,\n setScreencastTrackEncodingBandwidth,\n setScreencastTrackBandwidth,\n handleScreencastPermission,\n };\n}\n"]}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type { Participant, Track, TrackType, VadStatus, EncodingReason, } from './hooks/useParticipants';
|
|
2
|
+
export { useParticipants } from './hooks/useParticipants';
|
|
3
|
+
export type { AudioOutputDevice, AudioOutputDeviceType, AudioSessionMode, } from './hooks/useAudioSettings';
|
|
4
|
+
export { useAudioSettings } from './hooks/useAudioSettings';
|
|
5
|
+
export type { BandwidthEstimationEvent } from './hooks/useBandwidthEstimation';
|
|
6
|
+
export { useBandwidthEstimation } from './hooks/useBandwidthEstimation';
|
|
7
|
+
export type { CaptureDevice, CameraConfig, VideoQuality, } from './hooks/useCamera';
|
|
8
|
+
export { useCamera } from './hooks/useCamera';
|
|
9
|
+
export { useMicrophone } from './hooks/useMicrophone';
|
|
10
|
+
export { useRTCStatistics } from './stats/useRTCStatistics';
|
|
11
|
+
export type { ScreencastOptions, ScreencastQuality, } from './hooks/useScreencast';
|
|
12
|
+
export { useScreencast } from './hooks/useScreencast';
|
|
13
|
+
export type { ReconnectionStatus } from './hooks/useReconnection';
|
|
14
|
+
export { useReconnection } from './hooks/useReconnection';
|
|
15
|
+
export { updatePeerMetadata } from './common/metadata';
|
|
16
|
+
export type { LoggingSeverity } from './common/webRTC';
|
|
17
|
+
export { changeWebRTCLoggingSeverity, setTargetTrackEncoding, } from './common/webRTC';
|
|
18
|
+
export { connect, leaveRoom } from './common/client';
|
|
19
|
+
export type { VideoPreviewViewProps } from './components/VideoPreviewView';
|
|
20
|
+
export { VideoPreviewView } from './components/VideoPreviewView';
|
|
21
|
+
export type { VideoRendererProps } from './components/VideoRendererView';
|
|
22
|
+
export { VideoRendererView } from './components/VideoRendererView';
|
|
23
|
+
export type { TrackBandwidthLimit, TrackEncoding, SimulcastBandwidthLimit, BandwidthLimit, SimulcastConfig, VideoLayout, } from './types';
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,KAAK,EACL,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,YAAY,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAExE,YAAY,EACV,aAAa,EACb,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,YAAY,EACV,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAErD,YAAY,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,eAAe,EACf,WAAW,GACZ,MAAM,SAAS,CAAC"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { useParticipants } from './hooks/useParticipants';
|
|
2
|
+
export { useAudioSettings } from './hooks/useAudioSettings';
|
|
3
|
+
export { useBandwidthEstimation } from './hooks/useBandwidthEstimation';
|
|
4
|
+
export { useCamera } from './hooks/useCamera';
|
|
5
|
+
export { useMicrophone } from './hooks/useMicrophone';
|
|
6
|
+
export { useRTCStatistics } from './stats/useRTCStatistics';
|
|
7
|
+
export { useScreencast } from './hooks/useScreencast';
|
|
8
|
+
export { useReconnection } from './hooks/useReconnection';
|
|
9
|
+
export { updatePeerMetadata } from './common/metadata';
|
|
10
|
+
export { changeWebRTCLoggingSeverity, setTargetTrackEncoding, } from './common/webRTC';
|
|
11
|
+
export { connect, leaveRoom } from './common/client';
|
|
12
|
+
export { VideoPreviewView } from './components/VideoPreviewView';
|
|
13
|
+
export { VideoRendererView } from './components/VideoRendererView';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAO1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAOxE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAM5D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC","sourcesContent":["export type {\n Participant,\n Track,\n TrackType,\n VadStatus,\n EncodingReason,\n} from './hooks/useParticipants';\nexport { useParticipants } from './hooks/useParticipants';\n\nexport type {\n AudioOutputDevice,\n AudioOutputDeviceType,\n AudioSessionMode,\n} from './hooks/useAudioSettings';\nexport { useAudioSettings } from './hooks/useAudioSettings';\n\nexport type { BandwidthEstimationEvent } from './hooks/useBandwidthEstimation';\nexport { useBandwidthEstimation } from './hooks/useBandwidthEstimation';\n\nexport type {\n CaptureDevice,\n CameraConfig,\n VideoQuality,\n} from './hooks/useCamera';\nexport { useCamera } from './hooks/useCamera';\n\nexport { useMicrophone } from './hooks/useMicrophone';\n\nexport { useRTCStatistics } from './stats/useRTCStatistics';\n\nexport type {\n ScreencastOptions,\n ScreencastQuality,\n} from './hooks/useScreencast';\nexport { useScreencast } from './hooks/useScreencast';\n\nexport type { ReconnectionStatus } from './hooks/useReconnection';\nexport { useReconnection } from './hooks/useReconnection';\n\nexport { updatePeerMetadata } from './common/metadata';\n\nexport type { LoggingSeverity } from './common/webRTC';\nexport {\n changeWebRTCLoggingSeverity,\n setTargetTrackEncoding,\n} from './common/webRTC';\n\nexport { connect, leaveRoom } from './common/client';\n\nexport type { VideoPreviewViewProps } from './components/VideoPreviewView';\nexport { VideoPreviewView } from './components/VideoPreviewView';\n\nexport type { VideoRendererProps } from './components/VideoRendererView';\nexport { VideoRendererView } from './components/VideoRendererView';\n\nexport type {\n TrackBandwidthLimit,\n TrackEncoding,\n SimulcastBandwidthLimit,\n BandwidthLimit,\n SimulcastConfig,\n VideoLayout,\n} from './types';\n"]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as _m0 from "protobufjs/minimal";
|
|
2
|
+
export declare const protobufPackage = "fishjam";
|
|
3
|
+
/** Defines any type of message sent between FJ and a peer */
|
|
4
|
+
export interface PeerMessage {
|
|
5
|
+
authenticated?: PeerMessage_Authenticated | undefined;
|
|
6
|
+
authRequest?: PeerMessage_AuthRequest | undefined;
|
|
7
|
+
mediaEvent?: PeerMessage_MediaEvent | undefined;
|
|
8
|
+
}
|
|
9
|
+
/** Response sent by FJ, confirming successfull authentication */
|
|
10
|
+
export interface PeerMessage_Authenticated {
|
|
11
|
+
}
|
|
12
|
+
/** Request sent by peer, to authenticate to FJ server */
|
|
13
|
+
export interface PeerMessage_AuthRequest {
|
|
14
|
+
token: string;
|
|
15
|
+
}
|
|
16
|
+
/** Any type of WebRTC messages passed betweend FJ and peer */
|
|
17
|
+
export interface PeerMessage_MediaEvent {
|
|
18
|
+
data: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const PeerMessage: {
|
|
21
|
+
encode(message: PeerMessage, writer?: _m0.Writer): _m0.Writer;
|
|
22
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage;
|
|
23
|
+
fromJSON(object: any): PeerMessage;
|
|
24
|
+
toJSON(message: PeerMessage): unknown;
|
|
25
|
+
create<I extends Exact<DeepPartial<PeerMessage>, I>>(base?: I): PeerMessage;
|
|
26
|
+
fromPartial<I extends Exact<DeepPartial<PeerMessage>, I>>(object: I): PeerMessage;
|
|
27
|
+
};
|
|
28
|
+
export declare const PeerMessage_Authenticated: {
|
|
29
|
+
encode(_: PeerMessage_Authenticated, writer?: _m0.Writer): _m0.Writer;
|
|
30
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage_Authenticated;
|
|
31
|
+
fromJSON(_: any): PeerMessage_Authenticated;
|
|
32
|
+
toJSON(_: PeerMessage_Authenticated): unknown;
|
|
33
|
+
create<I extends Exact<DeepPartial<PeerMessage_Authenticated>, I>>(base?: I): PeerMessage_Authenticated;
|
|
34
|
+
fromPartial<I extends Exact<DeepPartial<PeerMessage_Authenticated>, I>>(_: I): PeerMessage_Authenticated;
|
|
35
|
+
};
|
|
36
|
+
export declare const PeerMessage_AuthRequest: {
|
|
37
|
+
encode(message: PeerMessage_AuthRequest, writer?: _m0.Writer): _m0.Writer;
|
|
38
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage_AuthRequest;
|
|
39
|
+
fromJSON(object: any): PeerMessage_AuthRequest;
|
|
40
|
+
toJSON(message: PeerMessage_AuthRequest): unknown;
|
|
41
|
+
create<I extends Exact<DeepPartial<PeerMessage_AuthRequest>, I>>(base?: I): PeerMessage_AuthRequest;
|
|
42
|
+
fromPartial<I extends Exact<DeepPartial<PeerMessage_AuthRequest>, I>>(object: I): PeerMessage_AuthRequest;
|
|
43
|
+
};
|
|
44
|
+
export declare const PeerMessage_MediaEvent: {
|
|
45
|
+
encode(message: PeerMessage_MediaEvent, writer?: _m0.Writer): _m0.Writer;
|
|
46
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): PeerMessage_MediaEvent;
|
|
47
|
+
fromJSON(object: any): PeerMessage_MediaEvent;
|
|
48
|
+
toJSON(message: PeerMessage_MediaEvent): unknown;
|
|
49
|
+
create<I extends Exact<DeepPartial<PeerMessage_MediaEvent>, I>>(base?: I): PeerMessage_MediaEvent;
|
|
50
|
+
fromPartial<I extends Exact<DeepPartial<PeerMessage_MediaEvent>, I>>(object: I): PeerMessage_MediaEvent;
|
|
51
|
+
};
|
|
52
|
+
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
53
|
+
export type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
|
|
54
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
55
|
+
} : Partial<T>;
|
|
56
|
+
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
|
57
|
+
export type Exact<P, I extends P> = P extends Builtin ? P : P & {
|
|
58
|
+
[K in keyof P]: Exact<P[K], I[K]>;
|
|
59
|
+
} & {
|
|
60
|
+
[K in Exclude<keyof I, KeysOfUnion<P>>]: never;
|
|
61
|
+
};
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=peer_notifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer_notifications.d.ts","sourceRoot":"","sources":["../../../src/protos/fishjam/peer_notifications.ts"],"names":[],"mappings":"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"}
|