@stream-io/video-react-native-sdk 1.22.2 → 1.23.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/CHANGELOG.md +26 -0
- package/android/src/main/java/com/streamvideo/reactnative/callmanager/ProximityManager.kt +183 -0
- package/android/src/main/java/com/streamvideo/reactnative/callmanager/StreamInCallManagerModule.kt +12 -1
- package/dist/commonjs/components/Livestream/LivestreamPlayer/LivestreamPlayer.js +3 -2
- package/dist/commonjs/components/Livestream/LivestreamPlayer/LivestreamPlayer.js.map +1 -1
- package/dist/commonjs/components/Participant/FloatingParticipantView/index.js +13 -6
- package/dist/commonjs/components/Participant/FloatingParticipantView/index.js.map +1 -1
- package/dist/commonjs/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.js +30 -0
- package/dist/commonjs/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.js.map +1 -0
- package/dist/commonjs/constants/index.js +1 -6
- package/dist/commonjs/constants/index.js.map +1 -1
- package/dist/commonjs/hooks/useTrackDimensions.js +1 -1
- package/dist/commonjs/hooks/useTrackDimensions.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/module/components/Livestream/LivestreamPlayer/LivestreamPlayer.js +3 -2
- package/dist/module/components/Livestream/LivestreamPlayer/LivestreamPlayer.js.map +1 -1
- package/dist/module/components/Participant/FloatingParticipantView/index.js +14 -7
- package/dist/module/components/Participant/FloatingParticipantView/index.js.map +1 -1
- package/dist/module/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.js +23 -0
- package/dist/module/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.js.map +1 -0
- package/dist/module/constants/index.js +0 -5
- package/dist/module/constants/index.js.map +1 -1
- package/dist/module/hooks/useTrackDimensions.js +1 -1
- package/dist/module/hooks/useTrackDimensions.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/components/Livestream/LivestreamPlayer/LivestreamPlayer.d.ts +3 -3
- package/dist/typescript/components/Livestream/LivestreamPlayer/LivestreamPlayer.d.ts.map +1 -1
- package/dist/typescript/components/Participant/FloatingParticipantView/index.d.ts.map +1 -1
- package/dist/typescript/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.d.ts +9 -0
- package/dist/typescript/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.d.ts.map +1 -0
- package/dist/typescript/constants/index.d.ts +0 -5
- package/dist/typescript/constants/index.d.ts.map +1 -1
- package/dist/typescript/hooks/useTrackDimensions.d.ts +1 -1
- package/dist/typescript/hooks/useTrackDimensions.d.ts.map +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/ios/StreamInCallManager.swift +105 -38
- package/package.json +3 -3
- package/src/components/Livestream/LivestreamPlayer/LivestreamPlayer.tsx +5 -3
- package/src/components/Participant/FloatingParticipantView/index.tsx +20 -6
- package/src/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.tsx +36 -0
- package/src/constants/index.ts +0 -6
- package/src/hooks/useTrackDimensions.ts +2 -2
- package/src/version.ts +1 -1
package/dist/module/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useTrackDimensions } from '../../../hooks/useTrackDimensions';
|
|
2
|
+
export const useFloatingVideoDimensions = (containerDimensions, participant, trackType) => {
|
|
3
|
+
const containerWidth = containerDimensions?.width ?? 0;
|
|
4
|
+
const {
|
|
5
|
+
width,
|
|
6
|
+
height
|
|
7
|
+
} = useTrackDimensions(participant, trackType);
|
|
8
|
+
if (width === 0 || height === 0 || containerWidth === 0) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const aspectRatio = width / height;
|
|
12
|
+
|
|
13
|
+
// based on Android AOSP PiP mode default dimensions algorithm
|
|
14
|
+
// 23% of the container width
|
|
15
|
+
const floatingVideoWidth = containerWidth * 0.23;
|
|
16
|
+
// the height is calculated based on the aspect ratio
|
|
17
|
+
const floatingVideoHeight = floatingVideoWidth / aspectRatio;
|
|
18
|
+
return {
|
|
19
|
+
width: floatingVideoWidth,
|
|
20
|
+
height: floatingVideoHeight
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=useFloatingVideoDimensions.js.map
|
package/dist/module/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useTrackDimensions","useFloatingVideoDimensions","containerDimensions","participant","trackType","containerWidth","width","height","undefined","aspectRatio","floatingVideoWidth","floatingVideoHeight"],"sourceRoot":"../../../../../src","sources":["components/Participant/FloatingParticipantView/useFloatingVideoDimensions.tsx"],"mappings":"AAIA,SAASA,kBAAkB,QAAQ,mCAAmC;AAEtE,OAAO,MAAMC,0BAA0B,GAAGA,CACxCC,mBAKa,EACbC,WAA+C,EAC/CC,SAAyB,KACtB;EACH,MAAMC,cAAc,GAAGH,mBAAmB,EAAEI,KAAK,IAAI,CAAC;EACtD,MAAM;IAAEA,KAAK;IAAEC;EAAO,CAAC,GAAGP,kBAAkB,CAACG,WAAW,EAAEC,SAAS,CAAC;EAEpE,IAAIE,KAAK,KAAK,CAAC,IAAIC,MAAM,KAAK,CAAC,IAAIF,cAAc,KAAK,CAAC,EAAE;IACvD,OAAOG,SAAS;EAClB;EAEA,MAAMC,WAAW,GAAGH,KAAK,GAAGC,MAAM;;EAElC;EACA;EACA,MAAMG,kBAAkB,GAAGL,cAAc,GAAG,IAAI;EAChD;EACA,MAAMM,mBAAmB,GAAGD,kBAAkB,GAAGD,WAAW;EAE5D,OAAO;IACLH,KAAK,EAAEI,kBAAkB;IACzBH,MAAM,EAAEI;EACV,CAAC;AACH,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["defaultEmojiReactions","type","emoji_code","custom","icon","Z_INDEX","IN_BACK","IN_MIDDLE","IN_FRONT"],"sourceRoot":"../../../src","sources":["constants/index.ts"],"mappings":"AAEA,OAAO,MAAMA,qBAA2C,GAAG,CACzD;EACEC,IAAI,EAAE,UAAU;EAChBC,UAAU,EAAE,iCAAiC;EAC7CC,MAAM,EAAE,CAAC,CAAC;EACVC,IAAI,EAAE;AACR,CAAC,EACD;EACEH,IAAI,EAAE,UAAU;EAChBC,UAAU,EAAE,QAAQ;EACpBC,MAAM,EAAE,CAAC,CAAC;EACVC,IAAI,EAAE;AACR,CAAC,EACD;EACEH,IAAI,EAAE,UAAU;EAChBC,UAAU,EAAE,UAAU;EACtBC,MAAM,EAAE,CAAC,CAAC;EACVC,IAAI,EAAE;AACR,CAAC,EACD;EACEH,IAAI,EAAE,UAAU;EAChBC,UAAU,EAAE,WAAW;EACvBC,MAAM,EAAE,CAAC,CAAC;EACVC,IAAI,EAAE;AACR,CAAC,EACD;EACEH,IAAI,EAAE,UAAU;EAChBC,UAAU,EAAE,aAAa;EACzBC,MAAM,EAAE,CAAC,CAAC;EACVC,IAAI,EAAE;AACR,CAAC,EACD;EACEH,IAAI,EAAE,UAAU;EAChBC,UAAU,EAAE,gBAAgB;EAC5BC,MAAM,EAAE,CAAC,CAAC;EACVC,IAAI,EAAE;AACR,CAAC,EACD;EACEH,IAAI,EAAE,aAAa;EACnBC,UAAU,EAAE,eAAe;EAC3BC,MAAM,EAAE,CAAC,CAAC;EACVC,IAAI,EAAE;AACR,CAAC,CACF;AAED,OAAO,MAAMC,OAAO,GAAG;EACrBC,OAAO,EAAE,CAAC;EACVC,SAAS,EAAE,CAAC;EACZC,QAAQ,EAAE;AACZ,CAAC","ignoreList":[]}
|
|
@@ -10,7 +10,7 @@ export function useTrackDimensions(participant, trackType) {
|
|
|
10
10
|
const {
|
|
11
11
|
videoStream,
|
|
12
12
|
screenShareStream
|
|
13
|
-
} = participant;
|
|
13
|
+
} = participant || {};
|
|
14
14
|
const stream = trackType === 'screenShareTrack' ? screenShareStream : videoStream;
|
|
15
15
|
const [track] = stream?.getVideoTracks() ?? [];
|
|
16
16
|
const trackId = track?.id;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useEffect","useState","NativeEventEmitter","NativeModules","useTrackDimensions","participant","trackType","videoStream","screenShareStream","stream","track","getVideoTracks","trackId","id","trackDimensions","setTrackDimensions","settings","getSettings","width","height","handleVideoTrackDimensionChanged","eventData","prev","webRTCEventEmitter","WebRTCModule","subscription","addListener","remove"],"sourceRoot":"../../../src","sources":["hooks/useTrackDimensions.ts"],"mappings":"AAIA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAC3C,SAASC,kBAAkB,EAAEC,aAAa,QAAQ,cAAc;;AAEhE;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,kBAAkBA,CAChCC,
|
|
1
|
+
{"version":3,"names":["useEffect","useState","NativeEventEmitter","NativeModules","useTrackDimensions","participant","trackType","videoStream","screenShareStream","stream","track","getVideoTracks","trackId","id","trackDimensions","setTrackDimensions","settings","getSettings","width","height","handleVideoTrackDimensionChanged","eventData","prev","webRTCEventEmitter","WebRTCModule","subscription","addListener","remove"],"sourceRoot":"../../../src","sources":["hooks/useTrackDimensions.ts"],"mappings":"AAIA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAC3C,SAASC,kBAAkB,EAAEC,aAAa,QAAQ,cAAc;;AAEhE;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,kBAAkBA,CAChCC,WAA+C,EAC/CC,SAAyB,EACzB;EACA,MAAM;IAAEC,WAAW;IAAEC;EAAkB,CAAC,GAAGH,WAAW,IAAI,CAAC,CAAC;EAC5D,MAAMI,MAAM,GACVH,SAAS,KAAK,kBAAkB,GAAGE,iBAAiB,GAAGD,WAAW;EACpE,MAAM,CAACG,KAAK,CAAC,GAAGD,MAAM,EAAEE,cAAc,CAAC,CAAC,IAAI,EAAE;EAC9C,MAAMC,OAAO,GAAGF,KAAK,EAAEG,EAAE;EAEzB,MAAM,CAACC,eAAe,EAAEC,kBAAkB,CAAC,GAAGd,QAAQ,CAAC,MAAM;IAC3D,MAAMe,QAAQ,GAAGN,KAAK,EAAEO,WAAW,CAAC,CAAC;IACrC,MAAMC,KAAK,GAAGF,QAAQ,EAAEE,KAAK,IAAI,CAAC;IAClC,MAAMC,MAAM,GAAGH,QAAQ,EAAEG,MAAM,IAAI,CAAC;IACpC,OAAO;MACLD,KAAK;MACLC;IACF,CAAC;EACH,CAAC,CAAC;;EAEF;EACAnB,SAAS,CAAC,MAAM;IACd,IAAI,CAACY,OAAO,IAAI,CAACF,KAAK,EAAE;IAExB,MAAMU,gCAAgC,GAAIC,SAKzC,IAAK;MACJ;MACA,IAAIA,SAAS,CAACT,OAAO,KAAKA,OAAO,EAAE;QACjCG,kBAAkB,CAAEO,IAAI,IAAK;UAC3B,IACEA,IAAI,CAACJ,KAAK,KAAKG,SAAS,CAACH,KAAK,IAC9BI,IAAI,CAACH,MAAM,KAAKE,SAAS,CAACF,MAAM,EAChC;YACA,OAAOG,IAAI;UACb;UACA,OAAO;YAAEJ,KAAK,EAAEG,SAAS,CAACH,KAAK;YAAEC,MAAM,EAAEE,SAAS,CAACF;UAAO,CAAC;QAC7D,CAAC,CAAC;MACJ;IACF,CAAC;IAED,MAAM;MAAED,KAAK;MAAEC;IAAO,CAAC,GAAGT,KAAK,CAACO,WAAW,CAAC,CAAC;IAC7CF,kBAAkB,CAAEO,IAAI,IAAK;MAC3B,IAAIA,IAAI,CAACJ,KAAK,KAAKA,KAAK,IAAII,IAAI,CAACH,MAAM,KAAKA,MAAM,EAAE;QAClD,OAAOG,IAAI;MACb;MACA,OAAO;QACLJ,KAAK,EAAEA,KAAK,IAAI,CAAC;QACjBC,MAAM,EAAEA,MAAM,IAAI;MACpB,CAAC;IACH,CAAC,CAAC;IAEF,MAAMI,kBAAkB,GAAG,IAAIrB,kBAAkB,CAC/CC,aAAa,CAACqB,YAChB,CAAC;IACD,MAAMC,YAAY,GAAGF,kBAAkB,CAACG,WAAW,CACjD,4BAA4B,EAC5BN,gCACF,CAAC;IAED,OAAO,MAAM;MACXK,YAAY,CAACE,MAAM,CAAC,CAAC;IACvB,CAAC;EACH,CAAC,EAAE,CAACf,OAAO,EAAEF,KAAK,CAAC,CAAC;EAEpB,OAAOI,eAAe;AACxB","ignoreList":[]}
|
package/dist/module/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '1.
|
|
1
|
+
export const version = '1.23.0';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
2
|
import { type ViewerLivestreamProps } from '../ViewerLivestream';
|
|
3
3
|
export type LivestreamPlayerProps = {
|
|
4
4
|
/**
|
|
@@ -19,7 +19,7 @@ export type LivestreamPlayerProps = {
|
|
|
19
19
|
*
|
|
20
20
|
* `"asap"` behavior means joining the call as soon as it is possible
|
|
21
21
|
* (either the `join_ahead_time_seconds` setting allows it, or the user
|
|
22
|
-
* has
|
|
22
|
+
* has the capability to join backstage).
|
|
23
23
|
*
|
|
24
24
|
* `"live"` behavior means joining the call when it goes live.
|
|
25
25
|
*
|
|
@@ -27,5 +27,5 @@ export type LivestreamPlayerProps = {
|
|
|
27
27
|
*/
|
|
28
28
|
joinBehavior?: 'asap' | 'live';
|
|
29
29
|
};
|
|
30
|
-
export declare const LivestreamPlayer: ({ callType, callId, ViewerLivestream, joinBehavior, }: LivestreamPlayerProps) => React.JSX.Element | null;
|
|
30
|
+
export declare const LivestreamPlayer: ({ callType, callId, ViewerLivestream, joinBehavior, children, }: PropsWithChildren<LivestreamPlayerProps>) => React.JSX.Element | null;
|
|
31
31
|
//# sourceMappingURL=LivestreamPlayer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LivestreamPlayer.d.ts","sourceRoot":"","sources":["../../../../../src/components/Livestream/LivestreamPlayer/LivestreamPlayer.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"LivestreamPlayer.d.ts","sourceRoot":"","sources":["../../../../../src/components/Livestream/LivestreamPlayer/LivestreamPlayer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAuB,MAAM,OAAO,CAAC;AACtE,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,qBAAqB,CAAC;AAK7B,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAE9D;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,iEAM9B,iBAAiB,CAAC,qBAAqB,CAAC,6BA4C1C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Participant/FloatingParticipantView/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAEL,KAAK,SAAS,EAGd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAKtB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,kCAAkC,EACxC,MAAM,YAAY,CAAC;AAEpB,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Participant/FloatingParticipantView/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAEL,KAAK,SAAS,EAGd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAKtB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,kCAAkC,EACxC,MAAM,YAAY,CAAC;AAEpB,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,MAAM,MAAM,gCAAgC,GACxC,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,6BAA6B,GACtE,IAAI,CAAC,kCAAkC,EAAE,iBAAiB,CAAC,GAC3D,IAAI,CAAC,gBAAgB,EAAE,oBAAoB,CAAC,GAC5C,IAAI,CAAC,oBAAoB,EAAE,WAAW,GAAG,aAAa,CAAC,GAAG;IACxD;;OAEG;IACH,SAAS,CAAC,EAAE,gCAAgC,CAAC;IAC7C;;OAEG;IACH,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC;;OAEG;IACH,oBAAoB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5C;;;OAGG;IACH,uBAAuB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/C;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AA2BJ;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,2PAcrC,4BAA4B,6BAsG9B,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { StreamVideoParticipant, VideoTrackType } from '@stream-io/video-client';
|
|
2
|
+
export declare const useFloatingVideoDimensions: (containerDimensions: {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
} | undefined, participant: StreamVideoParticipant | undefined, trackType: VideoTrackType) => {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
} | undefined;
|
|
9
|
+
//# sourceMappingURL=useFloatingVideoDimensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFloatingVideoDimensions.d.ts","sourceRoot":"","sources":["../../../../../src/components/Participant/FloatingParticipantView/useFloatingVideoDimensions.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,cAAc,EACf,MAAM,yBAAyB,CAAC;AAGjC,eAAO,MAAM,0BAA0B,GACrC,qBACI;IACE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GACD,SAAS,EACb,aAAa,sBAAsB,GAAG,SAAS,EAC/C,WAAW,cAAc;;;aAqB1B,CAAC"}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { type StreamReactionType } from '../components';
|
|
2
|
-
export declare const FLOATING_VIDEO_VIEW_STYLE: {
|
|
3
|
-
height: number;
|
|
4
|
-
width: number;
|
|
5
|
-
borderRadius: number;
|
|
6
|
-
};
|
|
7
2
|
export declare const defaultEmojiReactions: StreamReactionType[];
|
|
8
3
|
export declare const Z_INDEX: {
|
|
9
4
|
IN_BACK: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,eAAO,MAAM,qBAAqB,EAAE,kBAAkB,EA2CrD,CAAC;AAEF,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { type StreamVideoParticipant, type VideoTrackType } from '@stream-io/vid
|
|
|
4
4
|
* Note: the `tracktype` is used only for local participants.
|
|
5
5
|
* `tracktype` should be 'videoTrack' for video track and 'screenShareTrack' for screen share track.
|
|
6
6
|
*/
|
|
7
|
-
export declare function useTrackDimensions(participant: StreamVideoParticipant, trackType: VideoTrackType): {
|
|
7
|
+
export declare function useTrackDimensions(participant: StreamVideoParticipant | undefined, trackType: VideoTrackType): {
|
|
8
8
|
width: number;
|
|
9
9
|
height: number;
|
|
10
10
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTrackDimensions.d.ts","sourceRoot":"","sources":["../../../src/hooks/useTrackDimensions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAIjC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"useTrackDimensions.d.ts","sourceRoot":"","sources":["../../../src/hooks/useTrackDimensions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAIjC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,sBAAsB,GAAG,SAAS,EAC/C,SAAS,EAAE,cAAc;;;EAmE1B"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.
|
|
1
|
+
export declare const version = "1.23.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -18,32 +18,32 @@ enum DefaultAudioDevice {
|
|
|
18
18
|
|
|
19
19
|
@objc(StreamInCallManager)
|
|
20
20
|
class StreamInCallManager: RCTEventEmitter {
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
private let audioSessionQueue = DispatchQueue(label: "io.getstream.rn.audioSessionQueue")
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
private var audioManagerActivated = false
|
|
25
25
|
private var callAudioRole: CallAudioRole = .communicator
|
|
26
26
|
private var defaultAudioDevice: DefaultAudioDevice = .speaker
|
|
27
27
|
private var previousVolume: Float = 0.75
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
private struct AudioSessionState {
|
|
30
30
|
let category: AVAudioSession.Category
|
|
31
31
|
let mode: AVAudioSession.Mode
|
|
32
32
|
let options: AVAudioSession.CategoryOptions
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
private var previousAudioSessionState: AudioSessionState?
|
|
36
|
-
|
|
36
|
+
private var hasRegisteredRouteObserver = false
|
|
37
|
+
|
|
37
38
|
override func invalidate() {
|
|
38
39
|
stop()
|
|
39
40
|
super.invalidate()
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
+
|
|
42
43
|
override static func requiresMainQueueSetup() -> Bool {
|
|
43
44
|
return false
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
@objc(setAudioRole:)
|
|
48
48
|
func setAudioRole(audioRole: String) {
|
|
49
49
|
audioSessionQueue.async { [self] in
|
|
@@ -54,7 +54,7 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
54
54
|
self.callAudioRole = audioRole.lowercased() == "listener" ? .listener : .communicator
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
@objc(setDefaultAudioDeviceEndpointType:)
|
|
59
59
|
func setDefaultAudioDeviceEndpointType(endpointType: String) {
|
|
60
60
|
audioSessionQueue.async { [self] in
|
|
@@ -65,7 +65,7 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
65
65
|
self.defaultAudioDevice = endpointType.lowercased() == "earpiece" ? .earpiece : .speaker
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
@objc
|
|
70
70
|
func start() {
|
|
71
71
|
audioSessionQueue.async { [self] in
|
|
@@ -79,10 +79,17 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
79
79
|
options: session.categoryOptions
|
|
80
80
|
)
|
|
81
81
|
configureAudioSession()
|
|
82
|
+
// Enable wake lock to prevent the screen from dimming/locking during a call
|
|
83
|
+
DispatchQueue.main.async {
|
|
84
|
+
UIApplication.shared.isIdleTimerDisabled = true
|
|
85
|
+
self.registerAudioRouteObserver()
|
|
86
|
+
self.updateProximityMonitoring()
|
|
87
|
+
self.log("Wake lock enabled (idle timer disabled)")
|
|
88
|
+
}
|
|
82
89
|
audioManagerActivated = true
|
|
83
90
|
}
|
|
84
91
|
}
|
|
85
|
-
|
|
92
|
+
|
|
86
93
|
@objc
|
|
87
94
|
func stop() {
|
|
88
95
|
audioSessionQueue.async { [self] in
|
|
@@ -100,13 +107,20 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
100
107
|
}
|
|
101
108
|
audioManagerActivated = false
|
|
102
109
|
}
|
|
110
|
+
// Disable wake lock and proximity when call manager stops so the device can sleep again
|
|
111
|
+
DispatchQueue.main.async {
|
|
112
|
+
self.setProximityMonitoringEnabled(false)
|
|
113
|
+
self.unregisterAudioRouteObserver()
|
|
114
|
+
UIApplication.shared.isIdleTimerDisabled = false
|
|
115
|
+
self.log("Wake lock disabled (idle timer enabled)")
|
|
116
|
+
}
|
|
103
117
|
}
|
|
104
|
-
|
|
118
|
+
|
|
105
119
|
private func configureAudioSession() {
|
|
106
120
|
let intendedCategory: AVAudioSession.Category!
|
|
107
121
|
let intendedMode: AVAudioSession.Mode!
|
|
108
122
|
let intendedOptions: AVAudioSession.CategoryOptions!
|
|
109
|
-
|
|
123
|
+
|
|
110
124
|
if (callAudioRole == .listener) {
|
|
111
125
|
// enables high quality audio playback but disables microphone
|
|
112
126
|
intendedCategory = .playback
|
|
@@ -115,16 +129,16 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
115
129
|
} else {
|
|
116
130
|
intendedCategory = .playAndRecord
|
|
117
131
|
intendedMode = .voiceChat
|
|
118
|
-
|
|
132
|
+
|
|
119
133
|
if (defaultAudioDevice == .speaker) {
|
|
120
134
|
// defaultToSpeaker will route to speaker if nothing else is connected
|
|
121
|
-
intendedOptions = [.
|
|
135
|
+
intendedOptions = [.allowBluetoothHFP, .defaultToSpeaker]
|
|
122
136
|
} else {
|
|
123
137
|
// having no defaultToSpeaker makes sure audio goes to earpiece if nothing is connected
|
|
124
|
-
intendedOptions = [.
|
|
138
|
+
intendedOptions = [.allowBluetoothHFP]
|
|
125
139
|
}
|
|
126
140
|
}
|
|
127
|
-
|
|
141
|
+
|
|
128
142
|
// START: set the config that webrtc must use when it takes control
|
|
129
143
|
let rtcConfig = RTCAudioSessionConfiguration.webRTC()
|
|
130
144
|
rtcConfig.category = intendedCategory.rawValue
|
|
@@ -132,14 +146,14 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
132
146
|
rtcConfig.categoryOptions = intendedOptions
|
|
133
147
|
RTCAudioSessionConfiguration.setWebRTC(rtcConfig)
|
|
134
148
|
// END
|
|
135
|
-
|
|
149
|
+
|
|
136
150
|
// START: compare current audio session with intended, and update if different
|
|
137
151
|
let session = RTCAudioSession.sharedInstance()
|
|
138
152
|
let currentCategory = session.category
|
|
139
153
|
let currentMode = session.mode
|
|
140
154
|
let currentOptions = session.categoryOptions
|
|
141
155
|
let currentIsActive = session.isActive
|
|
142
|
-
|
|
156
|
+
|
|
143
157
|
if currentCategory != intendedCategory.rawValue || currentMode != intendedMode.rawValue || currentOptions != intendedOptions || !currentIsActive {
|
|
144
158
|
session.lockForConfiguration()
|
|
145
159
|
do {
|
|
@@ -162,7 +176,7 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
162
176
|
}
|
|
163
177
|
// END
|
|
164
178
|
}
|
|
165
|
-
|
|
179
|
+
|
|
166
180
|
@objc(showAudioRoutePicker)
|
|
167
181
|
public func showAudioRoutePicker() {
|
|
168
182
|
guard #available(iOS 11.0, tvOS 11.0, macOS 10.15, *) else {
|
|
@@ -177,7 +191,7 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
177
191
|
.sendActions(for: .touchUpInside)
|
|
178
192
|
}
|
|
179
193
|
}
|
|
180
|
-
|
|
194
|
+
|
|
181
195
|
@objc(setForceSpeakerphoneOn:)
|
|
182
196
|
func setForceSpeakerphoneOn(enable: Bool) {
|
|
183
197
|
let session = AVAudioSession.sharedInstance()
|
|
@@ -188,12 +202,12 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
188
202
|
log("Error setting speakerphone: \(error)")
|
|
189
203
|
}
|
|
190
204
|
}
|
|
191
|
-
|
|
205
|
+
|
|
192
206
|
@objc(setMicrophoneMute:)
|
|
193
207
|
func setMicrophoneMute(enable: Bool) {
|
|
194
208
|
log("iOS does not support setMicrophoneMute()")
|
|
195
209
|
}
|
|
196
|
-
|
|
210
|
+
|
|
197
211
|
@objc
|
|
198
212
|
func logAudioState() {
|
|
199
213
|
let session = AVAudioSession.sharedInstance()
|
|
@@ -209,17 +223,17 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
209
223
|
"""
|
|
210
224
|
log(logString)
|
|
211
225
|
}
|
|
212
|
-
|
|
226
|
+
|
|
213
227
|
@objc(muteAudioOutput)
|
|
214
228
|
func muteAudioOutput() {
|
|
215
229
|
DispatchQueue.main.async { [self] in
|
|
216
230
|
let volumeView = MPVolumeView()
|
|
217
|
-
|
|
231
|
+
|
|
218
232
|
// Add to a temporary view hierarchy to make it functional
|
|
219
233
|
if let window = getCurrentWindow() {
|
|
220
234
|
volumeView.frame = CGRect(x: -1000, y: -1000, width: 1, height: 1)
|
|
221
235
|
window.addSubview(volumeView)
|
|
222
|
-
|
|
236
|
+
|
|
223
237
|
// Give it a moment to initialize
|
|
224
238
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
|
225
239
|
if let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider {
|
|
@@ -230,24 +244,24 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
230
244
|
} else {
|
|
231
245
|
self.log("Could not find volume slider")
|
|
232
246
|
}
|
|
233
|
-
|
|
247
|
+
|
|
234
248
|
// Remove from view hierarchy after use
|
|
235
249
|
volumeView.removeFromSuperview()
|
|
236
250
|
}
|
|
237
251
|
}
|
|
238
252
|
}
|
|
239
253
|
}
|
|
240
|
-
|
|
254
|
+
|
|
241
255
|
@objc(unmuteAudioOutput)
|
|
242
256
|
func unmuteAudioOutput() {
|
|
243
257
|
DispatchQueue.main.async { [self] in
|
|
244
258
|
let volumeView = MPVolumeView()
|
|
245
|
-
|
|
259
|
+
|
|
246
260
|
// Add to a temporary view hierarchy to make it functional
|
|
247
261
|
if let window = getCurrentWindow() {
|
|
248
262
|
volumeView.frame = CGRect(x: -1000, y: -1000, width: 1, height: 1)
|
|
249
263
|
window.addSubview(volumeView)
|
|
250
|
-
|
|
264
|
+
|
|
251
265
|
// Give it a moment to initialize
|
|
252
266
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
|
253
267
|
if let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider {
|
|
@@ -258,31 +272,84 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
258
272
|
} else {
|
|
259
273
|
self.log("Could not find volume slider")
|
|
260
274
|
}
|
|
261
|
-
|
|
275
|
+
|
|
262
276
|
// Remove from view hierarchy after use
|
|
263
277
|
volumeView.removeFromSuperview()
|
|
264
278
|
}
|
|
265
279
|
}
|
|
266
280
|
}
|
|
267
281
|
}
|
|
268
|
-
|
|
282
|
+
|
|
283
|
+
// MARK: - Proximity Handling
|
|
284
|
+
private func registerAudioRouteObserver() {
|
|
285
|
+
if hasRegisteredRouteObserver { return }
|
|
286
|
+
NotificationCenter.default.addObserver(
|
|
287
|
+
self,
|
|
288
|
+
selector: #selector(handleAudioRouteChange(_:)),
|
|
289
|
+
name: AVAudioSession.routeChangeNotification,
|
|
290
|
+
object: nil
|
|
291
|
+
)
|
|
292
|
+
hasRegisteredRouteObserver = true
|
|
293
|
+
log("Registered AVAudioSession.routeChangeNotification observer")
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private func unregisterAudioRouteObserver() {
|
|
297
|
+
if !hasRegisteredRouteObserver { return }
|
|
298
|
+
NotificationCenter.default.removeObserver(self, name: AVAudioSession.routeChangeNotification, object: nil)
|
|
299
|
+
hasRegisteredRouteObserver = false
|
|
300
|
+
log("Unregistered AVAudioSession.routeChangeNotification observer")
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
@objc private func handleAudioRouteChange(_ notification: Notification) {
|
|
304
|
+
// Route changes can arrive on arbitrary queues; ensure UI-safe work on main
|
|
305
|
+
DispatchQueue.main.async { [weak self] in
|
|
306
|
+
self?.updateProximityMonitoring()
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private func updateProximityMonitoring() {
|
|
311
|
+
// Proximity is only meaningful while a call is active
|
|
312
|
+
guard audioManagerActivated else {
|
|
313
|
+
setProximityMonitoringEnabled(false)
|
|
314
|
+
return
|
|
315
|
+
}
|
|
316
|
+
let session = AVAudioSession.sharedInstance()
|
|
317
|
+
let port = session.currentRoute.outputs.first?.portType
|
|
318
|
+
let isEarpiece = (port == .builtInReceiver)
|
|
319
|
+
setProximityMonitoringEnabled(isEarpiece)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
private func setProximityMonitoringEnabled(_ enabled: Bool) {
|
|
323
|
+
// Always toggle on the main thread
|
|
324
|
+
if Thread.isMainThread {
|
|
325
|
+
if UIDevice.current.isProximityMonitoringEnabled != enabled {
|
|
326
|
+
UIDevice.current.isProximityMonitoringEnabled = enabled
|
|
327
|
+
log("Proximity monitoring \(enabled ? "ENABLED" : "DISABLED")")
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
DispatchQueue.main.async { [weak self] in
|
|
331
|
+
self?.setProximityMonitoringEnabled(enabled)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
269
336
|
// MARK: - RCTEventEmitter
|
|
270
|
-
|
|
337
|
+
|
|
271
338
|
override func supportedEvents() -> [String]! {
|
|
272
339
|
// TODO: list events that can be sent to JS
|
|
273
340
|
return []
|
|
274
341
|
}
|
|
275
|
-
|
|
342
|
+
|
|
276
343
|
@objc
|
|
277
344
|
override func addListener(_ eventName: String!) {
|
|
278
345
|
super.addListener(eventName)
|
|
279
346
|
}
|
|
280
|
-
|
|
347
|
+
|
|
281
348
|
@objc
|
|
282
349
|
override func removeListeners(_ count: Double) {
|
|
283
350
|
super.removeListeners(count)
|
|
284
351
|
}
|
|
285
|
-
|
|
352
|
+
|
|
286
353
|
// MARK: - Helper Methods
|
|
287
354
|
private func getCurrentWindow() -> UIWindow? {
|
|
288
355
|
if #available(iOS 13.0, *) {
|
|
@@ -294,10 +361,10 @@ class StreamInCallManager: RCTEventEmitter {
|
|
|
294
361
|
return UIApplication.shared.keyWindow
|
|
295
362
|
}
|
|
296
363
|
}
|
|
297
|
-
|
|
364
|
+
|
|
298
365
|
// MARK: - Logging Helper
|
|
299
366
|
private func log(_ message: String) {
|
|
300
367
|
NSLog("InCallManager: %@", message)
|
|
301
368
|
}
|
|
302
|
-
|
|
369
|
+
|
|
303
370
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-react-native-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.0",
|
|
4
4
|
"description": "Stream Video SDK for React Native",
|
|
5
5
|
"author": "https://getstream.io",
|
|
6
6
|
"homepage": "https://getstream.io/video/docs/react-native/",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"!**/.*"
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@stream-io/video-client": "1.
|
|
49
|
-
"@stream-io/video-react-bindings": "1.10.
|
|
48
|
+
"@stream-io/video-client": "1.35.1",
|
|
49
|
+
"@stream-io/video-react-bindings": "1.10.3",
|
|
50
50
|
"intl-pluralrules": "2.0.1",
|
|
51
51
|
"lodash.merge": "^4.6.2",
|
|
52
52
|
"react-native-url-polyfill": "^3.0.0",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
1
|
+
import React, { PropsWithChildren, useEffect, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
ViewerLivestream as DefaultViewerLivestream,
|
|
4
4
|
type ViewerLivestreamProps,
|
|
@@ -27,7 +27,7 @@ export type LivestreamPlayerProps = {
|
|
|
27
27
|
*
|
|
28
28
|
* `"asap"` behavior means joining the call as soon as it is possible
|
|
29
29
|
* (either the `join_ahead_time_seconds` setting allows it, or the user
|
|
30
|
-
* has
|
|
30
|
+
* has the capability to join backstage).
|
|
31
31
|
*
|
|
32
32
|
* `"live"` behavior means joining the call when it goes live.
|
|
33
33
|
*
|
|
@@ -41,7 +41,8 @@ export const LivestreamPlayer = ({
|
|
|
41
41
|
callId,
|
|
42
42
|
ViewerLivestream = DefaultViewerLivestream,
|
|
43
43
|
joinBehavior = 'asap',
|
|
44
|
-
|
|
44
|
+
children,
|
|
45
|
+
}: PropsWithChildren<LivestreamPlayerProps>) => {
|
|
45
46
|
const client = useStreamVideoClient();
|
|
46
47
|
|
|
47
48
|
const [call, setCall] = useState<Call>();
|
|
@@ -82,6 +83,7 @@ export const LivestreamPlayer = ({
|
|
|
82
83
|
return (
|
|
83
84
|
<StreamCall call={call}>
|
|
84
85
|
<ViewerLivestream joinBehavior={joinBehavior} />
|
|
86
|
+
{children}
|
|
85
87
|
</StreamCall>
|
|
86
88
|
);
|
|
87
89
|
};
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
View,
|
|
7
7
|
type ViewStyle,
|
|
8
8
|
} from 'react-native';
|
|
9
|
-
import {
|
|
9
|
+
import { Z_INDEX } from '../../../constants';
|
|
10
10
|
import { ComponentTestIds } from '../../../constants/TestIds';
|
|
11
11
|
import { VideoSlash } from '../../../icons';
|
|
12
12
|
import FloatingView from './FloatingView';
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
type ParticipantViewProps,
|
|
22
22
|
} from '../ParticipantView';
|
|
23
23
|
import { useTheme } from '../../../contexts/ThemeContext';
|
|
24
|
+
import { useFloatingVideoDimensions } from './useFloatingVideoDimensions';
|
|
24
25
|
import { type StreamVideoParticipant } from '@stream-io/video-client';
|
|
25
26
|
|
|
26
27
|
export type FloatingParticipantViewAlignment =
|
|
@@ -104,7 +105,11 @@ export const FloatingParticipantView = ({
|
|
|
104
105
|
objectFit,
|
|
105
106
|
}: FloatingParticipantViewProps) => {
|
|
106
107
|
const {
|
|
107
|
-
theme: {
|
|
108
|
+
theme: {
|
|
109
|
+
colors,
|
|
110
|
+
floatingParticipantsView,
|
|
111
|
+
variants: { spacingSizes },
|
|
112
|
+
},
|
|
108
113
|
} = useTheme();
|
|
109
114
|
|
|
110
115
|
const floatingAlignmentMap: Record<
|
|
@@ -122,6 +127,12 @@ export const FloatingParticipantView = ({
|
|
|
122
127
|
height: number;
|
|
123
128
|
}>();
|
|
124
129
|
|
|
130
|
+
const floatingVideoDimensions = useFloatingVideoDimensions(
|
|
131
|
+
containerDimensions,
|
|
132
|
+
participant,
|
|
133
|
+
'videoTrack',
|
|
134
|
+
);
|
|
135
|
+
|
|
125
136
|
const participantViewProps: ParticipantViewComponentProps = {
|
|
126
137
|
ParticipantLabel: null,
|
|
127
138
|
ParticipantNetworkQualityIndicator,
|
|
@@ -158,7 +169,7 @@ export const FloatingParticipantView = ({
|
|
|
158
169
|
});
|
|
159
170
|
}}
|
|
160
171
|
>
|
|
161
|
-
{containerDimensions && (
|
|
172
|
+
{containerDimensions && floatingVideoDimensions && (
|
|
162
173
|
<FloatingView
|
|
163
174
|
containerHeight={containerDimensions.height}
|
|
164
175
|
containerWidth={containerDimensions.width}
|
|
@@ -171,6 +182,12 @@ export const FloatingParticipantView = ({
|
|
|
171
182
|
trackType="videoTrack"
|
|
172
183
|
style={[
|
|
173
184
|
styles.participantViewContainer,
|
|
185
|
+
{
|
|
186
|
+
width: floatingVideoDimensions.width,
|
|
187
|
+
height: floatingVideoDimensions.height,
|
|
188
|
+
borderRadius: floatingVideoDimensions.width * 0.1,
|
|
189
|
+
marginHorizontal: spacingSizes.md,
|
|
190
|
+
},
|
|
174
191
|
participantViewStyle,
|
|
175
192
|
{ shadowColor: colors.sheetPrimary },
|
|
176
193
|
floatingParticipantsView.participantViewContainer,
|
|
@@ -197,9 +214,6 @@ const styles = StyleSheet.create({
|
|
|
197
214
|
flex: 1,
|
|
198
215
|
},
|
|
199
216
|
participantViewContainer: {
|
|
200
|
-
height: FLOATING_VIDEO_VIEW_STYLE.height,
|
|
201
|
-
width: FLOATING_VIDEO_VIEW_STYLE.width,
|
|
202
|
-
borderRadius: FLOATING_VIDEO_VIEW_STYLE.borderRadius,
|
|
203
217
|
shadowOffset: {
|
|
204
218
|
width: 0,
|
|
205
219
|
height: 2,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StreamVideoParticipant,
|
|
3
|
+
VideoTrackType,
|
|
4
|
+
} from '@stream-io/video-client';
|
|
5
|
+
import { useTrackDimensions } from '../../../hooks/useTrackDimensions';
|
|
6
|
+
|
|
7
|
+
export const useFloatingVideoDimensions = (
|
|
8
|
+
containerDimensions:
|
|
9
|
+
| {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}
|
|
13
|
+
| undefined,
|
|
14
|
+
participant: StreamVideoParticipant | undefined,
|
|
15
|
+
trackType: VideoTrackType,
|
|
16
|
+
) => {
|
|
17
|
+
const containerWidth = containerDimensions?.width ?? 0;
|
|
18
|
+
const { width, height } = useTrackDimensions(participant, trackType);
|
|
19
|
+
|
|
20
|
+
if (width === 0 || height === 0 || containerWidth === 0) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const aspectRatio = width / height;
|
|
25
|
+
|
|
26
|
+
// based on Android AOSP PiP mode default dimensions algorithm
|
|
27
|
+
// 23% of the container width
|
|
28
|
+
const floatingVideoWidth = containerWidth * 0.23;
|
|
29
|
+
// the height is calculated based on the aspect ratio
|
|
30
|
+
const floatingVideoHeight = floatingVideoWidth / aspectRatio;
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
width: floatingVideoWidth,
|
|
34
|
+
height: floatingVideoHeight,
|
|
35
|
+
};
|
|
36
|
+
};
|