chat-with-gpt/src/use-chat.ts

76 lines
2.1 KiB
TypeScript
Raw Normal View History

2023-03-06 13:30:58 +00:00
import { useCallback, useEffect, useState } from "react";
import { backend } from "./backend";
2023-03-08 21:30:11 +00:00
import { ChatManager } from "./chat-manager";
2023-03-06 13:30:58 +00:00
import { Chat, Message } from './types';
2023-03-08 21:30:11 +00:00
export interface UseChatResult {
chat: Chat | null | undefined;
chatLoadedAt: number;
messages: Message[];
messagesToDisplay: Message[];
leaf: Message | null | undefined;
}
export function useChat(chatManager: ChatManager, id: string | undefined | null, share = false): UseChatResult {
2023-03-06 13:30:58 +00:00
const [chat, setChat] = useState<Chat | null | undefined>(null);
2023-03-09 19:50:57 +00:00
const [_, setVersion] = useState(0);
2023-03-06 13:30:58 +00:00
// used to prevent auto-scroll when chat is first opened
const [chatLoadedAt, setLoadedAt] = useState(0);
const update = useCallback(async () => {
if (id) {
if (!share) {
2023-03-08 21:30:11 +00:00
const c = chatManager.get(id);
2023-03-06 13:30:58 +00:00
if (c) {
setChat(c);
setVersion(v => v + 1);
return;
}
} else {
2023-03-09 19:50:57 +00:00
const c = await backend.current?.getSharedChat(id);
2023-03-06 13:30:58 +00:00
if (c) {
setChat(c);
setVersion(v => v + 1);
return;
}
}
}
setChat(null);
2023-03-09 19:50:57 +00:00
}, [id, share, chatManager]);
2023-03-06 13:30:58 +00:00
useEffect(() => {
if (id) {
update();
2023-03-08 21:30:11 +00:00
chatManager.on(id, update);
setChat(chatManager.get(id));
2023-03-06 13:30:58 +00:00
setLoadedAt(Date.now());
} else {
setChat(null);
setLoadedAt(0);
}
return () => {
if (id) {
2023-03-08 21:30:11 +00:00
chatManager.off(id, update);
2023-03-06 13:30:58 +00:00
}
};
2023-03-09 19:50:57 +00:00
}, [id, update, chatManager]);
2023-03-06 13:30:58 +00:00
const leaf = chat?.messages.mostRecentLeaf();
let messages: Message[] = [];
2023-03-08 21:30:11 +00:00
let messagesToDisplay: Message[] = [];
2023-03-06 13:30:58 +00:00
if (leaf) {
2023-03-08 21:30:11 +00:00
messages = (chat?.messages.getMessageChainTo(leaf?.id) || []);
messagesToDisplay = messages.filter(m => ['user', 'assistant'].includes(m.role)) || [];
2023-03-06 13:30:58 +00:00
}
return {
chat,
chatLoadedAt,
messages,
2023-03-08 21:30:11 +00:00
messagesToDisplay,
2023-03-06 13:30:58 +00:00
leaf,
};
}