瀏覽代碼

Merge branch 'develop' into serverTrust

Marino Faggiana 3 年之前
父節點
當前提交
fd0c571e98
共有 89 個文件被更改,包括 237 次插入109 次删除
  1. 4 0
      Nextcloud.xcodeproj/project.pbxproj
  2. 2 2
      Nextcloud.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
  3. 84 33
      iOSClient/AppDelegate.swift
  4. 28 0
      iOSClient/Login/NCLoginNavigationController.swift
  5. 65 69
      iOSClient/Notification/NCNotification.swift
  6. 22 4
      iOSClient/Settings/NCSettings.m
  7. 二進制
      iOSClient/Supporting Files/af.lproj/Localizable.strings
  8. 二進制
      iOSClient/Supporting Files/ar.lproj/Localizable.strings
  9. 二進制
      iOSClient/Supporting Files/ast.lproj/Localizable.strings
  10. 二進制
      iOSClient/Supporting Files/az.lproj/Localizable.strings
  11. 二進制
      iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings
  12. 二進制
      iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings
  13. 二進制
      iOSClient/Supporting Files/br.lproj/Localizable.strings
  14. 二進制
      iOSClient/Supporting Files/bs.lproj/Localizable.strings
  15. 二進制
      iOSClient/Supporting Files/ca.lproj/Localizable.strings
  16. 二進制
      iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
  17. 二進制
      iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings
  18. 二進制
      iOSClient/Supporting Files/da.lproj/Localizable.strings
  19. 二進制
      iOSClient/Supporting Files/de.lproj/Localizable.strings
  20. 二進制
      iOSClient/Supporting Files/el.lproj/Localizable.strings
  21. 二進制
      iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
  22. 2 1
      iOSClient/Supporting Files/en.lproj/Localizable.strings
  23. 二進制
      iOSClient/Supporting Files/eo.lproj/Localizable.strings
  24. 二進制
      iOSClient/Supporting Files/es-419.lproj/Localizable.strings
  25. 二進制
      iOSClient/Supporting Files/es-AR.lproj/Localizable.strings
  26. 二進制
      iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
  27. 二進制
      iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
  28. 二進制
      iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
  29. 二進制
      iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
  30. 二進制
      iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
  31. 二進制
      iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
  32. 二進制
      iOSClient/Supporting Files/es-HN.lproj/Localizable.strings
  33. 二進制
      iOSClient/Supporting Files/es-MX.lproj/Localizable.strings
  34. 二進制
      iOSClient/Supporting Files/es-NI.lproj/Localizable.strings
  35. 二進制
      iOSClient/Supporting Files/es-PA.lproj/Localizable.strings
  36. 二進制
      iOSClient/Supporting Files/es-PE.lproj/Localizable.strings
  37. 二進制
      iOSClient/Supporting Files/es-PR.lproj/Localizable.strings
  38. 二進制
      iOSClient/Supporting Files/es-PY.lproj/Localizable.strings
  39. 二進制
      iOSClient/Supporting Files/es-SV.lproj/Localizable.strings
  40. 二進制
      iOSClient/Supporting Files/es-UY.lproj/Localizable.strings
  41. 二進制
      iOSClient/Supporting Files/es.lproj/Localizable.strings
  42. 二進制
      iOSClient/Supporting Files/et_EE.lproj/Localizable.strings
  43. 二進制
      iOSClient/Supporting Files/eu.lproj/Localizable.strings
  44. 二進制
      iOSClient/Supporting Files/fa.lproj/Localizable.strings
  45. 二進制
      iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings
  46. 二進制
      iOSClient/Supporting Files/fr.lproj/Localizable.strings
  47. 二進制
      iOSClient/Supporting Files/gl.lproj/Localizable.strings
  48. 二進制
      iOSClient/Supporting Files/he.lproj/Localizable.strings
  49. 二進制
      iOSClient/Supporting Files/hr.lproj/Localizable.strings
  50. 二進制
      iOSClient/Supporting Files/hu.lproj/Localizable.strings
  51. 二進制
      iOSClient/Supporting Files/ia.lproj/Localizable.strings
  52. 二進制
      iOSClient/Supporting Files/id.lproj/Localizable.strings
  53. 二進制
      iOSClient/Supporting Files/is.lproj/Localizable.strings
  54. 二進制
      iOSClient/Supporting Files/it.lproj/Localizable.strings
  55. 二進制
      iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings
  56. 二進制
      iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings
  57. 二進制
      iOSClient/Supporting Files/ko.lproj/Localizable.strings
  58. 二進制
      iOSClient/Supporting Files/lb.lproj/Localizable.strings
  59. 二進制
      iOSClient/Supporting Files/lo.lproj/Localizable.strings
  60. 二進制
      iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings
  61. 二進制
      iOSClient/Supporting Files/lv.lproj/Localizable.strings
  62. 二進制
      iOSClient/Supporting Files/mk.lproj/Localizable.strings
  63. 二進制
      iOSClient/Supporting Files/mn.lproj/Localizable.strings
  64. 二進制
      iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings
  65. 二進制
      iOSClient/Supporting Files/nl.lproj/Localizable.strings
  66. 二進制
      iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings
  67. 二進制
      iOSClient/Supporting Files/oc.lproj/Localizable.strings
  68. 二進制
      iOSClient/Supporting Files/pl.lproj/Localizable.strings
  69. 二進制
      iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings
  70. 二進制
      iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings
  71. 二進制
      iOSClient/Supporting Files/ro.lproj/Localizable.strings
  72. 二進制
      iOSClient/Supporting Files/ru.lproj/Localizable.strings
  73. 二進制
      iOSClient/Supporting Files/sc.lproj/Localizable.strings
  74. 二進制
      iOSClient/Supporting Files/si.lproj/Localizable.strings
  75. 二進制
      iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings
  76. 二進制
      iOSClient/Supporting Files/sl.lproj/Localizable.strings
  77. 二進制
      iOSClient/Supporting Files/sq.lproj/Localizable.strings
  78. 二進制
      iOSClient/Supporting Files/sr.lproj/Localizable.strings
  79. 二進制
      iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings
  80. 二進制
      iOSClient/Supporting Files/sv.lproj/Localizable.strings
  81. 二進制
      iOSClient/Supporting Files/th_TH.lproj/Localizable.strings
  82. 二進制
      iOSClient/Supporting Files/tr.lproj/Localizable.strings
  83. 二進制
      iOSClient/Supporting Files/uk.lproj/Localizable.strings
  84. 二進制
      iOSClient/Supporting Files/vi.lproj/Localizable.strings
  85. 二進制
      iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings
  86. 二進制
      iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings
  87. 二進制
      iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings
  88. 5 0
      iOSClient/Utility/CCUtility.h
  89. 25 0
      iOSClient/Utility/CCUtility.m

