Merge remote-tracking branch 'upstream/master'

# Conflicts:
#	iOS/AppAssets.swift
This commit is contained in:
Stuart Breckenridge 2019-06-21 15:27:44 +08:00
commit 7d226c46a4
25 changed files with 181 additions and 138 deletions

View File

@ -33,7 +33,7 @@ public enum AccountType: Int {
case feedbin = 17 case feedbin = 17
case feedWrangler = 18 case feedWrangler = 18
case newsBlur = 19 case newsBlur = 19
case readerAPI = 20 case freshRSS = 20
// TODO: more // TODO: more
} }
@ -221,7 +221,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
self.delegate = LocalAccountDelegate() self.delegate = LocalAccountDelegate()
case .feedbin: case .feedbin:
self.delegate = FeedbinAccountDelegate(dataFolder: dataFolder, transport: transport) self.delegate = FeedbinAccountDelegate(dataFolder: dataFolder, transport: transport)
case .readerAPI: case .freshRSS:
self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport) self.delegate = ReaderAPIAccountDelegate(dataFolder: dataFolder, transport: transport)
default: default:
fatalError("Only Local and Feedbin accounts are supported") fatalError("Only Local and Feedbin accounts are supported")
@ -250,8 +250,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
defaultName = "FeedWrangler" defaultName = "FeedWrangler"
case .newsBlur: case .newsBlur:
defaultName = "NewsBlur" defaultName = "NewsBlur"
case .readerAPI: case .freshRSS:
defaultName = "Reader API" defaultName = "FreshRSS"
} }
NotificationCenter.default.addObserver(self, selector: #selector(downloadProgressDidChange(_:)), name: .DownloadProgressDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(downloadProgressDidChange(_:)), name: .DownloadProgressDidChange, object: nil)
@ -295,34 +295,40 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
} }
public func retrieveBasicCredentials() throws -> Credentials? { public func retrieveCredentials() throws -> Credentials? {
switch type {
case .feedbin:
guard let username = self.username, let server = delegate.server else { guard let username = self.username, let server = delegate.server else {
return nil return nil
} }
return try CredentialsManager.retrieveBasicCredentials(server: server, username: username) return try CredentialsManager.retrieveBasicCredentials(server: server, username: username)
case .freshRSS:
guard let username = self.username, let server = delegate.server else {
return nil
}
return try CredentialsManager.retrieveReaderAPIAuthCredentials(server: server, username: username)
default:
return nil
}
} }
public func removeBasicCredentials() throws { public func removeCredentials() throws {
switch type {
case .feedbin:
guard let username = self.username, let server = delegate.server else { guard let username = self.username, let server = delegate.server else {
return return
} }
try CredentialsManager.removeBasicCredentials(server: server, username: username) try CredentialsManager.removeBasicCredentials(server: server, username: username)
self.username = nil self.username = nil
} case .freshRSS:
public func retrieveReaderAPIAuthCredentials() throws -> Credentials? {
guard let username = self.username, let server = delegate.server else {
return nil
}
return try CredentialsManager.retrieveReaderAPIAuthCredentials(server: server, username: username)
}
public func removeReaderAPIAuthCredentials() throws {
guard let username = self.username, let server = delegate.server else { guard let username = self.username, let server = delegate.server else {
return return
} }
try CredentialsManager.removeReaderAPIAuthCredentials(server: server, username: username) try CredentialsManager.removeReaderAPIAuthCredentials(server: server, username: username)
self.username = nil self.username = nil
default:
break
}
} }
public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result<Credentials?, Error>) -> Void) { public static func validateCredentials(transport: Transport = URLSession.webserviceTransport(), type: AccountType, credentials: Credentials, endpoint: URL? = nil, completion: @escaping (Result<Credentials?, Error>) -> Void) {
@ -331,7 +337,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
LocalAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion) LocalAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
case .feedbin: case .feedbin:
FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion) FeedbinAccountDelegate.validateCredentials(transport: transport, credentials: credentials, completion: completion)
case .readerAPI: case .freshRSS:
ReaderAPIAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, completion: completion) ReaderAPIAccountDelegate.validateCredentials(transport: transport, credentials: credentials, endpoint: endpoint, completion: completion)
default: default:
break break

View File

