Skip to content

Commit

Permalink
fix: user scrolling only recognized upwards
Browse files Browse the repository at this point in the history
  • Loading branch information
aeschi committed Sep 30, 2024
1 parent 7f911b7 commit 851f087
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 82 deletions.
37 changes: 17 additions & 20 deletions src/components/chat/chat-messages.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef } from "react";
import React, { useEffect, useRef, useState } from "react";
import { useChatHistoryStore } from "../../store/chat-history-store";
import { useCurrentChatIdStore } from "../../store/current-chat-id-store";
import { FileMessage } from "../messages/file-message";
Expand All @@ -11,6 +11,8 @@ export const ChatMessages: React.FC = () => {
const { currentChatId } = useCurrentChatIdStore();
const { setHasUserScrolled } = useHasUserScrolledStore();

const [lastScrollTop, setLastScrollTop] = useState(0);

const messages: Message[] = getChat(currentChatId)?.messages || [];

const messageContainerRef = useRef<null | HTMLDivElement>(null);
Expand All @@ -22,10 +24,8 @@ export const ChatMessages: React.FC = () => {
messagesContainer &&
!useHasUserScrolledStore.getState().hasUserScrolled
) {
messagesContainer.scrollTo({
top: messagesContainer.scrollHeight,
behavior: "smooth",
});
messagesContainer.scrollTop =
messagesContainer.scrollHeight - messagesContainer.clientHeight;
}
};

Expand All @@ -37,30 +37,26 @@ export const ChatMessages: React.FC = () => {
}

const isScrollPositionCloseToEnd =
messagesContainer.scrollTop + messagesContainer.clientHeight >=
messagesContainer.scrollHeight - 10;
messagesContainer.scrollHeight - messagesContainer.clientHeight <=
messagesContainer.scrollTop + 1;

if (isScrollPositionCloseToEnd) {
setHasUserScrolled(false);
return;
}

setHasUserScrolled(true);
};

useEffect(() => {
const messagesContainer = messageContainerRef.current;
const scrollTop = messagesContainer.scrollTop;

if (!messagesContainer) {
return () => {};
/*
/ Check for scroll direction to prevent programmatical scrolling being misinterpreted as user scrolling
/ There is no need to stop auto scrolling to the new message, when user is scrolling down as well.
*/
if (lastScrollTop > scrollTop) {
setHasUserScrolled(true);
}

messagesContainer.addEventListener("scroll", handleScroll);

return () => {
messagesContainer.removeEventListener("scroll", handleScroll);
};
}, []);
setLastScrollTop(scrollTop);
};

