@ray-js/t-agent-ui-ray 0.2.2-beta-2 → 0.2.3-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.js +1 -9
- package/dist/EchartsBlockRender/index.js +8 -10
- package/dist/LazyScrollView/LazyItem/index.d.ts +18 -0
- package/dist/LazyScrollView/LazyItem/index.js +51 -0
- package/dist/LazyScrollView/LazyItem/index.json +3 -0
- package/dist/LazyScrollView/LazyItem/index.tyml +16 -0
- package/dist/LazyScrollView/index.d.ts +26 -0
- package/dist/LazyScrollView/index.js +27 -0
- package/dist/LazyScrollView/index.json +3 -0
- package/dist/LazyScrollView/index.tyml +15 -0
- package/dist/LazyScrollView/lazy-scroll-view.sjs +317 -0
- package/dist/LazyScrollView/weak-ref.sjs +45 -0
- package/dist/MessageInput/MessageInputAIStream/AsrInput.js +2 -2
- package/dist/MessageInput/MessageInputAIStream/Waveform/index.d.ts +9 -0
- package/dist/MessageInput/MessageInputAIStream/Waveform/index.js +52 -0
- package/dist/MessageInput/MessageInputAIStream/Waveform/index.json +3 -0
- package/dist/MessageInput/MessageInputAIStream/Waveform/index.tyml +9 -0
- package/dist/MessageInput/MessageInputAIStream/index.d.ts +1 -0
- package/dist/MessageInput/MessageInputAIStream/index.js +2 -4
- package/dist/MessageList/ScrollBottomView.d.ts +20 -20
- package/dist/MessageList/ScrollBottomView.js +59 -138
- package/dist/MessageList/index.d.ts +5 -8
- package/dist/MessageList/index.js +89 -11
- package/dist/MessageList/index.less +1 -2
- package/dist/MessageRender/index.d.ts +6 -1
- package/dist/MessageRender/index.js +49 -17
- package/dist/MessageRender/index.less +4 -3
- package/dist/TileRender/index.d.ts +2 -1
- package/dist/TileRender/index.js +3 -3
- package/dist/contexts.d.ts +1 -5
- package/dist/hooks/context.d.ts +0 -2
- package/dist/hooks/context.js +0 -6
- package/dist/tiles/BubbleTile/index.js +2 -1
- package/dist/tiles/CardTile/index.less +1 -1
- package/dist/tiles/ExecuteCardTile/index.js +2 -1
- package/dist/tiles/OperateCardTile/Expand.d.ts +2 -1
- package/dist/tiles/OperateCardTile/Expand.js +4 -2
- package/dist/tiles/OperateCardTile/index.js +5 -6
- package/dist/utils/object.d.ts +8 -0
- package/dist/utils/object.js +57 -0
- package/package.json +2 -2
- package/dist/MessageInput/MessageInputAIStream/WaveformVisualizer.d.ts +0 -4
- package/dist/MessageInput/MessageInputAIStream/WaveformVisualizer.js +0 -54
- package/dist/MessageList/LazyView.d.ts +0 -9
- package/dist/MessageList/LazyView.js +0 -57
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import "core-js/modules/esnext.iterator.constructor.js";
|
|
2
|
+
import "core-js/modules/esnext.iterator.map.js";
|
|
3
|
+
import { systemInfo } from '../../../utils';
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line no-undef
|
|
6
|
+
Component({
|
|
7
|
+
options: {
|
|
8
|
+
styleIsolation: 'shared'
|
|
9
|
+
},
|
|
10
|
+
properties: {
|
|
11
|
+
amplitudeCount: {
|
|
12
|
+
type: Number,
|
|
13
|
+
value: 60
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
data: {
|
|
17
|
+
values: []
|
|
18
|
+
},
|
|
19
|
+
lifetimes: {
|
|
20
|
+
attached() {
|
|
21
|
+
// eslint-disable-next-line no-undef
|
|
22
|
+
ty.aistream.onRecordAmplitudes(this.update);
|
|
23
|
+
},
|
|
24
|
+
detached() {
|
|
25
|
+
// eslint-disable-next-line no-undef
|
|
26
|
+
ty.aistream.offRecordAmplitudes(this.update);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
methods: {
|
|
30
|
+
update(body) {
|
|
31
|
+
this.setData({
|
|
32
|
+
// 将数值映射到高度范围(0-1)
|
|
33
|
+
values: body.amplitudes.map(item => item > 1 ? 1 : item * 100)
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
observers: {
|
|
38
|
+
amplitudeCount(value) {
|
|
39
|
+
if (systemInfo.brand !== 'devtools') {
|
|
40
|
+
// eslint-disable-next-line no-undef
|
|
41
|
+
ty.aistream.registerRecordAmplitudes({
|
|
42
|
+
count: value
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
this.setData({
|
|
46
|
+
values: Array.from({
|
|
47
|
+
length: value
|
|
48
|
+
}, () => 0)
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
@@ -19,7 +19,6 @@ import logger from '../../logger';
|
|
|
19
19
|
import { systemInfo } from '../../utils';
|
|
20
20
|
import { useSleep } from '../../hooks/useSleep';
|
|
21
21
|
import { useStableCallback } from '../../hooks/useStableCallback';
|
|
22
|
-
const AMPLITUDE_COUNT = 60;
|
|
23
22
|
export let MessageInputState = /*#__PURE__*/function (MessageInputState) {
|
|
24
23
|
MessageInputState["PENDING"] = "pending";
|
|
25
24
|
MessageInputState["RECORDING"] = "recording";
|
|
@@ -320,7 +319,7 @@ export default function MessageInputAIStream(props) {
|
|
|
320
319
|
container = /*#__PURE__*/React.createElement(AsrInput, {
|
|
321
320
|
responding: canAbort,
|
|
322
321
|
disabled: state.current === MessageInputState.ABORTING,
|
|
323
|
-
amplitudeCount:
|
|
322
|
+
amplitudeCount: props.amplitudeCount || 60,
|
|
324
323
|
recording: state.current === MessageInputState.RECORDING,
|
|
325
324
|
onRecord: async () => {
|
|
326
325
|
logger.debug('MessageInputAIStream', 'AsrInput onRecord');
|
|
@@ -406,8 +405,7 @@ export default function MessageInputAIStream(props) {
|
|
|
406
405
|
setText('');
|
|
407
406
|
const inputBlocks = [...attachmentInput.blocks, {
|
|
408
407
|
type: 'audio',
|
|
409
|
-
audio_emitter: emitter
|
|
410
|
-
amplitude_count: AMPLITUDE_COUNT
|
|
408
|
+
audio_emitter: emitter
|
|
411
409
|
}];
|
|
412
410
|
try {
|
|
413
411
|
logger.debug('MessageInputAIStream', 'pushInputBlocks start');
|
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { ScrollEventDetail } from '../LazyScrollView';
|
|
3
|
+
interface ScrollBottomViewOptions {
|
|
4
|
+
scrollViewId?: string;
|
|
5
|
+
onScroll?: (event: {
|
|
6
|
+
detail: ScrollEventDetail;
|
|
7
|
+
}) => void;
|
|
8
|
+
tick: string;
|
|
9
|
+
loadedPromise?: Promise<void>;
|
|
4
10
|
}
|
|
5
|
-
export declare function useScrollBottomView(
|
|
11
|
+
export declare function useScrollBottomView(options: ScrollBottomViewOptions): {
|
|
6
12
|
scrollToBottom: ({ animation, follow }: {
|
|
7
13
|
animation?: boolean | undefined;
|
|
8
14
|
follow?: boolean | undefined;
|
|
9
|
-
}) =>
|
|
15
|
+
}) => Promise<boolean>;
|
|
10
16
|
scrollViewLoading: boolean;
|
|
11
17
|
scrollIntoViewId: string;
|
|
12
|
-
contentViewProps: {
|
|
13
|
-
contentViewId: string;
|
|
14
|
-
};
|
|
15
18
|
scrollViewProps: {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
scrollViewId: string;
|
|
20
|
+
bindscroll: (event: {
|
|
21
|
+
detail: ScrollEventDetail;
|
|
22
|
+
}) => void;
|
|
23
|
+
binddone: (event: {
|
|
20
24
|
detail: {
|
|
21
|
-
|
|
22
|
-
scrollHeight: number;
|
|
23
|
-
deltaY: number;
|
|
25
|
+
scrollIntoView: string;
|
|
24
26
|
};
|
|
25
|
-
currentTarget: any;
|
|
26
|
-
timeStamp: number;
|
|
27
27
|
}) => void;
|
|
28
28
|
scrollWithAnimation: boolean;
|
|
29
29
|
scrollIntoView: string;
|
|
30
30
|
};
|
|
31
31
|
};
|
|
32
|
-
interface Props {
|
|
32
|
+
interface Props extends ScrollBottomViewOptions {
|
|
33
|
+
scrollViewId?: string;
|
|
33
34
|
className?: string;
|
|
34
35
|
contentClassName?: string;
|
|
35
36
|
children: React.ReactNode;
|
|
36
37
|
style?: React.CSSProperties;
|
|
37
|
-
onScroll?: (event: any) => void;
|
|
38
38
|
hideScrollbar?: boolean;
|
|
39
39
|
}
|
|
40
|
-
interface
|
|
40
|
+
export interface ScrollBottomViewRef {
|
|
41
41
|
scrollToBottom: (options?: {
|
|
42
42
|
animation?: boolean;
|
|
43
43
|
follow?: boolean;
|
|
44
44
|
}) => void;
|
|
45
45
|
}
|
|
46
|
-
declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Props & React.RefAttributes<
|
|
46
|
+
declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Props & React.RefAttributes<ScrollBottomViewRef>>>;
|
|
47
47
|
export default _default;
|
|
@@ -1,178 +1,95 @@
|
|
|
1
|
-
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
-
import "core-js/modules/es.regexp.exec.js";
|
|
3
1
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
4
2
|
import React, { useCallback, useEffect, useRef, useState, forwardRef, useImperativeHandle } from 'react';
|
|
5
3
|
import { useSleep } from '../hooks/useSleep';
|
|
6
4
|
import { generateId } from '@ray-js/t-agent';
|
|
7
|
-
import { useOnEvent, useTick } from '../hooks';
|
|
8
|
-
import { ScrollView } from '@ray-js/ray';
|
|
9
5
|
import { View } from '@ray-js/components';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
6
|
+
import LazyScrollView from '../LazyScrollView';
|
|
7
|
+
import { createResolvable } from '../utils/object';
|
|
8
|
+
export function useScrollBottomView(options) {
|
|
9
|
+
const [scrollViewId] = useState(() => options.scrollViewId || "ScrollView-".concat(generateId()));
|
|
10
|
+
const {
|
|
11
|
+
tick,
|
|
12
|
+
loadedPromise
|
|
13
|
+
} = options;
|
|
14
14
|
const [ready, setReady] = useState(false);
|
|
15
15
|
const [scrollIntoViewFlag, setScrollIntoViewIdFlag] = useState(() => "".concat(Date.now()));
|
|
16
16
|
const [scrollWithAnimation, setScrollWithAnimation] = useState(false);
|
|
17
|
+
const prefix = "".concat(scrollViewId, "-toView-").concat(tick, "-");
|
|
18
|
+
const scrollIntoViewId = "".concat(prefix).concat(scrollIntoViewFlag);
|
|
17
19
|
const ref = useRef({
|
|
18
|
-
clientHeight: 0,
|
|
19
20
|
needFollow: true,
|
|
20
21
|
following: false,
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
resolvableMap: {},
|
|
23
|
+
prefix
|
|
23
24
|
});
|
|
25
|
+
ref.current.prefix = prefix;
|
|
24
26
|
const sleep = useSleep();
|
|
25
|
-
const makeScrollBottomEvent = useCallback(() => {
|
|
26
|
-
if (ref.current.lastScrollEvent) {
|
|
27
|
-
const {
|
|
28
|
-
detail,
|
|
29
|
-
currentTarget,
|
|
30
|
-
target
|
|
31
|
-
} = ref.current.lastScrollEvent;
|
|
32
|
-
const {
|
|
33
|
-
scrollTop,
|
|
34
|
-
scrollHeight
|
|
35
|
-
} = detail;
|
|
36
|
-
const newDetail = {
|
|
37
|
-
deltaX: 0,
|
|
38
|
-
scrollLeft: 0,
|
|
39
|
-
scrollTop: scrollHeight - ref.current.clientHeight,
|
|
40
|
-
scrollWidth: detail.scrollWidth,
|
|
41
|
-
scrollHeight,
|
|
42
|
-
deltaY: scrollTop - (scrollHeight - ref.current.clientHeight)
|
|
43
|
-
};
|
|
44
|
-
if (scrollTop === newDetail.scrollTop) {
|
|
45
|
-
// 如果滚动位置没有变化,则不触发事件
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
type: 'scroll',
|
|
50
|
-
timeStamp: Date.now() - ref.current.startTimestamp,
|
|
51
|
-
currentTarget,
|
|
52
|
-
target,
|
|
53
|
-
stopPropagation: () => {},
|
|
54
|
-
detail: newDetail
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
return null;
|
|
58
|
-
}, []);
|
|
59
27
|
const scrollToBottom = useCallback(_ref => {
|
|
60
28
|
let {
|
|
61
29
|
animation,
|
|
62
30
|
follow
|
|
63
31
|
} = _ref;
|
|
32
|
+
let promise = Promise.resolve(false);
|
|
33
|
+
const scroll = () => {
|
|
34
|
+
const flag = "".concat(Date.now());
|
|
35
|
+
const id = "".concat(ref.current.prefix).concat(flag);
|
|
36
|
+
setScrollIntoViewIdFlag(flag);
|
|
37
|
+
const r = createResolvable();
|
|
38
|
+
ref.current.resolvableMap[id] = r;
|
|
39
|
+
ref.current.needFollow = true;
|
|
40
|
+
promise = r.promise.then(() => true);
|
|
41
|
+
};
|
|
64
42
|
if (follow) {
|
|
65
43
|
if (ref.current.needFollow) {
|
|
66
|
-
|
|
67
|
-
ref.current.needFollow = true;
|
|
68
|
-
const event = makeScrollBottomEvent();
|
|
69
|
-
if (event) {
|
|
70
|
-
sleep(10).then(() => {
|
|
71
|
-
var _params$onScroll;
|
|
72
|
-
params === null || params === void 0 || (_params$onScroll = params.onScroll) === null || _params$onScroll === void 0 || _params$onScroll.call(params, event);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
44
|
+
scroll();
|
|
75
45
|
}
|
|
76
46
|
} else {
|
|
77
47
|
if (animation) {
|
|
78
48
|
setScrollWithAnimation(true);
|
|
79
49
|
}
|
|
80
|
-
|
|
81
|
-
setScrollIntoViewIdFlag("".concat(Date.now()));
|
|
82
|
-
const event = makeScrollBottomEvent();
|
|
83
|
-
if (event) {
|
|
84
|
-
sleep(100).then(() => {
|
|
85
|
-
var _params$onScroll2;
|
|
86
|
-
params === null || params === void 0 || (_params$onScroll2 = params.onScroll) === null || _params$onScroll2 === void 0 || _params$onScroll2.call(params, event);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
50
|
+
scroll();
|
|
89
51
|
if (animation) {
|
|
90
52
|
sleep(10).then(() => {
|
|
91
53
|
setScrollWithAnimation(false);
|
|
92
54
|
});
|
|
93
55
|
}
|
|
94
56
|
}
|
|
57
|
+
return promise;
|
|
58
|
+
}, []);
|
|
59
|
+
const onDone = useCallback(event => {
|
|
60
|
+
const id = event.detail.scrollIntoView;
|
|
61
|
+
if (id && ref.current.resolvableMap[id]) {
|
|
62
|
+
ref.current.resolvableMap[id].resolve();
|
|
63
|
+
delete ref.current.resolvableMap[id];
|
|
64
|
+
}
|
|
95
65
|
}, []);
|
|
96
66
|
useEffect(() => {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
// @ts-ignore
|
|
100
|
-
const query = ty.createSelectorQuery();
|
|
101
|
-
query.select("#".concat(scrollViewId)).fields({
|
|
102
|
-
dataset: true
|
|
103
|
-
}, res => {
|
|
104
|
-
resolve(res.dataset.renderTick);
|
|
105
|
-
}).exec();
|
|
106
|
-
});
|
|
107
|
-
};
|
|
108
|
-
const getClientHeight = () => {
|
|
109
|
-
return new Promise(resolve => {
|
|
110
|
-
// @ts-ignore
|
|
111
|
-
const query = ty.createSelectorQuery();
|
|
112
|
-
query.select("#".concat(scrollViewId)).fields({
|
|
113
|
-
size: true
|
|
114
|
-
}, res => {
|
|
115
|
-
resolve(res.height);
|
|
116
|
-
}).exec();
|
|
117
|
-
});
|
|
118
|
-
};
|
|
119
|
-
const scrollViewInterval = setInterval(() => {
|
|
120
|
-
// 外部容器高度变化不频繁,1 秒查一次
|
|
121
|
-
getClientHeight().then(height => {
|
|
122
|
-
ref.current.clientHeight = height;
|
|
123
|
-
});
|
|
124
|
-
}, 1000);
|
|
125
|
-
|
|
126
|
-
// 初始化好 clientHeight
|
|
127
|
-
(async () => {
|
|
128
|
-
let tick = await getDomTick();
|
|
129
|
-
while (tick <= 0) {
|
|
130
|
-
await sleep(1);
|
|
131
|
-
tick = await getDomTick();
|
|
132
|
-
}
|
|
133
|
-
return tick;
|
|
134
|
-
})().then(() => getClientHeight()).then(height => {
|
|
135
|
-
console.log('scrollView clientHeight', height);
|
|
136
|
-
ref.current.clientHeight = height;
|
|
137
|
-
})
|
|
67
|
+
const promise = loadedPromise || Promise.resolve();
|
|
68
|
+
promise
|
|
138
69
|
// 渲染完毕后,开始滚动到最底部
|
|
139
70
|
.then(() => scrollToBottom({}))
|
|
140
71
|
// 展示列表
|
|
141
72
|
.then(() => setReady(true));
|
|
142
|
-
return () => {
|
|
143
|
-
clearInterval(scrollViewInterval);
|
|
144
|
-
};
|
|
145
73
|
}, [scrollViewId]);
|
|
146
|
-
let scrollIntoViewId = "".concat(scrollViewId, "-toView-").concat(tickValue, "-").concat(scrollIntoViewFlag);
|
|
147
|
-
if (!ref.current.needFollow) {
|
|
148
|
-
scrollIntoViewId = null;
|
|
149
|
-
}
|
|
150
74
|
return {
|
|
151
75
|
scrollToBottom,
|
|
152
76
|
scrollViewLoading: !ready,
|
|
153
77
|
scrollIntoViewId,
|
|
154
|
-
contentViewProps: {
|
|
155
|
-
contentViewId
|
|
156
|
-
},
|
|
157
78
|
scrollViewProps: {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
onScroll: event => {
|
|
162
|
-
var _params$onScroll3;
|
|
163
|
-
ref.current.lastScrollEvent = event;
|
|
79
|
+
scrollViewId,
|
|
80
|
+
bindscroll: event => {
|
|
81
|
+
var _options$onScroll;
|
|
164
82
|
const {
|
|
165
83
|
scrollTop,
|
|
166
|
-
scrollHeight
|
|
84
|
+
scrollHeight,
|
|
85
|
+
clientHeight
|
|
167
86
|
} = event.detail;
|
|
168
|
-
ref.current.needFollow = scrollHeight - scrollTop <=
|
|
169
|
-
|
|
170
|
-
if (!ref.current.startTimestamp) {
|
|
171
|
-
ref.current.startTimestamp = Date.now() - event.timeStamp;
|
|
172
|
-
}
|
|
87
|
+
ref.current.needFollow = scrollHeight - scrollTop <= clientHeight + 25;
|
|
88
|
+
options === null || options === void 0 || (_options$onScroll = options.onScroll) === null || _options$onScroll === void 0 || _options$onScroll.call(options, event);
|
|
173
89
|
},
|
|
90
|
+
binddone: onDone,
|
|
174
91
|
scrollWithAnimation,
|
|
175
|
-
scrollIntoView: scrollIntoViewId
|
|
92
|
+
scrollIntoView: ref.current.needFollow ? scrollIntoViewId : ''
|
|
176
93
|
}
|
|
177
94
|
};
|
|
178
95
|
}
|
|
@@ -181,24 +98,28 @@ const ScrollBottomView = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
181
98
|
scrollToBottom,
|
|
182
99
|
scrollViewProps,
|
|
183
100
|
scrollIntoViewId,
|
|
184
|
-
contentViewProps,
|
|
185
101
|
scrollViewLoading
|
|
186
102
|
} = useScrollBottomView({
|
|
187
|
-
|
|
103
|
+
scrollViewId: props.scrollViewId,
|
|
104
|
+
onScroll: props.onScroll,
|
|
105
|
+
tick: props.tick,
|
|
106
|
+
loadedPromise: props.loadedPromise
|
|
188
107
|
});
|
|
189
|
-
useOnEvent('scrollToBottom', scrollToBottom);
|
|
190
108
|
useImperativeHandle(ref, () => ({
|
|
191
109
|
scrollToBottom
|
|
192
110
|
}), [scrollToBottom]);
|
|
193
|
-
return /*#__PURE__*/React.createElement(
|
|
194
|
-
className: "".concat(props.className || '', " ").concat(scrollViewLoading ? 't-agent-message-list-
|
|
195
|
-
style: props.style
|
|
196
|
-
|
|
197
|
-
,
|
|
198
|
-
|
|
199
|
-
|
|
111
|
+
return /*#__PURE__*/React.createElement(LazyScrollView, {
|
|
112
|
+
className: "".concat(props.className || '', " ").concat(scrollViewLoading ? 't-agent-message-list-loading' : ''),
|
|
113
|
+
style: props.style,
|
|
114
|
+
hideScrollbar: props.hideScrollbar || false,
|
|
115
|
+
bindscroll: scrollViewProps.bindscroll,
|
|
116
|
+
binddone: scrollViewProps.binddone,
|
|
117
|
+
scrollViewId: scrollViewProps.scrollViewId,
|
|
118
|
+
scrollWithAnimation: scrollViewProps.scrollWithAnimation,
|
|
119
|
+
scrollIntoView: scrollViewProps.scrollIntoView
|
|
120
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
200
121
|
className: "".concat(props.contentClassName || '')
|
|
201
|
-
}
|
|
122
|
+
}, props.children, /*#__PURE__*/React.createElement(View, {
|
|
202
123
|
id: scrollIntoViewId
|
|
203
124
|
})));
|
|
204
125
|
});
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import './index.less';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
interface RenderPartOptions {
|
|
4
|
+
notifyHeightChanged: () => void;
|
|
5
|
+
}
|
|
3
6
|
interface Props {
|
|
4
7
|
className?: string;
|
|
5
8
|
style?: React.CSSProperties;
|
|
6
9
|
wrapperClassName?: string;
|
|
7
10
|
wrapperStyle?: React.CSSProperties;
|
|
8
|
-
renderTop?: React.ReactNode;
|
|
9
|
-
renderBottom?: React.ReactNode;
|
|
11
|
+
renderTop?: React.ReactNode | ((options: RenderPartOptions) => React.ReactNode);
|
|
12
|
+
renderBottom?: React.ReactNode | ((options: RenderPartOptions) => React.ReactNode);
|
|
10
13
|
onScroll?: (event: any) => void;
|
|
11
14
|
hideScrollbar?: boolean;
|
|
12
15
|
roleSide?: {
|
|
@@ -14,12 +17,6 @@ interface Props {
|
|
|
14
17
|
assistant?: 'start' | 'end' | string;
|
|
15
18
|
[key: string]: 'start' | 'end' | string;
|
|
16
19
|
};
|
|
17
|
-
historyLimit?: {
|
|
18
|
-
/** 历史消息数量限制 */
|
|
19
|
-
count: number;
|
|
20
|
-
/** 超过限制时显示的提示文本 */
|
|
21
|
-
tipText: string;
|
|
22
|
-
};
|
|
23
20
|
}
|
|
24
21
|
declare const MessageList: (props: Props) => React.JSX.Element;
|
|
25
22
|
export default MessageList;
|
|
@@ -3,11 +3,15 @@ import "core-js/modules/esnext.iterator.map.js";
|
|
|
3
3
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
4
4
|
import './index.less';
|
|
5
5
|
import { View } from '@ray-js/components';
|
|
6
|
-
import React from 'react';
|
|
6
|
+
import React, { useRef, useState } from 'react';
|
|
7
7
|
import MessageRender from '../MessageRender';
|
|
8
|
-
import { useAgentMessage, useAgentSessionValue } from '../hooks';
|
|
8
|
+
import { useAgentMessage, useAgentSessionValue, useKeyboardHeight, useOnEvent } from '../hooks';
|
|
9
9
|
import ScrollBottomView from './ScrollBottomView';
|
|
10
10
|
import { useStableCallback } from '../hooks/useStableCallback';
|
|
11
|
+
import { createResolvable, objectsId } from '../utils/object';
|
|
12
|
+
import { generateId } from '@ray-js/t-agent';
|
|
13
|
+
import LazyItem from '../LazyScrollView/LazyItem';
|
|
14
|
+
import { useSleep } from '../hooks/useSleep';
|
|
11
15
|
const MessageList = props => {
|
|
12
16
|
const {
|
|
13
17
|
className,
|
|
@@ -15,28 +19,80 @@ const MessageList = props => {
|
|
|
15
19
|
style,
|
|
16
20
|
wrapperClassName,
|
|
17
21
|
wrapperStyle,
|
|
18
|
-
historyLimit,
|
|
19
22
|
hideScrollbar
|
|
20
23
|
} = props;
|
|
24
|
+
const [scrollViewId] = useState(() => "message-list-scroll-".concat(generateId()));
|
|
21
25
|
const messages = useAgentMessage();
|
|
22
26
|
const onScroll = useStableCallback(props.onScroll);
|
|
23
27
|
const [showSelect] = useAgentSessionValue('UIRay.multiSelect.show');
|
|
28
|
+
const keyboardHeight = useKeyboardHeight();
|
|
29
|
+
const ref = useRef();
|
|
30
|
+
if (!ref.current) {
|
|
31
|
+
ref.current = {
|
|
32
|
+
loaded: createResolvable()
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const scrollRef = useRef(null);
|
|
36
|
+
useOnEvent('scrollToBottom', payload => {
|
|
37
|
+
if (scrollRef.current) {
|
|
38
|
+
scrollRef.current.scrollToBottom(payload);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
useOnEvent('messageListInit', () => {
|
|
42
|
+
ref.current.loaded.resolve();
|
|
43
|
+
});
|
|
44
|
+
const [_tick, setTick] = useState(() => "".concat(Math.random()));
|
|
45
|
+
const tick = objectsId(messages, _tick, keyboardHeight);
|
|
46
|
+
const notifyHeightChanged = useStableCallback(() => {
|
|
47
|
+
setTick("".concat(Math.random()));
|
|
48
|
+
});
|
|
49
|
+
const [tickTop, setTickTop] = useState(() => "".concat(Math.random()));
|
|
50
|
+
const notifyHeightChangedTop = useStableCallback(() => {
|
|
51
|
+
notifyHeightChanged();
|
|
52
|
+
setTickTop("".concat(Math.random()));
|
|
53
|
+
});
|
|
54
|
+
const [tickBottom, setTickBottom] = useState(() => "".concat(Math.random()));
|
|
55
|
+
const notifyHeightChangedEnd = useStableCallback(() => {
|
|
56
|
+
notifyHeightChanged();
|
|
57
|
+
setTickBottom("".concat(Math.random()));
|
|
58
|
+
});
|
|
59
|
+
const showMapRef = useRef({
|
|
60
|
+
map: {},
|
|
61
|
+
pending: false
|
|
62
|
+
});
|
|
63
|
+
const [, forceUpdate] = useState(0);
|
|
64
|
+
const sleep = useSleep();
|
|
65
|
+
const top = typeof props.renderTop === 'function' ? props.renderTop({
|
|
66
|
+
notifyHeightChanged: notifyHeightChangedTop
|
|
67
|
+
}) : props.renderTop;
|
|
68
|
+
const bottom = typeof props.renderBottom === 'function' ? props.renderBottom({
|
|
69
|
+
notifyHeightChanged: notifyHeightChangedEnd
|
|
70
|
+
}) : props.renderBottom;
|
|
24
71
|
return /*#__PURE__*/React.createElement(View, {
|
|
25
72
|
className: "t-agent-message-list ".concat(wrapperClassName || ''),
|
|
26
73
|
"data-testid": "t-agent-message-list",
|
|
27
74
|
style: wrapperStyle,
|
|
28
75
|
id: "message-list"
|
|
29
76
|
}, /*#__PURE__*/React.createElement(ScrollBottomView, {
|
|
77
|
+
tick: tick,
|
|
78
|
+
scrollViewId: scrollViewId,
|
|
79
|
+
ref: scrollRef,
|
|
30
80
|
className: "".concat(className || '', " t-agent-message-list-scroll"),
|
|
31
81
|
contentClassName: "t-agent-message-list-scroll-content",
|
|
32
82
|
style: style,
|
|
33
83
|
onScroll: onScroll,
|
|
34
|
-
hideScrollbar: hideScrollbar
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
84
|
+
hideScrollbar: hideScrollbar,
|
|
85
|
+
loadedPromise: ref.current.loaded.promise
|
|
86
|
+
}, /*#__PURE__*/React.createElement(LazyItem, {
|
|
87
|
+
scrollViewId: scrollViewId,
|
|
88
|
+
itemId: "".concat(scrollViewId, "-top"),
|
|
89
|
+
key: "".concat(scrollViewId, "-top"),
|
|
90
|
+
update: tickTop,
|
|
91
|
+
ready: true,
|
|
92
|
+
index: 0
|
|
93
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
38
94
|
className: "t-agent-message-list-padding-start"
|
|
39
|
-
}),
|
|
95
|
+
}), top), messages.map((msg, index) => {
|
|
40
96
|
let side = roleSide === null || roleSide === void 0 ? void 0 : roleSide[msg.role];
|
|
41
97
|
if (!side) {
|
|
42
98
|
side = msg.role === 'user' ? 'end' : 'start';
|
|
@@ -47,10 +103,32 @@ const MessageList = props => {
|
|
|
47
103
|
key: msg.id,
|
|
48
104
|
message: msg,
|
|
49
105
|
isLatestMessage: isLatestMessage,
|
|
50
|
-
side: side
|
|
106
|
+
side: side,
|
|
107
|
+
notifyHeightChanged: notifyHeightChanged,
|
|
108
|
+
scrollViewId: scrollViewId,
|
|
109
|
+
index: index + 1,
|
|
110
|
+
show: showMapRef.current.map[msg.id] == null ? true : showMapRef.current.map[msg.id],
|
|
111
|
+
onShowChange: show => {
|
|
112
|
+
showMapRef.current.map[msg.id] = show;
|
|
113
|
+
if (showMapRef.current.pending) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
showMapRef.current.pending = true;
|
|
117
|
+
sleep(100).then(() => {
|
|
118
|
+
showMapRef.current.pending = false;
|
|
119
|
+
forceUpdate(Math.random());
|
|
120
|
+
});
|
|
121
|
+
}
|
|
51
122
|
});
|
|
52
|
-
}),
|
|
123
|
+
}), /*#__PURE__*/React.createElement(LazyItem, {
|
|
124
|
+
scrollViewId: scrollViewId,
|
|
125
|
+
itemId: "".concat(scrollViewId, "-bottom"),
|
|
126
|
+
key: "".concat(scrollViewId, "-bottom"),
|
|
127
|
+
update: tickBottom,
|
|
128
|
+
ready: true,
|
|
129
|
+
index: messages.length + 1
|
|
130
|
+
}, bottom, /*#__PURE__*/React.createElement(View, {
|
|
53
131
|
className: "t-agent-message-list-padding"
|
|
54
|
-
})));
|
|
132
|
+
}))));
|
|
55
133
|
};
|
|
56
134
|
export default MessageList;
|
|
@@ -6,6 +6,11 @@ interface Props {
|
|
|
6
6
|
isLatestMessage: boolean;
|
|
7
7
|
side: 'start' | 'end' | string;
|
|
8
8
|
showSelect?: boolean;
|
|
9
|
+
notifyHeightChanged: () => void;
|
|
10
|
+
scrollViewId?: string;
|
|
11
|
+
index: number;
|
|
12
|
+
onShowChange?: (show: boolean) => void;
|
|
13
|
+
show?: boolean;
|
|
9
14
|
}
|
|
10
|
-
export default function MessageRender({ message, isLatestMessage, side, showSelect }: Props): React.JSX.Element;
|
|
15
|
+
export default function MessageRender({ message, isLatestMessage, side, showSelect, notifyHeightChanged, scrollViewId, index, onShowChange, show, }: Props): React.JSX.Element;
|
|
11
16
|
export {};
|