@@ -66,6 +66,15 @@ import SwiftUI
6666 @ObservationIgnored
6767 private let cache = TimelineCache ( )
6868
69+ private enum Constants {
70+ static let fullTimelineFetchLimit = 800
71+ static let fullTimelineFetchMaxPages = fullTimelineFetchLimit / 40
72+ }
73+
74+ private var isFullTimelineFetchEnabled : Bool {
75+ UserPreferences . shared. fullTimelineFetch
76+ }
77+
6978 private var isCacheEnabled : Bool {
7079 canFilterTimeline && timeline. supportNewestPagination && client? . isAuth == true
7180 }
@@ -296,20 +305,58 @@ extension TimelineViewModel: GapLoadingFetcher {
296305 return
297306 }
298307
308+ var statusesToInsert = actuallyNewStatuses
309+
310+ if isFullTimelineFetchEnabled, statusesToInsert. count < Constants . fullTimelineFetchLimit {
311+ let additionalStatuses : [ Status ] = try await statusFetcher. fetchNewPages (
312+ client: client,
313+ timeline: timeline,
314+ minId: latestStatus,
315+ maxPages: Constants . fullTimelineFetchMaxPages)
316+
317+ if !additionalStatuses. isEmpty {
318+ var knownIds = Set ( currentIds)
319+ knownIds. formUnion ( statusesToInsert. map ( \. id) )
320+
321+ let filteredAdditional = additionalStatuses. filter { status in
322+ guard status. id > latestStatus else { return false }
323+ if knownIds. contains ( status. id) {
324+ return false
325+ }
326+ knownIds. insert ( status. id)
327+ return true
328+ }
329+
330+ if !filteredAdditional. isEmpty {
331+ let remainingCapacity = max ( 0 , Constants . fullTimelineFetchLimit - statusesToInsert. count)
332+ if remainingCapacity > 0 {
333+ statusesToInsert. append ( contentsOf: filteredAdditional. prefix ( remainingCapacity) )
334+ }
335+ }
336+ }
337+ }
338+
339+ statusesToInsert. sort { $0. id > $1. id }
340+
341+ if statusesToInsert. count > Constants . fullTimelineFetchLimit {
342+ statusesToInsert = Array ( statusesToInsert. prefix ( Constants . fullTimelineFetchLimit) )
343+ }
344+
299345 StatusDataControllerProvider . shared. updateDataControllers (
300- for: actuallyNewStatuses , client: client)
346+ for: statusesToInsert , client: client)
301347
302348 // Pass the original count to determine if we need a gap
303349 await updateTimelineWithNewStatuses (
304- actuallyNewStatuses ,
350+ statusesToInsert ,
305351 latestStatus: latestStatus,
306- fetchedCount: newestStatuses. count
352+ fetchedCount: newestStatuses. count,
353+ shouldCreateGap: !isFullTimelineFetchEnabled
307354 )
308355 canStreamEvents = true
309356 }
310357
311358 private func updateTimelineWithNewStatuses(
312- _ newStatuses: [ Status ] , latestStatus: String , fetchedCount: Int
359+ _ newStatuses: [ Status ] , latestStatus: String , fetchedCount: Int , shouldCreateGap : Bool
313360 ) async {
314361 let topStatus = await datasource. getFiltered ( ) . first
315362
@@ -319,7 +366,11 @@ extension TimelineViewModel: GapLoadingFetcher {
319366 // Only create a gap if:
320367 // 1. We fetched a full page (suggesting there might be more)
321368 // 2. AND we have a significant number of actually new statuses
322- if fetchedCount >= 40 && newStatuses. count >= 40 , let oldestNewStatus = newStatuses. last {
369+ if shouldCreateGap,
370+ fetchedCount >= 40 ,
371+ newStatuses. count >= 40 ,
372+ let oldestNewStatus = newStatuses. last
373+ {
323374 // Create a gap to load statuses between the oldest new status and our previous top
324375 let gap = TimelineGap ( sinceId: latestStatus, maxId: oldestNewStatus. id)
325376 // Insert the gap after all the new statuses
@@ -471,6 +522,7 @@ extension TimelineViewModel: GapLoadingFetcher {
471522
472523 private func createGapForOlderStatuses( sinceId: String ? = nil , maxId: String , at index: Int ) async
473524 {
525+ guard !isFullTimelineFetchEnabled else { return }
474526 let gap = TimelineGap ( sinceId: sinceId, maxId: maxId)
475527 await datasource. insertGap ( gap, at: index)
476528 }
0 commit comments