Bubble/Threaded/Data/Content/FetchTimeline.swift

128 lines
4.4 KiB
Swift
Raw Normal View History

2023-12-29 11:17:37 +01:00
//Made by Lumaa
import Foundation
2024-06-23 15:44:29 +02:00
class FetchTimeline {
2024-01-06 02:51:07 +01:00
var client: Client?
public private(set) var datasource: [Status] = []
2023-12-29 11:17:37 +01:00
public var statusesState: LoadingState = .loading
private var timeline: TimelineFilter = .home
2024-07-05 21:06:15 +02:00
public private(set) var filtering: Bool = false
public private(set) var lastFilter: PostFilter? = nil
2023-12-29 11:17:37 +01:00
init(client: Client) {
self.client = client
}
2024-01-06 02:51:07 +01:00
init() {
self.client = nil
}
2024-06-23 15:44:29 +02:00
public func fetch(client: Client) async -> [Status] {
2024-01-06 02:51:07 +01:00
self.client = client
2023-12-29 11:17:37 +01:00
self.statusesState = .loading
self.datasource = await fetchNewestStatuses()
2024-01-06 02:51:07 +01:00
self.statusesState = .loaded
return self.datasource
}
2024-06-23 15:44:29 +02:00
public func addStatuses(lastStatusIndex: Int) async -> [Status] {
// print("i: \(lastStatusIndex)\ndatasource-6: \(self.datasource.count - 6)")
2024-01-06 02:51:07 +01:00
guard client != nil && lastStatusIndex >= self.datasource.count - 6 else { return self.datasource }
self.statusesState = .loading
let lastStatus = self.datasource.last!
2024-07-05 21:06:15 +02:00
let newStatuses: [Status] = await fetchNewestStatuses(lastStatusId: lastStatus.id, filter: lastFilter)
2024-01-06 02:51:07 +01:00
self.datasource.append(contentsOf: newStatuses)
self.statusesState = .loaded
print("added posts")
return self.datasource
2023-12-29 11:17:37 +01:00
}
2024-06-25 14:01:34 +02:00
private func fetchNewestStatuses(lastStatusId: String? = nil, filter: PostFilter? = nil) async -> [Status] {
2024-01-06 02:51:07 +01:00
guard client != nil else { return [] }
2023-12-29 11:17:37 +01:00
do {
2024-06-25 14:01:34 +02:00
var statuses: [Status] = try await client!.get(endpoint: timeline.endpoint(sinceId: nil, maxId: lastStatusId, minId: nil, offset: 0))
statuses = applyContentFilter(statuses, filter: filter)
2024-07-05 21:06:15 +02:00
self.lastFilter = filter
2024-01-06 02:51:07 +01:00
if lastStatusId == nil {
self.datasource = statuses
}
2023-12-29 11:17:37 +01:00
self.statusesState = .loaded
return statuses
} catch {
statusesState = .error(error: error)
print("timeline parse error: \(error)")
}
return []
}
2024-06-23 15:44:29 +02:00
func setTimelineFilter(_ filter: TimelineFilter) {
self.timeline = filter
}
2024-06-25 14:01:34 +02:00
func useContentFilter(_ filter: PostFilter) async -> [Status] {
self.datasource = []
self.statusesState = .loading
return await self.fetchNewestStatuses(lastStatusId: nil, filter: filter)
}
2024-07-05 21:06:15 +02:00
private func applyContentFilter(_ statuses: [Status], filter: PostFilter? = nil) -> [Status] {
2024-06-25 14:01:34 +02:00
guard let postFilter = filter else { return statuses }
var filteredStatuses: [Status] = statuses
let contentFilter: any PostFilter = postFilter
2024-07-05 21:06:15 +02:00
let filterType: ContentFilter.FilterType = UserDefaults.standard.bool(forKey: "censorsFilter") ? .censor : .remove
2024-06-25 14:01:34 +02:00
for post in statuses {
let i = statuses.firstIndex(of: post) ?? -1
2024-07-05 21:06:15 +02:00
let isFiltered = contentFilter.filter(post, type: filterType) { sensitive in
2024-06-25 14:01:34 +02:00
post.content.asRawText = post.content.asRawText.replacingOccurrences(of: sensitive, with: "***")
post.content.asMarkdown = post.content.asMarkdown.replacingOccurrences(of: sensitive, with: "***")
post.content.asSafeMarkdownAttributedString = post.content.asSafeMarkdownAttributedString.replacing(sensitive, with: "***")
filteredStatuses[i] = post
2024-07-05 21:06:15 +02:00
print("Censored \(post.account.acct)'s post")
}
if isFiltered && filterType == .remove {
filteredStatuses.remove(at: i)
print("Removed \(post.account.acct)'s post")
2024-06-25 14:01:34 +02:00
}
}
return filteredStatuses
}
2024-07-05 21:06:15 +02:00
func toggleContentFilter(filter: PostFilter) async -> [Status] {
if self.filtering {
self.lastFilter = nil
self.filtering = false
self.datasource = []
self.statusesState = .loading
return await self.fetchNewestStatuses(lastStatusId: nil, filter: nil)
} else {
self.lastFilter = filter
self.filtering = true
return await self.useContentFilter(filter)
}
}
2023-12-29 11:17:37 +01:00
func getStatuses() -> [Status] {
return datasource
}
enum LoadingState {
case loading
case loaded
case error(error: Error)
}
}