Eduards commited on
Commit
a0ae79a
·
1 Parent(s): b7d609d

Add ability to return to older chat message state

Browse files
app/components/chat/Messages.client.tsx CHANGED
@@ -3,6 +3,7 @@ import React from 'react';
3
  import { classNames } from '~/utils/classNames';
4
  import { AssistantMessage } from './AssistantMessage';
5
  import { UserMessage } from './UserMessage';
 
6
 
7
  interface MessagesProps {
8
  id?: string;
@@ -13,12 +14,21 @@ interface MessagesProps {
13
 
14
  export const Messages = React.forwardRef<HTMLDivElement, MessagesProps>((props: MessagesProps, ref) => {
15
  const { id, isStreaming = false, messages = [] } = props;
 
 
 
 
 
 
 
 
 
16
 
17
  return (
18
  <div id={id} ref={ref} className={props.className}>
19
  {messages.length > 0
20
  ? messages.map((message, index) => {
21
- const { role, content } = message;
22
  const isUserMessage = role === 'user';
23
  const isFirst = index === 0;
24
  const isLast = index === messages.length - 1;
@@ -41,6 +51,15 @@ export const Messages = React.forwardRef<HTMLDivElement, MessagesProps>((props:
41
  <div className="grid grid-col-1 w-full">
42
  {isUserMessage ? <UserMessage content={content} /> : <AssistantMessage content={content} />}
43
  </div>
 
 
 
 
 
 
 
 
 
44
  </div>
45
  );
46
  })
 
3
  import { classNames } from '~/utils/classNames';
4
  import { AssistantMessage } from './AssistantMessage';
5
  import { UserMessage } from './UserMessage';
6
+ import { useLocation, useNavigate } from '@remix-run/react';
7
 
8
  interface MessagesProps {
9
  id?: string;
 
14
 
15
  export const Messages = React.forwardRef<HTMLDivElement, MessagesProps>((props: MessagesProps, ref) => {
16
  const { id, isStreaming = false, messages = [] } = props;
17
+ const location = useLocation();
18
+ const navigate = useNavigate();
19
+
20
+ const handleRewind = (messageId: string) => {
21
+ const searchParams = new URLSearchParams(location.search);
22
+ searchParams.set('rewindId', messageId);
23
+ window.location.search = searchParams.toString();
24
+ //navigate(`${location.pathname}?${searchParams.toString()}`);
25
+ };
26
 
27
  return (
28
  <div id={id} ref={ref} className={props.className}>
29
  {messages.length > 0
30
  ? messages.map((message, index) => {
31
+ const { role, content, id: messageId } = message;
32
  const isUserMessage = role === 'user';
33
  const isFirst = index === 0;
34
  const isLast = index === messages.length - 1;
 
51
  <div className="grid grid-col-1 w-full">
52
  {isUserMessage ? <UserMessage content={content} /> : <AssistantMessage content={content} />}
53
  </div>
54
+ {messageId && (
55
+ <button
56
+ onClick={() => handleRewind(messageId)}
57
+ className="self-start p-2 text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary"
58
+ title="Rewind to this message"
59
+ >
60
+ <div className="i-ph:arrow-counter-clockwise text-xl"></div>
61
+ </button>
62
+ )}
63
  </div>
64
  );
65
  })
app/lib/persistence/useChatHistory.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { useLoaderData, useNavigate } from '@remix-run/react';
2
  import { useState, useEffect } from 'react';
3
  import { atom } from 'nanostores';
4
  import type { Message } from 'ai';
@@ -24,6 +24,7 @@ export const description = atom<string | undefined>(undefined);
24
  export function useChatHistory() {
25
  const navigate = useNavigate();
26
  const { id: mixedId } = useLoaderData<{ id?: string }>();
 
27
 
28
  const [initialMessages, setInitialMessages] = useState<Message[]>([]);
29
  const [ready, setReady] = useState<boolean>(false);
@@ -44,7 +45,13 @@ export function useChatHistory() {
44
  getMessages(db, mixedId)
45
  .then((storedMessages) => {
46
  if (storedMessages && storedMessages.messages.length > 0) {
47
- setInitialMessages(storedMessages.messages);
 
 
 
 
 
 
48
  setUrlId(storedMessages.urlId);
49
  description.set(storedMessages.description);
50
  chatId.set(storedMessages.id);
 
1
+ import { useLoaderData, useNavigate, useSearchParams } from '@remix-run/react';
2
  import { useState, useEffect } from 'react';
3
  import { atom } from 'nanostores';
4
  import type { Message } from 'ai';
 
24
  export function useChatHistory() {
25
  const navigate = useNavigate();
26
  const { id: mixedId } = useLoaderData<{ id?: string }>();
27
+ const [searchParams] = useSearchParams();
28
 
29
  const [initialMessages, setInitialMessages] = useState<Message[]>([]);
30
  const [ready, setReady] = useState<boolean>(false);
 
45
  getMessages(db, mixedId)
46
  .then((storedMessages) => {
47
  if (storedMessages && storedMessages.messages.length > 0) {
48
+ const rewindId = searchParams.get('rewindId');
49
+ const filteredMessages = rewindId
50
+ ? storedMessages.messages.slice(0,
51
+ storedMessages.messages.findIndex(m => m.id === rewindId) + 1)
52
+ : storedMessages.messages;
53
+
54
+ setInitialMessages(filteredMessages);
55
  setUrlId(storedMessages.urlId);
56
  description.set(storedMessages.description);
57
  chatId.set(storedMessages.id);