diff --git a/pages/chat/@id/+Page.tsx b/pages/chat/@id/+Page.tsx index d3bbf18..a3d7993 100644 --- a/pages/chat/@id/+Page.tsx +++ b/pages/chat/@id/+Page.tsx @@ -493,7 +493,7 @@ export default function ChatPage() { Fact Triggers - + ; -}) { +function Messages() { const theme = useMantineTheme(); + const queryClient = useQueryClient(); + const trpc = useTRPC(); + const pageContext = usePageContext(); + const conversationId = pageContext.routeParams.id; + + const messagesResult = useQuery( + trpc.chat.messages.fetchByConversationId.queryOptions({ + conversationId, + }) + ); + const messages: Array | undefined = + messagesResult.data?.map((m) => ({ + ...m, + parts: m.parts.filter((p) => p.type === "text"), + })) || []; + + const deleteMessage = useMutation( + trpc.chat.messages.deleteOne.mutationOptions({ + onMutate: async ({ id: messageIdToDelete }) => { + /** Cancel affected queries that may be in-flight: */ + await queryClient.cancelQueries({ + queryKey: trpc.chat.messages.fetchByConversationId.queryKey({ + conversationId, + }), + }); + + /** Optimistically update the affected queries in react-query's cache: */ + const previousMessages = await queryClient.getQueryData( + trpc.chat.messages.fetchByConversationId.queryKey({ + conversationId, + }) + ); + if (!previousMessages) { + return { + previousMessages: [], + newMessages: [], + }; + } + const newMessages = previousMessages.filter( + (m: CommittedMessage) => m.id !== messageIdToDelete + ); + queryClient.setQueryData( + trpc.chat.messages.fetchByConversationId.queryKey({ + conversationId, + }), + newMessages + ); + + return { previousMessages, newMessages }; + }, + onSettled: async (data, variables, context) => { + await queryClient.invalidateQueries({ + queryKey: trpc.chat.messages.fetchByConversationId.queryKey({ + conversationId, + }), + }); + }, + onError: async (error, variables, context) => { + console.error(error); + if (!context) return; + queryClient.setQueryData( + trpc.chat.messages.fetchByConversationId.queryKey({ + conversationId, + }), + context.previousMessages + ); + }, + }) + ); + + async function handleDeleteMessage(message: DraftMessage | CommittedMessage) { + // If the message does not have an id, do nothing + if (!("id" in message) || !message.id) { + return; + } + + // Delete the message from the server using the mutation + try { + await deleteMessage.mutateAsync({ id: message.id }); + } catch (error) { + console.error("Failed to delete message:", error); + } + } + return ( {messages.map((message, index) => ( @@ -708,16 +788,17 @@ function Messages({ - - { - e.stopPropagation(); - e.preventDefault(); - // handleDeleteMessage(message.id); - }} - /> + { + e.stopPropagation(); + e.preventDefault(); + handleDeleteMessage(message); + }} + > + diff --git a/pages/chat/messages.ts b/pages/chat/messages.ts index e756d16..7acfb7e 100644 --- a/pages/chat/messages.ts +++ b/pages/chat/messages.ts @@ -54,6 +54,12 @@ export const messages = router({ .query(async ({ input: { conversationId } }) => { return await db.messages.findByConversationId(conversationId); }), + deleteOne: publicProcedure + .input((x) => x as { id: string }) + .mutation(async ({ input: { id } }) => { + await db.messages.delete(id); + return { success: true }; + }), generateRunningSummary: publicProcedure .input( (x) =>