feat: 实现 Socket 触发的智能列表自动刷新功能(带防抖)

核心改动:
- 扩展 NotificationContext,添加事件更新回调注册机制
- VirtualizedFourRowGrid 添加 forwardRef 暴露 getScrollPosition 方法
- DynamicNewsCard 实现智能刷新逻辑(根据模式和滚动位置判断是否刷新)
- Community 页面注册 Socket 回调自动触发刷新
- 创建 TypeScript 通用防抖工具函数(debounce.ts)
- 集成防抖机制(2秒延迟),避免短时间内频繁请求

智能刷新策略:
- 纵向模式 + 第1页:自动刷新列表
- 纵向模式 + 其他页:不刷新(避免打断用户)
- 平铺模式 + 滚动在顶部:自动刷新列表
- 平铺模式 + 滚动不在顶部:仅显示 Toast 提示

防抖效果:
- 短时间内收到多个新事件,只执行最后一次刷新
- 减少服务器压力,提升用户体验

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-11-14 19:04:00 +08:00
parent 9fd618c087
commit ddd6b2d4af
7 changed files with 382 additions and 9 deletions

View File

@@ -64,6 +64,9 @@ export const NotificationProvider = ({ children }) => {
const adaptEventToNotificationRef = useRef(null);
const isFirstConnect = useRef(true); // 标记是否首次连接
// ⚡ 事件更新回调列表(用于在收到 new_event 时通知其他组件刷新数据)
const eventUpdateCallbacks = useRef(new Set());
// ⚡ 使用权限引导管理 Hook
const { shouldShowGuide, markGuideAsShown } = usePermissionGuide();
@@ -160,6 +163,37 @@ export const NotificationProvider = ({ children }) => {
});
}, []);
/**
* 注册事件更新回调(用于在收到新事件时通知其他组件刷新)
* @param {Function} callback - 回调函数,接收 eventData 参数
* @returns {Function} 取消注册函数
*/
const registerEventUpdateCallback = useCallback((callback) => {
eventUpdateCallbacks.current.add(callback);
logger.info('NotificationContext', 'Event update callback registered', {
totalCallbacks: eventUpdateCallbacks.current.size
});
// 返回取消注册函数
return () => {
eventUpdateCallbacks.current.delete(callback);
logger.info('NotificationContext', 'Event update callback unregistered', {
totalCallbacks: eventUpdateCallbacks.current.size
});
};
}, []);
/**
* 取消注册事件更新回调(已废弃,建议使用 registerEventUpdateCallback 返回的函数)
* @param {Function} callback - 要取消的回调函数
*/
const unregisterEventUpdateCallback = useCallback((callback) => {
eventUpdateCallbacks.current.delete(callback);
logger.info('NotificationContext', 'Event update callback unregistered (manual)', {
totalCallbacks: eventUpdateCallbacks.current.size
});
}, []);
/**
* 请求浏览器通知权限
*/
@@ -764,6 +798,21 @@ export const NotificationProvider = ({ children }) => {
console.log('[NotificationContext] 准备添加通知到队列...');
addNotificationRef.current(notification);
console.log('[NotificationContext] ✅ 通知已添加到队列');
// ⚡ 调用所有注册的事件更新回调(用于通知其他组件刷新数据)
if (eventUpdateCallbacks.current.size > 0) {
console.log(`[NotificationContext] 🔔 触发 ${eventUpdateCallbacks.current.size} 个事件更新回调...`);
eventUpdateCallbacks.current.forEach(callback => {
try {
callback(data);
} catch (error) {
logger.error('NotificationContext', 'Event update callback error', error);
console.error('[NotificationContext] ❌ 事件更新回调执行失败:', error);
}
});
console.log('[NotificationContext] ✅ 所有事件更新回调已触发');
}
console.log('%c════════════════════════════════════════\n', 'color: #FF9800; font-weight: bold;');
});
@@ -1040,6 +1089,9 @@ export const NotificationProvider = ({ children }) => {
showWelcomeGuide,
showCommunityGuide,
showFirstFollowGuide,
// ⚡ 新增:事件更新回调注册方法
registerEventUpdateCallback,
unregisterEventUpdateCallback,
};
return (