@@ -2,46 +2,72 @@ import { getView } from "@follow/constants"
22import { entryActions } from "@follow/store/entry/store"
33import { unreadSyncService } from "@follow/store/unread/store"
44import type { Range } from "@tanstack/react-virtual"
5- import { useMemo } from "react"
5+ import { useEffect , useMemo , useRef } from "react"
66import { useEventCallback } from "usehooks-ts"
77
88import { useGeneralSettingKey } from "~/atoms/settings/general"
99import { useRouteParamsSelector } from "~/hooks/biz/useRouteParams"
1010
11- export const useEntryMarkReadHandler = ( entriesIds : string [ ] ) => {
11+ type EntryMarkReadHandler = ( range : Range , enabled ?: boolean ) => void
12+
13+ export const useEntryMarkReadHandler = (
14+ entriesIds : string [ ] ,
15+ { pauseScrollMarkRead = false } : { pauseScrollMarkRead ?: boolean } = { } ,
16+ ) => {
1217 const renderAsRead = useGeneralSettingKey ( "renderMarkUnread" )
1318 const scrollMarkUnread = useGeneralSettingKey ( "scrollMarkUnread" )
1419 const feedView = useRouteParamsSelector ( ( params ) => params . view )
1520
16- const processedEntryIds = useMemo ( ( ) => new Set < string > ( ) , [ entriesIds ] )
21+ const processedEntryIds = useRef ( new Set < string > ( ) )
22+
23+ useEffect ( ( ) => {
24+ processedEntryIds . current . clear ( )
25+ } , [ entriesIds ] )
1726
18- const handleRenderAsRead = useEventCallback (
27+ const handleRangeMarkRead = useEventCallback (
1928 ( { startIndex, endIndex } : Range , enabled ?: boolean ) => {
2029 if ( ! enabled ) return
2130 const idSlice = entriesIds ?. slice ( startIndex , endIndex )
2231 if ( ! idSlice ) return
2332
2433 // Filter out entries that have already been processed
25- const newEntries = idSlice . filter ( ( id ) => ! processedEntryIds . has ( id ) )
34+ const newEntries = idSlice . filter ( ( id ) => ! processedEntryIds . current . has ( id ) )
2635 if ( newEntries . length === 0 ) return
2736
2837 // Mark these entries as processed to avoid duplicate processing
29- newEntries . forEach ( ( id ) => processedEntryIds . add ( id ) )
38+ newEntries . forEach ( ( id ) => processedEntryIds . current . add ( id ) )
3039
3140 batchMarkRead ( newEntries )
3241 } ,
3342 )
3443
35- return useMemo ( ( ) => {
36- if ( getView ( feedView ) ?. wideMode && renderAsRead ) {
37- return handleRenderAsRead
44+ const handleScrollMarkRead = useEventCallback ( ( range : Range , enabled ?: boolean ) => {
45+ if ( pauseScrollMarkRead ) return
46+ handleRangeMarkRead ( range , enabled )
47+ } )
48+
49+ const renderMarkReadHandler = useMemo < EntryMarkReadHandler | undefined > ( ( ) => {
50+ if ( ! getView ( feedView ) ?. wideMode || ! renderAsRead ) {
51+ return
3852 }
3953
40- if ( scrollMarkUnread ) {
41- return handleRenderAsRead
54+ return handleRangeMarkRead
55+ } , [ feedView , handleRangeMarkRead , renderAsRead ] )
56+
57+ const scrollMarkReadHandler = useMemo < EntryMarkReadHandler | undefined > ( ( ) => {
58+ if ( ! scrollMarkUnread ) {
59+ return
60+ }
61+
62+ return handleScrollMarkRead
63+ } , [ handleScrollMarkRead , scrollMarkUnread ] )
64+
65+ return useMemo ( ( ) => {
66+ return {
67+ handleRenderMarkRead : renderMarkReadHandler ,
68+ handleScrollMarkRead : scrollMarkReadHandler ,
4269 }
43- return
44- } , [ feedView , handleRenderAsRead , renderAsRead , scrollMarkUnread ] )
70+ } , [ renderMarkReadHandler , scrollMarkReadHandler ] )
4571}
4672
4773export function batchMarkRead ( ids : string [ ] ) {
0 commit comments