@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.
@@ -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
- var container = containerRef.current;
54
- if (container) {
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
- container.scrollTo({
82
- top: container.scrollHeight,
83
- behavior: 'smooth'
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 (e.deltaY < 0) {
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
- markUserInteraction(true);
128
- } else if (position <= 5) {
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
+ }