+ 4 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -128,6 +128,7 @@
 		F7362A1F220C853A005101B5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7362A1E220C853A005101B5 /* LaunchScreen.storyboard */; };
 		F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381EDA218218C9000B1560 /* NCOffline.swift */; };
 		F7381EE5218218C9000B1560 /* NCOffline.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7381EDE218218C9000B1560 /* NCOffline.storyboard */; };
+		F738D4902756740100CD1D38 /* NCLoginNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F738D48F2756740100CD1D38 /* NCLoginNavigationController.swift */; };
 		F738E8421F90FFD100F95C8E /* NCManageEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F738E8411F90FFD100F95C8E /* NCManageEndToEndEncryption.m */; };
 		F73ADD1C265546890069EA0D /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = F73ADD1B265546890069EA0D /* SwiftEntryKit */; };
 		F73ADD2126554F8E0069EA0D /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = F73ADD2026554F8E0069EA0D /* SwiftEntryKit */; };
@@ -550,6 +551,7 @@
 		F736B551234DCF57008A5C9F /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = "<group>"; };
 		F7381EDA218218C9000B1560 /* NCOffline.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOffline.swift; sourceTree = "<group>"; };
 		F7381EDE218218C9000B1560 /* NCOffline.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCOffline.storyboard; sourceTree = "<group>"; };
+		F738D48F2756740100CD1D38 /* NCLoginNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginNavigationController.swift; sourceTree = "<group>"; };
 		F738E8401F90FFD100F95C8E /* NCManageEndToEndEncryption.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCManageEndToEndEncryption.h; sourceTree = "<group>"; };
 		F738E8411F90FFD100F95C8E /* NCManageEndToEndEncryption.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCManageEndToEndEncryption.m; sourceTree = "<group>"; };
 		F73B42292476764F00A30FD3 /* NCNotification.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = NCNotification.storyboard; path = Notification/NCNotification.storyboard; sourceTree = "<group>"; };
@@ -1342,6 +1344,7 @@
 				F7DBC37B23325E01001A85BA /* NCAppConfigView.swift */,
 				F702F2F025EE5CDA008F8E80 /* NCLogin.storyboard */,
 				F702F2F625EE5CEC008F8E80 /* NCLogin.swift */,
