@smart-link/rn-im 1.0.26 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/addressList.d.ts +16 -15
- package/dist/api/addressList.js +15 -1
- package/dist/api/user.js +1 -1
- package/dist/components/Camera/Camera.js +3 -2
- package/dist/components/Camera/CameraCapture.js +61 -12
- package/dist/components/ChatAvatar/ChatAvatar.d.ts +3 -3
- package/dist/components/ChatAvatar/ChatAvatar.js +51 -49
- package/dist/components/ChatAvatar/ChatAvatarId.d.ts +2 -2
- package/dist/components/ChatAvatar/ChatAvatarId.js +19 -46
- package/dist/components/ChatAvatar/ChatAvatarLocal.js +22 -9
- package/dist/components/Favicon.js +1 -1
- package/dist/components/LocalImage.js +3 -1
- package/dist/components/styles.d.ts +7 -1
- package/dist/components/styles.js +16 -11
- package/dist/hooks/useAnimatedValue.d.ts +2 -0
- package/dist/hooks/useAnimatedValue.js +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/init.d.ts +2 -2
- package/dist/init.js +8 -5
- package/dist/interface.d.ts +9 -3
- package/dist/pages/address-list/AddressList.js +22 -40
- package/dist/pages/address-list/ChooseContact.js +209 -45
- package/dist/pages/address-list/MyGroups.d.ts +6 -0
- package/dist/pages/address-list/MyGroups.js +90 -0
- package/dist/pages/address-list/Organization.d.ts +0 -7
- package/dist/pages/address-list/Organization.js +24 -108
- package/dist/pages/address-list/UserDetail.js +5 -5
- package/dist/pages/address-list/UserSearch.js +6 -7
- package/dist/pages/address-list/addressList.routes.d.ts +9 -0
- package/dist/pages/address-list/addressList.routes.js +8 -0
- package/dist/pages/address-list/components/Icons.d.ts +8 -0
- package/dist/pages/address-list/components/Icons.js +15 -0
- package/dist/pages/address-list/components/OrgPath.d.ts +12 -0
- package/dist/pages/address-list/components/OrgPath.js +59 -0
- package/dist/pages/address-list/components/RenderUserItem.d.ts +9 -0
- package/dist/pages/address-list/components/RenderUserItem.js +14 -0
- package/dist/pages/address-list/{UserJobs.js → components/UserJobs.js} +2 -2
- package/dist/pages/address-list/useGroupCategory.d.ts +2 -0
- package/dist/pages/address-list/useGroupCategory.js +11 -0
- package/dist/pages/address-list/useRoleList.d.ts +2 -0
- package/dist/pages/address-list/useRoleList.js +11 -0
- package/dist/pages/collection/Collection.js +52 -8
- package/dist/pages/collection/ContentFactory.js +50 -3
- package/dist/pages/conversation/ForwardToConversation.js +4 -2
- package/dist/pages/conversation/List.js +15 -7
- package/dist/pages/conversation/components/ConversationCard.js +1 -7
- package/dist/pages/conversation/setting/GroupTransfer.js +9 -2
- package/dist/pages/conversation/setting/OptionAvatars.js +0 -1
- package/dist/pages/conversation/setting/OptionGroup.d.ts +1 -1
- package/dist/pages/conversation/setting/OptionGroup.js +4 -4
- package/dist/pages/conversation/setting/OptionGroupManage.js +4 -8
- package/dist/pages/conversation/setting/OptionGroupMoreMember.js +37 -18
- package/dist/pages/conversation/setting/Setting.js +20 -7
- package/dist/pages/conversation/setting/SettingChatBg.js +32 -16
- package/dist/pages/message/ChooseMember.js +9 -12
- package/dist/pages/message/FileSelector.js +40 -3
- package/dist/pages/message/MessageList.js +64 -30
- package/dist/pages/message/MessageRecord.js +1 -1
- package/dist/pages/message/components/MessageItem.d.ts +5 -6
- package/dist/pages/message/components/MessageItem.js +23 -15
- package/dist/pages/message/components/MessageOption.js +1 -0
- package/dist/pages/message/components/MessagePictureAlbum.js +6 -4
- package/dist/pages/message/components/Payload/PayloadFile.d.ts +1 -1
- package/dist/pages/message/components/Payload/PayloadFile.js +31 -13
- package/dist/pages/message/components/Payload/PayloadMultiple.js +3 -3
- package/dist/pages/message/components/Payload/PayloadNotify.js +17 -5
- package/dist/pages/message/components/Payload/PayloadPicture.js +6 -3
- package/dist/pages/message/components/Payload/PayloadText.js +7 -8
- package/dist/pages/message/components/Payload/PayloadVoice.js +7 -13
- package/dist/pages/message/components/Payload/PayloadWrapper.js +40 -19
- package/dist/pages/message/components/Payload/type.d.ts +1 -0
- package/dist/pages/message/components/TextMixMessage.d.ts +2 -0
- package/dist/pages/message/components/TextMixMessage.js +10 -3
- package/dist/pages/message/components/TextMixQuote.js +3 -3
- package/dist/pages/message/components/TextMixQuoteMessage.d.ts +2 -1
- package/dist/pages/message/components/TextMixQuoteMessage.js +2 -2
- package/dist/pages/message/components/UploadProgress.d.ts +1 -1
- package/dist/pages/message/components/UploadProgress.js +1 -1
- package/dist/pages/message/components/messageBar/EmojiPanel.d.ts +2 -2
- package/dist/pages/message/components/messageBar/EmojiPanel.js +29 -13
- package/dist/pages/message/components/messageBar/MessageBar.d.ts +1 -1
- package/dist/pages/message/components/messageBar/MessageBar.js +34 -20
- package/dist/pages/message/components/messageBar/MessageInput.d.ts +6 -7
- package/dist/pages/message/components/messageBar/MessageInput.js +21 -3
- package/dist/pages/message/components/messageBar/OptionPanel.d.ts +2 -3
- package/dist/pages/message/components/messageBar/OptionPanel.js +38 -18
- package/dist/pages/search/components/SearchUser.js +2 -2
- package/dist/pages/types.d.ts +2 -0
- package/dist/slice/contact/contact.slice.js +1 -0
- package/dist/utils/common-action-sheet.d.ts +1 -0
- package/dist/utils/common-action-sheet.js +18 -0
- package/dist/utils/event.d.ts +13 -0
- package/dist/utils/event.js +32 -0
- package/dist/utils/file-icon.js +29 -2
- package/dist/utils/file.d.ts +12 -1
- package/dist/utils/file.js +79 -25
- package/dist/utils/phone.d.ts +1 -1
- package/dist/utils/phone.js +1 -9
- package/dist/utils/request.d.ts +2 -1
- package/dist/utils/request.js +17 -6
- package/dist/utils/upload.d.ts +2 -4
- package/dist/utils/upload.js +13 -49
- package/package.json +5 -5
- package/dist/pages/address-list/Icons.d.ts +0 -5
- package/dist/pages/address-list/Icons.js +0 -9
- package/dist/utils/cookie.d.ts +0 -2
- package/dist/utils/cookie.js +0 -25
- package/dist/utils/file-operate.d.ts +0 -1
- package/dist/utils/file-operate.js +0 -3
- package/dist/utils/text-mix.d.ts +0 -9
- package/dist/utils/text-mix.js +0 -75
- /package/dist/pages/address-list/{CardInfo.d.ts → components/CardInfo.d.ts} +0 -0
- /package/dist/pages/address-list/{CardInfo.js → components/CardInfo.js} +0 -0
- /package/dist/pages/address-list/{UserJobs.d.ts → components/UserJobs.d.ts} +0 -0
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
import { IUser } from '@smart-link/im-base';
|
|
2
|
+
import { IGroup, IRole } from "../interface";
|
|
2
3
|
type IListTreeParams = {
|
|
3
|
-
groupCatId
|
|
4
|
-
parentId
|
|
5
|
-
groupStatus
|
|
6
|
-
queryChild
|
|
4
|
+
groupCatId?: any;
|
|
5
|
+
parentId?: string;
|
|
6
|
+
groupStatus?: string;
|
|
7
|
+
queryChild?: boolean;
|
|
7
8
|
};
|
|
8
9
|
type IListUserParams = {
|
|
9
|
-
groupCategoryId
|
|
10
|
-
groupId
|
|
11
|
-
groupIdPathLike
|
|
10
|
+
groupCategoryId?: string;
|
|
11
|
+
groupId?: string;
|
|
12
|
+
groupIdPathLike?: string;
|
|
12
13
|
pageNum: number;
|
|
13
14
|
pageSize: number;
|
|
14
|
-
queryAll
|
|
15
|
-
userStatus
|
|
15
|
+
queryAll?: boolean;
|
|
16
|
+
userStatus?: string;
|
|
16
17
|
};
|
|
17
|
-
export declare const listGroupCategory: (data:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export declare const listTree: (data: IListTreeParams) => Promise<import("../utils/request").IResponse<any>>;
|
|
21
|
-
export declare const listUser: (data: IListUserParams) => Promise<import("../utils/request").IResponse<any>>;
|
|
18
|
+
export declare const listGroupCategory: (data: any) => Promise<import("../utils/request").IResponse<any>>;
|
|
19
|
+
export declare const listTree: (data: IListTreeParams) => Promise<import("../utils/request").IResponse<IGroup[]>>;
|
|
20
|
+
export declare const listUser: (data: IListUserParams) => Promise<import("../utils/request").IResponse<IUser[]>>;
|
|
22
21
|
export declare const queryUser: (userId: string) => Promise<import("../utils/request").IResponse<any>>;
|
|
22
|
+
export declare const queryUsersByCond: (userIds: string[]) => Promise<import("../utils/request").IResponse<IUser[]>>;
|
|
23
23
|
export declare const searchUser: (params: {
|
|
24
24
|
userNameLike: string;
|
|
25
|
-
tenantId: string;
|
|
26
25
|
}) => Promise<import("../utils/request").IResponse<IUser[]>>;
|
|
26
|
+
export declare const listRole: () => Promise<import("../utils/request").IResponse<IRole[]>>;
|
|
27
|
+
export declare const listRoleUser: (roleId: string) => Promise<import("../utils/request").IResponse<IUser[]>>;
|
|
27
28
|
export {};
|
package/dist/api/addressList.js
CHANGED
|
@@ -4,4 +4,18 @@ export const listGroupCategory = (data) => request.post(`${api}/open/groupQuery/
|
|
|
4
4
|
export const listTree = (data) => request.post(`${api}/open/groupQuery/listTree`, data);
|
|
5
5
|
export const listUser = (data) => request.post(`${api}/open/userQuery/listUser`, data);
|
|
6
6
|
export const queryUser = (userId) => request.post(`${api}/open/userQuery/queryUsersByIds`, [userId]);
|
|
7
|
-
export const
|
|
7
|
+
export const queryUsersByCond = (userIds) => request.post(`${api}/open/userQuery/queryUsersByCond`, {
|
|
8
|
+
userIds,
|
|
9
|
+
});
|
|
10
|
+
export const searchUser = (params) => request.post(`${api}/open/userQuery/listUser`, Object.assign(Object.assign({}, params), { queryAll: true, userStatus: 'valid', pageSize: 100, pageNum: 1 }));
|
|
11
|
+
export const listRole = () => request.post(`${api}/open/roleQuery/listRole`, {
|
|
12
|
+
pageNum: 1,
|
|
13
|
+
pageSize: 100,
|
|
14
|
+
roleStatus: "valid"
|
|
15
|
+
});
|
|
16
|
+
export const listRoleUser = (roleId) => request.post(`${api}/open/roleQuery/listRoleUser`, {
|
|
17
|
+
roleId,
|
|
18
|
+
pageNum: 1,
|
|
19
|
+
pageSize: 100,
|
|
20
|
+
userStatus: "valid"
|
|
21
|
+
});
|
package/dist/api/user.js
CHANGED
|
@@ -2,5 +2,5 @@ import request from '../utils/request';
|
|
|
2
2
|
export const userApi = '/api-user-center';
|
|
3
3
|
export const searchUser = (params) => request.post(`${userApi}/open/userQuery/listUser`, Object.assign(Object.assign({}, params), { queryAll: true, userStatus: 'valid' }));
|
|
4
4
|
export const updateUserInfo = (params) => request.post(`${userApi}/mgr/user/editUserInfo`, params);
|
|
5
|
-
export const reloadUserInfo = () => request.post('/reloadUserInfo', {});
|
|
5
|
+
export const reloadUserInfo = () => request.post('/auth/reloadUserInfo', {});
|
|
6
6
|
export const queryUserByIds = (userIds) => request.post(`${userApi}/open/userQuery/queryUsersByIds`, userIds);
|
|
@@ -11,7 +11,7 @@ import React, { memo } from 'react';
|
|
|
11
11
|
import CameraResult from './CameraResult';
|
|
12
12
|
import CameraCapture, { buildPictureData } from './CameraCapture';
|
|
13
13
|
import { Modal, Platform, StatusBar, NativeModules } from "react-native";
|
|
14
|
-
import { toAbsolutePath } from "../../utils/file";
|
|
14
|
+
import { toAbsolutePath, toFullPath } from "../../utils/file";
|
|
15
15
|
import PhotoEditor from "@baronha/react-native-photo-editor";
|
|
16
16
|
const Camera = memo(props => {
|
|
17
17
|
const { horizontal = true, cancelCamera, finishTakePicture, finishTakeRecord, } = props;
|
|
@@ -31,7 +31,8 @@ const Camera = memo(props => {
|
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
33
|
try {
|
|
34
|
-
|
|
34
|
+
console.log('editPicture', result.localPath, toFullPath(result.localPath));
|
|
35
|
+
const file = yield NativeModules.PictureEditingModule.editPicture(toFullPath(result.localPath));
|
|
35
36
|
console.log(file.uri);
|
|
36
37
|
file.path = file.uri;
|
|
37
38
|
const fileInfo = yield buildPictureData(file);
|
|
@@ -8,13 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import React, { memo, useEffect, useState, useCallback, useRef } from 'react';
|
|
11
|
-
import { StyleSheet, Text, TouchableOpacity, View, Animated, Dimensions } from 'react-native';
|
|
11
|
+
import { StyleSheet, Text, TouchableOpacity, View, Animated, Dimensions, Platform } from 'react-native';
|
|
12
12
|
import { Camera, useCameraDevice, useCameraFormat, useMicrophonePermission } from 'react-native-vision-camera';
|
|
13
13
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
|
14
14
|
import { numberToTime, ResourceType } from '@smart-link/im-base';
|
|
15
|
-
import { moveFile, requestSaveFilePermissionIfAndroid,
|
|
15
|
+
import { moveFile, requestSaveFilePermissionIfAndroid, toFullPath } from '../../utils/file';
|
|
16
16
|
import { getImManager } from '../../init';
|
|
17
|
-
import { dp, CaihIcon } from '@smart-link/rn-ui';
|
|
17
|
+
import { dp, CaihIcon, Toast } from '@smart-link/rn-ui';
|
|
18
18
|
import { createVideoThumbnail, Image, Video, getFileSize, uuidv4 } from 'react-native-compressor';
|
|
19
19
|
const { PICTURE, VIDEO } = ResourceType;
|
|
20
20
|
const FlashModeValue = ['on', 'off', 'auto'];
|
|
@@ -28,7 +28,8 @@ const CameraCapture = memo(props => {
|
|
|
28
28
|
const camera = useRef(null);
|
|
29
29
|
const [cameraTypeIndex, setCameraTypeIndex] = useState(0);
|
|
30
30
|
const [isRecording, setIsRecording] = useState(false);
|
|
31
|
-
const [flashModeIndex, setFlashModeIndex] = useState(
|
|
31
|
+
const [flashModeIndex, setFlashModeIndex] = useState(1);
|
|
32
|
+
const toast = useRef();
|
|
32
33
|
const microphone = useMicrophonePermission();
|
|
33
34
|
const device = useCameraDevice(CameraTypeValue[cameraTypeIndex]);
|
|
34
35
|
const format = useCameraFormat(device, [
|
|
@@ -39,6 +40,7 @@ const CameraCapture = memo(props => {
|
|
|
39
40
|
}
|
|
40
41
|
]);
|
|
41
42
|
const takePicture = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
var _a, _b;
|
|
42
44
|
if (camera.current && !isRecording) {
|
|
43
45
|
const success = yield requestSaveFilePermissionIfAndroid(getImManager());
|
|
44
46
|
if (!success) {
|
|
@@ -46,10 +48,29 @@ const CameraCapture = memo(props => {
|
|
|
46
48
|
}
|
|
47
49
|
const photo = yield camera.current.takePhoto({
|
|
48
50
|
flash: FlashModeValue[flashModeIndex],
|
|
51
|
+
enableShutterSound: false,
|
|
49
52
|
});
|
|
50
53
|
console.log('photo: ', photo);
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
if (Platform.OS === 'android') {
|
|
55
|
+
toast.current = Toast.loading();
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const pictureData = yield buildPictureData(photo);
|
|
59
|
+
if (Platform.OS === 'android') {
|
|
60
|
+
(_a = toast.current) === null || _a === void 0 ? void 0 : _a.close();
|
|
61
|
+
toast.current = null;
|
|
62
|
+
}
|
|
63
|
+
finishTakePicture === null || finishTakePicture === void 0 ? void 0 : finishTakePicture(pictureData);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
console.log('take picture error: ', e);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
if (Platform.OS === 'android') {
|
|
70
|
+
(_b = toast.current) === null || _b === void 0 ? void 0 : _b.close();
|
|
71
|
+
toast.current = null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
53
74
|
}
|
|
54
75
|
});
|
|
55
76
|
const takeRecord = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -63,9 +84,28 @@ const CameraCapture = memo(props => {
|
|
|
63
84
|
videoCodec: 'h264',
|
|
64
85
|
fileType: 'mp4',
|
|
65
86
|
onRecordingFinished: (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
87
|
+
var _c, _d;
|
|
66
88
|
console.log('onRecordingFinished: ', data);
|
|
67
|
-
|
|
68
|
-
|
|
89
|
+
if (Platform.OS === 'android') {
|
|
90
|
+
toast.current = Toast.loading();
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const videoData = yield buildVideoData(data);
|
|
94
|
+
if (Platform.OS === 'android') {
|
|
95
|
+
(_c = toast.current) === null || _c === void 0 ? void 0 : _c.close();
|
|
96
|
+
toast.current = null;
|
|
97
|
+
}
|
|
98
|
+
finishTakeRecord === null || finishTakeRecord === void 0 ? void 0 : finishTakeRecord(videoData);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
console.log('record error: ', e);
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
if (Platform.OS === 'android') {
|
|
105
|
+
(_d = toast.current) === null || _d === void 0 ? void 0 : _d.close();
|
|
106
|
+
toast.current = null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
69
109
|
}),
|
|
70
110
|
onRecordingError: (error) => {
|
|
71
111
|
console.log('onRecordingError: ', error);
|
|
@@ -75,12 +115,14 @@ const CameraCapture = memo(props => {
|
|
|
75
115
|
}
|
|
76
116
|
});
|
|
77
117
|
const stopRecord = () => {
|
|
78
|
-
var _a;
|
|
118
|
+
var _a, _b;
|
|
79
119
|
console.log('stopRecord: ', isRecording);
|
|
80
120
|
if (isRecording) {
|
|
81
121
|
(_a = camera.current) === null || _a === void 0 ? void 0 : _a.stopRecording();
|
|
82
122
|
setIsRecording(false);
|
|
83
123
|
}
|
|
124
|
+
(_b = toast.current) === null || _b === void 0 ? void 0 : _b.close();
|
|
125
|
+
toast.current = null;
|
|
84
126
|
};
|
|
85
127
|
const switchCameraType = useCallback(() => {
|
|
86
128
|
const index = (cameraTypeIndex + 1) % 2;
|
|
@@ -98,6 +140,13 @@ const CameraCapture = memo(props => {
|
|
|
98
140
|
}
|
|
99
141
|
cancelCamera && cancelCamera();
|
|
100
142
|
};
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
return () => {
|
|
145
|
+
var _a;
|
|
146
|
+
(_a = toast.current) === null || _a === void 0 ? void 0 : _a.close();
|
|
147
|
+
toast.current = null;
|
|
148
|
+
};
|
|
149
|
+
}, []);
|
|
101
150
|
return (<View style={styles.camera}>
|
|
102
151
|
{device ? (<Camera ref={camera} device={device} format={format} isActive={true} style={styles.preview} photo={true} video={true} audio={microphone.hasPermission} outputOrientation="portrait" onInitialized={() => {
|
|
103
152
|
console.log('Camera initialized!');
|
|
@@ -273,7 +322,7 @@ export function buildPictureData(data) {
|
|
|
273
322
|
compressionMethod: 'auto'
|
|
274
323
|
});
|
|
275
324
|
const localPath = yield moveFile(tmp, filename, PICTURE);
|
|
276
|
-
const size = yield getFileSize(localPath);
|
|
325
|
+
const size = yield getFileSize(toFullPath(localPath));
|
|
277
326
|
let width = data.width;
|
|
278
327
|
let height = data.height;
|
|
279
328
|
if (data.orientation === 'portrait') {
|
|
@@ -297,14 +346,14 @@ function buildVideoData(data) {
|
|
|
297
346
|
const uid = uuidv4();
|
|
298
347
|
const path = data.path;
|
|
299
348
|
try {
|
|
300
|
-
const compressPath = yield Video.compress(
|
|
349
|
+
const compressPath = yield Video.compress(path, {
|
|
301
350
|
compressionMethod: 'auto',
|
|
302
351
|
maxSize: 1080,
|
|
303
352
|
});
|
|
304
353
|
const ext = compressPath.split('.').pop();
|
|
305
354
|
const filename = VIDEO + '_' + uid + '.' + ext;
|
|
306
355
|
const size = yield getFileSize(compressPath);
|
|
307
|
-
let thumb = yield createVideoThumbnail(
|
|
356
|
+
let thumb = yield createVideoThumbnail(compressPath);
|
|
308
357
|
console.log('RNThumbnail', thumb);
|
|
309
358
|
const imageName = 'thumb_' + uid + '.jpg';
|
|
310
359
|
const imagePath = yield moveFile(thumb.path, imageName, VIDEO);
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ConversationType } from '@smart-link/im-base';
|
|
3
|
-
import { ChatAvatarIdProps } from "./ChatAvatarId";
|
|
4
3
|
type ChatAvatarProps = {
|
|
5
4
|
id: string;
|
|
6
5
|
name: string;
|
|
7
6
|
url?: string;
|
|
8
7
|
type?: ConversationType;
|
|
9
8
|
size?: number;
|
|
9
|
+
needUpdate?: boolean;
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
editable?: boolean;
|
|
12
12
|
onUpdate?: (url: string) => void;
|
|
13
|
-
}
|
|
14
|
-
declare const _default: React.MemoExoticComponent<({ id, name, url: fileId, size, disabled, type, editable, onUpdate,
|
|
13
|
+
};
|
|
14
|
+
declare const _default: React.MemoExoticComponent<({ id, name, url: fileId, size, disabled, type, needUpdate, editable, onUpdate, }: ChatAvatarProps) => React.JSX.Element>;
|
|
15
15
|
export default _default;
|
|
@@ -7,7 +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 { Avatar, dp, useNavigation } from '@smart-link/rn-ui';
|
|
10
|
+
import { Avatar, dp, Toast, useNavigation } from '@smart-link/rn-ui';
|
|
11
11
|
import React, { memo } from 'react';
|
|
12
12
|
import { Image, TouchableOpacity } from 'react-native';
|
|
13
13
|
import ImagePicker from 'react-native-image-crop-picker';
|
|
@@ -15,77 +15,79 @@ import { getImManager } from '../../init';
|
|
|
15
15
|
import { ConversationActions, ConversationType, updateGroupInfo } from '@smart-link/im-base';
|
|
16
16
|
import { defaultAvatars } from '../../default-assets';
|
|
17
17
|
import uploadFile from '../../utils/upload';
|
|
18
|
-
import { updateUserInfo } from '../../api/user';
|
|
19
|
-
import { useAuth } from '../../hooks/useImSelector';
|
|
18
|
+
import { reloadUserInfo, updateUserInfo } from '../../api/user';
|
|
20
19
|
import { moveFile } from "../../utils/file";
|
|
21
20
|
import ChatAvatarId from "./ChatAvatarId";
|
|
22
21
|
import useImReady from "../../hooks/useImReady";
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
import { uuidv4 } from "react-native-compressor";
|
|
23
|
+
import useTranslation from "../../hooks/useTranslation";
|
|
24
|
+
import to from "await-to-js";
|
|
25
|
+
const ChatAvatar = ({ id, name, url: fileId, size = dp(40), disabled, type = ConversationType.C2C, needUpdate, editable, onUpdate, }) => {
|
|
25
26
|
const navigation = useNavigation();
|
|
26
27
|
const ready = useImReady();
|
|
28
|
+
const { t } = useTranslation();
|
|
27
29
|
const defaultAvatar = {
|
|
28
30
|
[ConversationType.C2C]: defaultAvatars.EMPTY,
|
|
29
31
|
[ConversationType.C2G]: defaultAvatars.GROUP,
|
|
30
32
|
[ConversationType.B2C]: defaultAvatars.BUSI_NOTIFY,
|
|
31
33
|
}[type] || defaultAvatars.EMPTY;
|
|
32
|
-
const
|
|
34
|
+
const onPress = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
if (disabled)
|
|
36
|
+
return;
|
|
33
37
|
if (editable) {
|
|
34
38
|
const imManager = getImManager();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
console.log('pick cancel: ', e);
|
|
39
|
+
imManager.setNetwork(false);
|
|
40
|
+
const [err, image] = yield to(ImagePicker.openPicker({
|
|
41
|
+
cropping: true,
|
|
42
|
+
width: 300,
|
|
43
|
+
height: 300,
|
|
44
|
+
compressImageQuality: 0.7,
|
|
45
|
+
}));
|
|
46
|
+
imManager.setNetwork(true);
|
|
47
|
+
if (err) {
|
|
48
|
+
console.log('pick cancel: ', err);
|
|
46
49
|
return;
|
|
47
50
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
51
|
+
try {
|
|
52
|
+
const localPath = yield moveFile(image.path, uuidv4() + '.jpg', 'avatars');
|
|
53
|
+
const newFileId = yield uploadFile(localPath, image.mime);
|
|
54
|
+
if (type === ConversationType.C2C) {
|
|
55
|
+
imManager.user.avatars = newFileId;
|
|
56
|
+
const user = imManager.user;
|
|
57
|
+
yield updateUserInfo({
|
|
58
|
+
userId: user.userId,
|
|
59
|
+
userName: user.userName,
|
|
60
|
+
avatars: newFileId,
|
|
61
|
+
mobile: user.mobile,
|
|
62
|
+
});
|
|
63
|
+
yield reloadUserInfo();
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// 更新群头像
|
|
67
|
+
yield updateGroupInfo({
|
|
68
|
+
chatGroupId: id,
|
|
69
|
+
avatars: newFileId,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(newFileId);
|
|
73
|
+
yield imManager.store.dispatch(ConversationActions.updateAvatars(imManager, id, newFileId));
|
|
63
74
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
chatGroupId: id,
|
|
68
|
-
avatars: fileId,
|
|
69
|
-
});
|
|
75
|
+
catch (e) {
|
|
76
|
+
console.log('[ChatAvatar] update avatar error: ', e);
|
|
77
|
+
Toast.error(t('avatarsUpdateFail'));
|
|
70
78
|
}
|
|
71
|
-
// 更新本地资源
|
|
72
|
-
imManager.updateResource({ url: fileId, localPath });
|
|
73
|
-
imManager.store.dispatch(ConversationActions.updateAvatars(imManager, id, fileId));
|
|
74
|
-
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(fileId);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
const onPress = () => {
|
|
78
|
-
if (disabled || editable)
|
|
79
79
|
return;
|
|
80
|
+
}
|
|
80
81
|
if (type === ConversationType.C2C) {
|
|
81
82
|
// 跳转到个人详情页
|
|
82
83
|
navigation.navigate('UserDetail', {
|
|
83
84
|
userId: id,
|
|
84
85
|
});
|
|
85
86
|
}
|
|
86
|
-
};
|
|
87
|
-
return (<TouchableOpacity style={{ width: size, height: size }} disabled={disabled} onPress={onPress}
|
|
88
|
-
{ready ? <ChatAvatarId
|
|
87
|
+
});
|
|
88
|
+
return (<TouchableOpacity style={{ width: size, height: size }} disabled={disabled} onPress={onPress}>
|
|
89
|
+
{ready ? <ChatAvatarId needUpdate={needUpdate} id={id} fileId={fileId} size={size} name={name} defaultAvatar={defaultAvatar}/> :
|
|
90
|
+
<Avatar icon={<Image style={size ? { width: size, height: size } : {}} source={defaultAvatar}/>}/>}
|
|
89
91
|
</TouchableOpacity>);
|
|
90
92
|
};
|
|
91
93
|
export default memo(ChatAvatar);
|
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import { ChatAvatarProps } from "./ChatAvatarLocal";
|
|
3
3
|
export interface ChatAvatarIdProps extends ChatAvatarProps {
|
|
4
4
|
id: string;
|
|
5
|
-
|
|
5
|
+
needUpdate?: boolean;
|
|
6
6
|
}
|
|
7
|
-
declare const _default: React.MemoExoticComponent<({ id, fileId: fileIdProp,
|
|
7
|
+
declare const _default: React.MemoExoticComponent<({ id, fileId: fileIdProp, needUpdate, ...ret }: ChatAvatarIdProps) => React.JSX.Element>;
|
|
8
8
|
export default _default;
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
2
|
var t = {};
|
|
12
3
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -19,49 +10,31 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
19
10
|
return t;
|
|
20
11
|
};
|
|
21
12
|
import * as React from 'react';
|
|
22
|
-
import { memo, useEffect, useState } from
|
|
23
|
-
import { getImManager } from "../../init";
|
|
13
|
+
import { memo, useEffect, useState } from 'react';
|
|
24
14
|
import ChatAvatarLocal from "./ChatAvatarLocal";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
15
|
+
import { getImManager } from "../../init";
|
|
16
|
+
import { AvatarSubscribe } from '@smart-link/im-base';
|
|
27
17
|
const ChatAvatarId = (_a) => {
|
|
28
|
-
var { id, fileId: fileIdProp,
|
|
29
|
-
const [fileId, setFileId] = useState(fileIdProp);
|
|
30
|
-
const cacheFileId = useAvatars()[id];
|
|
18
|
+
var { id, fileId: fileIdProp, needUpdate } = _a, ret = __rest(_a, ["id", "fileId", "needUpdate"]);
|
|
19
|
+
const [fileId, setFileId] = useState(fileIdProp || '');
|
|
31
20
|
useEffect(() => {
|
|
32
|
-
if (
|
|
21
|
+
if (fileIdProp) {
|
|
33
22
|
setFileId(fileIdProp);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (priority === 'cache' && cacheFileId) {
|
|
38
|
-
setFileId(cacheFileId);
|
|
39
|
-
return;
|
|
23
|
+
if (needUpdate) {
|
|
24
|
+
getImManager().updateAvatar({ avatarsId: id, url: fileIdProp }).then(r => { });
|
|
25
|
+
}
|
|
40
26
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const { data: [user] } = yield queryUserByIds([id]);
|
|
46
|
-
if (user === null || user === void 0 ? void 0 : user.avatars) {
|
|
47
|
-
if (fileId !== user.avatars) {
|
|
48
|
-
setFileId(user.avatars);
|
|
49
|
-
getImManager().updateAvatar({ avatarsId: id, url: user.avatars });
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
setFileId('');
|
|
54
|
-
}
|
|
27
|
+
else {
|
|
28
|
+
getImManager().loadAvatarFromCache(id).then(fileId => {
|
|
29
|
+
if (fileId) {
|
|
30
|
+
setFileId(fileId);
|
|
55
31
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
}));
|
|
64
|
-
}, [id, priority, fileIdProp, cacheFileId]);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return AvatarSubscribe.subscribe(id, (fileId) => {
|
|
35
|
+
setFileId(fileId);
|
|
36
|
+
});
|
|
37
|
+
}, [id, needUpdate, fileIdProp]);
|
|
65
38
|
return (<ChatAvatarLocal fileId={fileId} {...ret}/>);
|
|
66
39
|
};
|
|
67
40
|
export default memo(ChatAvatarId);
|
|
@@ -14,6 +14,7 @@ import { useEffect, useState } from "react";
|
|
|
14
14
|
import { getImManager } from "../../init";
|
|
15
15
|
import RNFS from "react-native-fs";
|
|
16
16
|
import LocalImage from "../../components/LocalImage";
|
|
17
|
+
import { toAbsolutePath } from "../../utils/file";
|
|
17
18
|
// 防止重复下载
|
|
18
19
|
const downloadMap = Object.create(null);
|
|
19
20
|
const cacheMap = Object.create(null);
|
|
@@ -26,12 +27,24 @@ const ChatAvatarLocal = ({ fileId, size, name, defaultAvatar }) => {
|
|
|
26
27
|
setReady(true);
|
|
27
28
|
return;
|
|
28
29
|
}
|
|
30
|
+
const fetchFromCache = (fileId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
setTimeout(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
33
|
+
if (cacheMap[fileId]) {
|
|
34
|
+
setAvatar(cacheMap[fileId]);
|
|
35
|
+
resolve(cacheMap[fileId]);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
yield fetchFromCache(fileId);
|
|
39
|
+
}
|
|
40
|
+
}), 16);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
29
43
|
if (fileId) {
|
|
30
44
|
const imManager = getImManager();
|
|
31
45
|
const localPath = yield imManager.loadResourceFromCache(fileId);
|
|
32
|
-
// console.log('loadResourceFromCache: ', localPath)
|
|
33
46
|
if (localPath) {
|
|
34
|
-
const exists = yield RNFS.exists(localPath);
|
|
47
|
+
const exists = yield RNFS.exists(toAbsolutePath(localPath));
|
|
35
48
|
if (exists) {
|
|
36
49
|
cacheMap[fileId] = localPath;
|
|
37
50
|
setAvatar(localPath);
|
|
@@ -39,13 +52,14 @@ const ChatAvatarLocal = ({ fileId, size, name, defaultAvatar }) => {
|
|
|
39
52
|
return;
|
|
40
53
|
}
|
|
41
54
|
}
|
|
42
|
-
if (downloadMap[fileId]) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
downloadMap[fileId] = true;
|
|
46
55
|
try {
|
|
47
|
-
console.log('imManager.download: ', fileId, Number.isNaN(Number(fileId)));
|
|
48
56
|
if (Number.isNaN(Number(fileId))) {
|
|
57
|
+
if (downloadMap[fileId]) {
|
|
58
|
+
// 等待下载完成,从缓存获取
|
|
59
|
+
yield fetchFromCache(fileId);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
downloadMap[fileId] = true;
|
|
49
63
|
// 下载头像文件
|
|
50
64
|
const localPath = yield imManager.download({
|
|
51
65
|
fileId,
|
|
@@ -67,8 +81,7 @@ const ChatAvatarLocal = ({ fileId, size, name, defaultAvatar }) => {
|
|
|
67
81
|
setReady(true);
|
|
68
82
|
}
|
|
69
83
|
}
|
|
70
|
-
|
|
71
|
-
downloadMap[fileId] = false;
|
|
84
|
+
finally {
|
|
72
85
|
}
|
|
73
86
|
}
|
|
74
87
|
else {
|
|
@@ -7,6 +7,8 @@ const LocalImage = memo(props => {
|
|
|
7
7
|
if (Object.prototype.toString.call(localPath) === '[object String]') {
|
|
8
8
|
source = { uri: toAbsolutePath(localPath) };
|
|
9
9
|
}
|
|
10
|
-
return <Image style={style} resizeMode={resizeMode} source={source}
|
|
10
|
+
return <Image style={style} resizeMode={resizeMode} source={source} onError={(e) => {
|
|
11
|
+
console.log('local image error: ', localPath);
|
|
12
|
+
}}/>;
|
|
11
13
|
});
|
|
12
14
|
export default LocalImage;
|
|
@@ -6,8 +6,14 @@ export declare const shadowStyle: {
|
|
|
6
6
|
};
|
|
7
7
|
shadowRadius: number;
|
|
8
8
|
shadowOpacity: number;
|
|
9
|
+
elevation?: undefined;
|
|
10
|
+
} | {
|
|
9
11
|
elevation: number;
|
|
10
|
-
|
|
12
|
+
shadowColor?: undefined;
|
|
13
|
+
shadowOffset?: undefined;
|
|
14
|
+
shadowRadius?: undefined;
|
|
15
|
+
shadowOpacity?: undefined;
|
|
16
|
+
} | undefined;
|
|
11
17
|
export declare const borderStyle: {
|
|
12
18
|
borderRadius: number;
|
|
13
19
|
};
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import { dp } from '@smart-link/rn-ui';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { Platform } from "react-native";
|
|
3
|
+
export const shadowStyle = Platform.select({
|
|
4
|
+
ios: {
|
|
5
|
+
shadowColor: '#eee',
|
|
6
|
+
shadowOffset: {
|
|
7
|
+
width: 0,
|
|
8
|
+
height: dp(2),
|
|
9
|
+
},
|
|
10
|
+
shadowRadius: dp(3),
|
|
11
|
+
shadowOpacity: 1,
|
|
7
12
|
},
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
13
|
+
android: {
|
|
14
|
+
elevation: 2,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
12
17
|
export const borderStyle = {
|
|
13
18
|
borderRadius: dp(5),
|
|
14
19
|
};
|
|
15
20
|
export const plain = {
|
|
16
|
-
color: '#
|
|
17
|
-
fontSize: dp(
|
|
21
|
+
color: '#222',
|
|
22
|
+
fontSize: dp(15),
|
|
18
23
|
paddingHorizontal: dp(12),
|
|
19
24
|
paddingVertical: dp(10),
|
|
20
25
|
};
|