From 58e8dc187dc109c50257fce6f8c987a4cb60c793 Mon Sep 17 00:00:00 2001 From: Majid Achhoud Date: Wed, 9 Oct 2024 15:21:30 +0200 Subject: [PATCH 1/5] Add Reauthentication screen for invalid cloud access in Files app --- Cryptomator.xcodeproj/project.pbxproj | 4 + .../FileProviderCoordinator.swift | 14 ++++ .../ReauthenticationViewController.swift | 82 +++++++++++++++++++ SharedResources/de.lproj/Localizable.strings | 1 + SharedResources/en.lproj/Localizable.strings | 1 + 5 files changed, 102 insertions(+) create mode 100644 FileProviderExtensionUI/ReauthenticationViewController.swift diff --git a/Cryptomator.xcodeproj/project.pbxproj b/Cryptomator.xcodeproj/project.pbxproj index 69493c602..c5efd93ca 100644 --- a/Cryptomator.xcodeproj/project.pbxproj +++ b/Cryptomator.xcodeproj/project.pbxproj @@ -434,6 +434,7 @@ 74F5DC1C26DCD2FB00AFE989 /* StoreObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F5DC1B26DCD2FB00AFE989 /* StoreObserver.swift */; }; 74F5DC1F26DD036D00AFE989 /* StoreManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F5DC1E26DD036D00AFE989 /* StoreManager.swift */; }; 74FC576125ADED030003ED27 /* VaultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FC576025ADED030003ED27 /* VaultCell.swift */; }; + B330CB452CB5735300C21E03 /* ReauthenticationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B330CB442CB5735000C21E03 /* ReauthenticationViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1041,6 +1042,7 @@ 74F5DC1B26DCD2FB00AFE989 /* StoreObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreObserver.swift; sourceTree = ""; }; 74F5DC1E26DD036D00AFE989 /* StoreManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreManager.swift; sourceTree = ""; }; 74FC576025ADED030003ED27 /* VaultCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultCell.swift; sourceTree = ""; }; + B330CB442CB5735000C21E03 /* ReauthenticationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReauthenticationViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1664,6 +1666,7 @@ 4AA621EB249A6A8400A0BCBD /* Info.plist */, 4A6A521A268B7147006F7368 /* FileProviderCoordinator.swift */, 4A6A5218268B6D31006F7368 /* OnboardingViewController.swift */, + B330CB442CB5735000C21E03 /* ReauthenticationViewController.swift */, 4A6A520C268B5EF7006F7368 /* RootViewController.swift */, 4A9BED65268F2D9C00721BAA /* UnlockVaultViewController.swift */, 4AFD8C0E269304A700F77BA6 /* UnlockVaultViewModel.swift */, @@ -2670,6 +2673,7 @@ 4A804082276952C300D7D999 /* FileProviderCoordinatorSnapshotMock.swift in Sources */, 4A9BED66268F2D9D00721BAA /* UnlockVaultViewController.swift in Sources */, 4A6A521B268B7147006F7368 /* FileProviderCoordinator.swift in Sources */, + B330CB452CB5735300C21E03 /* ReauthenticationViewController.swift in Sources */, 4A6A5219268B6D32006F7368 /* OnboardingViewController.swift in Sources */, 4AFD8C0F269304A700F77BA6 /* UnlockVaultViewModel.swift in Sources */, ); diff --git a/FileProviderExtensionUI/FileProviderCoordinator.swift b/FileProviderExtensionUI/FileProviderCoordinator.swift index 40bc0ff09..4988a6fed 100644 --- a/FileProviderExtensionUI/FileProviderCoordinator.swift +++ b/FileProviderExtensionUI/FileProviderCoordinator.swift @@ -16,6 +16,7 @@ import LocalAuthentication import UIKit class FileProviderCoordinator: Coordinator { + private var isReauthenticationInProgress = false lazy var childCoordinators = [Coordinator]() lazy var navigationController: UINavigationController = { let appearance = UINavigationBarAppearance() @@ -80,6 +81,12 @@ class FileProviderCoordinator: Coordinator { navigationController.pushViewController(onboardingVC, animated: false) } + func showReauthentication(vaultName: String) { + let reauthenticationVC = ReauthenticationViewController(vaultName: vaultName) + reauthenticationVC.coordinator = self + navigationController.pushViewController(reauthenticationVC, animated: true) + } + func openCryptomatorApp() { let url = URL(string: "cryptomator:")! extensionContext.open(url) { success in @@ -134,10 +141,17 @@ class FileProviderCoordinator: Coordinator { switch error { case CloudProviderError.noInternetConnection, LocalizedCloudProviderError.itemNotFound: break + case LocalizedCloudProviderError.unauthorized: + self.showReauthentication(vaultName: domain.displayName) + self.isReauthenticationInProgress = true + return default: throw error } }.then { + guard !self.isReauthenticationInProgress else { + return + } let cachedVault = try vaultCache.getCachedVault(withVaultUID: vaultUID) if let vaultConfigToken = cachedVault.vaultConfigToken { let unverifiedVaultConfig = try UnverifiedVaultConfig(token: vaultConfigToken) diff --git a/FileProviderExtensionUI/ReauthenticationViewController.swift b/FileProviderExtensionUI/ReauthenticationViewController.swift new file mode 100644 index 000000000..07b0a8b66 --- /dev/null +++ b/FileProviderExtensionUI/ReauthenticationViewController.swift @@ -0,0 +1,82 @@ +// +// ReauthenticationViewController.swift +// Cryptomator +// +// Created by Majid Achhoud on 08.10.24. +// Copyright © 2024 Skymatic GmbH. All rights reserved. +// + +import CryptomatorCommonCore +import UIKit + +class ReauthenticationViewController: UITableViewController { + weak var coordinator: FileProviderCoordinator? + private var vaultName: String + + private lazy var openCryptomatorCell: UITableViewCell = { + let cell = UITableViewCell() + cell.textLabel?.text = LocalizedString.getValue("fileProvider.onboarding.button.openCryptomator") + cell.textLabel?.textColor = .cryptomatorPrimary + return cell + }() + + init(vaultName: String) { + self.vaultName = vaultName + super.init(style: .insetGrouped) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + title = vaultName + let doneButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(done)) + navigationItem.rightBarButtonItem = doneButton + tableView.backgroundColor = .cryptomatorBackground + tableView.cellLayoutMarginsFollowReadableWidth = true + } + + @objc func done() { + coordinator?.userCancelled() + } + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + // MARK: - UITableViewDataSource + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 1 + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + return openCryptomatorCell + } + + // MARK: - UITableViewDelegate + + override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + return ReauthenticationHeaderView(vaultName: vaultName) + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + coordinator?.openCryptomatorApp() + } +} + +private class ReauthenticationHeaderView: LargeHeaderFooterView { + init(vaultName: String) { + let config = UIImage.SymbolConfiguration(pointSize: 100) + let symbolImage = UIImage(systemName: "exclamationmark.triangle.fill", withConfiguration: config)?.withTintColor(.systemYellow, renderingMode: .alwaysOriginal) + + let infoText = String(format: LocalizedString.getValue("fileprovider.error.reauthentication"), vaultName) + + super.init(image: symbolImage, infoText: infoText) + } +} + diff --git a/SharedResources/de.lproj/Localizable.strings b/SharedResources/de.lproj/Localizable.strings index 1bf251644..431781349 100644 --- a/SharedResources/de.lproj/Localizable.strings +++ b/SharedResources/de.lproj/Localizable.strings @@ -101,6 +101,7 @@ "fileProvider.error.biometricalAuthWrongPassword.message" = "Das für %@ gespeicherte Passwort ist falsch. Bitte versuche es erneut und gib dein Passwort ein, um %@ wieder zu aktivieren."; "fileProvider.error.defaultLock.title" = "Entsperren erforderlich"; "fileProvider.error.defaultLock.message" = "Um auf den Inhalt deines Tresors zuzugreifen und ihn anzuzeigen, muss dieser entsperrt werden."; +"fileprovider.error.reauthentication" = "Der Cloud-Zugriff auf Ihren Tresor \"%@\" muss neu authentifiziert werden. Öffnen Sie die Haupt-App, um dies zu tun."; "fileProvider.error.unlockButton" = "Entsperren"; "fileProvider.clearFileFromCache.title" = "Datei aus Cache löschen"; "fileProvider.clearFileFromCache.message" = "Dies entfernt nur die lokale Datei von deinem Gerät und löscht nicht die Datei in der Cloud."; diff --git a/SharedResources/en.lproj/Localizable.strings b/SharedResources/en.lproj/Localizable.strings index 5a1eb77f1..38e019532 100644 --- a/SharedResources/en.lproj/Localizable.strings +++ b/SharedResources/en.lproj/Localizable.strings @@ -101,6 +101,7 @@ "fileProvider.error.biometricalAuthWrongPassword.message" = "The password that has been saved for %@ is wrong. Please try again and enter your password to re-enable %@."; "fileProvider.error.defaultLock.title" = "Unlock Required"; "fileProvider.error.defaultLock.message" = "To access and show the contents of your vault, it has to be unlocked."; +"fileprovider.error.reauthentication" = "The cloud access of your vault \"%@\" needs to be re-authenticated. Open the main app to do so."; "fileProvider.error.unlockButton" = "Unlock"; "fileProvider.clearFileFromCache.title" = "Clear File from Cache"; "fileProvider.clearFileFromCache.message" = "This only removes the local file from your device and does not delete the file in the cloud."; From 99a45342ded1440b987cb13509dc435c3f832b25 Mon Sep 17 00:00:00 2001 From: Majid Achhoud Date: Fri, 11 Oct 2024 16:58:59 +0200 Subject: [PATCH 2/5] Cleaned up code and renamed class --- Cryptomator.xcodeproj/project.pbxproj | 12 ++++++++---- .../FileProviderCoordinator.swift | 18 ++++++------------ .../FileProviderCoordinatorError.swift | 13 +++++++++++++ ...t => UnauthorizedErrorViewController.swift} | 9 ++++----- SharedResources/de.lproj/Localizable.strings | 1 - SharedResources/en.lproj/Localizable.strings | 2 +- 6 files changed, 32 insertions(+), 23 deletions(-) create mode 100644 FileProviderExtensionUI/FileProviderCoordinatorError.swift rename FileProviderExtensionUI/{ReauthenticationViewController.swift => UnauthorizedErrorViewController.swift} (90%) diff --git a/Cryptomator.xcodeproj/project.pbxproj b/Cryptomator.xcodeproj/project.pbxproj index c5efd93ca..7dfbf7e15 100644 --- a/Cryptomator.xcodeproj/project.pbxproj +++ b/Cryptomator.xcodeproj/project.pbxproj @@ -434,7 +434,8 @@ 74F5DC1C26DCD2FB00AFE989 /* StoreObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F5DC1B26DCD2FB00AFE989 /* StoreObserver.swift */; }; 74F5DC1F26DD036D00AFE989 /* StoreManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F5DC1E26DD036D00AFE989 /* StoreManager.swift */; }; 74FC576125ADED030003ED27 /* VaultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FC576025ADED030003ED27 /* VaultCell.swift */; }; - B330CB452CB5735300C21E03 /* ReauthenticationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B330CB442CB5735000C21E03 /* ReauthenticationViewController.swift */; }; + B330CB452CB5735300C21E03 /* UnauthorizedErrorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B330CB442CB5735000C21E03 /* UnauthorizedErrorViewController.swift */; }; + B3D19A442CB937C700CD18A5 /* FileProviderCoordinatorError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3D19A432CB937BF00CD18A5 /* FileProviderCoordinatorError.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1042,7 +1043,8 @@ 74F5DC1B26DCD2FB00AFE989 /* StoreObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreObserver.swift; sourceTree = ""; }; 74F5DC1E26DD036D00AFE989 /* StoreManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreManager.swift; sourceTree = ""; }; 74FC576025ADED030003ED27 /* VaultCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultCell.swift; sourceTree = ""; }; - B330CB442CB5735000C21E03 /* ReauthenticationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReauthenticationViewController.swift; sourceTree = ""; }; + B330CB442CB5735000C21E03 /* UnauthorizedErrorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnauthorizedErrorViewController.swift; sourceTree = ""; }; + B3D19A432CB937BF00CD18A5 /* FileProviderCoordinatorError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderCoordinatorError.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1665,8 +1667,9 @@ 4A9FCB0B251A02A3002A8B41 /* FileProviderExtensionUI.entitlements */, 4AA621EB249A6A8400A0BCBD /* Info.plist */, 4A6A521A268B7147006F7368 /* FileProviderCoordinator.swift */, + B3D19A432CB937BF00CD18A5 /* FileProviderCoordinatorError.swift */, 4A6A5218268B6D31006F7368 /* OnboardingViewController.swift */, - B330CB442CB5735000C21E03 /* ReauthenticationViewController.swift */, + B330CB442CB5735000C21E03 /* UnauthorizedErrorViewController.swift */, 4A6A520C268B5EF7006F7368 /* RootViewController.swift */, 4A9BED65268F2D9C00721BAA /* UnlockVaultViewController.swift */, 4AFD8C0E269304A700F77BA6 /* UnlockVaultViewModel.swift */, @@ -2673,7 +2676,8 @@ 4A804082276952C300D7D999 /* FileProviderCoordinatorSnapshotMock.swift in Sources */, 4A9BED66268F2D9D00721BAA /* UnlockVaultViewController.swift in Sources */, 4A6A521B268B7147006F7368 /* FileProviderCoordinator.swift in Sources */, - B330CB452CB5735300C21E03 /* ReauthenticationViewController.swift in Sources */, + B330CB452CB5735300C21E03 /* UnauthorizedErrorViewController.swift in Sources */, + B3D19A442CB937C700CD18A5 /* FileProviderCoordinatorError.swift in Sources */, 4A6A5219268B6D32006F7368 /* OnboardingViewController.swift in Sources */, 4AFD8C0F269304A700F77BA6 /* UnlockVaultViewModel.swift in Sources */, ); diff --git a/FileProviderExtensionUI/FileProviderCoordinator.swift b/FileProviderExtensionUI/FileProviderCoordinator.swift index 4988a6fed..be12ae85e 100644 --- a/FileProviderExtensionUI/FileProviderCoordinator.swift +++ b/FileProviderExtensionUI/FileProviderCoordinator.swift @@ -16,7 +16,6 @@ import LocalAuthentication import UIKit class FileProviderCoordinator: Coordinator { - private var isReauthenticationInProgress = false lazy var childCoordinators = [Coordinator]() lazy var navigationController: UINavigationController = { let appearance = UINavigationBarAppearance() @@ -81,12 +80,12 @@ class FileProviderCoordinator: Coordinator { navigationController.pushViewController(onboardingVC, animated: false) } - func showReauthentication(vaultName: String) { - let reauthenticationVC = ReauthenticationViewController(vaultName: vaultName) - reauthenticationVC.coordinator = self - navigationController.pushViewController(reauthenticationVC, animated: true) + func showUnauthorizedError(vaultName: String) { + let unauthorizedErrorVC = UnauthorizedErrorViewController(vaultName: vaultName) + unauthorizedErrorVC.coordinator = self + navigationController.pushViewController(unauthorizedErrorVC, animated: true) } - + func openCryptomatorApp() { let url = URL(string: "cryptomator:")! extensionContext.open(url) { success in @@ -142,16 +141,11 @@ class FileProviderCoordinator: Coordinator { case CloudProviderError.noInternetConnection, LocalizedCloudProviderError.itemNotFound: break case LocalizedCloudProviderError.unauthorized: - self.showReauthentication(vaultName: domain.displayName) - self.isReauthenticationInProgress = true - return + throw FileProviderCoordinatorError.unauthorized(vaultName: domain.displayName) default: throw error } }.then { - guard !self.isReauthenticationInProgress else { - return - } let cachedVault = try vaultCache.getCachedVault(withVaultUID: vaultUID) if let vaultConfigToken = cachedVault.vaultConfigToken { let unverifiedVaultConfig = try UnverifiedVaultConfig(token: vaultConfigToken) diff --git a/FileProviderExtensionUI/FileProviderCoordinatorError.swift b/FileProviderExtensionUI/FileProviderCoordinatorError.swift new file mode 100644 index 000000000..9c097d2d0 --- /dev/null +++ b/FileProviderExtensionUI/FileProviderCoordinatorError.swift @@ -0,0 +1,13 @@ +// +// FileProviderCoordinatorError.swift +// Cryptomator +// +// Created by Majid Achhoud on 11.10.24. +// Copyright © 2024 Skymatic GmbH. All rights reserved. +// + +import Foundation + +public enum FileProviderCoordinatorError: Error { + case unauthorized(vaultName: String) +} diff --git a/FileProviderExtensionUI/ReauthenticationViewController.swift b/FileProviderExtensionUI/UnauthorizedErrorViewController.swift similarity index 90% rename from FileProviderExtensionUI/ReauthenticationViewController.swift rename to FileProviderExtensionUI/UnauthorizedErrorViewController.swift index 07b0a8b66..446398c03 100644 --- a/FileProviderExtensionUI/ReauthenticationViewController.swift +++ b/FileProviderExtensionUI/UnauthorizedErrorViewController.swift @@ -1,5 +1,5 @@ // -// ReauthenticationViewController.swift +// UnauthorizedErrorViewController.swift // Cryptomator // // Created by Majid Achhoud on 08.10.24. @@ -9,7 +9,7 @@ import CryptomatorCommonCore import UIKit -class ReauthenticationViewController: UITableViewController { +class UnauthorizedErrorViewController: UITableViewController { weak var coordinator: FileProviderCoordinator? private var vaultName: String @@ -60,7 +60,7 @@ class ReauthenticationViewController: UITableViewController { // MARK: - UITableViewDelegate override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - return ReauthenticationHeaderView(vaultName: vaultName) + return UnauthorizedErrorHeaderView(vaultName: vaultName) } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { @@ -69,7 +69,7 @@ class ReauthenticationViewController: UITableViewController { } } -private class ReauthenticationHeaderView: LargeHeaderFooterView { +private class UnauthorizedErrorHeaderView: LargeHeaderFooterView { init(vaultName: String) { let config = UIImage.SymbolConfiguration(pointSize: 100) let symbolImage = UIImage(systemName: "exclamationmark.triangle.fill", withConfiguration: config)?.withTintColor(.systemYellow, renderingMode: .alwaysOriginal) @@ -79,4 +79,3 @@ private class ReauthenticationHeaderView: LargeHeaderFooterView { super.init(image: symbolImage, infoText: infoText) } } - diff --git a/SharedResources/de.lproj/Localizable.strings b/SharedResources/de.lproj/Localizable.strings index 431781349..1bf251644 100644 --- a/SharedResources/de.lproj/Localizable.strings +++ b/SharedResources/de.lproj/Localizable.strings @@ -101,7 +101,6 @@ "fileProvider.error.biometricalAuthWrongPassword.message" = "Das für %@ gespeicherte Passwort ist falsch. Bitte versuche es erneut und gib dein Passwort ein, um %@ wieder zu aktivieren."; "fileProvider.error.defaultLock.title" = "Entsperren erforderlich"; "fileProvider.error.defaultLock.message" = "Um auf den Inhalt deines Tresors zuzugreifen und ihn anzuzeigen, muss dieser entsperrt werden."; -"fileprovider.error.reauthentication" = "Der Cloud-Zugriff auf Ihren Tresor \"%@\" muss neu authentifiziert werden. Öffnen Sie die Haupt-App, um dies zu tun."; "fileProvider.error.unlockButton" = "Entsperren"; "fileProvider.clearFileFromCache.title" = "Datei aus Cache löschen"; "fileProvider.clearFileFromCache.message" = "Dies entfernt nur die lokale Datei von deinem Gerät und löscht nicht die Datei in der Cloud."; diff --git a/SharedResources/en.lproj/Localizable.strings b/SharedResources/en.lproj/Localizable.strings index 38e019532..89df8001e 100644 --- a/SharedResources/en.lproj/Localizable.strings +++ b/SharedResources/en.lproj/Localizable.strings @@ -101,7 +101,7 @@ "fileProvider.error.biometricalAuthWrongPassword.message" = "The password that has been saved for %@ is wrong. Please try again and enter your password to re-enable %@."; "fileProvider.error.defaultLock.title" = "Unlock Required"; "fileProvider.error.defaultLock.message" = "To access and show the contents of your vault, it has to be unlocked."; -"fileprovider.error.reauthentication" = "The cloud access of your vault \"%@\" needs to be re-authenticated. Open the main app to do so."; +"fileprovider.error.reauthentication" = "Access to your vault \"%@\" was denied. Open the main app to check your connection and re-authenticate if needed."; "fileProvider.error.unlockButton" = "Unlock"; "fileProvider.clearFileFromCache.title" = "Clear File from Cache"; "fileProvider.clearFileFromCache.message" = "This only removes the local file from your device and does not delete the file in the cloud."; From f7821ec1c6a30d322a2f23696368c937d5888cc9 Mon Sep 17 00:00:00 2001 From: Majid Achhoud Date: Mon, 14 Oct 2024 16:17:41 +0200 Subject: [PATCH 3/5] Added specific error handling for unauthorized in FileProviderCoordinator --- FileProviderExtensionUI/FileProviderCoordinator.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/FileProviderExtensionUI/FileProviderCoordinator.swift b/FileProviderExtensionUI/FileProviderCoordinator.swift index be12ae85e..3ea188c03 100644 --- a/FileProviderExtensionUI/FileProviderCoordinator.swift +++ b/FileProviderExtensionUI/FileProviderCoordinator.swift @@ -198,6 +198,15 @@ class FileProviderCoordinator: Coordinator { guard let hostViewController = hostViewController else { return } + + if let fileProviderError = error as? FileProviderCoordinatorError { + switch fileProviderError { + case let .unauthorized(vaultName): + showUnauthorizedError(vaultName: vaultName) + return + } + } + handleError(error, for: hostViewController) } } From 0bfa725374156c1f5b041dc2202ab4598341f875 Mon Sep 17 00:00:00 2001 From: Majid Achhoud Date: Tue, 15 Oct 2024 09:30:13 +0200 Subject: [PATCH 4/5] Adjust icon size in UnauthorizedErrorHeaderView, refactor error handling and update localization strings --- .../FileProviderCoordinator.swift | 16 +++++++--------- .../UnauthorizedErrorViewController.swift | 4 ++-- SharedResources/en.lproj/Localizable.strings | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/FileProviderExtensionUI/FileProviderCoordinator.swift b/FileProviderExtensionUI/FileProviderCoordinator.swift index 3ea188c03..6d7ceb0f8 100644 --- a/FileProviderExtensionUI/FileProviderCoordinator.swift +++ b/FileProviderExtensionUI/FileProviderCoordinator.swift @@ -63,6 +63,13 @@ class FileProviderCoordinator: Coordinator { func handleError(_ error: Error, for viewController: UIViewController) { DDLogError("Error: \(error)") + if let fileProviderError = error as? FileProviderCoordinatorError { + switch fileProviderError { + case let .unauthorized(vaultName): + showUnauthorizedError(vaultName: vaultName) + return + } + } let alertController = UIAlertController(title: LocalizedString.getValue("common.alert.error.title"), message: error.localizedDescription, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: LocalizedString.getValue("common.button.ok"), style: .default)) viewController.present(alertController, animated: true) @@ -198,15 +205,6 @@ class FileProviderCoordinator: Coordinator { guard let hostViewController = hostViewController else { return } - - if let fileProviderError = error as? FileProviderCoordinatorError { - switch fileProviderError { - case let .unauthorized(vaultName): - showUnauthorizedError(vaultName: vaultName) - return - } - } - handleError(error, for: hostViewController) } } diff --git a/FileProviderExtensionUI/UnauthorizedErrorViewController.swift b/FileProviderExtensionUI/UnauthorizedErrorViewController.swift index 446398c03..10797c1dd 100644 --- a/FileProviderExtensionUI/UnauthorizedErrorViewController.swift +++ b/FileProviderExtensionUI/UnauthorizedErrorViewController.swift @@ -71,10 +71,10 @@ class UnauthorizedErrorViewController: UITableViewController { private class UnauthorizedErrorHeaderView: LargeHeaderFooterView { init(vaultName: String) { - let config = UIImage.SymbolConfiguration(pointSize: 100) + let config = UIImage.SymbolConfiguration(pointSize: 120) let symbolImage = UIImage(systemName: "exclamationmark.triangle.fill", withConfiguration: config)?.withTintColor(.systemYellow, renderingMode: .alwaysOriginal) - let infoText = String(format: LocalizedString.getValue("fileprovider.error.reauthentication"), vaultName) + let infoText = String(format: LocalizedString.getValue("fileprovider.error.unauthorized.text"), vaultName) super.init(image: symbolImage, infoText: infoText) } diff --git a/SharedResources/en.lproj/Localizable.strings b/SharedResources/en.lproj/Localizable.strings index 89df8001e..6445a8fd8 100644 --- a/SharedResources/en.lproj/Localizable.strings +++ b/SharedResources/en.lproj/Localizable.strings @@ -101,7 +101,7 @@ "fileProvider.error.biometricalAuthWrongPassword.message" = "The password that has been saved for %@ is wrong. Please try again and enter your password to re-enable %@."; "fileProvider.error.defaultLock.title" = "Unlock Required"; "fileProvider.error.defaultLock.message" = "To access and show the contents of your vault, it has to be unlocked."; -"fileprovider.error.reauthentication" = "Access to your vault \"%@\" was denied. Open the main app to check your connection and re-authenticate if needed."; +"fileprovider.error.unauthorized.text" = "Access to your vault \"%@\" was denied. Open the main app to check your connection and re-authenticate if needed."; "fileProvider.error.unlockButton" = "Unlock"; "fileProvider.clearFileFromCache.title" = "Clear File from Cache"; "fileProvider.clearFileFromCache.message" = "This only removes the local file from your device and does not delete the file in the cloud."; From b1e02eb0c187e3bac3d64817e7672a3f1e98f9aa Mon Sep 17 00:00:00 2001 From: Majid Achhoud Date: Tue, 15 Oct 2024 12:11:34 +0200 Subject: [PATCH 5/5] Simplify error handling in FileProviderCoordinator --- .../FileProviderCoordinator.swift | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/FileProviderExtensionUI/FileProviderCoordinator.swift b/FileProviderExtensionUI/FileProviderCoordinator.swift index 6d7ceb0f8..eb74e39f5 100644 --- a/FileProviderExtensionUI/FileProviderCoordinator.swift +++ b/FileProviderExtensionUI/FileProviderCoordinator.swift @@ -63,16 +63,13 @@ class FileProviderCoordinator: Coordinator { func handleError(_ error: Error, for viewController: UIViewController) { DDLogError("Error: \(error)") - if let fileProviderError = error as? FileProviderCoordinatorError { - switch fileProviderError { - case let .unauthorized(vaultName): - showUnauthorizedError(vaultName: vaultName) - return - } + if let fileProviderError = error as? FileProviderCoordinatorError, case let .unauthorized(vaultName) = fileProviderError { + showUnauthorizedError(vaultName: vaultName) + } else { + let alertController = UIAlertController(title: LocalizedString.getValue("common.alert.error.title"), message: error.localizedDescription, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: LocalizedString.getValue("common.button.ok"), style: .default)) + viewController.present(alertController, animated: true) } - let alertController = UIAlertController(title: LocalizedString.getValue("common.alert.error.title"), message: error.localizedDescription, preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: LocalizedString.getValue("common.button.ok"), style: .default)) - viewController.present(alertController, animated: true) } func done() {