@@ -90,7 +90,7 @@ export function ChatHistoryList({
9090const isPulling = useRef ( false ) ;
9191const pullDistanceRef = useRef ( 0 ) ;
9292const wheelDeltaAccumulator = useRef ( 0 ) ;
93- const isRefreshingRef = useRef ( false ) ;
93+ const lastRefreshTime = useRef ( 0 ) ;
9494
9595// Fetch initial conversations from API using the OpenSecret SDK
9696const { isPending, error } = useQuery ( {
@@ -185,8 +185,6 @@ export function ChatHistoryList({
185185
186186// Pull-to-refresh handler
187187const handleRefresh = useCallback ( async ( ) => {
188- // Set ref immediately to block rapid-fire events
189- isRefreshingRef . current = true ;
190188setIsPullRefreshing ( true ) ;
191189try {
192190await pollForUpdates ( ) ;
@@ -197,7 +195,8 @@ export function ChatHistoryList({
197195setTimeout ( ( ) => {
198196setIsPullRefreshing ( false ) ;
199197setPullDistance ( 0 ) ;
200- isRefreshingRef . current = false ;
198+ // Record the time when refresh completes for cooldown
199+ lastRefreshTime . current = Date . now ( ) ;
201200} , 300 ) ;
202201}
203202} , [ pollForUpdates ] ) ;
@@ -241,11 +240,15 @@ export function ChatHistoryList({
241240
242241isPulling . current = false ;
243242
244- // Trigger refresh if pulled far enough (threshold: 60px)
245- if ( pullDistanceRef . current > 60 ) {
243+ // Check cooldown: enforce 5-second delay between refreshes
244+ const timeSinceLastRefresh = Date . now ( ) - lastRefreshTime . current ;
245+ const cooldownPeriod = 5000 ; // 5 seconds
246+
247+ // Trigger refresh if pulled far enough (threshold: 60px) and cooldown elapsed
248+ if ( pullDistanceRef . current > 60 && timeSinceLastRefresh >= cooldownPeriod ) {
246249handleRefresh ( ) ;
247250} else {
248- // Reset if not pulled far enough
251+ // Reset if not pulled far enough or still in cooldown
249252setPullDistance ( 0 ) ;
250253}
251254} ;
@@ -282,11 +285,15 @@ export function ChatHistoryList({
282285
283286isPulling . current = false ;
284287
285- // Trigger refresh if pulled far enough (threshold: 60px)
286- if ( pullDistanceRef . current > 60 ) {
288+ // Check cooldown: enforce 5-second delay between refreshes
289+ const timeSinceLastRefresh = Date . now ( ) - lastRefreshTime . current ;
290+ const cooldownPeriod = 5000 ; // 5 seconds
291+
292+ // Trigger refresh if pulled far enough (threshold: 60px) and cooldown elapsed
293+ if ( pullDistanceRef . current > 60 && timeSinceLastRefresh >= cooldownPeriod ) {
287294handleRefresh ( ) ;
288295} else {
289- // Reset if not pulled far enough
296+ // Reset if not pulled far enough or still in cooldown
290297setPullDistance ( 0 ) ;
291298}
292299} ;
@@ -295,11 +302,15 @@ export function ChatHistoryList({
295302const WHEEL_THRESHOLD = - 50 ; // Require accumulated scroll before triggering
296303
297304const handleWheel = ( e : WheelEvent ) => {
298- if ( ! isDesktopPlatform || isRefreshingRef . current ) return ;
305+ if ( ! isDesktopPlatform || isPullRefreshing ) return ;
299306
300307// Only handle if the event target is within our container
301308if ( ! container . contains ( e . target as Node ) ) return ;
302309
310+ // Check cooldown: enforce 5-second delay between refreshes
311+ const timeSinceLastRefresh = Date . now ( ) - lastRefreshTime . current ;
312+ const cooldownPeriod = 5000 ; // 5 seconds
313+
303314// Check if we're at the top and trying to scroll up
304315if ( container . scrollTop === 0 && e . deltaY < 0 ) {
305316// Prevent default to avoid browser overscroll bounce
@@ -313,8 +324,11 @@ export function ChatHistoryList({
313324pullDistanceRef . current = visualDistance ;
314325setPullDistance ( visualDistance ) ;
315326
316- // Trigger refresh if threshold is reached
317- if ( wheelDeltaAccumulator . current <= WHEEL_THRESHOLD ) {
327+ // Trigger refresh if threshold is reached and cooldown elapsed
328+ if (
329+ wheelDeltaAccumulator . current <= WHEEL_THRESHOLD &&
330+ timeSinceLastRefresh >= cooldownPeriod
331+ ) {
318332wheelDeltaAccumulator . current = 0 ;
319333handleRefresh ( ) ;
320334}
0 commit comments