Add Update Credetials button to the error dialog when a Feedbin credentials error happens. Issue #1441

This commit is contained in:
Maurice Parker 2020-01-16 13:50:30 -07:00
parent 61b788a1de
commit 4f36ec3b11
5 changed files with 98 additions and 6 deletions

View File

@ -16,6 +16,23 @@ public enum AccountError: LocalizedError {
case opmlImportInProgress case opmlImportInProgress
case wrappedError(error: Error, account: Account) case wrappedError(error: Error, account: Account)
public var acount: Account? {
if case .wrappedError(_, let account) = self {
return account
} else {
return nil
}
}
public var isCredentialsError: Bool {
if case .wrappedError(let error, _) = self {
if case TransportError.httpError(let status) = error {
return isCredentialsError(status: status)
}
}
return false
}
public var errorDescription: String? { public var errorDescription: String? {
switch self { switch self {
case .createErrorNotFound: case .createErrorNotFound:
@ -27,7 +44,7 @@ public enum AccountError: LocalizedError {
case .wrappedError(let error, let account): case .wrappedError(let error, let account):
switch error { switch error {
case TransportError.httpError(let status): case TransportError.httpError(let status):
if status == 401 || status == 403 { if isCredentialsError(status: status) {
let localizedText = NSLocalizedString("Your “%@” credentials are invalid or expired.", comment: "Invalid or expired") let localizedText = NSLocalizedString("Your “%@” credentials are invalid or expired.", comment: "Invalid or expired")
return NSString.localizedStringWithFormat(localizedText as NSString, account.nameForDisplay) as String return NSString.localizedStringWithFormat(localizedText as NSString, account.nameForDisplay) as String
} else { } else {
@ -48,7 +65,7 @@ public enum AccountError: LocalizedError {
case .wrappedError(let error, _): case .wrappedError(let error, _):
switch error { switch error {
case TransportError.httpError(let status): case TransportError.httpError(let status):
if status == 401 || status == 403 { if isCredentialsError(status: status) {
return NSLocalizedString("Please update your credentials for this account, or ensure that your account with this service is still valid.", comment: "Expired credentials") return NSLocalizedString("Please update your credentials for this account, or ensure that your account with this service is still valid.", comment: "Expired credentials")
} else { } else {
return NSLocalizedString("Please try again later.", comment: "Try later") return NSLocalizedString("Please try again later.", comment: "Try later")
@ -61,8 +78,19 @@ public enum AccountError: LocalizedError {
} }
} }
private func unknownError(_ error: Error, _ account: Account) -> String { }
// MARK: Private
private extension AccountError {
func unknownError(_ error: Error, _ account: Account) -> String {
let localizedText = NSLocalizedString("An error occurred while processing the “%@” account: %@", comment: "Unknown error") let localizedText = NSLocalizedString("An error occurred while processing the “%@” account: %@", comment: "Unknown error")
return NSString.localizedStringWithFormat(localizedText as NSString, account.nameForDisplay, error.localizedDescription) as String return NSString.localizedStringWithFormat(localizedText as NSString, account.nameForDisplay, error.localizedDescription) as String
} }
func isCredentialsError(status: Int) -> Bool {
return status == 401 || status == 403
}
} }

View File

@ -123,6 +123,7 @@
518B2EE82351B45600400001 /* NetNewsWire_iOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840D61952029031D009BC708 /* NetNewsWire_iOSTests.swift */; }; 518B2EE82351B45600400001 /* NetNewsWire_iOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840D61952029031D009BC708 /* NetNewsWire_iOSTests.swift */; };
518C3193237B00D9004D740F /* ArticleIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */; }; 518C3193237B00D9004D740F /* ArticleIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */; };
518C3194237B00DA004D740F /* ArticleIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */; }; 518C3194237B00DA004D740F /* ArticleIconSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5141E7552374A2890013FF27 /* ArticleIconSchemeHandler.swift */; };
518ED21D23D0F26000E0A862 /* UIViewController-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 518ED21C23D0F26000E0A862 /* UIViewController-Extensions.swift */; };
51934CCB230F599B006127BE /* InteractiveNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CC1230F5963006127BE /* InteractiveNavigationController.swift */; }; 51934CCB230F599B006127BE /* InteractiveNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CC1230F5963006127BE /* InteractiveNavigationController.swift */; };
51934CCE2310792F006127BE /* ActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCD2310792F006127BE /* ActivityManager.swift */; }; 51934CCE2310792F006127BE /* ActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCD2310792F006127BE /* ActivityManager.swift */; };
51938DF2231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; }; 51938DF2231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */; };
@ -1307,6 +1308,7 @@
5186A634235EF3A800C97195 /* VibrantLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VibrantLabel.swift; sourceTree = "<group>"; }; 5186A634235EF3A800C97195 /* VibrantLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VibrantLabel.swift; sourceTree = "<group>"; };
518B2ED22351B3DD00400001 /* NetNewsWire-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "NetNewsWire-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 518B2ED22351B3DD00400001 /* NetNewsWire-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "NetNewsWire-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
518B2EE92351B4C200400001 /* NetNewsWire_iOSTests_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSTests_target.xcconfig; sourceTree = "<group>"; }; 518B2EE92351B4C200400001 /* NetNewsWire_iOSTests_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_iOSTests_target.xcconfig; sourceTree = "<group>"; };
518ED21C23D0F26000E0A862 /* UIViewController-Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController-Extensions.swift"; sourceTree = "<group>"; };
51934CC1230F5963006127BE /* InteractiveNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveNavigationController.swift; sourceTree = "<group>"; }; 51934CC1230F5963006127BE /* InteractiveNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractiveNavigationController.swift; sourceTree = "<group>"; };
51934CCD2310792F006127BE /* ActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityManager.swift; sourceTree = "<group>"; }; 51934CCD2310792F006127BE /* ActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityManager.swift; sourceTree = "<group>"; };
51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchTimelineFeedDelegate.swift; sourceTree = "<group>"; }; 51938DF1231AFC660055A1A0 /* SearchTimelineFeedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchTimelineFeedDelegate.swift; sourceTree = "<group>"; };
@ -1889,13 +1891,14 @@
512363372369155100951F16 /* RoundedProgressView.swift */, 512363372369155100951F16 /* RoundedProgressView.swift */,
51C45250226506F400C03939 /* String-Extensions.swift */, 51C45250226506F400C03939 /* String-Extensions.swift */,
5108F6D723763094001ABC45 /* TickMarkSlider.swift */, 5108F6D723763094001ABC45 /* TickMarkSlider.swift */,
C5A6ED6C23C9B0C800AB6BE2 /* UIActivityViewController-Extensions.swift */,
51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */, 51F85BF82274AA7B00C787DC /* UIBarButtonItem-Extensions.swift */,
51F85BF622749FA100C787DC /* UIFont-Extensions.swift */, 51F85BF622749FA100C787DC /* UIFont-Extensions.swift */,
51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */, 51C4524E226506F400C03939 /* UIStoryboard-Extensions.swift */,
518ED21C23D0F26000E0A862 /* UIViewController-Extensions.swift */,
51FFF0C3235EE8E5002762AA /* VibrantButton.swift */, 51FFF0C3235EE8E5002762AA /* VibrantButton.swift */,
5186A634235EF3A800C97195 /* VibrantLabel.swift */, 5186A634235EF3A800C97195 /* VibrantLabel.swift */,
5F323808231DF9F000706F6B /* VibrantTableViewCell.swift */, 5F323808231DF9F000706F6B /* VibrantTableViewCell.swift */,
C5A6ED6C23C9B0C800AB6BE2 /* UIActivityViewController-Extensions.swift */,
); );
path = "UIKit Extensions"; path = "UIKit Extensions";
sourceTree = "<group>"; sourceTree = "<group>";
@ -3835,6 +3838,7 @@
51EF0F79227716380050506E /* ColorHash.swift in Sources */, 51EF0F79227716380050506E /* ColorHash.swift in Sources */,
5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */, 5183CCDA226E31A50010922C /* NonIntrinsicImageView.swift in Sources */,
B2B80778239C4C7000F191E0 /* RSImage-AppIcons.swift in Sources */, B2B80778239C4C7000F191E0 /* RSImage-AppIcons.swift in Sources */,
518ED21D23D0F26000E0A862 /* UIViewController-Extensions.swift in Sources */,
51A9A5F52380F6A60033AADF /* ModalNavigationController.swift in Sources */, 51A9A5F52380F6A60033AADF /* ModalNavigationController.swift in Sources */,
51EAED96231363EF00A9EEE3 /* NonIntrinsicButton.swift in Sources */, 51EAED96231363EF00A9EEE3 /* NonIntrinsicButton.swift in Sources */,
51C4527B2265091600C03939 /* MasterUnreadIndicatorView.swift in Sources */, 51C4527B2265091600C03939 /* MasterUnreadIndicatorView.swift in Sources */,