useEffect(() => {
scrollToBottom();
Expand All @@ -69,6 +65,7 @@ export const ChatMessages: React.FC = () => {
return (
<div
ref={messageContainerRef}
onScroll={handleScroll}
className="flex w-full justify-center overflow-y-auto overflow-x-hidden scroll-smooth mb-2"
>
<div className="md:w-[640px] lg:w-[768px] w-full h-full flex flex-col gap-y-4 px-5 md:pr-0 md:pl-2 ">
Expand Down
37 changes: 17 additions & 20 deletions src/components/edit/edit-chat-messages.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef } from "react";
import React, { useEffect, useRef, useState } from "react";
import { useChatHistoryStore } from "../../store/chat-history-store";
import { useCurrentChatIdStore } from "../../store/current-chat-id-store";
import { FileMessage } from "../messages/file-message";
Expand All @@ -12,6 +12,8 @@ export const EditChatMessages: React.FC = () => {
const { currentChatId } = useCurrentChatIdStore();
const { setHasUserScrolled } = useHasUserScrolledStore();

const [lastScrollTop, setLastScrollTop] = useState(0);

const messages: Message[] = getChat(currentChatId)?.messages || [];

const messageContainerRef = useRef<null | HTMLDivElement>(null);
Expand All @@ -23,10 +25,8 @@ export const EditChatMessages: React.FC = () => {
messagesContainer &&
!useHasUserScrolledStore.getState().hasUserScrolled
) {
messagesContainer.scrollTo({
top: messagesContainer.scrollHeight,
behavior: "smooth",
});
messagesContainer.scrollTop =
messagesContainer.scrollHeight - messagesContainer.clientHeight;
}
};

Expand All @@ -38,30 +38,26 @@ export const EditChatMessages: React.FC = () => {
}

const isScrollPositionCloseToEnd =
messagesContainer.scrollTop + messagesContainer.clientHeight >=
messagesContainer.scrollHeight - 10;
messagesContainer.scrollHeight - messagesContainer.clientHeight <=
messagesContainer.scrollTop + 1;

if (isScrollPositionCloseToEnd) {
setHasUserScrolled(false);
return;
}

setHasUserScrolled(true);
};

useEffect(() => {
const messagesContainer = messageContainerRef.current;
const scrollTop = messagesContainer.scrollTop;

if (!messagesContainer) {
return () => {};
/*
/ Check for scroll direction to prevent programmatical scrolling being misinterpreted as user scrolling
/ There is no need to stop auto scrolling to the new message, when user is scrolling down as well.
*/
if (lastScrollTop > scrollTop) {
setHasUserScrolled(true);
}

messagesContainer.addEventListener("scroll", handleScroll);

return () => {
messagesContainer.removeEventListener("scroll", handleScroll);
};
}, []);
setLastScrollTop(scrollTop);
};

useEffect(() => {
scrollToBottom();
Expand All @@ -70,6 +66,7 @@ export const EditChatMessages: React.FC = () => {
return (
<div
ref={messageContainerRef}
onScroll={handleScroll}
className="flex w-full justify-center overflow-y-auto overflow-x-hidden scroll-smooth mb-2"
>
<div className="md:w-[640px] lg:w-[768px] w-full h-full flex flex-col gap-y-4 px-5 md:pr-0 md:pl-2 ">
Expand Down
39 changes: 18 additions & 21 deletions src/components/email-chat/email-chat-messages.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef } from "react";
import React, { useEffect, useRef, useState } from "react";
import { useCurrentChatIdStore } from "../../store/current-chat-id-store";
import { Message } from "../../store/types";
import { TextMessage } from "../messages/text-message";
Expand All @@ -11,6 +11,8 @@ export const EmailChatMessages: React.FC = () => {
const { currentChatId } = useCurrentChatIdStore();
const { setHasUserScrolled } = useHasUserScrolledStore();

const [lastScrollTop, setLastScrollTop] = useState(0);

const messages: Message[] = getChat(currentChatId)?.messages || [];

const messageContainerRef = useRef<null | HTMLDivElement>(null);
Expand All @@ -22,10 +24,8 @@ export const EmailChatMessages: React.FC = () => {
messagesContainer &&
!useHasUserScrolledStore.getState().hasUserScrolled
) {
messagesContainer.scrollTo({
top: messagesContainer.scrollHeight,
behavior: "smooth",
});
messagesContainer.scrollTop =
messagesContainer.scrollHeight - messagesContainer.clientHeight;
}
};

Expand All @@ -37,30 +37,26 @@ export const EmailChatMessages: React.FC = () => {
}

const isScrollPositionCloseToEnd =
messagesContainer.scrollTop + messagesContainer.clientHeight >=
messagesContainer.scrollHeight - 10;
messagesContainer.scrollHeight - messagesContainer.clientHeight <=
messagesContainer.scrollTop + 1;

if (isScrollPositionCloseToEnd) {
setHasUserScrolled(false);
return;
}

setHasUserScrolled(true);
};

useEffect(() => {
const messagesContainer = messageContainerRef.current;
const scrollTop = messagesContainer.scrollTop;

if (!messagesContainer) {
return () => {};
/*
/ Check for scroll direction to prevent programmatical scrolling being misinterpreted as user scrolling
/ There is no need to stop auto scrolling to the new message, when user is scrolling down as well.
*/
if (lastScrollTop > scrollTop) {
setHasUserScrolled(true);
}

messagesContainer.addEventListener("scroll", handleScroll);

return () => {
messagesContainer.removeEventListener("scroll", handleScroll);
};
}, []);
setLastScrollTop(scrollTop);
};

useEffect(() => {
scrollToBottom();
Expand All @@ -69,7 +65,8 @@ export const EmailChatMessages: React.FC = () => {
return (
<div
ref={messageContainerRef}
className="flex w-full justify-center overflow-y-auto overflow-x-hidden pb-2 px-5"
onScroll={handleScroll}
className="flex w-full scroll-smooth justify-center overflow-y-auto overflow-x-hidden pb-2 px-5 mb-2 "
>
<div className="md:w-[640px] lg:w-[768px] flex flex-col gap-y-4">
<div className="flex">
Expand Down
39 changes: 18 additions & 21 deletions src/components/email/email-messages.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef } from "react";
import React, { useEffect, useRef, useState } from "react";
import { useCurrentChatIdStore } from "../../store/current-chat-id-store";
import { Message } from "../../store/types";
import { TextMessage } from "../messages/text-message";
Expand All @@ -10,6 +10,8 @@ export const EmailMessages: React.FC = () => {
const { currentChatId } = useCurrentChatIdStore();
const { setHasUserScrolled } = useHasUserScrolledStore();

const [lastScrollTop, setLastScrollTop] = useState(0);

const messages: Message[] = getChat(currentChatId)?.messages || [];

const messageContainerRef = useRef<null | HTMLDivElement>(null);
Expand All @@ -21,10 +23,8 @@ export const EmailMessages: React.FC = () => {
messagesContainer &&
!useHasUserScrolledStore.getState().hasUserScrolled
) {
messagesContainer.scrollTo({
top: messagesContainer.scrollHeight,
behavior: "smooth",
});
messagesContainer.scrollTop =
messagesContainer.scrollHeight - messagesContainer.clientHeight;
}
};

Expand All @@ -36,30 +36,26 @@ export const EmailMessages: React.FC = () => {
}

const isScrollPositionCloseToEnd =
messagesContainer.scrollTop + messagesContainer.clientHeight >=
messagesContainer.scrollHeight - 10;
messagesContainer.scrollHeight - messagesContainer.clientHeight <=
messagesContainer.scrollTop - 10;

if (isScrollPositionCloseToEnd) {
setHasUserScrolled(false);
return;
}

setHasUserScrolled(true);
};

useEffect(() => {
const messagesContainer = messageContainerRef.current;
const scrollTop = messagesContainer.scrollTop;

if (!messagesContainer) {
return () => {};
/*
/ Check for scroll direction to prevent programmatical scrolling being misinterpreted as user scrolling
/ There is no need to stop auto scrolling to the new message, when user is scrolling down as well.
*/
if (lastScrollTop > scrollTop) {
setHasUserScrolled(true);
}

messagesContainer.addEventListener("scroll", handleScroll);

return () => {
messagesContainer.removeEventListener("scroll", handleScroll);
};
}, []);
setLastScrollTop(scrollTop);
};

useEffect(() => {
scrollToBottom();
Expand All @@ -68,7 +64,8 @@ export const EmailMessages: React.FC = () => {
return (
<div
ref={messageContainerRef}
className="flex w-full justify-center overflow-y-auto overflow-x-hidden pb-2 px-5"
onScroll={handleScroll}
className="flex w-full justify-center overflow-y-auto overflow-x-hidden pb-2 px-5 scroll-smooth"
>
<div className="md:w-[640px] lg:w-[768px] flex flex-col gap-y-4">
{messages.map((message) => (
Expand Down

0 comments on commit 851f087

Please sign in to comment.