mirror of
https://github.com/hexastack/hexabot
synced 2025-01-23 02:47:56 +00:00
Merge pull request #203 from Hexastack/202-bug-freeze-in-the-widget-scrollbar
fix(widget): scrollbar freeze
This commit is contained in:
commit
a9070580bd
@ -6,15 +6,15 @@
|
|||||||
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { PropsWithChildren, useEffect, useRef, useState } from 'react';
|
import React, { PropsWithChildren, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import Message from './Message';
|
import Message from "./Message";
|
||||||
import TypingMessage from './messages/TypingMessage';
|
import TypingMessage from "./messages/TypingMessage";
|
||||||
import { useChat } from '../providers/ChatProvider';
|
import { useChat } from "../providers/ChatProvider";
|
||||||
import { useColors } from '../providers/ColorProvider';
|
import { useColors } from "../providers/ColorProvider";
|
||||||
import { useWidget } from '../providers/WidgetProvider';
|
import { useWidget } from "../providers/WidgetProvider";
|
||||||
|
import "./Messages.scss";
|
||||||
import './Messages.scss';
|
import { TMessage } from "../types/message.types";
|
||||||
|
|
||||||
type MessagesProps = PropsWithChildren<{
|
type MessagesProps = PropsWithChildren<{
|
||||||
Avatar?: () => JSX.Element;
|
Avatar?: () => JSX.Element;
|
||||||
@ -25,34 +25,16 @@ const Messages: React.FC<MessagesProps> = ({ Avatar }) => {
|
|||||||
const { messages, showTypingIndicator, setNewIOMessage } = useChat();
|
const { messages, showTypingIndicator, setNewIOMessage } = useChat();
|
||||||
const { colors } = useColors();
|
const { colors } = useColors();
|
||||||
const scrollListRef = useRef<HTMLDivElement>(null);
|
const scrollListRef = useRef<HTMLDivElement>(null);
|
||||||
const [timeoutId, setTimeoutId] = useState<number | null>(null);
|
const [lastReceivedMessage, setLastReceivedMessage] = useState<
|
||||||
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
|
TMessage | undefined
|
||||||
if (timeoutId) {
|
>();
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
const scrollPercent = Math.round(
|
|
||||||
(100 * e.currentTarget.scrollTop) / (e.currentTarget.scrollHeight || 1),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!scroll && scrollPercent) {
|
|
||||||
setScroll(scrollPercent);
|
|
||||||
} else if (scrollPercent) {
|
|
||||||
const id = setTimeout(() => {
|
|
||||||
setScroll(scrollPercent);
|
|
||||||
}, 400) as unknown as number;
|
|
||||||
|
|
||||||
setTimeoutId(id);
|
|
||||||
} else if (scroll) {
|
|
||||||
setScroll(scrollPercent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const scrollTo = (scroll: number) => {
|
const scrollTo = (scroll: number) => {
|
||||||
if (scrollListRef.current) {
|
if (scrollListRef.current) {
|
||||||
const scrollPercent = Math.round(
|
const scrollPercent = Math.round(
|
||||||
(100 * scrollListRef.current.scrollTop) /
|
(100 * scrollListRef.current.scrollTop) /
|
||||||
(scrollListRef.current.scrollHeight || 1),
|
(scrollListRef.current.scrollHeight || 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (Math.abs(scrollPercent - scroll) > 1 || scroll === 100) {
|
if (Math.abs(scrollPercent - scroll) > 1 || scroll === 100) {
|
||||||
@ -60,9 +42,9 @@ const Messages: React.FC<MessagesProps> = ({ Avatar }) => {
|
|||||||
if (scrollListRef.current) {
|
if (scrollListRef.current) {
|
||||||
scrollListRef.current.scrollTo({
|
scrollListRef.current.scrollTo({
|
||||||
top: Math.round(
|
top: Math.round(
|
||||||
(scroll * scrollListRef.current.scrollHeight) / 100,
|
(scroll * scrollListRef.current.scrollHeight) / 100
|
||||||
),
|
),
|
||||||
behavior: 'instant',
|
behavior: "instant",
|
||||||
left: 0,
|
left: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -83,12 +65,22 @@ const Messages: React.FC<MessagesProps> = ({ Avatar }) => {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const newestReceivedMessage = messages[messages.length - 1];
|
||||||
|
|
||||||
|
if (lastReceivedMessage !== newestReceivedMessage) {
|
||||||
|
setLastReceivedMessage(newestReceivedMessage);
|
||||||
|
setScroll(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [messages.length]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="sc-message-list"
|
className="sc-message-list"
|
||||||
ref={scrollListRef}
|
ref={scrollListRef}
|
||||||
style={{ backgroundColor: colors.messageList.bg }}
|
style={{ backgroundColor: colors.messageList.bg }}
|
||||||
onScroll={handleScroll}
|
|
||||||
>
|
>
|
||||||
{messages.map((message) => (
|
{messages.map((message) => (
|
||||||
<Message key={message.mid} message={message} Avatar={Avatar} />
|
<Message key={message.mid} message={message} Avatar={Avatar} />
|
||||||
|
Loading…
Reference in New Issue
Block a user