agora-appbuilder-core 4.1.7 → 4.1.8-beta.2

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.
Files changed (34) hide show
  1. package/package.json +2 -2
  2. package/template/_package-lock.json +30671 -5376
  3. package/template/bridge/rtc/webNg/RtcEngine.ts +4 -4
  4. package/template/defaultConfig.js +2 -2
  5. package/template/esbuild.rsdk.go +1 -2
  6. package/template/package.json +0 -1
  7. package/template/src/AppWrapper.tsx +30 -35
  8. package/template/src/auth/AuthProvider.tsx +28 -35
  9. package/template/src/auth/IDPAuth.tsx +1 -14
  10. package/template/src/components/Controls.tsx +45 -15
  11. package/template/src/components/common/GenericModal.tsx +143 -0
  12. package/template/src/components/common/GenericPopup.tsx +152 -0
  13. package/template/src/components/common/data-table.tsx +385 -0
  14. package/template/src/components/controls/useControlPermissionMatrix.tsx +6 -7
  15. package/template/src/components/precall/usePreCall.tsx +1 -2
  16. package/template/src/components/room-info/useRoomInfo.tsx +1 -0
  17. package/template/src/components/stt-transcript/STTTranscriptTable.tsx +295 -0
  18. package/template/src/components/stt-transcript/ViewSTTTranscriptModal.tsx +44 -0
  19. package/template/src/components/stt-transcript/useFetchSTTTranscript.tsx +193 -0
  20. package/template/src/components/useUserPreference.tsx +0 -11
  21. package/template/src/language/default-labels/videoCallScreenLabels.ts +7 -0
  22. package/template/src/logger/AppBuilderLogger.tsx +1 -0
  23. package/template/src/pages/Create.tsx +2 -2
  24. package/template/src/pages/VideoCall.tsx +1 -6
  25. package/template/src/subComponents/LogoutButton.tsx +1 -11
  26. package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +83 -78
  27. package/template/src/utils/common.tsx +79 -1
  28. package/template/src/utils/useCreateRoom.ts +94 -112
  29. package/template/src/utils/useEndCall.ts +16 -3
  30. package/template/src/utils/useGetMeetingPhrase.ts +67 -76
  31. package/template/src/utils/useJoinRoom.ts +5 -3
  32. package/template/src/utils/useMutePSTN.ts +47 -45
  33. package/template/webpack.rsdk.config.js +1 -2
  34. package/template/src/components/GraphQLProvider.tsx +0 -122
