@ray-js/t-agent-ui-ray 0.2.1-beta.3 → 0.2.2-beta-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/ChatContainer/index.d.ts +2 -1
- package/dist/ChatContainer/index.js +53 -48
- package/dist/EchartsBlockRender/index.js +6 -4
- package/dist/EchartsBlockRender/index.rjs +35 -9
- package/dist/MessageInput/MessageInputAIStream/WaveformVisualizer.d.ts +2 -2
- package/dist/MessageInput/MessageInputAIStream/WaveformVisualizer.js +30 -23
- package/dist/MessageInput/MessageInputAIStream/index.d.ts +8 -0
- package/dist/MessageInput/MessageInputAIStream/index.js +52 -41
- package/dist/MessageInput/index.d.ts +2 -1
- package/dist/MessageInput/index.js +2 -1
- package/dist/MessageList/LazyView.d.ts +9 -0
- package/dist/MessageList/LazyView.js +57 -0
- package/dist/MessageList/ScrollBottomView.d.ts +47 -0
- package/dist/MessageList/ScrollBottomView.js +205 -0
- package/dist/MessageList/index.d.ts +5 -2
- package/dist/MessageList/index.js +26 -88
- package/dist/MessageList/index.less +15 -4
- package/dist/MessageRender/index.less +1 -0
- package/dist/TileRender/index.js +5 -3
- package/dist/contexts.d.ts +18 -6
- package/dist/contexts.js +5 -17
- package/dist/hooks/context.d.ts +4 -4
- package/dist/hooks/context.js +13 -4
- package/dist/hooks/useStableCallback.d.ts +1 -0
- package/dist/hooks/useStableCallback.js +13 -0
- package/dist/tiles/BubbleTile/index.js +4 -4
- package/dist/tiles/ExecuteCardTile/index.d.ts +1 -8
- package/dist/tiles/ExecuteCardTile/index.js +7 -15
- package/dist/tiles/ExecuteCardTile/index.less +177 -151
- package/dist/tiles/OperateCardTile/index.d.ts +2 -6
- package/dist/tiles/OperateCardTile/index.js +6 -4
- package/dist/tiles/types.d.ts +31 -0
- package/dist/tiles/types.js +5 -0
- package/dist/types.d.ts +1 -0
- package/dist/utils/createSharedStore.d.ts +4 -0
- package/dist/utils/createSharedStore.js +64 -0
- package/dist/utils/index.js +1 -1
- package/package.json +2 -2
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import './index.less';
|
|
2
2
|
import React, { PropsWithChildren } from 'react';
|
|
3
3
|
import { ChatAgent } from '@ray-js/t-agent';
|
|
4
|
+
import { UIChatAgent } from '../contexts';
|
|
4
5
|
import { RenderOptions } from '../types';
|
|
5
6
|
export default function ChatContainer<T extends ChatAgent<any>>(props: PropsWithChildren<{
|
|
6
7
|
createAgent: () => T;
|
|
7
8
|
renderOptions?: RenderOptions;
|
|
8
9
|
className?: string;
|
|
9
10
|
style?: React.CSSProperties;
|
|
10
|
-
agentRef?: React.MutableRefObject<
|
|
11
|
+
agentRef?: React.MutableRefObject<UIChatAgent | null>;
|
|
11
12
|
}>): React.JSX.Element;
|
|
@@ -4,10 +4,10 @@ import "core-js/modules/esnext.iterator.filter.js";
|
|
|
4
4
|
import "core-js/modules/esnext.iterator.map.js";
|
|
5
5
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
6
6
|
import './index.less';
|
|
7
|
-
import React, { useEffect, useMemo, useState } from 'react';
|
|
7
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
8
8
|
import { View } from '@ray-js/components';
|
|
9
9
|
import cx from 'clsx';
|
|
10
|
-
import {
|
|
10
|
+
import { SharedProvider } from '../contexts';
|
|
11
11
|
import { defaultRenderOptions } from '../renderOption';
|
|
12
12
|
import logger from '../logger';
|
|
13
13
|
import { systemInfo } from '../utils';
|
|
@@ -27,6 +27,8 @@ export default function ChatContainer(props) {
|
|
|
27
27
|
style
|
|
28
28
|
} = props;
|
|
29
29
|
const [messages, setMessages] = useState([]);
|
|
30
|
+
const [tickValue, setRenderTick] = useState(0);
|
|
31
|
+
const notifyHeightChanged = useCallback(() => setRenderTick(t => t + 1), []);
|
|
30
32
|
const [agent] = useState(() => {
|
|
31
33
|
const agent = createAgent();
|
|
32
34
|
if (!agent.plugins.ui) {
|
|
@@ -41,9 +43,6 @@ export default function ChatContainer(props) {
|
|
|
41
43
|
});
|
|
42
44
|
return agent;
|
|
43
45
|
});
|
|
44
|
-
if (props.agentRef) {
|
|
45
|
-
props.agentRef.current = agent;
|
|
46
|
-
}
|
|
47
46
|
const uiAgent = useMemo(() => {
|
|
48
47
|
const session = {
|
|
49
48
|
get: agent.session.get,
|
|
@@ -58,63 +57,72 @@ export default function ChatContainer(props) {
|
|
|
58
57
|
});
|
|
59
58
|
return {
|
|
60
59
|
session,
|
|
61
|
-
plugins:
|
|
60
|
+
plugins: {
|
|
61
|
+
ui: agent.plugins.ui
|
|
62
|
+
},
|
|
62
63
|
pushInputBlocks: agent.pushInputBlocks,
|
|
63
64
|
emitTileEvent: agent.emitTileEvent,
|
|
64
65
|
removeMessage: agent.removeMessage
|
|
65
66
|
};
|
|
66
67
|
}, [agent]);
|
|
68
|
+
if (props.agentRef) {
|
|
69
|
+
props.agentRef.current = uiAgent;
|
|
70
|
+
}
|
|
67
71
|
useEffect(() => {
|
|
68
72
|
const {
|
|
69
73
|
onEvent,
|
|
70
74
|
emitEvent
|
|
71
75
|
} = agent.plugins.ui;
|
|
72
|
-
const offMessageListInit = onEvent('messageListInit', _ref => {
|
|
76
|
+
const offMessageListInit = onEvent('messageListInit', async _ref => {
|
|
73
77
|
let {
|
|
74
78
|
messages
|
|
75
79
|
} = _ref;
|
|
76
80
|
setMessages(messages);
|
|
81
|
+
notifyHeightChanged();
|
|
77
82
|
emitEvent('scrollToBottom', {
|
|
78
83
|
animation: false
|
|
79
84
|
});
|
|
80
85
|
});
|
|
81
|
-
const offMessageChange = onEvent('messageChange', _ref2 => {
|
|
86
|
+
const offMessageChange = onEvent('messageChange', async _ref2 => {
|
|
82
87
|
let {
|
|
83
88
|
type,
|
|
84
89
|
message
|
|
85
90
|
} = _ref2;
|
|
86
91
|
switch (type) {
|
|
87
92
|
case 'show':
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
{
|
|
94
|
+
setMessages(prev => [...prev, message]);
|
|
95
|
+
notifyHeightChanged();
|
|
96
|
+
emitEvent('scrollToBottom', {
|
|
97
|
+
animation: false
|
|
98
|
+
});
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
93
101
|
case 'update':
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return prev.map(item => {
|
|
107
|
-
if (item.id === message.id) {
|
|
108
|
-
return message;
|
|
109
|
-
}
|
|
110
|
-
return item;
|
|
102
|
+
{
|
|
103
|
+
setMessages(prev => {
|
|
104
|
+
return prev.map(item => {
|
|
105
|
+
if (item.id === message.id) {
|
|
106
|
+
notifyHeightChanged();
|
|
107
|
+
return message;
|
|
108
|
+
}
|
|
109
|
+
return item;
|
|
110
|
+
});
|
|
111
111
|
});
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
114
|
case 'remove':
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
{
|
|
116
|
+
setMessages(prev => {
|
|
117
|
+
return prev.filter(item => item.id !== message.id);
|
|
118
|
+
});
|
|
119
|
+
notifyHeightChanged();
|
|
120
|
+
emitEvent('scrollToBottom', {
|
|
121
|
+
animation: false,
|
|
122
|
+
follow: true
|
|
123
|
+
});
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
118
126
|
}
|
|
119
127
|
});
|
|
120
128
|
return () => {
|
|
@@ -122,12 +130,6 @@ export default function ChatContainer(props) {
|
|
|
122
130
|
offMessageChange();
|
|
123
131
|
};
|
|
124
132
|
}, [agent]);
|
|
125
|
-
const messageValue = useMemo(() => {
|
|
126
|
-
return {
|
|
127
|
-
messages,
|
|
128
|
-
keyboardHeight
|
|
129
|
-
};
|
|
130
|
-
}, [messages, keyboardHeight]);
|
|
131
133
|
useEffect(() => {
|
|
132
134
|
logger.debug('ChatProvider agent.start');
|
|
133
135
|
agent.start().then(() => {
|
|
@@ -181,11 +183,14 @@ export default function ChatContainer(props) {
|
|
|
181
183
|
className: cx('t-agent-chat-container', className, {
|
|
182
184
|
't-agent-chat-container-keyboard-show': keyboardHeight > 0
|
|
183
185
|
})
|
|
184
|
-
}, /*#__PURE__*/React.createElement(
|
|
185
|
-
value:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
186
|
+
}, /*#__PURE__*/React.createElement(SharedProvider, {
|
|
187
|
+
value: {
|
|
188
|
+
agent: uiAgent,
|
|
189
|
+
messages,
|
|
190
|
+
notifyHeightChanged,
|
|
191
|
+
keyboardHeight,
|
|
192
|
+
tickValue,
|
|
193
|
+
renderOptions
|
|
194
|
+
}
|
|
195
|
+
}, children));
|
|
191
196
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import Render from './index.rjs';
|
|
2
2
|
import logger from '../logger';
|
|
3
|
-
import { systemInfo } from '../utils';
|
|
4
3
|
|
|
5
4
|
// eslint-disable-next-line no-undef
|
|
6
5
|
Component({
|
|
@@ -47,9 +46,12 @@ Component({
|
|
|
47
46
|
});
|
|
48
47
|
const data = JSON.parse(content);
|
|
49
48
|
if (data.option) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
if (!this.isInit) {
|
|
50
|
+
this.rjs.init(this.data.canvasId, data.option);
|
|
51
|
+
this.isInit = true;
|
|
52
|
+
} else {
|
|
53
|
+
this.rjs.update(data.option);
|
|
54
|
+
}
|
|
53
55
|
this.setData({
|
|
54
56
|
loading: false,
|
|
55
57
|
error: false
|
|
@@ -1,15 +1,41 @@
|
|
|
1
1
|
export default Render({
|
|
2
2
|
myChart: null,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
option: null,
|
|
4
|
+
async init(canvasId, option) {
|
|
5
|
+
const { pixelRatio } = this.instance.getSystemInfo()
|
|
6
|
+
this.option = option
|
|
7
|
+
try {
|
|
5
8
|
const canvas = await this.instance.getCanvasById(canvasId)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
if (canvas) {
|
|
10
|
+
const echarts = await requirePlugin('rjs://echarts')
|
|
11
|
+
const myChart = echarts.init(canvas, undefined, {
|
|
12
|
+
devicePixelRatio: pixelRatio,
|
|
13
|
+
})
|
|
14
|
+
myChart.setOption(this.option, true)
|
|
15
|
+
this.myChart = myChart;
|
|
16
|
+
}
|
|
17
|
+
} catch (err) {
|
|
18
|
+
// ignore
|
|
11
19
|
}
|
|
12
|
-
|
|
13
|
-
|
|
20
|
+
},
|
|
21
|
+
async update(option) {
|
|
22
|
+
this.option = option
|
|
23
|
+
if (this.myChart) {
|
|
24
|
+
this.myChart.setOption(this.option, true)
|
|
25
|
+
}
|
|
26
|
+
// const { pixelRatio } = this.instance.getSystemInfo()
|
|
27
|
+
// if (!this.myChart) {
|
|
28
|
+
// const canvas = await this.instance.getCanvasById(canvasId)
|
|
29
|
+
// console.log(`EchartsBlockRender init render, ${canvasId}`, Object.keys(canvas))
|
|
30
|
+
// if (canvas) {
|
|
31
|
+
// const echarts = await requirePlugin('rjs://echarts')
|
|
32
|
+
// this.myChart = echarts.init(canvas, undefined, {
|
|
33
|
+
// devicePixelRatio: pixelRatio,
|
|
34
|
+
// })
|
|
35
|
+
// }
|
|
36
|
+
// }
|
|
37
|
+
// console.log(`EchartsBlockRender set option, ${canvasId}`)
|
|
38
|
+
// // 使用刚指定的配置项和数据显示图表。
|
|
39
|
+
// this.myChart.setOption(option, true)
|
|
14
40
|
},
|
|
15
41
|
})
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import "core-js/modules/esnext.iterator.constructor.js";
|
|
2
2
|
import "core-js/modules/esnext.iterator.map.js";
|
|
3
3
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
4
|
-
import React, { useState } from 'react';
|
|
4
|
+
import React, { useEffect, useState } from 'react';
|
|
5
5
|
import { View } from '@ray-js/ray';
|
|
6
|
-
|
|
7
|
-
export const WaveformVisualizer = _ref => {
|
|
6
|
+
export const WaveformVisualizer = /*#__PURE__*/React.memo(_ref => {
|
|
8
7
|
let {
|
|
9
8
|
amplitudeCount
|
|
10
9
|
} = _ref;
|
|
@@ -21,27 +20,35 @@ export const WaveformVisualizer = _ref => {
|
|
|
21
20
|
animationDelay: "".concat(index * 10, "ms")
|
|
22
21
|
}
|
|
23
22
|
})));
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const handle = _ref2 => {
|
|
25
|
+
let {
|
|
26
|
+
amplitudes
|
|
27
|
+
} = _ref2;
|
|
28
|
+
const bars = (amplitudes || []).map((item, index) => {
|
|
29
|
+
const value = item > 1 ? 1 : item * 100;
|
|
30
|
+
// 将数值映射到高度范围(0-100 → 2px-20px)
|
|
31
|
+
// const height = 2 + (value / 100) * 18;
|
|
32
|
+
return /*#__PURE__*/React.createElement(View
|
|
33
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
34
|
+
, {
|
|
35
|
+
key: "asr_wave_".concat(index),
|
|
36
|
+
className: "t-agent-message-input-waveform-bar",
|
|
37
|
+
style: {
|
|
38
|
+
height: "".concat(value, "%"),
|
|
39
|
+
// 添加渐变色偏移效果
|
|
40
|
+
animationDelay: "".concat(index * 10, "ms")
|
|
41
|
+
}
|
|
42
|
+
});
|
|
40
43
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
setBars(bars);
|
|
45
|
+
};
|
|
46
|
+
ty.aistream.onRecordAmplitudes(handle);
|
|
47
|
+
return () => {
|
|
48
|
+
ty.aistream.offRecordAmplitudes(handle);
|
|
49
|
+
};
|
|
50
|
+
}, []);
|
|
44
51
|
return /*#__PURE__*/React.createElement(View, {
|
|
45
52
|
className: "t-agent-message-input-waveform-container"
|
|
46
53
|
}, bars);
|
|
47
|
-
};
|
|
54
|
+
});
|
|
@@ -14,6 +14,14 @@ interface Props {
|
|
|
14
14
|
attachment?: boolean | AttachmentOptions;
|
|
15
15
|
maxTextLength?: number;
|
|
16
16
|
maxAudioMs?: number;
|
|
17
|
+
onStateChange?: (state: MessageInputState) => void;
|
|
18
|
+
}
|
|
19
|
+
export declare const enum MessageInputState {
|
|
20
|
+
PENDING = "pending",
|
|
21
|
+
RECORDING = "recording",
|
|
22
|
+
ASR = "asr",
|
|
23
|
+
RESPONDING = "responding",
|
|
24
|
+
ABORTING = "aborting"
|
|
17
25
|
}
|
|
18
26
|
export default function MessageInputAIStream(props: Props): React.JSX.Element;
|
|
19
27
|
export {};
|
|
@@ -17,15 +17,17 @@ import { useAttachmentInput, useChatAgent, useEmitEvent, useIsUnmounted, useOnEv
|
|
|
17
17
|
import AsrInput from './AsrInput';
|
|
18
18
|
import logger from '../../logger';
|
|
19
19
|
import { systemInfo } from '../../utils';
|
|
20
|
+
import { useSleep } from '../../hooks/useSleep';
|
|
21
|
+
import { useStableCallback } from '../../hooks/useStableCallback';
|
|
20
22
|
const AMPLITUDE_COUNT = 60;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return
|
|
28
|
-
}(
|
|
23
|
+
export let MessageInputState = /*#__PURE__*/function (MessageInputState) {
|
|
24
|
+
MessageInputState["PENDING"] = "pending";
|
|
25
|
+
MessageInputState["RECORDING"] = "recording";
|
|
26
|
+
MessageInputState["ASR"] = "asr";
|
|
27
|
+
MessageInputState["RESPONDING"] = "responding";
|
|
28
|
+
MessageInputState["ABORTING"] = "aborting";
|
|
29
|
+
return MessageInputState;
|
|
30
|
+
}({});
|
|
29
31
|
var InputAction = /*#__PURE__*/function (InputAction) {
|
|
30
32
|
InputAction["SEND"] = "send";
|
|
31
33
|
InputAction["RECORD"] = "record";
|
|
@@ -40,30 +42,30 @@ var InputAction = /*#__PURE__*/function (InputAction) {
|
|
|
40
42
|
return InputAction;
|
|
41
43
|
}(InputAction || {});
|
|
42
44
|
const transitions = {
|
|
43
|
-
[
|
|
44
|
-
[InputAction.SEND]:
|
|
45
|
-
[InputAction.RECORD]:
|
|
45
|
+
[MessageInputState.PENDING]: {
|
|
46
|
+
[InputAction.SEND]: MessageInputState.RESPONDING,
|
|
47
|
+
[InputAction.RECORD]: MessageInputState.RECORDING,
|
|
46
48
|
// 这个变更是为了兼容 pushInputBlocks 结束的场景,没有实际意义
|
|
47
|
-
[InputAction.TEXT_END]:
|
|
49
|
+
[InputAction.TEXT_END]: MessageInputState.PENDING
|
|
48
50
|
},
|
|
49
|
-
[
|
|
50
|
-
[InputAction.RECORD_TIMEOUT]:
|
|
51
|
-
[InputAction.RECORD_CANCEL]:
|
|
52
|
-
[InputAction.RECORD_CONFIRM]:
|
|
53
|
-
[InputAction.ABORT]:
|
|
54
|
-
[InputAction.ASR_ERROR]:
|
|
51
|
+
[MessageInputState.RECORDING]: {
|
|
52
|
+
[InputAction.RECORD_TIMEOUT]: MessageInputState.ASR,
|
|
53
|
+
[InputAction.RECORD_CANCEL]: MessageInputState.PENDING,
|
|
54
|
+
[InputAction.RECORD_CONFIRM]: MessageInputState.ASR,
|
|
55
|
+
[InputAction.ABORT]: MessageInputState.ABORTING,
|
|
56
|
+
[InputAction.ASR_ERROR]: MessageInputState.PENDING
|
|
55
57
|
},
|
|
56
|
-
[
|
|
57
|
-
[InputAction.ASR_END]:
|
|
58
|
-
[InputAction.ASR_ERROR]:
|
|
59
|
-
[InputAction.ABORT]:
|
|
58
|
+
[MessageInputState.ASR]: {
|
|
59
|
+
[InputAction.ASR_END]: MessageInputState.RESPONDING,
|
|
60
|
+
[InputAction.ASR_ERROR]: MessageInputState.PENDING,
|
|
61
|
+
[InputAction.ABORT]: MessageInputState.ABORTING
|
|
60
62
|
},
|
|
61
|
-
[
|
|
62
|
-
[InputAction.ABORT]:
|
|
63
|
-
[InputAction.TEXT_END]:
|
|
63
|
+
[MessageInputState.RESPONDING]: {
|
|
64
|
+
[InputAction.ABORT]: MessageInputState.ABORTING,
|
|
65
|
+
[InputAction.TEXT_END]: MessageInputState.PENDING
|
|
64
66
|
},
|
|
65
|
-
[
|
|
66
|
-
[InputAction.ABORT_DONE]:
|
|
67
|
+
[MessageInputState.ABORTING]: {
|
|
68
|
+
[InputAction.ABORT_DONE]: MessageInputState.PENDING
|
|
67
69
|
}
|
|
68
70
|
};
|
|
69
71
|
export default function MessageInputAIStream(props) {
|
|
@@ -71,12 +73,11 @@ export default function MessageInputAIStream(props) {
|
|
|
71
73
|
const t = useTranslate();
|
|
72
74
|
const [text, setText] = useState('');
|
|
73
75
|
const [state, setState] = useState({
|
|
74
|
-
current:
|
|
76
|
+
current: MessageInputState.PENDING,
|
|
75
77
|
payload: {}
|
|
76
78
|
});
|
|
77
|
-
const dispatchRef = useRef(null);
|
|
78
79
|
const initAudioRef = useRef(false);
|
|
79
|
-
|
|
80
|
+
const dispatch = useStableCallback((event, payload) => {
|
|
80
81
|
var _transitions$state$cu;
|
|
81
82
|
const next = (_transitions$state$cu = transitions[state.current]) === null || _transitions$state$cu === void 0 ? void 0 : _transitions$state$cu[event];
|
|
82
83
|
if (next) {
|
|
@@ -85,12 +86,14 @@ export default function MessageInputAIStream(props) {
|
|
|
85
86
|
current: next,
|
|
86
87
|
payload
|
|
87
88
|
});
|
|
89
|
+
if (props.onStateChange) {
|
|
90
|
+
props.onStateChange(next);
|
|
91
|
+
}
|
|
88
92
|
return true;
|
|
89
93
|
}
|
|
90
94
|
logger.error('MessageInputAIStream', "".concat(state.current, " ==").concat(event, "==> X not allowed"));
|
|
91
95
|
return false;
|
|
92
|
-
};
|
|
93
|
-
const dispatch = (event, payload) => dispatchRef.current(event, payload);
|
|
96
|
+
});
|
|
94
97
|
const attachmentOptions = useMemo(() => {
|
|
95
98
|
const options = {
|
|
96
99
|
image: true,
|
|
@@ -166,7 +169,7 @@ export default function MessageInputAIStream(props) {
|
|
|
166
169
|
let {
|
|
167
170
|
blocks
|
|
168
171
|
} = _ref2;
|
|
169
|
-
if (uploading || state.current !==
|
|
172
|
+
if (uploading || state.current !== MessageInputState.PENDING) {
|
|
170
173
|
return;
|
|
171
174
|
}
|
|
172
175
|
if (mode !== 'text') {
|
|
@@ -193,9 +196,10 @@ export default function MessageInputAIStream(props) {
|
|
|
193
196
|
}
|
|
194
197
|
};
|
|
195
198
|
let container;
|
|
196
|
-
const canSend = text.trim().length && state.current ===
|
|
197
|
-
const canAbort = state.current ===
|
|
199
|
+
const canSend = text.trim().length && state.current === MessageInputState.PENDING && !attachmentInput.uploading;
|
|
200
|
+
const canAbort = state.current === MessageInputState.RESPONDING || state.current === MessageInputState.ASR;
|
|
198
201
|
const recordingFlagRef = useRef(false);
|
|
202
|
+
const sleep = useSleep();
|
|
199
203
|
if (mode === 'text') {
|
|
200
204
|
container = /*#__PURE__*/React.createElement(View, {
|
|
201
205
|
className: "t-agent-message-input-text-bar"
|
|
@@ -223,6 +227,13 @@ export default function MessageInputAIStream(props) {
|
|
|
223
227
|
emitEvent('scrollToBottom', {
|
|
224
228
|
animation: true
|
|
225
229
|
});
|
|
230
|
+
},
|
|
231
|
+
onBlur: () => {
|
|
232
|
+
sleep(200).then(() => {
|
|
233
|
+
emitEvent('scrollToBottom', {
|
|
234
|
+
follow: true
|
|
235
|
+
});
|
|
236
|
+
});
|
|
226
237
|
}
|
|
227
238
|
}), /*#__PURE__*/React.createElement(Button, {
|
|
228
239
|
"data-testid": "t-agent-message-input-button-asr",
|
|
@@ -308,9 +319,9 @@ export default function MessageInputAIStream(props) {
|
|
|
308
319
|
} else {
|
|
309
320
|
container = /*#__PURE__*/React.createElement(AsrInput, {
|
|
310
321
|
responding: canAbort,
|
|
311
|
-
disabled: state.current ===
|
|
322
|
+
disabled: state.current === MessageInputState.ABORTING,
|
|
312
323
|
amplitudeCount: AMPLITUDE_COUNT,
|
|
313
|
-
recording: state.current ===
|
|
324
|
+
recording: state.current === MessageInputState.RECORDING,
|
|
314
325
|
onRecord: async () => {
|
|
315
326
|
logger.debug('MessageInputAIStream', 'AsrInput onRecord');
|
|
316
327
|
if (attachmentInput.uploading) {
|
|
@@ -332,10 +343,10 @@ export default function MessageInputAIStream(props) {
|
|
|
332
343
|
const emitter = new Emitter();
|
|
333
344
|
emitter.addEventListener('error', async error => {
|
|
334
345
|
logger.error('MessageInputAIStream', 'AsrInput error', error);
|
|
335
|
-
if (state.current ===
|
|
346
|
+
if (state.current === MessageInputState.RECORDING) {
|
|
336
347
|
clearTimeout(state.payload.recordTimeOutId);
|
|
337
348
|
}
|
|
338
|
-
if (state.current ===
|
|
349
|
+
if (state.current === MessageInputState.RESPONDING) {
|
|
339
350
|
return;
|
|
340
351
|
}
|
|
341
352
|
if (dispatch(InputAction.ASR_ERROR, {})) {
|
|
@@ -416,7 +427,7 @@ export default function MessageInputAIStream(props) {
|
|
|
416
427
|
onConfirm: async () => {
|
|
417
428
|
logger.debug('MessageInputAIStream', 'AsrInput onConfirm');
|
|
418
429
|
recordingFlagRef.current = false;
|
|
419
|
-
if (state.current ===
|
|
430
|
+
if (state.current === MessageInputState.ABORTING || state.current === MessageInputState.PENDING) {
|
|
420
431
|
return;
|
|
421
432
|
}
|
|
422
433
|
const payload = state.payload;
|
|
@@ -430,7 +441,7 @@ export default function MessageInputAIStream(props) {
|
|
|
430
441
|
onCancel: async () => {
|
|
431
442
|
logger.debug('MessageInputAIStream', 'AsrInput onCancel');
|
|
432
443
|
recordingFlagRef.current = false;
|
|
433
|
-
if (state.current ===
|
|
444
|
+
if (state.current === MessageInputState.ABORTING) {
|
|
434
445
|
return false;
|
|
435
446
|
}
|
|
436
447
|
const payload = state.payload;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import "core-js/modules/es.regexp.exec.js";
|
|
2
|
+
import "core-js/modules/web.dom-collections.iterator.js";
|
|
3
|
+
import { View } from '@ray-js/components';
|
|
4
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { usePageInstance } from '@ray-js/ray';
|
|
6
|
+
const queryHeight = id => {
|
|
7
|
+
return new Promise(resolve => {
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
const query = ty.createSelectorQuery();
|
|
10
|
+
query.select("#".concat(id)).boundingClientRect(res => {
|
|
11
|
+
resolve(res.height);
|
|
12
|
+
}).exec();
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
export default function LazyView(props) {
|
|
16
|
+
const {
|
|
17
|
+
id,
|
|
18
|
+
className,
|
|
19
|
+
children,
|
|
20
|
+
containerId
|
|
21
|
+
} = props;
|
|
22
|
+
const [visible, setVisible] = useState(true);
|
|
23
|
+
const heightRef = useRef(0);
|
|
24
|
+
const valid = heightRef.current > 0;
|
|
25
|
+
console.log();
|
|
26
|
+
const page = usePageInstance();
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
const observer = ty.createIntersectionObserver(page, {
|
|
30
|
+
thresholds: [0, 1],
|
|
31
|
+
initialRatio: 0
|
|
32
|
+
});
|
|
33
|
+
observer.relativeTo("#".concat(containerId), {
|
|
34
|
+
top: 50,
|
|
35
|
+
bottom: 50
|
|
36
|
+
}).observe("#".concat(id), res => {
|
|
37
|
+
setVisible(res.intersectionRatio > 0);
|
|
38
|
+
console.log(id, res);
|
|
39
|
+
});
|
|
40
|
+
return () => {
|
|
41
|
+
observer.disconnect();
|
|
42
|
+
};
|
|
43
|
+
}, [id, containerId]);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
queryHeight(id).then(height => {
|
|
46
|
+
console.log('queryHeight', id, height);
|
|
47
|
+
heightRef.current = height;
|
|
48
|
+
});
|
|
49
|
+
}, [id]);
|
|
50
|
+
console.log('rerender', id);
|
|
51
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
52
|
+
className: className,
|
|
53
|
+
"data-hide": !visible && valid,
|
|
54
|
+
id: id
|
|
55
|
+
// style={hide ? { visibility: 'hidden' } : null}
|
|
56
|
+
}, children);
|
|
57
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface ScrollBottomViewParams {
|
|
3
|
+
onScroll?: (event: any) => void;
|
|
4
|
+
}
|
|
5
|
+
export declare function useScrollBottomView(params: ScrollBottomViewParams): {
|
|
6
|
+
scrollToBottom: ({ animation, follow }: {
|
|
7
|
+
animation?: boolean | undefined;
|
|
8
|
+
follow?: boolean | undefined;
|
|
9
|
+
}) => void;
|
|
10
|
+
scrollViewLoading: boolean;
|
|
11
|
+
scrollIntoViewId: string;
|
|
12
|
+
contentViewProps: {
|
|
13
|
+
contentViewId: string;
|
|
14
|
+
};
|
|
15
|
+
scrollViewProps: {
|
|
16
|
+
'data-render-tick': number;
|
|
17
|
+
id: string;
|
|
18
|
+
scrollY: boolean;
|
|
19
|
+
onScroll: (event: {
|
|
20
|
+
detail: {
|
|
21
|
+
scrollTop: number;
|
|
22
|
+
scrollHeight: number;
|
|
23
|
+
deltaY: number;
|
|
24
|
+
};
|
|
25
|
+
currentTarget: any;
|
|
26
|
+
timeStamp: number;
|
|
27
|
+
}) => void;
|
|
28
|
+
scrollWithAnimation: boolean;
|
|
29
|
+
scrollIntoView: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
interface Props {
|
|
33
|
+
className?: string;
|
|
34
|
+
contentClassName?: string;
|
|
35
|
+
children: React.ReactNode;
|
|
36
|
+
style?: React.CSSProperties;
|
|
37
|
+
onScroll?: (event: any) => void;
|
|
38
|
+
hideScrollbar?: boolean;
|
|
39
|
+
}
|
|
40
|
+
interface Ref {
|
|
41
|
+
scrollToBottom: (options?: {
|
|
42
|
+
animation?: boolean;
|
|
43
|
+
follow?: boolean;
|
|
44
|
+
}) => void;
|
|
45
|
+
}
|
|
46
|
+
declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Props & React.RefAttributes<Ref>>>;
|
|
47
|
+
export default _default;
|