@sendbird/uikit-react-native 3.2.0 → 3.4.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/lib/commonjs/components/ChannelInput/EditInput.js +2 -11
- package/lib/commonjs/components/ChannelInput/EditInput.js.map +1 -1
- package/lib/commonjs/components/ChannelInput/SendInput.js +2 -11
- package/lib/commonjs/components/ChannelInput/SendInput.js.map +1 -1
- package/lib/commonjs/components/ChannelInput/index.js +30 -3
- package/lib/commonjs/components/ChannelInput/index.js.map +1 -1
- package/lib/commonjs/components/ChannelMessageList/index.js +148 -116
- package/lib/commonjs/components/ChannelMessageList/index.js.map +1 -1
- package/lib/commonjs/components/FileViewer/FileViewerContent.js +140 -0
- package/lib/commonjs/components/FileViewer/FileViewerContent.js.map +1 -0
- package/lib/commonjs/components/FileViewer/FileViewerFooter.js +82 -0
- package/lib/commonjs/components/FileViewer/FileViewerFooter.js.map +1 -0
- package/lib/commonjs/components/FileViewer/FileViewerHeader.js +93 -0
- package/lib/commonjs/components/FileViewer/FileViewerHeader.js.map +1 -0
- package/lib/commonjs/components/FileViewer/index.js +133 -0
- package/lib/commonjs/components/FileViewer/index.js.map +1 -0
- package/lib/commonjs/components/GroupChannelMessageRenderer/index.js +34 -1
- package/lib/commonjs/components/GroupChannelMessageRenderer/index.js.map +1 -1
- package/lib/commonjs/components/ReactionAddons/BottomSheetReactionAddon.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js +14 -4
- package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +11 -9
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/types.js.map +1 -1
- package/lib/commonjs/domain/messageSearch/component/MessageSearchHeader.js +4 -1
- package/lib/commonjs/domain/messageSearch/component/MessageSearchHeader.js.map +1 -1
- package/lib/commonjs/domain/openChannelCreate/component/OpenChannelCreateProfileInput.js +4 -2
- package/lib/commonjs/domain/openChannelCreate/component/OpenChannelCreateProfileInput.js.map +1 -1
- package/lib/commonjs/fragments/createGroupChannelFragment.js +18 -16
- package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
- package/lib/commonjs/index.js +4 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types.js +7 -0
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/utils/promise.js +138 -0
- package/lib/commonjs/utils/promise.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/components/ChannelInput/EditInput.js +3 -12
- package/lib/module/components/ChannelInput/EditInput.js.map +1 -1
- package/lib/module/components/ChannelInput/SendInput.js +3 -12
- package/lib/module/components/ChannelInput/SendInput.js.map +1 -1
- package/lib/module/components/ChannelInput/index.js +32 -5
- package/lib/module/components/ChannelInput/index.js.map +1 -1
- package/lib/module/components/ChannelMessageList/index.js +148 -116
- package/lib/module/components/ChannelMessageList/index.js.map +1 -1
- package/lib/module/components/FileViewer/FileViewerContent.js +130 -0
- package/lib/module/components/FileViewer/FileViewerContent.js.map +1 -0
- package/lib/module/components/FileViewer/FileViewerFooter.js +74 -0
- package/lib/module/components/FileViewer/FileViewerFooter.js.map +1 -0
- package/lib/module/components/FileViewer/FileViewerHeader.js +85 -0
- package/lib/module/components/FileViewer/FileViewerHeader.js.map +1 -0
- package/lib/module/components/FileViewer/index.js +123 -0
- package/lib/module/components/FileViewer/index.js.map +1 -0
- package/lib/module/components/GroupChannelMessageRenderer/index.js +34 -2
- package/lib/module/components/GroupChannelMessageRenderer/index.js.map +1 -1
- package/lib/module/components/ReactionAddons/BottomSheetReactionAddon.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelHeader.js +15 -5
- package/lib/module/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +11 -9
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/module/domain/groupChannel/types.js.map +1 -1
- package/lib/module/domain/messageSearch/component/MessageSearchHeader.js +4 -1
- package/lib/module/domain/messageSearch/component/MessageSearchHeader.js.map +1 -1
- package/lib/module/domain/openChannelCreate/component/OpenChannelCreateProfileInput.js +4 -2
- package/lib/module/domain/openChannelCreate/component/OpenChannelCreateProfileInput.js.map +1 -1
- package/lib/module/fragments/createGroupChannelFragment.js +19 -17
- package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.js +5 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils/promise.js +132 -0
- package/lib/module/utils/promise.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/src/components/ChannelInput/index.d.ts +2 -0
- package/lib/typescript/src/components/ChannelMessageList/index.d.ts +4 -1
- package/lib/typescript/src/components/FileViewer/FileViewerContent.d.ts +13 -0
- package/lib/typescript/src/components/FileViewer/FileViewerFooter.d.ts +9 -0
- package/lib/typescript/src/components/FileViewer/FileViewerHeader.d.ts +10 -0
- package/lib/typescript/src/components/{FileViewer.d.ts → FileViewer/index.d.ts} +5 -1
- package/lib/typescript/src/components/GroupChannelMessageRenderer/index.d.ts +3 -0
- package/lib/typescript/src/components/OpenChannelMessageRenderer/index.d.ts +2 -0
- package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +1 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelMessageList.d.ts +2 -2
- package/lib/typescript/src/domain/groupChannel/types.d.ts +5 -2
- package/lib/typescript/src/types.d.ts +4 -0
- package/lib/typescript/src/utils/promise.d.ts +7 -0
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +8 -7
- package/src/components/ChannelInput/EditInput.tsx +3 -15
- package/src/components/ChannelInput/SendInput.tsx +2 -9
- package/src/components/ChannelInput/index.tsx +27 -4
- package/src/components/ChannelMessageList/index.tsx +145 -115
- package/src/components/FileViewer/FileViewerContent.tsx +141 -0
- package/src/components/FileViewer/FileViewerFooter.tsx +73 -0
- package/src/components/FileViewer/FileViewerHeader.tsx +86 -0
- package/src/components/FileViewer/index.tsx +139 -0
- package/src/components/GroupChannelMessageRenderer/index.tsx +34 -2
- package/src/components/ReactionAddons/BottomSheetReactionAddon.tsx +3 -2
- package/src/domain/groupChannel/component/GroupChannelHeader.tsx +14 -3
- package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +8 -6
- package/src/domain/groupChannel/types.ts +6 -2
- package/src/domain/messageSearch/component/MessageSearchHeader.tsx +4 -1
- package/src/domain/openChannelCreate/component/OpenChannelCreateProfileInput.tsx +4 -2
- package/src/fragments/createGroupChannelFragment.tsx +25 -15
- package/src/index.ts +5 -1
- package/src/types.ts +5 -0
- package/src/utils/promise.ts +139 -0
- package/src/version.ts +1 -1
- package/lib/commonjs/components/FileViewer.js +0 -300
- package/lib/commonjs/components/FileViewer.js.map +0 -1
- package/lib/module/components/FileViewer.js +0 -291
- package/lib/module/components/FileViewer.js.map +0 -1
- package/src/components/FileViewer.tsx +0 -288
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import { StatusBar, StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
3
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
|
-
import { Icon, Image, LoadingSpinner, Text, createStyleSheet, useAlert, useHeaderStyle, useToast, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
|
|
5
|
-
import { Logger, getFileExtension, getFileType, isMyMessage, toMegabyte, truncate, useIIFE } from '@sendbird/uikit-utils';
|
|
6
|
-
import { useLocalization, usePlatformService, useSendbirdChat } from '../hooks/useContext';
|
|
7
|
-
const FileViewer = _ref => {
|
|
8
|
-
let {
|
|
9
|
-
headerShown = true,
|
|
10
|
-
deleteMessage,
|
|
11
|
-
headerTopInset,
|
|
12
|
-
fileMessage,
|
|
13
|
-
onPressDownload,
|
|
14
|
-
onPressDelete,
|
|
15
|
-
onClose
|
|
16
|
-
} = _ref;
|
|
17
|
-
const [loading, setLoading] = useState(true);
|
|
18
|
-
const {
|
|
19
|
-
bottom
|
|
20
|
-
} = useSafeAreaInsets();
|
|
21
|
-
const {
|
|
22
|
-
currentUser
|
|
23
|
-
} = useSendbirdChat();
|
|
24
|
-
const {
|
|
25
|
-
palette
|
|
26
|
-
} = useUIKitTheme();
|
|
27
|
-
const {
|
|
28
|
-
topInset,
|
|
29
|
-
statusBarTranslucent,
|
|
30
|
-
defaultHeight
|
|
31
|
-
} = useHeaderStyle();
|
|
32
|
-
const {
|
|
33
|
-
STRINGS
|
|
34
|
-
} = useLocalization();
|
|
35
|
-
const {
|
|
36
|
-
fileService,
|
|
37
|
-
mediaService
|
|
38
|
-
} = usePlatformService();
|
|
39
|
-
const toast = useToast();
|
|
40
|
-
const {
|
|
41
|
-
alert
|
|
42
|
-
} = useAlert();
|
|
43
|
-
const basicTopInset = statusBarTranslucent ? topInset : 0;
|
|
44
|
-
const canDelete = isMyMessage(fileMessage, currentUser === null || currentUser === void 0 ? void 0 : currentUser.userId);
|
|
45
|
-
const fileType = getFileType(fileMessage.type || getFileExtension(fileMessage.url));
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
if (fileType === 'file') onClose();
|
|
48
|
-
}, []);
|
|
49
|
-
const fileViewer = useIIFE(() => {
|
|
50
|
-
switch (fileType) {
|
|
51
|
-
case 'image':
|
|
52
|
-
{
|
|
53
|
-
return /*#__PURE__*/React.createElement(Image, {
|
|
54
|
-
source: {
|
|
55
|
-
uri: fileMessage.url
|
|
56
|
-
},
|
|
57
|
-
style: StyleSheet.absoluteFill,
|
|
58
|
-
resizeMode: 'contain',
|
|
59
|
-
onLoadEnd: () => setLoading(false)
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
case 'video':
|
|
63
|
-
case 'audio':
|
|
64
|
-
{
|
|
65
|
-
return /*#__PURE__*/React.createElement(mediaService.VideoComponent, {
|
|
66
|
-
source: {
|
|
67
|
-
uri: fileMessage.url
|
|
68
|
-
},
|
|
69
|
-
style: [StyleSheet.absoluteFill, {
|
|
70
|
-
top: basicTopInset + defaultHeight,
|
|
71
|
-
bottom: defaultHeight + bottom
|
|
72
|
-
}],
|
|
73
|
-
resizeMode: 'contain',
|
|
74
|
-
onLoad: () => setLoading(false)
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
default:
|
|
78
|
-
{
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
const _onPressDelete = () => {
|
|
84
|
-
if (!canDelete) return;
|
|
85
|
-
if (onPressDelete) {
|
|
86
|
-
onPressDelete(fileMessage);
|
|
87
|
-
} else {
|
|
88
|
-
alert({
|
|
89
|
-
title: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_TITLE,
|
|
90
|
-
buttons: [{
|
|
91
|
-
text: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_CANCEL
|
|
92
|
-
}, {
|
|
93
|
-
text: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_OK,
|
|
94
|
-
style: 'destructive',
|
|
95
|
-
onPress: () => {
|
|
96
|
-
deleteMessage().then(() => {
|
|
97
|
-
onClose();
|
|
98
|
-
}).catch(() => {
|
|
99
|
-
toast.show(STRINGS.TOAST.DELETE_MSG_ERROR, 'error');
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}]
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
const _onPressDownload = () => {
|
|
107
|
-
if (onPressDownload) {
|
|
108
|
-
onPressDownload(fileMessage);
|
|
109
|
-
} else {
|
|
110
|
-
if (toMegabyte(fileMessage.size) > 4) {
|
|
111
|
-
toast.show(STRINGS.TOAST.DOWNLOAD_START, 'success');
|
|
112
|
-
}
|
|
113
|
-
fileService.save({
|
|
114
|
-
fileUrl: fileMessage.url,
|
|
115
|
-
fileName: fileMessage.name,
|
|
116
|
-
fileType: fileMessage.type
|
|
117
|
-
}).then(response => {
|
|
118
|
-
toast.show(STRINGS.TOAST.DOWNLOAD_OK, 'success');
|
|
119
|
-
Logger.log('File saved to', response);
|
|
120
|
-
}).catch(err => {
|
|
121
|
-
toast.show(STRINGS.TOAST.DOWNLOAD_ERROR, 'error');
|
|
122
|
-
Logger.log('File save failure', err);
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
return /*#__PURE__*/React.createElement(View, {
|
|
127
|
-
style: {
|
|
128
|
-
flex: 1,
|
|
129
|
-
backgroundColor: palette.background700
|
|
130
|
-
}
|
|
131
|
-
}, /*#__PURE__*/React.createElement(StatusBar, {
|
|
132
|
-
barStyle: 'light-content',
|
|
133
|
-
animated: true
|
|
134
|
-
}), /*#__PURE__*/React.createElement(View, {
|
|
135
|
-
style: {
|
|
136
|
-
flex: 1,
|
|
137
|
-
alignItems: 'center',
|
|
138
|
-
justifyContent: 'center'
|
|
139
|
-
}
|
|
140
|
-
}, fileViewer, loading && /*#__PURE__*/React.createElement(LoadingSpinner, {
|
|
141
|
-
style: {
|
|
142
|
-
position: 'absolute'
|
|
143
|
-
},
|
|
144
|
-
size: 40,
|
|
145
|
-
color: palette.primary300
|
|
146
|
-
})), headerShown && /*#__PURE__*/React.createElement(FileViewerHeader, {
|
|
147
|
-
title: STRINGS.FILE_VIEWER.TITLE(fileMessage),
|
|
148
|
-
subtitle: STRINGS.FILE_VIEWER.SUBTITLE(fileMessage),
|
|
149
|
-
topInset: headerTopInset ?? basicTopInset,
|
|
150
|
-
onClose: onClose
|
|
151
|
-
}), /*#__PURE__*/React.createElement(FileViewerFooter, {
|
|
152
|
-
bottomInset: bottom,
|
|
153
|
-
deleteShown: canDelete,
|
|
154
|
-
onPressDelete: _onPressDelete,
|
|
155
|
-
onPressDownload: _onPressDownload
|
|
156
|
-
}));
|
|
157
|
-
};
|
|
158
|
-
const FileViewerHeader = _ref2 => {
|
|
159
|
-
let {
|
|
160
|
-
topInset,
|
|
161
|
-
onClose,
|
|
162
|
-
subtitle,
|
|
163
|
-
title
|
|
164
|
-
} = _ref2;
|
|
165
|
-
const {
|
|
166
|
-
palette
|
|
167
|
-
} = useUIKitTheme();
|
|
168
|
-
const {
|
|
169
|
-
defaultHeight
|
|
170
|
-
} = useHeaderStyle();
|
|
171
|
-
const {
|
|
172
|
-
left,
|
|
173
|
-
right
|
|
174
|
-
} = useSafeAreaInsets();
|
|
175
|
-
return /*#__PURE__*/React.createElement(View, {
|
|
176
|
-
style: [styles.headerContainer, {
|
|
177
|
-
paddingLeft: styles.headerContainer.paddingHorizontal + left,
|
|
178
|
-
paddingRight: styles.headerContainer.paddingHorizontal + right
|
|
179
|
-
}, {
|
|
180
|
-
paddingTop: topInset,
|
|
181
|
-
height: defaultHeight + topInset,
|
|
182
|
-
backgroundColor: palette.overlay01
|
|
183
|
-
}]
|
|
184
|
-
}, /*#__PURE__*/React.createElement(TouchableOpacity, {
|
|
185
|
-
onPress: onClose,
|
|
186
|
-
style: styles.barButton
|
|
187
|
-
}, /*#__PURE__*/React.createElement(Icon, {
|
|
188
|
-
icon: 'close',
|
|
189
|
-
size: 24,
|
|
190
|
-
color: palette.onBackgroundDark01
|
|
191
|
-
})), /*#__PURE__*/React.createElement(View, {
|
|
192
|
-
style: styles.barTitleContainer
|
|
193
|
-
}, /*#__PURE__*/React.createElement(Text, {
|
|
194
|
-
h2: true,
|
|
195
|
-
color: palette.onBackgroundDark01,
|
|
196
|
-
style: styles.headerTitle,
|
|
197
|
-
numberOfLines: 1
|
|
198
|
-
}, truncate(title, {
|
|
199
|
-
mode: 'mid',
|
|
200
|
-
maxLen: 18
|
|
201
|
-
})), /*#__PURE__*/React.createElement(Text, {
|
|
202
|
-
caption2: true,
|
|
203
|
-
color: palette.onBackgroundDark01,
|
|
204
|
-
numberOfLines: 1
|
|
205
|
-
}, subtitle)), /*#__PURE__*/React.createElement(View, {
|
|
206
|
-
style: styles.barButton
|
|
207
|
-
}));
|
|
208
|
-
};
|
|
209
|
-
const FileViewerFooter = _ref3 => {
|
|
210
|
-
let {
|
|
211
|
-
bottomInset,
|
|
212
|
-
deleteShown,
|
|
213
|
-
onPressDelete,
|
|
214
|
-
onPressDownload
|
|
215
|
-
} = _ref3;
|
|
216
|
-
const {
|
|
217
|
-
palette
|
|
218
|
-
} = useUIKitTheme();
|
|
219
|
-
const {
|
|
220
|
-
defaultHeight
|
|
221
|
-
} = useHeaderStyle();
|
|
222
|
-
const {
|
|
223
|
-
left,
|
|
224
|
-
right
|
|
225
|
-
} = useSafeAreaInsets();
|
|
226
|
-
return /*#__PURE__*/React.createElement(View, {
|
|
227
|
-
style: [styles.footerContainer, {
|
|
228
|
-
paddingLeft: styles.headerContainer.paddingHorizontal + left,
|
|
229
|
-
paddingRight: styles.headerContainer.paddingHorizontal + right
|
|
230
|
-
}, {
|
|
231
|
-
paddingBottom: bottomInset,
|
|
232
|
-
height: defaultHeight + bottomInset,
|
|
233
|
-
backgroundColor: palette.overlay01
|
|
234
|
-
}]
|
|
235
|
-
}, /*#__PURE__*/React.createElement(TouchableOpacity, {
|
|
236
|
-
onPress: onPressDownload,
|
|
237
|
-
style: styles.barButton
|
|
238
|
-
}, /*#__PURE__*/React.createElement(Icon, {
|
|
239
|
-
icon: 'download',
|
|
240
|
-
size: 24,
|
|
241
|
-
color: palette.onBackgroundDark01
|
|
242
|
-
})), /*#__PURE__*/React.createElement(View, {
|
|
243
|
-
style: styles.barTitleContainer
|
|
244
|
-
}), /*#__PURE__*/React.createElement(TouchableOpacity, {
|
|
245
|
-
onPress: onPressDelete,
|
|
246
|
-
style: styles.barButton,
|
|
247
|
-
disabled: !deleteShown
|
|
248
|
-
}, deleteShown && /*#__PURE__*/React.createElement(Icon, {
|
|
249
|
-
icon: 'delete',
|
|
250
|
-
size: 24,
|
|
251
|
-
color: palette.onBackgroundDark01
|
|
252
|
-
})));
|
|
253
|
-
};
|
|
254
|
-
const styles = createStyleSheet({
|
|
255
|
-
headerContainer: {
|
|
256
|
-
top: 0,
|
|
257
|
-
left: 0,
|
|
258
|
-
right: 0,
|
|
259
|
-
position: 'absolute',
|
|
260
|
-
flexDirection: 'row',
|
|
261
|
-
alignItems: 'center',
|
|
262
|
-
justifyContent: 'center',
|
|
263
|
-
paddingHorizontal: 12
|
|
264
|
-
},
|
|
265
|
-
barButton: {
|
|
266
|
-
width: 32,
|
|
267
|
-
height: 32,
|
|
268
|
-
alignItems: 'center',
|
|
269
|
-
justifyContent: 'center'
|
|
270
|
-
},
|
|
271
|
-
barTitleContainer: {
|
|
272
|
-
flex: 1,
|
|
273
|
-
alignItems: 'center',
|
|
274
|
-
justifyContent: 'center'
|
|
275
|
-
},
|
|
276
|
-
headerTitle: {
|
|
277
|
-
marginBottom: 2
|
|
278
|
-
},
|
|
279
|
-
footerContainer: {
|
|
280
|
-
position: 'absolute',
|
|
281
|
-
left: 0,
|
|
282
|
-
right: 0,
|
|
283
|
-
bottom: 0,
|
|
284
|
-
flexDirection: 'row',
|
|
285
|
-
alignItems: 'center',
|
|
286
|
-
justifyContent: 'center',
|
|
287
|
-
paddingHorizontal: 12
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
export default FileViewer;
|
|
291
|
-
//# sourceMappingURL=FileViewer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","useState","StatusBar","StyleSheet","TouchableOpacity","View","useSafeAreaInsets","Icon","Image","LoadingSpinner","Text","createStyleSheet","useAlert","useHeaderStyle","useToast","useUIKitTheme","Logger","getFileExtension","getFileType","isMyMessage","toMegabyte","truncate","useIIFE","useLocalization","usePlatformService","useSendbirdChat","FileViewer","_ref","headerShown","deleteMessage","headerTopInset","fileMessage","onPressDownload","onPressDelete","onClose","loading","setLoading","bottom","currentUser","palette","topInset","statusBarTranslucent","defaultHeight","STRINGS","fileService","mediaService","toast","alert","basicTopInset","canDelete","userId","fileType","type","url","fileViewer","createElement","source","uri","style","absoluteFill","resizeMode","onLoadEnd","VideoComponent","top","onLoad","_onPressDelete","title","LABELS","CHANNEL_MESSAGE_DELETE_CONFIRM_TITLE","buttons","text","CHANNEL_MESSAGE_DELETE_CONFIRM_CANCEL","CHANNEL_MESSAGE_DELETE_CONFIRM_OK","onPress","then","catch","show","TOAST","DELETE_MSG_ERROR","_onPressDownload","size","DOWNLOAD_START","save","fileUrl","fileName","name","response","DOWNLOAD_OK","log","err","DOWNLOAD_ERROR","flex","backgroundColor","background700","barStyle","animated","alignItems","justifyContent","position","color","primary300","FileViewerHeader","FILE_VIEWER","TITLE","subtitle","SUBTITLE","FileViewerFooter","bottomInset","deleteShown","_ref2","left","right","styles","headerContainer","paddingLeft","paddingHorizontal","paddingRight","paddingTop","height","overlay01","barButton","icon","onBackgroundDark01","barTitleContainer","h2","headerTitle","numberOfLines","mode","maxLen","caption2","_ref3","footerContainer","paddingBottom","disabled","flexDirection","width","marginBottom"],"sources":["FileViewer.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react';\nimport { StatusBar, StyleSheet, TouchableOpacity, View } from 'react-native';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\n\nimport {\n Icon,\n Image,\n LoadingSpinner,\n Text,\n createStyleSheet,\n useAlert,\n useHeaderStyle,\n useToast,\n useUIKitTheme,\n} from '@sendbird/uikit-react-native-foundation';\nimport type { SendbirdFileMessage } from '@sendbird/uikit-utils';\nimport {\n Logger,\n getFileExtension,\n getFileType,\n isMyMessage,\n toMegabyte,\n truncate,\n useIIFE,\n} from '@sendbird/uikit-utils';\n\nimport { useLocalization, usePlatformService, useSendbirdChat } from '../hooks/useContext';\n\ntype Props = {\n fileMessage: SendbirdFileMessage;\n deleteMessage: () => Promise<void>;\n\n onClose: () => void;\n onPressDownload?: (message: SendbirdFileMessage) => void;\n onPressDelete?: (message: SendbirdFileMessage) => void;\n\n headerShown?: boolean;\n headerTopInset?: number;\n};\nconst FileViewer = ({\n headerShown = true,\n deleteMessage,\n headerTopInset,\n fileMessage,\n onPressDownload,\n onPressDelete,\n onClose,\n}: Props) => {\n const [loading, setLoading] = useState(true);\n\n const { bottom } = useSafeAreaInsets();\n\n const { currentUser } = useSendbirdChat();\n const { palette } = useUIKitTheme();\n const { topInset, statusBarTranslucent, defaultHeight } = useHeaderStyle();\n const { STRINGS } = useLocalization();\n const { fileService, mediaService } = usePlatformService();\n const toast = useToast();\n const { alert } = useAlert();\n\n const basicTopInset = statusBarTranslucent ? topInset : 0;\n const canDelete = isMyMessage(fileMessage, currentUser?.userId);\n const fileType = getFileType(fileMessage.type || getFileExtension(fileMessage.url));\n\n useEffect(() => {\n if (fileType === 'file') onClose();\n }, []);\n\n const fileViewer = useIIFE(() => {\n switch (fileType) {\n case 'image': {\n return (\n <Image\n source={{ uri: fileMessage.url }}\n style={StyleSheet.absoluteFill}\n resizeMode={'contain'}\n onLoadEnd={() => setLoading(false)}\n />\n );\n }\n\n case 'video':\n case 'audio': {\n return (\n <mediaService.VideoComponent\n source={{ uri: fileMessage.url }}\n style={[StyleSheet.absoluteFill, { top: basicTopInset + defaultHeight, bottom: defaultHeight + bottom }]}\n resizeMode={'contain'}\n onLoad={() => setLoading(false)}\n />\n );\n }\n\n default: {\n return null;\n }\n }\n });\n\n const _onPressDelete = () => {\n if (!canDelete) return;\n\n if (onPressDelete) {\n onPressDelete(fileMessage);\n } else {\n alert({\n title: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_TITLE,\n buttons: [\n {\n text: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_CANCEL,\n },\n {\n text: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_OK,\n style: 'destructive',\n onPress: () => {\n deleteMessage()\n .then(() => {\n onClose();\n })\n .catch(() => {\n toast.show(STRINGS.TOAST.DELETE_MSG_ERROR, 'error');\n });\n },\n },\n ],\n });\n }\n };\n\n const _onPressDownload = () => {\n if (onPressDownload) {\n onPressDownload(fileMessage);\n } else {\n if (toMegabyte(fileMessage.size) > 4) {\n toast.show(STRINGS.TOAST.DOWNLOAD_START, 'success');\n }\n\n fileService\n .save({ fileUrl: fileMessage.url, fileName: fileMessage.name, fileType: fileMessage.type })\n .then((response) => {\n toast.show(STRINGS.TOAST.DOWNLOAD_OK, 'success');\n Logger.log('File saved to', response);\n })\n .catch((err) => {\n toast.show(STRINGS.TOAST.DOWNLOAD_ERROR, 'error');\n Logger.log('File save failure', err);\n });\n }\n };\n\n return (\n <View style={{ flex: 1, backgroundColor: palette.background700 }}>\n <StatusBar barStyle={'light-content'} animated />\n <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>\n {fileViewer}\n {loading && <LoadingSpinner style={{ position: 'absolute' }} size={40} color={palette.primary300} />}\n </View>\n {headerShown && (\n <FileViewerHeader\n title={STRINGS.FILE_VIEWER.TITLE(fileMessage)}\n subtitle={STRINGS.FILE_VIEWER.SUBTITLE(fileMessage)}\n topInset={headerTopInset ?? basicTopInset}\n onClose={onClose}\n />\n )}\n <FileViewerFooter\n bottomInset={bottom}\n deleteShown={canDelete}\n onPressDelete={_onPressDelete}\n onPressDownload={_onPressDownload}\n />\n </View>\n );\n};\n\ntype HeaderProps = {\n topInset: number;\n onClose: () => void;\n title: string;\n subtitle: string;\n};\nconst FileViewerHeader = ({ topInset, onClose, subtitle, title }: HeaderProps) => {\n const { palette } = useUIKitTheme();\n const { defaultHeight } = useHeaderStyle();\n const { left, right } = useSafeAreaInsets();\n\n return (\n <View\n style={[\n styles.headerContainer,\n {\n paddingLeft: styles.headerContainer.paddingHorizontal + left,\n paddingRight: styles.headerContainer.paddingHorizontal + right,\n },\n { paddingTop: topInset, height: defaultHeight + topInset, backgroundColor: palette.overlay01 },\n ]}\n >\n <TouchableOpacity onPress={onClose} style={styles.barButton}>\n <Icon icon={'close'} size={24} color={palette.onBackgroundDark01} />\n </TouchableOpacity>\n <View style={styles.barTitleContainer}>\n <Text h2 color={palette.onBackgroundDark01} style={styles.headerTitle} numberOfLines={1}>\n {truncate(title, { mode: 'mid', maxLen: 18 })}\n </Text>\n <Text caption2 color={palette.onBackgroundDark01} numberOfLines={1}>\n {subtitle}\n </Text>\n </View>\n <View style={styles.barButton} />\n </View>\n );\n};\n\ntype FooterProps = {\n bottomInset: number;\n deleteShown: boolean;\n onPressDelete: () => void;\n onPressDownload: () => void;\n};\nconst FileViewerFooter = ({ bottomInset, deleteShown, onPressDelete, onPressDownload }: FooterProps) => {\n const { palette } = useUIKitTheme();\n const { defaultHeight } = useHeaderStyle();\n const { left, right } = useSafeAreaInsets();\n\n return (\n <View\n style={[\n styles.footerContainer,\n {\n paddingLeft: styles.headerContainer.paddingHorizontal + left,\n paddingRight: styles.headerContainer.paddingHorizontal + right,\n },\n {\n paddingBottom: bottomInset,\n height: defaultHeight + bottomInset,\n backgroundColor: palette.overlay01,\n },\n ]}\n >\n <TouchableOpacity onPress={onPressDownload} style={styles.barButton}>\n <Icon icon={'download'} size={24} color={palette.onBackgroundDark01} />\n </TouchableOpacity>\n <View style={styles.barTitleContainer} />\n <TouchableOpacity onPress={onPressDelete} style={styles.barButton} disabled={!deleteShown}>\n {deleteShown && <Icon icon={'delete'} size={24} color={palette.onBackgroundDark01} />}\n </TouchableOpacity>\n </View>\n );\n};\n\nconst styles = createStyleSheet({\n headerContainer: {\n top: 0,\n left: 0,\n right: 0,\n position: 'absolute',\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n paddingHorizontal: 12,\n },\n barButton: {\n width: 32,\n height: 32,\n alignItems: 'center',\n justifyContent: 'center',\n },\n barTitleContainer: {\n flex: 1,\n alignItems: 'center',\n justifyContent: 'center',\n },\n headerTitle: {\n marginBottom: 2,\n },\n footerContainer: {\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n paddingHorizontal: 12,\n },\n});\n\nexport default FileViewer;\n"],"mappings":"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"}
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import { StatusBar, StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
3
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
Icon,
|
|
7
|
-
Image,
|
|
8
|
-
LoadingSpinner,
|
|
9
|
-
Text,
|
|
10
|
-
createStyleSheet,
|
|
11
|
-
useAlert,
|
|
12
|
-
useHeaderStyle,
|
|
13
|
-
useToast,
|
|
14
|
-
useUIKitTheme,
|
|
15
|
-
} from '@sendbird/uikit-react-native-foundation';
|
|
16
|
-
import type { SendbirdFileMessage } from '@sendbird/uikit-utils';
|
|
17
|
-
import {
|
|
18
|
-
Logger,
|
|
19
|
-
getFileExtension,
|
|
20
|
-
getFileType,
|
|
21
|
-
isMyMessage,
|
|
22
|
-
toMegabyte,
|
|
23
|
-
truncate,
|
|
24
|
-
useIIFE,
|
|
25
|
-
} from '@sendbird/uikit-utils';
|
|
26
|
-
|
|
27
|
-
import { useLocalization, usePlatformService, useSendbirdChat } from '../hooks/useContext';
|
|
28
|
-
|
|
29
|
-
type Props = {
|
|
30
|
-
fileMessage: SendbirdFileMessage;
|
|
31
|
-
deleteMessage: () => Promise<void>;
|
|
32
|
-
|
|
33
|
-
onClose: () => void;
|
|
34
|
-
onPressDownload?: (message: SendbirdFileMessage) => void;
|
|
35
|
-
onPressDelete?: (message: SendbirdFileMessage) => void;
|
|
36
|
-
|
|
37
|
-
headerShown?: boolean;
|
|
38
|
-
headerTopInset?: number;
|
|
39
|
-
};
|
|
40
|
-
const FileViewer = ({
|
|
41
|
-
headerShown = true,
|
|
42
|
-
deleteMessage,
|
|
43
|
-
headerTopInset,
|
|
44
|
-
fileMessage,
|
|
45
|
-
onPressDownload,
|
|
46
|
-
onPressDelete,
|
|
47
|
-
onClose,
|
|
48
|
-
}: Props) => {
|
|
49
|
-
const [loading, setLoading] = useState(true);
|
|
50
|
-
|
|
51
|
-
const { bottom } = useSafeAreaInsets();
|
|
52
|
-
|
|
53
|
-
const { currentUser } = useSendbirdChat();
|
|
54
|
-
const { palette } = useUIKitTheme();
|
|
55
|
-
const { topInset, statusBarTranslucent, defaultHeight } = useHeaderStyle();
|
|
56
|
-
const { STRINGS } = useLocalization();
|
|
57
|
-
const { fileService, mediaService } = usePlatformService();
|
|
58
|
-
const toast = useToast();
|
|
59
|
-
const { alert } = useAlert();
|
|
60
|
-
|
|
61
|
-
const basicTopInset = statusBarTranslucent ? topInset : 0;
|
|
62
|
-
const canDelete = isMyMessage(fileMessage, currentUser?.userId);
|
|
63
|
-
const fileType = getFileType(fileMessage.type || getFileExtension(fileMessage.url));
|
|
64
|
-
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
if (fileType === 'file') onClose();
|
|
67
|
-
}, []);
|
|
68
|
-
|
|
69
|
-
const fileViewer = useIIFE(() => {
|
|
70
|
-
switch (fileType) {
|
|
71
|
-
case 'image': {
|
|
72
|
-
return (
|
|
73
|
-
<Image
|
|
74
|
-
source={{ uri: fileMessage.url }}
|
|
75
|
-
style={StyleSheet.absoluteFill}
|
|
76
|
-
resizeMode={'contain'}
|
|
77
|
-
onLoadEnd={() => setLoading(false)}
|
|
78
|
-
/>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
case 'video':
|
|
83
|
-
case 'audio': {
|
|
84
|
-
return (
|
|
85
|
-
<mediaService.VideoComponent
|
|
86
|
-
source={{ uri: fileMessage.url }}
|
|
87
|
-
style={[StyleSheet.absoluteFill, { top: basicTopInset + defaultHeight, bottom: defaultHeight + bottom }]}
|
|
88
|
-
resizeMode={'contain'}
|
|
89
|
-
onLoad={() => setLoading(false)}
|
|
90
|
-
/>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
default: {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const _onPressDelete = () => {
|
|
101
|
-
if (!canDelete) return;
|
|
102
|
-
|
|
103
|
-
if (onPressDelete) {
|
|
104
|
-
onPressDelete(fileMessage);
|
|
105
|
-
} else {
|
|
106
|
-
alert({
|
|
107
|
-
title: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_TITLE,
|
|
108
|
-
buttons: [
|
|
109
|
-
{
|
|
110
|
-
text: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_CANCEL,
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
text: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_OK,
|
|
114
|
-
style: 'destructive',
|
|
115
|
-
onPress: () => {
|
|
116
|
-
deleteMessage()
|
|
117
|
-
.then(() => {
|
|
118
|
-
onClose();
|
|
119
|
-
})
|
|
120
|
-
.catch(() => {
|
|
121
|
-
toast.show(STRINGS.TOAST.DELETE_MSG_ERROR, 'error');
|
|
122
|
-
});
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
const _onPressDownload = () => {
|
|
131
|
-
if (onPressDownload) {
|
|
132
|
-
onPressDownload(fileMessage);
|
|
133
|
-
} else {
|
|
134
|
-
if (toMegabyte(fileMessage.size) > 4) {
|
|
135
|
-
toast.show(STRINGS.TOAST.DOWNLOAD_START, 'success');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
fileService
|
|
139
|
-
.save({ fileUrl: fileMessage.url, fileName: fileMessage.name, fileType: fileMessage.type })
|
|
140
|
-
.then((response) => {
|
|
141
|
-
toast.show(STRINGS.TOAST.DOWNLOAD_OK, 'success');
|
|
142
|
-
Logger.log('File saved to', response);
|
|
143
|
-
})
|
|
144
|
-
.catch((err) => {
|
|
145
|
-
toast.show(STRINGS.TOAST.DOWNLOAD_ERROR, 'error');
|
|
146
|
-
Logger.log('File save failure', err);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
return (
|
|
152
|
-
<View style={{ flex: 1, backgroundColor: palette.background700 }}>
|
|
153
|
-
<StatusBar barStyle={'light-content'} animated />
|
|
154
|
-
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
|
155
|
-
{fileViewer}
|
|
156
|
-
{loading && <LoadingSpinner style={{ position: 'absolute' }} size={40} color={palette.primary300} />}
|
|
157
|
-
</View>
|
|
158
|
-
{headerShown && (
|
|
159
|
-
<FileViewerHeader
|
|
160
|
-
title={STRINGS.FILE_VIEWER.TITLE(fileMessage)}
|
|
161
|
-
subtitle={STRINGS.FILE_VIEWER.SUBTITLE(fileMessage)}
|
|
162
|
-
topInset={headerTopInset ?? basicTopInset}
|
|
163
|
-
onClose={onClose}
|
|
164
|
-
/>
|
|
165
|
-
)}
|
|
166
|
-
<FileViewerFooter
|
|
167
|
-
bottomInset={bottom}
|
|
168
|
-
deleteShown={canDelete}
|
|
169
|
-
onPressDelete={_onPressDelete}
|
|
170
|
-
onPressDownload={_onPressDownload}
|
|
171
|
-
/>
|
|
172
|
-
</View>
|
|
173
|
-
);
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
type HeaderProps = {
|
|
177
|
-
topInset: number;
|
|
178
|
-
onClose: () => void;
|
|
179
|
-
title: string;
|
|
180
|
-
subtitle: string;
|
|
181
|
-
};
|
|
182
|
-
const FileViewerHeader = ({ topInset, onClose, subtitle, title }: HeaderProps) => {
|
|
183
|
-
const { palette } = useUIKitTheme();
|
|
184
|
-
const { defaultHeight } = useHeaderStyle();
|
|
185
|
-
const { left, right } = useSafeAreaInsets();
|
|
186
|
-
|
|
187
|
-
return (
|
|
188
|
-
<View
|
|
189
|
-
style={[
|
|
190
|
-
styles.headerContainer,
|
|
191
|
-
{
|
|
192
|
-
paddingLeft: styles.headerContainer.paddingHorizontal + left,
|
|
193
|
-
paddingRight: styles.headerContainer.paddingHorizontal + right,
|
|
194
|
-
},
|
|
195
|
-
{ paddingTop: topInset, height: defaultHeight + topInset, backgroundColor: palette.overlay01 },
|
|
196
|
-
]}
|
|
197
|
-
>
|
|
198
|
-
<TouchableOpacity onPress={onClose} style={styles.barButton}>
|
|
199
|
-
<Icon icon={'close'} size={24} color={palette.onBackgroundDark01} />
|
|
200
|
-
</TouchableOpacity>
|
|
201
|
-
<View style={styles.barTitleContainer}>
|
|
202
|
-
<Text h2 color={palette.onBackgroundDark01} style={styles.headerTitle} numberOfLines={1}>
|
|
203
|
-
{truncate(title, { mode: 'mid', maxLen: 18 })}
|
|
204
|
-
</Text>
|
|
205
|
-
<Text caption2 color={palette.onBackgroundDark01} numberOfLines={1}>
|
|
206
|
-
{subtitle}
|
|
207
|
-
</Text>
|
|
208
|
-
</View>
|
|
209
|
-
<View style={styles.barButton} />
|
|
210
|
-
</View>
|
|
211
|
-
);
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
type FooterProps = {
|
|
215
|
-
bottomInset: number;
|
|
216
|
-
deleteShown: boolean;
|
|
217
|
-
onPressDelete: () => void;
|
|
218
|
-
onPressDownload: () => void;
|
|
219
|
-
};
|
|
220
|
-
const FileViewerFooter = ({ bottomInset, deleteShown, onPressDelete, onPressDownload }: FooterProps) => {
|
|
221
|
-
const { palette } = useUIKitTheme();
|
|
222
|
-
const { defaultHeight } = useHeaderStyle();
|
|
223
|
-
const { left, right } = useSafeAreaInsets();
|
|
224
|
-
|
|
225
|
-
return (
|
|
226
|
-
<View
|
|
227
|
-
style={[
|
|
228
|
-
styles.footerContainer,
|
|
229
|
-
{
|
|
230
|
-
paddingLeft: styles.headerContainer.paddingHorizontal + left,
|
|
231
|
-
paddingRight: styles.headerContainer.paddingHorizontal + right,
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
paddingBottom: bottomInset,
|
|
235
|
-
height: defaultHeight + bottomInset,
|
|
236
|
-
backgroundColor: palette.overlay01,
|
|
237
|
-
},
|
|
238
|
-
]}
|
|
239
|
-
>
|
|
240
|
-
<TouchableOpacity onPress={onPressDownload} style={styles.barButton}>
|
|
241
|
-
<Icon icon={'download'} size={24} color={palette.onBackgroundDark01} />
|
|
242
|
-
</TouchableOpacity>
|
|
243
|
-
<View style={styles.barTitleContainer} />
|
|
244
|
-
<TouchableOpacity onPress={onPressDelete} style={styles.barButton} disabled={!deleteShown}>
|
|
245
|
-
{deleteShown && <Icon icon={'delete'} size={24} color={palette.onBackgroundDark01} />}
|
|
246
|
-
</TouchableOpacity>
|
|
247
|
-
</View>
|
|
248
|
-
);
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
const styles = createStyleSheet({
|
|
252
|
-
headerContainer: {
|
|
253
|
-
top: 0,
|
|
254
|
-
left: 0,
|
|
255
|
-
right: 0,
|
|
256
|
-
position: 'absolute',
|
|
257
|
-
flexDirection: 'row',
|
|
258
|
-
alignItems: 'center',
|
|
259
|
-
justifyContent: 'center',
|
|
260
|
-
paddingHorizontal: 12,
|
|
261
|
-
},
|
|
262
|
-
barButton: {
|
|
263
|
-
width: 32,
|
|
264
|
-
height: 32,
|
|
265
|
-
alignItems: 'center',
|
|
266
|
-
justifyContent: 'center',
|
|
267
|
-
},
|
|
268
|
-
barTitleContainer: {
|
|
269
|
-
flex: 1,
|
|
270
|
-
alignItems: 'center',
|
|
271
|
-
justifyContent: 'center',
|
|
272
|
-
},
|
|
273
|
-
headerTitle: {
|
|
274
|
-
marginBottom: 2,
|
|
275
|
-
},
|
|
276
|
-
footerContainer: {
|
|
277
|
-
position: 'absolute',
|
|
278
|
-
left: 0,
|
|
279
|
-
right: 0,
|
|
280
|
-
bottom: 0,
|
|
281
|
-
flexDirection: 'row',
|
|
282
|
-
alignItems: 'center',
|
|
283
|
-
justifyContent: 'center',
|
|
284
|
-
paddingHorizontal: 12,
|
|
285
|
-
},
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
export default FileViewer;
|