Skip to content

Commit f83753d

Browse files
committed
feat: adaptive floating video dimensions
1 parent 2399b86 commit f83753d

File tree

5 files changed

+58
-25
lines changed

5 files changed

+58
-25
lines changed

packages/react-native-sdk/src/components/Participant/FloatingParticipantView/index.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
View,
77
type ViewStyle,
88
} from 'react-native';
9-
import { FLOATING_VIDEO_VIEW_STYLE, Z_INDEX } from '../../../constants';
9+
import { Z_INDEX } from '../../../constants';
1010
import { ComponentTestIds } from '../../../constants/TestIds';
1111
import { VideoSlash } from '../../../icons';
1212
import FloatingView from './FloatingView';
@@ -21,6 +21,7 @@ import {
2121
type ParticipantViewProps,
2222
} from '../ParticipantView';
2323
import { useTheme } from '../../../contexts/ThemeContext';
24+
import { useFloatingVideoDimensions } from './useFloatingVideoDimensions';
2425
import { type StreamVideoParticipant } from '@stream-io/video-client';
2526

2627
export type FloatingParticipantViewAlignment =
@@ -104,7 +105,11 @@ export const FloatingParticipantView = ({
104105
objectFit,
105106
}: FloatingParticipantViewProps) => {
106107
const {
107-
theme: { colors, floatingParticipantsView },
108+
theme: {
109+
colors,
110+
floatingParticipantsView,
111+
variants: { spacingSizes },
112+
},
108113
} = useTheme();
109114

110115
const floatingAlignmentMap: Record<
@@ -122,6 +127,12 @@ export const FloatingParticipantView = ({
122127
height: number;
123128
}>();
124129

130+
const floatingVideoDimensions = useFloatingVideoDimensions(
131+
containerDimensions,
132+
participant,
133+
'videoTrack',
134+
);
135+
125136
const participantViewProps: ParticipantViewComponentProps = {
126137
ParticipantLabel: null,
127138
ParticipantNetworkQualityIndicator,
@@ -158,7 +169,7 @@ export const FloatingParticipantView = ({
158169
});
159170
}}
160171
>
161-
{containerDimensions && (
172+
{containerDimensions && floatingVideoDimensions && (
162173
<FloatingView
163174
containerHeight={containerDimensions.height}
164175
containerWidth={containerDimensions.width}
@@ -171,6 +182,12 @@ export const FloatingParticipantView = ({
171182
trackType="videoTrack"
172183
style={[
173184
styles.participantViewContainer,
185+
{
186+
width: floatingVideoDimensions.width,
187+
height: floatingVideoDimensions.height,
188+
borderRadius: floatingVideoDimensions.width * 0.1,
189+
marginHorizontal: spacingSizes.md,
190+
},
174191
participantViewStyle,
175192
{ shadowColor: colors.sheetPrimary },
176193
floatingParticipantsView.participantViewContainer,
@@ -197,9 +214,6 @@ const styles = StyleSheet.create({
197214
flex: 1,
198215
},
199216
participantViewContainer: {
200-
height: FLOATING_VIDEO_VIEW_STYLE.height,
201-
width: FLOATING_VIDEO_VIEW_STYLE.width,
202-
borderRadius: FLOATING_VIDEO_VIEW_STYLE.borderRadius,
203217
shadowOffset: {
204218
width: 0,
205219
height: 2,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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) {
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+
};

packages/react-native-sdk/src/constants/index.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import { type StreamReactionType } from '../components';
22

3-
export const FLOATING_VIDEO_VIEW_STYLE = {
4-
height: 140,
5-
width: 80,
6-
borderRadius: 10,
7-
};
8-
93
export const defaultEmojiReactions: StreamReactionType[] = [
104
{
115
type: 'reaction',

packages/react-native-sdk/src/hooks/useTrackDimensions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ import { NativeEventEmitter, NativeModules } from 'react-native';
1111
* `tracktype` should be 'videoTrack' for video track and 'screenShareTrack' for screen share track.
1212
*/
1313
export function useTrackDimensions(
14-
participant: StreamVideoParticipant,
14+
participant: StreamVideoParticipant | undefined,
1515
trackType: VideoTrackType,
1616
) {
17-
const { videoStream, screenShareStream } = participant;
17+
const { videoStream, screenShareStream } = participant || {};
1818
const stream =
1919
trackType === 'screenShareTrack' ? screenShareStream : videoStream;
2020
const [track] = stream?.getVideoTracks() ?? [];

sample-apps/react-native/dogfood/src/theme.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@ export const useCustomTheme = (mode: ThemeMode): DeepPartial<Theme> => {
5252
container: { paddingTop: 0, paddingBottom: 0, flexDirection: 'column' },
5353
};
5454

55-
const { height, width } = Dimensions.get('window');
56-
const floatingParticipantsView: DeepPartial<
57-
Theme['floatingParticipantsView']
58-
> = {
59-
participantViewContainer: {
60-
height: height * 0.2,
61-
width: width * 0.25,
62-
},
63-
};
64-
6555
const lightThemeColors: DeepPartial<Theme['colors']> = {
6656
buttonPrimary: '#3399ff',
6757
buttonSecondary: '#eff0f1',
@@ -82,7 +72,6 @@ export const useCustomTheme = (mode: ThemeMode): DeepPartial<Theme> => {
8272
const baseTheme: DeepPartial<Theme> = {
8373
variants,
8474
callContent,
85-
floatingParticipantsView,
8675
};
8776

8877
if (mode === 'light') {

0 commit comments

Comments
 (0)