Update ChatPanel to handle scroll position and message fetching
- Added selectors for isTop, isBottom, and isMiddle in chatSlice. - Removed scrollPosition and stopScrolling states from ChatPanel. - Added onScrollPositionChange function to handle scroll events. - Dispatch onMessagesTop, onMessagesBottom, and onMessagesMiddle actions based on scroll position.
This commit is contained in:
parent
ec440be005
commit
9a906a1c0f
@ -24,6 +24,12 @@ import {
|
|||||||
selectErrorMessage,
|
selectErrorMessage,
|
||||||
selectMessages,
|
selectMessages,
|
||||||
selectMessageCount,
|
selectMessageCount,
|
||||||
|
selectIsBottom,
|
||||||
|
selectIsTop,
|
||||||
|
selectIsMiddle,
|
||||||
|
onMessagesBottom,
|
||||||
|
onMessagesTop,
|
||||||
|
onMessagesMiddle,
|
||||||
fetchHistoryMessages,
|
fetchHistoryMessages,
|
||||||
} from './chatSlice';
|
} from './chatSlice';
|
||||||
|
|
||||||
@ -89,22 +95,38 @@ const chatPanel = () => {
|
|||||||
const errorMessage = useAppSelector(selectErrorMessage);
|
const errorMessage = useAppSelector(selectErrorMessage);
|
||||||
const messages = useAppSelector(selectMessages);
|
const messages = useAppSelector(selectMessages);
|
||||||
const messageCount = useAppSelector(selectMessageCount);
|
const messageCount = useAppSelector(selectMessageCount);
|
||||||
|
const isTop = useAppSelector(selectIsTop);
|
||||||
|
const isBottom = useAppSelector(selectIsBottom);
|
||||||
|
const isMiddle = useAppSelector(selectIsMiddle);
|
||||||
const [chatContainerRef, chatContainerRect] = useResizeObserver();
|
const [chatContainerRef, chatContainerRect] = useResizeObserver();
|
||||||
const scrollViewport = useRef<HTMLDivElement>(null);
|
const scrollViewport = useRef<HTMLDivElement>(null);
|
||||||
const { height, width } = useViewportSize();
|
const { height, width } = useViewportSize();
|
||||||
const [scrollPosition, onScrollPositionChange] = useState({ x: 0, y: 0 });
|
|
||||||
const [stopScrolling, setStopScrolling] = useState(false);
|
|
||||||
|
|
||||||
const scrollToBottom = () =>
|
const scrollToBottom = () =>
|
||||||
scrollViewport?.current?.scrollTo({ top: scrollViewport.current.scrollHeight, behavior: 'smooth' });
|
scrollViewport?.current?.scrollTo({ top: scrollViewport.current.scrollHeight, behavior: 'smooth' });
|
||||||
|
|
||||||
const timer = useTimeout(() => {
|
const timer = useTimeout(() => {
|
||||||
// console.log(`stopScrolling:${stopScrolling}`);
|
if (isBottom) {
|
||||||
if (!stopScrolling) {
|
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
const onScrollPositionChange = ({ x, y }) => {
|
||||||
|
const sh = scrollViewport.current?.scrollHeight || 0;
|
||||||
|
const vh = scrollViewport.current?.clientHeight || 0;
|
||||||
|
const gap = sh - vh - y;
|
||||||
|
const isBottom = sh < vh ? true : gap < 100;
|
||||||
|
const isTop = y === 0;
|
||||||
|
// console.log(`sh:${sh},vh:${vh},x:${x},y:${y},gap:${gap}`);
|
||||||
|
if (isBottom) {
|
||||||
|
dispatch(onMessagesBottom());
|
||||||
|
} else if (isTop) {
|
||||||
|
dispatch(onMessagesTop());
|
||||||
|
} else {
|
||||||
|
dispatch(onMessagesMiddle());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(fetchHistoryMessages());
|
dispatch(fetchHistoryMessages());
|
||||||
messageUtil.registerHandler('receiveMessagePartial', (message: { text: string; }) => {
|
messageUtil.registerHandler('receiveMessagePartial', (message: { text: string; }) => {
|
||||||
@ -122,17 +144,6 @@ const chatPanel = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const sh = scrollViewport.current?.scrollHeight || 0;
|
|
||||||
const vh = scrollViewport.current?.clientHeight || 0;
|
|
||||||
const isBottom = sh < vh ? true : sh - vh - scrollPosition.y < 3;
|
|
||||||
if (isBottom) {
|
|
||||||
setStopScrolling(false);
|
|
||||||
} else {
|
|
||||||
setStopScrolling(true);
|
|
||||||
}
|
|
||||||
}, [scrollPosition]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (generating) {
|
if (generating) {
|
||||||
// new a bot message
|
// new a bot message
|
||||||
|
@ -24,6 +24,9 @@ export const chatSlice = createSlice({
|
|||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
messages: <any>[],
|
messages: <any>[],
|
||||||
messageCount: 10,
|
messageCount: 10,
|
||||||
|
isBottom: true,
|
||||||
|
isMiddle: false,
|
||||||
|
isTop: false,
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
startGenerating: (state, action) => {
|
startGenerating: (state, action) => {
|
||||||
@ -71,6 +74,21 @@ export const chatSlice = createSlice({
|
|||||||
},
|
},
|
||||||
happendError: (state, action) => {
|
happendError: (state, action) => {
|
||||||
state.errorMessage = action.payload;
|
state.errorMessage = action.payload;
|
||||||
|
},
|
||||||
|
onMessagesTop: (state) => {
|
||||||
|
state.isTop = true;
|
||||||
|
state.isBottom = false;
|
||||||
|
state.isMiddle = false;
|
||||||
|
},
|
||||||
|
onMessagesBottom: (state) => {
|
||||||
|
state.isTop = false;
|
||||||
|
state.isBottom = true;
|
||||||
|
state.isMiddle = false;
|
||||||
|
},
|
||||||
|
onMessagesMiddle: (state) => {
|
||||||
|
state.isTop = false;
|
||||||
|
state.isBottom = false;
|
||||||
|
state.isMiddle = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
@ -99,6 +117,9 @@ export const selectCurrentMessage = (state: RootState) => state.chat.currentMess
|
|||||||
export const selectErrorMessage = (state: RootState) => state.chat.errorMessage;
|
export const selectErrorMessage = (state: RootState) => state.chat.errorMessage;
|
||||||
export const selectMessages = (state: RootState) => state.chat.messages;
|
export const selectMessages = (state: RootState) => state.chat.messages;
|
||||||
export const selectMessageCount = (state: RootState) => state.chat.messageCount;
|
export const selectMessageCount = (state: RootState) => state.chat.messageCount;
|
||||||
|
export const selectIsBottom = (state: RootState) => state.chat.isBottom;
|
||||||
|
export const selectIsTop = (state: RootState) => state.chat.isTop;
|
||||||
|
export const selectIsMiddle = (state: RootState) => state.chat.isMiddle;
|
||||||
|
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
@ -112,6 +133,9 @@ export const {
|
|||||||
popMessage,
|
popMessage,
|
||||||
clearMessages,
|
clearMessages,
|
||||||
updateMessage,
|
updateMessage,
|
||||||
|
onMessagesTop,
|
||||||
|
onMessagesBottom,
|
||||||
|
onMessagesMiddle,
|
||||||
} = chatSlice.actions;
|
} = chatSlice.actions;
|
||||||
|
|
||||||
export default chatSlice.reducer;
|
export default chatSlice.reducer;
|
Loading…
x
Reference in New Issue
Block a user