View File

@ -106,7 +106,9 @@ class ShareViewController: SLComposeServiceViewController, ShareFolderPickerCont
} }
if let urlString = url?.absoluteString, account!.hasWebFeed(withURL: urlString) { if let urlString = url?.absoluteString, account!.hasWebFeed(withURL: urlString) {
presentError(AccountError.createErrorAlreadySubscribed) let errorTitle = NSLocalizedString("Error", comment: "Error")
presentError(title: errorTitle, message: AccountError.createErrorAlreadySubscribed.localizedDescription)
self.extensionContext!.cancelRequest(withError: AccountError.createErrorAlreadySubscribed)
return return
} }

View File

@ -0,0 +1,58 @@
//
// UIViewController-Extensions.swift
// NetNewsWire-iOS
//
// Created by Maurice Parker on 1/16/20.
// Copyright © 2020 Ranchero Software. All rights reserved.
//
import UIKit
import RSCore
import Account
extension UIViewController {
func presentError(_ error: Error, dismiss: (() -> Void)? = nil) {
if let accountError = error as? AccountError, accountError.isCredentialsError {
presentAccountError(accountError, dismiss: dismiss)
} else {
let errorTitle = NSLocalizedString("Error", comment: "Error")
presentError(title: errorTitle, message: error.localizedDescription, dismiss: dismiss)
}
}
}
private extension UIViewController {
func presentAccountError(_ error: AccountError, dismiss: (() -> Void)? = nil) {
let title = NSLocalizedString("Account Error", comment: "Account Error")
let alertController = UIAlertController(title: title, message: error.localizedDescription, preferredStyle: .alert)
if error.acount?.type == .feedbin {
let credentialsTitle = NSLocalizedString("Update Credentials", comment: "Update Credentials")
let credentialsAction = UIAlertAction(title: credentialsTitle, style: .default) { [weak self] _ in
dismiss?()
let navController = UIStoryboard.account.instantiateViewController(withIdentifier: "FeedbinAccountNavigationViewController") as! UINavigationController
navController.modalPresentationStyle = .formSheet
let addViewController = navController.topViewController as! FeedbinAccountViewController
addViewController.account = error.acount
self?.present(navController, animated: true)
}
alertController.addAction(credentialsAction)
}
let dismissTitle = NSLocalizedString("OK", comment: "OK")
let dismissAction = UIAlertAction(title: dismissTitle, style: .default) { _ in
dismiss?()
}
alertController.addAction(dismissAction)
self.present(alertController, animated: true, completion: nil)
}
}

@ -1 +1 @@
Subproject commit 3a2d030e8237bdb6ebbd6c389358aaae34d2d3b0 Subproject commit 6359d586b370b12539cdf2b3766f138448e1dc97