101 lines
3.4 KiB
Swift
101 lines
3.4 KiB
Swift
//Made by Lumaa
|
|
|
|
import Foundation
|
|
|
|
class FetchTimeline {
|
|
var client: Client?
|
|
public private(set) var datasource: [Status] = []
|
|
public var statusesState: LoadingState = .loading
|
|
|
|
private var timeline: TimelineFilter = .home
|
|
|
|
init(client: Client) {
|
|
self.client = client
|
|
}
|
|
|
|
init() {
|
|
self.client = nil
|
|
}
|
|
|
|
public func fetch(client: Client) async -> [Status] {
|
|
self.client = client
|
|
self.statusesState = .loading
|
|
self.datasource = await fetchNewestStatuses()
|
|
self.statusesState = .loaded
|
|
return self.datasource
|
|
}
|
|
|
|
public func addStatuses(lastStatusIndex: Int) async -> [Status] {
|
|
// print("i: \(lastStatusIndex)\ndatasource-6: \(self.datasource.count - 6)")
|
|
guard client != nil && lastStatusIndex >= self.datasource.count - 6 else { return self.datasource }
|
|
|
|
self.statusesState = .loading
|
|
let lastStatus = self.datasource.last!
|
|
let newStatuses: [Status] = await fetchNewestStatuses(lastStatusId: lastStatus.id)
|
|
self.datasource.append(contentsOf: newStatuses)
|
|
self.statusesState = .loaded
|
|
|
|
print("added posts")
|
|
return self.datasource
|
|
}
|
|
|
|
private func fetchNewestStatuses(lastStatusId: String? = nil, filter: PostFilter? = nil) async -> [Status] {
|
|
guard client != nil else { return [] }
|
|
do {
|
|
var statuses: [Status] = try await client!.get(endpoint: timeline.endpoint(sinceId: nil, maxId: lastStatusId, minId: nil, offset: 0))
|
|
statuses = applyContentFilter(statuses, filter: filter)
|
|
if lastStatusId == nil {
|
|
self.datasource = statuses
|
|
}
|
|
self.statusesState = .loaded
|
|
return statuses
|
|
} catch {
|
|
statusesState = .error(error: error)
|
|
print("timeline parse error: \(error)")
|
|
}
|
|
return []
|
|
}
|
|
|
|
func setTimelineFilter(_ filter: TimelineFilter) {
|
|
self.timeline = filter
|
|
}
|
|
|
|
func useContentFilter(_ filter: PostFilter) async -> [Status] {
|
|
self.datasource = []
|
|
self.statusesState = .loading
|
|
return await self.fetchNewestStatuses(lastStatusId: nil, filter: filter)
|
|
}
|
|
|
|
func applyContentFilter(_ statuses: [Status], filter: PostFilter? = nil) -> [Status] {
|
|
guard let postFilter = filter else { return statuses }
|
|
var filteredStatuses: [Status] = statuses
|
|
let contentFilter: any PostFilter = postFilter
|
|
|
|
for post in statuses {
|
|
let i = statuses.firstIndex(of: post) ?? -1
|
|
|
|
_ = contentFilter.filter(post, type: .censor) { sensitive in
|
|
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
|
|
|
|
print("Edited \(post.account.acct)'s post")
|
|
}
|
|
}
|
|
|
|
return filteredStatuses
|
|
}
|
|
|
|
func getStatuses() -> [Status] {
|
|
return datasource
|
|
}
|
|
|
|
enum LoadingState {
|
|
case loading
|
|
case loaded
|
|
case error(error: Error)
|
|
}
|
|
}
|