Skip to content

Commit

Permalink
Add UnauthorizedError screen for invalid cloud access in Files app (#384
Browse files Browse the repository at this point in the history
)
  • Loading branch information
iammajid authored Oct 15, 2024
1 parent 87bda1b commit 483223f
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 3 deletions.
8 changes: 8 additions & 0 deletions Cryptomator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +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 /* 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 */
Expand Down Expand Up @@ -1041,6 +1043,8 @@
74F5DC1B26DCD2FB00AFE989 /* StoreObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreObserver.swift; sourceTree = "<group>"; };
74F5DC1E26DD036D00AFE989 /* StoreManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreManager.swift; sourceTree = "<group>"; };
74FC576025ADED030003ED27 /* VaultCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultCell.swift; sourceTree = "<group>"; };
B330CB442CB5735000C21E03 /* UnauthorizedErrorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnauthorizedErrorViewController.swift; sourceTree = "<group>"; };
B3D19A432CB937BF00CD18A5 /* FileProviderCoordinatorError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderCoordinatorError.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -1663,7 +1667,9 @@
4A9FCB0B251A02A3002A8B41 /* FileProviderExtensionUI.entitlements */,
4AA621EB249A6A8400A0BCBD /* Info.plist */,
4A6A521A268B7147006F7368 /* FileProviderCoordinator.swift */,
B3D19A432CB937BF00CD18A5 /* FileProviderCoordinatorError.swift */,
4A6A5218268B6D31006F7368 /* OnboardingViewController.swift */,
B330CB442CB5735000C21E03 /* UnauthorizedErrorViewController.swift */,
4A6A520C268B5EF7006F7368 /* RootViewController.swift */,
4A9BED65268F2D9C00721BAA /* UnlockVaultViewController.swift */,
4AFD8C0E269304A700F77BA6 /* UnlockVaultViewModel.swift */,
Expand Down Expand Up @@ -2670,6 +2676,8 @@
4A804082276952C300D7D999 /* FileProviderCoordinatorSnapshotMock.swift in Sources */,
4A9BED66268F2D9D00721BAA /* UnlockVaultViewController.swift in Sources */,
4A6A521B268B7147006F7368 /* FileProviderCoordinator.swift in Sources */,
B330CB452CB5735300C21E03 /* UnauthorizedErrorViewController.swift in Sources */,
B3D19A442CB937C700CD18A5 /* FileProviderCoordinatorError.swift in Sources */,
4A6A5219268B6D32006F7368 /* OnboardingViewController.swift in Sources */,
4AFD8C0F269304A700F77BA6 /* UnlockVaultViewModel.swift in Sources */,
);
Expand Down
18 changes: 15 additions & 3 deletions FileProviderExtensionUI/FileProviderCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ class FileProviderCoordinator: Coordinator {

func handleError(_ error: Error, for viewController: UIViewController) {
DDLogError("Error: \(error)")
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)
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)
}
}

func done() {
Expand All @@ -80,6 +84,12 @@ class FileProviderCoordinator: Coordinator {
navigationController.pushViewController(onboardingVC, animated: false)
}

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
Expand Down Expand Up @@ -134,6 +144,8 @@ class FileProviderCoordinator: Coordinator {
switch error {
case CloudProviderError.noInternetConnection, LocalizedCloudProviderError.itemNotFound:
break
case LocalizedCloudProviderError.unauthorized:
throw FileProviderCoordinatorError.unauthorized(vaultName: domain.displayName)
default:
throw error
}
Expand Down
13 changes: 13 additions & 0 deletions FileProviderExtensionUI/FileProviderCoordinatorError.swift
Original file line number Diff line number Diff line change
@@ -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)
}
81 changes: 81 additions & 0 deletions FileProviderExtensionUI/UnauthorizedErrorViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// UnauthorizedErrorViewController.swift
// Cryptomator
//
// Created by Majid Achhoud on 08.10.24.
// Copyright © 2024 Skymatic GmbH. All rights reserved.
//

import CryptomatorCommonCore
import UIKit

class UnauthorizedErrorViewController: 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 UnauthorizedErrorHeaderView(vaultName: vaultName)
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
coordinator?.openCryptomatorApp()
}
}

private class UnauthorizedErrorHeaderView: LargeHeaderFooterView {
init(vaultName: String) {
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.unauthorized.text"), vaultName)

super.init(image: symbolImage, infoText: infoText)
}
}
1 change: 1 addition & 0 deletions SharedResources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -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.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.";
Expand Down

0 comments on commit 483223f

Please sign in to comment.