+				F738D48F2756740100CD1D38 /* NCLoginNavigationController.swift */,
 				F745B252222D88AE00346520 /* NCLoginQRCode.swift */,
 				F7AE00F4230D5F9E007ACF8A /* NCLoginWeb.swift */,
 			);
@@ -2233,6 +2236,7 @@
 				F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */,
 				F769454422E9F142000A798A /* NCShareUserMenuView.swift in Sources */,
 				F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */,
+				F738D4902756740100CD1D38 /* NCLoginNavigationController.swift in Sources */,
 				F77B0E981D118A16002130FE /* CCManageAccount.m in Sources */,
 				F77EFC0C26D6751F00806ED6 /* NCShareQuickStatusMenu.swift in Sources */,
 				F702F30125EE5D2C008F8E80 /* NYMnemonic.m in Sources */,

+ 2 - 2
Nextcloud.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -113,9 +113,9 @@
         "package": "NCCommunication",
         "repositoryURL": "https://github.com/nextcloud/ios-communication-library/",
         "state": {
-          "branch": null,
+          "branch": "develop",
           "revision": "c8e3eac61a846775d570b1d252612a8d2d02930d",
-          "version": "0.99.3"
+          "version": null
         }
       },
       {

+ 84 - 33
iOSClient/AppDelegate.swift

@@ -64,6 +64,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     var shares: [tableShare] = []
     var timerErrorNetworking: Timer?
     
+    private var privacyProtectionWindow: UIWindow?
+    
     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
         
         let userAgent = CCUtility.getUserAgent() as String
@@ -97,7 +99,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         } else {
             
             levelLog = CCUtility.getLogLevel()
-            NCCommunicationCommon.shared.levelLog = levelLog            
+            NCCommunicationCommon.shared.levelLog = levelLog
             NCCommunicationCommon.shared.copyLogToDocumentDirectory = true
             if isSimulatorOrTestFlight {
                 NCCommunicationCommon.shared.writeLog("Start session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
@@ -167,7 +169,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         } else {
             if !CCUtility.getIntro() {
                 if let viewController = UIStoryboard(name: "NCIntro", bundle: nil).instantiateInitialViewController() {
-                    let navigationController = UINavigationController(rootViewController: viewController)
+                    let navigationController = NCLoginNavigationController.init(rootViewController: viewController)
                     window?.rootViewController = navigationController
                     window?.makeKeyAndVisible()
                 }
@@ -176,7 +178,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         
         // Passcode
         DispatchQueue.main.async {
-            self.presentPasscode()
+            self.presentPasscode {
+                self.enableTouchFaceID()
+            }
         }
         
         return true
@@ -187,6 +191,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     // L' applicazione entrerà in primo piano (attivo sempre)
     func applicationDidBecomeActive(_ application: UIApplication) {
         
+        // Privacy
+        hidePrivacyProtectionWindow()
+        
         NCSettingsBundleHelper.setVersionAndBuildNumber()
         
         if account == "" { return }
@@ -219,9 +226,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             networkingProcessUpload?.startTimer()
         }
         
-        // Request Passcode
-        presentPasscode()
-        
         // Initialize Auto upload
         NCAutoUpload.shared.initAutoUpload(viewController: nil) { (_) in }
                 
@@ -231,6 +235,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         // Request Service Server Nextcloud
         NCService.shared.startRequestServicesServer()
         
+        // Request TouchID, FaceID
+        enableTouchFaceID()
+        
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterApplicationWillEnterForeground)
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterRichdocumentGrabFocus)
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced)
@@ -240,7 +247,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     func applicationWillResignActive(_ application: UIApplication) {
         
         if account == "" { return }
-        
+
+        // Privacy
+        showPrivacyProtectionWindow()
+                
         // Clear operation queue
         NCOperationQueue.shared.cancelAllQueue()
         // Clear download
@@ -260,9 +270,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         
         if account == "" { return }
         
-        // Dismiss rootViewController
-        self.window?.rootViewController?.dismiss(animated: false)
-        
         // STOP TIMER UPLOAD PROCESS
         if NCUtility.shared.isSimulator() {
             networkingProcessUpload?.stopTimer()
@@ -273,6 +280,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             scheduleBackgroundProcessing()
         }
         
+        // Passcode
+        presentPasscode { }
+        
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterApplicationDidEnterBackground)
     }
     