@@ -0,0 +1,152 @@
1
+ import React, {ReactNode, SetStateAction} from 'react';
2
+ import {StyleSheet, Text, View} from 'react-native';
3
+ import Spacer from '../../atoms/Spacer';
4
+ import Popup from '../../atoms/Popup';
5
+ import TertiaryButton from '../../atoms/TertiaryButton';
6
+ import PrimaryButton from '../../atoms/PrimaryButton';
7
+ import ThemeConfig from '../../theme';
8
+ import {useIsDesktop} from '../../utils/common';
9
+
10
+ export type ModalVariant = 'info' | 'warning' | 'error' | 'success';
11
+
12
+ export interface ConfirmationModalProps {
13
+ visible: boolean;
14
+ setVisible: React.Dispatch<SetStateAction<boolean>>;
15
+ title: string;
16
+ subTitle?: string;
17
+ message?: string;
18
+ variant?: ModalVariant;
19
+ confirmLabel?: string;
20
+ cancelLabel?: string;
21
+ onConfirm: () => void;
22
+ onCancel?: () => void;
23
+ footer?: ReactNode;
24
+ }
25
+
26
+ const VARIANT_COLOR: Record<ModalVariant, string> = {
27
+ info: $config.SEMANTIC_NEUTRAL,
28
+ warning: $config.SEMANTIC_WARNING,
29
+ error: $config.SEMANTIC_ERROR,
30
+ success: $config.SEMANTIC_SUCCESS,
31
+ };
32
+
33
+ const GenericPopup: React.FC<ConfirmationModalProps> = ({
34
+ visible,
35
+ setVisible,
36
+ title,
37
+ subTitle = '',
38
+ message,
39
+ variant = 'info',
40
+ confirmLabel = 'OK',
41
+ cancelLabel = 'Cancel',
42
+ onConfirm,
43
+ onCancel,
44
+ footer,
45
+ }) => {
46
+ const isDesktop = useIsDesktop()('popup');
47
+ const color = VARIANT_COLOR[variant];
48
+
49
+ const handleCancel = () => {
50
+ setVisible(false);
51
+ onCancel && onCancel();
52
+ };
53
+ const handleConfirm = () => {
54
+ setVisible(false);
55
+ onConfirm();
56
+ };
57
+
58
+ return (
59
+ <Popup
60
+ modalVisible={visible}
61
+ setModalVisible={setVisible}
62
+ showCloseIcon={false}
63
+ contentContainerStyle={styles.contentContainer}>
64
+ <Text style={[styles.title, {color}]}>{title}</Text>
65
+ <Spacer size={18} />
66
+ {message ? <Text style={styles.message}>{message}</Text> : null}
67
+ {footer ? (
68
+ <>
69
+ <Spacer size={16} />
70
+ {footer}
71
+ </>
72
+ ) : null}
73
+ <Spacer size={32} />
74
+ <View style={isDesktop ? styles.row : styles.column}>
75
+ <View style={isDesktop && {flex: 1}}>
76
+ <TertiaryButton
77
+ containerStyle={styles.tertiary}
78
+ textStyle={styles.buttonText}
79
+ text={cancelLabel}
80
+ onPress={handleCancel}
81
+ />
82
+ </View>
83
+ <Spacer size={isDesktop ? 12 : 20} horizontal={isDesktop} />
84
+ <View style={isDesktop && {flex: 1}}>
85
+ <PrimaryButton
86
+ containerStyle={[styles.primary, {backgroundColor: color}]}
87
+ textStyle={styles.buttonText}
88
+ text={confirmLabel}
89
+ onPress={handleConfirm}
90
+ />
91
+ </View>
92
+ </View>
93
+ </Popup>
94
+ );
95
+ };
96
+
97
+ export default GenericPopup;
98
+
99
+ const styles = StyleSheet.create({
100
+ contentContainer: {
101
+ padding: 24,
102
+ maxWidth: 360,
103
+ minWidth: 360,
104
+ },
105
+ title: {
106
+ fontFamily: ThemeConfig.FontFamily.sansPro,
107
+ fontWeight: '600',
108
+ fontSize: 22,
109
+ },
110
+ subTitle: {
111
+ fontFamily: ThemeConfig.FontFamily.sansPro,
112
+ fontWeight: '400',
113
+ fontSize: 14,
114
+ color: $config.FONT_COLOR,
115
+ },
116
+ message: {
117
+ fontFamily: ThemeConfig.FontFamily.sansPro,
118
+ fontWeight: '400',
119
+ fontSize: 14,
120
+ color: $config.FONT_COLOR,
121
+ },
122
+ row: {
123
+ flex: 1,
124
+ flexDirection: 'row',
125
+ justifyContent: 'center',
126
+ alignItems: 'center',
127
+ },
128
+ column: {
129
+ flexDirection: 'column-reverse',
130
+ },
131
+ primary: {
132
+ minWidth: 'auto',
133
+ width: '100%',
134
+ borderRadius: ThemeConfig.BorderRadius.medium,
135
+ height: 48,
136
+ backgroundColor: $config.SEMANTIC_ERROR,
137
+ paddingVertical: 12,
138
+ paddingHorizontal: 12,
139
+ },
140
+ tertiary: {
141
+ width: '100%',
142
+ height: 48,
143
+ paddingVertical: 12,
144
+ paddingHorizontal: 12,
145
+ borderRadius: ThemeConfig.BorderRadius.medium,
146
+ },
147
+ buttonText: {
148
+ fontWeight: '600',
149
+ fontSize: 16,
150
+ lineHeight: 24,
151
+ },
152
+ });
@@ -0,0 +1,385 @@
1
+ import React from 'react';
2
+ import {
3
+ View,
4
+ StyleSheet,
5
+ ViewStyle,
6
+ TextStyle,
7
+ Text,
8
+ StyleProp,
9
+ ScrollView,
10
+ } from 'react-native';
11
+ import ThemeConfig from '../../theme';
12
+ import hexadecimalTransparency from '../../utils/hexadecimalTransparency';
13
+ import Pagination from '../../atoms/pagination/Pagination';
14
+
15
+ // Header
16
+ interface TableHeaderProps {
17
+ columns: string[];
18
+ containerStyle?: ViewStyle;
19
+ rowStyle?: ViewStyle;
20
+ cellStyle?: ViewStyle;
21
+ firstCellStyle?: ViewStyle;
22
+ textStyle?: TextStyle;
23
+ }
24
+
25
+ const TableHeader: React.FC<TableHeaderProps> = ({
26
+ columns,
27
+ containerStyle,
28
+ rowStyle,
29
+ cellStyle,
30
+ firstCellStyle,
31
+ textStyle,
32
+ }) => (
33
+ <View style={[style.thead, containerStyle]}>
34
+ <View style={[style.throw, rowStyle]}>
35
+ {columns.map((col, index) => (
36
+ <View
37
+ key={col}
38
+ style={[
39
+ style.th,
40
+ index === 0 && style.plzero,
41
+ cellStyle,
42
+ index === 0 && firstCellStyle,
43
+ ]}>
44
+ <Text style={[style.thText, textStyle]}>{col}</Text>
45
+ </View>
46
+ ))}
47
+ </View>
48
+ </View>
49
+ );
50
+
51
+ // Body
52
+
53
+ export type TableStatus = 'idle' | 'pending' | 'resolved' | 'rejected';
54
+
55
+ export interface TableBodyProps<T> {
56
+ status: TableStatus;
57
+ items: T[];
58
+ loadingComponent?: React.ReactNode;
59
+ emptyComponent?: React.ReactNode;
60
+ renderRow: (item: T, index: number) => React.ReactNode;
61
+ containerStyle?: StyleProp<ViewStyle>;
62
+ horizontalContainerStyle?: StyleProp<ViewStyle>;
63
+ bodyStyle?: StyleProp<ViewStyle>;
64
+ }
65
+
66
+ function TableBody<T>({
67
+ status,
68
+ items,
69
+ loadingComponent,
70
+ emptyComponent,
71
+ renderRow,
72
+ bodyStyle,
73
+ }: TableBodyProps<T>) {
74
+ const renderTableBodyContent = () => {
75
+ // Loading state
76
+ if (status === 'idle' || status === 'pending') {
77
+ return <>{loadingComponent || null}</>;
78
+ }
79
+ // Empty state
80
+ if (status === 'resolved' && items.length === 0) {
81
+ return <>{emptyComponent || null}</>;
82
+ }
83
+ // Data state
84
+ return items.map((item, index) => renderRow(item, index));
85
+ };
86
+
87
+ // Data state
88
+ return (
89
+ <ScrollView contentContainerStyle={[style.scrollgrow]}>
90
+ <ScrollView horizontal contentContainerStyle={[style.scrollgrow]}>
91
+ <View style={[style.tbody, bodyStyle]}>{renderTableBodyContent()}</View>
92
+ </ScrollView>
93
+ </ScrollView>
94
+ );
95
+ }
96
+
97
+ // Footer
98
+ interface TableFooterProps {
99
+ currentPage: number;
100
+ onPageChange: (page: number) => void;
101
+ pagination?: Partial<{
102
+ total: number;
103
+ limit: number;
104
+ page: number;
105
+ }>;
106
+ containerStyle?: ViewStyle;
107
+ infoTextStyle?: TextStyle;
108
+ paginationWrapperStyle?: ViewStyle;
109
+ paginationContainerStyle?: ViewStyle;
110
+ }
111
+
112
+ const TableFooter: React.FC<TableFooterProps> = ({
113
+ currentPage,
114
+ onPageChange,
115
+ pagination,
116
+ containerStyle,
117
+ infoTextStyle,
118
+ paginationWrapperStyle,
119
+ paginationContainerStyle,
120
+ }) => {
121
+ if (!pagination || pagination.total === 0) {
122
+ return (
123
+ <View style={[style.mfooter, containerStyle]}>
124
+ <Text style={infoTextStyle}> </Text>
125
+ </View>
126
+ );
127
+ }
128
+
129
+ const {limit = 10, total = 0} = pagination || {};
130
+ const maxShowing = Math.min(limit * currentPage, total);
131
+ const showing = total <= limit ? total : maxShowing;
132
+
133
+ return (
134
+ <View style={[style.mfooter, containerStyle]}>
135
+ <Text style={[style.mfooterTitle, infoTextStyle]}>
136
+ Showing {showing} of {total}
137
+ </Text>
138
+ <View style={[style.pushRight, paginationWrapperStyle]}>
139
+ <View style={[style.pagination, paginationContainerStyle]}>
140
+ <Pagination
141
+ currentPage={currentPage}
142
+ totalCount={total}
143
+ pageSize={limit}
144
+ onPageChange={onPageChange}
145
+ />
146
+ </View>
147
+ </View>
148
+ </View>
149
+ );
150
+ };
151
+
152
+ export {TableHeader, TableFooter, TableBody};
153
+
154
+ const style = StyleSheet.create({
155
+ scrollgrow: {
156
+ flexGrow: 1,
157
+ },
158
+ mContainer: {
159
+ display: 'flex',
160
+ flexDirection: 'column',
161
+ alignItems: 'flex-start',
162
+ flexShrink: 0,
163
+ // width: 620,
164
+ width: '100%',
165
+ maxWidth: 680,
166
+ minWidth: 340,
167
+ height: 620,
168
+ maxHeight: 620,
169
+ borderRadius: 4,
170
+ zIndex: 2,
171
+ },
172
+ mHeader: {
173
+ display: 'flex',
174
+ flexDirection: 'row',
175
+ width: '100%',
176
+ height: 60,
177
+ paddingHorizontal: 20,
178
+ paddingVertical: 12,
179
+ alignItems: 'center',
180
+ gap: 20,
181
+ flexShrink: 0,
182
+ borderWidth: 1,
183
+ borderColor: $config.CARD_LAYER_3_COLOR,
184
+ backgroundColor: $config.CARD_LAYER_1_COLOR,
185
+ },
186
+ mbody: {
187
+ width: '100%',
188
+ flex: 1,
189
+ },
190
+ mfooter: {
191
+ display: 'flex',
192
+ flexDirection: 'row',
193
+ width: '100%',
194
+ height: 60,
195
+ paddingVertical: 12,
196
+ paddingHorizontal: 16,
197
+ justifyContent: 'space-between',
198
+ alignItems: 'center',
199
+ flexShrink: 0,
200
+ borderTopWidth: 1,
201
+ borderTopColor: $config.CARD_LAYER_3_COLOR,
202
+ backgroundColor: $config.CARD_LAYER_2_COLOR,
203
+ },
204
+ ttable: {
205
+ flex: 1,
206
+ },
207
+ // Header styles start
208
+ thead: {
209
+ display: 'flex',
210
+ height: 40,
211
+ paddingHorizontal: 20,
212
+ alignItems: 'center',
213
+ flexShrink: 0,
214
+ backgroundColor: $config.CARD_LAYER_2_COLOR,
215
+ },
216
+ throw: {
217
+ flex: 1,
218
+ alignSelf: 'stretch',
219
+ flexDirection: 'row',
220
+ },
221
+ th: {
222
+ flex: 1,
223
+ alignSelf: 'stretch',
224
+ justifyContent: 'center',
225
+ paddingHorizontal: 12,
226
+ },
227
+ thText: {
228
+ color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.medium,
229
+ fontSize: ThemeConfig.FontSize.small,
230
+ fontFamily: ThemeConfig.FontFamily.sansPro,
231
+ lineHeight: 16,
232
+ },
233
+ // Header style ends
234
+ // Body style starts
235
+ tbody: {
236
+ backgroundColor: $config.CARD_LAYER_1_COLOR,
237
+ paddingHorizontal: 20,
238
+ flex: 1,
239
+ },
240
+ tbrow: {
241
+ display: 'flex',
242
+ alignSelf: 'stretch',
243
+ minHeight: 50,
244
+ flexDirection: 'row',
245
+ paddingBottom: 10,
246
+ paddingTop: 20,
247
+ },
248
+ td: {
249
+ flex: 1,
250
+ alignSelf: 'center',
251
+ justifyContent: 'center',
252
+ // height: 100,
253
+ gap: 10,
254
+ },
255
+ tpreview: {
256
+ width: '100%',
257
+ height: 76,
258
+ padding: 4,
259
+ backgroundColor: 'black',
260
+ border: '1px solid grey',
261
+ color: $config.FONT_COLOR,
262
+ },
263
+ ttime: {
264
+ color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.medium,
265
+ fontSize: ThemeConfig.FontSize.small,
266
+ fontFamily: ThemeConfig.FontFamily.sansPro,
267
+ lineHeight: 16,
268
+ },
269
+ tname: {
270
+ color: $config.VIDEO_AUDIO_TILE_AVATAR_COLOR,
271
+ fontSize: ThemeConfig.FontSize.small,
272
+ fontFamily: ThemeConfig.FontFamily.sansPro,
273
+ lineHeight: 16,
274
+ },
275
+ tactions: {
276
+ display: 'flex',
277
+ flexDirection: 'row',
278
+ },
279
+ tlink: {
280
+ color: $config.PRIMARY_ACTION_BRAND_COLOR,
281
+ fontSize: ThemeConfig.FontSize.tiny,
282
+ fontFamily: ThemeConfig.FontFamily.sansPro,
283
+ fontWeight: '600',
284
+ lineHeight: 12,
285
+ },
286
+ // footer start
287
+ mfooterTitle: {
288
+ color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.low,
289
+ fontSize: ThemeConfig.FontSize.small,
290
+ fontFamily: ThemeConfig.FontFamily.sansPro,
291
+ lineHeight: 16,
292
+ },
293
+ pagination: {
294
+ display: 'flex',
295
+ flexDirection: 'row',
296
+ alignItems: 'flex-start',
297
+ borderRadius: 4,
298
+ borderWidth: 1,
299
+ borderColor: $config.CARD_LAYER_4_COLOR,
300
+ backgroundColor: $config.CARD_LAYER_3_COLOR,
301
+ },
302
+ placeHolder: {
303
+ fontSize: ThemeConfig.FontSize.tiny,
304
+ fontFamily: ThemeConfig.FontFamily.sansPro,
305
+ color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.low,
306
+ },
307
+ // footer ends
308
+ captionContainer: {
309
+ height: 44,
310
+ backgroundColor: $config.CARD_LAYER_2_COLOR,
311
+ padding: 12,
312
+ borderRadius: 4,
313
+ flexDirection: 'row',
314
+ justifyContent: 'flex-start',
315
+ },
316
+ captionText: {
317
+ fontSize: 12,
318
+ fontWeight: '400',
319
+ fontFamily: 'Source Sans Pro',
320
+ color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.high,
321
+ paddingLeft: 8,
322
+ },
323
+ infotextContainer: {
324
+ display: 'flex',
325
+ flex: 1,
326
+ alignItems: 'center',
327
+ justifyContent: 'center',
328
+ },
329
+ infoText: {
330
+ fontSize: 16,
331
+ fontWeight: '600',
332
+ fontFamily: 'Source Sans Pro',
333
+ color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.low,
334
+ },
335
+ iconButtonContainer: {
336
+ marginTop: -8,
337
+ },
338
+ iconButton: {
339
+ width: 32,
340
+ height: 32,
341
+ display: 'flex',
342
+ alignItems: 'center',
343
+ justifyContent: 'center',
344
+ shadowColor: $config.HARD_CODED_BLACK_COLOR,
345
+ },
346
+ iconButtonHoverEffect: {
347
+ backgroundColor:
348
+ $config.CARD_LAYER_5_COLOR + hexadecimalTransparency['25%'],
349
+ borderRadius: 16,
350
+ },
351
+ iconShareLink: {
352
+ width: 32,
353
+ height: 32,
354
+ display: 'flex',
355
+ alignItems: 'center',
356
+ justifyContent: 'center',
357
+ },
358
+ zeroHPadding: {
359
+ paddingHorizontal: 0,
360
+ },
361
+ pushRight: {
362
+ marginLeft: 'auto',
363
+ },
364
+ pl10: {
365
+ paddingLeft: 10,
366
+ },
367
+ plzero: {
368
+ paddingLeft: 0,
369
+ },
370
+ pt10: {
371
+ paddingTop: 10,
372
+ },
373
+ pt12: {
374
+ paddingTop: 12,
375
+ },
376
+ pv10: {
377
+ paddingVertical: 10,
378
+ },
379
+ ph20: {
380
+ paddingHorizontal: 20,
381
+ },
382
+ pl15: {
383
+ paddingLeft: 15,
384
+ },
385
+ });
@@ -3,7 +3,7 @@ import {useContext} from 'react';
3
3
  import {ClientRoleType, PropsContext} from '../../../agora-rn-uikit/src';
