feat(message): enhance message store management and UI stability
Some checks failed
Frontend CI / ota-android (push) Successful in 1m40s
Frontend CI / ota-ios (push) Successful in 1m38s
Frontend CI / build-and-push-web (push) Successful in 4m32s
Frontend CI / build-android-apk (push) Failing after 8m53s

Implement `removeMessage` in `useMessageStore` to allow for atomic message deletion from the state. Improve `useChatScreen` loading logic to prevent layout jumps and ensure consistent UI state during initial message loading. Additionally, add type safety for WebSocket sequence numbers and optimize message selector stability.

- Add `removeMessage` action to `useMessageStore` for state-consistent deletions
- Refine `useChatScreen` loading state logic to prevent FlashList layout issues
- Ensure `useMessages` hook returns a stable `EMPTY_MESSAGES` constant
- Cast WebSocket `seq` to integer to ensure consistent numeric comparison
- Update `useChatScreen` to use `useMessageStore` for immediate local deletion feedback
This commit is contained in:
2026-05-25 02:30:59 +08:00
parent f4db4eb1ed
commit 313820ed20
4 changed files with 29 additions and 15 deletions

View File

@@ -26,6 +26,7 @@ import { uploadService } from '@/services/upload';
import { ApiError } from '@/services/core';
// 【新架构】使用 MessageManager
import { useChat, useGroupTyping, useGroupMuted, messageManager, callStore } from '../../../../stores';
import { useMessageStore } from '../../../../stores/message';
import { groupService } from '@/services/message';
import { userManager } from '../../../../stores/user';
import { groupManager } from '../../../../stores/group';
@@ -295,17 +296,14 @@ export const useChatScreen = (props?: ChatScreenProps) => {
}, [followRestricted, myPrivateSentCount]);
// 加载态语义修正:
// isLoadingMessages 在分页加载历史时也会短暂为 true。
// 若直接驱动 ChatScreen 的 loading会导致消息列表被卸载重挂载触发“回到底部”。
// 这里只在“首屏且尚未展示过消息列表”时展示 loading 占位。
// 首屏加载:尚未展示过消息列表 且 无消息 → 显示 loading避免 FlashList 以空 data 挂载后 inverted 布局异常)
// 一旦有消息或加载完成isLoadingMessages 归 false即解除 loading
useEffect(() => {
if (messageManagerMessages.length > 0) {
hasShownMessageListRef.current = true;
}
const shouldShowInitialLoading =
!hasShownMessageListRef.current &&
isLoadingMessages &&
messageManagerMessages.length === 0;
!hasShownMessageListRef.current && messageManagerMessages.length === 0 && isLoadingMessages;
setLoading(shouldShowInitialLoading);
}, [isLoadingMessages, messageManagerMessages.length]);
@@ -1400,16 +1398,15 @@ export const useChatScreen = (props?: ChatScreenProps) => {
const handleDeleteMessage = useCallback(async (messageId: string) => {
try {
await messageService.deleteMessage(messageId);
// 从本地状态移除MessageManager 不会自动处理删除)
const updatedMessages = messages.filter(m => m.id !== messageId);
// 注意:这里我们依赖 MessageManager 的数据,所以需要通过其他方式刷新
// 暂时只删除本地数据库
await messageRepository.delete(messageId);
if (conversationId) {
useMessageStore.getState().removeMessage(conversationId, messageId);
}
} catch (error) {
console.error('删除消息失败:', error);
Alert.alert('删除失败', '无法删除消息');
}
}, [messages]);
}, [conversationId]);
// 清空会话的所有聊天记录
const handleClearConversation = useCallback(async () => {