From c0ebebe3da12ac52e539aacfdae0f974e995a306 Mon Sep 17 00:00:00 2001 From: lan Date: Tue, 5 May 2026 02:01:05 +0800 Subject: [PATCH] feat(db): add getLastMessageByConversation and update conversation list preview Add `getLastMessageByConversation` to `MessageRepository` to allow fetching the most recent message for a specific conversation. Update `ConversationListRow` to use this new repository method as a fallback when message segments are missing, ensuring the conversation list preview displays the last message content correctly. --- .../repositories/MessageRepository.ts | 10 +++++++ .../components/ConversationListRow.tsx | 28 +++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/database/repositories/MessageRepository.ts b/src/database/repositories/MessageRepository.ts index 961bd41..f64384c 100644 --- a/src/database/repositories/MessageRepository.ts +++ b/src/database/repositories/MessageRepository.ts @@ -18,6 +18,7 @@ export interface IMessageRepository { clearConversation(conversationId: string): Promise; search(keyword: string): Promise; getStats(): Promise<{ totalMessages: number; totalConversations: number }>; + getLastMessageByConversation(conversationId: string): Promise; } export class MessageRepository implements IMessageRepository { @@ -147,6 +148,15 @@ export class MessageRepository implements IMessageRepository { const convCount = await this.dataSource.getFirst<{ count: number }>(`SELECT COUNT(*) as count FROM conversations`); return { totalMessages: msgCount?.count || 0, totalConversations: convCount?.count || 0 }; } + + async getLastMessageByConversation(conversationId: string): Promise { + const r = await this.dataSource.getFirst( + `SELECT * FROM messages WHERE conversationId = ? AND status != 'deleted' ORDER BY seq DESC LIMIT 1`, + [conversationId] + ); + if (!r) return null; + return { ...r, isRead: r.isRead === 1, segments: r.segments ? JSON.parse(r.segments) : undefined }; + } } export const messageRepository = new MessageRepository(); \ No newline at end of file diff --git a/src/screens/message/components/ConversationListRow.tsx b/src/screens/message/components/ConversationListRow.tsx index a83a4af..a80ca02 100644 --- a/src/screens/message/components/ConversationListRow.tsx +++ b/src/screens/message/components/ConversationListRow.tsx @@ -14,7 +14,7 @@ import { MessageSegment, } from '../../../types/dto'; import { authService } from '../../../services'; -import { userCacheRepository } from '@/database'; +import { userCacheRepository, messageRepository } from '@/database'; import { Avatar, Text } from '../../../components/common'; const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity); @@ -34,7 +34,8 @@ const AsyncMessagePreview: React.FC<{ status?: string; isGroupChat?: boolean; senderName?: string; -}> = ({ segments, status, isGroupChat, senderName }) => { + conversationId?: string; +}> = ({ segments, status, isGroupChat, senderName, conversationId }) => { const [displayText, setDisplayText] = useState(''); const isMountedRef = useRef(true); @@ -49,19 +50,33 @@ const AsyncMessagePreview: React.FC<{ return; } - const initialText = extractTextFromSegments(segments); + let effectiveSegments = segments; + + // 当 segments 为空时,从本地 SQLite 回退查询 + if ((!effectiveSegments || effectiveSegments.length === 0) && conversationId) { + try { + const lastMsg = await messageRepository.getLastMessageByConversation(conversationId); + if (lastMsg?.segments) { + effectiveSegments = Array.isArray(lastMsg.segments) + ? lastMsg.segments + : JSON.parse(lastMsg.segments); + } + } catch {} + } + + const initialText = extractTextFromSegments(effectiveSegments); if (isMountedRef.current) { setDisplayText(initialText); } - const hasAtWithoutNickname = segments?.some( + const hasAtWithoutNickname = effectiveSegments?.some( (s) => s.type === 'at' && s.data.user_id !== 'all' && !s.data.nickname ); if (hasAtWithoutNickname) { try { const asyncText = await extractTextFromSegmentsAsync( - segments, + effectiveSegments, userCacheRepository.get.bind(userCacheRepository), authService.getUserById.bind(authService) ); @@ -79,7 +94,7 @@ const AsyncMessagePreview: React.FC<{ return () => { isMountedRef.current = false; }; - }, [segments, status]); + }, [segments, status, conversationId]); if (!displayText) return null; @@ -363,6 +378,7 @@ const ConversationListRowInner: React.FC = ({ status={item.last_message?.status} isGroupChat={isGroupChat} senderName={getSenderName()} + conversationId={item.id} /> )}