4
4
  import {useRoomInfo} from '../room-info/useRoomInfo';
5
5
  import {joinRoomPreference} from '../../utils/useJoinRoom';
6
- import isMobileOrTablet from '../../utils/isMobileOrTablet';
6
+ import {isWeb} from '../../utils/common';
7
7
 
8
8
  /**
9
9
  * ControlPermissionKey represents the different keys
@@ -14,7 +14,8 @@ export type ControlPermissionKey =
14
14
  | 'inviteControl'
15
15
  | 'participantControl'
16
16
  | 'screenshareControl'
17
- | 'settingsControl';
17
+ | 'settingsControl'
18
+ | 'viewAllTranscripts';
18
19
 
19
20
  /**
20
21
  * ControlPermissionRule defines the properties used to evaluate permission rules.
@@ -35,11 +36,9 @@ export const controlPermissionMatrix: Record<
35
36
  settingsControl: ({preference}) => !preference.disableSettings,
36
37
  screenshareControl: ({preference}) =>
37
38
  $config.SCREEN_SHARING && !preference.disableScreenShare,
38
- // !(
39
- // $config.EVENT_MODE &&
40
- // role == ClientRoleType.ClientRoleAudience &&
41
- // !$config.RAISE_HAND
42
- // ),
39
+ viewAllTranscripts: ({isHost}) =>
40
+ $config.ENABLE_STT && $config.ENABLE_MEETING_TRANSCRIPT && isWeb(),
41
+ // isHost,
43
42
  };
44
43
 
45
44
  export const useControlPermissionMatrix = (
@@ -11,7 +11,6 @@
11
11
  */
12
12
  import React, {createContext, useContext, useEffect, useState} from 'react';
13
13
  import {createHook} from 'customization-implementation';
14
- import {ApolloError} from '@apollo/client';
15
14
  import {SdkApiContext} from '../SdkApiContext';
16
15
  import {useRoomInfo} from '../room-info/useRoomInfo';
17
16
  import SDKEvents from '../../utils/SdkEvents';
@@ -21,7 +20,7 @@ import useSetName from '../../utils/useSetName';
21
20
  export interface PreCallContextInterface {
22
21
  callActive: boolean;
23
22
  setCallActive: React.Dispatch<React.SetStateAction<boolean>>;
24
- error?: ApolloError;
23
+ error?: any;
25
24
  isCameraAvailable?: boolean;
26
25
  setCameraAvailable: React.Dispatch<React.SetStateAction<boolean>>;
27
26
  isMicAvailable?: boolean;
@@ -63,6 +63,7 @@ export interface RoomData {
63
63
  rtmToken?: string;
64
64
  encryptionSecret?: string;
65
65
  encryptionSecretSalt?: Uint8Array;
66
+ encryptionMode?: number;
66
67
  screenShareUid?: string;
67
68
  screenShareToken?: string;
68
69
  agents?: AIAgentInterface[];