feat: implement chat persistence with MongoDB
- Add full chat persistence to database (conversations and messages) - Implement MongoChatRepository with cursor-based pagination - Add getConversations/getConversation endpoints in ChatController - Save user and assistant messages in ChatService.processMessage() - Track respondedAction (confirm/reject) on proposed event messages - Load existing messages on chat screen mount - Add addMessages() bulk action and chatMessageToMessageData() helper to ChatStore - Add RespondedAction type and UpdateMessageDTO to shared types
This commit is contained in:
@@ -1,18 +1,25 @@
|
||||
import { View, Text, TextInput, Pressable, KeyboardAvoidingView, Platform, Keyboard } from "react-native";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TextInput,
|
||||
Pressable,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
Keyboard,
|
||||
} from "react-native";
|
||||
import currentTheme from "../../Themes";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import Header from "../../components/Header";
|
||||
import BaseBackground from "../../components/BaseBackground";
|
||||
import { FlashList } from "@shopify/flash-list";
|
||||
import { ChatService } from "../../services";
|
||||
import { useChatStore, MessageData } from "../../stores";
|
||||
import { useChatStore, chatMessageToMessageData, MessageData } from "../../stores";
|
||||
import { ProposedEventChange } from "@caldav/shared";
|
||||
import { ProposedEventCard } from "../../components/ProposedEventCard";
|
||||
|
||||
// TODO: better shadows for everything
|
||||
// (maybe with extra library because of differences between android and ios)
|
||||
// TODO: max width for messages
|
||||
// TODO: create new messages
|
||||
|
||||
type BubbleSide = "left" | "right";
|
||||
|
||||
@@ -30,14 +37,43 @@ type ChatInputProps = {
|
||||
};
|
||||
|
||||
const Chat = () => {
|
||||
const { messages, addMessage, updateMessage } = useChatStore();
|
||||
const listRef = useRef<FlashList<MessageData>>(null);
|
||||
const { messages, addMessage, addMessages, updateMessage } = useChatStore();
|
||||
const listRef =
|
||||
useRef<React.ComponentRef<typeof FlashList<MessageData>>>(null);
|
||||
const [currentConversationId, setCurrentConversationId] = useState<
|
||||
string | undefined
|
||||
>();
|
||||
|
||||
useEffect(() => {
|
||||
const keyboardDidShow = Keyboard.addListener("keyboardDidShow", scrollToEnd);
|
||||
const keyboardDidShow = Keyboard.addListener(
|
||||
"keyboardDidShow",
|
||||
scrollToEnd,
|
||||
);
|
||||
return () => keyboardDidShow.remove();
|
||||
}, []);
|
||||
|
||||
// Load existing messages from database on mount
|
||||
useEffect(() => {
|
||||
const fetchMessages = async () => {
|
||||
try {
|
||||
const conversationSummaries = await ChatService.getConversations();
|
||||
if (conversationSummaries.length > 0) {
|
||||
const conversationId = conversationSummaries[0].id;
|
||||
setCurrentConversationId(conversationId);
|
||||
|
||||
const serverMessages =
|
||||
await ChatService.getConversation(conversationId);
|
||||
const clientMessages = serverMessages.map(chatMessageToMessageData);
|
||||
addMessages(clientMessages);
|
||||
scrollToEnd();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to load messages:", error);
|
||||
}
|
||||
};
|
||||
fetchMessages();
|
||||
}, []);
|
||||
|
||||
const scrollToEnd = () => {
|
||||
setTimeout(() => {
|
||||
listRef.current?.scrollToEnd({ animated: true });
|
||||
@@ -87,13 +123,22 @@ const Chat = () => {
|
||||
id: Date.now().toString(),
|
||||
side: "right",
|
||||
content: text,
|
||||
conversationId: currentConversationId,
|
||||
};
|
||||
addMessage(userMessage);
|
||||
scrollToEnd();
|
||||
|
||||
try {
|
||||
// Fetch server response
|
||||
const response = await ChatService.sendMessage({ content: text });
|
||||
// Fetch server response (include conversationId for existing conversations)
|
||||
const response = await ChatService.sendMessage({
|
||||
content: text,
|
||||
conversationId: currentConversationId,
|
||||
});
|
||||
|
||||
// Track conversation ID for subsequent messages
|
||||
if (!currentConversationId) {
|
||||
setCurrentConversationId(response.conversationId);
|
||||
}
|
||||
|
||||
// Show bot response
|
||||
const botMessage: MessageData = {
|
||||
|
||||
Reference in New Issue
Block a user