diff --git a/web/app/(commonLayout)/apps/Apps.tsx b/web/app/(commonLayout)/apps/Apps.tsx index ee9d13536a..37bfaa8b78 100644 --- a/web/app/(commonLayout)/apps/Apps.tsx +++ b/web/app/(commonLayout)/apps/Apps.tsx @@ -1,15 +1,14 @@ 'use client' -import { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { useRouter, useSearchParams } from 'next/navigation' import useSWRInfinite from 'swr/infinite' -import { debounce } from 'lodash-es' import { useTranslation } from 'react-i18next' import AppCard from './AppCard' import NewAppCard from './NewAppCard' import type { AppListResponse } from '@/models/app' import { fetchAppList } from '@/service/apps' -import { useAppContext, useSelector } from '@/context/app-context' +import { useAppContext } from '@/context/app-context' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { ProviderEnum } from '@/app/components/header/account-setting/model-page/declarations' import Confirm from '@/app/components/base/confirm/common' @@ -24,15 +23,18 @@ const Apps = () => { const { t } = useTranslation() const { isCurrentWorkspaceManager } = useAppContext() const { data, isLoading, setSize, mutate } = useSWRInfinite(getKey, fetchAppList, { revalidateFirstPage: false }) - const loadingStateRef = useRef(false) - const pageContainerRef = useSelector(state => state.pageContainerRef) - const anchorRef = useRef(null) + const anchorRef = useRef(null) const searchParams = useSearchParams() const router = useRouter() const payProviderName = searchParams.get('provider_name') const payStatus = searchParams.get('payment_result') const [showPayStatusModal, setShowPayStatusModal] = useState(false) + const handleCancelShowPayStatusModal = useCallback(() => { + setShowPayStatusModal(false) + router.replace('/', { forceOptimisticNavigation: false }) + }, [router]) + useEffect(() => { document.title = `${t('app.title')} - Dify` if (localStorage.getItem(NEED_REFRESH_APP_LIST_KEY) === '1') { @@ -41,35 +43,24 @@ const Apps = () => { } if (payProviderName === ProviderEnum.anthropic && (payStatus === 'succeeded' || payStatus === 'cancelled')) setShowPayStatusModal(true) - }, []) + }, [mutate, payProviderName, payStatus, t]) useEffect(() => { - loadingStateRef.current = isLoading - }, [isLoading]) - - useEffect(() => { - const onScroll = debounce(() => { - if (!loadingStateRef.current) { - const { scrollTop, clientHeight } = pageContainerRef.current! - const anchorOffset = anchorRef.current!.offsetTop - if (anchorOffset - scrollTop - clientHeight < 100) + let observer: IntersectionObserver | undefined + if (anchorRef.current) { + observer = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting) setSize(size => size + 1) - } - }, 50) - - pageContainerRef.current?.addEventListener('scroll', onScroll) - return () => pageContainerRef.current?.removeEventListener('scroll', onScroll) - }, []) - - const handleCancelShowPayStatusModal = () => { - setShowPayStatusModal(false) - router.replace('/', { forceOptimisticNavigation: false }) - } + }, { rootMargin: '100px' }) + observer.observe(anchorRef.current) + } + return () => observer?.disconnect() + }, [isLoading, setSize, anchorRef, mutate]) return ( -