refactor(ProcessPostUseCase, useCursorPagination, useDifferentialPosts): enhance post merging and loading states
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 4m57s
Frontend CI / ota-android (push) Successful in 10m48s
Frontend CI / build-android-apk (push) Successful in 52m58s

- Introduced new methods for merging posts and comments efficiently, improving performance during data updates.
- Updated loading state management in hooks to include initial loading and loading more states for better user feedback.
- Refactored HomeScreen and PostDetailScreen to utilize the new loading states and merging logic, enhancing user experience during data fetching.
- Improved pagination handling in useCursorPagination and useDifferentialPosts to ensure consistent data management across components.
This commit is contained in:
lafay
2026-03-24 01:19:09 +08:00
parent aaf53d1c3b
commit 5c9cb6acea
11 changed files with 475 additions and 101 deletions

View File

@@ -120,6 +120,7 @@ export const useChatScreen = () => {
const prevMessageCountRef = useRef(0);
const prevLatestSeqRef = useRef(0);
const prevMarkedReadSeqRef = useRef(0);
const enterMarkedKeyRef = useRef<string>('');
const isProgrammaticScrollRef = useRef(false);
const suppressAutoFollowRef = useRef(false);
const isBrowsingHistoryRef = useRef(false);
@@ -277,6 +278,7 @@ export const useChatScreen = () => {
prevMessageCountRef.current = 0;
prevLatestSeqRef.current = 0;
prevMarkedReadSeqRef.current = 0;
enterMarkedKeyRef.current = '';
suppressAutoFollowRef.current = false;
isBrowsingHistoryRef.current = false;
}, [conversationId]);
@@ -479,6 +481,29 @@ export const useChatScreen = () => {
isBrowsingHistoryRef.current = browsing;
}, []);
// 进入聊天详情后立即清未读(不依赖滚动位置)
useEffect(() => {
if (!conversationId) return;
if (!conversation) return;
const unreadCount = Number((conversation as any).unread_count || 0);
if (unreadCount <= 0) return;
const latestFromConversation = Number((conversation as any).last_seq || 0);
const latestFromMessages = messages.length > 0 ? Math.max(...messages.map(m => m.seq || 0)) : 0;
const targetSeq = Math.max(latestFromConversation, latestFromMessages);
if (targetSeq <= 0) return;
const markKey = `${conversationId}:${targetSeq}`;
if (enterMarkedKeyRef.current === markKey) return;
enterMarkedKeyRef.current = markKey;
prevMarkedReadSeqRef.current = Math.max(prevMarkedReadSeqRef.current, targetSeq);
markAsRead(targetSeq).catch(error => {
console.error('[ChatScreen] 进入会话清未读失败:', error);
});
}, [conversationId, conversation, messages, markAsRead]);
// 自动标记已读QQ/Telegram 风格):
// 仅当出现更大的 latest seq且用户在最新端附近时才上报。
// 历史加载/浏览历史不会触发 read。
@@ -521,20 +546,10 @@ export const useChatScreen = () => {
const keyboardWillShow = (e: KeyboardEvent) => {
setKeyboardHeight(e.endCoordinates.height);
setActivePanel(prev => prev === 'mention' ? 'mention' : 'none');
if (isNearBottom()) {
setTimeout(() => {
scrollToLatest(false, false, 'keyboard-show');
}, 150);
}
};
const keyboardWillHide = () => {
setKeyboardHeight(0);
if (isNearBottom()) {
setTimeout(() => {
scrollToLatest(false, false, 'keyboard-hide');
}, 100);
}
};
const showSubscription = Keyboard.addListener(
@@ -550,7 +565,7 @@ export const useChatScreen = () => {
showSubscription.remove();
hideSubscription.remove();
};
}, [scrollToLatest, isNearBottom]);
}, []);
// 格式化时间
const formatTime = useCallback((dateString: string): string => {
@@ -996,28 +1011,18 @@ export const useChatScreen = () => {
Keyboard.dismiss();
setActivePanel(prev => {
const newPanel = prev === 'emoji' ? 'none' : 'emoji';
if (newPanel !== 'none' && isNearBottom()) {
setTimeout(() => {
scrollToLatest(false, false, 'open-emoji-panel');
}, 200);
}
return newPanel;
});
}, [scrollToLatest, isNearBottom]);
}, []);
// 切换更多功能面板
const toggleMorePanel = useCallback(() => {
Keyboard.dismiss();
setActivePanel(prev => {
const newPanel = prev === 'more' ? 'none' : 'more';
if (newPanel !== 'none' && isNearBottom()) {
setTimeout(() => {
scrollToLatest(false, false, 'open-more-panel');
}, 200);
}
return newPanel;
});
}, [scrollToLatest, isNearBottom]);
}, []);
// 关闭面板
const closePanel = useCallback(() => {