Skip to content

Commit 2594c0d

Browse files
committed
update im 10.3.0
1 parent 3130651 commit 2594c0d

File tree

112 files changed

+5162
-1477
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+5162
-1477
lines changed

react/src/YXUIKit/im-kit-ui/package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@xkit-yx/im-kit-ui",
3-
"version": "10.0.1",
3+
"version": "10.3.0",
44
"description": "云信即时通讯组件",
55
"license": "MIT",
66
"main": "lib/index.js",
@@ -54,13 +54,13 @@
5454
},
5555
"dependencies": {
5656
"@ant-design/icons": "^5.0.1",
57-
"@xkit-yx/im-store-v2": "^0.1.1",
58-
"@xkit-yx/utils": "^0.6.0",
57+
"@xkit-yx/im-store-v2": "^0.2.0",
58+
"@xkit-yx/utils": "^0.7.1",
5959
"antd": "^4.16.3",
6060
"mobx": "^6.6.1",
6161
"mobx-react": "^7.5.2",
62-
"nim-web-sdk-ng": "10.2.700",
62+
"nim-web-sdk-ng": "10.3.0",
6363
"react-string-replace": "^1.1.0"
6464
},
65-
"gitHead": "4e09464e7bb40f8b578b2704e7931ea1e6928417"
65+
"gitHead": "5309f0b247ec3584301aa3ec5f8df0c3cbcd0966"
6666
}

