diff --git a/Packages/Explore/Sources/Explore/ExploreViewModel.swift b/Packages/Explore/Sources/Explore/ExploreViewModel.swift index 774587c6..49227cdb 100644 --- a/Packages/Explore/Sources/Explore/ExploreViewModel.swift +++ b/Packages/Explore/Sources/Explore/ExploreViewModel.swift @@ -69,7 +69,7 @@ class ExploreViewModel: ObservableObject { do { async let suggestedAccounts: [Account] = client.get(endpoint: Accounts.suggestions) async let trendingTags: [Tag] = client.get(endpoint: Trends.tags) - async let trendingStatuses: [Status] = client.get(endpoint: Trends.statuses) + async let trendingStatuses: [Status] = client.get(endpoint: Trends.statuses(offset: nil)) async let trendingLinks: [Card] = client.get(endpoint: Trends.links) self.suggestedAccounts = try await suggestedAccounts diff --git a/Packages/Network/Sources/Network/Endpoint/Trends.swift b/Packages/Network/Sources/Network/Endpoint/Trends.swift index 270f32e8..16bb3933 100644 --- a/Packages/Network/Sources/Network/Endpoint/Trends.swift +++ b/Packages/Network/Sources/Network/Endpoint/Trends.swift @@ -2,7 +2,7 @@ import Foundation public enum Trends: Endpoint { case tags - case statuses + case statuses(offset: Int?) case links public func path() -> String { @@ -18,6 +18,11 @@ public enum Trends: Endpoint { public func queryItems() -> [URLQueryItem]? { switch self { + case let .statuses(offset): + if let offset { + return [.init(name: "offset", value: String(offset))] + } + return nil default: return nil } diff --git a/Packages/Timeline/Sources/Timeline/TimelineFilter.swift b/Packages/Timeline/Sources/Timeline/TimelineFilter.swift index 3d0c4ef9..75ba48b8 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineFilter.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineFilter.swift @@ -3,7 +3,7 @@ import Models import Network public enum TimelineFilter: Hashable, Equatable { - case pub, local, home + case pub, local, home, trending case hashtag(tag: String, accountId: String?) public func hash(into hasher: inout Hasher) { @@ -12,9 +12,9 @@ public enum TimelineFilter: Hashable, Equatable { public static func availableTimeline(client: Client) -> [TimelineFilter] { if !client.isAuth { - return [.pub, .local] + return [.pub, .local, .trending] } - return [.pub, .local, .home] + return [.pub, .local, .trending, .home] } public func title() -> String { @@ -23,6 +23,8 @@ public enum TimelineFilter: Hashable, Equatable { return "Federated" case .local: return "Local" + case .trending: + return "Trending" case .home: return "Home" case let .hashtag(tag, _): @@ -36,6 +38,8 @@ public enum TimelineFilter: Hashable, Equatable { return "globe.americas" case .local: return "person.3" + case .trending: + return "chart.line.uptrend.xyaxis" case .home: return "house" default: @@ -43,11 +47,12 @@ public enum TimelineFilter: Hashable, Equatable { } } - public func endpoint(sinceId: String?, maxId: String?, minId: String?) -> Endpoint { + public func endpoint(sinceId: String?, maxId: String?, minId: String?, offset: Int?) -> Endpoint { switch self { case .pub: return Timelines.pub(sinceId: sinceId, maxId: maxId, minId: minId, local: false) case .local: return Timelines.pub(sinceId: sinceId, maxId: maxId, minId: minId, local: true) case .home: return Timelines.home(sinceId: sinceId, maxId: maxId, minId: minId) + case .trending: return Trends.statuses(offset: offset) case let .hashtag(tag, accountId): if let accountId { return Accounts.statuses(id: accountId, sinceId: nil, tag: tag, onlyMedia: nil, excludeReplies: nil) diff --git a/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift b/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift index 2552da53..da1ba6ed 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift @@ -71,7 +71,10 @@ class TimelineViewModel: ObservableObject, StatusesFetcher { if statuses.isEmpty { pendingStatuses = [] statusesState = .loading - statuses = try await client.get(endpoint: timeline.endpoint(sinceId: nil, maxId: nil, minId: nil)) + statuses = try await client.get(endpoint: timeline.endpoint(sinceId: nil, + maxId: nil, + minId: nil, + offset: statuses.count)) statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage) } else if let first = statuses.first { var newStatuses: [Status] = await fetchNewPages(minId: first.id, maxPages: 10) @@ -103,7 +106,8 @@ class TimelineViewModel: ObservableObject, StatusesFetcher { do { while let newStatuses: [Status] = try await client.get(endpoint: timeline.endpoint(sinceId: nil, maxId: nil, - minId: latestMinId)), + minId: latestMinId, + offset: statuses.count)), !newStatuses.isEmpty, pagesLoaded < maxPages { pagesLoaded += 1 @@ -123,7 +127,8 @@ class TimelineViewModel: ObservableObject, StatusesFetcher { statusesState = .display(statuses: statuses, nextPageState: .loadingNextPage) let newStatuses: [Status] = try await client.get(endpoint: timeline.endpoint(sinceId: nil, maxId: lastId, - minId: nil)) + minId: nil, + offset: statuses.count)) statuses.append(contentsOf: newStatuses) statusesState = .display(statuses: statuses, nextPageState: .hasNextPage) } catch {