Compare commits
2 Commits
db7c183d06
...
b21703f6d9
Author | SHA1 | Date |
---|---|---|
Shadowfacts | b21703f6d9 | |
Shadowfacts | d003098146 |
|
@ -24,6 +24,20 @@ public struct Poll: Codable, Sendable {
|
||||||
expired || (expiresAt != nil && expiresAt! < Date())
|
expired || (expiresAt != nil && expiresAt! < Date())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
self.id = try container.decode(String.self, forKey: .id)
|
||||||
|
self.expiresAt = try container.decodeIfPresent(Date.self, forKey: .expiresAt)
|
||||||
|
self.expired = try container.decode(Bool.self, forKey: .expired)
|
||||||
|
self.multiple = try container.decode(Bool.self, forKey: .multiple)
|
||||||
|
self.votesCount = try container.decode(Int.self, forKey: .votesCount)
|
||||||
|
self.votersCount = try container.decodeIfPresent(Int.self, forKey: .votersCount)
|
||||||
|
self.voted = try container.decodeIfPresent(Bool.self, forKey: .voted)
|
||||||
|
self.ownVotes = try container.decodeIfPresent([Int].self, forKey: .ownVotes)
|
||||||
|
self.options = try container.decode([Poll.Option].self, forKey: .options)
|
||||||
|
self.emojis = try container.decodeIfPresent([Emoji].self, forKey: .emojis) ?? []
|
||||||
|
}
|
||||||
|
|
||||||
public static func vote(_ pollID: String, choices: [Int]) -> Request<Poll> {
|
public static func vote(_ pollID: String, choices: [Int]) -> Request<Poll> {
|
||||||
return Request<Poll>(method: .post, path: "/api/v1/polls/\(pollID)/votes", body: FormDataBody("choices" => choices, nil))
|
return Request<Poll>(method: .post, path: "/api/v1/polls/\(pollID)/votes", body: FormDataBody("choices" => choices, nil))
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
let objClazz = clazz as AnyObject as? NSObjectProtocol,
|
let objClazz = clazz as AnyObject as? NSObjectProtocol,
|
||||||
objClazz.responds(to: Selector(("id"))),
|
objClazz.responds(to: Selector(("id"))),
|
||||||
let id = objClazz.perform(Selector(("id"))).takeUnretainedValue() as? String {
|
let id = objClazz.perform(Selector(("id"))).takeUnretainedValue() as? String {
|
||||||
logger.info("Initialized Sentry with installation/user ID: \(id)")
|
logger.info("Initialized Sentry with installation/user ID: \(id, privacy: .public)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ class NotificationsCollectionViewController: UIViewController, TimelineLikeColle
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
self.controller = TimelineLikeController(delegate: self)
|
self.controller = TimelineLikeController(delegate: self, ownerType: String(describing: self))
|
||||||
|
|
||||||
addKeyCommand(MenuController.refreshCommand(discoverabilityTitle: "Refresh Notifications"))
|
addKeyCommand(MenuController.refreshCommand(discoverabilityTitle: "Refresh Notifications"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ProfileStatusesViewController: UIViewController, TimelineLikeCollectionVie
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
self.controller = TimelineLikeController(delegate: self)
|
self.controller = TimelineLikeController(delegate: self, ownerType: String(describing: self))
|
||||||
|
|
||||||
addKeyCommand(MenuController.refreshCommand(discoverabilityTitle: "Refresh Profile"))
|
addKeyCommand(MenuController.refreshCommand(discoverabilityTitle: "Refresh Profile"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
self.controller = TimelineLikeController(delegate: self)
|
self.controller = TimelineLikeController(delegate: self, ownerType: String(describing: self))
|
||||||
|
|
||||||
self.navigationItem.title = timeline.title
|
self.navigationItem.title = timeline.title
|
||||||
addKeyCommand(MenuController.refreshCommand(discoverabilityTitle: "Refresh Timeline"))
|
addKeyCommand(MenuController.refreshCommand(discoverabilityTitle: "Refresh Timeline"))
|
||||||
|
|
|
@ -40,19 +40,21 @@ private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category:
|
||||||
class TimelineLikeController<Item: Sendable> {
|
class TimelineLikeController<Item: Sendable> {
|
||||||
|
|
||||||
private unowned var delegate: any TimelineLikeControllerDelegate<Item>
|
private unowned var delegate: any TimelineLikeControllerDelegate<Item>
|
||||||
|
private let ownerType: String
|
||||||
|
|
||||||
private(set) var state = State.notLoadedInitial {
|
private(set) var state = State.notLoadedInitial {
|
||||||
willSet {
|
willSet {
|
||||||
guard state.canTransition(to: newValue) else {
|
guard state.canTransition(to: newValue) else {
|
||||||
logger.error("State \(self.state.debugDescription, privacy: .public) cannot transition to \(newValue.debugDescription, privacy: .public)")
|
logger.error("\(self.ownerType, privacy: .public) State \(self.state.debugDescription, privacy: .public) cannot transition to \(newValue.debugDescription, privacy: .public)")
|
||||||
fatalError("State \(state) cannot transition to \(newValue)")
|
fatalError("State \(state) cannot transition to \(newValue)")
|
||||||
}
|
}
|
||||||
logger.debug("State: \(self.state.debugDescription, privacy: .public) -> \(newValue.debugDescription, privacy: .public)")
|
logger.debug("\(self.ownerType, privacy: .public) State: \(self.state.debugDescription, privacy: .public) -> \(newValue.debugDescription, privacy: .public)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(delegate: any TimelineLikeControllerDelegate<Item>) {
|
init(delegate: any TimelineLikeControllerDelegate<Item>, ownerType: String) {
|
||||||
self.delegate = delegate
|
self.delegate = delegate
|
||||||
|
self.ownerType = ownerType
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadInitial() async {
|
func loadInitial() async {
|
||||||
|
@ -171,7 +173,7 @@ class TimelineLikeController<Item: Sendable> {
|
||||||
|
|
||||||
private func emit(event: Event) async {
|
private func emit(event: Event) async {
|
||||||
guard state.canEmit(event: event) else {
|
guard state.canEmit(event: event) else {
|
||||||
logger.error("State \(self.state.debugDescription, privacy: .public) cannot emit event: \(event.debugDescription, privacy: .public)")
|
logger.error("\(self.ownerType, privacy: .public) State \(self.state.debugDescription, privacy: .public) cannot emit event: \(event.debugDescription, privacy: .public)")
|
||||||
fatalError("State \(state) cannot emit event: \(event)")
|
fatalError("State \(state) cannot emit event: \(event)")
|
||||||
}
|
}
|
||||||
switch event {
|
switch event {
|
||||||
|
@ -324,7 +326,7 @@ class TimelineLikeController<Item: Sendable> {
|
||||||
case .loadAllError(let error, let token):
|
case .loadAllError(let error, let token):
|
||||||
return "loadAllError(\(error), \(token))"
|
return "loadAllError(\(error), \(token))"
|
||||||
case .replaceAllItems(_, let token):
|
case .replaceAllItems(_, let token):
|
||||||
return "replcaeAllItems(<omitted>, \(token))"
|
return "replaceAllItems(<omitted>, \(token))"
|
||||||
case .loadNewerError(let error, let token):
|
case .loadNewerError(let error, let token):
|
||||||
return "loadNewerError(\(error), \(token))"
|
return "loadNewerError(\(error), \(token))"
|
||||||
case .prependItems(_, let token):
|
case .prependItems(_, let token):
|
||||||
|
|
Loading…
Reference in New Issue