diff --git a/www/app/globals.css b/www/app/globals.css
index f788bea..526170c 100644
--- a/www/app/globals.css
+++ b/www/app/globals.css
@@ -2,6 +2,9 @@
@tailwind components;
@tailwind utilities;
+html {
+ scroll-behavior: smooth;
+}
.typing_dot {
animation: typing 1s infinite;
@@ -28,4 +31,4 @@
.typing_dot:nth-child(3) {
animation-delay: 0.4s;
-}
\ No newline at end of file
+}
diff --git a/www/app/page.tsx b/www/app/page.tsx
index fc0cd00..fc31452 100644
--- a/www/app/page.tsx
+++ b/www/app/page.tsx
@@ -15,7 +15,14 @@ import {
} from "react-icons/fa";
// import { IoIosArrowDown } from "react-icons/io";
// import { GrClose } from "react-icons/gr";
-import { useRef, useEffect, useState, useCallback } from "react";
+import {
+ useRef,
+ useEffect,
+ useState,
+ useCallback,
+ use,
+ ElementRef,
+} from "react";
import { v4 as uuidv4 } from "uuid";
import Typing from "@/components/typing";
@@ -56,9 +63,12 @@ export default function Home() {
conversation_id: "",
name: "",
});
- const input = useRef(null);
+ const input = useRef>(null);
const supabase = createClientComponentClient();
+ const isAtBottom = useRef(true);
+ const messageContainerRef = useRef>(null);
+
const newChat = useCallback(async () => {
return await fetch(`${URL}/api/conversations/insert?user_id=${userId}`)
.then((res) => res.json())
@@ -144,8 +154,33 @@ export default function Home() {
setMessages([defaultMessage, ...messages]);
});
}
+
+ // scroll to bottom
+ const messageContainer = messageContainerRef.current;
+ if (messageContainer) {
+ messageContainer.scrollTop = messageContainer.scrollHeight;
+ }
}, [currentConversation, userId]);
+ useEffect(() => {
+ const messageContainer = messageContainerRef.current;
+ if (!messageContainer) return;
+
+ const func = () => {
+ const val =
+ Math.round(
+ messageContainer.scrollHeight - messageContainer.scrollTop
+ ) === messageContainer.clientHeight;
+ isAtBottom.current = val;
+ };
+
+ messageContainer.addEventListener("scroll", func);
+
+ return () => {
+ messageContainer.removeEventListener("scroll", func);
+ };
+ }, []);
+
// async function newChat() {
// return await fetch(`${URL}/api/conversations/insert?user_id=${userId}`)
// .then((res) => res.json())
@@ -207,6 +242,11 @@ export default function Home() {
const reader = data.body?.pipeThrough(new TextDecoderStream()).getReader()!;
+ const messageContainer = messageContainerRef.current;
+ if (messageContainer) {
+ messageContainer.scrollTop = messageContainer.scrollHeight;
+ }
+
// clear the last message
setMessages((prev) => {
prev[prev.length - 1].text = "";
@@ -240,6 +280,13 @@ export default function Home() {
prev[prev.length - 1].text += value;
return [...prev];
});
+
+ if (isAtBottom.current) {
+ const messageContainer = messageContainerRef.current;
+ if (messageContainer) {
+ messageContainer.scrollTop = messageContainer.scrollHeight;
+ }
+ }
}
}
}
@@ -285,7 +332,10 @@ export default function Home() {
)}
-
+
{messages.map((message, i) => (