agora-appbuilder-core 4.1.8-beta.1 → 4.1.8-beta.10
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/package.json +2 -2
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +1 -1
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +18 -9
- package/template/bridge/rtc/webNg/RtcEngine.ts +2 -2
- package/template/defaultConfig.js +4 -3
- package/template/global.d.ts +1 -0
- package/template/package.json +1 -1
- package/template/src/components/Controls.tsx +17 -15
- package/template/src/components/common/GenericPopup.tsx +0 -1
- package/template/src/components/common/data-table.tsx +42 -15
- package/template/src/components/controls/useControlPermissionMatrix.tsx +7 -4
- package/template/src/components/recordings/RecordingItemRow.tsx +289 -0
- package/template/src/components/recordings/RecordingsDateTable.tsx +99 -25
- package/template/src/components/recordings/TextTrackItemRow.tsx +120 -0
- package/template/src/components/room-info/useRoomInfo.tsx +1 -0
- package/template/src/components/{stt-transcript/STTTranscriptTable.tsx → text-tracks/TextTracksTable.tsx} +61 -50
- package/template/src/components/{stt-transcript/ViewSTTTranscriptModal.tsx → text-tracks/ViewTextTracksModal.tsx} +7 -7
- package/template/src/components/text-tracks/useFetchSTTTranscript.tsx +262 -0
- package/template/src/language/default-labels/videoCallScreenLabels.ts +7 -7
- package/template/src/pages/VideoCall.tsx +1 -1
- package/template/src/subComponents/recording/useRecording.tsx +19 -4
- package/template/src/utils/useCreateRoom.ts +1 -1
- package/template/src/utils/useJoinRoom.ts +5 -0
- package/template/src/components/stt-transcript/useFetchSTTTranscript.tsx +0 -193
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agora-appbuilder-core",
|
|
3
|
-
"version": "4.1.8-beta.
|
|
3
|
+
"version": "4.1.8-beta.10",
|
|
4
4
|
"description": "React Native template for RTE app builder",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
11
|
"vercel-build": "npm run dev-setup && cd template && npm run web:build && cd .. && npm run copy-vercel",
|
|
12
|
-
"uikit": "rm -rf template/agora-rn-uikit && git clone https://github.com/AgoraIO-Community/appbuilder-ui-kit.git template/agora-rn-uikit && cd template/agora-rn-uikit && git checkout appbuilder-uikit-3.1.
|
|
12
|
+
"uikit": "rm -rf template/agora-rn-uikit && git clone https://github.com/AgoraIO-Community/appbuilder-ui-kit.git template/agora-rn-uikit && cd template/agora-rn-uikit && git checkout appbuilder-uikit-3.1.8",
|
|
13
13
|
"deps": "cd template && npm i --force",
|
|
14
14
|
"dev-setup": "npm run uikit && npm run deps && node devSetup.js",
|
|
15
15
|
"web-build": "cd template && npm run web:build && cd .. && npm run copy-vercel",
|
|
@@ -142,7 +142,7 @@ export interface RtcPropsInterface {
|
|
|
142
142
|
callActive?: boolean;
|
|
143
143
|
encryption?: {
|
|
144
144
|
key: string;
|
|
145
|
-
mode: EncryptionMode.
|
|
145
|
+
mode: EncryptionMode.Aes128Xts | EncryptionMode.Aes256Gcm2;
|
|
146
146
|
salt: number[];
|
|
147
147
|
};
|
|
148
148
|
// commented for v1 release
|
|
@@ -51,18 +51,27 @@ const Join: React.FC<{
|
|
|
51
51
|
const videoState = defaultContent[maxUid]?.video;
|
|
52
52
|
async function join() {
|
|
53
53
|
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
rtcProps
|
|
57
|
-
|
|
54
|
+
// rtcProps?.encryption &&
|
|
55
|
+
// rtcProps?.encryption.key &&
|
|
56
|
+
rtcProps?.encryption?.mode
|
|
57
|
+
// rtcProps.encryption.salt
|
|
58
58
|
) {
|
|
59
59
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
console.log(
|
|
61
|
+
'ui kit setting encryption mode to ',
|
|
62
|
+
rtcProps?.encryption?.mode,
|
|
63
|
+
);
|
|
64
|
+
const encryptionConfig = {
|
|
65
|
+
encryptionKey: rtcProps?.encryption?.key,
|
|
66
|
+
encryptionMode: rtcProps?.encryption?.mode,
|
|
64
67
|
datastreamEncryptionEnabled: true,
|
|
65
|
-
|
|
68
|
+
...(rtcProps?.encryption?.mode == 1
|
|
69
|
+
? {}
|
|
70
|
+
: {
|
|
71
|
+
encryptionKdfSalt: rtcProps?.encryption?.salt,
|
|
72
|
+
}),
|
|
73
|
+
};
|
|
74
|
+
await engine.enableEncryption(true, encryptionConfig);
|
|
66
75
|
} catch (error) {
|
|
67
76
|
console.warn('encryption error', error);
|
|
68
77
|
}
|
|
@@ -1466,13 +1466,13 @@ export default class RtcEngine {
|
|
|
1466
1466
|
this.client.setEncryptionConfig(
|
|
1467
1467
|
mode,
|
|
1468
1468
|
config.encryptionKey,
|
|
1469
|
-
config.encryptionKdfSalt,
|
|
1469
|
+
config.encryptionMode === 1? null:config.encryptionKdfSalt,
|
|
1470
1470
|
true, // encryptDataStream
|
|
1471
1471
|
),
|
|
1472
1472
|
this.screenClient.setEncryptionConfig(
|
|
1473
1473
|
mode,
|
|
1474
1474
|
config.encryptionKey,
|
|
1475
|
-
config.encryptionKdfSalt,
|
|
1475
|
+
config.encryptionMode === 1? null:config.encryptionKdfSalt,
|
|
1476
1476
|
true, // encryptDataStream
|
|
1477
1477
|
),
|
|
1478
1478
|
]);
|
|
@@ -77,8 +77,8 @@ const DefaultConfig = {
|
|
|
77
77
|
CHAT_ORG_NAME: '',
|
|
78
78
|
CHAT_APP_NAME: '',
|
|
79
79
|
CHAT_URL: '',
|
|
80
|
-
CLI_VERSION: '3.1.8-beta.
|
|
81
|
-
CORE_VERSION: '4.1.8-beta.
|
|
80
|
+
CLI_VERSION: '3.1.8-beta.10',
|
|
81
|
+
CORE_VERSION: '4.1.8-beta.10',
|
|
82
82
|
DISABLE_LANDSCAPE_MODE: false,
|
|
83
83
|
STT_AUTO_START: false,
|
|
84
84
|
CLOUD_RECORDING_AUTO_START: false,
|
|
@@ -89,7 +89,8 @@ const DefaultConfig = {
|
|
|
89
89
|
AI_LAYOUT: 'LAYOUT_TYPE_1',
|
|
90
90
|
SDK_CODEC: 'vp8',
|
|
91
91
|
ENABLE_WAITING_ROOM_AUTO_APPROVAL: false,
|
|
92
|
-
ENABLE_WAITING_ROOM_AUTO_REQUEST: false
|
|
92
|
+
ENABLE_WAITING_ROOM_AUTO_REQUEST: false,
|
|
93
|
+
ENABLE_TEXT_TRACKS: true,
|
|
93
94
|
};
|
|
94
95
|
|
|
95
96
|
module.exports = DefaultConfig;
|
package/template/global.d.ts
CHANGED
|
@@ -177,6 +177,7 @@ interface ConfigInterface {
|
|
|
177
177
|
SDK_CODEC: string;
|
|
178
178
|
ENABLE_WAITING_ROOM_AUTO_APPROVAL: boolean;
|
|
179
179
|
ENABLE_WAITING_ROOM_AUTO_REQUEST: boolean;
|
|
180
|
+
ENABLE_TEXT_TRACKS: boolean;
|
|
180
181
|
}
|
|
181
182
|
declare var $config: ConfigInterface;
|
|
182
183
|
declare module 'customization' {
|
package/template/package.json
CHANGED
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"agora-extension-beauty-effect": "^1.0.2-beta",
|
|
65
65
|
"agora-extension-virtual-background": "^1.1.3",
|
|
66
66
|
"agora-react-native-rtm": "1.5.1",
|
|
67
|
-
"agora-rtc-sdk-ng": "4.23.
|
|
67
|
+
"agora-rtc-sdk-ng": "4.23.4",
|
|
68
68
|
"agora-rtm-sdk": "1.5.1",
|
|
69
69
|
"buffer": "^6.0.3",
|
|
70
70
|
"electron-log": "4.3.5",
|
|
@@ -103,7 +103,7 @@ import {
|
|
|
103
103
|
toolbarItemTranscriptText,
|
|
104
104
|
toolbarItemVirtualBackgroundText,
|
|
105
105
|
toolbarItemWhiteboardText,
|
|
106
|
-
|
|
106
|
+
toolbarItemManageTextTracksText,
|
|
107
107
|
} from '../language/default-labels/videoCallScreenLabels';
|
|
108
108
|
import {LogSource, logger} from '../logger/AppBuilderLogger';
|
|
109
109
|
import {useModal} from '../utils/useModal';
|
|
@@ -116,7 +116,7 @@ import {
|
|
|
116
116
|
InviteToolbarItem,
|
|
117
117
|
ScreenshareToolbarItem,
|
|
118
118
|
} from './controls/toolbar-items';
|
|
119
|
-
import
|
|
119
|
+
import ViewTextTracksModal from './text-tracks/ViewTextTracksModal';
|
|
120
120
|
|
|
121
121
|
export const useToggleWhiteboard = () => {
|
|
122
122
|
const {
|
|
@@ -278,7 +278,9 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
|
|
|
278
278
|
const viewRecordingsLabel = useString<boolean>(
|
|
279
279
|
toolbarItemViewRecordingText,
|
|
280
280
|
)();
|
|
281
|
-
const
|
|
281
|
+
const viewTextTracksLabel = useString<boolean>(
|
|
282
|
+
toolbarItemManageTextTracksText,
|
|
283
|
+
)();
|
|
282
284
|
const moreButtonLabel = useString(toolbarItemMoreText)();
|
|
283
285
|
const virtualBackgroundLabel = useString(toolbarItemVirtualBackgroundText)();
|
|
284
286
|
const chatLabel = useString(toolbarItemChatText)();
|
|
@@ -297,9 +299,9 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
|
|
|
297
299
|
toggle: toggleVRModal,
|
|
298
300
|
} = useModal();
|
|
299
301
|
const {
|
|
300
|
-
modalOpen:
|
|
301
|
-
setModalOpen:
|
|
302
|
-
toggle:
|
|
302
|
+
modalOpen: isTextTrackModalOpen,
|
|
303
|
+
setModalOpen: setTextTrackModalOpen,
|
|
304
|
+
toggle: toggleTextTrackModal,
|
|
303
305
|
} = useModal();
|
|
304
306
|
const moreBtnRef = useRef(null);
|
|
305
307
|
const {width: globalWidth, height: globalHeight} = useWindowDimensions();
|
|
@@ -814,20 +816,20 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
|
|
|
814
816
|
});
|
|
815
817
|
}
|
|
816
818
|
|
|
817
|
-
// 13.
|
|
818
|
-
const
|
|
819
|
-
useControlPermissionMatrix('
|
|
819
|
+
// 13. Text-tracks to download
|
|
820
|
+
const canAccessAllTextTracks =
|
|
821
|
+
useControlPermissionMatrix('viewAllTextTracks');
|
|
820
822
|
|
|
821
|
-
if (
|
|
823
|
+
if (canAccessAllTextTracks) {
|
|
822
824
|
actionMenuitems.push({
|
|
823
|
-
componentName: 'view-all-
|
|
825
|
+
componentName: 'view-all-text-tracks',
|
|
824
826
|
order: 13,
|
|
825
827
|
icon: 'transcript',
|
|
826
828
|
iconColor: $config.SECONDARY_ACTION_COLOR,
|
|
827
829
|
textColor: $config.FONT_COLOR,
|
|
828
|
-
title:
|
|
830
|
+
title: viewTextTracksLabel,
|
|
829
831
|
onPress: () => {
|
|
830
|
-
|
|
832
|
+
toggleTextTrackModal();
|
|
831
833
|
},
|
|
832
834
|
});
|
|
833
835
|
}
|
|
@@ -978,8 +980,8 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
|
|
|
978
980
|
)}
|
|
979
981
|
</>
|
|
980
982
|
)}
|
|
981
|
-
{
|
|
982
|
-
<
|
|
983
|
+
{canAccessAllTextTracks && isTextTrackModalOpen ? (
|
|
984
|
+
<ViewTextTracksModal setModalOpen={setTextTrackModalOpen} />
|
|
983
985
|
) : (
|
|
984
986
|
<></>
|
|
985
987
|
)}
|
|
@@ -19,6 +19,7 @@ interface TableHeaderProps {
|
|
|
19
19
|
rowStyle?: ViewStyle;
|
|
20
20
|
cellStyle?: ViewStyle;
|
|
21
21
|
firstCellStyle?: ViewStyle;
|
|
22
|
+
lastCellStyle?: ViewStyle;
|
|
22
23
|
textStyle?: TextStyle;
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -28,22 +29,27 @@ const TableHeader: React.FC<TableHeaderProps> = ({
|
|
|
28
29
|
rowStyle,
|
|
29
30
|
cellStyle,
|
|
30
31
|
firstCellStyle,
|
|
32
|
+
lastCellStyle,
|
|
31
33
|
textStyle,
|
|
32
34
|
}) => (
|
|
33
35
|
<View style={[style.thead, containerStyle]}>
|
|
34
36
|
<View style={[style.throw, rowStyle]}>
|
|
35
|
-
{columns.map((col, index) =>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
{columns.map((col, index) => {
|
|
38
|
+
const isFirst = index === 0;
|
|
39
|
+
const isLast = index === (columns.length > 1 ? columns.length - 1 : 0);
|
|
40
|
+
return (
|
|
41
|
+
<View
|
|
42
|
+
key={col}
|
|
43
|
+
style={[
|
|
44
|
+
style.th,
|
|
45
|
+
cellStyle,
|
|
46
|
+
isFirst && firstCellStyle,
|
|
47
|
+
isLast && lastCellStyle,
|
|
48
|
+
]}>
|
|
49
|
+
<Text style={[style.thText, textStyle]}>{col}</Text>
|
|
50
|
+
</View>
|
|
51
|
+
);
|
|
52
|
+
})}
|
|
47
53
|
</View>
|
|
48
54
|
</View>
|
|
49
55
|
);
|
|
@@ -151,7 +157,7 @@ const TableFooter: React.FC<TableFooterProps> = ({
|
|
|
151
157
|
|
|
152
158
|
export {TableHeader, TableFooter, TableBody};
|
|
153
159
|
|
|
154
|
-
const style = StyleSheet.create({
|
|
160
|
+
export const style = StyleSheet.create({
|
|
155
161
|
scrollgrow: {
|
|
156
162
|
flexGrow: 1,
|
|
157
163
|
},
|
|
@@ -222,7 +228,7 @@ const style = StyleSheet.create({
|
|
|
222
228
|
flex: 1,
|
|
223
229
|
alignSelf: 'stretch',
|
|
224
230
|
justifyContent: 'center',
|
|
225
|
-
paddingHorizontal: 12,
|
|
231
|
+
// paddingHorizontal: 12,
|
|
226
232
|
},
|
|
227
233
|
thText: {
|
|
228
234
|
color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.medium,
|
|
@@ -249,7 +255,6 @@ const style = StyleSheet.create({
|
|
|
249
255
|
flex: 1,
|
|
250
256
|
alignSelf: 'center',
|
|
251
257
|
justifyContent: 'center',
|
|
252
|
-
// height: 100,
|
|
253
258
|
gap: 10,
|
|
254
259
|
},
|
|
255
260
|
tpreview: {
|
|
@@ -275,6 +280,8 @@ const style = StyleSheet.create({
|
|
|
275
280
|
tactions: {
|
|
276
281
|
display: 'flex',
|
|
277
282
|
flexDirection: 'row',
|
|
283
|
+
alignItems: 'center',
|
|
284
|
+
justifyContent: 'flex-end',
|
|
278
285
|
},
|
|
279
286
|
tlink: {
|
|
280
287
|
color: $config.PRIMARY_ACTION_BRAND_COLOR,
|
|
@@ -382,4 +389,24 @@ const style = StyleSheet.create({
|
|
|
382
389
|
pl15: {
|
|
383
390
|
paddingLeft: 15,
|
|
384
391
|
},
|
|
392
|
+
// icon celles
|
|
393
|
+
tdIconCell: {
|
|
394
|
+
flex: 0,
|
|
395
|
+
flexShrink: 0,
|
|
396
|
+
alignItems: 'flex-start',
|
|
397
|
+
justifyContent: 'center',
|
|
398
|
+
minWidth: 52,
|
|
399
|
+
// paddingRight: 50 + 12,
|
|
400
|
+
},
|
|
401
|
+
thIconCell: {
|
|
402
|
+
flex: 0,
|
|
403
|
+
flexShrink: 0,
|
|
404
|
+
alignSelf: 'stretch',
|
|
405
|
+
justifyContent: 'center',
|
|
406
|
+
minWidth: 50,
|
|
407
|
+
paddingHorizontal: 12,
|
|
408
|
+
},
|
|
409
|
+
alignCellToRight: {
|
|
410
|
+
alignItems: 'flex-end',
|
|
411
|
+
},
|
|
385
412
|
});
|
|
@@ -15,7 +15,7 @@ export type ControlPermissionKey =
|
|
|
15
15
|
| 'participantControl'
|
|
16
16
|
| 'screenshareControl'
|
|
17
17
|
| 'settingsControl'
|
|
18
|
-
| '
|
|
18
|
+
| 'viewAllTextTracks';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* ControlPermissionRule defines the properties used to evaluate permission rules.
|
|
@@ -36,9 +36,12 @@ export const controlPermissionMatrix: Record<
|
|
|
36
36
|
settingsControl: ({preference}) => !preference.disableSettings,
|
|
37
37
|
screenshareControl: ({preference}) =>
|
|
38
38
|
$config.SCREEN_SHARING && !preference.disableScreenShare,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
viewAllTextTracks: ({isHost}) =>
|
|
40
|
+
isHost &&
|
|
41
|
+
$config.ENABLE_STT &&
|
|
42
|
+
$config.ENABLE_MEETING_TRANSCRIPT &&
|
|
43
|
+
$config.ENABLE_TEXT_TRACKS &&
|
|
44
|
+
isWeb(),
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
export const useControlPermissionMatrix = (
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import React, {useEffect, useState} from 'react';
|
|
2
|
+
import {View, Text, Linking, TouchableOpacity, StyleSheet} from 'react-native';
|
|
3
|
+
import {downloadRecording, getDuration, getRecordedDateTime} from './utils';
|
|
4
|
+
import IconButtonWithToolTip from '../../atoms/IconButton';
|
|
5
|
+
import Tooltip from '../../atoms/Tooltip';
|
|
6
|
+
import Clipboard from '../../subComponents/Clipboard';
|
|
7
|
+
import Spacer from '../../atoms/Spacer';
|
|
8
|
+
import PlatformWrapper from '../../utils/PlatformWrapper';
|
|
9
|
+
import {useFetchSTTTranscript} from '../text-tracks/useFetchSTTTranscript';
|
|
10
|
+
import {style} from '../common/data-table';
|
|
11
|
+
import {FetchRecordingData} from '../../subComponents/recording/useRecording';
|
|
12
|
+
import ImageIcon from '../../atoms/ImageIcon';
|
|
13
|
+
import TextTrackItemRow from './TextTrackItemRow';
|
|
14
|
+
|
|
15
|
+
interface RecordingItemRowProps {
|
|
16
|
+
item: FetchRecordingData['recordings'][0];
|
|
17
|
+
onDeleteAction: (id: string) => void;
|
|
18
|
+
onTextTrackDownload: (textTrackLink: string) => void;
|
|
19
|
+
showTextTracks: boolean;
|
|
20
|
+
}
|
|
21
|
+
export default function RecordingItemRow({
|
|
22
|
+
item,
|
|
23
|
+
onDeleteAction,
|
|
24
|
+
onTextTrackDownload,
|
|
25
|
+
showTextTracks = false,
|
|
26
|
+
}: RecordingItemRowProps) {
|
|
27
|
+
const [expanded, setIsExpanded] = useState(false);
|
|
28
|
+
|
|
29
|
+
const [date, time] = getRecordedDateTime(item.created_at);
|
|
30
|
+
const recordingStatus = item.status;
|
|
31
|
+
|
|
32
|
+
const {sttRecState, getSTTsForRecording} = useFetchSTTTranscript();
|
|
33
|
+
const {
|
|
34
|
+
status,
|
|
35
|
+
error,
|
|
36
|
+
data: {stts = []},
|
|
37
|
+
} = sttRecState;
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (expanded) {
|
|
41
|
+
if (item.id) {
|
|
42
|
+
getSTTsForRecording(item.id);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}, [expanded, item.id, getSTTsForRecording]);
|
|
46
|
+
|
|
47
|
+
if (
|
|
48
|
+
recordingStatus === 'STOPPING' ||
|
|
49
|
+
recordingStatus === 'STARTED' ||
|
|
50
|
+
(recordingStatus === 'INPROGRESS' && !item?.download_url)
|
|
51
|
+
) {
|
|
52
|
+
return (
|
|
53
|
+
<View key={item.id} style={style.pt12}>
|
|
54
|
+
<View style={[style.infotextContainer, style.captionContainer]}>
|
|
55
|
+
<ImageIcon
|
|
56
|
+
iconSize={20}
|
|
57
|
+
iconType="plain"
|
|
58
|
+
name="info"
|
|
59
|
+
tintColor={$config.SEMANTIC_NEUTRAL}
|
|
60
|
+
/>
|
|
61
|
+
<Text style={[style.captionText]}>
|
|
62
|
+
Current recording is ongoing. Once it concludes, we'll generate the
|
|
63
|
+
link
|
|
64
|
+
</Text>
|
|
65
|
+
</View>
|
|
66
|
+
</View>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Collapsible Row
|
|
71
|
+
return (
|
|
72
|
+
<View>
|
|
73
|
+
{/* ========== PARENT ROW ========== */}
|
|
74
|
+
<View style={style.tbrow} key={item.id}>
|
|
75
|
+
{showTextTracks && (
|
|
76
|
+
<View style={style.tdIconCell}>
|
|
77
|
+
<IconButtonWithToolTip
|
|
78
|
+
hoverEffect={true}
|
|
79
|
+
hoverEffectStyle={style.iconButtonHoverEffect}
|
|
80
|
+
containerStyle={style.iconButton}
|
|
81
|
+
iconProps={{
|
|
82
|
+
name: expanded ? 'arrow-up' : 'arrow-down',
|
|
83
|
+
iconType: 'plain',
|
|
84
|
+
iconSize: 20,
|
|
85
|
+
tintColor: `${$config.FONT_COLOR}`,
|
|
86
|
+
}}
|
|
87
|
+
onPress={() => setIsExpanded(prev => !prev)}
|
|
88
|
+
/>
|
|
89
|
+
</View>
|
|
90
|
+
)}
|
|
91
|
+
<View style={[style.td, style.plzero]}>
|
|
92
|
+
<Text style={style.ttime}>
|
|
93
|
+
{date}
|
|
94
|
+
<br />
|
|
95
|
+
<Text style={style.ttime}>{time}</Text>
|
|
96
|
+
</Text>
|
|
97
|
+
</View>
|
|
98
|
+
<View style={[style.td]}>
|
|
99
|
+
<Text style={style.ttime}>
|
|
100
|
+
{getDuration(item.created_at, item.ended_at)}
|
|
101
|
+
</Text>
|
|
102
|
+
</View>
|
|
103
|
+
<View style={style.td}>
|
|
104
|
+
{!item.download_url ? (
|
|
105
|
+
<View style={(style.tactions, {marginTop: 0})}>
|
|
106
|
+
<Text style={style.placeHolder}>{'No recording found'}</Text>
|
|
107
|
+
</View>
|
|
108
|
+
) : item?.download_url?.length > 0 ? (
|
|
109
|
+
<View style={style.tactions}>
|
|
110
|
+
<View>
|
|
111
|
+
{item?.download_url?.map((link: string, i: number) => (
|
|
112
|
+
<View
|
|
113
|
+
style={[
|
|
114
|
+
style.tactions,
|
|
115
|
+
//if recording contains multiple parts then we need to add some space each row
|
|
116
|
+
i >= 1 ? {marginTop: 8} : {},
|
|
117
|
+
]}>
|
|
118
|
+
<View>
|
|
119
|
+
<IconButtonWithToolTip
|
|
120
|
+
hoverEffect={true}
|
|
121
|
+
hoverEffectStyle={style.iconButtonHoverEffect}
|
|
122
|
+
containerStyle={style.iconButton}
|
|
123
|
+
iconProps={{
|
|
124
|
+
name: 'download',
|
|
125
|
+
iconType: 'plain',
|
|
126
|
+
iconSize: 20,
|
|
127
|
+
tintColor: `${$config.SECONDARY_ACTION_COLOR}`,
|
|
128
|
+
}}
|
|
129
|
+
onPress={() => {
|
|
130
|
+
downloadRecording(link);
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
</View>
|
|
134
|
+
<View style={style.pl10}>
|
|
135
|
+
<IconButtonWithToolTip
|
|
136
|
+
hoverEffect={true}
|
|
137
|
+
hoverEffectStyle={style.iconButtonHoverEffect}
|
|
138
|
+
containerStyle={style.iconButton}
|
|
139
|
+
iconProps={{
|
|
140
|
+
name: 'link-share',
|
|
141
|
+
iconType: 'plain',
|
|
142
|
+
iconSize: 20,
|
|
143
|
+
tintColor: `${$config.SECONDARY_ACTION_COLOR}`,
|
|
144
|
+
}}
|
|
145
|
+
onPress={async () => {
|
|
146
|
+
if (await Linking.canOpenURL(link)) {
|
|
147
|
+
await Linking.openURL(link);
|
|
148
|
+
}
|
|
149
|
+
}}
|
|
150
|
+
/>
|
|
151
|
+
</View>
|
|
152
|
+
<View style={[style.pl10]}>
|
|
153
|
+
<Tooltip
|
|
154
|
+
isClickable
|
|
155
|
+
placement="left"
|
|
156
|
+
toolTipMessage="Link Copied"
|
|
157
|
+
onPress={() => {
|
|
158
|
+
Clipboard.setString(link);
|
|
159
|
+
}}
|
|
160
|
+
toolTipIcon={
|
|
161
|
+
<>
|
|
162
|
+
<ImageIcon
|
|
163
|
+
iconType="plain"
|
|
164
|
+
name="tick-fill"
|
|
165
|
+
tintColor={$config.SEMANTIC_SUCCESS}
|
|
166
|
+
iconSize={20}
|
|
167
|
+
/>
|
|
168
|
+
<Spacer size={8} horizontal={true} />
|
|
169
|
+
</>
|
|
170
|
+
}
|
|
171
|
+
fontSize={12}
|
|
172
|
+
renderContent={() => {
|
|
173
|
+
return (
|
|
174
|
+
<PlatformWrapper>
|
|
175
|
+
{(isHovered: boolean) => (
|
|
176
|
+
<TouchableOpacity
|
|
177
|
+
style={[
|
|
178
|
+
isHovered
|
|
179
|
+
? style.iconButtonHoverEffect
|
|
180
|
+
: {},
|
|
181
|
+
style.iconShareLink,
|
|
182
|
+
]}
|
|
183
|
+
onPress={() => {
|
|
184
|
+
Clipboard.setString(link);
|
|
185
|
+
}}>
|
|
186
|
+
<ImageIcon
|
|
187
|
+
iconType="plain"
|
|
188
|
+
name="copy-link"
|
|
189
|
+
iconSize={20}
|
|
190
|
+
tintColor={$config.SECONDARY_ACTION_COLOR}
|
|
191
|
+
/>
|
|
192
|
+
</TouchableOpacity>
|
|
193
|
+
)}
|
|
194
|
+
</PlatformWrapper>
|
|
195
|
+
);
|
|
196
|
+
}}
|
|
197
|
+
/>
|
|
198
|
+
</View>
|
|
199
|
+
</View>
|
|
200
|
+
))}
|
|
201
|
+
</View>
|
|
202
|
+
<View style={[style.pl10]}>
|
|
203
|
+
<IconButtonWithToolTip
|
|
204
|
+
hoverEffect={true}
|
|
205
|
+
hoverEffectStyle={style.iconButtonHoverEffect}
|
|
206
|
+
containerStyle={style.iconButton}
|
|
207
|
+
iconProps={{
|
|
208
|
+
name: 'delete',
|
|
209
|
+
iconType: 'plain',
|
|
210
|
+
iconSize: 20,
|
|
211
|
+
tintColor: `${$config.SEMANTIC_ERROR}`,
|
|
212
|
+
}}
|
|
213
|
+
onPress={() => {
|
|
214
|
+
onDeleteAction && onDeleteAction(item.id);
|
|
215
|
+
}}
|
|
216
|
+
/>
|
|
217
|
+
</View>
|
|
218
|
+
</View>
|
|
219
|
+
) : (
|
|
220
|
+
<View style={(style.tactions, {marginTop: 0})}>
|
|
221
|
+
<Text style={style.placeHolder}>No recordings found</Text>
|
|
222
|
+
</View>
|
|
223
|
+
)}
|
|
224
|
+
</View>
|
|
225
|
+
</View>
|
|
226
|
+
{/* ========== CHILDREN ROW ========== */}
|
|
227
|
+
{expanded && (
|
|
228
|
+
<View style={expanedStyles.expandedContainer}>
|
|
229
|
+
<View>
|
|
230
|
+
<Text style={expanedStyles.expandedHeaderText}>Text-tracks</Text>
|
|
231
|
+
</View>
|
|
232
|
+
<View style={expanedStyles.expandedHeaderBody}>
|
|
233
|
+
{status === 'idle' || status === 'pending' ? (
|
|
234
|
+
<Text style={style.ttime}>Fetching text-tracks....</Text>
|
|
235
|
+
) : status === 'rejected' ? (
|
|
236
|
+
<Text style={style.ttime}>
|
|
237
|
+
{error?.message ||
|
|
238
|
+
'There was an error while fetching the text-tracks'}
|
|
239
|
+
</Text>
|
|
240
|
+
) : status === 'resolved' && stts?.length === 0 ? (
|
|
241
|
+
<Text style={style.ttime}>
|
|
242
|
+
There are no text-tracks's for this recording
|
|
243
|
+
</Text>
|
|
244
|
+
) : (
|
|
245
|
+
<>
|
|
246
|
+
<Text style={style.ttime}>Found {stts.length} text tracks</Text>
|
|
247
|
+
<View>
|
|
248
|
+
{stts.map(item => (
|
|
249
|
+
<TextTrackItemRow
|
|
250
|
+
key={item.id}
|
|
251
|
+
item={item}
|
|
252
|
+
onTextTrackDownload={onTextTrackDownload}
|
|
253
|
+
/>
|
|
254
|
+
))}
|
|
255
|
+
</View>
|
|
256
|
+
</>
|
|
257
|
+
)}
|
|
258
|
+
</View>
|
|
259
|
+
</View>
|
|
260
|
+
)}
|
|
261
|
+
</View>
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const expanedStyles = StyleSheet.create({
|
|
266
|
+
expandedContainer: {
|
|
267
|
+
display: 'flex',
|
|
268
|
+
flexDirection: 'column',
|
|
269
|
+
gap: 5,
|
|
270
|
+
color: $config.FONT_COLOR,
|
|
271
|
+
borderColor: $config.CARD_LAYER_3_COLOR,
|
|
272
|
+
backgroundColor: $config.CARD_LAYER_2_COLOR,
|
|
273
|
+
paddingHorizontal: 12,
|
|
274
|
+
paddingVertical: 15,
|
|
275
|
+
borderRadius: 5,
|
|
276
|
+
},
|
|
277
|
+
expandedHeaderText: {
|
|
278
|
+
fontSize: 15,
|
|
279
|
+
lineHeight: 32,
|
|
280
|
+
fontWeight: '500',
|
|
281
|
+
color: $config.FONT_COLOR,
|
|
282
|
+
},
|
|
283
|
+
expandedHeaderBody: {
|
|
284
|
+
display: 'flex',
|
|
285
|
+
flexDirection: 'row',
|
|
286
|
+
justifyContent: 'space-between',
|
|
287
|
+
alignItems: 'flex-start',
|
|
288
|
+
},
|
|
289
|
+
});
|