@fishjam-cloud/react-native-client 0.7.0 → 0.8.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.
@@ -4,7 +4,7 @@ apply plugin: 'com.android.library'
4
4
  apply plugin: 'kotlin-android'
5
5
  apply plugin: 'maven-publish'
6
6
 
7
- def inputFile = new File("$projectDir/../../../package.json")
7
+ def inputFile = new File("$projectDir/../package.json")
8
8
  def packageJson = new JsonSlurper().parseText(inputFile.text)
9
9
  def packageVersion = packageJson["version"]
10
10
 
@@ -41,6 +41,7 @@ import io.fishjam.reactnative.utils.PermissionUtils
41
41
  import kotlinx.coroutines.CoroutineScope
42
42
  import kotlinx.coroutines.Dispatchers
43
43
  import kotlinx.coroutines.SupervisorJob
44
+ import kotlinx.coroutines.delay
44
45
  import kotlinx.coroutines.launch
45
46
  import org.webrtc.Logging
46
47
 
@@ -68,6 +69,24 @@ class RNFishjamClient(
68
69
  }
69
70
 
70
71
  private var connectPromise: Promise? = null
72
+ private set(value) {
73
+ field = value
74
+ if (value == null) {
75
+ return
76
+ }
77
+ coroutineScope.launch {
78
+ delay(15000)
79
+ // If promise is still assigned it means it was not resolved in that time,
80
+ // so close the client and reject it with timeout error
81
+ connectPromise?.let { promise ->
82
+ fishjamClient.leave {
83
+ promise.reject(SocketError("Failed to connect: Fishjam server is not responding"))
84
+ connectPromise = null
85
+ peerStatus = PeerStatus.Error
86
+ }
87
+ }
88
+ }
89
+ }
71
90
  private var screenSharePermissionPromise: Promise? = null
72
91
 
73
92
  var videoSimulcastConfig: SimulcastConfig = SimulcastConfig()
@@ -166,8 +166,10 @@ class RNFishjamClientModule : Module() {
166
166
  }
167
167
 
