diff --git a/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Add Account/AddAccountModel.swift b/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Add Account/AddAccountModel.swift index 31f2976ba..78a836122 100644 --- a/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Add Account/AddAccountModel.swift +++ b/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Add Account/AddAccountModel.swift @@ -10,15 +10,14 @@ import Foundation import Account import RSWeb import Secrets +import RSCore class AddAccountModel: ObservableObject { - - #if DEBUG - let addableAccountTypes: [AccountType] = [.onMyMac, .feedbin, .feedly, .feedWrangler, .freshRSS, .cloudKit, .newsBlur] + var addableAccountTypes: [AccountType] = [.onMyMac, .feedbin, .feedly, .feedWrangler, .freshRSS, .cloudKit, .newsBlur] #else - let addableAccountTypes: [AccountType] = [.onMyMac, .feedbin, .feedly] + var addableAccountTypes: [AccountType] = [.onMyMac, .feedbin, .feedly] #endif // Add Accounts @@ -40,6 +39,10 @@ class AddAccountModel: ObservableObject { @Published var showError: Bool = false @Published var accountAdded: Bool = false + init() { + restrictAccounts() + } + func resetUserEntries() { userName = "" password = "" @@ -66,6 +69,25 @@ class AddAccountModel: ObservableObject { } } + func restrictAccounts() { + func removeAccountType(_ accountType: AccountType) { + if let index = addableAccountTypes.firstIndex(of: accountType) { + addableAccountTypes.remove(at: index) + } + } + + if AppDefaults.shared.isDeveloperBuild { + removeAccountType(.cloudKit) + removeAccountType(.feedly) + removeAccountType(.feedWrangler) + return + } + + if AccountManager.shared.activeAccounts.firstIndex(where: { $0.type == .cloudKit }) != nil { + removeAccountType(.cloudKit) + } + } + } // MARK:- Authentication APIs @@ -266,7 +288,32 @@ extension AddAccountModel { } private func authenticateFeedly() { - // TBC + accountIsAuthenticating = true + let addAccount = OAuthAccountAuthorizationOperation(accountType: .feedly) + addAccount.delegate = self + addAccount.presentationAnchor = NSApplication.shared.windows.last + MainThreadOperationQueue.shared.add(addAccount) } } + +// MARK:- OAuthAccountAuthorizationOperationDelegate +extension AddAccountModel: OAuthAccountAuthorizationOperationDelegate { + func oauthAccountAuthorizationOperation(_ operation: OAuthAccountAuthorizationOperation, didCreate account: Account) { + accountIsAuthenticating = false + accountAdded = true + account.refreshAll { [weak self] result in + switch result { + case .success: + break + case .failure(let error): + self?.addAccountError = .other(error: error) + } + } + } + + func oauthAccountAuthorizationOperation(_ operation: OAuthAccountAuthorizationOperation, didFailWith error: Error) { + accountIsAuthenticating = false + addAccountError = .other(error: error) + } +} diff --git a/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Add Account/AddAccountView.swift b/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Add Account/AddAccountView.swift index 48e0dcd6d..aa231c3a8 100644 --- a/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Add Account/AddAccountView.swift +++ b/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Add Account/AddAccountView.swift @@ -28,12 +28,11 @@ struct AddAccountView: View { }) }) - switch viewModel.selectedAddAccount { case .onMyMac: addLocalAccountView case .cloudKit: - Text("iCloud") + iCloudAccountView case .feedbin: userNameAndPasswordView case .feedWrangler: @@ -41,12 +40,17 @@ struct AddAccountView: View { case .freshRSS: userNamePasswordAndAPIUrlView case .feedly: - Text("Feedly") + oAuthView case .newsBlur: userNameAndPasswordView } + } + + + + Spacer() HStack { if viewModel.accountIsAuthenticating { @@ -57,28 +61,33 @@ struct AddAccountView: View { Text("Cancel") }) - if viewModel.selectedAddAccount == .onMyMac { - Button("Add", action: { - viewModel.authenticateAccount() - }) - } - - if viewModel.selectedAddAccount != .onMyMac && viewModel.selectedAddAccount != .freshRSS { - Button("Add Account", action: { - viewModel.authenticateAccount() - }) - .disabled(viewModel.userName.count == 0 || viewModel.password.count == 0) - } - - if viewModel.selectedAddAccount == .freshRSS { - Button("Add Account", action: { - viewModel.authenticateAccount() - }) - .disabled(viewModel.userName.count == 0 || viewModel.password.count == 0 || viewModel.apiUrl.count == 0) + switch viewModel.selectedAddAccount { + case .onMyMac: + Button("Add Account", action: { + viewModel.authenticateAccount() + }) + case .feedly: + Button("Authenticate", action: { + viewModel.authenticateAccount() + }) + case .cloudKit: + Button("Add Account", action: { + viewModel.authenticateAccount() + }) + case .freshRSS: + Button("Add Account", action: { + viewModel.authenticateAccount() + }) + .disabled(viewModel.userName.count == 0 || viewModel.password.count == 0 || viewModel.apiUrl.count == 0) + default: + Button("Add Account", action: { + viewModel.authenticateAccount() + }) + .disabled(viewModel.userName.count == 0 || viewModel.password.count == 0) } } } - .frame(idealWidth: 300, idealHeight: 200, alignment: .top) + .frame(width: 300, height: 200, alignment: .top) .padding() .onChange(of: viewModel.selectedAddAccount) { _ in viewModel.resetUserEntries() @@ -102,20 +111,25 @@ struct AddAccountView: View { var addLocalAccountView: some View { Group { TextField("Account Name", text: $viewModel.newLocalAccountName) - .textFieldStyle(RoundedBorderTextFieldStyle()) Text("This account stores all of its data on your device. It does not sync.") .foregroundColor(.secondary) .multilineTextAlignment(.leading) - } + }.textFieldStyle(RoundedBorderTextFieldStyle()) + } + + var iCloudAccountView: some View { + Group { + Text("This account syncs across your devices using your iCloud account.") + .foregroundColor(.secondary) + .multilineTextAlignment(.leading) + }.textFieldStyle(RoundedBorderTextFieldStyle()) } var userNameAndPasswordView: some View { Group { TextField("Email", text: $viewModel.userName) - .textFieldStyle(RoundedBorderTextFieldStyle()) SecureField("Password", text: $viewModel.password) - .textFieldStyle(RoundedBorderTextFieldStyle()) - } + }.textFieldStyle(RoundedBorderTextFieldStyle()) } var userNamePasswordAndAPIUrlView: some View { @@ -126,6 +140,12 @@ struct AddAccountView: View { }.textFieldStyle(RoundedBorderTextFieldStyle()) } + var oAuthView: some View { + Group { + Text("Click Authenticate") + }.textFieldStyle(RoundedBorderTextFieldStyle()) + } + } struct AddAccountView_Previews: PreviewProvider { diff --git a/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Edit Account/EditAccountCredentialsModel.swift b/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Edit Account/EditAccountCredentialsModel.swift index 55dd2e323..d01103ecb 100644 --- a/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Edit Account/EditAccountCredentialsModel.swift +++ b/Multiplatform/macOS/Preferences/Preference Panes/Accounts/Account Preferences/Edit Account/EditAccountCredentialsModel.swift @@ -9,6 +9,7 @@ import Foundation import Account import Secrets +import RSCore class EditAccountCredentialsModel: ObservableObject { @@ -52,19 +53,17 @@ class EditAccountCredentialsModel: ObservableObject { case .feedbin: let credentials = try? account.retrieveCredentials(type: .basic) userName = credentials?.username ?? "" - password = credentials?.secret ?? "" case .feedWrangler: let credentials = try? account.retrieveCredentials(type: .feedWranglerBasic) userName = credentials?.username ?? "" - password = credentials?.secret ?? "" + case .feedly: + return case .freshRSS: let credentials = try? account.retrieveCredentials(type: .readerBasic) userName = credentials?.username ?? "" - password = credentials?.secret ?? "" case .newsBlur: let credentials = try? account.retrieveCredentials(type: .newsBlurBasic) userName = credentials?.username ?? "" - password = credentials?.secret ?? "" default: return } @@ -160,7 +159,11 @@ extension EditAccountCredentialsModel { } func updateFeedly(_ account: Account) { - + accountIsUpdatingCredentials = true + let updateAccount = OAuthAccountAuthorizationOperation(accountType: .feedly) + updateAccount.delegate = self + updateAccount.presentationAnchor = NSApplication.shared.windows.last + MainThreadOperationQueue.shared.add(updateAccount) } func updateFreshRSS(_ account: Account) { @@ -251,12 +254,23 @@ extension EditAccountCredentialsModel { } -// MARK:- Retrieve Credentials -extension EditAccountCredentialsModel { - - - - - +// MARK:- OAuthAccountAuthorizationOperationDelegate +extension EditAccountCredentialsModel: OAuthAccountAuthorizationOperationDelegate { + func oauthAccountAuthorizationOperation(_ operation: OAuthAccountAuthorizationOperation, didCreate account: Account) { + accountIsUpdatingCredentials = false + accountCredentialsWereUpdated = true + account.refreshAll { [weak self] result in + switch result { + case .success: + break + case .failure(let error): + self?.error = .other(error: error) + } + } + } + func oauthAccountAuthorizationOperation(_ operation: OAuthAccountAuthorizationOperation, didFailWith error: Error) { + accountIsUpdatingCredentials = false + self.error = .other(error: error) + } }