import React, { useState, useEffect, useRef, useCallback } from 'react'; import _ from 'lodash'; import NewChat from './NewChat'; import Spinner from '../svg/Spinner'; import Pages from '../Conversations/Pages'; import Conversations from '../Conversations'; import NavLinks from './NavLinks'; import { searchFetcher, swr } from '~/utils/fetchers'; import { useDispatch, useSelector } from 'react-redux'; import { setConvos, setNewConvo, refreshConversation } from '~/store/convoSlice'; import { setMessages } from '~/store/messageSlice'; import { setDisabled } from '~/store/submitSlice'; export default function Nav({ navVisible, setNavVisible }) { const dispatch = useDispatch(); const [isHovering, setIsHovering] = useState(false); const [isFetching, setIsFetching] = useState(false); const [pages, setPages] = useState(1); const [pageNumber, setPage] = useState(1); const { search, query } = useSelector((state) => state.search); const { conversationId, convos, refreshConvoHint } = useSelector((state) => state.convo); const onSuccess = (data, searchFetch = false) => { if (search) { return; } const { conversations, pages } = data; if (pageNumber > pages) { setPage(pages); } else { dispatch(setConvos({ convos: conversations, searchFetch })); setPages(pages); } }; const onSearchSuccess = (data, expectedPage) => { const res = data; dispatch(setConvos({ convos: res.conversations, searchFetch: true })); if (expectedPage) { setPage(expectedPage); } setPage(res.pageNumber); setPages(res.pages); setIsFetching(false); if (res.messages?.length > 0) { dispatch(setMessages(res.messages)); dispatch(setDisabled(true)); } }; const fetch = useCallback(_.partialRight(searchFetcher.bind(null, () => setIsFetching(true)), onSearchSuccess), [dispatch]); const clearSearch = () => { setPage(1); dispatch(refreshConversation()); if (!conversationId) { dispatch(setNewConvo()); dispatch(setMessages([])); } dispatch(setDisabled(false)); }; const { data, isLoading, mutate } = swr(`/api/convos?pageNumber=${pageNumber}`, onSuccess, { revalidateOnMount: false, }); const containerRef = useRef(null); const scrollPositionRef = useRef(null); const moveToTop = () => { const container = containerRef.current; if (container) { scrollPositionRef.current = container.scrollTop; } }; const nextPage = async () => { moveToTop(); if (!search) { setPage((prev) => prev + 1); await mutate(); } else { await fetch(query, +pageNumber + 1); } }; const previousPage = async () => { moveToTop(); if (!search) { setPage((prev) => prev - 1); await mutate(); } else { await fetch(query, +pageNumber - 1); } }; useEffect(() => { if (!search) { mutate(); } }, [pageNumber, conversationId, refreshConvoHint]); useEffect(() => { const container = containerRef.current; if (container && scrollPositionRef.current !== null) { const { scrollHeight, clientHeight } = container; const maxScrollTop = scrollHeight - clientHeight; container.scrollTop = Math.min(maxScrollTop, scrollPositionRef.current); } }, [data]); useEffect(() => { setNavVisible(false); }, [conversationId]); const toggleNavVisible = () => { setNavVisible((prev) => { return !prev; }); }; const containerClasses = isLoading && pageNumber === 1 ? 'flex flex-col gap-2 text-gray-100 text-sm h-full justify-center items-center' : 'flex flex-col gap-2 text-gray-100 text-sm'; return ( <>