From 03453b13e83845e8c7f712dbfd61e4da9c1a7d15 Mon Sep 17 00:00:00 2001 From: leeing <372711472@qq.com> Date: Thu, 22 Feb 2024 19:25:06 +0800 Subject: [PATCH] update uikit 9.8.0 --- react/package.json | 2 +- react/src/YXUIKit/im-kit-ui/package.json | 12 +-- .../components/ChatMessageInput/index.tsx | 102 +++++++++++++++--- .../ChatMessageInput/style/index.ts | 2 + .../chat/components/ChatMessageItem/index.tsx | 30 +++++- .../components/ChatP2pMessageList/index.tsx | 6 ++ .../components/ChatTeamMessageList/index.tsx | 6 ++ .../src/chat/containers/p2pChatContainer.tsx | 44 +++++++- .../src/chat/containers/teamChatContainer.tsx | 44 +++++++- .../components/CommonParseSession/index.tsx | 72 +++++++++++-- .../CommonParseSession/style/index.less | 50 ++++++++- .../CommonParseSession/style/index.ts | 1 + .../im-kit-ui/src/common/locales/zh.ts | 4 +- .../YXUIKit/im-kit-ui/src/uploadingTask.ts | 22 ++++ react/src/YXUIKit/im-kit-ui/src/utils.ts | 39 +++++++ vue/package.json | 2 +- 16 files changed, 393 insertions(+), 45 deletions(-) create mode 100644 react/src/YXUIKit/im-kit-ui/src/uploadingTask.ts diff --git a/react/package.json b/react/package.json index 3db187e..916bf8b 100644 --- a/react/package.json +++ b/react/package.json @@ -9,7 +9,7 @@ "dependencies": { "@xkit-yx/call-kit": "^2.0.1", "@xkit-yx/call-kit-react-ui": "^0.4.1", - "@xkit-yx/im-kit-ui": "^9.7.0", + "@xkit-yx/im-kit-ui": "^9.8.0", "react-dom": "^16.8.0", "umi": "^3.5.40" }, diff --git a/react/src/YXUIKit/im-kit-ui/package.json b/react/src/YXUIKit/im-kit-ui/package.json index 66f519a..04a8dc9 100644 --- a/react/src/YXUIKit/im-kit-ui/package.json +++ b/react/src/YXUIKit/im-kit-ui/package.json @@ -1,6 +1,6 @@ { "name": "@xkit-yx/im-kit-ui", - "version": "9.7.0", + "version": "9.8.0", "description": "云信即时通讯组件", "license": "MIT", "main": "lib/index.js", @@ -33,7 +33,7 @@ "gulp-typescript": "^6.0.0-alpha.1", "less": "^4.1.1", "less-plugin-npm-import": "^2.1.0", - "nim-web-sdk-ng": "0.15.0", + "nim-web-sdk-ng": "0.17.0", "postcss": "^8.3.5", "postcss-nested": "^5.0.5", "react": "^16.8.0", @@ -41,7 +41,7 @@ "rollup": "^2.39.0", "rollup-plugin-postcss": "^4.0.0", "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-typescript2": "^0.30.0", + "rollup-plugin-typescript2": "^0.31.0", "sass": "^1.58.3", "typescript": "^4.6.4" }, @@ -56,13 +56,13 @@ }, "dependencies": { "@ant-design/icons": "^5.0.1", - "@xkit-yx/core-kit": "^0.11.0", - "@xkit-yx/im-store": "^0.1.0", + "@xkit-yx/core-kit": "^0.13.0", + "@xkit-yx/im-store": "^0.2.0", "@xkit-yx/utils": "^0.5.6", "antd": "^4.16.3", "mobx": "^6.6.1", "mobx-react": "^7.5.2", "react-string-replace": "^1.1.0" }, - "gitHead": "f3ce7aa9536c224fcdc0e4a1a26b333be1036442" + "gitHead": "2460a56b946207f24db9a8d74c10d3776aa5f267" } diff --git a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageInput/index.tsx b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageInput/index.tsx index 73714d4..5ee4692 100644 --- a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageInput/index.tsx +++ b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageInput/index.tsx @@ -8,7 +8,16 @@ import React, { useCallback, useEffect, } from 'react' -import { Input, Upload, Popover, message, Button, Spin } from 'antd' +import { + Input, + Upload, + Popover, + message, + Button, + Spin, + Dropdown, + Menu, +} from 'antd' import { IMMessage } from 'nim-web-sdk-ng/dist/NIM_BROWSER_SDK/MsgServiceInterface' import { CommonIcon, @@ -48,6 +57,7 @@ export interface ChatMessageInputProps { onSendText: (value: string, ext?: Record) => void onSendFile: (file: File) => void onSendImg: (file: File) => void + onSendVideo: (file: File) => void onRemoveReplyMsg?: () => void } @@ -80,6 +90,7 @@ const ChatMessageInput = observer( onSendText, onSendFile, onSendImg, + onSendVideo, onRemoveReplyMsg, } = props const _prefix = `${prefix}-message-input` @@ -108,7 +119,7 @@ const ChatMessageInput = observer( visible: true, render: () => { return ( - ) }, @@ -486,6 +536,24 @@ const ChatMessageInput = observer( return false } + const onBeforeUploadVideoHandler = ( + file: File + ): boolean | Promise => { + const isLimit = file.size / 1024 / 1000 > MAX_UPLOAD_FILE_SIZE + + if (isLimit) { + message.error( + `${t('uploadLimitText')}${MAX_UPLOAD_FILE_SIZE}${t( + 'uploadLimitUnit' + )}` + ) + } else { + onSendVideo(file) + } + + return false + } + // const onUploadImgHandler = (file: any): any => { // onSendImg(file) // } diff --git a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageInput/style/index.ts b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageInput/style/index.ts index d283ede..a423b10 100644 --- a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageInput/style/index.ts +++ b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageInput/style/index.ts @@ -4,5 +4,7 @@ import 'antd/lib/upload/style' import 'antd/lib/message/style' import 'antd/lib/button/style' import 'antd/lib/spin/style' +import 'antd/lib/dropdown/style' +import 'antd/lib/menu/style' import './chatAtMemberList.less' import './index.less' diff --git a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageItem/index.tsx b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageItem/index.tsx index e351d10..96f20bd 100644 --- a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageItem/index.tsx +++ b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatMessageItem/index.tsx @@ -41,6 +41,8 @@ export interface MessageItemProps { replyMsg?: IMMessage normalStatusRenderer?: React.ReactNode msgOperMenu?: MsgOperMenuItem[] + onSendImg: (file: File, randomId?: string) => Promise + onSendVideo: (file: File, randomId?: string) => Promise onResend: (msg: IMMessage) => void onReeditClick: (msg: IMMessage) => void onMessageAction: (key: MenuItemKey, msg: IMMessage) => void @@ -61,6 +63,8 @@ export const ChatMessageItem: React.FC = observer( normalStatusRenderer, msgOperMenu, onResend, + onSendImg, + onSendVideo, onMessageAction, onMessageAvatarAction, onReeditClick, @@ -83,6 +87,10 @@ export const ChatMessageItem: React.FC = observer( attach, idClient, status, + // @ts-ignore + uploadProgress, + // @ts-ignore + uploadFileInfo, time, type, scene, @@ -113,6 +121,24 @@ export const ChatMessageItem: React.FC = observer( oldBody = '', } = attach || { type: '', canRecall: false, canEdit: false, oldBody: '' } + const handleResendMsg = () => { + // 如果是上传过程中失败的图片和视频消息,则重新发送 + if (uploadFileInfo && ['image', 'video'].includes(msg.type)) { + switch (msg.type) { + case 'image': + onSendImg(uploadFileInfo.file, msg.idClient) + break + case 'video': + onSendVideo(uploadFileInfo.file, msg.idClient) + break + default: + break + } + } else { + onResend(msg) + } + } + const renderSendStatus = () => { if (status === 'sending') { return @@ -125,7 +151,7 @@ export const ChatMessageItem: React.FC = observer( onResend(msg)} + onClick={handleResendMsg} /> ) @@ -170,7 +196,7 @@ export const ChatMessageItem: React.FC = observer( icon: , }, { - show: 1, + show: uploadProgress === void 0 ? 1 : 0, label: t('deleteText'), key: 'delete', icon: , diff --git a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatP2pMessageList/index.tsx b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatP2pMessageList/index.tsx index 7b8e8cb..c0fd99a 100644 --- a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatP2pMessageList/index.tsx +++ b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatP2pMessageList/index.tsx @@ -48,6 +48,8 @@ const ChatP2pMessageList = observer( noMore, myAccount, onResend, + onSendImg, + onSendVideo, onMessageAction, onReeditClick, onScroll, @@ -79,6 +81,8 @@ const ChatP2pMessageList = observer( replyMsg: replyMsgsMap[msg.idClient], member, onResend, + onSendImg, + onSendVideo, onReeditClick, onMessageAction, }) ?? ( @@ -100,6 +104,8 @@ const ChatP2pMessageList = observer( } myAccount={myAccount} onResend={onResend} + onSendImg={onSendImg} + onSendVideo={onSendVideo} onMessageAction={onMessageAction} onReeditClick={onReeditClick} renderMessageAvatar={renderMessageAvatar} diff --git a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatTeamMessageList/index.tsx b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatTeamMessageList/index.tsx index 8481a74..73dc824 100644 --- a/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatTeamMessageList/index.tsx +++ b/react/src/YXUIKit/im-kit-ui/src/chat/components/ChatTeamMessageList/index.tsx @@ -51,6 +51,8 @@ const ChatTeamMessageList = forwardRef< noMore, myAccount, onResend, + onSendImg, + onSendVideo, onMessageAction, onMessageAvatarAction, onReeditClick, @@ -83,6 +85,8 @@ const ChatTeamMessageList = forwardRef< replyMsg: replyMsgsMap[msg.idClient], members, onResend, + onSendImg, + onSendVideo, onReeditClick, onMessageAction, }) ?? ( @@ -105,6 +109,8 @@ const ChatTeamMessageList = forwardRef< } myAccount={myAccount} onResend={onResend} + onSendImg={onSendImg} + onSendVideo={onSendVideo} onMessageAction={onMessageAction} onMessageAvatarAction={onMessageAvatarAction} onReeditClick={onReeditClick} diff --git a/react/src/YXUIKit/im-kit-ui/src/chat/containers/p2pChatContainer.tsx b/react/src/YXUIKit/im-kit-ui/src/chat/containers/p2pChatContainer.tsx index ebc98d2..3550a15 100644 --- a/react/src/YXUIKit/im-kit-ui/src/chat/containers/p2pChatContainer.tsx +++ b/react/src/YXUIKit/im-kit-ui/src/chat/containers/p2pChatContainer.tsx @@ -35,6 +35,8 @@ import { message } from 'antd' import { storeConstants } from '@xkit-yx/im-store' import { observer } from 'mobx-react' import ChatForwardModal from '../components/ChatForwardModal' +import { getImgDataUrl, getVideoFirstFrameDataUrl } from '../../utils' +import { addTask, removeTask } from '../../uploadingTask' export interface P2pChatContainerProps { scene: TMsgScene @@ -289,12 +291,49 @@ const P2pChatContainer: React.FC = observer( ) const onSendImg = useCallback( - async (file: File) => { + async (file: File, randomId?: string) => { try { + const previewImg = await getImgDataUrl(file) await store.msgStore.sendImageMsgActive({ scene, to, file, + previewImg, + randomId, + onUploadStart(task, taskId) { + scrollToBottom() + addTask(taskId, task) + }, + onUploadDone(taskId) { + removeTask(taskId) + }, + }) + } catch (error) { + // message.error(t('sendMsgFailedText')) + } finally { + scrollToBottom() + } + }, + [scene, store.msgStore, to, scrollToBottom] + ) + + const onSendVideo = useCallback( + async (file: File, randomId?: string) => { + try { + const previewImg = await getVideoFirstFrameDataUrl(file) + await store.msgStore.sendVideoMsgActive({ + scene, + to, + file, + previewImg, + randomId, + onUploadStart(task, taskId) { + scrollToBottom() + addTask(taskId, task) + }, + onUploadDone(taskId) { + removeTask(taskId) + }, }) } catch (error) { // message.error(t('sendMsgFailedText')) @@ -599,6 +638,8 @@ const P2pChatContainer: React.FC = observer( msgReceiptTime={session?.msgReceiptTime} onReceiveMsgBtnClick={scrollToBottom} onResend={onResend} + onSendImg={onSendImg} + onSendVideo={onSendVideo} onMessageAction={onMessageAction} onReeditClick={onReeditClick} onScroll={onMsgListScrollHandler} @@ -628,6 +669,7 @@ const P2pChatContainer: React.FC = observer( onSendText={onSendText} onSendFile={onSendFile} onSendImg={onSendImg} + onSendVideo={onSendVideo} onRemoveReplyMsg={onRemoveReplyMsg} /> = observer( ) const onSendImg = useCallback( - async (file: File) => { + async (file: File, randomId?: string) => { try { + const previewImg = await getImgDataUrl(file) await store.msgStore.sendImageMsgActive({ scene, to, file, + previewImg, + randomId, + onUploadStart(task, taskId) { + scrollToBottom() + addTask(taskId, task) + }, + onUploadDone(taskId) { + removeTask(taskId) + }, + }) + } catch (error) { + // message.error(t('sendMsgFailedText')) + } finally { + scrollToBottom() + } + }, + [scene, store.msgStore, to, scrollToBottom] + ) + + const onSendVideo = useCallback( + async (file: File, randomId?: string) => { + try { + const previewImg = await getVideoFirstFrameDataUrl(file) + await store.msgStore.sendVideoMsgActive({ + scene, + to, + file, + previewImg, + randomId, + onUploadStart(task, taskId) { + scrollToBottom() + addTask(taskId, task) + }, + onUploadDone(taskId) { + removeTask(taskId) + }, }) } catch (error) { // message.error(t('sendMsgFailedText')) @@ -1081,6 +1120,8 @@ const TeamChatContainer: React.FC = observer( receiveMsgBtnVisible={receiveMsgBtnVisible} onReceiveMsgBtnClick={scrollToBottom} onResend={onResend} + onSendImg={onSendImg} + onSendVideo={onSendVideo} onMessageAction={onMessageAction} onMessageAvatarAction={onMessageAvatarAction} onReeditClick={onReeditClick} @@ -1121,6 +1162,7 @@ const TeamChatContainer: React.FC = observer( onSendText={onSendText} onSendFile={onSendFile} onSendImg={onSendImg} + onSendVideo={onSendVideo} /> = observer( const { EMOJI_ICON_MAP_CONFIG, INPUT_EMOJI_SYMBOL_REG } = handleEmojiTranslate(t) - const renderCustomText = (msg) => { + const renderCustomText = (msg: IMMessage) => { const { body, idClient, ext } = msg let text = reactStringReplace(body, /(https?:\/\/\S+)/gi, (match, i) => ( @@ -160,7 +161,49 @@ export const ParseSession: React.FC = observer( handler() } - const renderImage = (msg, isReplyMsg: boolean) => { + const renderUploadMsg = (msg: IMMessage) => { + // @ts-ignore + const { uploadProgress, previewImg, idClient } = msg + + return ( +
+ +
+
{ + abortTask(idClient) + }} + > + +
+
+
+ ) + } + + const renderImage = (msg: IMMessage, isReplyMsg: boolean) => { + // @ts-ignore + const { uploadProgress, uploadFileInfo } = msg + + // uploadProgress 属性只会在上传中存在,uploadFileInfo 在上传中和上传失败时都存在 + if (uploadProgress !== void 0 || uploadFileInfo) { + return renderUploadMsg(msg) + } + return (
= observer( ) } - const renderFile = (msg) => { + const renderFile = (msg: IMMessage) => { return (
= observer( ) } - const renderNotification = (msg) => { + const renderNotification = (msg: IMMessage) => { switch (msg.attach?.type) { case 'updateTeam': { const team: Team = msg.attach?.team || {} @@ -430,7 +473,7 @@ export const ParseSession: React.FC = observer( } } - const renderAudio = (msg) => { + const renderAudio = (msg: IMMessage) => { const { flow, attach } = msg const duration = Math.floor(attach?.dur / 1000) || 0 @@ -482,13 +525,21 @@ export const ParseSession: React.FC = observer( ) } - const renderVideo = (msg) => { - const { attach } = msg + const renderVideo = (msg: IMMessage) => { + // @ts-ignore + const { uploadProgress, uploadFileInfo, attach } = msg + + // uploadProgress 属性只会在上传中存在,uploadFileInfo 在上传中和上传失败时都存在 + if (uploadProgress !== void 0 || uploadFileInfo) { + return renderUploadMsg(msg) + } + const url = `${attach?.url}?download=${msg.idClient}.${attach?.ext}` return (