mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-29 03:21:02 +00:00
85 lines
3.7 KiB
Swift
85 lines
3.7 KiB
Swift
// Copyright © 2020 Metabolist. All rights reserved.
|
|
|
|
import Foundation
|
|
import GRDB
|
|
import Mastodon
|
|
|
|
struct TimelineItemsInfo: Codable, Hashable, FetchableRecord {
|
|
let timelineRecord: TimelineRecord
|
|
let statusInfos: [StatusInfo]
|
|
let pinnedStatusesInfo: PinnedStatusesInfo?
|
|
let loadMoreRecords: [LoadMoreRecord]
|
|
}
|
|
|
|
extension TimelineItemsInfo {
|
|
struct PinnedStatusesInfo: Codable, Hashable, FetchableRecord {
|
|
let accountRecord: AccountRecord
|
|
let pinnedStatusInfos: [StatusInfo]
|
|
}
|
|
|
|
static func addingIncludes<T: DerivableRequest>( _ request: T,
|
|
ordered: Bool) -> T where T.RowDecoder == TimelineRecord {
|
|
let statusesAssociation = ordered ? TimelineRecord.orderedStatuses : TimelineRecord.statuses
|
|
|
|
return request.including(all: StatusInfo.addingIncludes(statusesAssociation).forKey(CodingKeys.statusInfos))
|
|
.including(all: TimelineRecord.loadMores.forKey(CodingKeys.loadMoreRecords))
|
|
.including(optional: PinnedStatusesInfo.addingIncludes(TimelineRecord.account)
|
|
.forKey(CodingKeys.pinnedStatusesInfo))
|
|
}
|
|
|
|
static func request(_ request: QueryInterfaceRequest<TimelineRecord>,
|
|
ordered: Bool) -> QueryInterfaceRequest<Self> {
|
|
addingIncludes(request, ordered: ordered).asRequest(of: self)
|
|
}
|
|
|
|
func items(filters: [Filter]) -> [CollectionSection] {
|
|
let timeline = Timeline(record: timelineRecord)!
|
|
let filterRegularExpression = filters.regularExpression(context: timeline.filterContext)
|
|
var timelineItems = statusInfos.filtered(regularExpression: filterRegularExpression)
|
|
.map {
|
|
CollectionItem.status(
|
|
.init(info: $0),
|
|
.init(showContentToggled: $0.showContentToggled,
|
|
showAttachmentsToggled: $0.showAttachmentsToggled),
|
|
$0.reblogRelationship ?? $0.relationship)
|
|
}
|
|
|
|
for loadMoreRecord in loadMoreRecords {
|
|
guard let index = timelineItems.firstIndex(where: {
|
|
guard case let .status(status, _, _) = $0 else { return false }
|
|
|
|
return loadMoreRecord.afterStatusId > status.id
|
|
}) else { continue }
|
|
|
|
timelineItems.insert(
|
|
.loadMore(LoadMore(
|
|
timeline: timeline,
|
|
afterStatusId: loadMoreRecord.afterStatusId,
|
|
beforeStatusId: loadMoreRecord.beforeStatusId)),
|
|
at: index)
|
|
}
|
|
|
|
if timelineRecord.profileCollection == .statuses,
|
|
let pinnedStatusInfos = pinnedStatusesInfo?.pinnedStatusInfos {
|
|
return [.init(items: pinnedStatusInfos.filtered(regularExpression: filterRegularExpression)
|
|
.map {
|
|
CollectionItem.status(
|
|
.init(info: $0),
|
|
.init(showContentToggled: $0.showContentToggled,
|
|
showAttachmentsToggled: $0.showAttachmentsToggled,
|
|
isPinned: true),
|
|
$0.reblogRelationship ?? $0.relationship)
|
|
}),
|
|
.init(items: timelineItems)]
|
|
} else {
|
|
return [.init(items: timelineItems)]
|
|
}
|
|
}
|
|
}
|
|
|
|
extension TimelineItemsInfo.PinnedStatusesInfo {
|
|
static func addingIncludes<T: DerivableRequest>(_ request: T) -> T where T.RowDecoder == AccountRecord {
|
|
request.including(all: StatusInfo.addingIncludes(AccountRecord.pinnedStatuses)
|
|
.forKey(CodingKeys.pinnedStatusInfos))
|
|
}
|
|
}
|