@@ -505,7 +515,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         
         if contextViewController == nil {
             if let viewController = viewController {
-                let navigationController = UINavigationController.init(rootViewController: viewController)
+                let navigationController = NCLoginNavigationController.init(rootViewController: viewController)
                 navigationController.navigationBar.barStyle = .black
                 navigationController.navigationBar.tintColor = NCBrandColor.shared.customerText
                 navigationController.navigationBar.barTintColor = NCBrandColor.shared.customer
@@ -519,7 +529,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             }
         } else {
             if let viewController = viewController, let contextViewController = contextViewController {
-                let navigationController = UINavigationController.init(rootViewController: viewController)
+                let navigationController = NCLoginNavigationController.init(rootViewController: viewController)
                 navigationController.modalPresentationStyle = .fullScreen
                 navigationController.navigationBar.barStyle = .black
                 navigationController.navigationBar.tintColor = NCBrandColor.shared.customerText
@@ -602,7 +612,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         
         if let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) {
             NCPushNotification.shared().unsubscribingNextcloudServerPushNotification(account.account, urlBase: account.urlBase, user: account.user, withSubscribing: false)
-        }        
+        }
         
         let results = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@", account), sorted: "ocId", ascending: false)
         for result in results {
@@ -682,19 +692,28 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
     
     // MARK: - Passcode
     
-    func presentPasscode() {
-        
+    func presentPasscode(completion: @escaping ()->()) {
+
         let laContext = LAContext()
         var error: NSError?
-        
+
         defer {
             self.requestAccount()
         }
-                
-        if account == "" { return }
-        guard let passcode = CCUtility.getPasscode() else { return }
-        if passcode.count == 0 || CCUtility.getNotPasscodeAtStart() { return }
-                
+
+        guard !account.isEmpty, CCUtility.isPasscodeAtStartEnabled() else { return }
+        
+        // If activated hide the privacy protection
+        hidePrivacyProtectionWindow()
+
+        // Dismiss present window?.rootViewController? [ONLY PASSCODE]
+        let presentedViewController = window?.rootViewController?.presentedViewController
+        if presentedViewController is NCLoginNavigationController {
+            return
+        } else {
+            presentedViewController?.dismiss(animated: false)
+        }
+
         let passcodeViewController = TOPasscodeViewController.init(passcodeType: .sixDigits, allowCancel: false)
         passcodeViewController.delegate = self
         passcodeViewController.keypadButtonShowLettering = false
@@ -706,17 +725,38 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
                     passcodeViewController.biometryType = .touchID
                 }
                 passcodeViewController.allowBiometricValidation = true
-                passcodeViewController.automaticallyPromptForBiometricValidation = true
+                passcodeViewController.automaticallyPromptForBiometricValidation = false
             }
         }
         
-        window?.rootViewController?.present(passcodeViewController, animated: true)
+        window?.rootViewController?.present(passcodeViewController, animated: true, completion: {
+            completion()
+        })
     }
     
     func isPasscodePresented() -> Bool {
         return window?.rootViewController?.presentedViewController is TOPasscodeViewController
     }
     
