diff --git a/AmahiAnywhere/AmahiAnywhere.xcodeproj/project.pbxproj b/AmahiAnywhere/AmahiAnywhere.xcodeproj/project.pbxproj index 0097eb7938f..24a86064639 100644 --- a/AmahiAnywhere/AmahiAnywhere.xcodeproj/project.pbxproj +++ b/AmahiAnywhere/AmahiAnywhere.xcodeproj/project.pbxproj @@ -70,6 +70,8 @@ 46657183205085FC000E0D45 /* FilesPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46657182205085FC000E0D45 /* FilesPresenter.swift */; }; 46CB896B204FB0FC0031151F /* SharesPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46CB896A204FB0FC0031151F /* SharesPresenter.swift */; }; 46F87397204CC69500F1AF37 /* Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F87396204CC69500F1AF37 /* Server.swift */; }; + 7215CACF24E55B230001CEF4 /* SettingsBiometricTVCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7215CACE24E55B230001CEF4 /* SettingsBiometricTVCell.swift */; }; + 7241C6E124E5B7A700415406 /* SettingsBiometricTVCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7241C6E024E5B7A700415406 /* SettingsBiometricTVCell.xib */; }; 7253F21824BDA89F0094C385 /* AudioThumbnailCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7253F21624BDA89F0094C385 /* AudioThumbnailCollectionCell.swift */; }; 7253F21924BDA89F0094C385 /* AudioThumbnailCollectionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7253F21724BDA89F0094C385 /* AudioThumbnailCollectionCell.xib */; }; 7253F21B24BDAF890094C385 /* AudioPlayerViewController+CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7253F21A24BDAF890094C385 /* AudioPlayerViewController+CollectionView.swift */; }; @@ -215,6 +217,8 @@ 46F87396204CC69500F1AF37 /* Server.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Server.swift; sourceTree = ""; }; 499AAFCDBDAB4C05C7264992 /* Pods-AmahiAnywhere.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AmahiAnywhere.release.xcconfig"; path = "Pods/Target Support Files/Pods-AmahiAnywhere/Pods-AmahiAnywhere.release.xcconfig"; sourceTree = ""; }; 665E1C7EF1F0DEBF3A9809B0 /* Pods-AmahiAnywhere.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AmahiAnywhere.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AmahiAnywhere/Pods-AmahiAnywhere.debug.xcconfig"; sourceTree = ""; }; + 7215CACE24E55B230001CEF4 /* SettingsBiometricTVCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsBiometricTVCell.swift; sourceTree = ""; }; + 7241C6E024E5B7A700415406 /* SettingsBiometricTVCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsBiometricTVCell.xib; sourceTree = ""; }; 7253F21624BDA89F0094C385 /* AudioThumbnailCollectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioThumbnailCollectionCell.swift; sourceTree = ""; }; 7253F21724BDA89F0094C385 /* AudioThumbnailCollectionCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AudioThumbnailCollectionCell.xib; sourceTree = ""; }; 7253F21A24BDAF890094C385 /* AudioPlayerViewController+CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AudioPlayerViewController+CollectionView.swift"; sourceTree = ""; }; @@ -650,6 +654,7 @@ C8DA5B2120D5E0C600F5A527 /* Cells */ = { isa = PBXGroup; children = ( + 7215CACE24E55B230001CEF4 /* SettingsBiometricTVCell.swift */, 3BCAFBA022C537C10044057E /* DownloadsListCollectionCell.swift */, 3BCAFBA222C537DE0044057E /* DownloadsGridCollectionCell.swift */, 3BCAFBA422C5385D0044057E /* DownloadsBaseCollectionCell.swift */, @@ -666,6 +671,7 @@ 72BDA8B424A9ED6900B4469E /* QueueItemTableViewCell.xib */, 7253F21624BDA89F0094C385 /* AudioThumbnailCollectionCell.swift */, 7253F21724BDA89F0094C385 /* AudioThumbnailCollectionCell.xib */, + 7241C6E024E5B7A700415406 /* SettingsBiometricTVCell.xib */, ); path = Cells; sourceTree = ""; @@ -792,6 +798,7 @@ FB71BEA2201CB2FC0005492C /* LaunchScreen.storyboard in Resources */, FB71BE9F201CB2FC0005492C /* Assets.xcassets in Resources */, 72BDA8B624A9ED6900B4469E /* QueueItemTableViewCell.xib in Resources */, + 7241C6E124E5B7A700415406 /* SettingsBiometricTVCell.xib in Resources */, 3B24FE1822970B6B0044721D /* WalkthroughCell.xib in Resources */, 3B24FE162297086A0044721D /* WalkthroughAmahiCell.xib in Resources */, FB71BE9D201CB2FC0005492C /* Main.storyboard in Resources */, @@ -943,6 +950,7 @@ C8DA5B1820D5D7EA00F5A527 /* Download.swift in Sources */, 3B2805E62312DE930022ED48 /* RecentFilesViewController+CollectionView.swift in Sources */, 8A67FC2B22666F81005A5038 /* OfflineFile+MimeType.swift in Sources */, + 7215CACF24E55B230001CEF4 /* SettingsBiometricTVCell.swift in Sources */, 80F3FDC7206C0D4D0061CD51 /* ConnectionViewController.swift in Sources */, 3B1B35A423080E710058B1D8 /* UINavigationItem.swift in Sources */, 3B2805EC2312DFFF0022ED48 /* RecentFilesViewController+Remote.swift in Sources */, diff --git a/AmahiAnywhere/AmahiAnywhere/AppDelegate.swift b/AmahiAnywhere/AmahiAnywhere/AppDelegate.swift index a75dc747d48..babb4995578 100644 --- a/AmahiAnywhere/AmahiAnywhere/AppDelegate.swift +++ b/AmahiAnywhere/AmahiAnywhere/AppDelegate.swift @@ -95,6 +95,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { let mainStoryboard: UIStoryboard = UIStoryboard(name: StoryBoardIdentifiers.main, bundle: nil) var initialViewController: UIViewController? = nil + LocalStorage.shared.persist(bool: false, for: PersistenceIdentifiers.overrideBiometric) + if LocalStorage.shared.contains(key: PersistenceIdentifiers.accessToken) { if useCastContainerViewController { diff --git a/AmahiAnywhere/AmahiAnywhere/Cells/SettingsBiometricTVCell.swift b/AmahiAnywhere/AmahiAnywhere/Cells/SettingsBiometricTVCell.swift new file mode 100644 index 00000000000..d6dbb7035d5 --- /dev/null +++ b/AmahiAnywhere/AmahiAnywhere/Cells/SettingsBiometricTVCell.swift @@ -0,0 +1,30 @@ +// +// SettingsBiometricTVCellTableViewCell.swift +// AmahiAnywhere +// +// Created by Shresth Pratap Singh on 13/08/20. +// Copyright © 2020 Amahi. All rights reserved. +// + +import UIKit + +class SettingsBiometricTVCell: UITableViewCell { + + @IBOutlet weak var toggleSwitch: UISwitch! + @IBOutlet weak var titleLabel:UILabel! + weak var delegate: SettingsViewController? + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + @IBAction func toggleAction(_ sender: Any) { + if toggleSwitch.isOn{ + delegate?.turnOnBiometric() + }else{ + delegate?.turnOffBiometric() + } + } + +} diff --git a/AmahiAnywhere/AmahiAnywhere/Cells/SettingsBiometricTVCell.xib b/AmahiAnywhere/AmahiAnywhere/Cells/SettingsBiometricTVCell.xib new file mode 100644 index 00000000000..980c2ae5653 --- /dev/null +++ b/AmahiAnywhere/AmahiAnywhere/Cells/SettingsBiometricTVCell.xib @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AmahiAnywhere/AmahiAnywhere/Data/Local/LocalStorage.swift b/AmahiAnywhere/AmahiAnywhere/Data/Local/LocalStorage.swift index 3337ffadd6c..65e9d1813e3 100644 --- a/AmahiAnywhere/AmahiAnywhere/Data/Local/LocalStorage.swift +++ b/AmahiAnywhere/AmahiAnywhere/Data/Local/LocalStorage.swift @@ -21,12 +21,20 @@ final class LocalStorage: NSObject { UserDefaults.standard.setValue(string, forKey: key); UserDefaults.standard.synchronize(); } + + public func persist(bool: Bool, for key:String){ + UserDefaults.standard.set(bool, forKey: key) + } public func getString(key: String!) -> String? { UserDefaults.standard.synchronize() return UserDefaults.standard.value(forKey: key) as? String; } + public func getBool(for key: String) -> Bool{ + return UserDefaults.standard.bool(forKey: key) + } + public func contains(key: String!) -> Bool{ return UserDefaults.standard.object(forKey: key) != nil } @@ -37,8 +45,17 @@ final class LocalStorage: NSObject { } public func logout(_ complete: () -> Void){ + var permissionAsked = false + var biometricEnabled = false + //saving permision state for biometrics + if contains(key: PersistenceIdentifiers.biometricLoginPermissionAsked){ + permissionAsked = getBool(for: PersistenceIdentifiers.biometricLoginPermissionAsked) + biometricEnabled = getBool(for: PersistenceIdentifiers.biometricEnabled) + } clearAll() persistString(string: "completed", key: "walkthrough") + persist(bool: permissionAsked, for: PersistenceIdentifiers.biometricLoginPermissionAsked) + persist(bool: biometricEnabled , for: PersistenceIdentifiers.biometricEnabled) complete(); } diff --git a/AmahiAnywhere/AmahiAnywhere/Data/Local/PersistenceIdentifiers.swift b/AmahiAnywhere/AmahiAnywhere/Data/Local/PersistenceIdentifiers.swift index 3d0c77b9fa3..3dcd093de09 100644 --- a/AmahiAnywhere/AmahiAnywhere/Data/Local/PersistenceIdentifiers.swift +++ b/AmahiAnywhere/AmahiAnywhere/Data/Local/PersistenceIdentifiers.swift @@ -14,4 +14,7 @@ struct PersistenceIdentifiers { static let accessToken = "access_token" static let prefConnection = "pref_connection" + static let biometricLoginPermissionAsked = "biometric_login" + static let biometricEnabled = "biometric_enabled" + static let overrideBiometric = "biometric_override" } diff --git a/AmahiAnywhere/AmahiAnywhere/Data/Local/StringLiterals.swift b/AmahiAnywhere/AmahiAnywhere/Data/Local/StringLiterals.swift index acf68bdbeb5..6b94e0ae2cd 100644 --- a/AmahiAnywhere/AmahiAnywhere/Data/Local/StringLiterals.swift +++ b/AmahiAnywhere/AmahiAnywhere/Data/Local/StringLiterals.swift @@ -45,7 +45,7 @@ struct StringLiterals { static let emailErrorTitle = "Couldn't Send Mail" static let emailErrorMessage = "Your Device Couldn't Send Mail" static let disabled = "Disabled" - static let accountSectionSubItems = ["Sign Out"] + static let accountSectionSubItems = ["Sign Out","Login with face/touch ID"] static let settingsSectionSubItems = ["Connection", clearCacheTitle] static let aboutSectionSubItems = ["Version", "Tell a friend"] static let settingsSectionsTitle = ["Account", "Settings", "About"] diff --git a/AmahiAnywhere/AmahiAnywhere/Info.plist b/AmahiAnywhere/AmahiAnywhere/Info.plist index e1f3cb1f7c5..3055eef8c61 100644 --- a/AmahiAnywhere/AmahiAnywhere/Info.plist +++ b/AmahiAnywhere/AmahiAnywhere/Info.plist @@ -2,6 +2,8 @@ + NSFaceIDUsageDescription + Use FaceID to log in CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName diff --git a/AmahiAnywhere/AmahiAnywhere/Presentation/Cast/RootContainerViewController.swift b/AmahiAnywhere/AmahiAnywhere/Presentation/Cast/RootContainerViewController.swift index dae4d7839e2..633d82ae0f3 100644 --- a/AmahiAnywhere/AmahiAnywhere/Presentation/Cast/RootContainerViewController.swift +++ b/AmahiAnywhere/AmahiAnywhere/Presentation/Cast/RootContainerViewController.swift @@ -8,6 +8,7 @@ import GoogleCast import UIKit +import LocalAuthentication let kCastControlBarsAnimationDuration: TimeInterval = 0.20 @@ -25,6 +26,10 @@ class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewC } var overridenNavigationController: UINavigationController? + var biometricAuthOverride:Bool{ + return LocalStorage.shared.getBool(for: PersistenceIdentifiers.overrideBiometric) + } + private var isAskingForBiometric = false override var navigationController: UINavigationController? { get { return overridenNavigationController @@ -36,6 +41,17 @@ class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewC var miniMediaControlsItemEnabled = false + lazy var blurrEffect : UIVisualEffectView = { + var blur : UIBlurEffect? + if #available(iOS 13.0, *){ + blur = UIBlurEffect(style: .systemMaterial) + }else{ + blur = UIBlurEffect(style: .regular) + } + let effectsView = UIVisualEffectView(effect: blur) + return effectsView + }() + override func viewDidLoad() { super.viewDidLoad() let castContext = GCKCastContext.sharedInstance() @@ -44,6 +60,146 @@ class RootContainerViewController: UIViewController, GCKUIMiniMediaControlsViewC updateControlBarsVisibility() installViewController(miniMediaControlsViewController, inContainerView: _miniMediaControlsContainerView) + view.addSubview(blurrEffect) + blurrEffect.translatesAutoresizingMaskIntoConstraints = false + blurrEffect.setAnchors(top: view.topAnchor, leading: view.leadingAnchor, trailing: view.trailingAnchor, bottom: view.bottomAnchor, topConstant: 0, leadingConstant: 0, trailingConstant: 0, bottomConstant: 0) + NotificationCenter.default.addObserver(self, selector: #selector(applicationWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil) + } + + @objc func applicationWillEnterForeground(){ + if isAskingForBiometric{ + initiateBiometricAuth() + showBlurView() + } + } + + override func viewDidAppear(_ animated: Bool) { + initiateBiometricAuth() + } + + @objc func initiateBiometricAuth(){ + hideBlurrView() + let localStorage = LocalStorage.shared + if localStorage.contains(key: PersistenceIdentifiers.biometricLoginPermissionAsked){ + if localStorage.getBool(for: PersistenceIdentifiers.biometricLoginPermissionAsked) + && localStorage.getBool(for: PersistenceIdentifiers.biometricEnabled) && !biometricAuthOverride{ + showBlurView() + performBiometricAuth() + } + + if biometricAuthOverride == true{ + localStorage.persist(bool: false, for: PersistenceIdentifiers.overrideBiometric) + hideBlurrView() + } + }else{ + isAskingForBiometric = true + showBlurView() + let biometricAlert = UIAlertController(title: "Use Biometrics for Login?", message: "You can turn this off any time in app settings", preferredStyle: .alert) + biometricAlert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (_) in + localStorage.persist(bool: true, for: PersistenceIdentifiers.biometricEnabled) + self.performBiometricAuth() + })) + biometricAlert.addAction(UIAlertAction(title: "No", style: .default, handler: { (_) in + localStorage.persist(bool: false, for: PersistenceIdentifiers.biometricEnabled) + DispatchQueue.main.async { + self.hideBlurrView() + } + })) + present(biometricAlert, animated: true) { + localStorage.persist(bool: true, for: PersistenceIdentifiers.biometricLoginPermissionAsked) + } + } + } + + func performBiometricAuth(){ + isAskingForBiometric = true + let context = LAContext() + var error:NSError? + if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error){ + context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "Please identify yourself!") { (success, evaluationError) in + DispatchQueue.main.async { + self.isAskingForBiometric = false + if success{ + AmahiLogger.log("Biometric Succesfully verified") + self.hideBlurrView() + }else{ + AmahiLogger.log(error?.localizedDescription) + if let error = evaluationError as? LAError { + print("\(error.code.rawValue): Shresth LAError") + switch error.code { + case .authenticationFailed: + let alert = UIAlertController(title: "Failed to authenticate user", message: "Too many unsuccessful attempts! Please login again.", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in + LocalStorage.shared.logout{} + LocalStorage.shared.persist(bool: true, for: PersistenceIdentifiers.overrideBiometric) + self.signOut() + })) + self.present(alert, animated: true, completion: nil) + case .passcodeNotSet: + let alert = UIAlertController(title: "Passcode not set", message: "Please set a lockscreen passcode to login using Passcode", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in + LocalStorage.shared.logout{} + LocalStorage.shared.persist(bool: true, for: PersistenceIdentifiers.overrideBiometric) + self.signOut() + })) + self.present(alert, animated: true, completion: nil) + default: + LocalStorage.shared.logout{} + LocalStorage.shared.persist(bool: true, for: PersistenceIdentifiers.overrideBiometric) + self.signOut() + } + } + } + } + } + }else{ + AmahiLogger.log(error?.localizedDescription ?? "Device is unable to configure biometric authorization") + if let laError = error as? LAError{ + var errorTitle = "Could not initiate biometric Authentication" + var errorDescription = "Please check your biometric/passcode setup in device settings and retry again." + switch laError.errorCode { + case LAError.Code.biometryNotEnrolled.rawValue: + errorTitle = "Biometry not available" + errorDescription = "Please enroll your touch/face ID in device settings" + case LAError.Code.passcodeNotSet.rawValue: + errorTitle = "Could not initiate biometric authentication" + errorDescription = "Please set a lockscreen passcode." + default: + break + } + let alert = UIAlertController(title: errorTitle, message: errorDescription, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "login with username/email", style: .default, handler: { (_) in + LocalStorage.shared.logout{} + LocalStorage.shared.persist(bool: true, for: PersistenceIdentifiers.overrideBiometric) + self.signOut() + })) + present(alert, animated: true, completion: nil) + } + } + } + + func showBlurView(){ + view.bringSubviewToFront(blurrEffect) + UIView.animate(withDuration: 0.5,animations: { + self.blurrEffect.alpha = 1 + }) + } + + func hideBlurrView(){ + UIView.animate(withDuration: 0.5, animations: { + self.blurrEffect.alpha = 0 + }) + } + + func signOut() { + self.dismiss(animated: false, completion: nil) + let loginVc = self.viewController(viewControllerClass: LoginViewController.self, from: StoryBoardIdentifiers.main) + if let appDelegate = UIApplication.shared.delegate as? AppDelegate, let currentWindow = appDelegate.window{ + UIView.transition(with: currentWindow, duration: 0.3, options: .transitionFlipFromRight, animations: { + currentWindow.rootViewController = loginVc + currentWindow.makeKeyAndVisible() + }, completion: nil) + } } override var preferredStatusBarStyle: UIStatusBarStyle { diff --git a/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController+TableViewDataSource.swift b/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController+TableViewDataSource.swift index ca0f1113293..1c9623b8cbb 100644 --- a/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController+TableViewDataSource.swift +++ b/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController+TableViewDataSource.swift @@ -55,20 +55,55 @@ extension SettingsViewController { } cell.detailTextLabel?.text = sizeString } - }else if section == 2 && row == 0{ - cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.settingsCellRightDetail, for: indexPath) - cell.textLabel?.text = settingItems[section][row] - formatCell(cell: &cell) - if let versionNumber = Bundle.main.object(forInfoDictionaryKey: StringLiterals.versionNumberDictionaryKey) as! String? { - cell.detailTextLabel?.text = "v\(versionNumber)" + cell.backgroundColor = .clear + cell.contentView.backgroundColor = .clear + return cell + }else if section == 2 { + if row == 0{ + cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.settingsCellRightDetail, for: indexPath) + cell.textLabel?.text = settingItems[section][row] + formatCell(cell: &cell) + if let versionNumber = Bundle.main.object(forInfoDictionaryKey: StringLiterals.versionNumberDictionaryKey) as! String? { + cell.detailTextLabel?.text = "v\(versionNumber)" + } + cell.backgroundColor = .clear + cell.contentView.backgroundColor = .clear + return cell + } + else if row == 1{ + cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.settingsCell, for: indexPath) + cell.textLabel?.text = settingItems[section][row] + formatCell(cell: &cell) + cell.backgroundColor = .clear + cell.contentView.backgroundColor = .clear + return cell + }else{ + return UITableViewCell() + } + }else if section == 0{ + if row == 0{ + cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.settingsCell, for: indexPath) + cell.textLabel?.text = settingItems[section][row] + formatCell(cell: &cell) + return cell + }else if row == 1{ + guard let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.biometricCell) as? SettingsBiometricTVCell else{ + return UITableViewCell() + } + cell.titleLabel?.text = settingItems[section][row] + cell.delegate = self + cell.toggleSwitch.setOn(LocalStorage.shared.getBool(for: PersistenceIdentifiers.biometricEnabled), animated: false) + return cell + }else{ + return UITableViewCell() } }else{ - cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.settingsCell, for: indexPath) - cell.textLabel?.text = settingItems[section][row] - formatCell(cell: &cell) + return UITableViewCell() } - - return cell + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 55 } func formatCell(cell: inout UITableViewCell){ diff --git a/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController+TableViewDelegate.swift b/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController+TableViewDelegate.swift index 3d7e6964c3e..37bc255cf29 100644 --- a/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController+TableViewDelegate.swift +++ b/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController+TableViewDelegate.swift @@ -21,7 +21,9 @@ extension SettingsViewController { switch section { case 0: - handleSignOut() + if indexPath.row == 0{ + handleSignOut() + } break case 1: if row == 0 { diff --git a/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController.swift b/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController.swift index 5f70d886b57..9a940c5fbe1 100644 --- a/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController.swift +++ b/AmahiAnywhere/AmahiAnywhere/Presentation/Settings/SettingsViewController.swift @@ -16,6 +16,7 @@ class SettingsViewController: BaseUITableViewController { super.viewDidLoad() tableView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0) tableView.sectionFooterHeight = 0 + tableView.register(UINib(nibName: "SettingsBiometricTVCell", bundle: nil), forCellReuseIdentifier: CellIdentifiers.biometricCell) if #available(iOS 13.0, *) { self.view.backgroundColor = UIColor.secondarySystemBackground } else { @@ -37,6 +38,14 @@ class SettingsViewController: BaseUITableViewController { return nil } + func turnOffBiometric(){ + LocalStorage.shared.persist(bool: false, for: PersistenceIdentifiers.biometricEnabled) + } + + func turnOnBiometric(){ + LocalStorage.shared.persist(bool: true, for: PersistenceIdentifiers.biometricEnabled) + } + internal func configureMailComposeViewController(recipient: String, subject: String, message: String) ->MFMailComposeViewController { diff --git a/AmahiAnywhere/AmahiAnywhere/Utils/StringIdentifiers.swift b/AmahiAnywhere/AmahiAnywhere/Utils/StringIdentifiers.swift index d32f85c2555..2617fe28d38 100644 --- a/AmahiAnywhere/AmahiAnywhere/Utils/StringIdentifiers.swift +++ b/AmahiAnywhere/AmahiAnywhere/Utils/StringIdentifiers.swift @@ -33,4 +33,5 @@ struct CellIdentifiers { static let settingsCellWithDetails = "settingsCellWithDetails" static let settingsCellRightDetail = "settingsCellRightDetail" static let serverCell = "serverCollectionViewCell" + static let biometricCell = "SettingsBiometricTVCell" }