From 7435d02f6e2b2c26992fbcc4f50aa4c2a542d72a Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 1 Apr 2024 19:22:55 -0400 Subject: [PATCH] Fiddle with how the timeline markers API is organized --- .../Pachyderm/Model/TimelineMarkers.swift | 93 ++++++++++++++----- .../Timeline/TimelineViewController.swift | 11 +-- 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/Packages/Pachyderm/Sources/Pachyderm/Model/TimelineMarkers.swift b/Packages/Pachyderm/Sources/Pachyderm/Model/TimelineMarkers.swift index 010a8727..046f2601 100644 --- a/Packages/Pachyderm/Sources/Pachyderm/Model/TimelineMarkers.swift +++ b/Packages/Pachyderm/Sources/Pachyderm/Model/TimelineMarkers.swift @@ -7,34 +7,83 @@ import Foundation -public struct TimelineMarkers: Decodable, Sendable { - public let home: Marker? - public let notifications: Marker? +public struct TimelineMarkers { + private init() {} - public static func request(timelines: [Timeline]) -> Request { - return Request(method: .get, path: "/api/v1/markers", queryParameters: "timeline[]" => timelines.map(\.rawValue)) + public static func request(timeline: T) -> Request> { + Request(method: .get, path: "/api/v1/markers", queryParameters: ["timeline[]" => T.name]) } - public static func update(timeline: Timeline, lastReadID: String) -> Request { - return Request(method: .post, path: "/api/v1/markers", body: ParametersBody([ - "\(timeline.rawValue)[last_read_id]" => lastReadID, + public static func update(timeline: T, lastReadID: String) -> Request { + Request(method: .post, path: "/api/v1/markers", body: ParametersBody([ + "\(T.name)[last_read_id]" => lastReadID ])) } +} + +public struct TimelineMarker: Decodable, Sendable { + let payload: Payload - public enum Timeline: String { - case home - case notifications + public var lastReadID: String { + payload.payload.lastReadID } - - public struct Marker: Decodable, Sendable { - public let lastReadID: String - public let version: Int - public let updatedAt: Date - - enum CodingKeys: String, CodingKey { - case lastReadID = "last_read_id" - case version - case updatedAt = "updated_at" - } + public var version: Int { + payload.payload.version + } + public var updatedAt: Date { + payload.payload.updatedAt + } + + public init(from decoder: any Decoder) throws { + self.payload = try Payload(from: decoder) } } + +public protocol TimelineMarkerTypePayload: Decodable, Sendable { + var payload: MarkerPayload { get } +} + +public struct HomeMarkerPayload: TimelineMarkerTypePayload { + public var home: MarkerPayload + public var payload: MarkerPayload { home } +} + +public struct NotificationsMarkerPayload: TimelineMarkerTypePayload { + public var notifications: MarkerPayload + public var payload: MarkerPayload { notifications } +} + +public struct MarkerPayload: Decodable, Sendable { + public let lastReadID: String + public let version: Int + public let updatedAt: Date + + enum CodingKeys: String, CodingKey { + case lastReadID = "last_read_id" + case version + case updatedAt = "updated_at" + } +} + +public protocol TimelineMarkerType { + static var name: String { get } + associatedtype Payload: TimelineMarkerTypePayload +} + +extension TimelineMarkerType where Self == HomeMarker { + public static var home: Self { .init() } +} + +extension TimelineMarkerType where Self == NotificationsMarker { + public static var notifications: Self { .init() } +} + +public struct HomeMarker: TimelineMarkerType { + public typealias Payload = HomeMarkerPayload + public static var name: String { "home" } +} + +public struct NotificationsMarker: TimelineMarkerType { + public typealias Payload = NotificationsMarkerPayload + public static var name: String { "notifications" } +} diff --git a/Tusker/Screens/Timeline/TimelineViewController.swift b/Tusker/Screens/Timeline/TimelineViewController.swift index 18448c85..3b6d0eb6 100644 --- a/Tusker/Screens/Timeline/TimelineViewController.swift +++ b/Tusker/Screens/Timeline/TimelineViewController.swift @@ -573,12 +573,9 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro @MainActor private func restoreStatusesFromMarkerPosition() async -> Bool { do { - let (marker, _) = try await mastodonController.run(TimelineMarkers.request(timelines: [.home])) - guard let home = marker.home else { - return false - } - async let status = try await mastodonController.run(Client.getStatus(id: home.lastReadID)).0 - async let olderStatuses = try await mastodonController.run(Client.getStatuses(timeline: .home, range: .before(id: home.lastReadID, count: Self.pageSize))).0 + let (marker, _) = try await mastodonController.run(TimelineMarkers.request(timeline: .home)) + async let status = try await mastodonController.run(Client.getStatus(id: marker.lastReadID)).0 + async let olderStatuses = try await mastodonController.run(Client.getStatuses(timeline: .home, range: .before(id: marker.lastReadID, count: Self.pageSize))).0 let allStatuses = try await [status] + olderStatuses await mastodonController.persistentContainer.addAll(statuses: allStatuses) @@ -590,7 +587,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro await apply(snapshot, animatingDifferences: false) collectionView.contentOffset = CGPoint(x: 0, y: -collectionView.adjustedContentInset.top) - stateRestorationLogger.debug("TimelineViewController: restored from timeline marker with last read ID: \(home.lastReadID)") + stateRestorationLogger.debug("TimelineViewController: restored from timeline marker with last read ID: \(marker.lastReadID)") return true } catch {