@smart-link/rn-im 1.0.24 → 1.1.1

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 (125) hide show
  1. package/assets/file-dir.jpg +0 -0
  2. package/dist/api/addressList.d.ts +16 -15
  3. package/dist/api/addressList.js +15 -1
  4. package/dist/api/user.js +1 -1
  5. package/dist/components/Camera/Camera.js +3 -2
  6. package/dist/components/Camera/CameraCapture.js +61 -12
  7. package/dist/components/ChatAvatar/ChatAvatar.d.ts +3 -3
  8. package/dist/components/ChatAvatar/ChatAvatar.js +51 -49
  9. package/dist/components/ChatAvatar/ChatAvatarId.d.ts +2 -2
  10. package/dist/components/ChatAvatar/ChatAvatarId.js +19 -46
  11. package/dist/components/ChatAvatar/ChatAvatarLocal.js +22 -10
  12. package/dist/components/Favicon.js +1 -1
  13. package/dist/components/LocalImage.js +3 -1
  14. package/dist/components/styles.d.ts +7 -1
  15. package/dist/components/styles.js +16 -11
  16. package/dist/default-assets.d.ts +1 -0
  17. package/dist/default-assets.js +1 -0
  18. package/dist/hooks/useAnimatedValue.d.ts +2 -0
  19. package/dist/hooks/useAnimatedValue.js +9 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +1 -0
  22. package/dist/init.d.ts +2 -2
  23. package/dist/init.js +8 -5
  24. package/dist/interface.d.ts +15 -0
  25. package/dist/pages/address-list/AddressList.js +22 -40
  26. package/dist/pages/address-list/ChooseContact.js +209 -45
  27. package/dist/pages/address-list/MyGroups.d.ts +6 -0
  28. package/dist/pages/address-list/MyGroups.js +90 -0
  29. package/dist/pages/address-list/Organization.d.ts +0 -7
  30. package/dist/pages/address-list/Organization.js +24 -108
  31. package/dist/pages/address-list/UserDetail.js +5 -5
  32. package/dist/pages/address-list/UserSearch.js +6 -7
  33. package/dist/pages/address-list/addressList.routes.d.ts +9 -0
  34. package/dist/pages/address-list/addressList.routes.js +8 -0
  35. package/dist/pages/address-list/components/Icons.d.ts +8 -0
  36. package/dist/pages/address-list/components/Icons.js +15 -0
  37. package/dist/pages/address-list/components/OrgPath.d.ts +12 -0
  38. package/dist/pages/address-list/components/OrgPath.js +59 -0
  39. package/dist/pages/address-list/components/RenderUserItem.d.ts +9 -0
  40. package/dist/pages/address-list/components/RenderUserItem.js +14 -0
  41. package/dist/pages/address-list/{UserJobs.js → components/UserJobs.js} +2 -2
  42. package/dist/pages/address-list/useGroupCategory.d.ts +2 -0
  43. package/dist/pages/address-list/useGroupCategory.js +11 -0
  44. package/dist/pages/address-list/useRoleList.d.ts +2 -0
  45. package/dist/pages/address-list/useRoleList.js +11 -0
  46. package/dist/pages/collection/Collection.js +52 -8
  47. package/dist/pages/collection/ContentFactory.js +50 -3
  48. package/dist/pages/conversation/ForwardToConversation.js +4 -2
  49. package/dist/pages/conversation/List.js +15 -7
  50. package/dist/pages/conversation/components/ConversationCard.js +1 -7
  51. package/dist/pages/conversation/setting/OptionAvatars.d.ts +1 -1
  52. package/dist/pages/conversation/setting/OptionAvatars.js +0 -1
  53. package/dist/pages/conversation/setting/OptionGroup.d.ts +2 -2
  54. package/dist/pages/conversation/setting/OptionGroup.js +4 -4
  55. package/dist/pages/conversation/setting/OptionGroupManage.js +4 -8
  56. package/dist/pages/conversation/setting/OptionGroupMoreMember.js +37 -18
  57. package/dist/pages/conversation/setting/Setting.js +5 -5
  58. package/dist/pages/conversation/setting/SettingChatBg.js +32 -16
  59. package/dist/pages/message/ChooseMember.js +2 -2
  60. package/dist/pages/message/FileSelector.d.ts +6 -0
  61. package/dist/pages/message/FileSelector.js +272 -0
  62. package/dist/pages/message/MessageList.js +81 -43
  63. package/dist/pages/message/MessageRecord.js +34 -23
  64. package/dist/pages/message/components/MessageItem.d.ts +7 -7
  65. package/dist/pages/message/components/MessageItem.js +29 -20
  66. package/dist/pages/message/components/MessageOption.d.ts +7 -3
  67. package/dist/pages/message/components/MessageOption.js +14 -16
  68. package/dist/pages/message/components/MessagePayload.d.ts +2 -1
  69. package/dist/pages/message/components/MessagePictureAlbum.js +6 -4
  70. package/dist/pages/message/components/Payload/PayloadFile.d.ts +1 -1
  71. package/dist/pages/message/components/Payload/PayloadFile.js +34 -16
  72. package/dist/pages/message/components/Payload/PayloadMultiple.js +12 -8
  73. package/dist/pages/message/components/Payload/PayloadNotify.js +14 -5
  74. package/dist/pages/message/components/Payload/PayloadPicture.d.ts +1 -1
  75. package/dist/pages/message/components/Payload/PayloadPicture.js +9 -7
  76. package/dist/pages/message/components/Payload/PayloadText.js +7 -8
  77. package/dist/pages/message/components/Payload/PayloadVideo.js +2 -1
  78. package/dist/pages/message/components/Payload/PayloadVoice.js +7 -13
  79. package/dist/pages/message/components/Payload/PayloadWrapper.d.ts +2 -1
  80. package/dist/pages/message/components/Payload/PayloadWrapper.js +46 -20
  81. package/dist/pages/message/components/Payload/type.d.ts +3 -1
  82. package/dist/pages/message/components/ReceiptBack.js +2 -2
  83. package/dist/pages/message/components/TextMixMessage.d.ts +2 -0
  84. package/dist/pages/message/components/TextMixMessage.js +10 -3
  85. package/dist/pages/message/components/TextMixQuote.js +10 -15
  86. package/dist/pages/message/components/TextMixQuoteMessage.d.ts +2 -1
  87. package/dist/pages/message/components/TextMixQuoteMessage.js +5 -5
  88. package/dist/pages/message/components/UploadProgress.d.ts +1 -1
  89. package/dist/pages/message/components/UploadProgress.js +1 -1
  90. package/dist/pages/message/components/messageBar/EmojiPanel.js +8 -9
  91. package/dist/pages/message/components/messageBar/MessageBar.d.ts +1 -1
  92. package/dist/pages/message/components/messageBar/MessageBar.js +14 -12
  93. package/dist/pages/message/components/messageBar/MessageInput.d.ts +1 -0
  94. package/dist/pages/message/components/messageBar/MessageInput.js +19 -1
  95. package/dist/pages/message/components/messageBar/OptionPanel.js +22 -44
  96. package/dist/pages/message/message.routes.js +10 -0
  97. package/dist/pages/search/components/SearchUser.js +2 -2
  98. package/dist/pages/types.d.ts +6 -2
  99. package/dist/slice/contact/contact.slice.js +1 -0
  100. package/dist/slice/video/video.action.js +9 -1
  101. package/dist/utils/common-action-sheet.d.ts +1 -0
  102. package/dist/utils/common-action-sheet.js +18 -0
  103. package/dist/utils/file-icon.js +29 -2
  104. package/dist/utils/file.d.ts +21 -2
  105. package/dist/utils/file.js +209 -42
  106. package/dist/utils/phone.d.ts +1 -1
  107. package/dist/utils/phone.js +1 -9
  108. package/dist/utils/request.d.ts +2 -1
  109. package/dist/utils/request.js +17 -6
  110. package/dist/utils/upload.d.ts +2 -4
  111. package/dist/utils/upload.js +13 -49
  112. package/package.json +5 -5
  113. package/dist/pages/address-list/Icons.d.ts +0 -5
  114. package/dist/pages/address-list/Icons.js +0 -9
  115. package/dist/slice/contact/contact.action.d.ts +0 -1
  116. package/dist/slice/contact/contact.action.js +0 -1
  117. package/dist/utils/cookie.d.ts +0 -2
  118. package/dist/utils/cookie.js +0 -25
  119. package/dist/utils/file-operate.d.ts +0 -1
  120. package/dist/utils/file-operate.js +0 -3
  121. package/dist/utils/text-mix.d.ts +0 -9
  122. package/dist/utils/text-mix.js +0 -75
  123. /package/dist/pages/address-list/{CardInfo.d.ts → components/CardInfo.d.ts} +0 -0
  124. /package/dist/pages/address-list/{CardInfo.js → components/CardInfo.js} +0 -0
  125. /package/dist/pages/address-list/{UserJobs.d.ts → components/UserJobs.d.ts} +0 -0
