Skip to content

Commit c8fba6d

Browse files
committed
feat(design-v2): new call control buttons
1 parent e7b86b6 commit c8fba6d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+562
-447
lines changed

packages/react-native-sdk/__tests__/components/ParticipantView.test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ describe('ParticipantView', () => {
4343
expect(
4444
await screen.findByTestId(ComponentTestIds.PARTICIPANT_AVATAR)
4545
).toBeOnTheScreen();
46-
expect(screen.getByTestId(IconTestIds.MUTED_VIDEO)).toBeOnTheScreen();
4746
expect(screen.getByText(testParticipant.name)).toBeOnTheScreen();
4847
// reaction is visible and then disappears after 5500 ms
4948
expect(screen.getByText('🎉')).toBeOnTheScreen();

packages/react-native-sdk/docusaurus/docs/reactnative/04-ui-components/call/call-content.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import CallContentSpotlight from '../../assets/04-ui-components/call/call-conten
1010

1111
import CallTopView from '../../common-content/ui-components/call/call-content/call-top-view.mdx';
1212
import CallControls from '../../common-content/ui-components/call/call-content/call-controls.mdx';
13-
import ParticipantsInfoBadge from '../../common-content/ui-components/call/call-content/participants-info-badge.mdx';
1413
import Landscape from '../../common-content/ui-components/call/call-content/landscape.mdx';
1514
import OnBackPressed from '../../common-content/ui-components/call/call-content/on-back-pressed.mdx';
1615
import OnParticipantInfoPress from '../../common-content/ui-components/call/call-content/on-participant-info-press.mdx';

packages/react-native-sdk/docusaurus/docs/reactnative/04-ui-components/call/call-top-view.mdx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@ Style to override the container of the `CallTopView`.
6060
| ---------------------------------------------------------- |
6161
| [ViewStyle](https://reactnative.dev/docs/view-style-props) |
6262

63-
### `ParticipantsInfoBadge`
64-
65-
<ParticipantsInfoBadge />
66-
6763
## Customization
6864

6965
You can create your own custom `CallTopView` using the [Call Top View UI Cookbook guide](../../../ui-cookbook/replacing-call-top-view/).

packages/react-native-sdk/docusaurus/docs/reactnative/common-content/ui-components/call/call-content/participants-info-badge.mdx

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/react-native-sdk/src/components/Call/CallContent/CallContent.tsx

Lines changed: 66 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React, { useEffect, useState } from 'react';
2-
import { StyleSheet, View, ViewStyle } from 'react-native';
1+
import React, { useEffect, useMemo, useState } from 'react';
2+
import { SafeAreaView, StyleSheet, View, ViewStyle } from 'react-native';
33
import InCallManager from 'react-native-incall-manager';
44

55
import {
@@ -71,10 +71,7 @@ export type CallContentProps = Pick<
7171
HangUpCallButtonProps,
7272
'onHangupCallHandler'
7373
> &
74-
Pick<
75-
CallTopViewProps,
76-
'onBackPressed' | 'onParticipantInfoPress' | 'ParticipantsInfoBadge'
77-
> &
74+
Pick<CallTopViewProps, 'onBackPressed'> &
7875
CallContentComponentProps & {
7976
/**
8077
* This switches the participant's layout between the grid and the spotlight mode.
@@ -101,7 +98,6 @@ export type CallContentProps = Pick<
10198

10299
export const CallContent = ({
103100
onBackPressed,
104-
onParticipantInfoPress,
105101
onHangupCallHandler,
106102
CallParticipantsList,
107103
CallTopView = DefaultCallTopView,
@@ -113,7 +109,6 @@ export const CallContent = ({
113109
ParticipantReaction,
114110
ParticipantVideoFallback,
115111
ParticipantView,
116-
ParticipantsInfoBadge,
117112
VideoRenderer,
118113
layout = 'grid',
119114
landscape = false,
@@ -146,6 +141,7 @@ export const CallContent = ({
146141
const isInPiPMode = useIsInPiPMode(disablePictureInPicture);
147142
const hasScreenShare = useHasOngoingScreenShare();
148143
const showSpotlightLayout = hasScreenShare || layout === 'spotlight';
144+
const styles = useStyles();
149145

150146
const showFloatingView =
151147
!showSpotlightLayout &&
@@ -201,67 +197,82 @@ export const CallContent = ({
201197
supportedReactions,
202198
};
203199

204-
const landscapeStyles: ViewStyle = {
205-
flexDirection: landscape ? 'row' : 'column',
206-
};
207-
208200
return (
209201
<>
210202
{!disablePictureInPicture && (
211203
<RTCViewPipIOS
212204
includeLocalParticipantVideo={iOSPiPIncludeLocalParticipantVideo}
213205
/>
214206
)}
215-
<View style={[styles.container, landscapeStyles, callContent.container]}>
216-
<View style={[styles.container, callContent.callParticipantsContainer]}>
207+
<View style={styles.mainContainer}>
208+
<View style={styles.unsafeArea} />
209+
<SafeAreaView style={[styles.safeArea, callContent.container]}>
217210
<View
218-
style={[styles.view, callContent.topContainer]}
219-
// "box-none" disallows the container view to be not take up touches
220-
// and allows only the top and floating view (its child views) to take up the touches
221-
pointerEvents="box-none"
211+
style={[styles.callContent, callContent.callParticipantsContainer]}
222212
>
223-
{!isInPiPMode && CallTopView && (
224-
<CallTopView
225-
onBackPressed={onBackPressed}
226-
onParticipantInfoPress={onParticipantInfoPress}
227-
ParticipantsInfoBadge={ParticipantsInfoBadge}
228-
/>
229-
)}
230-
{showFloatingView && FloatingParticipantView && (
231-
<FloatingParticipantView
232-
participant={
233-
isRemoteParticipantInFloatingView
234-
? remoteParticipants[0]
235-
: localParticipant
236-
}
237-
onPressHandler={handleFloatingViewParticipantSwitch}
238-
supportedReactions={supportedReactions}
239-
{...participantViewProps}
240-
/>
213+
<View
214+
style={[styles.view, callContent.topContainer]}
215+
// "box-none" disallows the container view to be not take up touches
216+
// and allows only the top and floating view (its child views) to take up the touches
217+
pointerEvents="box-none"
218+
>
219+
{!isInPiPMode && CallTopView && (
220+
<CallTopView onBackPressed={onBackPressed} />
221+
)}
222+
{showFloatingView && FloatingParticipantView && (
223+
<FloatingParticipantView
224+
participant={
225+
isRemoteParticipantInFloatingView
226+
? remoteParticipants[0]
227+
: localParticipant
228+
}
229+
onPressHandler={handleFloatingViewParticipantSwitch}
230+
supportedReactions={supportedReactions}
231+
{...participantViewProps}
232+
/>
233+
)}
234+
</View>
235+
{showSpotlightLayout ? (
236+
<CallParticipantsSpotlight {...callParticipantsSpotlightProps} />
237+
) : (
238+
<CallParticipantsGrid {...callParticipantsGridProps} />
241239
)}
242240
</View>
243-
{showSpotlightLayout ? (
244-
<CallParticipantsSpotlight {...callParticipantsSpotlightProps} />
245-
) : (
246-
<CallParticipantsGrid {...callParticipantsGridProps} />
247-
)}
248-
</View>
249241

250-
{!isInPiPMode && CallControls && (
251-
<CallControls
252-
onHangupCallHandler={onHangupCallHandler}
253-
landscape={landscape}
254-
/>
255-
)}
242+
{!isInPiPMode && CallControls && (
243+
<CallControls
244+
onHangupCallHandler={onHangupCallHandler}
245+
landscape={landscape}
246+
/>
247+
)}
248+
</SafeAreaView>
256249
</View>
257250
</>
258251
);
259252
};
260253

261-
const styles = StyleSheet.create({
262-
container: { flex: 1 },
263-
view: {
264-
...StyleSheet.absoluteFillObject,
265-
zIndex: Z_INDEX.IN_FRONT,
266-
},
267-
});
254+
const useStyles = () => {
255+
const { theme } = useTheme();
256+
return useMemo(
257+
() =>
258+
StyleSheet.create({
259+
mainContainer: { flex: 1 },
260+
callContent: { flex: 1 },
261+
safeArea: { flex: 1 },
262+
unsafeArea: {
263+
position: 'absolute',
264+
left: 0,
265+
right: 0,
266+
bottom: 0,
267+
// TODO: should be replaced with safeAreaInsets.bottom for all devices on ios and android
268+
height: 34,
269+
backgroundColor: theme.colors.sheetPrimary,
270+
},
271+
view: {
272+
...StyleSheet.absoluteFillObject,
273+
zIndex: Z_INDEX.IN_FRONT,
274+
},
275+
}),
276+
[theme]
277+
);
278+
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import React, { useMemo } from 'react';
2+
import { StyleSheet, Text, View } from 'react-native';
3+
import { useTheme } from '../../../contexts/ThemeContext';
4+
import { ComponentTestIds } from '../../../constants/TestIds';
5+
import { Z_INDEX } from '../../../constants';
6+
7+
/**
8+
* A badge that displays a number.
9+
*
10+
* @prop {number} count - The number to display in the badge.
11+
*
12+
* @returns {ReactElement} A View with a Text that displays the count in the badge.
13+
*/
14+
export const BadgeCountIndicator = ({
15+
count,
16+
}: {
17+
count: number | undefined;
18+
}) => {
19+
const {
20+
theme: { colors, typefaces },
21+
} = useTheme();
22+
const styles = useStyles();
23+
24+
// Don't show badge if count is 0 or undefined
25+
if (!count) {
26+
return null;
27+
}
28+
29+
return (
30+
<View
31+
testID={ComponentTestIds.BADGE_COUNT_INDICATOR}
32+
style={[styles.badge, { backgroundColor: colors.iconAlertSuccess }]}
33+
>
34+
<Text
35+
style={[
36+
styles.badgeText,
37+
{ color: colors.sheetPrimary },
38+
typefaces.caption,
39+
]}
40+
>
41+
{count}
42+
</Text>
43+
</View>
44+
);
45+
};
46+
47+
const useStyles = () => {
48+
const { theme } = useTheme();
49+
return useMemo(
50+
() =>
51+
StyleSheet.create({
52+
badge: {
53+
position: 'absolute',
54+
justifyContent: 'center',
55+
borderRadius: theme.defaults.borderRadius,
56+
left: 13,
57+
bottom: 17,
58+
zIndex: Z_INDEX.IN_FRONT,
59+
height: theme.variants.roundButtonSizes.xs,
60+
width: theme.variants.roundButtonSizes.xs,
61+
},
62+
badgeText: {
63+
textAlign: 'center',
64+
},
65+
}),
66+
[theme]
67+
);
68+
};

packages/react-native-sdk/src/components/Call/CallControls/CallControlsButton.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,26 +57,29 @@ export const CallControlsButton = (
5757

5858
const {
5959
theme: {
60-
variants: { buttonSizes },
6160
colors,
61+
defaults,
62+
variants: { roundButtonSizes },
6263
callControlsButton: { container },
6364
},
6465
} = useTheme();
6566

6667
const pressableStyle: PressableProps['style'] = ({ pressed }) => [
6768
styles.container,
6869
{
69-
backgroundColor: disabled ? colors.disabled : colorProp || colors.base1,
70+
backgroundColor: disabled
71+
? colors.buttonPrimaryDisabled
72+
: colorProp || colors.buttonSecondaryDefault,
7073
opacity: pressed ? 0.2 : 1,
71-
height: size || buttonSizes.sm,
72-
width: size || buttonSizes.sm,
73-
borderRadius: (size || buttonSizes.sm) / 2,
74-
borderColor: colors.background1,
74+
height: size || roundButtonSizes.lg,
75+
width: size || roundButtonSizes.lg,
76+
borderRadius: defaults.borderRadius,
7577
},
7678
styleProp?.container ?? null,
7779
container,
7880
];
7981

82+
const childrenSize = (size || roundButtonSizes.lg) / 2 - 5;
8083
return (
8184
<Pressable
8285
disabled={disabled}
@@ -87,10 +90,7 @@ export const CallControlsButton = (
8790
>
8891
<View
8992
style={[
90-
{
91-
height: (size || buttonSizes.sm) / 2 - 5,
92-
width: (size || buttonSizes.sm) / 2 - 5,
93-
},
93+
{ height: childrenSize, width: childrenSize },
9494
styleProp?.svgContainer ?? null,
9595
]}
9696
>

0 commit comments

Comments
 (0)