@@ -9,6 +9,11 @@ import type { Entry } from '~/types/bindings';
9
9
import { findEntryItem } from '~/utils/entries' ;
10
10
import { useQueryState } from '../../contexts/query-state-context' ;
11
11
12
+ /**
13
+ * How many times are we willing to fetch more pages in order to populate the entry list up to the currently-viewed entry?
14
+ */
15
+ const MAX_FETCHES = 25 ;
16
+
12
17
export const useInfiniteEntries = ( ) => {
13
18
const state = useQueryState ( ) ;
14
19
const viewport = useViewport ( ) ;
@@ -18,10 +23,10 @@ export const useInfiniteEntries = () => {
18
23
queryFn : fetchParams =>
19
24
getEntries ( {
20
25
feed : state . params . feed_uuid ,
21
- view : state . getView ( ) ,
22
- sort : state . getSort ( ) ,
23
26
folder : state . params . folder_slug ,
24
27
cursor : fetchParams . pageParam as undefined | string ,
28
+ view : state . getView ( ) ,
29
+ sort : state . getSort ( ) ,
25
30
} ) ,
26
31
getNextPageParam : last => last . next_cursor ,
27
32
initialPageParam : undefined ,
@@ -31,37 +36,39 @@ export const useInfiniteEntries = () => {
31
36
32
37
const allEntries = ( ) => query . data ?. pages . flatMap ( page => page . data ) || [ ] ;
33
38
34
- const fetchMore = leading (
35
- debounce ,
36
- ( ) => {
37
- // Only fetch more if we have more to fetch and we're not already fetching
38
- if ( ! query . hasNextPage || query . isFetchingNextPage ) return ;
39
+ const canFetchMore = ( ) => query . hasNextPage && ! query . isFetchingNextPage ;
39
40
40
- query . fetchNextPage ( ) ;
41
- } ,
42
- 100 ,
43
- ) ;
41
+ // Only fetch more if we have more to fetch and we're not already fetching
42
+ const fetchMore = leading ( debounce , ( ) => canFetchMore ( ) && query . fetchNextPage ( ) , 100 ) ;
43
+
44
+ const getNextCursor = ( ) => query . data ?. pages [ query . data ?. pages . length - 1 ] . next_cursor ;
44
45
45
46
const [ init , setInit ] = createSignal ( false ) ;
47
+ const [ fetches , setFetches ] = createSignal ( 0 ) ;
48
+ const [ lastCursor , setLastCursor ] = createSignal ( getNextCursor ( ) ) ;
46
49
47
50
// All the entries up until the current entry (and maybe fetch more on mobile)
48
51
createEffect ( ( ) => {
49
- if ( init ( ) || ! state . params . entry_uuid || ! query . hasNextPage ) return ;
52
+ if ( init ( ) || ! state . params . entry_uuid || getNextCursor ( ) === lastCursor ( ) || ! canFetchMore ( ) ) return ;
53
+
54
+ setTimeout ( ( ) => {
55
+ const activeItem = findEntryItem ( state . params . entry_uuid ) ;
56
+ if ( activeItem ) activeItem . scrollIntoView ( { behavior : 'smooth' , block : 'center' } ) ;
57
+ } , 500 ) ;
50
58
51
59
const uuids = allEntries ( ) . map ( entry => entry . uuid ) ;
52
60
53
61
const entryIsLoaded = uuids . includes ( state . params . entry_uuid ) ;
54
62
const viewingLastMobile = viewport . lte ( 'md' ) ? uuids [ uuids . length - 1 ] === state . params . entry_uuid : false ;
55
63
56
64
// If the entry is not listed or if we're viewing the last item on mobile, fetch more entries
57
- if ( ! entryIsLoaded || viewingLastMobile ) {
65
+ if ( ( ! entryIsLoaded && fetches ( ) < MAX_FETCHES ) || viewingLastMobile ) {
58
66
query . fetchNextPage ( ) ;
67
+ setFetches ( val => val + 1 ) ;
68
+ setLastCursor ( getNextCursor ( ) ) ;
59
69
return ;
60
70
}
61
71
62
- const activeItem = findEntryItem ( state . params . entry_uuid ) ;
63
- if ( activeItem ) activeItem . focus ( ) ;
64
-
65
72
setInit ( true ) ;
66
73
} ) ;
67
74
0 commit comments