168
168
  AsyncFunction("startCamera") Coroutine { config: CameraConfig ->
169
- return@Coroutine withContext(Dispatchers.Main) {
170
- return@withContext rnFishjamClient.startCamera(config)
169
+ mutex.withLock {
170
+ return@Coroutine withContext(Dispatchers.Main) {
171
+ return@withContext rnFishjamClient.startCamera(config)
172
+ }
171
173
  }
172
174
  }
173
175
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FishjamRoom/index.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,8BAA+B,gBAAgB,gCA0BtE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FishjamRoom/index.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,8BAA+B,gBAAgB,gCA8BtE,CAAC"}
@@ -22,15 +22,20 @@ export const FishjamRoom = ({ fishjamUrl, peerToken }) => {
22
22
  const { prepareCamera } = useCamera();
23
23
  useEffect(() => {
24
24
  const join = async () => {
25
- await prepareCamera({
26
- simulcastEnabled: true,
27
- quality: 'HD169',
28
- cameraEnabled: true,
29
- });
30
- await joinRoom(fishjamUrl, peerToken, {
31
- peer: {},
32
- server: {},
33
- });
25
+ try {
26
+ await prepareCamera({
27
+ simulcastEnabled: true,
28
+ quality: 'HD169',
29
+ cameraEnabled: true,
30
+ });
31
+ await joinRoom(fishjamUrl, peerToken, {
32
+ peer: {},
33
+ server: {},
34
+ });
35
+ }
36
+ catch (e) {
37
+ console.warn(e);
38
+ }
34
39
  };
35
40
  join();
36
41
  return () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/FishjamRoom/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAa5C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,EAAoB,EAAE,EAAE;IACzE,MAAM,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,CAAC;IAEtC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;YACtB,MAAM,aAAa,CAAC;gBAClB,gBAAgB,EAAE,IAAI;gBACtB,OAAO,EAAE,OAAO;gBAChB,aAAa,EAAE,IAAI;aACpB,CAAC,CAAC;YACH,MAAM,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE;gBACpC,IAAI,EAAE,EAAE;gBACR,MAAM,EAAE,EAAE;aACX,CAAC,CAAC;QACL,CAAC,CAAC;QACF,IAAI,EAAE,CAAC;QACP,OAAO,GAAG,EAAE;YACV,SAAS,EAAE,CAAC;QACd,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;IAE3C,OAAO,CACL,CAAC,YAAY,CACX;MAAA,CAAC,UAAU,CAAC,AAAD,EACb;IAAA,EAAE,YAAY,CAAC,CAChB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { useEffect } from 'react';\nimport { joinRoom, leaveRoom } from '../../common/client';\nimport { useCamera } from '../../hooks/useCamera';\nimport { VideosGrid } from './VideosGrid';\nimport { SafeAreaView } from 'react-native';\n\nexport type FishjamRoomProps = {\n /**\n * URL to your fishjam instance\n */\n fishjamUrl: string;\n /**\n * Peer Token\n */\n peerToken: string;\n};\n\n/**\n * Simple component that enables your camera and show all tracks\n *\n * Example usage:\n * ```tsx\n * <FishjamRoom\n * fishjamUrl={FISHJAM_URL}\n * peerToken={PEER_TOKEN}\n * />\n * ```\n * @category Components\n * @param {object} props\n * @param {string} props.fishjamUrl\n * @param {string} props.peerToken\n */\nexport const FishjamRoom = ({ fishjamUrl, peerToken }: FishjamRoomProps) => {\n const { prepareCamera } = useCamera();\n\n useEffect(() => {\n const join = async () => {\n await prepareCamera({\n simulcastEnabled: true,\n quality: 'HD169',\n cameraEnabled: true,\n });\n await joinRoom(fishjamUrl, peerToken, {\n peer: {},\n server: {},\n });\n };\n join();\n return () => {\n leaveRoom();\n };\n }, [fishjamUrl, peerToken, prepareCamera]);\n\n return (\n <SafeAreaView>\n <VideosGrid />\n </SafeAreaView>\n );\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/FishjamRoom/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAa5C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,EAAoB,EAAE,EAAE;IACzE,MAAM,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,CAAC;IAEtC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;YACtB,IAAI,CAAC;gBACH,MAAM,aAAa,CAAC;oBAClB,gBAAgB,EAAE,IAAI;oBACtB,OAAO,EAAE,OAAO;oBAChB,aAAa,EAAE,IAAI;iBACpB,CAAC,CAAC;gBACH,MAAM,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE;oBACpC,IAAI,EAAE,EAAE;oBACR,MAAM,EAAE,EAAE;iBACX,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC;QACF,IAAI,EAAE,CAAC;QACP,OAAO,GAAG,EAAE;YACV,SAAS,EAAE,CAAC;QACd,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;IAE3C,OAAO,CACL,CAAC,YAAY,CACX;MAAA,CAAC,UAAU,CAAC,AAAD,EACb;IAAA,EAAE,YAAY,CAAC,CAChB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { useEffect } from 'react';\nimport { joinRoom, leaveRoom } from '../../common/client';\nimport { useCamera } from '../../hooks/useCamera';\nimport { VideosGrid } from './VideosGrid';\nimport { SafeAreaView } from 'react-native';\n\nexport type FishjamRoomProps = {\n /**\n * URL to your fishjam instance\n */\n fishjamUrl: string;\n /**\n * Peer Token\n */\n peerToken: string;\n};\n\n/**\n * Simple component that enables your camera and show all tracks\n *\n * Example usage:\n * ```tsx\n * <FishjamRoom\n * fishjamUrl={FISHJAM_URL}\n * peerToken={PEER_TOKEN}\n * />\n * ```\n * @category Components\n * @param {object} props\n * @param {string} props.fishjamUrl\n * @param {string} props.peerToken\n */\nexport const FishjamRoom = ({ fishjamUrl, peerToken }: FishjamRoomProps) => {\n const { prepareCamera } = useCamera();\n\n useEffect(() => {\n const join = async () => {\n try {\n await prepareCamera({\n simulcastEnabled: true,\n quality: 'HD169',\n cameraEnabled: true,\n });\n await joinRoom(fishjamUrl, peerToken, {\n peer: {},\n server: {},\n });\n } catch (e) {\n console.warn(e);\n }\n };\n join();\n return () => {\n leaveRoom();\n };\n }, [fishjamUrl, peerToken, prepareCamera]);\n\n return (\n <SafeAreaView>\n <VideosGrid />\n </SafeAreaView>\n );\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  import { SimulcastConfig } from '../types';
2
2
  import { ScreenShareOptions } from './useScreenShare';
3
- type AppScreenShareData = {
3
+ export type AppScreenShareData = {
4
4
  isAppScreenShareOn: boolean;
5
5
  simulcastConfig: SimulcastConfig;
6
6
  toggleAppScreenShare: (screenShareOptions?: Partial<ScreenShareOptions>) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"useAppScreenShare.d.ts","sourceRoot":"","sources":["../../src/hooks/useAppScreenShare.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAWtD,KAAK,kBAAkB,GAAG;IACxB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,eAAe,CAAC;IACjC,oBAAoB,EAAE,CACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,KAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAwCF,iBAAS,+BAA+B,IAAI,kBAAkB,CAM7D;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,wCAG5B,CAAC"}
1
+ {"version":3,"file":"useAppScreenShare.d.ts","sourceRoot":"","sources":["../../src/hooks/useAppScreenShare.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAWtD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,eAAe,CAAC;IACjC,oBAAoB,EAAE,CACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,KAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAwCF,iBAAS,+BAA+B,IAAI,kBAAkB,CAM7D;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,wCAG5B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAppScreenShare.js","sourceRoot":"","sources":["../../src/hooks/useAppScreenShare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,qBAAqB,EAAE,EAC5B,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,MAAM,sBAAsB,GAAG,GAAG,EAAE,CAClC,CAAC;IACC,OAAO,EAAE,KAAK;CACf,CAA2B,CAAC;AAE/B,IAAI,0BAA0B,GAAoB,sBAAsB,EAAE,CAAC;AAU3E,SAAS,oBAAoB;IAC3B,MAAM,kBAAkB,GAAG,oBAAoB,CAC7C,gBAAgB,CAAC,kBAAkB,EACnC,qBAAqB,CAAC,kBAAkB,CACzC,CAAC;IAEF,MAAM,eAAe,GAAG,oBAAoB,CAC1C,gBAAgB,CAAC,qBAAqB,EACtC,0BAA0B,CAC3B,CAAC;IAEF,MAAM,oBAAoB,GAAG,WAAW,CACtC,KAAK,EAAE,qBAAkD,EAAE,EAAE,EAAE;QAC7D,MAAM,OAAO,GAAG;YACd,GAAG,kBAAkB;YACrB,mBAAmB,EAAE;gBACnB,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,kBAA2B;gBACjC,MAAM,EAAE,CAAC,kBAAkB;aAC5B;SACF,CAAC;QACF,MAAM,qBAAqB,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1D,0BAA0B,GAAG,sBAAsB,EAAE,CAAC,CAAC,kCAAkC;IAC3F,CAAC,EACD,CAAC,kBAAkB,CAAC,CACrB,CAAC;IAEF,OAAO;QACL,kBAAkB;QAClB,eAAe;QACf;;;WAGG;QACH,oBAAoB;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B;IACtC,OAAO;QACL,kBAAkB,EAAE,KAAK;QACzB,eAAe,EAAE,sBAAsB,EAAE;QACzC,oBAAoB,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;KACrC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/C,GAAG,EAAE,oBAAoB;IACzB,OAAO,EAAE,+BAA+B;CACzC,CAAC,CAAC","sourcesContent":["import { useCallback } from 'react';\nimport RNFishjamClientModule, {\n ReceivableEvents,\n} from '../RNFishjamClientModule';\nimport { SimulcastConfig } from '../types';\nimport { ScreenShareOptions } from './useScreenShare';\nimport { Platform } from 'react-native';\nimport { useFishjamEventState } from './internal/useFishjamEventState';\n\nconst defaultSimulcastConfig = () =>\n ({\n enabled: false,\n }) satisfies SimulcastConfig;\n\nlet screenShareSimulcastConfig: SimulcastConfig = defaultSimulcastConfig();\n\ntype AppScreenShareData = {\n isAppScreenShareOn: boolean;\n simulcastConfig: SimulcastConfig;\n toggleAppScreenShare: (\n screenShareOptions?: Partial<ScreenShareOptions>,\n ) => Promise<void>;\n};\n\nfunction useIosAppScreenShare(): AppScreenShareData {\n const isAppScreenShareOn = useFishjamEventState(\n ReceivableEvents.IsAppScreenShareOn,\n RNFishjamClientModule.isAppScreenShareOn,\n );\n\n const simulcastConfig = useFishjamEventState(\n ReceivableEvents.SimulcastConfigUpdate,\n screenShareSimulcastConfig,\n );\n\n const toggleAppScreenShare = useCallback(\n async (screenShareOptions: Partial<ScreenShareOptions> = {}) => {\n const options = {\n ...screenShareOptions,\n screenShareMetadata: {\n displayName: 'presenting',\n type: 'screenShareVideo' as const,\n active: !isAppScreenShareOn,\n },\n };\n await RNFishjamClientModule.toggleAppScreenShare(options);\n screenShareSimulcastConfig = defaultSimulcastConfig(); //to do: sync with camera settings\n },\n [isAppScreenShareOn],\n );\n\n return {\n isAppScreenShareOn,\n simulcastConfig,\n /**\n * Toggles the screen share on/off.\n * Emits warning on ios when user is screensharing full screen.\n */\n toggleAppScreenShare,\n };\n}\n\nfunction useDefaultAppScreenShareAndroid(): AppScreenShareData {\n return {\n isAppScreenShareOn: false,\n simulcastConfig: defaultSimulcastConfig(),\n toggleAppScreenShare: async () => {},\n };\n}\n\n/**\n * This hook can toggle client app screen sharing on/off and provides current screen share state.\n *\n * It works only on iOS.\n *\n * @returns An object with functions to manage app screen share on iOS and null on android.\n * @category Connection\n * @group Hooks\n */\nexport const useAppScreenShare = Platform.select({\n ios: useIosAppScreenShare,\n default: useDefaultAppScreenShareAndroid,\n});\n"]}
1
+ {"version":3,"file":"useAppScreenShare.js","sourceRoot":"","sources":["../../src/hooks/useAppScreenShare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,qBAAqB,EAAE,EAC5B,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,MAAM,sBAAsB,GAAG,GAAG,EAAE,CAClC,CAAC;IACC,OAAO,EAAE,KAAK;CACf,CAA2B,CAAC;AAE/B,IAAI,0BAA0B,GAAoB,sBAAsB,EAAE,CAAC;AAU3E,SAAS,oBAAoB;IAC3B,MAAM,kBAAkB,GAAG,oBAAoB,CAC7C,gBAAgB,CAAC,kBAAkB,EACnC,qBAAqB,CAAC,kBAAkB,CACzC,CAAC;IAEF,MAAM,eAAe,GAAG,oBAAoB,CAC1C,gBAAgB,CAAC,qBAAqB,EACtC,0BAA0B,CAC3B,CAAC;IAEF,MAAM,oBAAoB,GAAG,WAAW,CACtC,KAAK,EAAE,qBAAkD,EAAE,EAAE,EAAE;QAC7D,MAAM,OAAO,GAAG;YACd,GAAG,kBAAkB;YACrB,mBAAmB,EAAE;gBACnB,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,kBAA2B;gBACjC,MAAM,EAAE,CAAC,kBAAkB;aAC5B;SACF,CAAC;QACF,MAAM,qBAAqB,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1D,0BAA0B,GAAG,sBAAsB,EAAE,CAAC,CAAC,kCAAkC;IAC3F,CAAC,EACD,CAAC,kBAAkB,CAAC,CACrB,CAAC;IAEF,OAAO;QACL,kBAAkB;QAClB,eAAe;QACf;;;WAGG;QACH,oBAAoB;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B;IACtC,OAAO;QACL,kBAAkB,EAAE,KAAK;QACzB,eAAe,EAAE,sBAAsB,EAAE;QACzC,oBAAoB,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;KACrC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/C,GAAG,EAAE,oBAAoB;IACzB,OAAO,EAAE,+BAA+B;CACzC,CAAC,CAAC","sourcesContent":["import { useCallback } from 'react';\nimport RNFishjamClientModule, {\n ReceivableEvents,\n} from '../RNFishjamClientModule';\nimport { SimulcastConfig } from '../types';\nimport { ScreenShareOptions } from './useScreenShare';\nimport { Platform } from 'react-native';\nimport { useFishjamEventState } from './internal/useFishjamEventState';\n\nconst defaultSimulcastConfig = () =>\n ({\n enabled: false,\n }) satisfies SimulcastConfig;\n\nlet screenShareSimulcastConfig: SimulcastConfig = defaultSimulcastConfig();\n\nexport type AppScreenShareData = {\n isAppScreenShareOn: boolean;\n simulcastConfig: SimulcastConfig;\n toggleAppScreenShare: (\n screenShareOptions?: Partial<ScreenShareOptions>,\n ) => Promise<void>;\n};\n\nfunction useIosAppScreenShare(): AppScreenShareData {\n const isAppScreenShareOn = useFishjamEventState(\n ReceivableEvents.IsAppScreenShareOn,\n RNFishjamClientModule.isAppScreenShareOn,\n );\n\n const simulcastConfig = useFishjamEventState(\n ReceivableEvents.SimulcastConfigUpdate,\n screenShareSimulcastConfig,\n );\n\n const toggleAppScreenShare = useCallback(\n async (screenShareOptions: Partial<ScreenShareOptions> = {}) => {\n const options = {\n ...screenShareOptions,\n screenShareMetadata: {\n displayName: 'presenting',\n type: 'screenShareVideo' as const,\n active: !isAppScreenShareOn,\n },\n };\n await RNFishjamClientModule.toggleAppScreenShare(options);\n screenShareSimulcastConfig = defaultSimulcastConfig(); //to do: sync with camera settings\n },\n [isAppScreenShareOn],\n );\n\n return {\n isAppScreenShareOn,\n simulcastConfig,\n /**\n * Toggles the screen share on/off.\n * Emits warning on ios when user is screensharing full screen.\n */\n toggleAppScreenShare,\n };\n}\n\nfunction useDefaultAppScreenShareAndroid(): AppScreenShareData {\n return {\n isAppScreenShareOn: false,\n simulcastConfig: defaultSimulcastConfig(),\n toggleAppScreenShare: async () => {},\n };\n}\n\n/**\n * This hook can toggle client app screen sharing on/off and provides current screen share state.\n *\n * It works only on iOS.\n *\n * @returns An object with functions to manage app screen share on iOS and null on android.\n * @category Connection\n * @group Hooks\n */\nexport const useAppScreenShare = Platform.select({\n ios: useIosAppScreenShare,\n default: useDefaultAppScreenShareAndroid,\n});\n"]}
@@ -12,7 +12,7 @@ export type CurrentCameraChangedType = {
12
12
  isCameraInitialized: boolean;
13
13
  };
14
14
  export type VideoQuality = 'QVGA169' | 'VGA169' | 'QHD169' | 'HD169' | 'FHD169' | 'QVGA43' | 'VGA43' | 'QHD43' | 'HD43' | 'FHD43';
15
- type CameraConfigBase = {
15
+ export type CameraConfigBase = {
16
16
  /**
17
17
  * resolution + aspect ratio of local video track, one of: `QVGA_169`, `VGA_169`, `QHD_169`, `HD_169`,
18
18
  * `FHD_169`, `QVGA_43`, `VGA_43`, `QHD_43`, `HD_43`, `FHD_43`. Note that quality might be worse than
@@ -110,5 +110,4 @@ export declare function useCamera(): {
110
110
  */
111
111
  switchCamera: (cameraId: CameraId) => Promise<void>;
112
112
  };
113
- export {};
114
113
  //# sourceMappingURL=useCamera.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCamera.d.ts","sourceRoot":"","sources":["../../src/hooks/useCamera.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMlD,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEjD,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC;AAErE,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,qBAAqB,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,OAAO,GACP,MAAM,GACN,OAAO,CAAC;AAEZ,KAAK,gBAAgB,GAAG;IACtB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG;IAC5C;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAI5B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG;IACpD,kBAAkB,CAAC,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC;IACzD;;OAEG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,CAAC;AAgBF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,GAC7B,oBAAoB,CAMtB;AAED;;;;GAIG;AACH,wBAAgB,SAAS;IAmDrB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;;OAGG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;;;OAIG;6BA1DY,QAAQ,CAAC,YAAY,CAAC;IA4DrC;;;;OAIG;6BAxC6C,QAAQ;EA2C3D"}
1
+ {"version":3,"file":"useCamera.d.ts","sourceRoot":"","sources":["../../src/hooks/useCamera.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMlD,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEjD,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,CAAC;AAErE,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,qBAAqB,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,OAAO,GACP,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG;IAC5C;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAI5B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG;IACpD,kBAAkB,CAAC,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC;IACzD;;OAEG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,CAAC;AAgBF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,GAC7B,oBAAoB,CAMtB;AAED;;;;GAIG;AACH,wBAAgB,SAAS;IAmDrB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;;OAGG;;IAEH;;OAEG;;IAEH;;OAEG;;IAEH;;;;OAIG;6BA1DY,QAAQ,CAAC,YAAY,CAAC;IA4DrC;;;;OAIG;6BAxC6C,QAAQ;EA2C3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"useCamera.js","sourceRoot":"","sources":["../../src/hooks/useCamera.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useMemo } from 'react';\nimport { Brand, SimulcastConfig } from '../types';\nimport RNFishjamClientModule, {\n ReceivableEvents,\n} from '../RNFishjamClientModule';\nimport { useFishjamEventState } from './internal/useFishjamEventState';\n\nexport type CameraId = Brand<string, 'CameraId'>;\n\nexport type CameraFacingDirection = 'front' | 'back' | 'unspecified';\n\nexport type Camera = {\n id: CameraId;\n name: string;\n facingDirection: CameraFacingDirection;\n};\n\nexport type CurrentCameraChangedType = {\n currentCamera: Camera | null;\n isCameraOn: boolean;\n isCameraInitialized: boolean;\n};\n\nexport type VideoQuality =\n | 'QVGA169'\n | 'VGA169'\n | 'QHD169'\n | 'HD169'\n | 'FHD169'\n | 'QVGA43'\n | 'VGA43'\n | 'QHD43'\n | 'HD43'\n | 'FHD43';\n\ntype CameraConfigBase = {\n /**\n * resolution + aspect ratio of local video track, one of: `QVGA_169`, `VGA_169`, `QHD_169`, `HD_169`,\n * `FHD_169`, `QVGA_43`, `VGA_43`, `QHD_43`, `HD_43`, `FHD_43`. Note that quality might be worse than\n * specified due to device capabilities, internet connection etc.\n * @default `VGA_169`\n */\n quality?: VideoQuality;\n /**\n * whether to flip the dimensions of the video, that is whether to film in vertical orientation.\n * This basically switches width with height and is only used to select closes capture format.\n *\n * To record horizontal video your phone orientation must be in landscape and your app must support this orientation.\n *\n * Platform specific capture formats:\n * @see iOS: https://developer.apple.com/documentation/avfoundation/avcapturedevice/format\n * @see Android: https://github.com/webrtc-sdk/webrtc/blob/cdc3bba5aa38910a55428b919ba45aceac1ad9ad/sdk/android/api/org/webrtc/CameraEnumerationAndroid.java#L50\n *\n * WebRTC device orientation handling:\n * @see iOS: https://github.com/webrtc-sdk/webrtc/blob/cdc3bba5aa38910a55428b919ba45aceac1ad9ad/sdk/objc/components/capturer/RTCCameraVideoCapturer.m#L285\n * @see Android: https://github.com/pristineio/webrtc-mirror/blob/7a5bcdffaab90a05bc1146b2b1ea71c004e54d71/webrtc/sdk/android/src/java/org/webrtc/Camera2Session.java#L347\n *\n * @default `true`\n */\n flipDimensions?: boolean;\n /**\n * whether the camera track is initially enabled, you can toggle it on/off later with toggleCamera method\n * @default `true`\n */\n cameraEnabled?: boolean;\n /**\n * id of the camera to start capture with. Get available cameras with `cameras`.\n * You can switch the cameras later with `switchCamera` functions.\n * @default the first front camera\n */\n cameraId?: CameraId;\n};\n\nexport type CameraConfig = CameraConfigBase & {\n /**\n * whether video track uses simulcast. By default simulcast is disabled.\n */\n simulcastEnabled?: boolean;\n /**\n * bandwidth limit of a video track. By default there is no bandwidth limit.\n */\n};\n\nexport type CameraConfigInternal = CameraConfigBase & {\n videoTrackMetadata?: { active: boolean; type: 'camera' };\n /**\n * SimulcastConfig of a video track. By default simulcast is disabled.\n */\n simulcastConfig?: SimulcastConfig;\n};\n\nconst defaultSimulcastConfig = () =>\n ({\n enabled: false,\n }) satisfies SimulcastConfig;\n\nfunction getSimulcastConfig(\n simulcastEnabled: boolean | undefined,\n): SimulcastConfig | undefined {\n if (simulcastEnabled) {\n return { enabled: true };\n }\n return undefined;\n}\n\nexport function updateCameraConfig(\n config: Readonly<CameraConfig>,\n): CameraConfigInternal {\n return {\n ...config,\n videoTrackMetadata: { active: true, type: 'camera' },\n simulcastConfig: getSimulcastConfig(config.simulcastEnabled),\n };\n}\n\n/**\n * This hook can toggle camera on/off and provides current camera state.\n * @category Devices\n * @group Hooks\n */\nexport function useCamera() {\n const simulcastConfig = useFishjamEventState(\n ReceivableEvents.SimulcastConfigUpdate,\n defaultSimulcastConfig(), // TODO: Fetch from native\n );\n\n const {\n currentCamera: currentCameraState,\n isCameraOn,\n isCameraInitialized,\n } = useFishjamEventState(ReceivableEvents.CurrentCameraChanged, {\n currentCamera: RNFishjamClientModule.currentCamera,\n isCameraOn: RNFishjamClientModule.isCameraOn,\n isCameraInitialized: RNFishjamClientModule.isCameraInitialized,\n });\n\n // For Android Expo converts null to undefined ¯\\_(ツ)_/¯\n const currentCamera = currentCameraState ?? null;\n\n const cameras = useMemo(() => RNFishjamClientModule.cameras, []);\n\n const prepareCamera = useCallback(\n async (config: Readonly<CameraConfig> = {}) => {\n const camera = RNFishjamClientModule.cameras.find((cam) =>\n config.cameraId\n ? cam.id === config.cameraId\n : cam.facingDirection === 'front',\n );\n\n const updatedConfig = updateCameraConfig({\n ...config,\n cameraId: camera?.id,\n });\n return RNFishjamClientModule.startCamera(updatedConfig);\n },\n [],\n );\n\n const toggleCamera = useCallback(async () => {\n const state = await RNFishjamClientModule.toggleCamera();\n await RNFishjamClientModule.updateVideoTrackMetadata({\n active: state,\n type: 'camera',\n });\n }, []);\n\n const switchCamera = useCallback(async (cameraId: CameraId) => {\n await RNFishjamClientModule.switchCamera(cameraId);\n }, []);\n\n return {\n /**\n * Informs if user camera is streaming video\n */\n isCameraOn,\n /**\n * Which camera is now used for streaming (or will be used as default when camera will be enabled)\n */\n currentCamera,\n /**\n * Simulcast configuration\n */\n simulcastConfig,\n /**\n * Property that lists cameras available on device.\n * @returns A promise that resolves to the list of available cameras.\n */\n cameras,\n /**\n * A value indicating if camera was already initialized (if `prepareCamera` was called).\n */\n isInitialized: isCameraInitialized,\n /**\n * Enable/disable current camera\n */\n toggleCamera,\n /**\n * Prepares camera and starts local video track\n * @param config configuration of the camera capture\n * @returns A promise that resolves when camera is started.\n */\n prepareCamera,\n /**\n * Switches to the specified camera.\n * List of available devices can be retrieved from `cameras` variable\n * @returns A promise that resolves when camera is switched.\n */\n switchCamera,\n };\n}\n"]}
1
+ {"version":3,"file":"useCamera.js","sourceRoot":"","sources":["../../src/hooks/useCamera.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useMemo } from 'react';\nimport { Brand, SimulcastConfig } from '../types';\nimport RNFishjamClientModule, {\n ReceivableEvents,\n} from '../RNFishjamClientModule';\nimport { useFishjamEventState } from './internal/useFishjamEventState';\n\nexport type CameraId = Brand<string, 'CameraId'>;\n\nexport type CameraFacingDirection = 'front' | 'back' | 'unspecified';\n\nexport type Camera = {\n id: CameraId;\n name: string;\n facingDirection: CameraFacingDirection;\n};\n\nexport type CurrentCameraChangedType = {\n currentCamera: Camera | null;\n isCameraOn: boolean;\n isCameraInitialized: boolean;\n};\n\nexport type VideoQuality =\n | 'QVGA169'\n | 'VGA169'\n | 'QHD169'\n | 'HD169'\n | 'FHD169'\n | 'QVGA43'\n | 'VGA43'\n | 'QHD43'\n | 'HD43'\n | 'FHD43';\n\nexport type CameraConfigBase = {\n /**\n * resolution + aspect ratio of local video track, one of: `QVGA_169`, `VGA_169`, `QHD_169`, `HD_169`,\n * `FHD_169`, `QVGA_43`, `VGA_43`, `QHD_43`, `HD_43`, `FHD_43`. Note that quality might be worse than\n * specified due to device capabilities, internet connection etc.\n * @default `VGA_169`\n */\n quality?: VideoQuality;\n /**\n * whether to flip the dimensions of the video, that is whether to film in vertical orientation.\n * This basically switches width with height and is only used to select closes capture format.\n *\n * To record horizontal video your phone orientation must be in landscape and your app must support this orientation.\n *\n * Platform specific capture formats:\n * @see iOS: https://developer.apple.com/documentation/avfoundation/avcapturedevice/format\n * @see Android: https://github.com/webrtc-sdk/webrtc/blob/cdc3bba5aa38910a55428b919ba45aceac1ad9ad/sdk/android/api/org/webrtc/CameraEnumerationAndroid.java#L50\n *\n * WebRTC device orientation handling:\n * @see iOS: https://github.com/webrtc-sdk/webrtc/blob/cdc3bba5aa38910a55428b919ba45aceac1ad9ad/sdk/objc/components/capturer/RTCCameraVideoCapturer.m#L285\n * @see Android: https://github.com/pristineio/webrtc-mirror/blob/7a5bcdffaab90a05bc1146b2b1ea71c004e54d71/webrtc/sdk/android/src/java/org/webrtc/Camera2Session.java#L347\n *\n * @default `true`\n */\n flipDimensions?: boolean;\n /**\n * whether the camera track is initially enabled, you can toggle it on/off later with toggleCamera method\n * @default `true`\n */\n cameraEnabled?: boolean;\n /**\n * id of the camera to start capture with. Get available cameras with `cameras`.\n * You can switch the cameras later with `switchCamera` functions.\n * @default the first front camera\n */\n cameraId?: CameraId;\n};\n\nexport type CameraConfig = CameraConfigBase & {\n /**\n * whether video track uses simulcast. By default simulcast is disabled.\n */\n simulcastEnabled?: boolean;\n /**\n * bandwidth limit of a video track. By default there is no bandwidth limit.\n */\n};\n\nexport type CameraConfigInternal = CameraConfigBase & {\n videoTrackMetadata?: { active: boolean; type: 'camera' };\n /**\n * SimulcastConfig of a video track. By default simulcast is disabled.\n */\n simulcastConfig?: SimulcastConfig;\n};\n\nconst defaultSimulcastConfig = () =>\n ({\n enabled: false,\n }) satisfies SimulcastConfig;\n\nfunction getSimulcastConfig(\n simulcastEnabled: boolean | undefined,\n): SimulcastConfig | undefined {\n if (simulcastEnabled) {\n return { enabled: true };\n }\n return undefined;\n}\n\nexport function updateCameraConfig(\n config: Readonly<CameraConfig>,\n): CameraConfigInternal {\n return {\n ...config,\n videoTrackMetadata: { active: true, type: 'camera' },\n simulcastConfig: getSimulcastConfig(config.simulcastEnabled),\n };\n}\n\n/**\n * This hook can toggle camera on/off and provides current camera state.\n * @category Devices\n * @group Hooks\n */\nexport function useCamera() {\n const simulcastConfig = useFishjamEventState(\n ReceivableEvents.SimulcastConfigUpdate,\n defaultSimulcastConfig(), // TODO: Fetch from native\n );\n\n const {\n currentCamera: currentCameraState,\n isCameraOn,\n isCameraInitialized,\n } = useFishjamEventState(ReceivableEvents.CurrentCameraChanged, {\n currentCamera: RNFishjamClientModule.currentCamera,\n isCameraOn: RNFishjamClientModule.isCameraOn,\n isCameraInitialized: RNFishjamClientModule.isCameraInitialized,\n });\n\n // For Android Expo converts null to undefined ¯\\_(ツ)_/¯\n const currentCamera = currentCameraState ?? null;\n\n const cameras = useMemo(() => RNFishjamClientModule.cameras, []);\n\n const prepareCamera = useCallback(\n async (config: Readonly<CameraConfig> = {}) => {\n const camera = RNFishjamClientModule.cameras.find((cam) =>\n config.cameraId\n ? cam.id === config.cameraId\n : cam.facingDirection === 'front',\n );\n\n const updatedConfig = updateCameraConfig({\n ...config,\n cameraId: camera?.id,\n });\n return RNFishjamClientModule.startCamera(updatedConfig);\n },\n [],\n );\n\n const toggleCamera = useCallback(async () => {\n const state = await RNFishjamClientModule.toggleCamera();\n await RNFishjamClientModule.updateVideoTrackMetadata({\n active: state,\n type: 'camera',\n });\n }, []);\n\n const switchCamera = useCallback(async (cameraId: CameraId) => {\n await RNFishjamClientModule.switchCamera(cameraId);\n }, []);\n\n return {\n /**\n * Informs if user camera is streaming video\n */\n isCameraOn,\n /**\n * Which camera is now used for streaming (or will be used as default when camera will be enabled)\n */\n currentCamera,\n /**\n * Simulcast configuration\n */\n simulcastConfig,\n /**\n * Property that lists cameras available on device.\n * @returns A promise that resolves to the list of available cameras.\n */\n cameras,\n /**\n * A value indicating if camera was already initialized (if `prepareCamera` was called).\n */\n isInitialized: isCameraInitialized,\n /**\n * Enable/disable current camera\n */\n toggleCamera,\n /**\n * Prepares camera and starts local video track\n * @param config configuration of the camera capture\n * @returns A promise that resolves when camera is started.\n */\n prepareCamera,\n /**\n * Switches to the specified camera.\n * List of available devices can be retrieved from `cameras` variable\n * @returns A promise that resolves when camera is switched.\n */\n switchCamera,\n };\n}\n"]}
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { SimulcastConfig, VideoLayout } from './types';
1
+ export type { SimulcastConfig, VideoLayout, GenericMetadata, TrackMetadata, Brand, } from './types';
2
2
  export type { ConnectionConfig } from './common/client';
3
3
  export { updatePeerMetadata } from './common/metadata';
4
4
  export {
@@ -10,12 +10,13 @@ export type { VideoPreviewViewProps } from './components/VideoPreviewView';
10
10
  export type { VideoRendererProps } from './components/VideoRendererView';
11
11
  export { VideoPreviewView } from './components/VideoPreviewView';
12
12
  export { VideoRendererView } from './components/VideoRendererView';
13
- export type { Peer, PeerId, Track, TrackId, TrackType, VadStatus, EncodingReason, TrackBase, AudioTrack, VideoTrack, UsePeersResult, PeerWithTracks, PeerTrackMetadata, } from './hooks/usePeers';
13
+ export type { Peer, PeerId, Track, TrackId, TrackType, VadStatus, EncodingReason, TrackBase, AudioTrack, VideoTrack, UsePeersResult, PeerWithTracks, PeerTrackMetadata, DistinguishedTracks, } from './hooks/usePeers';
14
14
  export type { AudioOutputDevice, AudioOutputDeviceType, AudioSessionMode, } from './hooks/useAudioSettings';
15
- export type { CameraId, Camera, CameraConfig, VideoQuality, CameraFacingDirection, } from './hooks/useCamera';
15
+ export type { CameraId, Camera, CameraConfig, VideoQuality, CameraFacingDirection, CameraConfigBase, } from './hooks/useCamera';
16
16
  export type { ScreenShareOptions, ScreenShareQuality, } from './hooks/useScreenShare';
17
17
  export type { ForegroundServiceConfig } from './hooks/useForegroundService';
18
18
  export type { JoinRoomConfig, ReconnectionStatus, PeerStatus, } from './hooks/useConnection';
19
+ export type { AppScreenShareData } from './hooks/useAppScreenShare';
19
20
  export { useAudioSettings } from './hooks/useAudioSettings';
20
21
  export { useBandwidthEstimation } from './hooks/useBandwidthEstimation';
21
22
  export { useCamera } from './hooks/useCamera';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAGA,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAIxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO;AACL,kBAAkB;AAClB,QAAQ;AACR,kBAAkB;AAClB,SAAS,GACV,MAAM,iBAAiB,CAAC;AAIzB,YAAY,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAInE,YAAY,EACV,IAAI,EACJ,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,cAAc,EACd,SAAS,EACT,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,UAAU,GACX,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAGA,YAAY,EACV,eAAe,EACf,WAAW,EACX,eAAe,EACf,aAAa,EACb,KAAK,GACN,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAIxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO;AACL,kBAAkB;AAClB,QAAQ;AACR,kBAAkB;AAClB,SAAS,GACV,MAAM,iBAAiB,CAAC;AAIzB,YAAY,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAInE,YAAY,EACV,IAAI,EACJ,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,cAAc,EACd,SAAS,EACT,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,UAAU,GACX,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAIpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAKlE,aAAa;AAEb,kBAAkB;AAClB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO;AACL,kBAAkB;AAClB,QAAQ;AACR,kBAAkB;AAClB,SAAS,GACV,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AA4CnE,aAAa;AAEb,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAItE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,yBAAyB,EAAE,CAAC","sourcesContent":["import { initializeWarningListener } from './utils/errorListener';\n\n// #region types\nexport type { SimulcastConfig, VideoLayout } from './types';\nexport type { ConnectionConfig } from './common/client';\n// #endregion\n\n// #region methods\nexport { updatePeerMetadata } from './common/metadata';\nexport {\n /** @deprecated */\n joinRoom,\n /** @deprecated */\n leaveRoom,\n} from './common/client';\n// #endregion\n\n// #region components\nexport type { VideoPreviewViewProps } from './components/VideoPreviewView';\nexport type { VideoRendererProps } from './components/VideoRendererView';\n\nexport { VideoPreviewView } from './components/VideoPreviewView';\nexport { VideoRendererView } from './components/VideoRendererView';\n// #endregion\n\n// #region types for hooks\nexport type {\n Peer,\n PeerId,\n Track,\n TrackId,\n TrackType,\n VadStatus,\n EncodingReason,\n TrackBase,\n AudioTrack,\n VideoTrack,\n UsePeersResult,\n PeerWithTracks,\n PeerTrackMetadata,\n} from './hooks/usePeers';\n\nexport type {\n AudioOutputDevice,\n AudioOutputDeviceType,\n AudioSessionMode,\n} from './hooks/useAudioSettings';\n\nexport type {\n CameraId,\n Camera,\n CameraConfig,\n VideoQuality,\n CameraFacingDirection,\n} from './hooks/useCamera';\n\nexport type {\n ScreenShareOptions,\n ScreenShareQuality,\n} from './hooks/useScreenShare';\nexport type { ForegroundServiceConfig } from './hooks/useForegroundService';\nexport type {\n JoinRoomConfig,\n ReconnectionStatus,\n PeerStatus,\n} from './hooks/useConnection';\n// #endregion\n\n// #region hooks\nexport { useAudioSettings } from './hooks/useAudioSettings';\nexport { useBandwidthEstimation } from './hooks/useBandwidthEstimation';\nexport { useCamera } from './hooks/useCamera';\nexport { useMicrophone } from './hooks/useMicrophone';\nexport { useScreenShare } from './hooks/useScreenShare';\nexport { useAppScreenShare } from './hooks/useAppScreenShare';\nexport { useReconnection } from './hooks/useReconnection';\nexport { usePeerStatus } from './hooks/usePeerStatus';\nexport { usePeers } from './hooks/usePeers';\nexport { useForegroundService } from './hooks/useForegroundService';\nexport { useConnection } from './hooks/useConnection';\nexport { useUpdatePeerMetadata } from './hooks/useUpdatePeerMetadata';\n// #endregion\n\nexport type { FishjamRoomProps } from './components/FishjamRoom';\nexport { FishjamRoom } from './components/FishjamRoom';\n\ninitializeWarningListener();\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAWlE,aAAa;AAEb,kBAAkB;AAClB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO;AACL,kBAAkB;AAClB,QAAQ;AACR,kBAAkB;AAClB,SAAS,GACV,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AA+CnE,aAAa;AAEb,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAItE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,yBAAyB,EAAE,CAAC","sourcesContent":["import { initializeWarningListener } from './utils/errorListener';\n\n// #region types\nexport type {\n SimulcastConfig,\n VideoLayout,\n GenericMetadata,\n TrackMetadata,\n Brand,\n} from './types';\nexport type { ConnectionConfig } from './common/client';\n// #endregion\n\n// #region methods\nexport { updatePeerMetadata } from './common/metadata';\nexport {\n /** @deprecated */\n joinRoom,\n /** @deprecated */\n leaveRoom,\n} from './common/client';\n// #endregion\n\n// #region components\nexport type { VideoPreviewViewProps } from './components/VideoPreviewView';\nexport type { VideoRendererProps } from './components/VideoRendererView';\n\nexport { VideoPreviewView } from './components/VideoPreviewView';\nexport { VideoRendererView } from './components/VideoRendererView';\n// #endregion\n\n// #region types for hooks\nexport type {\n Peer,\n PeerId,\n Track,\n TrackId,\n TrackType,\n VadStatus,\n EncodingReason,\n TrackBase,\n AudioTrack,\n VideoTrack,\n UsePeersResult,\n PeerWithTracks,\n PeerTrackMetadata,\n DistinguishedTracks,\n} from './hooks/usePeers';\n\nexport type {\n AudioOutputDevice,\n AudioOutputDeviceType,\n AudioSessionMode,\n} from './hooks/useAudioSettings';\n\nexport type {\n CameraId,\n Camera,\n CameraConfig,\n VideoQuality,\n CameraFacingDirection,\n CameraConfigBase,\n} from './hooks/useCamera';\n\nexport type {\n ScreenShareOptions,\n ScreenShareQuality,\n} from './hooks/useScreenShare';\nexport type { ForegroundServiceConfig } from './hooks/useForegroundService';\nexport type {\n JoinRoomConfig,\n ReconnectionStatus,\n PeerStatus,\n} from './hooks/useConnection';\nexport type { AppScreenShareData } from './hooks/useAppScreenShare';\n// #endregion\n\n// #region hooks\nexport { useAudioSettings } from './hooks/useAudioSettings';\nexport { useBandwidthEstimation } from './hooks/useBandwidthEstimation';\nexport { useCamera } from './hooks/useCamera';\nexport { useMicrophone } from './hooks/useMicrophone';\nexport { useScreenShare } from './hooks/useScreenShare';\nexport { useAppScreenShare } from './hooks/useAppScreenShare';\nexport { useReconnection } from './hooks/useReconnection';\nexport { usePeerStatus } from './hooks/usePeerStatus';\nexport { usePeers } from './hooks/usePeers';\nexport { useForegroundService } from './hooks/useForegroundService';\nexport { useConnection } from './hooks/useConnection';\nexport { useUpdatePeerMetadata } from './hooks/useUpdatePeerMetadata';\n// #endregion\n\nexport type { FishjamRoomProps } from './components/FishjamRoom';\nexport { FishjamRoom } from './components/FishjamRoom';\n\ninitializeWarningListener();\n"]}
package/build/types.d.ts CHANGED
@@ -23,6 +23,9 @@ export type TrackMetadata = {
23
23
  };
24
24
  export type GenericMetadata = Record<string, unknown>;
25
25
  declare const brand: unique symbol;
26
+ /**
27
+ * Branded type
28
+ */
26
29
  export type Brand<T, TBrand extends string> = T & {
27
30
  [brand]: TBrand;
28
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,YAAY,GAAG,QAAQ,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;CACzE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAGtD,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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,YAAY,GAAG,QAAQ,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;CACzE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAGtD,OAAO,CAAC,MAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AACnC;;GAEG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,MAAM,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * `FILL` or `FIT` - it works just like RN Image component. `FILL` fills the whole view\n * with video and it may cut some parts of the video. `FIT` scales the video so the whole\n * video is visible, but it may leave some empty space in the view.\n */\nexport type VideoLayout = 'FILL' | 'FIT';\n\n/**\n * A type describing simulcast configuration.\n *\n * At the moment, simulcast track is initialized in three versions - low, medium and high.\n * High resolution is the original track resolution, while medium and low resolutions are\n * the original track resolution scaled down by 2 and 4 respectively.\n */\nexport type SimulcastConfig = {\n /**\n * whether to simulcast track or not. By default simulcast is disabled.\n */\n enabled: boolean;\n};\n\nexport type TrackMetadata = {\n active: boolean;\n type: 'microphone' | 'camera' | 'screenShareVideo' | 'screenShareAudio';\n};\n\nexport type GenericMetadata = Record<string, unknown>;\n\n// branded types are useful for restricting where given value can be passed\ndeclare const brand: unique symbol;\nexport type Brand<T, TBrand extends string> = T & { [brand]: TBrand };\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * `FILL` or `FIT` - it works just like RN Image component. `FILL` fills the whole view\n * with video and it may cut some parts of the video. `FIT` scales the video so the whole\n * video is visible, but it may leave some empty space in the view.\n */\nexport type VideoLayout = 'FILL' | 'FIT';\n\n/**\n * A type describing simulcast configuration.\n *\n * At the moment, simulcast track is initialized in three versions - low, medium and high.\n * High resolution is the original track resolution, while medium and low resolutions are\n * the original track resolution scaled down by 2 and 4 respectively.\n */\nexport type SimulcastConfig = {\n /**\n * whether to simulcast track or not. By default simulcast is disabled.\n */\n enabled: boolean;\n};\n\nexport type TrackMetadata = {\n active: boolean;\n type: 'microphone' | 'camera' | 'screenShareVideo' | 'screenShareAudio';\n};\n\nexport type GenericMetadata = Record<string, unknown>;\n\n// branded types are useful for restricting where given value can be passed\ndeclare const brand: unique symbol;\n/**\n * Branded type\n */\nexport type Brand<T, TBrand extends string> = T & { [brand]: TBrand };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"eventPayloadValidator.d.ts","sourceRoot":"","sources":["../../src/utils/eventPayloadValidator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAgElC,wBAAgB,0BAA0B,CACxC,CAAC,SAAS,MAAM,OAAO,gBAAgB,EACvC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAAG,IAAI,CAiDzD"}
1
+ {"version":3,"file":"eventPayloadValidator.d.ts","sourceRoot":"","sources":["../../src/utils/eventPayloadValidator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAsDlC,wBAAgB,0BAA0B,CACxC,CAAC,SAAS,MAAM,OAAO,gBAAgB,EACvC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAAG,IAAI,CAiDzD"}
@@ -1,17 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  import { ReceivableEvents, } from '../RNFishjamClientModule';
3
- const TrackMetadataSchema = z.object({
4
- active: z.boolean(),
5
- type: z.enum([
6
- 'microphone',
7
- 'camera',
8
- 'screenShareVideo',
9
- 'screenShareAudio',
10
- ]),
11
- });
12
3
  const BaseTrackSchema = z.object({
13
4
  id: z.string(),
14
- metadata: TrackMetadataSchema.optional(),
5
+ metadata: z.object({}).passthrough(),
15
6
  });
16
7
  const AudioTrackSchema = BaseTrackSchema.extend({
17
8
  type: z.literal('Audio'),
@@ -28,7 +19,7 @@ const PeerSchema = z.object({
28
19
  id: z.string(),
29
20
  isLocal: z.boolean(),
30
21
  tracks: z.array(TrackSchema),
31
- metadata: z.record(z.any()),
22
+ metadata: z.object({}).passthrough(),
32
23
  });
33
24
  const SimulcastConfigSchema = z.object({
34
25
  enabled: z.boolean(),
@@ -1 +1 @@
1
- {"version":3,"file":"eventPayloadValidator.js","sourceRoot":"","sources":["../../src/utils/eventPayloadValidator.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport {\n ReceivableEventPayloads,\n ReceivableEvents,\n} from '../RNFishjamClientModule';\n\nconst TrackMetadataSchema = z.object({\n active: z.boolean(),\n type: z.enum([\n 'microphone',\n 'camera',\n 'screenShareVideo',\n 'screenShareAudio',\n ]),\n});\n\nconst BaseTrackSchema = z.object({\n id: z.string(),\n metadata: TrackMetadataSchema.optional(),\n});\n\nconst AudioTrackSchema = BaseTrackSchema.extend({\n type: z.literal('Audio'),\n vadStatus: z.enum(['silence', 'speech']).optional(),\n});\n\nconst VideoTrackSchema = BaseTrackSchema.extend({\n type: z.literal('Video'),\n});\n\nconst TrackSchema = z.discriminatedUnion('type', [\n AudioTrackSchema,\n VideoTrackSchema,\n]);\n\nconst PeerSchema = z.object({\n id: z.string(),\n isLocal: z.boolean(),\n tracks: z.array(TrackSchema),\n metadata: z.record(z.any()),\n});\n\nconst SimulcastConfigSchema = z.object({\n enabled: z.boolean(),\n activeEncodings: z.array(z.enum(['l', 'm', 'h'])),\n});\n\nconst AudioOutputDeviceSchema = z.object({\n name: z.string(),\n type: z.enum(['bluetooth', 'headset', 'speaker', 'earpiece']),\n});\n\nconst AudioDeviceEventSchema = z.object({\n availableDevices: z.array(AudioOutputDeviceSchema),\n selectedDevice: AudioOutputDeviceSchema.nullable(),\n});\n\nconst CameraSchema = z.object({\n id: z.string(),\n name: z.string(),\n facingDirection: z.enum(['front', 'back', 'unspecified']),\n});\n\nconst CameraChangedEventSchema = z.object({\n isCameraOn: z.boolean(),\n currentCamera: CameraSchema.nullable(),\n});\n\nexport function validateNativeEventPayload<\n T extends keyof typeof ReceivableEvents,\n>(eventName: T, payload: ReceivableEventPayloads[T]): void {\n switch (eventName) {\n case ReceivableEvents.IsMicrophoneOn:\n case ReceivableEvents.IsScreenShareOn:\n case ReceivableEvents.IsAppScreenShareOn:\n z.boolean().parse(payload);\n break;\n\n case ReceivableEvents.SimulcastConfigUpdate:\n SimulcastConfigSchema.parse(payload);\n break;\n\n case ReceivableEvents.PeersUpdate:\n z.array(PeerSchema).parse(payload);\n break;\n\n case ReceivableEvents.AudioDeviceUpdate:\n AudioDeviceEventSchema.parse(payload);\n break;\n\n case ReceivableEvents.BandwidthEstimation:\n z.number().nullable().parse(payload);\n break;\n\n case ReceivableEvents.ReconnectionRetriesLimitReached:\n case ReceivableEvents.ReconnectionStarted:\n case ReceivableEvents.Reconnected:\n z.undefined().parse(payload);\n break;\n\n case ReceivableEvents.Warning:\n z.string().parse(payload);\n break;\n\n case ReceivableEvents.PeerStatusChanged:\n z.enum(['connecting', 'connected', 'error', 'idle']).parse(payload);\n break;\n\n case ReceivableEvents.ReconnectionStatusChanged:\n z.enum(['connecting', 'connected', 'error']).parse(payload);\n break;\n\n case ReceivableEvents.CurrentCameraChanged:\n CameraChangedEventSchema.parse(payload);\n break;\n\n default:\n throw new Error(`Unknown event: ${eventName}`);\n }\n}\n"]}
1
+ {"version":3,"file":"eventPayloadValidator.js","sourceRoot":"","sources":["../../src/utils/eventPayloadValidator.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport {\n ReceivableEventPayloads,\n ReceivableEvents,\n} from '../RNFishjamClientModule';\n\nconst BaseTrackSchema = z.object({\n id: z.string(),\n metadata: z.object({}).passthrough(),\n});\n\nconst AudioTrackSchema = BaseTrackSchema.extend({\n type: z.literal('Audio'),\n vadStatus: z.enum(['silence', 'speech']).optional(),\n});\n\nconst VideoTrackSchema = BaseTrackSchema.extend({\n type: z.literal('Video'),\n});\n\nconst TrackSchema = z.discriminatedUnion('type', [\n AudioTrackSchema,\n VideoTrackSchema,\n]);\n\nconst PeerSchema = z.object({\n id: z.string(),\n isLocal: z.boolean(),\n tracks: z.array(TrackSchema),\n metadata: z.object({}).passthrough(),\n});\n\nconst SimulcastConfigSchema = z.object({\n enabled: z.boolean(),\n activeEncodings: z.array(z.enum(['l', 'm', 'h'])),\n});\n\nconst AudioOutputDeviceSchema = z.object({\n name: z.string(),\n type: z.enum(['bluetooth', 'headset', 'speaker', 'earpiece']),\n});\n\nconst AudioDeviceEventSchema = z.object({\n availableDevices: z.array(AudioOutputDeviceSchema),\n selectedDevice: AudioOutputDeviceSchema.nullable(),\n});\n\nconst CameraSchema = z.object({\n id: z.string(),\n name: z.string(),\n facingDirection: z.enum(['front', 'back', 'unspecified']),\n});\n\nconst CameraChangedEventSchema = z.object({\n isCameraOn: z.boolean(),\n currentCamera: CameraSchema.nullable(),\n});\n\nexport function validateNativeEventPayload<\n T extends keyof typeof ReceivableEvents,\n>(eventName: T, payload: ReceivableEventPayloads[T]): void {\n switch (eventName) {\n case ReceivableEvents.IsMicrophoneOn:\n case ReceivableEvents.IsScreenShareOn:\n case ReceivableEvents.IsAppScreenShareOn:\n z.boolean().parse(payload);\n break;\n\n case ReceivableEvents.SimulcastConfigUpdate:\n SimulcastConfigSchema.parse(payload);\n break;\n\n case ReceivableEvents.PeersUpdate:\n z.array(PeerSchema).parse(payload);\n break;\n\n case ReceivableEvents.AudioDeviceUpdate:\n AudioDeviceEventSchema.parse(payload);\n break;\n\n case ReceivableEvents.BandwidthEstimation:\n z.number().nullable().parse(payload);\n break;\n\n case ReceivableEvents.ReconnectionRetriesLimitReached:\n case ReceivableEvents.ReconnectionStarted:\n case ReceivableEvents.Reconnected:\n z.undefined().parse(payload);\n break;\n\n case ReceivableEvents.Warning:\n z.string().parse(payload);\n break;\n\n case ReceivableEvents.PeerStatusChanged:\n z.enum(['connecting', 'connected', 'error', 'idle']).parse(payload);\n break;\n\n case ReceivableEvents.ReconnectionStatusChanged:\n z.enum(['connecting', 'connected', 'error']).parse(payload);\n break;\n\n case ReceivableEvents.CurrentCameraChanged:\n CameraChangedEventSchema.parse(payload);\n break;\n\n default:\n throw new Error(`Unknown event: ${eventName}`);\n }\n}\n"]}
@@ -22,7 +22,23 @@ class RNFishjamClient: FishjamClientListener {
22
22
  }
23
23
  }
24
24
 
25
- var connectPromise: Promise? = nil
25
+ var connectPromise: Promise? = nil {
26
+ didSet {
27
+ guard connectPromise != nil else { return }
28
+
29
+ let timeout = DispatchTime.now() + .seconds(15)
30
+ DispatchQueue.main.asyncAfter(deadline: timeout) { [weak self] in
31
+ // If promise is still assigned it means it was not resolved in that time,
32
+ // so close the client and reject it with timeout error.
33
+ guard let promise = self?.connectPromise else { return }
34
+ RNFishjamClient.fishjamClient?.leave { [weak self] in
35
+ promise.reject("E_MEMBRANE_CONNECT", "Failed to connect: Fishjam server is not responding")
36
+ self?.connectPromise = nil
37
+ self?.peerStatus = .error
38
+ }
39
+ }
40
+ }
41
+ }
26
42
 
27
43
  var videoSimulcastConfig: SimulcastConfig = SimulcastConfig()
28
44
 
@@ -236,31 +252,35 @@ class RNFishjamClient: FishjamClientListener {
236
252
  }
237
253
  }
238
254
 
255
+ private let startCameraLock = NSLock()
256
+
239
257
  func startCamera(config: CameraConfig) async throws -> Bool {
240
258
  #if targetEnvironment(simulator)
241
259
  emit(
242
260
  event: .warning(
243
261
  message: "Camera is not supported on simulator."))
244
262
  return false
245
- #else
246
- try ensureCreated()
263
+ #endif
264
+
265
+ try ensureCreated()
266
+
267
+ guard await PermissionUtils.requestCameraPermission() else {
268
+ emit(event: .warning(message: "Camera permission not granted."))
269
+ return false
270
+ }
247
271
 
272
+ return try startCameraLock.withLock {
248
273
  guard !isCameraInitialized else {
249
274
  return true
250
275
  }
251
276
 
252
- guard await PermissionUtils.requestCameraPermission() else {
253
- emit(event: .warning(message: "Camera permission not granted."))
254
- return false
255
- }
256
-
257
277
  let cameraTrack = try createCameraTrack(config: config)
258
278
  cameraTrack.captureDeviceChangedListener = self
259
279
  setCameraTrackState(cameraTrack, enabled: config.cameraEnabled)
260
280
  emitEndpoints()
261
281
  isCameraInitialized = true
262
282
  return true
263
- #endif
283
+ }
264
284
  }
265
285
 
266
286
  private func createCameraTrack(config: CameraConfig) throws -> LocalCameraTrack {
@@ -45,6 +45,11 @@ class VideoPreviewView: ExpoView, LocalCameraTrackChangedListener {
45
45
  }
46
46
  }
47
47
 
48
+ override func layoutSubviews() {
49
+ super.layoutSubviews()
50
+ videoView.frame = self.frame
51
+ }
52
+
48
53
  var videoLayout: String = "FILL" {
49
54
  didSet {
50
55
  switch videoLayout {
@@ -26,6 +26,11 @@ class VideoRendererView: ExpoView, TrackUpdateListener {
26
26
  }
27
27
  }
28
28
 
29
+ override func layoutSubviews() {
30
+ super.layoutSubviews()
31
+ videoView.frame = self.frame
32
+ }
33
+
29
34
  func updateVideoTrack() {
30
35
  DispatchQueue.main.async { [weak self] in
31
36
  guard let self, self.superview != nil else { return }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fishjam-cloud/react-native-client",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "A React Native client for Fishjam",
5
5
  "author": "Fishjam Team",
6
6
  "license": "Apache-2.0",
@@ -40,7 +40,6 @@
40
40
  },
41
41
  "homepage": "https://fishjam.io",
42
42
  "dependencies": {
43
- "phoenix": "^1.7.6",
44
43
  "promise-fs": "^2.1.1",
45
44
  "protobufjs": "^7.4.0",
46
45
  "zod": "^3.24.1"
@@ -48,22 +47,21 @@
48
47
  "devDependencies": {
49
48
  "@testing-library/dom": "^10.4.0",
50
49
  "@testing-library/react": "^16.0.1",
51
- "@types/lodash": "^4.17.13",
52
- "@types/phoenix": "^1.6.5",
50
+ "@types/lodash": "^4.17.15",
53
51
  "@types/promise-fs": "^2.1.2",
54
52
  "@types/react": "^18.3.12",
55
- "expo-module-scripts": "^4.0.2",
53
+ "expo-module-scripts": "^4.0.3",
56
54
  "husky": "^9.1.7",
57
55
  "jest": "^29.6.1",
58
56
  "jest-environment-jsdom": "^29.6.1",
59
57
  "jest-expo": "~52.0.2",
60
58
  "jest-websocket-mock": "^2.4.0",
61
- "pod-install": "^0.3.2",
59
+ "pod-install": "^0.3.4",
62
60
  "react-dom": "^18.3.1",
63
- "ts-proto": "^2.6.0",
64
- "typedoc": "^0.27.4",
61
+ "ts-proto": "^2.6.1",
62
+ "typedoc": "^0.27.6",
65
63
  "typedoc-plugin-mark-react-functional-components": "^0.2.2",
66
- "typescript": "^5.7.2"
64
+ "typescript": "^5.7.3"
67
65
  },
68
66
  "peerDependencies": {
69
67
  "expo": "*",
@@ -10,6 +10,7 @@ const withFishjamForegroundService = (config) => (0, config_plugins_1.withAndroi
10
10
  $: {
11
11
  'android:name': 'io.fishjam.reactnative.foregroundService.FishjamForegroundService',
12
12
  'android:foregroundServiceType': 'camera|microphone|mediaProjection',
13
+ 'android:stopWithTask': 'true',
13
14
  },
14
15
  };
15
16
  const existingServiceIndex = mainApplication.service.findIndex((service) => service.$['android:name'] === newService.$['android:name']);