@ -55,7 +55,7 @@ final class FeedbinAPICaller: NSObject {
switch error { switch error {
case TransportError.httpError(let status): case TransportError.httpError(let status):
if status == 401 { if status == 401 {
completion(.success(self.credentials)) completion(.success(nil))
} else { } else {
completion(.failure(error)) completion(.failure(error))
} }

View File

@ -510,7 +510,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
} }
func accountDidInitialize(_ account: Account) { func accountDidInitialize(_ account: Account) {
credentials = try? account.retrieveBasicCredentials() credentials = try? account.retrieveCredentials()
accountMetadata = account.metadata accountMetadata = account.metadata
} }

View File

@ -411,7 +411,7 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
func accountDidInitialize(_ account: Account) { func accountDidInitialize(_ account: Account) {
accountMetadata = account.metadata accountMetadata = account.metadata
credentials = try? account.retrieveReaderAPIAuthCredentials() credentials = try? account.retrieveCredentials()
} }
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result<Credentials?, Error>) -> Void) { static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL?, completion: @escaping (Result<Credentials?, Error>) -> Void) {

View File

@ -34,8 +34,8 @@ struct AppAssets {
return RSImage(named: "accountFeedbin") return RSImage(named: "accountFeedbin")
}() }()
static var accountReader: RSImage! = { static var accountFreshRSS: RSImage! = {
return RSImage(named: "accountReader") return RSImage(named: "accountFreshRSS")
}() }()
static var faviconTemplateImage: RSImage = { static var faviconTemplateImage: RSImage = {

View File

@ -64,8 +64,8 @@ extension AccountsAddViewController: NSTableViewDelegate {
cell.accountNameLabel?.stringValue = NSLocalizedString("Feedbin", comment: "Feedbin") cell.accountNameLabel?.stringValue = NSLocalizedString("Feedbin", comment: "Feedbin")
cell.accountImageView?.image = AppAssets.accountFeedbin cell.accountImageView?.image = AppAssets.accountFeedbin
case 2: case 2:
cell.accountNameLabel?.stringValue = NSLocalizedString("Reader API", comment: "Reader API") cell.accountNameLabel?.stringValue = NSLocalizedString("FreshRSS", comment: "FreshRSS")
cell.accountImageView?.image = AppAssets.accountReader cell.accountImageView?.image = AppAssets.accountFreshRSS
default: default:
break break
} }
@ -92,6 +92,7 @@ extension AccountsAddViewController: NSTableViewDelegate {
accountsAddWindowController = accountsFeedbinWindowController accountsAddWindowController = accountsFeedbinWindowController
case 2: case 2:
let accountsReaderAPIWindowController = AccountsReaderAPIWindowController() let accountsReaderAPIWindowController = AccountsReaderAPIWindowController()
accountsReaderAPIWindowController.accountType = .freshRSS
accountsReaderAPIWindowController.runSheetOnWindow(self.view.window!) accountsReaderAPIWindowController.runSheetOnWindow(self.view.window!)
accountsAddWindowController = accountsReaderAPIWindowController accountsAddWindowController = accountsReaderAPIWindowController
default: default:

View File

@ -27,10 +27,9 @@ class AccountsFeedbinWindowController: NSWindowController {
} }
override func windowDidLoad() { override func windowDidLoad() {
if let account = account, let credentials = try? account.retrieveBasicCredentials() { if let account = account, let credentials = try? account.retrieveCredentials() {
if case .basic(let username, let password) = credentials { if case .basic(let username, _) = credentials {
usernameTextField.stringValue = username usernameTextField.stringValue = username
passwordTextField.stringValue = password
} }
actionButton.title = NSLocalizedString("Update", comment: "Update") actionButton.title = NSLocalizedString("Update", comment: "Update")
} else { } else {
@ -87,7 +86,7 @@ class AccountsFeedbinWindowController: NSWindowController {
} }
do { do {
try self.account?.removeBasicCredentials() try self.account?.removeCredentials()
try self.account?.storeCredentials(validatedCredentials) try self.account?.storeCredentials(validatedCredentials)
if newAccount { if newAccount {
self.account?.refreshAll() { result in self.account?.refreshAll() { result in

View File

@ -107,8 +107,8 @@ extension AccountsPreferencesViewController: NSTableViewDelegate {
cell.imageView?.image = AppAssets.accountLocal cell.imageView?.image = AppAssets.accountLocal
case .feedbin: case .feedbin:
cell.imageView?.image = NSImage(named: "accountFeedbin") cell.imageView?.image = NSImage(named: "accountFeedbin")
case .readerAPI: case .freshRSS:
cell.imageView?.image = AppAssets.accountReader cell.imageView?.image = AppAssets.accountFreshRSS
default: default:
break break
} }

View File

@ -13,6 +13,8 @@
<outlet property="errorMessageLabel" destination="byK-Sd-r7F" id="8zt-9d-dWQ"/> <outlet property="errorMessageLabel" destination="byK-Sd-r7F" id="8zt-9d-dWQ"/>
<outlet property="passwordTextField" destination="JSa-LY-zNQ" id="E9W-0F-69m"/> <outlet property="passwordTextField" destination="JSa-LY-zNQ" id="E9W-0F-69m"/>
<outlet property="progressIndicator" destination="B0W-bh-Evv" id="Tiq-gx-s3F"/> <outlet property="progressIndicator" destination="B0W-bh-Evv" id="Tiq-gx-s3F"/>
<outlet property="titleImageView" destination="Ssh-Dh-xbg" id="8Iy-jf-EYR"/>
<outlet property="titleLabel" destination="lti-yM-8LV" id="AP0-ds-6tS"/>
<outlet property="usernameTextField" destination="78p-Cf-f55" id="RWd-0q-oAL"/> <outlet property="usernameTextField" destination="78p-Cf-f55" id="RWd-0q-oAL"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/> <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections> </connections>
@ -37,7 +39,7 @@
<constraint firstAttribute="height" constant="36" id="Ern-Kk-8LX"/> <constraint firstAttribute="height" constant="36" id="Ern-Kk-8LX"/>
<constraint firstAttribute="width" constant="36" id="PLS-68-NMc"/> <constraint firstAttribute="width" constant="36" id="PLS-68-NMc"/>
</constraints> </constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="accountReader" id="y38-YL-woC"/> <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="y38-YL-woC"/>
</imageView> </imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lti-yM-8LV"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lti-yM-8LV">
<rect key="frame" x="53" y="0.0" width="156" height="38"/> <rect key="frame" x="53" y="0.0" width="156" height="38"/>
@ -205,7 +207,4 @@ Gw
<point key="canvasLocation" x="116.5" y="136.5"/> <point key="canvasLocation" x="116.5" y="136.5"/>
</window> </window>
</objects> </objects>
<resources>
<image name="accountReader" width="73" height="73"/>
</resources>
</document> </document>

View File

@ -12,6 +12,9 @@ import RSWeb
class AccountsReaderAPIWindowController: NSWindowController { class AccountsReaderAPIWindowController: NSWindowController {
@IBOutlet weak var titleImageView: NSImageView!
@IBOutlet weak var titleLabel: NSTextField!
@IBOutlet weak var progressIndicator: NSProgressIndicator! @IBOutlet weak var progressIndicator: NSProgressIndicator!
@IBOutlet weak var usernameTextField: NSTextField! @IBOutlet weak var usernameTextField: NSTextField!
@IBOutlet weak var apiURLTextField: NSTextField! @IBOutlet weak var apiURLTextField: NSTextField!
@ -20,6 +23,7 @@ class AccountsReaderAPIWindowController: NSWindowController {
@IBOutlet weak var actionButton: NSButton! @IBOutlet weak var actionButton: NSButton!
var account: Account? var account: Account?
var accountType: AccountType?
private weak var hostWindow: NSWindow? private weak var hostWindow: NSWindow?
@ -28,10 +32,19 @@ class AccountsReaderAPIWindowController: NSWindowController {
} }
override func windowDidLoad() { override func windowDidLoad() {
if let account = account, let credentials = try? account.retrieveBasicCredentials() { if let accountType = accountType {
if case .basic(let username, let password) = credentials { switch accountType {
case .freshRSS:
titleImageView.image = AppAssets.accountFreshRSS
titleLabel.stringValue = NSLocalizedString("FreshRSS", comment: "FreshRSS")
default:
break
}
}
if let account = account, let credentials = try? account.retrieveCredentials() {
if case .basic(let username, _) = credentials {
usernameTextField.stringValue = username usernameTextField.stringValue = username
passwordTextField.stringValue = password
} }
actionButton.title = NSLocalizedString("Update", comment: "Update") actionButton.title = NSLocalizedString("Update", comment: "Update")
} else { } else {
@ -71,7 +84,7 @@ class AccountsReaderAPIWindowController: NSWindowController {
} }
let credentials = Credentials.readerAPIBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue) let credentials = Credentials.readerAPIBasicLogin(username: usernameTextField.stringValue, password: passwordTextField.stringValue)
Account.validateCredentials(type: .readerAPI, credentials: credentials, endpoint: apiURL) { [weak self] result in Account.validateCredentials(type: accountType!, credentials: credentials, endpoint: apiURL) { [weak self] result in
guard let self = self else { return } guard let self = self else { return }
@ -89,14 +102,14 @@ class AccountsReaderAPIWindowController: NSWindowController {
var newAccount = false var newAccount = false
if self.account == nil { if self.account == nil {
self.account = AccountManager.shared.createAccount(type: .readerAPI) self.account = AccountManager.shared.createAccount(type: self.accountType!)
newAccount = true newAccount = true
} }
do { do {
self.account?.endpointURL = apiURL self.account?.endpointURL = apiURL
try self.account?.removeReaderAPIAuthCredentials() try self.account?.removeCredentials()
try self.account?.storeCredentials(validatedCredentials) try self.account?.storeCredentials(validatedCredentials)
if newAccount { if newAccount {

View File

@ -2,7 +2,7 @@
"images" : [ "images" : [
{ {
"idiom" : "universal", "idiom" : "universal",
"filename" : "accountReader.pdf" "filename" : "accountFreshRSS.pdf"
} }
], ],
"info" : { "info" : {

View File

@ -142,8 +142,8 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
osType = "FWrg" osType = "FWrg"
case .newsBlur: case .newsBlur:
osType = "NBlr" osType = "NBlr"
case .readerAPI: case .freshRSS:
osType = "Grdr" osType = "Frsh"
} }
return osType.fourCharCode() return osType.fourCharCode()
} }

View File

@ -51,7 +51,7 @@ private extension RSImage {
let rect = CGRect(x: 0, y: 0, width: avatarSize, height: avatarSize) let rect = CGRect(x: 0, y: 0, width: avatarSize, height: avatarSize)
UIGraphicsBeginImageContext(rect.size) UIGraphicsBeginImageContext(rect.size)
if let context = UIGraphicsGetCurrentContext() { if let context = UIGraphicsGetCurrentContext() {
context.setFillColor(AppAssets.avatarLightBackgroundColor.cgColor) context.setFillColor(AppAssets.avatarBackgroundColor.cgColor)
context.fill(rect) context.fill(rect)
context.translateBy(x: 0.0, y: CGFloat(integerLiteral: avatarSize)); context.translateBy(x: 0.0, y: CGFloat(integerLiteral: avatarSize));
context.scaleBy(x: 1.0, y: -1.0) context.scaleBy(x: 1.0, y: -1.0)

View File

@ -10,34 +10,30 @@ import RSCore
struct AppAssets { struct AppAssets {
static var avatarDarkBackgroundColor: UIColor { static var avatarBackgroundColor: UIColor = {
return UIColor(named: "avatarDarkBackgroundColor")! return UIColor(named: "avatarBackgroundColor")!
}
static var avatarLightBackgroundColor: UIColor {
return UIColor(named: "avatarLightBackgroundColor")!
}
static var circleClosedImage: UIImage = {
return UIImage(systemName: "circle.fill")!
}() }()
static var circleOpenImage: UIImage = { static var circleClosedImage: RSImage = {
return UIImage(systemName: "circle")! return RSImage(named: "circleClosedImage")!
}()
static var circleOpenImage: RSImage = {
return RSImage(named: "circleOpenImage")!
}() }()
static var chevronDisclosureColor: UIColor = { static var chevronDisclosureColor: UIColor = {
return UIColor(named: "chevronDisclosureColor")! return UIColor(named: "chevronDisclosureColor")!
}() }()
static var chevronDownImage: UIImage = { static var chevronDownImage: RSImage = {
let image = UIImage(systemName: "chevron.down")! let image = RSImage(named: "chevronDownImage")!
return image.withTintColor(AppAssets.chevronDisclosureColor, renderingMode: .alwaysOriginal) return image.maskWithColor(color: AppAssets.chevronDisclosureColor.cgColor)!
}() }()
static var chevronRightImage: UIImage = { static var chevronRightImage: RSImage = {
let image = UIImage(systemName: "chevron.right")! let image = RSImage(named: "chevronRightImage")!
return image.withTintColor(AppAssets.chevronDisclosureColor, renderingMode: .alwaysOriginal) return image.maskWithColor(color: AppAssets.chevronDisclosureColor.cgColor)!
}() }()
static var faviconTemplateImage: RSImage = { static var faviconTemplateImage: RSImage = {
@ -52,9 +48,9 @@ struct AppAssets {
return UIColor(named: "masterFolderColor")! return UIColor(named: "masterFolderColor")!
}() }()
static var masterFolderImage: UIImage = { static var masterFolderImage: RSImage = {
let image = UIImage(systemName: "folder.fill")! let image = RSImage(systemName: "folder.fill")!
return image.withTintColor(AppAssets.masterFolderColor, renderingMode: .alwaysOriginal) return image.maskWithColor(color: AppAssets.masterFolderColor.cgColor)!
}() }()
static var netNewsWireBlueColor: UIColor = { static var netNewsWireBlueColor: UIColor = {
@ -65,26 +61,26 @@ struct AppAssets {
return UIColor(named: "smartFeedColor")! return UIColor(named: "smartFeedColor")!
}() }()
static var smartFeedImage: UIImage = { static var smartFeedImage: RSImage = {
let image = UIImage(systemName: "gear")! let image = RSImage(named: "smartFeedImage")!
return image.withTintColor(AppAssets.smartFeedColor, renderingMode: .alwaysOriginal) return image.maskWithColor(color: AppAssets.smartFeedColor.cgColor)!
}() }()
static var starColor: UIColor = { static var starColor: UIColor = {
return UIColor(named: "starColor")! return UIColor(named: "starColor")!
}() }()
static var starClosedImage: UIImage = { static var starClosedImage: RSImage = {
return UIImage(systemName: "star.fill")! return RSImage(named: "starClosedImage")!
}() }()
static var starOpenImage: UIImage = { static var starOpenImage: RSImage = {
return UIImage(systemName: "star")! return RSImage(named: "starOpenImage")!
}() }()
static var timelineStarImage: UIImage = { static var timelineStarImage: RSImage = {
let image = UIImage(systemName: "star.fill")! let image = RSImage(named: "starClosedImage")!
return image.withTintColor(AppAssets.starColor, renderingMode: .alwaysOriginal) return image.maskWithColor(color: AppAssets.starColor.cgColor)!
}() }()
static var timelineUnreadCircleColor: UIColor = { static var timelineUnreadCircleColor: UIColor = {

View File

@ -73,6 +73,19 @@ class MasterTimelineViewController: ProgressTableViewController, UndoableCommand
} }
} }
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.userInterfaceStyle != previousTraitCollection?.userInterfaceStyle {
appDelegate.authorAvatarDownloader.resetCache()
appDelegate.feedIconDownloader.resetCache()
appDelegate.faviconDownloader.resetCache()
performBlockAndRestoreSelection {
tableView.reloadData()
}
}
}
// MARK Actions // MARK Actions
@IBAction func markAllAsRead(_ sender: Any) { @IBAction func markAllAsRead(_ sender: Any) {

View File

@ -24,7 +24,7 @@ public final class NavigationProgressView: UIView {
internal let bar = UIView() internal let bar = UIView()
@objc public dynamic var progressTintColor: UIColor? = UIColor(red: 0, green: 122/255, blue: 1, alpha: 1) { @objc public dynamic var progressTintColor: UIColor? = AppAssets.netNewsWireBlueColor {
didSet { didSet {
bar.backgroundColor = progressTintColor bar.backgroundColor = progressTintColor
} }

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "accountFreshRSS.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@ -0,0 +1,38 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
},
"colors" : [
{
"idiom" : "universal",
"color" : {
"color-space" : "srgb",
"components" : {
"red" : "242",
"alpha" : "1.000",
"blue" : "242",
"green" : "242"
}
}
},
{
"idiom" : "universal",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"red" : "56",
"alpha" : "1.000",
"blue" : "56",
"green" : "56"
}
}
}
]
}

View File

@ -1,20 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
},
"colors" : [
{
"idiom" : "universal",
"color" : {
"color-space" : "srgb",
"components" : {
"red" : "56",
"alpha" : "1.000",
"blue" : "56",
"green" : "56"
}
}
}
]
}

View File

@ -1,20 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
},
"colors" : [
{
"idiom" : "universal",
"color" : {
"color-space" : "srgb",
"components" : {
"red" : "242",
"alpha" : "1.000",
"blue" : "242",
"green" : "242"
}
}
}
]
}

View File

@ -93,7 +93,7 @@ struct SettingsFeedbinAccountView : View {
do { do {
do { do {
try workAccount.removeBasicCredentials() try workAccount.removeCredentials()
} catch {} } catch {}
try workAccount.storeCredentials(credentials) try workAccount.storeCredentials(credentials)
@ -132,7 +132,7 @@ struct SettingsFeedbinAccountView : View {
init(account: Account) { init(account: Account) {
self.account = account self.account = account
if case .basic(let username, let password) = try? account.retrieveBasicCredentials() { if case .basic(let username, let password) = try? account.retrieveCredentials() {
self.email = username self.email = username
self.password = password self.password = password
} }

View File

@ -21,7 +21,7 @@ struct SettingsReaderAPIAccountView : View {
NavigationView { NavigationView {
List { List {
Section(header: Section(header:
SettingsAccountLabelView(accountImage: "accountLocal", accountLabel: "Google Reader Compatible").padding() SettingsAccountLabelView(accountImage: "accountFreshRSS", accountLabel: "FreshRSS").padding()
) { ) {
HStack { HStack {
Text("Email:") Text("Email:")
@ -83,7 +83,7 @@ struct SettingsReaderAPIAccountView : View {
return return
} }
Account.validateCredentials(type: .readerAPI, credentials: credentials, endpoint: apiURL) { result in Account.validateCredentials(type: viewModel.accountType, credentials: credentials, endpoint: apiURL) { result in
self.busy = false self.busy = false
@ -95,7 +95,7 @@ struct SettingsReaderAPIAccountView : View {
var newAccount = false var newAccount = false
let workAccount: Account let workAccount: Account
if self.viewModel.account == nil { if self.viewModel.account == nil {
workAccount = AccountManager.shared.createAccount(type: .readerAPI) workAccount = AccountManager.shared.createAccount(type: self.viewModel.accountType)
newAccount = true newAccount = true
} else { } else {
workAccount = self.viewModel.account! workAccount = self.viewModel.account!
@ -104,7 +104,7 @@ struct SettingsReaderAPIAccountView : View {
do { do {
do { do {
try workAccount.removeBasicCredentials() try workAccount.removeCredentials()
} catch {} } catch {}
workAccount.endpointURL = apiURL workAccount.endpointURL = apiURL
@ -139,14 +139,17 @@ struct SettingsReaderAPIAccountView : View {
class ViewModel: BindableObject { class ViewModel: BindableObject {
let didChange = PassthroughSubject<ViewModel, Never>() let didChange = PassthroughSubject<ViewModel, Never>()
var accountType: AccountType
var account: Account? = nil var account: Account? = nil
init() { init(accountType: AccountType) {
self.accountType = accountType
} }
init(account: Account) { init(accountType: AccountType, account: Account) {
self.account = account self.account = account
if case .basic(let username, let password) = try? account.retrieveBasicCredentials() { self.accountType = accountType
if case .basic(let username, let password) = try? account.retrieveCredentials() {
self.email = username self.email = username
self.password = password self.password = password
} }
@ -181,7 +184,7 @@ struct SettingsReaderAPIAccountView : View {
#if DEBUG #if DEBUG
struct SettingsReaderAPIAccountView_Previews : PreviewProvider { struct SettingsReaderAPIAccountView_Previews : PreviewProvider {
static var previews: some View { static var previews: some View {
SettingsReaderAPIAccountView(viewModel: SettingsReaderAPIAccountView.ViewModel()) SettingsReaderAPIAccountView(viewModel: SettingsReaderAPIAccountView.ViewModel(accountType: .freshRSS))
} }
} }
#endif #endif

View File

@ -30,7 +30,7 @@ class FeedbinAccountViewController: UIViewController {
emailTextField.delegate = self emailTextField.delegate = self
passwordTextField.delegate = self passwordTextField.delegate = self
if let account = account, let credentials = try? account.retrieveBasicCredentials() { if let account = account, let credentials = try? account.retrieveCredentials() {
actionButton.setTitle(NSLocalizedString("Update Credentials", comment: "Update Credentials"), for: .normal) actionButton.setTitle(NSLocalizedString("Update Credentials", comment: "Update Credentials"), for: .normal)
if case .basic(let username, let password) = credentials { if case .basic(let username, let password) = credentials {
emailTextField.text = username emailTextField.text = username
@ -77,7 +77,7 @@ class FeedbinAccountViewController: UIViewController {
do { do {
do { do {
try self.account?.removeBasicCredentials() try self.account?.removeCredentials()
} catch {} } catch {}
try self.account?.storeCredentials(credentials) try self.account?.storeCredentials(credentials)