diff --git a/Mac/Preferences/Accounts/AccountsGoogleReaderCompatibleWindowController.swift b/Mac/Preferences/Accounts/AccountsGoogleReaderCompatibleWindowController.swift index 89db9f277..b70b481b1 100644 --- a/Mac/Preferences/Accounts/AccountsGoogleReaderCompatibleWindowController.swift +++ b/Mac/Preferences/Accounts/AccountsGoogleReaderCompatibleWindowController.swift @@ -66,7 +66,7 @@ class AccountsGoogleReaderCompatibleWindowController: NSWindowController { progressIndicator.startAnimation(self) guard let apiURL = URL(string: apiURLTextField.stringValue) else { - self.errorMessageLabel.stringValue = NSLocalizedString("Invalie API URL.", comment: "Credentials Error") + self.errorMessageLabel.stringValue = NSLocalizedString("Invalid API URL.", comment: "Credentials Error") return } diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 414f74d58..09871e8cd 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -154,6 +154,7 @@ 51F85BF92274AA7B00C787DC /* UIBarButtonItem-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */; }; 51F85BFB2275D85000C787DC /* Array-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BFA2275D85000C787DC /* Array-Extensions.swift */; }; 51F85BFD2275DCA800C787DC /* SingleLineUILabelSizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F85BFC2275DCA800C787DC /* SingleLineUILabelSizer.swift */; }; + 557EE1AE22B6F4E1004206FA /* SettingsGoogleReaderCompatibleAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557EE1A522B6F4E1004206FA /* SettingsGoogleReaderCompatibleAccountView.swift */; }; 55E15BCB229D65A900D6602A /* AccountsGoogleReaderCompatible.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55E15BC1229D65A900D6602A /* AccountsGoogleReaderCompatible.xib */; }; 55E15BCC229D65A900D6602A /* AccountsGoogleReaderCompatibleWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E15BCA229D65A900D6602A /* AccountsGoogleReaderCompatibleWindowController.swift */; }; 6581C73820CED60100F4AD34 /* SafariExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */; }; @@ -750,6 +751,7 @@ 51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem-Extensions.swift"; sourceTree = ""; }; 51F85BFA2275D85000C787DC /* Array-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array-Extensions.swift"; sourceTree = ""; }; 51F85BFC2275DCA800C787DC /* SingleLineUILabelSizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleLineUILabelSizer.swift; sourceTree = ""; }; + 557EE1A522B6F4E1004206FA /* SettingsGoogleReaderCompatibleAccountView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsGoogleReaderCompatibleAccountView.swift; sourceTree = ""; }; 55E15BC1229D65A900D6602A /* AccountsGoogleReaderCompatible.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsGoogleReaderCompatible.xib; sourceTree = ""; }; 55E15BCA229D65A900D6602A /* AccountsGoogleReaderCompatibleWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountsGoogleReaderCompatibleWindowController.swift; sourceTree = ""; }; 6581C73320CED60000F4AD34 /* Subscribe to Feed.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Subscribe to Feed.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1050,6 +1052,7 @@ 5183CCEB227117C70010922C /* Settings */ = { isa = PBXGroup; children = ( + 557EE1A522B6F4E1004206FA /* SettingsGoogleReaderCompatibleAccountView.swift */, 510D708122B041CC004E8F65 /* SettingsAccountLabelView.swift */, 510D707322B028E1004E8F65 /* SettingsAddAccountView.swift */, 51F772EC22B2789B0087D9D1 /* SettingsDetailAccountView.swift */, @@ -2375,6 +2378,7 @@ 51F85BF722749FA100C787DC /* UIFont-Extensions.swift in Sources */, 515436882291D75D005E1CDF /* AddLocalAccountViewController.swift in Sources */, 51C452AF2265108300C03939 /* ArticleArray.swift in Sources */, + 557EE1AE22B6F4E1004206FA /* SettingsGoogleReaderCompatibleAccountView.swift in Sources */, 51C4528E2265099C00C03939 /* SmartFeedsController.swift in Sources */, 51C4529C22650A1000C03939 /* SingleFaviconDownloader.swift in Sources */, 51E595A6228CC36500FCC42B /* ArticleStatusSyncTimer.swift in Sources */, diff --git a/iOS/Settings/SettingsAddAccountView.swift b/iOS/Settings/SettingsAddAccountView.swift index fde5175f0..212c62f04 100644 --- a/iOS/Settings/SettingsAddAccountView.swift +++ b/iOS/Settings/SettingsAddAccountView.swift @@ -16,6 +16,9 @@ struct SettingsAddAccountView : View { destination: SettingsLocalAccountView(name: "")).padding(.all, 4) PresentationButton(SettingsAccountLabelView(accountImage: "accountFeedbin", accountLabel: "Feedbin"), destination: SettingsFeedbinAccountView(viewModel: SettingsFeedbinAccountView.ViewModel())).padding(.all, 4) + PresentationButton(SettingsAccountLabelView(accountImage: "accountLocal", accountLabel: "Google Reader Compatible"), + destination: SettingsGoogleReaderCompatibleAccountView(viewModel: SettingsGoogleReaderCompatibleAccountView.ViewModel())).padding(.all, 4) + } .listStyle(.grouped) .navigationBarTitle(Text("Add Account"), displayMode: .inline) diff --git a/iOS/Settings/SettingsFeedbinAccountView.swift b/iOS/Settings/SettingsFeedbinAccountView.swift index c867c94d2..59d7a7094 100644 --- a/iOS/Settings/SettingsFeedbinAccountView.swift +++ b/iOS/Settings/SettingsFeedbinAccountView.swift @@ -80,7 +80,7 @@ struct SettingsFeedbinAccountView : View { switch result { case .success(let authenticated): - if authenticated { + if (authenticated != nil) { var newAccount = false let workAccount: Account diff --git a/iOS/Settings/SettingsGoogleReaderCompatibleAccountView.swift b/iOS/Settings/SettingsGoogleReaderCompatibleAccountView.swift new file mode 100644 index 000000000..c36d71023 --- /dev/null +++ b/iOS/Settings/SettingsGoogleReaderCompatibleAccountView.swift @@ -0,0 +1,187 @@ +// +// SettingsGoogleReaderCompatibleAccountView.swift +// NetNewsWire-iOS +// +// Created by Maurice Parker on 6/11/19. +// Copyright © 2019 Ranchero Software. All rights reserved. +// + +import SwiftUI +import Combine +import Account +import RSWeb + +struct SettingsGoogleReaderCompatibleAccountView : View { + @Environment(\.isPresented) private var isPresented + @ObjectBinding var viewModel: ViewModel + @State var busy: Bool = false + @State var error: Text = Text("") + + var body: some View { + NavigationView { + List { + Section(header: + SettingsAccountLabelView(accountImage: "accountLocal", accountLabel: "Google Reader Compatible").padding() + ) { + HStack { + Text("Email:") + Divider() + TextField($viewModel.email) + .textContentType(.username) + } + HStack { + Text("Password:") + Divider() + SecureField($viewModel.password) + } + HStack { + Text("API URL:") + Divider() + TextField($viewModel.apiURL) + .textContentType(.URL) + } + } + Section(footer: + HStack { + Spacer() + error.color(.red) + Spacer() + } + ) { + HStack { + Spacer() + Button(action: { self.addAccount() }) { + if viewModel.isUpdate { + Text("Update Account") + } else { + Text("Add Account") + } + } + .disabled(!viewModel.isValid) + Spacer() + } + } + } + .disabled(busy) + .listStyle(.grouped) + .navigationBarTitle(Text(""), displayMode: .inline) + .navigationBarItems(leading: + Button(action: { self.dismiss() }) { Text("Cancel") } + ) + } + } + + private func addAccount() { + + busy = true + error = Text("") + + let emailAddress = viewModel.email.trimmingCharacters(in: .whitespaces) + let credentials = Credentials.basic(username: emailAddress, password: viewModel.password) + guard let apiURL = URL(string: viewModel.apiURL) else { + self.error = Text("Invalide API URL.") + return + } + + Account.validateCredentials(type: .googleReaderCompatible, credentials: credentials, endpoint: apiURL) { result in + + self.busy = false + + switch result { + case .success(let authenticated): + + if (authenticated != nil) { + + var newAccount = false + let workAccount: Account + if self.viewModel.account == nil { + workAccount = AccountManager.shared.createAccount(type: .googleReaderCompatible) + newAccount = true + } else { + workAccount = self.viewModel.account! + } + + do { + + do { + try workAccount.removeBasicCredentials() + } catch {} + + workAccount.endpointURL = apiURL + + try workAccount.storeCredentials(credentials) + + if newAccount { + workAccount.refreshAll() { result in } + } + + self.dismiss() + + } catch { + self.error = Text("Keychain error while storing credentials.") + } + + } else { + self.error = Text("Invalid email/password combination.") + } + + case .failure: + self.error = Text("Network error. Try again later.") + } + + } + + } + + private func dismiss() { + isPresented?.value = false + } + + class ViewModel: BindableObject { + let didChange = PassthroughSubject() + var account: Account? = nil + + init() { + } + + init(account: Account) { + self.account = account + if case .basic(let username, let password) = try? account.retrieveBasicCredentials() { + self.email = username + self.password = password + } + } + + var email: String = "" { + didSet { + didChange.send(self) + } + } + var password: String = "" { + didSet { + didChange.send(self) + } + } + var apiURL: String = "" { + didSet { + didChange.send(self) + } + } + var isUpdate: Bool { + return account != nil + } + + var isValid: Bool { + return !email.isEmpty && !password.isEmpty + } + } + +} + +#if DEBUG +struct SettingsGoogleReaderCompatibleAccountView_Previews : PreviewProvider { + static var previews: some View { + SettingsGoogleReaderCompatibleAccountView(viewModel: SettingsGoogleReaderCompatibleAccountView.ViewModel()) + } +} +#endif diff --git a/iOS/Settings/UIKit/FeedbinAccountViewController.swift b/iOS/Settings/UIKit/FeedbinAccountViewController.swift index c12d3d941..3cbf24bea 100644 --- a/iOS/Settings/UIKit/FeedbinAccountViewController.swift +++ b/iOS/Settings/UIKit/FeedbinAccountViewController.swift @@ -67,7 +67,7 @@ class FeedbinAccountViewController: UIViewController { switch result { case .success(let authenticated): - if authenticated { + if (authenticated != nil) { var newAccount = false if self.account == nil { self.account = AccountManager.shared.createAccount(type: .feedbin)