@@ -9,13 +9,50 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { dp } from '@smart-link/rn-ui';
13
- import React, { memo } from 'react';
12
+ import React, { memo, useState } from 'react';
14
13
  import { View, StyleSheet, TouchableOpacity } from 'react-native';
14
+ import { dp } from "@smart-link/rn-ui";
15
+ import Svg, { Path } from "react-native-svg";
16
+ import Color from "color";
17
+ // 通过 Svg 实现箭头
18
+ const SvgFromUri = ({ direction, focus }) => {
19
+ let fill = direction === 'left' ? '#fff' : '#cde6f9';
20
+ let stroke = direction === 'left' ? "#eee" : '#cde6f9';
21
+ if (focus) {
22
+ fill = Color(fill).darken(0.08).hex();
23
+ if (direction === 'right') {
24
+ stroke = Color(stroke).darken(0.08).hex();
25
+ }
26
+ }
27
+ return (<Svg width={12} height={12}>
28
+ <Path d={direction == 'left' ? "M 12 12 L 0 5 L 12 0" : "M 0 12 L 12 5 L 0 0"} fill={fill} stroke={stroke} strokeWidth={1}></Path>
29
+ </Svg>);
30
+ };
15
31
  const PayloadWrapper = memo((_a) => {
16
- var { children, direction, showArrow } = _a, retProps = __rest(_a, ["children", "direction", "showArrow"]);
17
- return (<TouchableOpacity {...retProps}>
18
- {showArrow && (<View style={[styles.arrow, direction === 'right' ? styles.rightArrow : styles.leftArrow]}/>)}
32
+ var { children, direction, showArrow, onLongPress, style } = _a, retProps = __rest(_a, ["children", "direction", "showArrow", "onLongPress", "style"]);
33
+ const [layout, setLayout] = useState();
34
+ const [focus, setFocus] = useState(false);
35
+ let backgroundColor = direction === 'right' ? '#cde6f9' : '#fff';
36
+ if (focus) {
37
+ backgroundColor = Color(backgroundColor).darken(0.08).hex();
38
+ }
39
+ return (<TouchableOpacity {...retProps} style={[
40
+ style,
41
+ {
42
+ backgroundColor,
43
+ }
44
+ ]} onLayout={e => {
45
+ setLayout(e.nativeEvent.layout);
46
+ }} onLongPress={(e) => {
47
+ onLongPress && onLongPress(e, layout);
48
+ }} activeOpacity={1} onPressIn={() => {
49
+ setFocus(true);
50
+ }} onPressOut={() => {
51
+ setFocus(false);
52
+ }}>
53
+ {showArrow && (<View style={[styles.arrow, direction === 'right' ? styles.rightArrow : styles.leftArrow]}>
54
+ <SvgFromUri direction={direction} focus={focus}/>
55
+ </View>)}
19
56
  {children}
20
57
  </TouchableOpacity>);
21
58
  });
@@ -24,25 +61,14 @@ const styles = StyleSheet.create({
24
61
  width: dp(12),
25
62
  height: dp(12),
26
63
  position: 'absolute',
27
- top: dp(11),
28
- zIndex: 1,
29
- borderStyle: 'solid',
30
- borderTopWidth: dp(8),
31
- borderTopColor: 'transparent',
32
- borderBottomWidth: dp(8),
33
- borderBottomColor: 'transparent',
64
+ top: dp(12),
65
+ zIndex: -10,
34
66
  },
35
67
  leftArrow: {
36
- left: -dp(11),
37
- borderRightColor: '#fff',
38
- borderRightWidth: dp(8),
39
- borderLeftWidth: 0,
68
+ left: -dp(10),
40
69
  },
41
70
  rightArrow: {
42
- right: -dp(12),
43
- borderLeftColor: '#e3e3e3',
44
- borderLeftWidth: dp(8),
45
- borderRightWidth: 0,
71
+ right: -dp(10),
46
72
  },
47
73
  });
