@smart-link/rn-im 1.0.24 → 1.0.26

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 (40) hide show
  1. package/assets/file-dir.jpg +0 -0
  2. package/dist/components/ChatAvatar/ChatAvatarLocal.js +0 -1
  3. package/dist/default-assets.d.ts +1 -0
  4. package/dist/default-assets.js +1 -0
  5. package/dist/interface.d.ts +9 -0
  6. package/dist/pages/conversation/setting/OptionAvatars.d.ts +1 -1
  7. package/dist/pages/conversation/setting/OptionGroup.d.ts +1 -1
  8. package/dist/pages/conversation/setting/Setting.js +2 -3
  9. package/dist/pages/message/FileSelector.d.ts +6 -0
  10. package/dist/pages/message/FileSelector.js +235 -0
  11. package/dist/pages/message/MessageList.js +19 -15
  12. package/dist/pages/message/MessageRecord.js +33 -22
  13. package/dist/pages/message/components/MessageItem.d.ts +2 -1
  14. package/dist/pages/message/components/MessageItem.js +6 -5
  15. package/dist/pages/message/components/MessageOption.d.ts +7 -3
  16. package/dist/pages/message/components/MessageOption.js +13 -16
  17. package/dist/pages/message/components/MessagePayload.d.ts +2 -1
  18. package/dist/pages/message/components/Payload/PayloadFile.d.ts +1 -1
  19. package/dist/pages/message/components/Payload/PayloadFile.js +11 -11
  20. package/dist/pages/message/components/Payload/PayloadMultiple.js +9 -5
  21. package/dist/pages/message/components/Payload/PayloadPicture.d.ts +1 -1
  22. package/dist/pages/message/components/Payload/PayloadPicture.js +3 -4
  23. package/dist/pages/message/components/Payload/PayloadVideo.js +2 -1
  24. package/dist/pages/message/components/Payload/PayloadVoice.js +1 -1
  25. package/dist/pages/message/components/Payload/PayloadWrapper.d.ts +2 -1
  26. package/dist/pages/message/components/Payload/PayloadWrapper.js +8 -3
  27. package/dist/pages/message/components/Payload/type.d.ts +2 -1
  28. package/dist/pages/message/components/ReceiptBack.js +2 -2
  29. package/dist/pages/message/components/TextMixQuote.js +7 -12
  30. package/dist/pages/message/components/TextMixQuoteMessage.js +3 -3
  31. package/dist/pages/message/components/messageBar/OptionPanel.js +6 -31
  32. package/dist/pages/message/message.routes.js +10 -0
  33. package/dist/pages/types.d.ts +4 -2
  34. package/dist/slice/video/video.action.js +9 -1
  35. package/dist/utils/file.d.ts +10 -2
  36. package/dist/utils/file.js +140 -27
  37. package/dist/utils/upload.js +1 -1
  38. package/package.json +2 -2
  39. package/dist/slice/contact/contact.action.d.ts +0 -1
  40. package/dist/slice/contact/contact.action.js +0 -1
@@ -11,26 +11,27 @@ import { dp, Toast } from '@smart-link/rn-ui';
11
11
  import FileViewer from 'react-native-file-viewer';
12
12
  import React, { memo, useRef, useState } from 'react';
13
13
  import { View, Text, StyleSheet, Dimensions, } from 'react-native';
14
- import { numberToFileSize } from '../../../../utils/file';
14
+ import { numberToFileSize, toAbsolutePath } from '../../../../utils/file';
15
15
  import { MessageStatus } from '@smart-link/im-base';
16
16
  import UploadProgress from '../UploadProgress';
17
17
  import { getImManager } from '../../../../init';
18
18
  import PayloadWrapper from './PayloadWrapper';
19
19
  import { findSvgIcon } from '../../../../utils/file-icon';
20
20
  import useTranslation from "../../../../hooks/useTranslation";
