feat: implement scroll handling with new custom hook
- Added a new hook, useAttachScrollBeyond, to manage scroll behavior and state across components. - Updated ChatInterface and WelcomeScreen to utilize the new hook for handling scroll events, improving the user experience by ensuring consistent scroll threshold management. - Refactored AIChatRoot to maintain clean code structure. These changes enhance the chat interface by providing a centralized way to manage scroll interactions, improving overall usability. Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
parent
2a2085a0f1
commit
3776d82d97
|
|
@ -36,6 +36,7 @@ const AIChatRootInner: FC<AIChatRootProps> = ({ children, chatId: externalChatId
|
|||
const inputRef = useRef<HTMLTextAreaElement>(null!)
|
||||
const refsContext = useMemo<AIPanelRefs>(() => ({ panelRef, inputRef }), [panelRef, inputRef])
|
||||
useAIShortcut()
|
||||
|
||||
if (!currentChatId) {
|
||||
return (
|
||||
<div className="bg-background flex size-full items-center justify-center">
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@ import { tracker } from "@follow/tracker"
|
|||
import { clsx, cn, nextFrame } from "@follow/utils"
|
||||
import type { BizUIMessage } from "@folo-services/ai-tools"
|
||||
import { ErrorBoundary } from "@sentry/react"
|
||||
import { useSetAtom } from "jotai"
|
||||
import type { EditorState, LexicalEditor } from "lexical"
|
||||
import { AnimatePresence } from "motion/react"
|
||||
import { nanoid } from "nanoid"
|
||||
import type { FC, Ref } from "react"
|
||||
import { Suspense, useCallback, useEffect, useRef, useState } from "react"
|
||||
import { Suspense, useEffect, useRef, useState } from "react"
|
||||
import { useEventCallback } from "usehooks-ts"
|
||||
|
||||
import { useAISettingKey } from "~/atoms/settings/ai"
|
||||
|
|
@ -32,8 +31,7 @@ import {
|
|||
useMessages,
|
||||
} from "~/modules/ai-chat/store/hooks"
|
||||
|
||||
import { SCROLLED_BEYOND_THRESHOLD } from "../../constants"
|
||||
import { useAIRootState } from "../../store/AIChatContext"
|
||||
import { useAttachScrollBeyond } from "../../hooks/useAttachScrollBeyond"
|
||||
import type { AIChatContextBlock } from "../../store/types"
|
||||
import { convertLexicalToMarkdown } from "../../utils/lexical-markdown"
|
||||
import { GlobalFileDropZone } from "../file/GlobalFileDropZone"
|
||||
|
|
@ -228,15 +226,7 @@ const ChatInterfaceContent = ({ centerInputOnEmpty }: ChatInterfaceProps) => {
|
|||
|
||||
const shouldShowScrollToBottom = hasMessages && !isAtBottom && !isLoadingHistory
|
||||
|
||||
const { isScrolledBeyondThreshold } = useAIRootState()
|
||||
const setIsScrolledBeyondThreshold = useSetAtom(isScrolledBeyondThreshold)
|
||||
const handleScroll = useCallback(
|
||||
(event: React.UIEvent<HTMLDivElement>) => {
|
||||
const { scrollTop } = event.currentTarget
|
||||
setIsScrolledBeyondThreshold(scrollTop > SCROLLED_BEYOND_THRESHOLD)
|
||||
},
|
||||
[setIsScrolledBeyondThreshold],
|
||||
)
|
||||
const { handleScroll } = useAttachScrollBeyond()
|
||||
return (
|
||||
<GlobalFileDropZone className="@container flex size-full flex-col">
|
||||
<div className="flex min-h-0 flex-1 flex-col" ref={scrollContainerParentRef}>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
import { Folo } from "@follow/components/icons/folo.js"
|
||||
import { ScrollArea } from "@follow/components/ui/scroll-area/ScrollArea.js"
|
||||
import { clsx } from "@follow/utils"
|
||||
import { useSetAtom } from "jotai"
|
||||
import type { EditorState, LexicalEditor } from "lexical"
|
||||
import { AnimatePresence, m } from "motion/react"
|
||||
import { useCallback } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { useAISettingValue } from "~/atoms/settings/ai"
|
||||
import { AISpline } from "~/modules/ai-chat/components/3d-models/AISpline"
|
||||
|
||||
import { SCROLLED_BEYOND_THRESHOLD } from "../../constants"
|
||||
import { useAttachScrollBeyond } from "../../hooks/useAttachScrollBeyond"
|
||||
import { useMainEntryId } from "../../hooks/useMainEntryId"
|
||||
import { useAIRootState } from "../../store/AIChatContext"
|
||||
import { DefaultWelcomeContent, EntrySummaryCard } from "../welcome"
|
||||
|
||||
interface WelcomeScreenProps {
|
||||
|
|
@ -28,15 +25,7 @@ export const WelcomeScreen = ({ onSend, centerInputOnEmpty }: WelcomeScreenProps
|
|||
const hasEntryContext = !!mainEntryId
|
||||
const enabledShortcuts = aiSettings.shortcuts?.filter((shortcut) => shortcut.enabled) || []
|
||||
|
||||
const { isScrolledBeyondThreshold } = useAIRootState()
|
||||
const setIsScrolledBeyondThreshold = useSetAtom(isScrolledBeyondThreshold)
|
||||
const handleScroll = useCallback(
|
||||
(event: React.UIEvent<HTMLDivElement>) => {
|
||||
const { scrollTop } = event.currentTarget
|
||||
setIsScrolledBeyondThreshold(scrollTop > SCROLLED_BEYOND_THRESHOLD)
|
||||
},
|
||||
[setIsScrolledBeyondThreshold],
|
||||
)
|
||||
const { handleScroll } = useAttachScrollBeyond()
|
||||
return (
|
||||
<ScrollArea
|
||||
rootClassName="flex min-h-0 flex-1"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
import { useSetAtom } from "jotai"
|
||||
import { useCallback, useEffect } from "react"
|
||||
|
||||
import { SCROLLED_BEYOND_THRESHOLD } from "../constants"
|
||||
import { useAIRootState } from "../store/AIChatContext"
|
||||
import { useCurrentChatId } from "../store/hooks"
|
||||
|
||||
export const useAttachScrollBeyond = () => {
|
||||
const { isScrolledBeyondThreshold } = useAIRootState()
|
||||
const setIsScrolledBeyondThreshold = useSetAtom(isScrolledBeyondThreshold)
|
||||
const handleScroll = useCallback(
|
||||
(event: React.UIEvent<HTMLDivElement>) => {
|
||||
const { scrollTop } = event.currentTarget
|
||||
setIsScrolledBeyondThreshold(scrollTop > SCROLLED_BEYOND_THRESHOLD)
|
||||
},
|
||||
[setIsScrolledBeyondThreshold],
|
||||
)
|
||||
const currentChatId = useCurrentChatId()
|
||||
useEffect(() => {
|
||||
if (currentChatId) {
|
||||
setIsScrolledBeyondThreshold(false)
|
||||
}
|
||||
}, [currentChatId, setIsScrolledBeyondThreshold])
|
||||
return { handleScroll }
|
||||
}
|
||||
Loading…
Reference in New Issue