Fix logging in to PixelFed instances

See #68
This commit is contained in:
Shadowfacts 2020-10-25 23:07:41 -04:00
parent 39b244384b
commit 93828830a9
Signed by untrusted user: shadowfacts
GPG Key ID: 94A5AB95422746E5
8 changed files with 42 additions and 19 deletions

View File

@ -22,8 +22,8 @@ public final class Account: AccountProtocol, Decodable {
public let url: URL public let url: URL
public let avatar: URL public let avatar: URL
public let avatarStatic: URL public let avatarStatic: URL
public let header: URL public let header: URL?
public let headerStatic: URL public let headerStatic: URL?
public private(set) var emojis: [Emoji] public private(set) var emojis: [Emoji]
public let moved: Bool? public let moved: Bool?
public let movedTo: Account? public let movedTo: Account?
@ -46,8 +46,8 @@ public final class Account: AccountProtocol, Decodable {
self.url = try container.decode(URL.self, forKey: .url) self.url = try container.decode(URL.self, forKey: .url)
self.avatar = try container.decode(URL.self, forKey: .avatar) self.avatar = try container.decode(URL.self, forKey: .avatar)
self.avatarStatic = try container.decode(URL.self, forKey: .avatarStatic) self.avatarStatic = try container.decode(URL.self, forKey: .avatarStatic)
self.header = try container.decode(URL.self, forKey: .header) self.header = try? container.decode(URL.self, forKey: .header)
self.headerStatic = try container.decode(URL.self, forKey: .headerStatic) self.headerStatic = try? container.decode(URL.self, forKey: .headerStatic)
self.emojis = try container.decode([Emoji].self, forKey: .emojis) self.emojis = try container.decode([Emoji].self, forKey: .emojis)
self.fields = (try? container.decode([Field].self, forKey: .fields)) ?? [] self.fields = (try? container.decode([Field].self, forKey: .fields)) ?? []
self.bot = try? container.decode(Bool.self, forKey: .bot) self.bot = try? container.decode(Bool.self, forKey: .bot)

View File

@ -10,9 +10,10 @@ import Foundation
public class LoginSettings: Decodable { public class LoginSettings: Decodable {
public let accessToken: String public let accessToken: String
private let scope: String private let scope: String?
public var scopes: [Scope] { public var scopes: [Scope] {
guard let scope = scope else { return [] }
return scope.components(separatedBy: .whitespaces).compactMap(Scope.init) return scope.components(separatedBy: .whitespaces).compactMap(Scope.init)
} }

View File

@ -23,7 +23,7 @@ public protocol AccountProtocol {
var note: String { get } var note: String { get }
var url: URL { get } var url: URL { get }
var avatar: URL { get } var avatar: URL { get }
var header: URL { get } var header: URL? { get }
var moved: Bool? { get } var moved: Bool? { get }
var bot: Bool? { get } var bot: Bool? { get }

View File

@ -13,6 +13,25 @@ public class RegisteredApplication: Decodable {
public let clientID: String public let clientID: String
public let clientSecret: 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 { private enum CodingKeys: String, CodingKey {
case id case id
case clientID = "client_id" case clientID = "client_id"

View File

@ -27,7 +27,7 @@ public final class AccountMO: NSManagedObject, AccountProtocol {
@NSManaged private var fieldsData: Data? @NSManaged private var fieldsData: Data?
@NSManaged public var followersCount: Int @NSManaged public var followersCount: Int
@NSManaged public var followingCount: Int @NSManaged public var followingCount: Int
@NSManaged public var header: URL @NSManaged public var header: URL?
@NSManaged public var id: String @NSManaged public var id: String
@NSManaged public var locked: Bool @NSManaged public var locked: Bool
@NSManaged public var movedCD: Bool @NSManaged public var movedCD: Bool

View File

@ -10,7 +10,7 @@
<attribute name="fieldsData" optional="YES" attributeType="Binary"/> <attribute name="fieldsData" optional="YES" attributeType="Binary"/>
<attribute name="followersCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="followersCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="followingCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="followingCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="header" attributeType="URI"/> <attribute name="header" optional="YES" attributeType="URI"/>
<attribute name="id" attributeType="String"/> <attribute name="id" attributeType="String"/>
<attribute name="locked" attributeType="Boolean" usesScalarValueType="YES"/> <attribute name="locked" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="movedCD" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/> <attribute name="movedCD" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>

View File

@ -113,13 +113,15 @@ class ProfileHeaderView: UIView {
self.avatarImageView.image = UIImage(data: data) self.avatarImageView.image = UIImage(data: data)
} }
} }
headerRequest = ImageCache.headers.get(account.header) { [weak self] (data) in 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 } guard let self = self, let data = data, self.accountID == accountID else { return }
self.headerRequest = nil self.headerRequest = nil
DispatchQueue.main.async { DispatchQueue.main.async {
self.headerImageView.image = UIImage(data: data) self.headerImageView.image = UIImage(data: data)
} }
} }
}
if #available(iOS 14.0, *) { if #available(iOS 14.0, *) {
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: actionsForProfile(accountID: accountID, sourceView: moreButton)) moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: actionsForProfile(accountID: accountID, sourceView: moreButton))
@ -205,16 +207,17 @@ class ProfileHeaderView: UIView {
@objc func avatarPressed() { @objc func avatarPressed() {
guard let account = mastodonController.persistentContainer.account(for: accountID) else { 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) delegate?.showLoadingLargeImage(url: account.avatar, cache: .avatars, description: nil, animatingFrom: avatarImageView)
} }
@objc func headerPressed() { @objc func headerPressed() {
guard let account = mastodonController.persistentContainer.account(for: accountID) else { guard let account = mastodonController.persistentContainer.account(for: accountID),
fatalError("Missing cached account \(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) { @IBAction func postsSegmentedControlChanged(_ sender: UISegmentedControl) {

View File

@ -270,7 +270,7 @@ struct XCBActions {
"following": account.followingCount.description, "following": account.followingCount.description,
"url": account.url.absoluteString, "url": account.url.absoluteString,
"avatarURL": account.avatar.absoluteString, "avatarURL": account.avatar.absoluteString,
"headerURL": account.header.absoluteString "headerURL": account.header?.absoluteString
]) ])
} }
} }
@ -285,7 +285,7 @@ struct XCBActions {
"following": account.followingCount.description, "following": account.followingCount.description,
"url": account.url.absoluteString, "url": account.url.absoluteString,
"avatarURL": account.avatar.absoluteString, "avatarURL": account.avatar.absoluteString,
"headerURL": account.header.absoluteString "headerURL": account.header?.absoluteString
]) ])
} }