@myun/gimi-chat 0.7.3 → 0.7.5
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/components/message-list/index.d.ts +1 -0
- package/dist/components/message-list/index.js +40 -17
- package/dist/components/templates/CommonChat.js +10 -5
- package/dist/components/templates/index.module.css +1 -0
- package/dist/hooks/useChatHistory.d.ts +2 -1
- package/dist/hooks/useChatHistory.js +166 -74
- package/dist/hooks/useCommonChatAPI.d.ts +1 -0
- package/dist/hooks/useCommonChatAPI.js +6 -1
- package/dist/hooks/useScroll.js +55 -44
- package/dist/types/react-virtuoso.d.ts +13 -0
- package/dist/umd/index.min.js +1 -1
- package/package.json +3 -2
package/dist/hooks/useScroll.js
CHANGED
|
@@ -26,8 +26,23 @@ var useScroll = function useScroll(containerRef) {
|
|
|
26
26
|
scrollTimeout: 0,
|
|
27
27
|
interactionTimer: null,
|
|
28
28
|
lastScrollTop: 0,
|
|
29
|
-
isUserInteracting: false
|
|
29
|
+
isUserInteracting: false,
|
|
30
|
+
wasAtBottom: true,
|
|
31
|
+
lastWheelAt: 0
|
|
30
32
|
}).current;
|
|
33
|
+
var scrollBottomNow = React.useCallback(function () {
|
|
34
|
+
var tries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 4;
|
|
35
|
+
var count = 0;
|
|
36
|
+
var tick = function tick() {
|
|
37
|
+
var container = containerRef.current;
|
|
38
|
+
if (!container) return;
|
|
39
|
+
container.scrollTop = container.scrollHeight;
|
|
40
|
+
count += 1;
|
|
41
|
+
if (count < tries) requestAnimationFrame(tick);
|
|
42
|
+
};
|
|
43
|
+
requestAnimationFrame(tick);
|
|
44
|
+
setTimeout(tick, 0);
|
|
45
|
+
}, [containerRef]);
|
|
31
46
|
|
|
32
47
|
// 标记用户交互状态
|
|
33
48
|
var markUserInteraction = React.useCallback(function (isInteracting) {
|
|
@@ -50,18 +65,8 @@ var useScroll = function useScroll(containerRef) {
|
|
|
50
65
|
|
|
51
66
|
// 基础滚动到底部
|
|
52
67
|
var scrollBottom = React.useCallback(function () {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// 使用 requestAnimationFrame 确保在浏览器渲染前执行,
|
|
56
|
-
// 并且如果一次不行,尝试在下一帧再做一次,以应对复杂的布局变化
|
|
57
|
-
var doScroll = function doScroll() {
|
|
58
|
-
container.scrollTop = container.scrollHeight;
|
|
59
|
-
};
|
|
60
|
-
requestAnimationFrame(doScroll);
|
|
61
|
-
// 双重保证
|
|
62
|
-
setTimeout(doScroll, 0);
|
|
63
|
-
}
|
|
64
|
-
}, [containerRef.current]);
|
|
68
|
+
scrollBottomNow(2);
|
|
69
|
+
}, [scrollBottomNow]);
|
|
65
70
|
|
|
66
71
|
// 智能滚动到底部(只在非用户交互时执行)
|
|
67
72
|
var throttledScrollToBottom = React.useCallback(throttle(function () {
|
|
@@ -78,15 +83,24 @@ var useScroll = function useScroll(containerRef) {
|
|
|
78
83
|
markUserInteraction(false); // 重置为用户非交互状态
|
|
79
84
|
|
|
80
85
|
if (animate) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
var smoothScroll = function smoothScroll() {
|
|
87
|
+
var current = containerRef.current;
|
|
88
|
+
if (!current) return;
|
|
89
|
+
current.scrollTo({
|
|
90
|
+
top: current.scrollHeight,
|
|
91
|
+
behavior: 'smooth'
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
smoothScroll();
|
|
95
|
+
setTimeout(smoothScroll, 120);
|
|
96
|
+
setTimeout(function () {
|
|
97
|
+
if (!refs.isUserInteracting) scrollBottomNow(3);
|
|
98
|
+
}, 420);
|
|
85
99
|
} else {
|
|
86
100
|
scrollBottom();
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
|
-
}, [containerRef.current, markUserInteraction, scrollBottom]);
|
|
103
|
+
}, [containerRef.current, markUserInteraction, refs, scrollBottom, scrollBottomNow]);
|
|
90
104
|
|
|
91
105
|
// 更新滚动位置
|
|
92
106
|
var updateScrollHeight = React.useCallback(function () {
|
|
@@ -99,16 +113,22 @@ var useScroll = function useScroll(containerRef) {
|
|
|
99
113
|
setCurrentPosition(position);
|
|
100
114
|
}
|
|
101
115
|
}, [containerRef.current]);
|
|
102
|
-
|
|
103
|
-
// 滚轮事件处理 - 检测用户向上滚动意图
|
|
104
116
|
var handleWheel = React.useCallback(throttle(function (e) {
|
|
105
|
-
|
|
106
|
-
if (
|
|
117
|
+
var container = containerRef.current;
|
|
118
|
+
if (!container) return;
|
|
119
|
+
refs.lastWheelAt = Date.now();
|
|
120
|
+
var scrollTop = container.scrollTop,
|
|
121
|
+
scrollHeight = container.scrollHeight,
|
|
122
|
+
clientHeight = container.clientHeight;
|
|
123
|
+
var canScroll = scrollHeight - clientHeight > 1;
|
|
124
|
+
if (!canScroll) return;
|
|
125
|
+
var position = Math.max(0, scrollHeight - clientHeight - scrollTop);
|
|
126
|
+
if (e.deltaY < -2) {
|
|
107
127
|
markUserInteraction(true);
|
|
128
|
+
} else if (e.deltaY > 2 && position <= bottomPosition) {
|
|
129
|
+
markUserInteraction(false);
|
|
108
130
|
}
|
|
109
|
-
}, 100), [markUserInteraction]);
|
|
110
|
-
|
|
111
|
-
// 滚动事件处理
|
|
131
|
+
}, 100), [containerRef.current, bottomPosition, markUserInteraction, refs]);
|
|
112
132
|
var handleScroll = React.useCallback(throttle(function () {
|
|
113
133
|
if (!containerRef.current) return;
|
|
114
134
|
var _containerRef$current2 = containerRef.current,
|
|
@@ -118,26 +138,24 @@ var useScroll = function useScroll(containerRef) {
|
|
|
118
138
|
var position = Math.max(0, scrollHeight - clientHeight - scrollTop);
|
|
119
139
|
setCurrentPosition(position);
|
|
120
140
|
setIsScrolling(true);
|
|
121
|
-
|
|
122
|
-
// 检测滚动方向
|
|
141
|
+
refs.wasAtBottom = position <= bottomPosition * 2;
|
|
123
142
|
var scrollDelta = scrollTop - refs.lastScrollTop;
|
|
124
143
|
if (Math.abs(scrollDelta) > 2) {
|
|
125
144
|
if (scrollDelta < 0) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
145
|
+
var now = Date.now();
|
|
146
|
+
if (refs.isUserInteracting || now - refs.lastWheelAt < 600) {
|
|
147
|
+
markUserInteraction(true);
|
|
148
|
+
}
|
|
149
|
+
} else if (scrollDelta > 0 && position <= bottomPosition) {
|
|
130
150
|
markUserInteraction(false);
|
|
131
151
|
}
|
|
132
152
|
refs.lastScrollTop = scrollTop;
|
|
133
153
|
}
|
|
134
|
-
|
|
135
|
-
// 设置滚动结束状态
|
|
136
154
|
if (refs.scrollTimeout) clearTimeout(refs.scrollTimeout);
|
|
137
155
|
refs.scrollTimeout = setTimeout(function () {
|
|
138
156
|
setIsScrolling(false);
|
|
139
157
|
}, 200);
|
|
140
|
-
}, 150), [containerRef.current, markUserInteraction]);
|
|
158
|
+
}, 150), [containerRef.current, bottomPosition, markUserInteraction]);
|
|
141
159
|
|
|
142
160
|
// 事件监听器
|
|
143
161
|
React.useEffect(function () {
|
|
@@ -169,15 +187,8 @@ var useScroll = function useScroll(containerRef) {
|
|
|
169
187
|
scrollHeight = container.scrollHeight,
|
|
170
188
|
clientHeight = container.clientHeight;
|
|
171
189
|
var distanceToBottom = scrollHeight - clientHeight - scrollTop;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
// 注意:这里的判定逻辑需要考虑到新内容可能还没撑开高度
|
|
175
|
-
// 所以我们直接尝试在下一帧滚动
|
|
176
|
-
if (distanceToBottom <= bottomPosition * 5) {
|
|
177
|
-
// 稍微放宽判定范围,因为新内容可能已经改变了 scrollHeight
|
|
178
|
-
requestAnimationFrame(function () {
|
|
179
|
-
container.scrollTop = container.scrollHeight;
|
|
180
|
-
});
|
|
190
|
+
if (refs.wasAtBottom || distanceToBottom <= bottomPosition * 5) {
|
|
191
|
+
scrollBottomNow(4);
|
|
181
192
|
}
|
|
182
193
|
});
|
|
183
194
|
observer.observe(container, {
|
|
@@ -188,7 +199,7 @@ var useScroll = function useScroll(containerRef) {
|
|
|
188
199
|
return function () {
|
|
189
200
|
return observer.disconnect();
|
|
190
201
|
};
|
|
191
|
-
}, [containerRef.current, bottomPosition]);
|
|
202
|
+
}, [containerRef.current, bottomPosition, refs, scrollBottomNow]);
|
|
192
203
|
return [throttledScrollToBottom, scrollBottomForce, currentPosition, scrollBottom, updateScrollHeight, isScrolling, isUserScroll];
|
|
193
204
|
};
|
|
194
205
|
export default useScroll;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare module 'react-virtuoso' {
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
export interface VirtuosoProps<TData = any> extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
data?: TData[];
|
|
6
|
+
customScrollParent?: HTMLElement | null;
|
|
7
|
+
itemContent?: (index: number, data: TData) => React.ReactNode;
|
|
8
|
+
startReached?: () => void;
|
|
9
|
+
style?: React.CSSProperties;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const Virtuoso: React.ComponentType<VirtuosoProps<any>>;
|
|
13
|
+
}
|