diff --git a/Pachyderm/Model/Account.swift b/Pachyderm/Model/Account.swift index 5a7e8499..688d24a2 100644 --- a/Pachyderm/Model/Account.swift +++ b/Pachyderm/Model/Account.swift @@ -22,8 +22,8 @@ public final class Account: AccountProtocol, Decodable { public let url: URL public let avatar: URL public let avatarStatic: URL - public let header: URL - public let headerStatic: URL + public let header: URL? + public let headerStatic: URL? public private(set) var emojis: [Emoji] public let moved: Bool? public let movedTo: Account? @@ -46,8 +46,8 @@ public final class Account: AccountProtocol, Decodable { self.url = try container.decode(URL.self, forKey: .url) self.avatar = try container.decode(URL.self, forKey: .avatar) self.avatarStatic = try container.decode(URL.self, forKey: .avatarStatic) - self.header = try container.decode(URL.self, forKey: .header) - self.headerStatic = try container.decode(URL.self, forKey: .headerStatic) + self.header = try? container.decode(URL.self, forKey: .header) + self.headerStatic = try? container.decode(URL.self, forKey: .headerStatic) self.emojis = try container.decode([Emoji].self, forKey: .emojis) self.fields = (try? container.decode([Field].self, forKey: .fields)) ?? [] self.bot = try? container.decode(Bool.self, forKey: .bot) diff --git a/Pachyderm/Model/LoginSettings.swift b/Pachyderm/Model/LoginSettings.swift index 096345e4..3f76388d 100644 --- a/Pachyderm/Model/LoginSettings.swift +++ b/Pachyderm/Model/LoginSettings.swift @@ -10,9 +10,10 @@ import Foundation public class LoginSettings: Decodable { public let accessToken: String - private let scope: String + private let scope: String? public var scopes: [Scope] { + guard let scope = scope else { return [] } return scope.components(separatedBy: .whitespaces).compactMap(Scope.init) } diff --git a/Pachyderm/Model/Protocols/AccountProtocol.swift b/Pachyderm/Model/Protocols/AccountProtocol.swift index 020d4b45..47b29ee4 100644 --- a/Pachyderm/Model/Protocols/AccountProtocol.swift +++ b/Pachyderm/Model/Protocols/AccountProtocol.swift @@ -23,7 +23,7 @@ public protocol AccountProtocol { var note: String { get } var url: URL { get } var avatar: URL { get } - var header: URL { get } + var header: URL? { get } var moved: Bool? { get } var bot: Bool? { get } diff --git a/Pachyderm/Model/RegisteredApplication.swift b/Pachyderm/Model/RegisteredApplication.swift index c0db4ed0..ffb5f62d 100644 --- a/Pachyderm/Model/RegisteredApplication.swift +++ b/Pachyderm/Model/RegisteredApplication.swift @@ -13,6 +13,25 @@ public class RegisteredApplication: Decodable { public let clientID: String public let clientSecret: String + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + // Pixelfed API returns id/client_id as numbers instead of strings + func decodeStringOrInt(key: CodingKeys) throws -> String { + if let str = try? container.decode(String.self, forKey: key) { + return str + } else if let int = try? container.decode(Int.self, forKey: key) { + return int.description + } else { + throw DecodingError.typeMismatch(String.self, DecodingError.Context(codingPath: container.codingPath + [CodingKeys.id], debugDescription: "")) + } + } + + self.id = try decodeStringOrInt(key: .id) + self.clientID = try decodeStringOrInt(key: .clientID) + self.clientSecret = try container.decode(String.self, forKey: .clientSecret) + } + private enum CodingKeys: String, CodingKey { case id case clientID = "client_id" diff --git a/Tusker/CoreData/AccountMO.swift b/Tusker/CoreData/AccountMO.swift index 8349246f..7aeb90cb 100644 --- a/Tusker/CoreData/AccountMO.swift +++ b/Tusker/CoreData/AccountMO.swift @@ -27,7 +27,7 @@ public final class AccountMO: NSManagedObject, AccountProtocol { @NSManaged private var fieldsData: Data? @NSManaged public var followersCount: Int @NSManaged public var followingCount: Int - @NSManaged public var header: URL + @NSManaged public var header: URL? @NSManaged public var id: String @NSManaged public var locked: Bool @NSManaged public var movedCD: Bool diff --git a/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents b/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents index 6a75df8f..0da7d6de 100644 --- a/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents +++ b/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents @@ -10,7 +10,7 @@ - + diff --git a/Tusker/Views/Profile Header/ProfileHeaderView.swift b/Tusker/Views/Profile Header/ProfileHeaderView.swift index 190f24b3..a20b8c79 100644 --- a/Tusker/Views/Profile Header/ProfileHeaderView.swift +++ b/Tusker/Views/Profile Header/ProfileHeaderView.swift @@ -113,11 +113,13 @@ class ProfileHeaderView: UIView { self.avatarImageView.image = UIImage(data: data) } } - headerRequest = ImageCache.headers.get(account.header) { [weak self] (data) in - guard let self = self, let data = data, self.accountID == accountID else { return } - self.headerRequest = nil - DispatchQueue.main.async { - self.headerImageView.image = UIImage(data: data) + if let header = account.header { + headerRequest = ImageCache.headers.get(header) { [weak self] (data) in + guard let self = self, let data = data, self.accountID == accountID else { return } + self.headerRequest = nil + DispatchQueue.main.async { + self.headerImageView.image = UIImage(data: data) + } } } @@ -205,16 +207,17 @@ class ProfileHeaderView: UIView { @objc func avatarPressed() { guard let account = mastodonController.persistentContainer.account(for: accountID) else { - fatalError("Missing cached account \(accountID!)") + return } delegate?.showLoadingLargeImage(url: account.avatar, cache: .avatars, description: nil, animatingFrom: avatarImageView) } @objc func headerPressed() { - guard let account = mastodonController.persistentContainer.account(for: accountID) else { - fatalError("Missing cached account \(accountID!)") + guard let account = mastodonController.persistentContainer.account(for: accountID), + let header = account.header else { + return } - delegate?.showLoadingLargeImage(url: account.header, cache: .headers, description: nil, animatingFrom: headerImageView) + delegate?.showLoadingLargeImage(url: header, cache: .headers, description: nil, animatingFrom: headerImageView) } @IBAction func postsSegmentedControlChanged(_ sender: UISegmentedControl) { diff --git a/Tusker/XCallbackURL/XCBActions.swift b/Tusker/XCallbackURL/XCBActions.swift index 110b410a..78f8490e 100644 --- a/Tusker/XCallbackURL/XCBActions.swift +++ b/Tusker/XCallbackURL/XCBActions.swift @@ -270,7 +270,7 @@ struct XCBActions { "following": account.followingCount.description, "url": account.url.absoluteString, "avatarURL": account.avatar.absoluteString, - "headerURL": account.header.absoluteString + "headerURL": account.header?.absoluteString ]) } } @@ -285,7 +285,7 @@ struct XCBActions { "following": account.followingCount.description, "url": account.url.absoluteString, "avatarURL": account.avatar.absoluteString, - "headerURL": account.header.absoluteString + "headerURL": account.header?.absoluteString ]) }