react/src/YXUIKit/im-kit-ui/src/chat/Container.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { ReactNode } from 'react'
22
import P2pChatContainer from './containers/p2pChatContainer'
33
import TeamChatContainer from './containers/teamChatContainer'
4-
import { useStateContext, useEventTracking, Welcome, Utils } from '../common'
4+
import { useStateContext, useEventTracking, Welcome } from '../common'
55
import { RenderP2pCustomMessageOptions } from './components/ChatP2pMessageList'
66
import { RenderTeamCustomMessageOptions } from './components/ChatTeamMessageList'
77
import { ChatMessageInputProps } from './components/ChatMessageInput'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { Drawer, Input, message } from 'antd'
2+
import { observer } from 'mobx-react'
3+
import React, { FC, useState } from 'react'
4+
import { useStateContext, useTranslation } from '../../../common'
5+
import { LoadingOutlined } from '@ant-design/icons'
6+
import { V2NIMAIModelRoleType } from 'nim-web-sdk-ng/dist/v2/NIM_BROWSER_SDK/V2NIMAIService'
7+
import { getAIErrorMap } from '../../../utils'
8+
9+
export interface ChatAISearchProps {
10+
prefix?: string
11+
}
12+
13+
export const ChatAISearch: FC<ChatAISearchProps> = observer(
14+
({ prefix = 'chat' }) => {
15+
const _prefix = `${prefix}-ai-search`
16+
17+
const { store } = useStateContext()
18+
const { t } = useTranslation()
19+
20+
const aiErrorMap = getAIErrorMap(t)
21+
22+
const [inputValue, setInputValue] = useState('')
23+
24+
const title = store.aiUserStore.aiProxying ? (
25+
<div className={`${_prefix}-title`}>
26+
<LoadingOutlined style={{ color: '#1861df' }} />
27+
<span style={{ marginLeft: '5px' }}>{t('aiSearchingText')}</span>
28+
</div>
29+
) : (
30+
<div>{t('aiSearchText')}</div>
31+
)
32+
33+
const onInputChangeHandler = (
34+
e: React.ChangeEvent<HTMLTextAreaElement>
35+
) => {
36+
setInputValue(e.target.value)
37+
}
38+
39+
const onPressEnterHandler = (
40+
e: React.KeyboardEvent<HTMLTextAreaElement>
41+
) => {
42+
const trimValue = inputValue.trim()
43+
44+
if (!e.shiftKey) {
45+
e.preventDefault()
46+
if (!trimValue) {
47+
message.warning(t('sendEmptyText'))
48+
return
49+
}
50+
51+
const aiSearchUser = store.aiUserStore.getAISearchUser()
52+
53+
if (aiSearchUser) {
54+
store.aiUserStore
55+
.sendAIProxyActive({
56+
accountId: aiSearchUser.accountId,
57+
content: { msg: trimValue, type: 0 },
58+
messages: store.aiUserStore.aiReqMsgs.map((item) => ({
59+
role: 'user' as V2NIMAIModelRoleType,
60+
...item,
61+
})),
62+
onSendAIProxyErrorHandler: (code: number) => {
63+
const errorText = aiErrorMap[code] || t('aiProxyFailedText')
64+
65+
message.error(errorText)
66+
},
67+
})
68+
.catch(() => {
69+
//
70+
})
71+
}
72+
73+
setInputValue('')
74+
}
75+
}
76+
77+
const onCloseHandler = () => {
78+
store.aiUserStore.resetAIProxy()
79+
}
80+
81+
return (
82+
<Drawer
83+
mask={false}
84+
maskClosable={false}
85+
placement="bottom"
86+
open={store.aiUserStore.isAISearching()}
87+
closable={true}
88+
getContainer={false}
89+
title={title}
90+
onClose={onCloseHandler}
91+
keyboard={false}
92+
className={_prefix}
93+
>
94+
<div className={`${_prefix}-content`}>
95+
<Input.TextArea
96+
placeholder={t('aiSearchInputPlaceholder')}
97+
bordered={true}
98+
className={`${_prefix}-textarea`}
99+
value={inputValue}
100+
onInput={onInputChangeHandler}
101+
onPressEnter={onPressEnterHandler}
102+
autoSize={{ maxRows: 3 }}
103+
/>
104+
<div className={`${_prefix}-tip`}>{t('searchTipText')}</div>
105+
<div className={`${_prefix}-list`}>
106+
{store.aiUserStore.aiResMsgs
107+
.slice()
108+
.reverse()
109+
.map((item, index) => (
110+
<div key={`${item}_${index}`} className={`${_prefix}-item`}>
111+
{item}
112+
</div>
113+
))}
114+
</div>
115+
</div>
116+
</Drawer>
117+
)
118+
}
119+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
@import '../../../style/theme.less';
2+
@import '~antd/lib/style/themes/variable.less';
3+
4+
@prefix-cls: ~'@{chat-prefix}-ai-search';
5+
6+
.@{prefix-cls} {
7+
&-content {
8+
display: flex;
9+
flex-direction: column;
10+
color: @yx-primary-text-color;
11+
font-size: @yx-primary-font-size;
12+
height: 100%;
13+
}
14+
15+
.@{ant-prefix}-drawer-header-title {
16+
flex-flow: row-reverse;
17+
}
18+
19+
&-title {
20+
display: flex;
21+
align-items: center;
22+
}
23+
24+
&-textarea {
25+
resize: 'none';
26+
line-height: '22px';
27+
padding: 12px;
28+
29+
&.@{ant-prefix}-input {
30+
min-height: 48px;
31+
}
32+
}
33+
34+
&-tip {
35+
color: @yx-text-color-2;
36+
font-size: @yx-font-size-12;
37+
text-align: right;
38+
margin-top: 5px;
39+
}
40+
41+
&-list {
42+
overflow-y: auto;
43+
padding: 0 16px;
44+
}
45+
46+
&-item {
47+
padding: 16px 0;
48+
&:not(:last-child) {
49+
border-bottom: 1px solid @yx-border-color-3;
50+
}
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'antd/lib/input/style'
2+
import 'antd/lib/drawer/style'
3+
import 'antd/lib/message/style'
4+
5+
import './index.less'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import { observer } from 'mobx-react'
2+
import React, { FC, useEffect, useState } from 'react'
3+
import { useStateContext, useTranslation } from '../../../common'
4+
import { Select, Button, message } from 'antd'
5+
import {
6+
ArrowDownOutlined,
7+
CloseOutlined,
8+
LoadingOutlined,
9+
} from '@ant-design/icons'
10+
import { getAIErrorMap, logger } from '../../../utils'
11+
import { V2NIMError } from 'nim-web-sdk-ng/dist/v2/NIM_BROWSER_SDK/types'
12+
13+
export interface ChatAITranslateProps {
14+
inputValue: string
15+
setInputValue: (value: string) => void
16+
onClose: () => void
17+
visible: boolean
18+
19+
prefix?: string
20+
}
21+
22+
export const ChatAITranslate: FC<ChatAITranslateProps> = observer(
23+
({ inputValue, setInputValue, onClose, visible, prefix = 'chat' }) => {
24+
const _prefix = `${prefix}-ai-translate`
25+
26+
const { store } = useStateContext()
27+
const { t } = useTranslation()
28+
29+
const aiErrorMap = getAIErrorMap(t)
30+
31+
const options = store.aiUserStore.getAITranslateLangs().map((lang) => ({
32+
label: lang,
33+
value: lang,
34+
}))
35+
36+
const resonpse = store.aiUserStore.isAITranslating()
37+
? store.aiUserStore.aiResMsgs[0]
38+
: ''
39+
40+
const [selectedLang, setSelectedLang] = useState(options[0].value)
41+
42+
const resetState = () => {
43+
setSelectedLang(options[0].value)
44+
}
45+
46+
useEffect(() => {
47+
resetState()
48+
store.aiUserStore.resetAIProxy()
49+
}, [visible, store.aiUserStore])
50+
51+
useEffect(() => {
52+
store.aiUserStore.resetAIProxy()
53+
}, [inputValue, store.aiUserStore, selectedLang])
54+
55+
const onUseTranslateHandler = () => {
56+
setInputValue(resonpse)
57+
}
58+
59+
const onTranslateHandler = async () => {
60+
if (!inputValue) {
61+
message.warning(t('aiTranslateEmptyText'))
62+
return
63+
}
64+
65+
const aiTranslateUser = store.aiUserStore.getAITranslateUser()
66+
67+
if (aiTranslateUser) {
68+
try {
69+
await store.aiUserStore.sendAIProxyActive({
70+
accountId: aiTranslateUser.accountId,
71+
requestId: Math.random().toString(36).slice(2),
72+
content: { msg: inputValue, type: 0 },
73+
promptVariables: JSON.stringify({ Language: selectedLang }),
74+
onSendAIProxyErrorHandler: (code: number) => {
75+
const errorText = aiErrorMap[code] || t('aiProxyFailedText')
76+
77+
message.error(errorText)
78+
},
79+
})
80+
} catch (error) {
81+
logger.error('AI 翻译失败', (error as V2NIMError).toString())
82+
}
83+
}
84+
}
85+
86+
const renderBtn = () => {
87+
return store.aiUserStore.aiProxying ? (
88+
<div className={`${_prefix}-btn`}>
89+
<LoadingOutlined />
90+
<span style={{ marginLeft: '5px' }}>{t('aiTranslatingText')}</span>
91+
</div>
92+
) : resonpse ? (
93+
<Button
94+
type="link"
95+
className={`${_prefix}-btn`}
96+
onClick={onUseTranslateHandler}
97+
>
98+
<span>{t('aiTranslatedText')}</span>
99+
<ArrowDownOutlined style={{ fontSize: 12 }} />
100+
</Button>
101+
) : (
102+
<Button
103+
type="link"
104+
className={`${_prefix}-btn`}
105+
onClick={onTranslateHandler}
106+
>
107+
{t('aiTranslateText')}
108+
</Button>
109+
)
110+
}
111+
112+
return visible ? (
113+
<div className={_prefix}>
114+
<Select
115+
options={options}
116+
value={selectedLang}
117+
onSelect={setSelectedLang}
118+
className={`${_prefix}-select`}
119+
showArrow={false}
120+
dropdownMatchSelectWidth={120}
121+
/>
122+
<div className={`${_prefix}-content`}>
123+
{resonpse ? (
124+
resonpse
125+
) : (
126+
<span className={`${_prefix}-tip`}>
127+
{t('aiTranslatePlaceholder')}
128+
</span>
129+
)}
130+
</div>
131+
{renderBtn()}
132+
<Button
133+
type="text"
134+
icon={<CloseOutlined style={{ fontSize: 12 }} />}
135+
onClick={onClose}
136+
></Button>
137+
</div>
138+
) : null
139+
}
140+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@import '../../../style/theme.less';
2+
@import '~antd/lib/style/themes/variable.less';
3+
4+
@prefix-cls: ~'@{chat-prefix}-ai-translate';
5+
6+
.@{prefix-cls} {
7+
display: flex;
8+
flex-direction: row;
9+
align-items: center;
10+
padding: 9px 12px;
11+
background-color: @yx-background-color-4;
12+
border-top: 1px solid @yx-border-color-8;
13+
border-radius: 4px 4px 0 0;
14+
font-size: @yx-primary-font-size;
15+
color: @yx-primary-text-color;
16+
17+
&-content {
18+
flex: 1;
19+
word-wrap: break-word;
20+
max-height: 46px;
21+
overflow-y: auto;
22+
margin: 0 5px;
23+
}
24+
25+
&-tip {
26+
color: @yx-text-color-3;
27+
}
28+
29+
&-btn {
30+
color: @yx-primary-button-color;
31+
display: flex;
32+
flex-direction: row;
33+
align-items: center;
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'antd/lib/button/style'
2+
import 'antd/lib/select/style'
3+
import 'antd/lib/message/style'
4+
5+
import './index.less'

0 commit comments

Comments
 (0)