feat: more stable switching timeline back to top

This commit is contained in:
DIYgod 2025-09-11 21:46:54 +08:00
parent 8db85827d9
commit 418d99aae9
No known key found for this signature in database
3 changed files with 30 additions and 32 deletions

View File

@ -13,10 +13,11 @@ import type { UseEntriesReturn } from "@follow/store/entry/types"
import { fallbackReturn } from "@follow/store/entry/utils"
import { useFolderFeedsByFeedId } from "@follow/store/subscription/hooks"
import { unreadSyncService } from "@follow/store/unread/store"
import { nextFrame } from "@follow/utils"
import { isBizId } from "@follow/utils/utils"
import { useMutation } from "@tanstack/react-query"
import { debounce } from "es-toolkit/compat"
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { useCallback, useEffect, useMemo, useState } from "react"
import { useGeneralSettingKey } from "~/atoms/settings/general"
import { ROUTE_FEED_PENDING } from "~/constants/app"
@ -119,6 +120,7 @@ const useRemoteEntries = (): UseEntriesReturn => {
hasNextPage: query.hasNextPage,
error: query.isError ? query.error : null,
fetchedTime,
queryKey: query.queryKey,
}
}
@ -237,7 +239,7 @@ const useLocalEntries = (): UseEntriesReturn => {
}
export const useEntriesByView = ({ onReset }: { onReset?: () => void }) => {
const { feedId, view, listId } = useRouteParams()
const { view, listId } = useRouteParams()
const remoteQuery = useRemoteEntries()
const localQuery = useLocalEntries()
@ -254,35 +256,15 @@ export const useEntriesByView = ({ onReset }: { onReset?: () => void }) => {
const query = remoteQuery.isReady ? remoteQuery : localQuery
const entryIds: string[] = query.entriesIds
// in unread only entries only can grow the data, but not shrink
// so we memo this previous data to avoid the flicker
const prevEntryIdsRef = useRef(entryIds)
const isFetchingFirstPage = query.isFetching && !query.isFetchingNextPage
const isFetchingFirstPage = remoteQuery.isFetching && !remoteQuery.isFetchingNextPage
useEffect(() => {
if (!isFetchingFirstPage) {
prevEntryIdsRef.current = entryIds
onReset?.()
if (isFetchingFirstPage) {
nextFrame(() => {
onReset?.()
})
}
}, [isFetchingFirstPage])
const entryIdsAsDeps = entryIds.toString()
useEffect(() => {
prevEntryIdsRef.current = []
}, [feedId])
useEffect(() => {
if (!prevEntryIdsRef.current) {
prevEntryIdsRef.current = entryIds
return
}
// merge the new entries with the old entries, and unique them
const nextIds = [...new Set([...prevEntryIdsRef.current, ...entryIds])]
prevEntryIdsRef.current = nextIds
}, [entryIdsAsDeps])
}, [isFetchingFirstPage, query.queryKey])
const groupByDate = useGeneralSettingKey("groupByDate")
const groupedCounts: number[] | undefined = useMemo(() => {

View File

@ -70,9 +70,8 @@ export const useEntriesQuery = (
const isPop =
"history" in globalThis && "isPop" in globalThis.history && !!globalThis.history.isPop
const query = useInfiniteQuery({
queryKey: [
const queryKey = useMemo(
() => [
"entries",
feedId,
inboxId,
@ -84,6 +83,21 @@ export const useEntriesQuery = (
unreadOnly,
hidePrivateSubscriptionsInTimeline,
],
[
feedId,
inboxId,
listId,
view,
limit,
feedIdList,
isCollection,
unreadOnly,
hidePrivateSubscriptionsInTimeline,
],
)
const query = useInfiniteQuery({
queryKey,
queryFn: ({ pageParam }) =>
entrySyncServices.fetchEntries({
...props,
@ -124,8 +138,9 @@ export const useEntriesQuery = (
return {
...query,
entriesIds,
queryKey,
}
}, [entriesIds, query])
}, [entriesIds, query, queryKey])
}
export const usePrefetchEntryDetail = (entryId: string | undefined, isInbox?: boolean) => {

View File

@ -39,6 +39,7 @@ export type UseEntriesReturn = {
hasNextPage: boolean
error: Error | null
fetchedTime?: number
queryKey?: (string | number | boolean | string[] | undefined)[]
}
export type UseEntriesControl = Pick<