48
74
  export default PayloadWrapper;
@@ -1,11 +1,13 @@
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 {
5
+ width?: number;
4
6
  style?: StyleProp<ViewStyle>;
5
7
  direction?: 'left' | 'right';
6
8
  showArrow?: boolean;
7
9
  isRecord?: boolean;
8
10
  onPress?: (e: GestureResponderEvent) => void;
9
- onLongPress?: (e: GestureResponderEvent) => void;
11
+ onLongPress?: (e: GestureResponderEvent, layout: NativeEventLayout) => void;
10
12
  onLoad?: (localPath: string) => void;
11
13
  }
@@ -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>
@@ -1,6 +1,8 @@
1
+ import { IGroupMember } from "@smart-link/im-base";
1
2
  import React from 'react';
2
3
  export type TextMixMessageProps = {
3
4
  text: string;
5
+ atList?: IGroupMember[];
4
6
  onLongPressPhone?: (phone: string) => void;
5
7
  onLongPressURL?: (url: string) => void;
6
8
  textStyle?: any;
@@ -1,9 +1,9 @@
1
+ import { mix, mixAtList } from "@smart-link/im-base";
1
2
  import React, { memo } from 'react';
2
3
  import { Text, StyleSheet } from "react-native";
3
- import { mix } from '../../../utils/text-mix';
4
4
  const TextMixMessage = memo(props => {
5
- const { text, onLongPressPhone, onLongPressURL, textStyle, } = props;
6
- const viewItems = mix(text);
5
+ const { text, atList, onLongPressPhone, onLongPressURL, textStyle, } = props;
6
+ const viewItems = mixAtList(atList, mix(text));
7
7
  return (<Text style={textStyle}>
8
8
  {viewItems.map((item, index) => {
9
9
  if (item.type === 'phone') {
@@ -21,6 +21,9 @@ const TextMixMessage = memo(props => {
21
21
  {item.value}
22
22
  </Text>);
23
23
  }
24
+ else if (item.type === 'at') {
25
+ return (<Text key={index} style={styles.at}>{item.value}</Text>);
26
+ }
24
27
  return item.value;
25
28
  })}
26
29
  </Text>);
@@ -33,5 +36,9 @@ const styles = StyleSheet.create({
33
36
  color: '#208aff',
34
37
  textDecorationLine: 'underline'
35
38
  },
39
+ at: {
40
+ color: '#208aff',
41
+ fontWeight: "700"
42
+ }
36
43
  });
37
44
  export default TextMixMessage;
@@ -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>
@@ -91,8 +86,8 @@ export const QuoteFile = memo(props => {
91
86
  {' : '}
92
87
  </Text>
93
88
  <View style={styles.h5}/>
94
- <View style={[styles.popoverFile, { backgroundColor: dark(color, 10) }]}>
95
- <PayloadFile {...quoteMessage} style={{ flex: 1 }} showArrow={false}/>
89
+ <View style={[styles.popoverFile, { backgroundColor: dark(color, 10), paddingHorizontal: dp(5), flexDirection: 'column' }]}>
90
+ <PayloadFile {...quoteMessage} style={{ flex: 1, padding: dp(5) }} width={width - dp(155)} showArrow={false}/>
96
91
  </View>
97
92
  </TouchableOpacity>);
98
93
  });
@@ -190,7 +185,7 @@ const styles = StyleSheet.create({
190
185
  popoverFile: {
191
186
  backgroundColor: '#fff',
192
187
  flexDirection: 'row',
193
- paddingVertical: dp(8),
188
+ paddingTop: dp(8),
194
189
  width: width - dp(145),
195
190
  },
196
191
  voiceImage: {
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
- import { IMessageQuote } from '@smart-link/im-base';
2
+ import { IGroupMember, IMessageQuote } from '@smart-link/im-base';
3
3
  interface QuoteTextMixProps {
4
4
  text: string;
5
5
  quote?: IMessageQuote | null;
6
+ atList?: IGroupMember[];
6
7
  textStyle?: any;
7
8
  quoteBgColor: string;
8
9
  quoteStyle?: any;
@@ -5,7 +5,7 @@ import TextMixMessage from './TextMixMessage';
5
5
  import { PayloadType } from '@smart-link/im-base';
6
6
  const { TEXT, VOICE, VIDEO, PICTURE, FILE, MULTIPLE } = PayloadType;
7
7
  const TextMixQuoteMessage = memo(props => {
8
- const { text, quote, textStyle, quoteStyle, quoteBgColor, onLongPressPhone, onLongPressURL, onPressQuote } = props;
8
+ const { text, quote, atList, textStyle, quoteStyle, quoteBgColor, onLongPressPhone, onLongPressURL, onPressQuote } = props;
9
9
  let quotePayloadType;
10
10
  let quoteMessageSeq;
11
11
  const haveQuote = quote && Object.keys(quote).length > 0;
@@ -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={() => {
@@ -40,7 +40,7 @@ const TextMixQuoteMessage = memo(props => {
40
40
  <View style={{ height: 10 }}/>
41
41
  </>)}
42
42
 
43
- <TextMixMessage text={text} textStyle={textStyle} onLongPressPhone={onLongPressPhone} onLongPressURL={onLongPressURL}/>
43
+ <TextMixMessage text={text} atList={atList} textStyle={textStyle} onLongPressPhone={onLongPressPhone} onLongPressURL={onLongPressURL}/>
44
44
  </>);
45
45
  });
46
46
  export default TextMixQuoteMessage;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  type UploadProgressProps = {
3
3
  show: boolean;
4
- width: number;
4
+ width?: number;
5
5
  sendSize: number;
6
6
  totalSize: number;
7
7
  };
@@ -11,7 +11,7 @@ const UploadProgress = ({ show, sendSize, totalSize, width }) => {
11
11
  return null;
12
12
  }
13
13
  const progress = sendSize / totalSize;
14
- return (<View>
14
+ return (<View style={{ width }}>
15
15
  <Bar progress={progress} width={width} height={dp(3)} color={'#999'} borderRadius={dp(1)}/>
16
16
  <Text style={styles.rate}>{numberToFileSize(sendSize) + ' / ' + numberToFileSize(totalSize)}</Text>
17
17
  </View>);
@@ -2,16 +2,16 @@ import React, { forwardRef, memo, useImperativeHandle, useRef, useState } from '
2
2
  import { View, Text, FlatList, Animated, TouchableOpacity, Dimensions } from 'react-native';
3
3
  import { face } from '../../../../utils/emoji';
4
4
  import { DeleteSvg } from './Icons';
5
+ import { useAnimatedValue } from "../../../../hooks/useAnimatedValue";
5
6
  const emojis = Array.from(new Set([...face]));
6
7
  const EMOJI_SIZE = (Dimensions.get('screen').width - 20) / 8;
7
8
  const keyExtractor = (item) => item;
8
9
  const EmojiPanel = forwardRef(({ onCheck, onBackspace }, ref) => {
9
- const visible = useRef(false);
10
- const [, forceUpdate] = useState({});
10
+ const [visible, setVisible] = useState(false);
11
11
  const timer = useRef(null);
12
12
  const start = useRef(false);
13
13
  //通过动画设置表情面板高度
14
- const [heightAnim] = useState(new Animated.Value(0));
14
+ const heightAnim = useAnimatedValue(0);
15
15
  const renderItem = ({ item }) => (<TouchableOpacity style={{
16
16
  width: EMOJI_SIZE,
17
17
  height: EMOJI_SIZE,
@@ -23,27 +23,26 @@ const EmojiPanel = forwardRef(({ onCheck, onBackspace }, ref) => {
23
23
  </TouchableOpacity>);
24
24
  useImperativeHandle(ref, () => ({
25
25
  show: (height) => {
26
- visible.current = true;
26
+ setVisible(true);
27
27
  heightAnim.setValue(height);
28
- forceUpdate({});
29
28
  },
30
29
  hide: () => {
31
- visible.current = false;
30
+ setVisible(false);
32
31
  heightAnim.setValue(0);
33
- forceUpdate({});
34
32
  },
35
33
  }), []);
34
+ console.log('EmojiPanel: ', heightAnim);
36
35
  return (<Animated.View style={{
37
36
  height: heightAnim,
38
37
  position: 'relative',
39
38
  flexDirection: 'column',
40
- paddingBottom: visible.current ? 20 : 0,
39
+ paddingBottom: visible ? 20 : 0,
41
40
  }} pointerEvents='auto'>
42
41
  <FlatList numColumns={8} initialNumToRender={80} data={emojis} keyExtractor={keyExtractor} contentContainerStyle={{
43
42
  paddingHorizontal: 10,
44
43
  paddingBottom: 50,
45
44
  }} pointerEvents='auto' keyboardShouldPersistTaps={'handled'} renderItem={renderItem} scrollEnabled/>
46
- {visible.current && <View style={{
45
+ {visible && <View style={{
47
46
  position: 'absolute',
48
47
  height: EMOJI_SIZE,
49
48
  width: 80,
@@ -5,7 +5,7 @@ export interface MessageBarProps {
5
5
  export interface MessageBarMethods {
6
6
  reset(): void;
7
7
  focusTextInput(): void;
8
- appendInputText(text: string): void;
8
+ inertText(text: string): void;
9
9
  setMessageText(text: string): void;
10
10
  }
11
11
  declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<MessageBarProps & React.RefAttributes<MessageBarMethods>>>;
@@ -56,6 +56,10 @@ const MessageBar = forwardRef(({ onKeyboardAt }, ref) => {
56
56
  var _a;
57
57
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.insertEmoji(emoji);
58
58
  }, []);
59
+ const onEmojiBack = useCallback(() => {
60
+ var _a;
61
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.backspace();
62
+ }, []);
59
63
  const switchVoice = useCallback(() => {
60
64
  var _a, _b;
61
65
  (_a = emojiPanelRef.current) === null || _a === void 0 ? void 0 : _a.hide();
@@ -85,15 +89,13 @@ const MessageBar = forwardRef(({ onKeyboardAt }, ref) => {
85
89
  }, timeout);
86
90
  }, []);
87
91
  const switchEmojiInputMode = useCallback(() => {
92
+ var _a, _b, _c;
88
93
  modeRef.current = 'emoji';
89
94
  setInputMode('emoji');
90
95
  Keyboard.dismiss();
91
- setTimeout(() => {
92
- var _a, _b, _c;
93
- (_a = optionPanelRef.current) === null || _a === void 0 ? void 0 : _a.hide();
94
- (_b = emojiPanelRef.current) === null || _b === void 0 ? void 0 : _b.show(keyboardHeight.current);
95
- (_c = inputRef.current) === null || _c === void 0 ? void 0 : _c.focusNoSoftKeyboard();
96
- }, keyboardDuration.current);
96
+ (_a = optionPanelRef.current) === null || _a === void 0 ? void 0 : _a.hide();
97
+ (_b = emojiPanelRef.current) === null || _b === void 0 ? void 0 : _b.show(keyboardHeight.current);
98
+ (_c = inputRef.current) === null || _c === void 0 ? void 0 : _c.focusNoSoftKeyboard();
97
99
  }, []);
98
100
  const switchOptionPanelMode = useMemoizedFn(() => {
99
101
  var _a;
@@ -111,7 +113,7 @@ const MessageBar = forwardRef(({ onKeyboardAt }, ref) => {
111
113
  }, keyboardDuration.current);
112
114
  });
113
115
  const onKeyPress = useCallback((e) => {
114
- if (e.nativeEvent.key === '@') {
116
+ if (['@', '@'].includes(e.nativeEvent.key)) {
115
117
  if (!debounceAt.current) {
116
118
  debounceAt.current = debounce(() => {
117
119
  onKeyboardAt && onKeyboardAt();
@@ -162,16 +164,15 @@ const MessageBar = forwardRef(({ onKeyboardAt }, ref) => {
162
164
  (_b = emojiPanelRef.current) === null || _b === void 0 ? void 0 : _b.hide();
163
165
  (_c = optionPanelRef.current) === null || _c === void 0 ? void 0 : _c.hide();
164
166
  },
165
- appendInputText: (text) => {
167
+ inertText: (text) => {
166
168
  var _a, _b, _c;
167
- tempText.current += text;
168
- (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.setText(tempText.current);
169
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.insertText(text);
169
170
  setTimeout(() => {
170
171
  var _a;
171
172
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
172
173
  }, keyboardDuration.current);
173
174
  (_b = emojiPanelRef.current) === null || _b === void 0 ? void 0 : _b.hide();
174
- (_c = optionPanelRef.current) === null || _c === void 0 ? void 0 : _c.hide();
175
+ (_c = optionPanelRef.current) === null || _c === void 0 ? void 0 : _c.hide;
175
176
  },
176
177
  setMessageText: (text) => {
177
178
  var _a, _b, _c;
@@ -199,6 +200,7 @@ const MessageBar = forwardRef(({ onKeyboardAt }, ref) => {
199
200
  }
200
201
  const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', event => {
201
202
  var _a, _b;
203
+ console.log(event.endCoordinates.height);
202
204
  keyboardHeight.current = Math.max(event.endCoordinates.height, 240);
203
205
  keyboardDuration.current = event.duration;
204
206
  (_a = emojiPanelRef.current) === null || _a === void 0 ? void 0 : _a.hide();
@@ -236,7 +238,7 @@ const MessageBar = forwardRef(({ onKeyboardAt }, ref) => {
236
238
  </TouchableOpacity>)}
237
239
  </View>
238
240
  </View>
239
- <EmojiPanel ref={emojiPanelRef} onCheck={handleInsertEmoji} onBackspace={() => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.backspace(); }}/>
241
+ <EmojiPanel ref={emojiPanelRef} onCheck={handleInsertEmoji} onBackspace={onEmojiBack}/>
240
242
  <OptionPanel ref={optionPanelRef}/>
241
243
  </>);
242
244
  });
@@ -15,6 +15,7 @@ export type MessageInputMethods = {
15
15
  setText: (text: string) => void;
16
16
  getText: () => string;
17
17
  insertEmoji: (text: string) => void;
18
+ insertText: (text: string) => void;
18
19
  backspace: () => void;
19
20
  };
20
21
  declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<MessageInputProps & React.RefAttributes<MessageInputMethods>>>;
@@ -58,6 +58,25 @@ const MessageInput = forwardRef(({ onChangeText, onKeyPress, style }, ref) => {
58
58
  (_c = inputRef.current) === null || _c === void 0 ? void 0 : _c.setSelection(start + emoji.length, start + emoji.length);
59
59
  }
60
60
  },
61
+ insertText(text) {
62
+ var _a, _b, _c;
63
+ const { start, end } = selection;
64
+ let newText = ((_a = innerText.current) === null || _a === void 0 ? void 0 : _a.slice(0, start)) + text + ((_b = innerText.current) === null || _b === void 0 ? void 0 : _b.slice(end));
65
+ onChangeText === null || onChangeText === void 0 ? void 0 : onChangeText(newText);
66
+ innerText.current = newText;
67
+ setText(newText);
68
+ setSelection({
69
+ start: start + text.length,
70
+ end: start + text.length,
71
+ });
72
+ if (Platform.OS === 'ios') {
73
+ selectionIos.current = {
74
+ start: start + text.length,
75
+ end: start + text.length,
76
+ };
77
+ (_c = inputRef.current) === null || _c === void 0 ? void 0 : _c.setSelection(start + text.length, start + text.length);
78
+ }
79
+ },
61
80
  getText: () => {
62
81
  return innerText.current;
63
82
  },
@@ -152,7 +171,6 @@ const MessageInput = forwardRef(({ onChangeText, onKeyPress, style }, ref) => {
152
171
  const styles = StyleSheet.create({
153
172
  container: {
154
173
  flex: 1,
155
- position: 'relative',
156
174
  marginVertical: dp(6),
157
175
  maxHeight: dp(120),
158
176
  },
@@ -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,17 +16,18 @@ 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";
23
+ import { useAnimatedValue } from "../../../../hooks/useAnimatedValue";
24
24
  const OPTION_SIZE = (Dimensions.get('screen').width - 20) / 4;
25
25
  const keyExtractor = (item) => item.id;
26
26
  const OptionPanel = forwardRef((props, ref) => {
27
27
  const navigation = useNavigation();
28
28
  const [visible, setVisible] = useState(false);
29
29
  const { currentConversation } = useConversation();
30
- const [heightAnim] = useState(new Animated.Value(0));
30
+ const heightAnim = useAnimatedValue(0);
31
31
  const { t } = useTranslation();
32
32
  const imManager = getImManager();
33
33
  useImperativeHandle(ref, () => ({
@@ -43,17 +43,18 @@ const OptionPanel = forwardRef((props, ref) => {
43
43
  }), [visible]);
44
44
  const sendPicture = (data) => __awaiter(void 0, void 0, void 0, function* () {
45
45
  scrollToBottom();
46
- yield getImManager().sendPictureMessage(Object.assign({}, currentConversation), data);
47
- });
48
- const sendVideo = (data) => __awaiter(void 0, void 0, void 0, function* () {
49
- scrollToBottom();
50
- yield getImManager().sendVideoMessage(Object.assign({}, currentConversation), data);
51
- });
52
- const sendFile = (data) => __awaiter(void 0, void 0, void 0, function* () {
53
- scrollToBottom();
54
- const destPath = yield copyFile(data.localPath, data.filename, 'file');
55
- yield getImManager().sendFileMessage(Object.assign({}, currentConversation), Object.assign(Object.assign({}, data), { localPath: destPath }));
46
+ yield imManager.sendPictureMessage(Object.assign({}, currentConversation), data);
56
47
  });
48
+ // const sendVideo = async (data: IPayload) => {
49
+ // scrollToBottom();
50
+ // await imManager.sendVideoMessage({...currentConversation!}, data);
51
+ // };
52
+ //
53
+ // const sendFile = async (data: IPayload) => {
54
+ // scrollToBottom();
55
+ // const destPath = await copyFile(data.localPath as string, data.filename!, 'file');
56
+ // await imManager.sendFileMessage({...currentConversation!}, {...data, localPath: destPath});
57
+ // };
57
58
  const openAlbum = () => __awaiter(void 0, void 0, void 0, function* () {
58
59
  try {
59
60
  const images = yield ImagePicker.openPicker({
@@ -63,17 +64,18 @@ const OptionPanel = forwardRef((props, ref) => {
63
64
  compressImageMaxWidth: 1080,
64
65
  });
65
66
  console.log(images);
66
- images.map(item => {
67
- sendPicture({
67
+ for (const item of images) {
68
+ const localPath = yield copyFile(item.path, item.filename, 'picture');
69
+ yield sendPicture({
68
70
  filename: item.filename,
69
71
  size: item.size,
70
- localPath: item.path,
72
+ localPath: localPath,
71
73
  type: item.mime,
72
74
  lastModified: Number(item.modificationDate),
73
75
  width: item.width,
74
76
  height: item.height,
75
77
  });
76
- });
78
+ }
77
79
  }
78
80
  catch (e) {
79
81
  console.log(e);
@@ -89,31 +91,7 @@ const OptionPanel = forwardRef((props, ref) => {
89
91
  });
90
92
  const pickFile = () => __awaiter(void 0, void 0, void 0, function* () {
91
93
  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
- });
94
+ navigation.navigate('FileSelector');
117
95
  }
118
96
  catch (e) {
119
97
  console.log(e);
@@ -155,7 +133,7 @@ const OptionPanel = forwardRef((props, ref) => {
155
133
  {
156
134
  id: 'star',
157
135
  icon: <FontAwesome name="star" color="#000" size={32}/>,
158
- text: t('collect'),
136
+ text: t('collected'),
159
137
  onPress: () => {
160
138
  navigation.navigate('Collection');
161
139
  },
@@ -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,