21
- const PayloadFile = ({ payload, messageSeq, direction, showArrow = true, isRecord, messageStatus, sendSize, style, onLongPress }) => {
21
+ const PayloadFile = ({ payload, messageSeq, direction, showArrow = true, isRecord, messageStatus, jobId, sendSize, style, onLongPress }) => {
22
22
  const ext = payload.filename.split('.').pop();
23
23
  const Icon = findSvgIcon(ext);
24
24
  const path = useRef('');
25
25
  const downloading = useRef(false);
26
26
  const { t } = useTranslation();
27
+ const width = Dimensions.get('window').width * 0.75 - dp(24);
27
28
  const [download, setDownload] = useState({
28
29
  progress: 0,
29
30
  status: 'pending',
30
31
  });
31
32
  const openWithLocal = (path) => __awaiter(void 0, void 0, void 0, function* () {
32
33
  try {
33
- yield FileViewer.open(path);
34
+ yield FileViewer.open(toAbsolutePath(path));
34
35
  }
35
36
  catch (e) {
36
37
  Toast.warning(t('fileOpenFail'));
@@ -48,7 +49,7 @@ const PayloadFile = ({ payload, messageSeq, direction, showArrow = true, isRecor
48
49
  onProgress: (e) => {
49
50
  setDownload({
50
51
  progress: e.loaded,
51
- status: 'downloading',
52
+ status: e.loaded === payload.size ? 'done' : 'downloading',
52
53
  });
53
54
  }
54
55
  });
@@ -103,25 +104,24 @@ const PayloadFile = ({ payload, messageSeq, direction, showArrow = true, isRecor
103
104
  yield openWithLocal(localPath);
104
105
  }
105
106
  });
106
- return (<PayloadWrapper direction={direction} showArrow={showArrow} onLongPress={onLongPress} style={[style, styles.file]} onPress={pressFile}>
107
+ return (<PayloadWrapper direction={direction} showArrow={showArrow} onLongPress={onLongPress} style={[style, styles.file, { width: width + dp(12) }]} onPress={pressFile}>
107
108
  <View style={{ flexDirection: 'row', alignItems: 'center', flex: 1 }}>
108
109
  <Icon style={styles.fileIcon}/>
109
110
  <View style={{ flex: 1 }}>
110
111
  <Text numberOfLines={1} ellipsizeMode="middle">{payload.filename}</Text>
111
- <Text style={styles.size}>{numberToFileSize(payload.size)}{payload.localPath ? t('downloaded') : ''}</Text>
112
+ <Text style={styles.size}>{numberToFileSize(payload.size)} {payload.localPath ? t('downloaded') : ''}</Text>
112
113
  </View>
113
114
  </View>
114
- <UploadProgress show={download.status === 'downloading'} width={200} sendSize={download.progress} totalSize={payload.size}/>
115
- <UploadProgress show={messageStatus === MessageStatus.EMITTING} width={200} sendSize={sendSize || 0} totalSize={payload.size}/>
115
+ <UploadProgress show={download.status === 'downloading'} width={width} sendSize={download.progress} totalSize={payload.size}/>
116
+ <UploadProgress show={messageStatus === MessageStatus.EMITTING || Boolean(jobId)} width={width} sendSize={sendSize || 0} totalSize={payload.size}/>
116
117
  </PayloadWrapper>);
117
118
  };
118
119
  const styles = StyleSheet.create({
119
120
  file: {
120
- minWidth: 200,
121
+ flexDirection: 'column',
121
122
  alignItems: 'center',
122
123
  padding: dp(6),
123
- borderRadius: dp(8),
124
- width: Dimensions.get('window').width * 0.75,
124
+ borderRadius: dp(8)
125
125
  },
126
126
  fileIcon: {
127
127
  marginRight: dp(8),
@@ -1,7 +1,7 @@
1
1
  import { borderStyle, shadowStyle } from '../../../../components/styles';
2
2
  import useTranslation from '../../../../hooks/useTranslation';
3
3
  import { getImManager } from '../../../../init';
4
- import { buildSimpleText, ConversationType } from '@smart-link/im-base';
4
+ import { buildSimpleText, ConversationType, MessageListActions } from '@smart-link/im-base';
5
5
  import { dp, useNavigation } from '@smart-link/rn-ui';
6
6
  import React, { memo } from 'react';
7
7
  import { View, StyleSheet, Text, Dimensions } from 'react-native';
@@ -17,10 +17,14 @@ const PayloadMultiple = memo(({ payload, messageSeq, direction, showArrow = true
17
17
  ? t('multipleChatRecordTitle', { fromName, toName })
18
18
  : t('multipleChatRecordTitleGroup');
19
19
  return (<PayloadWrapper direction={direction} showArrow={showArrow} style={[style, styles.wrap]} onPress={() => {
20
- navigation.navigate('MessageRecord', {
21
- messageSeq,
22
- messages: selectedMessages,
23
- title,
20
+ imManager.store.dispatch(MessageListActions.addMessageListData(imManager, messageSeq, selectedMessages));
21
+ navigation.navigate({
22
+ name: 'MessageRecord',
23
+ key: Date.now().toString(),
24
+ params: {
25
+ messageSeq,
26
+ title,
27
+ },
24
28
  });
25
29
  }} onLongPress={onLongPress}>
26
30
  <Text style={styles.titleText} numberOfLines={2}>
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { PayloadProps } from "./type";
3
- declare const _default: React.MemoExoticComponent<({ payload, onLoad, ...retProps }: PayloadProps) => React.JSX.Element>;
3
+ declare const _default: React.MemoExoticComponent<({ payload, onLoad, isRecord, ...retProps }: PayloadProps) => React.JSX.Element>;
4
4
  export default _default;
@@ -17,13 +17,12 @@ import { borderStyle, shadowStyle } from '../../../../components/styles';
17
17
  import { dp } from '@smart-link/rn-ui';
18
18
  import PayloadWrapper from './PayloadWrapper';
19
19
  import Image from 'react-native-fast-image';
20
- import useDownloadSource from "../../../../hooks/useDownloadSource";
21
20
  import { toAbsolutePath } from "../../../../utils/file";
22
21
  const { width: screenWidth } = Dimensions.get('window');
23
22
  const PayloadPicture = (_a) => {
24
- var { payload, onLoad } = _a, retProps = __rest(_a, ["payload", "onLoad"]);
23
+ var { payload, onLoad, isRecord } = _a, retProps = __rest(_a, ["payload", "onLoad", "isRecord"]);
25
24
  const ext = payload.filename.split('.').pop();
26
- const localPath = useDownloadSource(payload);
25
+ const { localPath } = payload;
27
26
  useEffect(() => {
28
27
  if (localPath) {
29
28
  onLoad === null || onLoad === void 0 ? void 0 : onLoad(localPath);
@@ -35,7 +34,7 @@ const PayloadPicture = (_a) => {
35
34
  }
36
35
  let content;
37
36
  if (/svg/i.test(ext)) {
38
- content = <SvgFromUri style={[borderStyle]} uri={localPath} viewBox={'0 0 1024 1024'} width={screenWidth * 0.4} height={screenWidth * 0.4}/>;
37
+ content = <SvgFromUri style={[borderStyle]} uri={toAbsolutePath(localPath)} viewBox={'0 0 1024 1024'} width={screenWidth * 0.4} height={screenWidth * 0.4}/>;
39
38
  }
40
39
  else {
41
40
  content = <Image resizeMode="cover" style={[borderStyle, size]} source={{
@@ -11,10 +11,11 @@ import UploadProgress from '../UploadProgress';
11
11
  import PayloadWrapper from './PayloadWrapper';
12
12
  import { getImManager } from '../../../../init';
13
13
  import Image from 'react-native-fast-image';
14
+ import { toAbsolutePath } from "../../../../utils/file";
14
15
  const PayloadVideo = ({ messageStatus, messageSeq, payload, sendSize = 0, isRecord, onLongPress }) => {
15
16
  const { width, height } = payload;
16
17
  const size = calculate(height || dp(163), width || dp(100));
17
- const thumbnail = payload.imagePath ? { uri: 'file://' + payload.imagePath }
18
+ const thumbnail = payload.imagePath ? { uri: toAbsolutePath(payload.imagePath) }
18
19
  : { uri: getDownloadUrl(payload.imageFileId) };
19
20
  return (<PayloadWrapper style={[styles.root, shadowStyle, borderStyle, size]} onPress={() => {
20
21
  getImManager().store.dispatch(loadVideoPlayer({
@@ -83,7 +83,7 @@ const PayloadVoice = ({ payload, direction, style, messageSeq, showArrow = true,
83
83
  return;
84
84
  }
85
85
  else {
86
- const isExist = yield RNFS.exists(payload.localPath);
86
+ const isExist = yield RNFS.exists(toAbsolutePath(payload.localPath));
87
87
  if (!isExist) {
88
88
  console.log('path not exists');
89
89
  const destPath = yield download();
@@ -1,12 +1,13 @@
1
1
  import React from 'react';
2
2
  import { GestureResponderEvent } from 'react-native';
3
+ import { NativeEventLayout } from "../../../types";
3
4
  export interface PayloadWrapperProps {
4
5
  showArrow?: boolean;
5
6
  direction?: 'left' | 'right';
6
7
  children: React.ReactNode;
7
8
  style?: any;
8
9
  onPress?: (e: GestureResponderEvent) => void;
9
- onLongPress?: (e: GestureResponderEvent) => void;
10
+ onLongPress?: (e: GestureResponderEvent, layout: NativeEventLayout) => void;
10
11
  }
11
12
  declare const PayloadWrapper: React.NamedExoticComponent<PayloadWrapperProps>;
12
13
  export default PayloadWrapper;
@@ -10,11 +10,16 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { dp } from '@smart-link/rn-ui';
13
- import React, { memo } from 'react';
13
+ import React, { memo, useState } from 'react';
14
14
  import { View, StyleSheet, TouchableOpacity } from 'react-native';
15
15
  const PayloadWrapper = memo((_a) => {
16
- var { children, direction, showArrow } = _a, retProps = __rest(_a, ["children", "direction", "showArrow"]);
17
- return (<TouchableOpacity {...retProps}>
16
+ var { children, direction, showArrow, onLongPress } = _a, retProps = __rest(_a, ["children", "direction", "showArrow", "onLongPress"]);
17
+ const [layout, setLayout] = useState();
18
+ return (<TouchableOpacity {...retProps} onLayout={e => {
19
+ setLayout(e.nativeEvent.layout);
20
+ }} onLongPress={(e) => {
21
+ onLongPress && onLongPress(e, layout);
22
+ }}>
18
23
  {showArrow && (<View style={[styles.arrow, direction === 'right' ? styles.rightArrow : styles.leftArrow]}/>)}
19
24
  {children}
20
25
  </TouchableOpacity>);
@@ -1,11 +1,12 @@
1
1
  import { IMessage } from "@smart-link/im-base";
2
2
  import { GestureResponderEvent, StyleProp, ViewStyle } from "react-native";
3
+ import { NativeEventLayout } from "../../../types";
3
4
  export interface PayloadProps extends IMessage {
4
5
  style?: StyleProp<ViewStyle>;
5
6
  direction?: 'left' | 'right';
6
7
  showArrow?: boolean;
7
8
  isRecord?: boolean;
8
9
  onPress?: (e: GestureResponderEvent) => void;
9
- onLongPress?: (e: GestureResponderEvent) => void;
10
+ onLongPress?: (e: GestureResponderEvent, layout: NativeEventLayout) => void;
10
11
  onLoad?: (localPath: string) => void;
11
12
  }
@@ -6,11 +6,11 @@ import useTranslation from "../../../hooks/useTranslation";
6
6
  import dayjs from "dayjs";
7
7
  export const ReceiptBack = ({ message }) => {
8
8
  const { t } = useTranslation();
9
- // console.log('ReceiptBack: '', message.receiptBackList.length, message.receiptBackList);
9
+ // console.log('ReceiptBack: ', message.receiptBackList.length, message.receiptBackList);
10
10
  return (<View style={styles.content}>
11
11
  <View style={{ flexDirection: 'row' }}>
12
12
  <Text style={[styles.text, { width: dp(165) }]}>
13
- {dayjs(message.messageTime).format('YYYY-MM-DD hh:mm:ss')}
13
+ {dayjs(message.messageTime).format('YYYY-MM-DD HH:mm:ss')}
14
14
  </Text>
15
15
  <Text style={styles.text}>{message.messageStatus === MessageStatus.EMIT_ERROR ? t('sendFail') : t('sent')}</Text>
16
16
  </View>
@@ -11,7 +11,6 @@ import LocalImage from '../../../components/LocalImage';
11
11
  import useTranslation from '../../../hooks/useTranslation';
12
12
  import { getImManager } from '../../../init';
13
13
  import PayloadFile from './Payload/PayloadFile';
14
- import useDownloadSource, { useDownloadImgSource } from "../../../hooks/useDownloadSource";
15
14
  const voiceLeft = require('../../../../assets/voice-left.png');
16
15
  const { width } = Dimensions.get('window');
17
16
  export const QuoteTextMix = memo(props => {
@@ -27,10 +26,8 @@ export const QuoteTextMix = memo(props => {
27
26
  });
28
27
  export const QuotePicture = memo(props => {
29
28
  const { quoteTitle, quoteMessage, quoteStyle, color, textStyle, borderColor, backgroundColor, onPressQuote } = props;
30
- const { height, width } = quoteMessage.payload;
29
+ const { height, width, localPath } = quoteMessage.payload;
31
30
  const theme = useTheme();
32
- console.log('QuotePicture', quoteMessage);
33
- const localImg = useDownloadSource(quoteMessage.payload);
34
31
  const sizeStyle = calculate(height || 100, width || 61.8, 100);
35
32
  return (<TouchableOpacity activeOpacity={0.5} onPress={onPressQuote} style={[quoteStyle, styles.leftBorder, { backgroundColor: dark(color, 6) }]}>
36
33
  <Text style={[textStyle, styles.replyUserName]}>
@@ -38,7 +35,7 @@ export const QuotePicture = memo(props => {
38
35
  {' : '}
39
36
  </Text>
40
37
  <View style={styles.h5}/>
41
- {(!localImg) && (<View style={[
38
+ {(!localPath) && (<View style={[
42
39
  styles.pictureEmpty,
43
40
  Object.assign({ backgroundColor,
44
41
  borderColor }, sizeStyle),
@@ -47,23 +44,21 @@ export const QuotePicture = memo(props => {
47
44
  <ActivityIndicator color={theme.primaryColor} animating={true}/>
48
45
  </View>)}
49
46
 
50
- {localImg && (<LocalImage style={sizeStyle} resizeMode="cover" localPath={localImg}/>)}
47
+ {localPath && (<LocalImage style={sizeStyle} resizeMode="cover" localPath={localPath}/>)}
51
48
  </TouchableOpacity>);
52
49
  });
53
50
  export const QuoteVideo = memo(props => {
54
51
  const { quoteTitle, quoteMessage, quoteStyle, color, textStyle, borderColor, backgroundColor, onPressQuote } = props;
55
- const { duration, height, width } = quoteMessage.payload;
52
+ const { duration, height, width, imagePath } = quoteMessage.payload;
56
53
  const theme = useTheme();
57
- console.log('QuoteVideo: ', quoteMessage);
58
54
  const sizeStyle = calculate(height, width);
59
- const localImg = useDownloadImgSource(quoteMessage.payload);
60
55
  return (<TouchableOpacity activeOpacity={0.5} onPress={onPressQuote} style={[quoteStyle, styles.leftBorder, { backgroundColor: dark(color, 6) }]}>
61
56
  <Text style={[textStyle, styles.replyUserName]}>
62
57
  {quoteTitle}
63
58
  {' : '}
64
59
  </Text>
65
60
  <View style={styles.h5}/>
66
- {(!localImg) && (<View style={[
61
+ {(!imagePath) && (<View style={[
67
62
  styles.pictureEmpty,
68
63
  Object.assign({ backgroundColor,
69
64
  borderColor }, sizeStyle),
@@ -72,8 +67,8 @@ export const QuoteVideo = memo(props => {
72
67
  <ActivityIndicator color={theme.primaryColor} animating={true}/>
73
68
  </View>)}
74
69
 
75
- {localImg && (<View style={{ width: sizeStyle.width }}>
76
- <LocalImage style={sizeStyle} resizeMode="cover" localPath={localImg}/>
70
+ {imagePath && (<View style={{ width: sizeStyle.width }}>
71
+ <LocalImage style={sizeStyle} resizeMode="cover" localPath={imagePath}/>
77
72
  <View style={styles.playView}>
78
73
  <AntDesign size={30} name="playcircleo" color="#fff"/>
79
74
  </View>
@@ -20,15 +20,15 @@ const TextMixQuoteMessage = memo(props => {
20
20
  }}/>)}
21
21
 
22
22
  {quotePayloadType === PICTURE && (<QuotePicture quoteTitle={quote.quoteTitle} quoteMessage={quote.quoteMessage} quoteStyle={quoteStyle} color={quoteBgColor} textStyle={textStyle} backgroundColor={quoteBgColor} borderColor={quoteBgColor} onPressQuote={() => {
23
- onPressQuote && onPressQuote(quoteMessageSeq);
23
+ onPressQuote === null || onPressQuote === void 0 ? void 0 : onPressQuote(quoteMessageSeq);
24
24
  }}/>)}
25
25
 
26
26
  {quotePayloadType === VIDEO && (<QuoteVideo quoteTitle={quote.quoteTitle} quoteMessage={quote.quoteMessage} quoteStyle={quoteStyle} color={quoteBgColor} textStyle={textStyle} backgroundColor={quoteBgColor} borderColor={quoteBgColor} onPressQuote={() => {
27
- onPressQuote && onPressQuote(quoteMessageSeq);
27
+ onPressQuote === null || onPressQuote === void 0 ? void 0 : onPressQuote(quoteMessageSeq);
28
28
  }}/>)}
29
29
 
30
30
  {quotePayloadType === FILE && (<QuoteFile quoteTitle={quote.quoteTitle} quoteMessage={quote.quoteMessage} color={quoteBgColor} textStyle={textStyle} onPressQuote={() => {
31
- onPressQuote && onPressQuote(quoteMessageSeq);
31
+ onPressQuote === null || onPressQuote === void 0 ? void 0 : onPressQuote(quoteMessageSeq);
32
32
  }}/>)}
33
33
 
34
34
  {quotePayloadType === VOICE && (<QuoteVoice quoteTitle={quote.quoteTitle} quoteMessage={quote.quoteMessage} color={quoteBgColor} textStyle={textStyle} onPressQuote={() => {
@@ -7,8 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { dp, Toast, useNavigation } from '@smart-link/rn-ui';
11
- import * as DocumentPicker from '@react-native-documents/picker';
10
+ import { dp, useNavigation } from '@smart-link/rn-ui';
12
11
  import React, { forwardRef, memo, useImperativeHandle, useState } from 'react';
13
12
  import { View, Text, FlatList, TouchableOpacity, Dimensions, StyleSheet, Animated } from 'react-native';
14
13
  import { useConversation } from '../../../../hooks/useImSelector';
@@ -17,7 +16,7 @@ import { getImManager } from '../../../../init';
17
16
  import { FileIcon, PhotosIcon, ShootingIcon, UserIcon } from './Icons';
18
17
  import ImagePicker from 'react-native-image-crop-picker';
19
18
  import { startSendContact } from '../../../../slice/contact/contact.slice';
20
- import { copyFile, getExtensionFromMime } from '../../../../utils/file';
19
+ import { copyFile } from '../../../../utils/file';
21
20
  import { scrollToBottom } from '../../../../utils/scroll';
22
21
  import { takeCamera } from '../../../../utils/take-camera';
23
22
  import FontAwesome from "react-native-vector-icons/FontAwesome";
@@ -63,8 +62,8 @@ const OptionPanel = forwardRef((props, ref) => {
63
62
  compressImageMaxWidth: 1080,
64
63
  });
65
64
  console.log(images);
66
- images.map(item => {
67
- sendPicture({
65
+ for (const item of images) {
66
+ yield sendPicture({
68
67
  filename: item.filename,
69
68
  size: item.size,
70
69
  localPath: item.path,
@@ -73,7 +72,7 @@ const OptionPanel = forwardRef((props, ref) => {
73
72
  width: item.width,
74
73
  height: item.height,
75
74
  });
76
- });
75
+ }
77
76
  }
78
77
  catch (e) {
79
78
  console.log(e);
@@ -89,31 +88,7 @@ const OptionPanel = forwardRef((props, ref) => {
89
88
  });
90
89
  const pickFile = () => __awaiter(void 0, void 0, void 0, function* () {
91
90
  try {
92
- const files = yield DocumentPicker.pick({
93
- type: [DocumentPicker.types.allFiles],
94
- });
95
- const fileInfo = files[0];
96
- console.log('chooseFile: ', fileInfo);
97
- if (!fileInfo.uri) {
98
- Toast.error(t("failedToObtainFilePath"));
99
- return;
100
- }
101
- const ext = getExtensionFromMime(fileInfo.type);
102
- if (!ext) {
103
- Toast.error(t("unsupportedFileTypes"));
104
- return;
105
- }
106
- if (!fileInfo.name.endsWith(ext)) {
107
- fileInfo.name = fileInfo.name + ext;
108
- }
109
- yield sendFile({
110
- // ios 中文名称编码了,需要解码
111
- localPath: decodeURI(fileInfo.uri),
112
- filename: fileInfo.name,
113
- size: fileInfo.size,
114
- type: fileInfo.type,
115
- lastModified: Date.now(),
116
- });
91
+ navigation.navigate('FileSelector');
117
92
  }
118
93
  catch (e) {
119
94
  console.log(e);
@@ -2,6 +2,7 @@ import MessageList from './MessageList';
2
2
  import ChooseMember from './ChooseMember';
3
3
  import MessageRecord from './MessageRecord';
4
4
  import MessageBackup, { StartBackupPage, RestoreBackupPage } from './MessageBackup';
5
+ import FileSelector from "./FileSelector";
5
6
  export const messageRoutes = [
6
7
  {
7
8
  name: 'MessageList',
@@ -26,6 +27,15 @@ export const messageRoutes = [
26
27
  title: '',
27
28
  },
28
29
  },
30
+ {
31
+ name: 'FileSelector',
32
+ component: FileSelector,
33
+ options: {
34
+ title: '',
35
+ animation: 'fade_from_bottom',
36
+ animationDuration: 150,
37
+ },
38
+ },
29
39
  {
30
40
  name: 'MessageBackup',
31
41
  component: MessageBackup,
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
- import { IConversation, IMessage } from '@smart-link/im-base';
2
+ import { IConversation } from '@smart-link/im-base';
3
3
  import { IGroupCategory } from '../interface';
4
+ import { LayoutChangeEvent } from "react-native";
4
5
  type StackAnimationTypes = 'default' | 'fade' | 'fade_from_bottom' | 'flip' | 'none' | 'simple_push' | 'slide_from_bottom' | 'slide_from_right' | 'slide_from_left';
5
6
  export type IMPageParamList = {
6
7
  ScanCode: undefined;
@@ -54,9 +55,9 @@ export type IMPageParamList = {
54
55
  OptionGroupManage: undefined;
55
56
  MessageRecord: {
56
57
  messageSeq: string;
57
- messages: IMessage[];
58
58
  title: string;
59
59
  };
60
+ FileSelector: undefined;
60
61
  };
61
62
  export type RouteConfig = {
62
63
  name: string;
@@ -68,4 +69,5 @@ export type RouteConfig = {
68
69
  animationDuration?: number;
69
70
  };
70
71
  };
72
+ export type NativeEventLayout = LayoutChangeEvent['nativeEvent']['layout'];
71
73
  export {};
@@ -12,13 +12,14 @@ import { setVideoDownloadProgress, showVideoPlayer, setVideoDownloadError, cance
12
12
  import { dp } from '@smart-link/rn-ui';
13
13
  import { getDownloadUrl } from '../../api/file';
14
14
  import { getImManager } from '../../init';
15
+ import { toAbsolutePath } from "../../utils/file";
15
16
  let stopFn = () => { };
16
17
  export const loadVideoPlayer = message => (dispatch) => __awaiter(void 0, void 0, void 0, function* () {
17
18
  console.log('loadVideoPlayer: ', message);
18
19
  const { payload, messageSeq, isRecord } = message;
19
20
  const { width = dp(100), height = dp(163), localPath } = payload;
20
21
  const thumbnail = payload.imagePath
21
- ? { uri: 'file://' + payload.imagePath }
22
+ ? { uri: toAbsolutePath(payload.imagePath) }
22
23
  : { uri: getDownloadUrl(payload.imageFileId) };
23
24
  const imManager = getImManager();
24
25
  const download = () => __awaiter(void 0, void 0, void 0, function* () {
@@ -28,6 +29,7 @@ export const loadVideoPlayer = message => (dispatch) => __awaiter(void 0, void 0
28
29
  resourceType: 'video',
29
30
  filename: payload.filename || (payload.fileId + '.mp4'),
30
31
  onProgress(o) {
32
+ console.log('download video: ', o);
31
33
  dispatch(setVideoDownloadProgress(o.loaded / Number(o.total || payload.size)));
32
34
  },
33
35
  onStart: (stop) => {
@@ -70,6 +72,12 @@ export const loadVideoPlayer = message => (dispatch) => __awaiter(void 0, void 0
70
72
  }
71
73
  else if (!localPath && isRecord) {
72
74
  // 下载文件,缓存资源
75
+ dispatch(showVideoPlayer({
76
+ videoLocalPath: '',
77
+ videoImageHeight: height,
78
+ videoImageWidth: width,
79
+ videoImagePath: thumbnail.uri,
80
+ }));
73
81
  let destPath = yield imManager.loadResourceFromCache(payload.fileId);
74
82
  console.log('video cache: ', destPath);
75
83
  if (!destPath) {
@@ -1,4 +1,5 @@
1
1
  import { IUser, IDownloadOptions, ImManager, ResourceType } from '@smart-link/im-base';
2
+ import { IPathItem } from "../interface";
2
3
  declare const resourceDirBase: {
3
4
  readonly avatars: "/avatars";
4
5
  readonly voice: "/voice";
@@ -14,10 +15,17 @@ export declare function toAbsolutePath(filePath: string): string;
14
15
  export declare function toRelativePath(filePath: string): string;
15
16
  export declare const numberToFileSize: (number: number) => string;
16
17
  export declare const moveFile: (filePath: string, filename: string, resourceType: ResourceDir) => Promise<string>;
17
- export declare const copyFile: (localPath: string, filename: string, resourceType?: ResourceDir) => Promise<string>;
18
+ export declare const copyFile: (localPath: string, filename: string, resourceType: ResourceDir) => Promise<string>;
18
19
  export declare const getSuffix: (filename: string) => string;
19
- export declare const download: ({ fileId, fileSize, resourceType, filename, onProgress, onStart }: IDownloadOptions) => Promise<string>;
20
+ export declare const download: ({ fileId, resourceType, filename, onProgress, onStart }: IDownloadOptions) => Promise<string>;
20
21
  export declare function saveToAlbum(imManager: ImManager, localPath: string, showTips?: boolean): Promise<boolean>;
21
22
  export declare function requestSaveFilePermissionIfAndroid(imManager: ImManager): Promise<boolean>;
22
23
  export declare function getExtensionFromMime(mime: string): string;
24
+ export declare function selectFile(imManager: ImManager, filePath: string, filename: string): Promise<string | undefined>;
25
+ export declare function readFileDir(imManager: ImManager, path: string, keyword?: string): Promise<IPathItem[]>;
26
+ export declare function getChildrenCount(imManager: ImManager, isDir: boolean, path: string): Promise<number>;
27
+ export declare function getFileRootItem(imManager: ImManager): Promise<IPathItem[]>;
28
+ export declare function createRootItem(imManager: ImManager, name: string, path: string): Promise<IPathItem>;
29
+ export declare function getFileType(path: string): string;
30
+ export declare function isImage(path: string): boolean;
23
31
  export {};