+    func enableTouchFaceID() {
+
+        guard !account.isEmpty,
+              CCUtility.getEnableTouchFaceID(),
+              CCUtility.isPasscodeAtStartEnabled(),
+              let passcodeViewController = window?.rootViewController?.presentedViewController as? TOPasscodeViewController
+        else { return }
+
+        LAContext().evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: NCBrandOptions.shared.brand) { (success, error) in
+            if success {
+                DispatchQueue.main.async {
+                    passcodeViewController.dismiss(animated: true) {
+                        self.requestAccount()
+                    }
+                }
+            }
+        }
+    }
+    
     func didInputCorrectPasscode(in passcodeViewController: TOPasscodeViewController) {
         DispatchQueue.main.async {
             passcodeViewController.dismiss(animated: true) {
@@ -729,18 +769,29 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         return code == CCUtility.getPasscode()
     }
     
-    func didPerformBiometricValidationRequest(in passcodeViewController: TOPasscodeViewController) {
-        LAContext().evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: NCBrandOptions.shared.brand) { (success, error) in
-            if success {
-                DispatchQueue.main.async {
-                    passcodeViewController.dismiss(animated: true) {
-                        self.requestAccount()
-                    }
-                }
-            }
-        }
+    // MARK: - Privacy Protection
+       
+    private func showPrivacyProtectionWindow() {
+        
+        guard CCUtility.getPrivacyScreenEnabled() else { return }
+        
+        privacyProtectionWindow = UIWindow(frame: UIScreen.main.bounds)
+          
+        let storyboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
+        let initialViewController = storyboard.instantiateInitialViewController()
+
+        self.privacyProtectionWindow?.rootViewController = initialViewController
+        
+        privacyProtectionWindow?.windowLevel = .alert + 1
+        privacyProtectionWindow?.makeKeyAndVisible()
     }
 
+    private func hidePrivacyProtectionWindow() {
+        
+        privacyProtectionWindow?.isHidden = true
+        privacyProtectionWindow = nil
+    }
+    
     // MARK: - Open URL
 
     func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

+ 28 - 0
iOSClient/Login/NCLoginNavigationController.swift

@@ -0,0 +1,28 @@
+//
+//  NCLoginNavigationController.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 30/11/21.
+//  Copyright © 2021 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+import UIKit
+
+class NCLoginNavigationController: UINavigationController {
+}

+ 65 - 69
iOSClient/Notification/NCNotification.swift

@@ -6,7 +6,7 @@
 //  Copyright (c) 2017 Marino Faggiana. All rights reserved.
 //
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//  Henrik Storch <henrik.storch@nextcloud.com>
+//  Author Henrik Storch <henrik.storch@nextcloud.com>
 //
 //  This program is free software: you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by
@@ -133,26 +133,20 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
         // Avatar
         cell.avatar.isHidden = true
         cell.avatarLeadingMargin.constant = 10
-        if let subjectRichParameters = notification.subjectRichParameters {
-            if let json = JSON(subjectRichParameters).dictionary {
-                if let user = json["user"]?["id"].stringValue {
-                    
-                    let fileName = appDelegate.userBaseUrl + "-" + user + ".png"
-                    let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
-                    
-                    if FileManager.default.fileExists(atPath: fileNameLocalPath) {
-                        if let image = UIImage(contentsOfFile: fileNameLocalPath) {
-                            cell.avatar.isHidden = false
-                            cell.avatarLeadingMargin.constant = 50
-                            cell.avatar.image = image
-                        }
-                    } else {
-                        cell.avatar.isHidden = false
-                        cell.avatarLeadingMargin.constant = 50
-                        cell.fileUser = user
-                        NCOperationQueue.shared.downloadAvatar(user: user, dispalyName: nil, fileName: fileName, cell: cell, view: tableView)
-                    }
-                }
+        if let subjectRichParameters = notification.subjectRichParameters,
+           let json = JSON(subjectRichParameters).dictionary,
+           let user = json["user"]?["id"].stringValue {
+            cell.avatar.isHidden = false
+            cell.avatarLeadingMargin.constant = 50
+            
+            let fileName = appDelegate.userBaseUrl + "-" + user + ".png"
+            let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
+            
+            if let image = UIImage(contentsOfFile: fileNameLocalPath) {
+                cell.avatar.image = image
+            } else if !FileManager.default.fileExists(atPath: fileNameLocalPath) {
+                cell.fileUser = user
+                NCOperationQueue.shared.downloadAvatar(user: user, dispalyName: json["user"]?["name"].string, fileName: fileName, cell: cell, view: tableView)
             }
         }
         
@@ -178,13 +172,11 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
         cell.secondary.isEnabled = false
         cell.secondary.isHidden = true
         cell.secondary.titleLabel?.font = .systemFont(ofSize: 15)
-        cell.secondary.setTitleColor(.gray, for: .normal)
+        cell.secondary.setTitleColor(NCBrandColor.shared.label, for: .normal)
         cell.secondary.layer.cornerRadius = 15
         cell.secondary.layer.masksToBounds = true
-        cell.secondary.layer.backgroundColor = NCBrandColor.shared.systemGray5.cgColor
-        cell.secondary.layer.borderWidth = 0.3
-        cell.secondary.layer.borderColor = UIColor.gray.cgColor
-        
+        cell.secondary.layer.backgroundColor = NCBrandColor.shared.systemFill.cgColor
+
         // Action
         if let actions = notification.actions,
            let jsonActions = JSON(actions).array {
@@ -224,16 +216,16 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
         
         return cell
     }
-    
+
     // MARK: - tap Action
-    
-    func tapRemove(with notification: NCCommunicationNotifications?) {
-           
-        NCCommunication.shared.setNotification(serverUrl:nil, idNotification: notification!.idNotification , method: "DELETE") { (account, errorCode, errorDescription) in
+
+    func tapRemove(with notification: NCCommunicationNotifications) {
+
+        NCCommunication.shared.setNotification(serverUrl: nil, idNotification: notification.idNotification , method: "DELETE") { (account, errorCode, errorDescription) in
             if errorCode == 0 && account == self.appDelegate.account {
 
                 if let index = self.notifications
-                    .firstIndex(where: { $0.idNotification == notification!.idNotification })  {
+                    .firstIndex(where: { $0.idNotification == notification.idNotification })  {
                     self.notifications.remove(at: index)
                 }
                 
@@ -242,46 +234,44 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
             } else if errorCode != 0 {
                 NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
             } else {
-                print("[LOG] It has been changed user during networking process, error.")
+                print("[Error] The user has been changed during networking process.")
             }
         }
     }
 
-    func tapAction(with notification: NCCommunicationNotifications?, label: String) {
-        
-        if let actions = notification!.actions {
-            if let jsonActions = JSON(actions).array {
-                for action in jsonActions {
-                    if action["label"].string == label {
-                        let serverUrl = action["link"].stringValue
-                        let method = action["type"].stringValue
+    func tapAction(with notification: NCCommunicationNotifications, label: String) {
+        if notification.app == "spreed",
+           let roomToken = notification.objectId.split(separator: "/").first,
+           let talkUrl = URL(string: "nextcloudtalk://open-conversation?server=\(appDelegate.urlBase)&user=\(appDelegate.userId)&withRoomToken=\(roomToken)"),
+           UIApplication.shared.canOpenURL(talkUrl) {
+            UIApplication.shared.open(talkUrl)
+        } else if let actions = notification.actions,
+                  let jsonActions = JSON(actions).array,
+                  let action = jsonActions.first(where: { $0["label"].string == label }) {
+                      let serverUrl = action["link"].stringValue
+            let method = action["type"].stringValue
 
-                        if method == "WEB", let url = action["link"].url {
-                            UIApplication.shared.open(url, options: [:], completionHandler: nil)
-                            return
-                        }
+            if method == "WEB", let url = action["link"].url {
+                UIApplication.shared.open(url, options: [:], completionHandler: nil)
+                return
+            }
 
-                        NCCommunication.shared.setNotification(serverUrl: serverUrl, idNotification: 0, method: method) { (account, errorCode, errorDescription) in
-                            
-                            if errorCode == 0 && account == self.appDelegate.account {
+            NCCommunication.shared.setNotification(serverUrl: serverUrl, idNotification: 0, method: method) { (account, errorCode, errorDescription) in
 
-                                if let index = self.notifications
-                                    .firstIndex(where: { $0.idNotification == notification!.idNotification })  {
-                                    self.notifications.remove(at: index)
-                                }
-                                
-                                self.reloadDatasource()
-                                
-                            } else if errorCode != 0 {
-                                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
-                            } else {
-                                print("[LOG] It has been changed user during networking process, error.")
-                            }
-                        }
+                if errorCode == 0 && account == self.appDelegate.account {
+                    if let index = self.notifications.firstIndex(where: { $0.idNotification == notification.idNotification }) {
+                        self.notifications.remove(at: index)
                     }
+
+                    self.reloadDatasource()
+
+                } else if errorCode != 0 {
+                    NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                } else {
+                    print("[Error] The user has been changed during networking process.")
                 }
             }
-        }
+        } // else: Action not found
     }
     
     // MARK: - Load notification networking
@@ -325,7 +315,6 @@ class NCNotificationCell: UITableViewCell, NCCellProtocol {
     @IBOutlet weak var primary: UIButton!
     @IBOutlet weak var secondary: UIButton!
     @IBOutlet weak var avatarLeadingMargin: NSLayoutConstraint!
-//    @IBOutlet weak var messageBottomMargin: NSLayoutConstraint!
     @IBOutlet weak var primaryWidth: NSLayoutConstraint!
     @IBOutlet weak var secondaryWidth: NSLayoutConstraint!
     
@@ -363,21 +352,28 @@ class NCNotificationCell: UITableViewCell, NCCellProtocol {
     }
     
     @IBAction func touchUpInsideRemove(_ sender: Any) {
+        guard let notification = notification else { return }
         delegate?.tapRemove(with: notification)
     }
     
     @IBAction func touchUpInsidePrimary(_ sender: Any) {
-        let button = sender as! UIButton
-        delegate?.tapAction(with: notification, label: button.titleLabel!.text!)
+        guard let notification = notification,
+                let button = sender as? UIButton,
+                let label = button.titleLabel?.text
+        else { return }
+        delegate?.tapAction(with: notification, label: label)
     }
     
     @IBAction func touchUpInsideSecondary(_ sender: Any) {
-        let button = sender as! UIButton
-        delegate?.tapAction(with: notification, label: button.titleLabel!.text!)
+        guard let notification = notification,
+                let button = sender as? UIButton,
+                let label = button.titleLabel?.text
+        else { return }
+        delegate?.tapAction(with: notification, label: label)
     }
 }
 
 protocol NCNotificationCellDelegate {
-    func tapRemove(with notification: NCCommunicationNotifications?)
-    func tapAction(with notification: NCCommunicationNotifications?, label: String)
+    func tapRemove(with notification: NCCommunicationNotifications)
+    func tapAction(with notification: NCCommunicationNotifications, label: String)
 }

+ 22 - 4
iOSClient/Settings/NCSettings.m

@@ -66,9 +66,9 @@
     row.action.viewControllerClass = [CCManageAutoUpload class];
     [section addFormRow:row];
 
-    // Section : LOCK --------------------------------------------------------------
+    // Section : PRIVACY --------------------------------------------------------------
     
-    section = [XLFormSectionDescriptor formSectionWithTitle:NSLocalizedString(@"_lock_", nil)];
+    section = [XLFormSectionDescriptor formSectionWithTitle:NSLocalizedString(@"_privacy_", nil)];
     [form addFormSection:section];
     
     // Lock active YES/NO
@@ -93,6 +93,12 @@
     [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
     [row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
     [section addFormRow:row];
+    // Privacy screen
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"privacyScreen" rowType:XLFormRowDescriptorTypeBooleanSwitch title:NSLocalizedString(@"_privacy_screen_", nil)];
+    row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
+    [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
+    [row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
+    [section addFormRow:row];
     
     // Section : E2EEncryption --------------------------------------------------------------
         
@@ -144,8 +150,8 @@
     
     if (!NCBrandOptions.shared.disable_crash_service) {
         
-        // Privacy
-        row = [XLFormRowDescriptor formRowDescriptorWithTag:@"privacy" rowType:XLFormRowDescriptorTypeButton title:NSLocalizedString(@"_privacy_", nil)];
+        // Privacy and Legal Policy
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:@"privacy" rowType:XLFormRowDescriptorTypeButton title:NSLocalizedString(@"_privacy_legal_", nil)];
         row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
         [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
         [row.cellConfig setObject:@(NSTextAlignmentLeft) forKey:@"textLabel.textAlignment"];
@@ -224,6 +230,7 @@
     XLFormRowDescriptor *rowBloccoPasscode = [self.form formRowWithTag:@"bloccopasscode"];
     XLFormRowDescriptor *rowNotPasscodeAtStart = [self.form formRowWithTag:@"notPasscodeAtStart"];
     XLFormRowDescriptor *rowEnableTouchDaceID = [self.form formRowWithTag:@"enableTouchDaceID"];
+    XLFormRowDescriptor *rowPrivacyScreen = [self.form formRowWithTag:@"privacyScreen"];
 
     // ------------------------------------------------------------------
     
@@ -237,6 +244,8 @@
     
     if ([CCUtility getEnableTouchFaceID]) [rowEnableTouchDaceID setValue:@1]; else [rowEnableTouchDaceID setValue:@0];
     if ([CCUtility getNotPasscodeAtStart]) [rowNotPasscodeAtStart setValue:@1]; else [rowNotPasscodeAtStart setValue:@0];
+    if ([CCUtility getPrivacyScreenEnabled]) [rowPrivacyScreen setValue:@1]; else [rowPrivacyScreen setValue:@0];
+
 
     // -----------------------------------------------------------------
     
@@ -266,6 +275,15 @@
             [CCUtility setEnableTouchFaceID:false];
         }
     }
+    
+    if ([rowDescriptor.tag isEqualToString:@"privacyScreen"]) {
+        
+        if ([[rowDescriptor.value valueData] boolValue] == YES) {
+            [CCUtility setPrivacyScreenEnabled:true];
+        } else {
+            [CCUtility setPrivacyScreenEnabled:false];
+        }
+    }
 }
 
 #pragma mark -

二進制
iOSClient/Supporting Files/af.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ar.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ast.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/az.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/br.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/bs.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ca.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/da.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/de.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/el.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/en-GB.lproj/Localizable.strings


+ 2 - 1
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -168,7 +168,7 @@
 "_upload_e2ee_"             = "The file you are uploading is encrypted, keep the app in the foreground until complete";
 "_chunk_size_mb_"           = "Chunk size in MB";
 "_chunk_footer_title_"      = "Chunked file upload (0 is disabled)\nImportant: the chunked upload works only when the app is \"active\".";
-"_privacy_"                 = "Privacy";
+"_privacy_legal_"           = "Privacy and Legal Policy";
 "_source_code_"             = "Get source code";
 "_account_select_"          = "Select the account";
 "_host_insert_"             = "Insert the host name, for example:";
@@ -821,4 +821,5 @@
 "_copied_path_"             = "Copied path";
 "_copy_path_"               = "Copy path";
 "_certificates_"            = "Certificates";
+"_privacy_screen_"          = "Splash screen when app inactive";
 

二進制
iOSClient/Supporting Files/eo.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-419.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-AR.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-CL.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-CO.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-CR.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-DO.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-EC.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-GT.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-HN.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-MX.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-NI.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-PA.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-PE.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-PR.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-PY.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-SV.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es-UY.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/es.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/et_EE.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/eu.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/fa.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/fr.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/gl.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/he.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/hr.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/hu.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ia.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/id.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/is.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/it.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ko.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/lb.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/lo.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/lv.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/mk.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/mn.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/nl.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/oc.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/pl.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ro.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/ru.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/sc.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/si.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/sl.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/sq.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/sr.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/sv.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/th_TH.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/tr.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/uk.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/vi.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings


二進制
iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings


+ 5 - 0
iOSClient/Utility/CCUtility.h

@@ -51,6 +51,8 @@
 + (BOOL)getEnableTouchFaceID;
 + (void)setEnableTouchFaceID:(BOOL)set;
 
++ (BOOL)isPasscodeAtStartEnabled;
+
 + (NSString *)getGroupBySettings;
 + (void)setGroupBySettings:(NSString *)groupby;
 
@@ -181,6 +183,9 @@
 + (PDFDisplayDirection)getPDFDisplayDirection;
 + (void)setPDFDisplayDirection:(PDFDisplayDirection)direction;
 
++ (BOOL)getPrivacyScreenEnabled;
++ (void)setPrivacyScreenEnabled:(BOOL)set;
+
 // ===== Varius =====
 
 + (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL;

+ 25 - 0
iOSClient/Utility/CCUtility.m

@@ -103,6 +103,12 @@
     [UICKeyChainStore setString:sSet forKey:@"enableTouchFaceID" service:NCGlobal.shared.serviceShareKeyChain];
 }
 
++ (BOOL)isPasscodeAtStartEnabled
+{
+    if ([self getPasscode].length > 0 && ![self getNotPasscodeAtStart]) return true;
+    else return false;
+}
+
 + (NSString *)getGroupBySettings
 {
     NSString *groupby = [UICKeyChainStore stringForKey:@"groupby" service:NCGlobal.shared.serviceShareKeyChain];
@@ -726,6 +732,25 @@
     [UICKeyChainStore setString:directionString forKey:@"PDFDisplayDirection" service:NCGlobal.shared.serviceShareKeyChain];
 }
 
++ (BOOL)getPrivacyScreenEnabled
+{
+    NSString *valueString = [UICKeyChainStore stringForKey:@"privacyScreen" service:NCGlobal.shared.serviceShareKeyChain];
+    
+    // Default TRUE
+    if (valueString == nil) {
+        [self setPrivacyScreenEnabled:YES];
+        return true;
+    }
+    
+    return [valueString boolValue];
+}
+
++ (void)setPrivacyScreenEnabled:(BOOL)set
+{
+    NSString *sSet = (set) ? @"true" : @"false";
+    [UICKeyChainStore setString:sSet forKey:@"privacyScreen" service:NCGlobal.shared.serviceShareKeyChain];
+}
+
 #pragma --------------------------------------------------------------------------------------------
 #pragma mark ===== Various =====
 #pragma --------------------------------------------------------------------------------------------