Browse Source

Merge branch 'develop'

marinofaggiana 5 years ago
parent
commit
6b3ebaade3
90 changed files with 948 additions and 603 deletions
  1. 1 2
      Cartfile
  2. 1 3
      Cartfile.resolved
  3. 1 4
      File Provider Extension/FileProviderData.swift
  4. 75 101
      File Provider Extension/FileProviderEnumerator.swift
  5. 1 0
      File Provider Extension/FileProviderExtension+Actions.swift
  6. 18 2
      File Provider Extension/FileProviderExtension+NetworkingDelegate.swift
  7. 1 1
      Libraries external/Imagemeter/IMCreate.swift
  8. 29 21
      Nextcloud.xcodeproj/project.pbxproj
  9. 2 1
      Share/ShareViewController.m
  10. 8 2
      iOSClient/AppDelegate.m
  11. 2 2
      iOSClient/Brand/File_Provider_Extension.plist
  12. 0 47
      iOSClient/Brand/Intro/CCIntro.h
  13. 0 265
      iOSClient/Brand/Intro/CCIntro.m
  14. 34 0
      iOSClient/Brand/Intro/IntroCollectionViewCell.swift
  15. 60 0
      iOSClient/Brand/Intro/IntroCollectionViewCell.xib
  16. 144 0
      iOSClient/Brand/Intro/IntroView.swift
  17. 118 0
      iOSClient/Brand/Intro/IntroView.xib
  18. 2 2
      iOSClient/Brand/Share.plist
  19. 2 2
      iOSClient/Brand/iOSClient.plist
  20. 17 0
      iOSClient/CCGlobal.h
  21. 30 0
      iOSClient/Database/NCManageDatabase.swift
  22. 48 41
      iOSClient/Login/NCLoginWeb.swift
  23. 24 0
      iOSClient/Main/CCMain.m
  24. 2 3
      iOSClient/Main/CCSplit.h
  25. 5 4
      iOSClient/Main/CCSplit.m
  26. 2 21
      iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift
  27. 25 18
      iOSClient/Main/Create cloud/NCCreateMenuAdd.swift
  28. 14 23
      iOSClient/Main/NCMainCommon.swift
  29. 4 0
      iOSClient/Main/NCPhotosPickerViewController.swift
  30. 57 28
      iOSClient/Networking/CCNetworking.m
  31. 3 4
      iOSClient/Networking/NCNetworking.swift
  32. 1 0
      iOSClient/Nextcloud-Bridging-Header.h
  33. BIN
      iOSClient/Supporting Files/ast.lproj/Localizable.strings
  34. BIN
      iOSClient/Supporting Files/ca.lproj/Localizable.strings
  35. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
  36. BIN
      iOSClient/Supporting Files/da.lproj/Localizable.strings
  37. BIN
      iOSClient/Supporting Files/de.lproj/Localizable.strings
  38. BIN
      iOSClient/Supporting Files/el.lproj/Localizable.strings
  39. BIN
      iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
  40. 4 0
      iOSClient/Supporting Files/en.lproj/Localizable.strings
  41. BIN
      iOSClient/Supporting Files/es-419.lproj/Localizable.strings
  42. BIN
      iOSClient/Supporting Files/es-AR.lproj/Localizable.strings
  43. BIN
      iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
  44. BIN
      iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
  45. BIN
      iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
  46. BIN
      iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
  47. BIN
      iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
  48. BIN
      iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
  49. BIN
      iOSClient/Supporting Files/es-HN.lproj/Localizable.strings
  50. BIN
      iOSClient/Supporting Files/es-MX.lproj/Localizable.strings
  51. BIN
      iOSClient/Supporting Files/es-NI.lproj/Localizable.strings
  52. BIN
      iOSClient/Supporting Files/es-PA.lproj/Localizable.strings
  53. BIN
      iOSClient/Supporting Files/es-PE.lproj/Localizable.strings
  54. BIN
      iOSClient/Supporting Files/es-PR.lproj/Localizable.strings
  55. BIN
      iOSClient/Supporting Files/es-PY.lproj/Localizable.strings
  56. BIN
      iOSClient/Supporting Files/es-SV.lproj/Localizable.strings
  57. BIN
      iOSClient/Supporting Files/es-UY.lproj/Localizable.strings
  58. BIN
      iOSClient/Supporting Files/es.lproj/Localizable.strings
  59. BIN
      iOSClient/Supporting Files/eu.lproj/Localizable.strings
  60. BIN
      iOSClient/Supporting Files/fa.lproj/Localizable.strings
  61. BIN
      iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings
  62. BIN
      iOSClient/Supporting Files/fr.lproj/Localizable.strings
  63. BIN
      iOSClient/Supporting Files/gl.lproj/Localizable.strings
  64. BIN
      iOSClient/Supporting Files/hr.lproj/Localizable.strings
  65. BIN
      iOSClient/Supporting Files/hu.lproj/Localizable.strings
  66. BIN
      iOSClient/Supporting Files/is.lproj/Localizable.strings
  67. BIN
      iOSClient/Supporting Files/it.lproj/Localizable.strings
  68. BIN
      iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings
  69. BIN
      iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings
  70. BIN
      iOSClient/Supporting Files/ko.lproj/Localizable.strings
  71. BIN
      iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings
  72. BIN
      iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings
  73. BIN
      iOSClient/Supporting Files/nl.lproj/Localizable.strings
  74. BIN
      iOSClient/Supporting Files/pl.lproj/Localizable.strings
  75. BIN
      iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings
  76. BIN
      iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings
  77. BIN
      iOSClient/Supporting Files/ru.lproj/Localizable.strings
  78. BIN
      iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings
  79. BIN
      iOSClient/Supporting Files/sl.lproj/Localizable.strings
  80. BIN
      iOSClient/Supporting Files/sq.lproj/Localizable.strings
  81. BIN
      iOSClient/Supporting Files/sr.lproj/Localizable.strings
  82. BIN
      iOSClient/Supporting Files/sv.lproj/Localizable.strings
  83. BIN
      iOSClient/Supporting Files/tr.lproj/Localizable.strings
  84. BIN
      iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings
  85. BIN
      iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings
  86. 1 0
      iOSClient/Utility/CCUtility.h
  87. 23 1
      iOSClient/Utility/CCUtility.m
  88. 87 4
      iOSClient/Utility/NCUtility.swift
  89. 89 0
      iOSClient/Utility/UIImage+fixedOrientation.swift
  90. 13 1
      iOSClient/Viewer/NCViewerDocumentWeb.swift

+ 1 - 2
Cartfile

@@ -1,10 +1,9 @@
-github "nextcloud/ios-communication-library" "develop"
+github "nextcloud/ios-communication-library" "v0.1"
 github "tilltue/TLPhotoPicker" "1.9.3"
 github "kishikawakatsumi/UICKeyChainStore" "v2.1.2"
 github "danielsaidi/Sheeeeeeeeet" "2.0.2"
 github "MortimerGoro/MGSwipeTableCell" "1.6.8"
 github "dzenbot/DZNEmptyDataSet" "v1.8.1"
-github "ealeksandrov/EAIntroView" "2.12.0"
 github "calimarkus/JDStatusBarNotification" "1.6.0"
 github "ChangbaDevs/KTVHTTPCache" "2.0.1"
 github "jdg/MBProgressHUD" "1.1.0"

+ 1 - 3
Cartfile.resolved

@@ -10,15 +10,13 @@ github "WenchaoD/FSCalendar" "2.8.0"
 github "calimarkus/JDStatusBarNotification" "1.6.0"
 github "danielsaidi/Sheeeeeeeeet" "2.0.2"
 github "dzenbot/DZNEmptyDataSet" "v1.8.1"
-github "ealeksandrov/EAIntroView" "2.12.0"
-github "ealeksandrov/EARestrictedScrollView" "1.1.0"
 github "jdg/MBProgressHUD" "1.1.0"
 github "kishikawakatsumi/UICKeyChainStore" "v2.1.2"
 github "krzyzanowskim/OpenSSL" "1.0.218"
 github "malcommac/SwiftRichString" "3.0.3"
 github "marinofaggiana/AFNetworking" "2967678c3e0e98c9b8d7e06222ad12d1f49c26f2"
 github "marinofaggiana/FastScroll" "81967c2309d29bc2c330d422da612160a30bade8"
-github "nextcloud/ios-communication-library" "e4fc47719555c1b00c5cfbc717c4a68ab1e62522"
+github "nextcloud/ios-communication-library" "v0.1"
 github "realm/realm-cocoa" "v3.17.3"
 github "rechsteiner/Parchment" "v1.7.0"
 github "tilltue/TLPhotoPicker" "1.9.3"

+ 1 - 4
File Provider Extension/FileProviderData.swift

@@ -37,10 +37,7 @@ class fileProviderData: NSObject {
     var homeServerUrl = ""
         
     // Max item for page
-    let itemForPage = 20
-
-    // List of etag for serverUrl
-    var listServerUrlEtag = [String:String]()
+    let itemForPage = 100
     
     // Anchor
     var currentAnchor: UInt64 = 0

+ 75 - 101
File Provider Extension/FileProviderEnumerator.swift

@@ -56,7 +56,6 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     func enumerateItems(for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage) {
         
         var items: [NSFileProviderItemProtocol] = []
-        var metadatasFromDB: [tableMetadata]?
         
         /*** WorkingSet ***/
         if enumeratedItemIdentifier == .workingSet {
@@ -101,82 +100,24 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
                 return
             }
             
-            // Select items from database
-            metadatasFromDB = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.sharedInstance.account, serverUrl), sorted: "fileName", ascending: true)
-            
-            // Calculate current page
-            if (page != NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage && page != NSFileProviderPage.initialPageSortedByName as NSFileProviderPage) {
-                
-                var numPage = Int(String(data: page.rawValue, encoding: .utf8)!)!
+            if (page == NSFileProviderPage.initialPageSortedByDate as NSFileProviderPage || page == NSFileProviderPage.initialPageSortedByName as NSFileProviderPage) {
                 
-                if (metadatasFromDB != nil) {
-                    items = self.selectItems(numPage: numPage, account: fileProviderData.sharedInstance.account, metadatas: metadatasFromDB!)
-                    observer.didEnumerate(items)
-                }
-                if (items.count == fileProviderData.sharedInstance.itemForPage) {
-                    numPage += 1
-                    let providerPage = NSFileProviderPage("\(numPage)".data(using: .utf8)!)
-                    observer.finishEnumerating(upTo: providerPage)
-                } else {
-                    observer.finishEnumerating(upTo: nil)
+                readFileOrFolder(serverUrl: serverUrl) {
+                    let metadatas = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.sharedInstance.account, serverUrl), page: 1, limit: fileProviderData.sharedInstance.itemForPage, sorted: "fileName", ascending: true)
+                    
+                    self.completeObserver(observer, numPage: 1, metadatas: metadatas)
                 }
-                return
-            }
-            
-            // Update the WorkingSet -> Favorite
-            fileProviderData.sharedInstance.updateFavoriteForWorkingSet()
-            
-            NCCommunication.sharedInstance.readFileOrFolder(serverUrlFileName: serverUrl, depth: "0", account: fileProviderData.sharedInstance.account, completionHandler: { (account, files, errorCode, errorDescription) in
                 
-                var etag = ""
-                let etagServerUrl = fileProviderData.sharedInstance.listServerUrlEtag[serverUrl]
-                if errorCode == 0 && files != nil && files!.count == 1 { etag = files![0].etag }
+                // Update the WorkingSet -> Favorite
+                fileProviderData.sharedInstance.updateFavoriteForWorkingSet()
                 
-                if etag != etagServerUrl {
-                                
-                    NCCommunication.sharedInstance.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", account: fileProviderData.sharedInstance.account, completionHandler: { (account, files, errorCode, errorDescription) in
-                        
-                        if errorCode == 0 && files != nil  && files!.count >= 1 {
-                            
-                            let file = files![0]
-
-                            // Update directory etag
-                            NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrl, serverUrlTo: nil, etag: file.etag, ocId: file.ocId, encrypted: file.e2eEncrypted, account: account)
-                            // Save etag for this serverUrl
-                            fileProviderData.sharedInstance.listServerUrlEtag[serverUrl] = file.etag
-                            
-                            NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d)", account, serverUrl, k_metadataStatusNormal, k_metadataStatusHide))
-                                
-                            NCManageDatabase.sharedInstance.setDateReadDirectory(serverUrl: serverUrl, account: account)
-                                
-                            let metadatasInDownload = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d OR status == %d OR status == %d)", account, serverUrl, k_metadataStatusWaitDownload, k_metadataStatusInDownload, k_metadataStatusDownloading, k_metadataStatusDownloadError), sorted: nil, ascending: false)
-                             
-                            let metadatasInUpload = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d OR status == %d OR status == %d)", account, serverUrl, k_metadataStatusWaitUpload, k_metadataStatusInUpload, k_metadataStatusUploading, k_metadataStatusUploadError), sorted: nil, ascending: false)
-                           
-                            NCManageDatabase.sharedInstance.addMetadatas(files: files!, account: account, serverUrl: serverUrl, removeFirst: true)
-                            
-                            if metadatasInDownload != nil {
-                                _ = NCManageDatabase.sharedInstance.addMetadatas(metadatasInDownload!)
-                            }
-                            if metadatasInUpload != nil {
-                                _ = NCManageDatabase.sharedInstance.addMetadatas(metadatasInUpload!)
-                            }
-                            
-                            metadatasFromDB = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", account, serverUrl), sorted: "fileName", ascending: true)
-                            
-                            self.selectFirstPageItems(metadatasFromDB, observer: observer)
-                            
-                        } else {
-                            
-                            self.selectFirstPageItems(metadatasFromDB, observer: observer)
-                        }
-                    })
-                    
-                } else {
-                    
-                    self.selectFirstPageItems(metadatasFromDB, observer: observer)
-                }
-            })
+            } else {
+                
+                let numPage = Int(String(data: page.rawValue, encoding: .utf8)!)!
+                let metadatas = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.sharedInstance.account, serverUrl), page: numPage, limit: fileProviderData.sharedInstance.itemForPage, sorted: "fileName", ascending: true)
+                
+                completeObserver(observer, numPage: numPage, metadatas: metadatas)
+            }
         }
     }
     
@@ -226,51 +167,84 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
     }
     
     // --------------------------------------------------------------------------------------------
-    //  MARK: - User Function
+    //  MARK: - User Function + Network
     // --------------------------------------------------------------------------------------------
 
-    func selectFirstPageItems(_ metadatas: [tableMetadata]?, observer: NSFileProviderEnumerationObserver) {
-        
+    func completeObserver(_ observer: NSFileProviderEnumerationObserver, numPage: Int, metadatas: [tableMetadata]?) {
+            
+        var numPage = numPage
         var items: [NSFileProviderItemProtocol] = []
-        
+
         if (metadatas != nil) {
-            items = self.selectItems(numPage: 0, account: fileProviderData.sharedInstance.account, metadatas: metadatas!)
+            
+            for metadata in metadatas! {
+                    
+                if metadata.e2eEncrypted || metadata.status == Int(k_metadataStatusHide) || (metadata.session != "" && metadata.session != k_upload_session_extension) { continue }
+                    
+                fileProviderUtility.sharedInstance.createocIdentifierOnFileSystem(metadata: metadata)
+                        
+                let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl)
+                if parentItemIdentifier != nil {
+                    let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!)
+                    items.append(item)
+                }
+            }
             observer.didEnumerate(items)
         }
+        
         if (items.count == fileProviderData.sharedInstance.itemForPage) {
-            let providerPage = NSFileProviderPage("1".data(using: .utf8)!)
+            numPage += 1
+            let providerPage = NSFileProviderPage("\(numPage)".data(using: .utf8)!)
             observer.finishEnumerating(upTo: providerPage)
         } else {
             observer.finishEnumerating(upTo: nil)
         }
     }
-    
-    func selectItems(numPage: Int, account: String, metadatas: [tableMetadata]) -> [NSFileProviderItemProtocol] {
         
-        var items: [NSFileProviderItemProtocol] = []
-        let start = numPage * fileProviderData.sharedInstance.itemForPage + 1
-        let stop = start + (fileProviderData.sharedInstance.itemForPage - 1)
-        var counter = 0
+    func readFileOrFolder(serverUrl: String, completionHandler: @escaping () -> Void) {
         
-        autoreleasepool {
+        NCCommunication.sharedInstance.readFileOrFolder(serverUrlFileName: serverUrl, depth: "0", account: fileProviderData.sharedInstance.account, completionHandler: { (account, files, errorCode, errorDescription) in
             
-            for metadata in metadatas {
-                
-                if metadata.e2eEncrypted || metadata.status == Int(k_metadataStatusHide) || (metadata.session != "" && metadata.session != k_upload_session_extension) { continue }
-                
-                counter += 1
-                if (counter >= start && counter <= stop) {
-                    
-                    fileProviderUtility.sharedInstance.createocIdentifierOnFileSystem(metadata: metadata)
-                    
-                    let parentItemIdentifier = fileProviderUtility.sharedInstance.getParentItemIdentifier(metadata: metadata, homeServerUrl: fileProviderData.sharedInstance.homeServerUrl)
-                    if parentItemIdentifier != nil {
-                        let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier!)
-                        items.append(item)
+            var needReadFolder = true
+        
+            if let tableDirectory = NCManageDatabase.sharedInstance.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", account, serverUrl)) {
+                if errorCode == 0 && files != nil && files!.count == 1 {
+                    if tableDirectory.etag == files![0].etag {
+                        needReadFolder = false
                     }
                 }
             }
-        }
-        return items
+            
+            if needReadFolder {
+
+                NCCommunication.sharedInstance.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", account: fileProviderData.sharedInstance.account, completionHandler: { (account, files, errorCode, errorDescription) in
+                    
+                    if errorCode == 0 && files != nil  && files!.count >= 1 {
+                        
+                        // Update directory etag
+                        let directory = files![0]
+                        NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrl, serverUrlTo: nil, etag: directory.etag, ocId: directory.ocId, encrypted: directory.e2eEncrypted, account: account)
+                                                
+                        // Update DB
+                        NCManageDatabase.sharedInstance.deleteMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d)", account, serverUrl, k_metadataStatusNormal, k_metadataStatusHide))
+                        NCManageDatabase.sharedInstance.setDateReadDirectory(serverUrl: serverUrl, account: account)
+                        let metadatasInDownload = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d OR status == %d OR status == %d)", account, serverUrl, k_metadataStatusWaitDownload, k_metadataStatusInDownload, k_metadataStatusDownloading, k_metadataStatusDownloadError), sorted: nil, ascending: false)
+                        let metadatasInUpload = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d OR status == %d OR status == %d)", account, serverUrl, k_metadataStatusWaitUpload, k_metadataStatusInUpload, k_metadataStatusUploading, k_metadataStatusUploadError), sorted: nil, ascending: false)
+                        NCManageDatabase.sharedInstance.addMetadatas(files: files!, account: account, serverUrl: serverUrl, removeFirst: true)
+                         
+                        if metadatasInDownload != nil {
+                            _ = NCManageDatabase.sharedInstance.addMetadatas(metadatasInDownload!)
+                        }
+                        if metadatasInUpload != nil {
+                            _ = NCManageDatabase.sharedInstance.addMetadatas(metadatasInUpload!)
+                        }
+                    }
+                    completionHandler()
+                })
+            } else {
+                completionHandler()
+            }
+        })
     }
+    
 }

+ 1 - 0
File Provider Extension/FileProviderExtension+Actions.swift

@@ -33,6 +33,7 @@ extension FileProviderExtension {
             return
         }
         
+        let directoryName = NCUtility.sharedInstance.createFileName(directoryName, serverUrl: tableDirectory.serverUrl, account: fileProviderData.sharedInstance.account)
         let serverUrlFileName = tableDirectory.serverUrl + "/" + directoryName
         
         NCCommunication.sharedInstance.createFolder(serverUrlFileName, account: fileProviderData.sharedInstance.account) { (account, ocId, date, errorCode, errorDescription) in

+ 18 - 2
File Provider Extension/FileProviderExtension+NetworkingDelegate.swift

@@ -3,7 +3,22 @@
 //  File Provider Extension
 //
 //  Created by Marino Faggiana on 02/11/2019.
-//  Copyright © 2019 TWS. All rights reserved.
+//  Copyright © 2018 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 FileProvider
@@ -11,7 +26,7 @@ import NCCommunication
 
 extension FileProviderExtension: NCNetworkingDelegate {
 
-    func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, description: String?, error: Error?, statusCode: Int) {
+    func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, error: Error?, statusCode: Int) {
                 
         guard let ocIdTemp = description else { return }
         guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp)) else { return }
@@ -41,6 +56,7 @@ extension FileProviderExtension: NCNetworkingDelegate {
             if let ocId = ocId { metadata.ocId = ocId }
             if let date = date { metadata.date = date }
             metadata.session = ""
+            metadata.size = Double(size)
             metadata.status = Int(k_metadataStatusNormal)
                   
             guard let metadataUpdated = NCManageDatabase.sharedInstance.addMetadata(metadata) else { return }

+ 1 - 1
Libraries external/Imagemeter/IMCreate.swift

@@ -24,7 +24,7 @@
 import Foundation
 
 class IMCreate: NSObject {
-    init(fileName: String, directory: String) {
+    init(serverUrl: String) {
         super.init()
     }
 }

+ 29 - 21
Nextcloud.xcodeproj/project.pbxproj

@@ -7,6 +7,10 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		375CF03E238282B8000F2B53 /* IntroCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 375CF03C238282B7000F2B53 /* IntroCollectionViewCell.swift */; };
+		375CF03F238282B8000F2B53 /* IntroCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 375CF03D238282B7000F2B53 /* IntroCollectionViewCell.xib */; };
+		379DC949237EF4DD008EC025 /* IntroView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 379DC948237EF4DD008EC025 /* IntroView.swift */; };
+		379DC94B237EF4EB008EC025 /* IntroView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 379DC94A237EF4EB008EC025 /* IntroView.xib */; };
 		F700222C1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700222D1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F70022B31EC4C9100080073F /* OCActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = F70022671EC4C9100080073F /* OCActivity.m */; };
@@ -62,7 +66,6 @@
 		F70BFC7520E0FA7D00C67599 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
 		F70CAE3A1F8CF31A008125FD /* NCEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */; };
 		F70F2BA5225F2D8900EBB73E /* ZIPFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F70F2BA4225F2D8900EBB73E /* ZIPFoundation.framework */; };
-		F710E8101EF95C9C00DC2427 /* CCIntro.m in Sources */ = {isa = PBXBuildFile; fileRef = F710E80E1EF95C9C00DC2427 /* CCIntro.m */; };
 		F710E8111EF95C9C00DC2427 /* ImagesIntro.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F710E80F1EF95C9C00DC2427 /* ImagesIntro.xcassets */; };
 		F71459B81D12E3B700CAFEEC /* CCError.m in Sources */ = {isa = PBXBuildFile; fileRef = F76C3B881C638A4C00DC4301 /* CCError.m */; };
 		F71459BA1D12E3B700CAFEEC /* NSString+TruncateToWidth.m in Sources */ = {isa = PBXBuildFile; fileRef = F73049B91CB567F000C7C320 /* NSString+TruncateToWidth.m */; };
@@ -438,6 +441,7 @@
 		F7B6F70121BD0DD3007D194D /* DZNEmptyDataSet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BE621998F410004137E /* DZNEmptyDataSet.framework */; };
 		F7B6F70221BD0E6D007D194D /* MBProgressHUD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BF22199978B0004137E /* MBProgressHUD.framework */; };
 		F7B6F70321BD0EA0007D194D /* JDStatusBarNotification.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BEC219993330004137E /* JDStatusBarNotification.framework */; };
+		F7B7504B2397D38F004E13EC /* UIImage+fixedOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+fixedOrientation.swift */; };
 		F7BAADC81ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
 		F7BAADC91ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
 		F7BAADCB1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
@@ -445,8 +449,6 @@
 		F7BF1B431D51E893000854F6 /* CCLogin.m in Sources */ = {isa = PBXBuildFile; fileRef = F7BF1B401D51E893000854F6 /* CCLogin.m */; };
 		F7C40BE521998D5B0004137E /* MGSwipeTableCell.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BE421998D5A0004137E /* MGSwipeTableCell.framework */; };
 		F7C40BE721998F410004137E /* DZNEmptyDataSet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BE621998F410004137E /* DZNEmptyDataSet.framework */; };
-		F7C40BE9219991A60004137E /* EAIntroView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BE8219991A60004137E /* EAIntroView.framework */; };
-		F7C40BEB219991AC0004137E /* EARestrictedScrollView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BEA219991AC0004137E /* EARestrictedScrollView.framework */; };
 		F7C40BED219993330004137E /* JDStatusBarNotification.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BEC219993330004137E /* JDStatusBarNotification.framework */; };
 		F7C40BEF219994ED0004137E /* KTVCocoaHTTPServer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BEE219994ED0004137E /* KTVCocoaHTTPServer.framework */; };
 		F7C40BF1219994F20004137E /* KTVHTTPCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7C40BF0219994F20004137E /* KTVHTTPCache.framework */; };
@@ -664,6 +666,10 @@
 		08EA97451E6554FC004C83FA /* FirebaseCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FirebaseCore.framework; sourceTree = "<group>"; };
 		08EA97461E6554FC004C83FA /* FirebaseInstanceID.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FirebaseInstanceID.framework; sourceTree = "<group>"; };
 		08EA97471E6554FC004C83FA /* GoogleToolboxForMac.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = GoogleToolboxForMac.framework; sourceTree = "<group>"; };
+		375CF03C238282B7000F2B53 /* IntroCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroCollectionViewCell.swift; sourceTree = "<group>"; };
+		375CF03D238282B7000F2B53 /* IntroCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IntroCollectionViewCell.xib; sourceTree = "<group>"; };
+		379DC948237EF4DD008EC025 /* IntroView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroView.swift; sourceTree = "<group>"; };
+		379DC94A237EF4EB008EC025 /* IntroView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IntroView.xib; sourceTree = "<group>"; };
 		F700222B1EC479840080073F /* Custom.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Custom.xcassets; sourceTree = "<group>"; };
 		F70022661EC4C9100080073F /* OCActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCActivity.h; sourceTree = "<group>"; };
 		F70022671EC4C9100080073F /* OCActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCActivity.m; sourceTree = "<group>"; };
@@ -737,8 +743,6 @@
 		F70F05571C889184008DAB36 /* UIImage+animatedGIF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+animatedGIF.h"; sourceTree = "<group>"; };
 		F70F05581C889184008DAB36 /* UIImage+animatedGIF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+animatedGIF.m"; sourceTree = "<group>"; };
 		F70F2BA4225F2D8900EBB73E /* ZIPFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ZIPFoundation.framework; path = Carthage/Build/iOS/ZIPFoundation.framework; sourceTree = "<group>"; };
-		F710E80D1EF95C9C00DC2427 /* CCIntro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCIntro.h; sourceTree = "<group>"; };
-		F710E80E1EF95C9C00DC2427 /* CCIntro.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCIntro.m; sourceTree = "<group>"; };
 		F710E80F1EF95C9C00DC2427 /* ImagesIntro.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = ImagesIntro.xcassets; sourceTree = "<group>"; };
 		F7151A811D477A4B00E6AF45 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7169A171EE590930086BD69 /* NCShares.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCShares.h; sourceTree = "<group>"; };
@@ -1187,6 +1191,7 @@
 		F7B6ACD522FC2BD4008AB646 /* NCXMLCommentsParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCXMLCommentsParser.h; sourceTree = "<group>"; };
 		F7B6ACD922FC2D14008AB646 /* NCComments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCComments.h; sourceTree = "<group>"; };
 		F7B6ACDA22FC2D15008AB646 /* NCComments.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NCComments.m; sourceTree = "<group>"; };
+		F7B7504A2397D38E004E13EC /* UIImage+fixedOrientation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+fixedOrientation.swift"; sourceTree = "<group>"; };
 		F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCDatabase.swift; sourceTree = "<group>"; };
 		F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCManageDatabase.swift; sourceTree = "<group>"; };
 		F7BB04851FD58ACB00BBFD2A /* cs-CZ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "cs-CZ"; path = "cs-CZ.lproj/Localizable.strings"; sourceTree = "<group>"; };
@@ -1463,10 +1468,8 @@
 				F733B65221997CC2001C1FFA /* TLPhotoPicker.framework in Frameworks */,
 				F7D4B6872295663D000C2C86 /* FirebaseAnalytics.framework in Frameworks */,
 				F7FC7D561DC1F93800BB2C6A /* libz.tbd in Frameworks */,
-				F7C40BE9219991A60004137E /* EAIntroView.framework in Frameworks */,
 				F7C40BE521998D5B0004137E /* MGSwipeTableCell.framework in Frameworks */,
 				F7D4B68B2295663D000C2C86 /* FirebaseInstanceID.framework in Frameworks */,
-				F7C40BEB219991AC0004137E /* EARestrictedScrollView.framework in Frameworks */,
 				F745B251222D871800346520 /* QRCodeReader.framework in Frameworks */,
 				F7A3771A1EB2364A002856D3 /* Fabric.framework in Frameworks */,
 				F72382C32295856A005B8A07 /* GoogleToolboxForMac.framework in Frameworks */,
@@ -1678,9 +1681,11 @@
 		F710E80C1EF95C9C00DC2427 /* Intro */ = {
 			isa = PBXGroup;
 			children = (
-				F710E80D1EF95C9C00DC2427 /* CCIntro.h */,
-				F710E80E1EF95C9C00DC2427 /* CCIntro.m */,
 				F710E80F1EF95C9C00DC2427 /* ImagesIntro.xcassets */,
+				379DC948237EF4DD008EC025 /* IntroView.swift */,
+				375CF03C238282B7000F2B53 /* IntroCollectionViewCell.swift */,
+				375CF03D238282B7000F2B53 /* IntroCollectionViewCell.xib */,
+				379DC94A237EF4EB008EC025 /* IntroView.xib */,
 			);
 			path = Intro;
 			sourceTree = "<group>";
@@ -2428,9 +2433,6 @@
 		F7BFFA991A24D7BB0044ED85 /* Utility */ = {
 			isa = PBXGroup;
 			children = (
-				F70BFC7320E0FA7C00C67599 /* NCUtility.swift */,
-				F707C26421A2DC5200F6181E /* NCStoreReview.swift */,
-				F78E7064219F096B006F23E4 /* NCAvatar.swift */,
 				F76C3B871C638A4C00DC4301 /* CCError.h */,
 				F76C3B881C638A4C00DC4301 /* CCError.m */,
 				F7A54C341C6267B500E2C8BF /* CCExifGeo.h */,
@@ -2441,10 +2443,14 @@
 				F7514EDB1C7B1336008F3338 /* CCHud.m */,
 				F7053E3C1C639DF500741EA5 /* CCUtility.h */,
 				F7053E3D1C639DF500741EA5 /* CCUtility.m */,
+				F78E7064219F096B006F23E4 /* NCAvatar.swift */,
+				F707C26421A2DC5200F6181E /* NCStoreReview.swift */,
+				F70BFC7320E0FA7C00C67599 /* NCUtility.swift */,
 				F78071071EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.h */,
 				F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */,
 				F73049B81CB567F000C7C320 /* NSString+TruncateToWidth.h */,
 				F73049B91CB567F000C7C320 /* NSString+TruncateToWidth.m */,
+				F7B7504A2397D38E004E13EC /* UIImage+fixedOrientation.swift */,
 			);
 			path = Utility;
 			sourceTree = "<group>";
@@ -3124,6 +3130,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				F79728D422F96F2E003CACA7 /* NCShareLinkFolderMenuView.xib in Resources */,
+				375CF03F238282B8000F2B53 /* IntroCollectionViewCell.xib in Resources */,
 				F760F78421F21F61006B1A73 /* ColorCollectionViewCell.xib in Resources */,
 				F7362A1F220C853A005101B5 /* LaunchScreen.storyboard in Resources */,
 				F75ADF451DC75FFE008A7347 /* CCLogin.storyboard in Resources */,
@@ -3134,6 +3141,7 @@
 				F7F54CF51E5B14C700E19C62 /* PlayButtonOverlayLarge@2x.png in Resources */,
 				F77D49A91DC238E500CDC568 /* loading.gif in Resources */,
 				F77444F622281649000D5EB0 /* NCGridMediaCell.xib in Resources */,
+				379DC94B237EF4EB008EC025 /* IntroView.xib in Resources */,
 				F78ACD4421903CF20088454D /* NCListCell.xib in Resources */,
 				F78ACD4621903D010088454D /* NCGridCell.xib in Resources */,
 				F7F54CF91E5B14C700E19C62 /* PlayButtonOverlayLargeTap@3x.png in Resources */,
@@ -3293,8 +3301,6 @@
 				"$(SRCROOT)/Carthage/Build/iOS/UICKeyChainStore.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/MGSwipeTableCell.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/DZNEmptyDataSet.framework",
-				"$(SRCROOT)/Carthage/Build/iOS/EAIntroView.framework",
-				"$(SRCROOT)/Carthage/Build/iOS/EARestrictedScrollView.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/JDStatusBarNotification.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/KTVHTTPCache.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/KTVCocoaHTTPServer.framework",
@@ -3482,6 +3488,7 @@
 				F73B4F0D1F470D9100BBEE4B /* nsLatin1Prober.cpp in Sources */,
 				F77B0DF51D118A16002130FE /* CCUtility.m in Sources */,
 				F762CB071EACB66200B38484 /* XLFormOptionsObject.m in Sources */,
+				375CF03E238282B8000F2B53 /* IntroCollectionViewCell.swift in Sources */,
 				F7C525A01E3B48B700FFE02C /* CCNotification.swift in Sources */,
 				F7F54D0E1E5B14C800E19C62 /* UIImage+MWPhotoBrowser.m in Sources */,
 				F7F54D091E5B14C800E19C62 /* MWPhoto.m in Sources */,
@@ -3588,7 +3595,6 @@
 				F760F78D21F21F61006B1A73 /* Protocols.swift in Sources */,
 				F762CAFF1EACB66200B38484 /* XLFormPickerCell.m in Sources */,
 				F7A321AD1E9E6AD50069AD1B /* CCAdvanced.m in Sources */,
-				F710E8101EF95C9C00DC2427 /* CCIntro.m in Sources */,
 				F77B0E411D118A16002130FE /* CCSplit.m in Sources */,
 				F73CC0781E813DFF006E3047 /* BKShiftingView.m in Sources */,
 				F7A3218C1E9E42B30069AD1B /* CCMenuAccount.m in Sources */,
@@ -3664,6 +3670,7 @@
 				F77B0E9B1D118A16002130FE /* CCBKPasscode.m in Sources */,
 				F760F77F21F21F61006B1A73 /* PhotoEditor+Controls.swift in Sources */,
 				F7169A1D1EE590930086BD69 /* NCSharesCell.m in Sources */,
+				F7B7504B2397D38F004E13EC /* UIImage+fixedOrientation.swift in Sources */,
 				F77B0EA61D118A16002130FE /* NSString+TruncateToWidth.m in Sources */,
 				F70022C21EC4C9100080073F /* OCNotifications.m in Sources */,
 				F70022BF1EC4C9100080073F /* OCFileDto.m in Sources */,
@@ -3690,6 +3697,7 @@
 				F7E0E1DC22327885006B0911 /* NCAudioRecorderViewController.swift in Sources */,
 				F70CAE3A1F8CF31A008125FD /* NCEndToEndEncryption.m in Sources */,
 				F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */,
+				379DC949237EF4DD008EC025 /* IntroView.swift in Sources */,
 				F73B4F0C1F470D9100BBEE4B /* nsHebrewProber.cpp in Sources */,
 				F762CAFB1EACB66200B38484 /* XLFormDatePickerCell.m in Sources */,
 				F762CB0F1EACB66200B38484 /* NSObject+XLFormAdditions.m in Sources */,
@@ -3842,7 +3850,7 @@
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				CURRENT_PROJECT_VERSION = 0;
+				CURRENT_PROJECT_VERSION = 6;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -3886,7 +3894,7 @@
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				CURRENT_PROJECT_VERSION = 0;
+				CURRENT_PROJECT_VERSION = 6;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -3936,7 +3944,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 0;
+				CURRENT_PROJECT_VERSION = 6;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -3986,7 +3994,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 0;
+				CURRENT_PROJECT_VERSION = 6;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -4028,7 +4036,7 @@
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				CURRENT_PROJECT_VERSION = 0;
+				CURRENT_PROJECT_VERSION = 6;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				ENABLE_BITCODE = YES;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -4075,7 +4083,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0;
+				CURRENT_PROJECT_VERSION = 6;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				ENABLE_BITCODE = YES;
 				FRAMEWORK_SEARCH_PATHS = (

+ 2 - 1
Share/ShareViewController.m

@@ -213,7 +213,7 @@
         
         (void)[[NCCommunication sharedInstance] uploadWithServerUrlFileName:fileNameServer fileNameLocalPath:fileNameLocal dateCreationFile:nil dateModificationFile:nil account:self.activeAccount progressHandler:^(NSProgress * progress) {
             [self.hud progress:progress.fractionCompleted];
-        } completionHandler:^(NSString *account, NSString *ocId, NSString *etag, NSDate *date, NSInteger errorCode, NSString *errorDescription) {
+        } completionHandler:^(NSString *account, NSString *ocId, NSString *etag, NSDate *date, int64_t size, NSInteger errorCode, NSString *errorDescription) {
             [self.hud hideHud];
             [self.filesName removeObject:fileName];
            
@@ -230,6 +230,7 @@
                 metadata.fileName = fileNameForUpload;
                 metadata.fileNameView = fileNameForUpload;
                 metadata.serverUrl = self.serverUrl;
+                metadata.size = size;
                 (void)[CCUtility insertTypeFileIconName:fileNameForUpload metadata:metadata];
                
                 metadata = [[NCManageDatabase sharedInstance] addMetadata:metadata];

+ 8 - 2
iOSClient/AppDelegate.m

@@ -942,8 +942,14 @@ PKPushRegistry *pushRegistry;
     // Test Maintenance
     if (self.maintenanceMode)
         return;
-        
-    (void)[[NCCreateMenuAdd alloc] initWithViewController:self.window.rootViewController view:[(UIButton *)sender superview]];
+    
+    tableDirectory *tableDirectory = [[NCManageDatabase sharedInstance] getTableDirectoryWithPredicate:[NSPredicate predicateWithFormat:@"account == %@ AND serverUrl == %@", self.activeAccount, self.activeMain.serverUrl]];
+    
+    if ([tableDirectory.permissions containsString:@"CK"]) {
+        (void)[[NCCreateMenuAdd alloc] initWithViewController:self.window.rootViewController view:[(UIButton *)sender superview]];
+    } else {
+        [self messageNotification:@"_warning_" description:@"_no_permission_add_file_" visible:YES delay:k_dismissAfterSecond type:TWMessageBarMessageTypeInfo errorCode:0];
+    }
 }
 
 - (void)selectedTabBarController:(NSInteger)index

+ 2 - 2
iOSClient/Brand/File_Provider_Extension.plist

@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>XPC!</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.25.0</string>
+	<string>2.25.1</string>
 	<key>CFBundleVersion</key>
-	<string>15</string>
+	<string>10</string>
 	<key>NSAppTransportSecurity</key>
 	<dict>
 		<key>NSAllowsArbitraryLoads</key>

+ 0 - 47
iOSClient/Brand/Intro/CCIntro.h

@@ -1,47 +0,0 @@
-//
-//  CCIntro.h
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 05/11/15.
-//  Copyright (c) 2017 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 <UIKit/UIKit.h>
-#import <EAIntroView/EAIntroView.h>
-
-#import "CCUtility.h"
-
-@protocol CCIntroDelegate;
-
-@interface CCIntro : UIView <EAIntroDelegate>
-
-- (id)initWithDelegate:(id <CCIntroDelegate>)delegate delegateView:(UIView *)delegateView;
-
-@property (nonatomic, strong) EAIntroView *intro;
-@property (nonatomic, weak) id <CCIntroDelegate> delegate;
-@property (nonatomic, strong) UIView *rootView;
-
-- (void)show;
-
-@end
-
-@protocol CCIntroDelegate <NSObject>
-
-- (void)introFinishSelector:(NSInteger)selector;
-
-@end

+ 0 - 265
iOSClient/Brand/Intro/CCIntro.m

@@ -1,265 +0,0 @@
-//
-//  CCIntro.m
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 05/11/15.
-//  Copyright (c) 2017 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 "CCIntro.h"
-#import "AppDelegate.h"
-#import "NCBridgeSwift.h"
-
-@class NCBrowserWeb;
-
-@interface CCIntro ()
-{
-    int titlePositionY;
-    int titleIconPositionY;
-    int buttonPosition;
-    int safeAreaBottom;
-    
-    int selector;
-}
-@end
-
-@implementation CCIntro
-
-- (id)initWithDelegate:(id <CCIntroDelegate>)delegate delegateView:(UIView *)delegateView
-{
-    self = [super init];
-    
-    if (self) {
-        self.delegate = delegate;
-        self.rootView = delegateView;
-    }
-
-    return self;
-}
-
-- (UIStatusBarStyle)preferredStatusBarStyle
-{
-    return UIStatusBarStyleLightContent;
-}
-
-- (void)introWillFinish:(EAIntroView *)introView wasSkipped:(BOOL)wasSkipped
-{
-    [self.delegate introFinishSelector:selector];
-}
-
-- (void)introDidFinish:(EAIntroView *)introView wasSkipped:(BOOL)wasSkipped
-{
-}
-
-- (void)show
-{
-    [self showIntro];
-}
-
-- (void)showIntro
-{
-    //NSString *language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];
-    CGFloat height = self.rootView.bounds.size.height;
-    CGFloat width = self.rootView.bounds.size.width;
-    
-    if (height <= 568) { // iPhone 5
-        titleIconPositionY = 20;
-        titlePositionY = height / 2 + 40.0;
-        buttonPosition = height / 2 + 70.0;
-    } else {
-        titleIconPositionY = 40;
-        titlePositionY = height / 2 + 40.0;
-        buttonPosition = height / 2 + 120.0;
-    }
-    
-    // SafeArea
-    if (@available(iOS 11, *)) {
-        UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
-        if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
-            safeAreaBottom = [UIApplication sharedApplication].delegate.window.safeAreaInsets.right;
-        } else {
-            safeAreaBottom = [UIApplication sharedApplication].delegate.window.safeAreaInsets.bottom;
-        }
-    }
-    
-    // Button
-    
-    UIView *buttonView = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.rootView.bounds.size.width, height - buttonPosition)];
-    buttonView.userInteractionEnabled = YES ;
-    
-    UIButton *buttonLogin = [UIButton buttonWithType:UIButtonTypeRoundedRect];
-    buttonLogin.frame = CGRectMake(50.0, 0.0, width - 100.0, 40.0);
-    buttonLogin.layer.cornerRadius = 20;
-    buttonLogin.clipsToBounds = YES;
-    [buttonLogin setTitle:NSLocalizedString(@"_log_in_", nil) forState:UIControlStateNormal];
-    buttonLogin.titleLabel.font = [UIFont systemFontOfSize:14];
-    [buttonLogin setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
-    buttonLogin.backgroundColor = NCBrandColor.sharedInstance.customerText;
-    [buttonLogin addTarget:self action:@selector(login:) forControlEvents:UIControlEventTouchDown];
-    
-    [buttonView addSubview:buttonLogin];
-    
-    UIButton *buttonSignUp = [UIButton buttonWithType:UIButtonTypeRoundedRect];
-    buttonSignUp.frame = CGRectMake(50.0, 60.0, width - 100.0, 40.0);
-    buttonSignUp.layer.cornerRadius = 20;
-    buttonSignUp.clipsToBounds = YES;
-    [buttonSignUp setTitle:NSLocalizedString(@"_sign_up_", nil) forState:UIControlStateNormal];
-    buttonSignUp.titleLabel.font = [UIFont systemFontOfSize:14];
-    [buttonSignUp setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
-    buttonSignUp.backgroundColor = [UIColor colorWithRed:25.0/255.0 green:89.0/255.0 blue:141.0/255.0 alpha:1.000];
-    [buttonSignUp addTarget:self action:@selector(signUp:) forControlEvents:UIControlEventTouchDown];
-        
-    [buttonView addSubview:buttonSignUp];
-    
-    UIButton *buttonHost = [UIButton buttonWithType:UIButtonTypeRoundedRect];
-    buttonHost.frame = CGRectMake(50.0, height - buttonPosition - 30.0 - safeAreaBottom, width - 100.0, 20.0);
-    buttonHost.layer.cornerRadius = 20;
-    buttonHost.clipsToBounds = YES;
-    [buttonHost setTitle:NSLocalizedString(@"_host_your_own_server", nil) forState:UIControlStateNormal];
-    buttonHost.titleLabel.font = [UIFont systemFontOfSize:14];
-    [buttonHost setTitleColor:[UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:0.7] forState:UIControlStateNormal];
-    buttonHost.backgroundColor = [UIColor clearColor];
-    [buttonHost addTarget:self action:@selector(host:) forControlEvents:UIControlEventTouchDown];
-    
-    [buttonView addSubview:buttonHost];
-    
-    // Pages
-    
-    /*
-    EAIntroPage *page1 = [EAIntroPage pageWithCustomViewFromNibNamed:@"NCIntroPage1"];
-    page1.customView.backgroundColor = [NCBrandColor.sharedInstance customer];
-    UILabel *titlePage1 = (UILabel *)[page1.customView viewWithTag:1];
-    titlePage1.text = NSLocalizedString(@"_intro_1_title_", nil);
-    */
-    
-    EAIntroPage *page1 = [EAIntroPage page];
-
-    page1.titleIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"intro1"]];
-    page1.titleIconPositionY = titleIconPositionY;
-
-    page1.title = NSLocalizedString(@"_intro_1_title_", nil);
-    page1.titlePositionY = titlePositionY;
-    page1.titleColor = NCBrandColor.sharedInstance.customerText;
-    page1.titleFont = [UIFont systemFontOfSize:23];
-
-    page1.bgColor = NCBrandColor.sharedInstance.customer;
-    page1.showTitleView = YES;
-
-    EAIntroPage *page2 = [EAIntroPage page];
-
-    page2.titleIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"intro2"]];
-    page2.titleIconPositionY = titleIconPositionY;
-
-    page2.title = NSLocalizedString(@"_intro_2_title_", nil);
-    page2.titlePositionY = titlePositionY;
-    page2.titleColor = NCBrandColor.sharedInstance.customerText;
-    page2.titleFont = [UIFont systemFontOfSize:23];
-    
-    page2.bgColor = NCBrandColor.sharedInstance.customer;
-    page2.showTitleView = YES;
-
-    EAIntroPage *page3 = [EAIntroPage page];
-    
-    page3.titleIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"intro3"]];
-    page3.titleIconPositionY = titleIconPositionY;
-
-    page3.title = NSLocalizedString(@"_intro_3_title_", nil);
-    page3.titlePositionY = titlePositionY;
-    page3.titleColor = NCBrandColor.sharedInstance.customerText;
-    page3.titleFont = [UIFont systemFontOfSize:23];
-    
-    page3.bgColor = NCBrandColor.sharedInstance.customer;
-    page3.showTitleView = YES;
-
-    EAIntroPage *page4 = [EAIntroPage page];
-    
-    page4.titleIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"intro4"]];
-    page4.titleIconPositionY = titleIconPositionY;
-    
-    page4.title = NSLocalizedString(@"_intro_4_title_", nil);
-    page4.titlePositionY = titlePositionY;
-    page4.titleColor = NCBrandColor.sharedInstance.customerText;
-    page4.titleFont = [UIFont systemFontOfSize:23];
-    
-    page4.bgColor = NCBrandColor.sharedInstance.customer;
-    page4.showTitleView = YES;
-    
-    // INTRO
-    
-    self.intro = [[EAIntroView alloc] initWithFrame:self.rootView.bounds andPages:@[page1,page2,page3,page4]];
-
-    self.intro.tapToNext = NO;
-    self.intro.pageControlY = height - buttonPosition + 50;
-    self.intro.pageControl.pageIndicatorTintColor = NCBrandColor.sharedInstance.nextcloudSoft;
-    self.intro.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
-    self.intro.pageControl.backgroundColor = NCBrandColor.sharedInstance.customer;
-//    [intro.skipButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
-//    intro.skipButton.enabled = NO;
-    self.intro.swipeToExit = NO ;
-    self.intro.skipButton = nil ;
-    self.intro.titleView = buttonView;
-    self.intro.titleViewY = buttonPosition;
-    self.intro.swipeToExit = NO;
-    
-    /*
-    page1.onPageDidAppear = ^{
-        intro.skipButton.enabled = YES;
-        [UIView animateWithDuration:0.3f animations:^{
-            intro.skipButton.alpha = 1.f;
-        }];
-    };
-    page2.onPageDidDisappear = ^{
-        intro.skipButton.enabled = NO;
-        [UIView animateWithDuration:0.3f animations:^{
-            intro.skipButton.alpha = 0.f;
-        }];
-    };
-    */
-    
-    [self.intro setDelegate:self];
-    [self.intro showInView:self.rootView animateDuration:0];
-}
-
-#pragma --------------------------------------------------------------------------------------------
-#pragma mark ===== Action =====
-#pragma --------------------------------------------------------------------------------------------
-
-- (void)login:(id)sender
-{
-    selector = k_intro_login;
-    [self.intro hideWithFadeOutDuration:0.7];
-}
-
-- (void)signUp:(id)sender
-{
-    selector = k_intro_signup;
-    [self.intro hideWithFadeOutDuration:0.7];
-}
-
-- (void)host:(id)sender
-{
-    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
-
-    NCBrowserWeb *browserWebVC = [[UIStoryboard storyboardWithName:@"NCBrowserWeb" bundle:nil] instantiateInitialViewController];
-    
-    browserWebVC.urlBase = [NCBrandOptions sharedInstance].linkLoginHost;
-    
-    [appDelegate.window.rootViewController presentViewController:browserWebVC animated:YES completion:nil];
-}
-
-@end

+ 34 - 0
iOSClient/Brand/Intro/IntroCollectionViewCell.swift

@@ -0,0 +1,34 @@
+//
+//  IntroCollectionViewCell.swift
+//  Nextcloud
+//
+//  Created by Philippe Weidmann on 18.11.19.
+//  Copyright © 2019 Philippe Weidmann. All rights reserved.
+//
+//  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 UIKit
+
+class IntroCollectionViewCell: UICollectionViewCell {
+
+    @IBOutlet weak var titleLabel: UILabel!
+    @IBOutlet weak var imageView: UIImageView!
+    
+    override func awakeFromNib() {
+        super.awakeFromNib()
+    }
+
+}

+ 60 - 0
iOSClient/Brand/Intro/IntroCollectionViewCell.xib

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="introCell" id="gTV-IL-0wX" customClass="IntroCollectionViewCell" customModule="Nextcloud" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="337" height="462"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                <rect key="frame" x="0.0" y="0.0" width="337" height="462"/>
+                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                <subviews>
+                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bZc-Ai-h3y">
+                        <rect key="frame" x="8" y="426" width="321" height="28"/>
+                        <constraints>
+                            <constraint firstAttribute="height" relation="greaterThanOrEqual" constant="28" id="bXT-nO-EeQ"/>
+                        </constraints>
+                        <fontDescription key="fontDescription" type="system" pointSize="23"/>
+                        <nil key="textColor"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" image="intro1" translatesAutoresizingMaskIntoConstraints="NO" id="f3T-nC-cwA">
+                        <rect key="frame" x="93.5" y="8" width="150" height="410"/>
+                        <constraints>
+                            <constraint firstAttribute="width" relation="lessThanOrEqual" constant="150" id="jne-Xj-IAh"/>
+                        </constraints>
+                    </imageView>
+                </subviews>
+            </view>
+            <color key="backgroundColor" red="1" green="0.57637232540000005" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="f3T-nC-cwA" firstAttribute="centerX" secondItem="gTV-IL-0wX" secondAttribute="centerX" id="4le-ih-K34"/>
+                <constraint firstItem="bZc-Ai-h3y" firstAttribute="top" secondItem="f3T-nC-cwA" secondAttribute="bottom" constant="8" id="AWt-Zg-Blt"/>
+                <constraint firstItem="f3T-nC-cwA" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" constant="8" id="Eh0-Bq-FKp"/>
+                <constraint firstAttribute="bottom" secondItem="bZc-Ai-h3y" secondAttribute="bottom" constant="8" id="YBJ-eg-EmZ"/>
+                <constraint firstItem="bZc-Ai-h3y" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" constant="8" id="eNj-fx-een"/>
+                <constraint firstAttribute="trailing" secondItem="bZc-Ai-h3y" secondAttribute="trailing" constant="8" id="uif-cW-sAI"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
+            <size key="customSize" width="337" height="428"/>
+            <connections>
+                <outlet property="imageView" destination="f3T-nC-cwA" id="aRR-4x-Dwk"/>
+                <outlet property="titleLabel" destination="bZc-Ai-h3y" id="WAd-FO-VtY"/>
+            </connections>
+            <point key="canvasLocation" x="339.85507246376812" y="223.66071428571428"/>
+        </collectionViewCell>
+    </objects>
+    <resources>
+        <image name="intro1" width="200" height="200"/>
+    </resources>
+</document>

+ 144 - 0
iOSClient/Brand/Intro/IntroView.swift

@@ -0,0 +1,144 @@
+//
+//  IntroView.swift
+//  Nextcloud
+//
+//  Created by Philippe Weidmann on 15.11.19.
+//  Copyright © 2019 Philippe Weidmann. All rights reserved.
+//
+//  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 UIKit
+
+class IntroView: UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
+
+    @IBOutlet weak var backgroundView: UIView!
+    @IBOutlet weak var buttonLogin: UIButton!
+    @IBOutlet weak var buttonSignUp: UIButton!
+    @IBOutlet weak var buttonHost: UIButton!
+    @IBOutlet weak var introCollectionView: UICollectionView!
+    @IBOutlet weak var pageControl: UIPageControl!
+    
+    @objc var delegate: CCSplit?
+    private let titles = [NSLocalizedString("_intro_1_title_", comment: ""), NSLocalizedString("_intro_2_title_", comment: ""), NSLocalizedString("_intro_3_title_", comment: ""), NSLocalizedString("_intro_4_title_", comment: "")]
+    private let images = [UIImage(named: "intro1"), UIImage(named: "intro2"), UIImage(named: "intro3"), UIImage(named: "intro4")]
+    private var timerAutoScroll: Timer?
+
+    @objc func autoScroll() {
+        if(pageControl.currentPage + 1 >= titles.count) {
+            pageControl.currentPage = 0
+        }
+        else {
+            pageControl.currentPage += 1
+        }
+        introCollectionView.scrollToItem(at: IndexPath(row: pageControl.currentPage, section: 0), at: .centeredHorizontally, animated: true)
+    }
+
+    override func layoutSubviews() {
+        pageControl.currentPage = 0
+        introCollectionView.collectionViewLayout.invalidateLayout()
+    }
+
+    func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
+        return CGPoint.zero
+    }
+
+    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return titles.count
+    }
+
+    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "introCell", for: indexPath) as! IntroCollectionViewCell
+        cell.backgroundColor = NCBrandColor.sharedInstance.customer
+
+        cell.titleLabel.textColor = NCBrandColor.sharedInstance.customerText
+        cell.titleLabel.text = titles[indexPath.row]
+        cell.imageView.image = images[indexPath.row]
+        return cell
+    }
+
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+        return collectionView.bounds.size
+    }
+
+    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
+        timerAutoScroll = Timer.scheduledTimer(timeInterval: 5, target: self, selector: (#selector(IntroView.autoScroll)), userInfo: nil, repeats: true)
+        pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
+    }
+    
+    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
+        timerAutoScroll?.invalidate()
+    }
+
+    override func removeFromSuperview() {
+        super.removeFromSuperview()
+        timerAutoScroll?.invalidate()
+    }
+
+    @objc class func instanceFromNib() -> IntroView {
+        let view = UINib(nibName: "IntroView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! IntroView
+
+        view.buttonLogin.layer.cornerRadius = 20
+        view.buttonLogin.setTitleColor(.black, for: .normal)
+        view.buttonLogin.backgroundColor = NCBrandColor.sharedInstance.customerText
+        view.buttonLogin.setTitle(NSLocalizedString("_log_in_", comment: ""), for: .normal)
+
+        view.buttonSignUp.layer.cornerRadius = 20
+        view.buttonSignUp.setTitleColor(.white, for: .normal)
+        view.buttonSignUp.backgroundColor = UIColor(red: 25.0 / 255.0, green: 89.0 / 255.0, blue: 141.0 / 255.0, alpha: 1)
+        view.buttonSignUp.setTitle(NSLocalizedString("_sign_up_", comment: ""), for: .normal)
+
+        view.buttonHost.layer.cornerRadius = 20
+        view.buttonHost.setTitle(NSLocalizedString("_host_your_own_server", comment: ""), for: .normal)
+        view.buttonHost.setTitleColor(UIColor(red: 1, green: 1, blue: 1, alpha: 0.7), for: .normal)
+
+        view.introCollectionView.register(UINib(nibName: "IntroCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "introCell")
+        view.introCollectionView.dataSource = view
+        view.introCollectionView.delegate = view
+        view.introCollectionView.backgroundColor = NCBrandColor.sharedInstance.customer
+        view.pageControl.numberOfPages = view.titles.count
+        view.backgroundView.backgroundColor = NCBrandColor.sharedInstance.customer
+        view.timerAutoScroll = Timer.scheduledTimer(timeInterval: 5, target: view, selector: (#selector(IntroView.autoScroll)), userInfo: nil, repeats: true)
+
+        return view
+    }
+    
+    @IBAction func login(_ sender: Any) {
+        delegate?.introFinishSelector(Int(k_intro_login))
+        UIView.animate(withDuration: 1.7) {
+            self.alpha = 0
+        }
+    }
+    
+    @IBAction func signup(_ sender: Any) {
+        delegate?.introFinishSelector(Int(k_intro_signup))
+        UIView.animate(withDuration: 1.7) {
+            self.alpha = 0
+        }
+    }
+    
+    @IBAction func host(_ sender: Any) {
+        let appDelegate = UIApplication.shared.delegate as? AppDelegate
+        
+        let browserWebVC = UIStoryboard(name: "NCBrowserWeb", bundle: nil).instantiateInitialViewController() as? NCBrowserWeb
+        
+        browserWebVC?.urlBase = NCBrandOptions.sharedInstance.linkLoginHost
+        
+        if let browserWebVC = browserWebVC {
+            appDelegate?.window.rootViewController?.present(browserWebVC, animated: true)
+        }
+    }
+
+}

+ 118 - 0
iOSClient/Brand/Intro/IntroView.xib

@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina5_9" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="IntroView" customModule="Nextcloud" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eXx-EZ-qlO">
+                    <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
+                    <subviews>
+                        <button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="twJ-n3-mgv">
+                            <rect key="frame" x="52.666666666666657" y="501" width="270" height="40"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="270" id="fg7-vj-OWg"/>
+                                <constraint firstAttribute="height" constant="40" id="nuu-SU-mRi"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <state key="normal" title="Login"/>
+                            <connections>
+                                <action selector="login:" destination="iN0-l3-epB" eventType="touchUpInside" id="neB-f8-gWJ"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FfA-1J-1vc">
+                            <rect key="frame" x="52.666666666666657" y="557" width="270" height="40"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="270" id="XMy-Bo-AbU"/>
+                                <constraint firstAttribute="height" constant="40" id="pbU-Yz-Qz5"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <state key="normal" title="Signup"/>
+                            <connections>
+                                <action selector="signup:" destination="iN0-l3-epB" eventType="touchUpInside" id="hQK-vz-uRg"/>
+                            </connections>
+                        </button>
+                        <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="NgB-S6-3Cp">
+                            <rect key="frame" x="8" y="60" width="359" height="359"/>
+                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            <constraints>
+                                <constraint firstAttribute="width" secondItem="NgB-S6-3Cp" secondAttribute="height" multiplier="1:1" priority="750" id="2Vf-FT-E9n"/>
+                            </constraints>
+                            <collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="Yfp-WG-gMy">
+                                <size key="itemSize" width="0.0" height="0.0"/>
+                                <size key="headerReferenceSize" width="0.0" height="0.0"/>
+                                <size key="footerReferenceSize" width="0.0" height="0.0"/>
+                                <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
+                            </collectionViewFlowLayout>
+                        </collectionView>
+                        <pageControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="3" translatesAutoresizingMaskIntoConstraints="NO" id="Zxj-8i-ZOp">
+                            <rect key="frame" x="168" y="427" width="39" height="10"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="10" id="raN-SI-1Y0"/>
+                            </constraints>
+                        </pageControl>
+                        <button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Om8-k2-tHk">
+                            <rect key="frame" x="52.666666666666657" y="740" width="270" height="30"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="30" id="GNx-pk-SxY"/>
+                                <constraint firstAttribute="width" constant="270" id="edq-KT-xx7"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <state key="normal" title="Host"/>
+                            <connections>
+                                <action selector="host:" destination="iN0-l3-epB" eventType="touchUpInside" id="g4o-hg-ifv"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="twJ-n3-mgv" firstAttribute="top" secondItem="Zxj-8i-ZOp" secondAttribute="bottom" priority="250" constant="64" id="21a-6U-WrX"/>
+                        <constraint firstItem="twJ-n3-mgv" firstAttribute="centerX" secondItem="eXx-EZ-qlO" secondAttribute="centerX" id="664-10-bMf"/>
+                        <constraint firstItem="NgB-S6-3Cp" firstAttribute="leading" secondItem="eXx-EZ-qlO" secondAttribute="leading" constant="8" id="AUg-aI-b8x"/>
+                        <constraint firstItem="twJ-n3-mgv" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Zxj-8i-ZOp" secondAttribute="bottom" constant="8" id="CiK-vp-QWa"/>
+                        <constraint firstItem="Om8-k2-tHk" firstAttribute="bottom" secondItem="eXx-EZ-qlO" secondAttribute="bottomMargin" id="MI4-7x-BGg"/>
+                        <constraint firstItem="FfA-1J-1vc" firstAttribute="centerX" secondItem="eXx-EZ-qlO" secondAttribute="centerX" id="MV1-pv-egh"/>
+                        <constraint firstItem="Zxj-8i-ZOp" firstAttribute="centerX" secondItem="eXx-EZ-qlO" secondAttribute="centerX" id="Ps1-ur-W19"/>
+                        <constraint firstItem="NgB-S6-3Cp" firstAttribute="top" secondItem="eXx-EZ-qlO" secondAttribute="top" constant="60" id="Qvd-7E-KJI">
+                            <variation key="heightClass=compact" constant="8"/>
+                        </constraint>
+                        <constraint firstItem="Zxj-8i-ZOp" firstAttribute="top" secondItem="NgB-S6-3Cp" secondAttribute="bottom" constant="8" id="Ryu-kt-AaI"/>
+                        <constraint firstItem="Om8-k2-tHk" firstAttribute="centerX" secondItem="eXx-EZ-qlO" secondAttribute="centerX" id="Trv-Pp-F65"/>
+                        <constraint firstItem="NgB-S6-3Cp" firstAttribute="centerX" secondItem="eXx-EZ-qlO" secondAttribute="centerX" id="gUz-Nd-Ogo"/>
+                        <constraint firstItem="FfA-1J-1vc" firstAttribute="top" secondItem="twJ-n3-mgv" secondAttribute="bottom" constant="16" id="lwW-jL-d54"/>
+                        <constraint firstItem="Om8-k2-tHk" firstAttribute="top" relation="greaterThanOrEqual" secondItem="FfA-1J-1vc" secondAttribute="bottom" constant="8" id="qhI-hY-G2p"/>
+                        <constraint firstAttribute="trailing" secondItem="NgB-S6-3Cp" secondAttribute="trailing" constant="8" id="ruS-K1-w3R"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="eXx-EZ-qlO" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="IDH-xX-Qnw"/>
+                <constraint firstItem="eXx-EZ-qlO" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Z86-yt-xah"/>
+                <constraint firstItem="eXx-EZ-qlO" firstAttribute="trailing" secondItem="iN0-l3-epB" secondAttribute="trailing" id="aA6-fr-CsP"/>
+                <constraint firstAttribute="bottom" secondItem="eXx-EZ-qlO" secondAttribute="bottom" id="gvf-hq-bop"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
+            <connections>
+                <outlet property="backgroundView" destination="eXx-EZ-qlO" id="IFL-aL-yiu"/>
+                <outlet property="buttonHost" destination="Om8-k2-tHk" id="Cg2-s2-qFe"/>
+                <outlet property="buttonLogin" destination="twJ-n3-mgv" id="SH1-qa-92p"/>
+                <outlet property="buttonSignUp" destination="FfA-1J-1vc" id="nfS-MO-U6Z"/>
+                <outlet property="introCollectionView" destination="NgB-S6-3Cp" id="x8f-W0-LmU"/>
+                <outlet property="pageControl" destination="Zxj-8i-ZOp" id="D4w-Yb-Rm3"/>
+            </connections>
+            <point key="canvasLocation" x="34.782608695652179" y="34.821428571428569"/>
+        </view>
+    </objects>
+</document>

+ 2 - 2
iOSClient/Brand/Share.plist

@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>XPC!</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.25.0</string>
+	<string>2.25.1</string>
 	<key>CFBundleVersion</key>
-	<string>15</string>
+	<string>10</string>
 	<key>NSAppTransportSecurity</key>
 	<dict>
 		<key>NSAllowsArbitraryLoads</key>

+ 2 - 2
iOSClient/Brand/iOSClient.plist

@@ -46,7 +46,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.25.0</string>
+	<string>2.25.1</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleURLTypes</key>
@@ -63,7 +63,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>15</string>
+	<string>10</string>
 	<key>FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED</key>
 	<true/>
 	<key>Fabric</key>

+ 17 - 0
iOSClient/CCGlobal.h

@@ -45,6 +45,23 @@
 //#if TARGET_OS_SIMULATOR
 //#endif
 
+// PERMISSION:
+//
+// Create file or folder or Full permission RGDNVW
+// Full permission for folder               RGDNVCK
+// Full permission for a file               SRGDNVW
+// Full permission                          SRMGDNVW
+// Update file                              SGDNVW
+// Update file                              RGD
+// Delete file                              RGNVW
+// Read file                                RDNVW
+// Create folder                            RGDNV
+// Read folder                              RDNVCK
+// Shared File read                         SGD
+// Sharing related                          SRGDNVCK
+// Reshare file, but not edit               SRGD
+
+
 #define CALL_ORIGIN NSLog(@"Origin: [%@]", [[[[NSThread callStackSymbols] objectAtIndex:1] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"[]"]] objectAtIndex:1])
 
 #endif

+ 30 - 0
iOSClient/Database/NCManageDatabase.swift

@@ -2099,6 +2099,36 @@ class NCManageDatabase: NSObject {
         }
     }
     
+    @objc func getMetadatas(predicate: NSPredicate, page: Int, limit: Int, sorted: String, ascending: Bool) -> [tableMetadata]? {
+        
+        let realm = try! Realm()
+        realm.refresh()
+        
+        let results : Results<tableMetadata>
+        results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending)
+        
+        if results.count > 0 {
+        
+            let nFrom = (page - 1) * limit
+            let nTo = nFrom + (limit - 1)
+            var metadatas = [tableMetadata]()
+            
+            for n in nFrom...nTo {
+                if n == results.count {
+                    break
+                }
+                let metadata = tableMetadata.init(value: results[n])
+                metadatas.append(metadata)
+            }
+            
+            return metadatas
+            
+        } else {
+            
+            return nil
+        }
+    }
+    
     @objc func getMetadataAtIndex(predicate: NSPredicate, sorted: String, ascending: Bool, index: Int) -> tableMetadata? {
         
         let realm = try! Realm()

+ 48 - 41
iOSClient/Login/NCLoginWeb.swift

@@ -102,49 +102,56 @@ extension NCLoginWeb: WKNavigationDelegate {
         
         if (urlString.hasPrefix(NCBrandOptions.sharedInstance.webLoginAutenticationProtocol) == true && urlString.contains("login") == true) {
             
+            var server: String = ""
+            var user: String = ""
+            var password: String = ""
+            
             let keyValue = url.path.components(separatedBy: "&")
-            if (keyValue.count >= 3) {
+            for value in keyValue {
+                if value.contains("server:") { server = value }
+                if value.contains("user:") { user = value }
+                if value.contains("password:") { password = value }
+            }
+            
+            if server != "" && user != "" && password != "" {
+                
+                var serverUrl: String = server.replacingOccurrences(of: "/server:", with: "")
+                
+                // Login Flow NC 12
+                if (NCBrandOptions.sharedInstance.use_login_web_personalized == false && serverUrl.hasPrefix("http://") == false && serverUrl.hasPrefix("https://") == false) {
+                    serverUrl = urlBase
+                }
+                
+                if (serverUrl.last == "/") {
+                    serverUrl = String(serverUrl.dropLast())
+                }
+                
+                let username: String = user.replacingOccurrences(of: "user:", with: "").replacingOccurrences(of: "+", with: " ")
+                let token: String = password.replacingOccurrences(of: "password:", with: "")
+                
+                let account : String = "\(username) \(serverUrl)"
+                
+                // NO account found, clear
+                if NCManageDatabase.sharedInstance.getAccounts() == nil { NCUtility.sharedInstance.removeAllSettings() }
+                
+                // STOP Intro
+                CCUtility.setIntro(true)
+                
+                // Add new account
+                NCManageDatabase.sharedInstance.deleteAccount(account)
+                NCManageDatabase.sharedInstance.addAccount(account, url: serverUrl, user: username, password: token)
+                
+                guard let tableAccount = NCManageDatabase.sharedInstance.setAccountActive(account) else {
+                    self.dismiss(animated: true, completion: nil)
+                    return
+                }
+                
+                appDelegate.settingActiveAccount(account, activeUrl: serverUrl, activeUser: username, activeUserID: tableAccount.userID, activePassword: token)
+                
+                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "initializeMain"), object: nil, userInfo: nil)
                 
-                if (keyValue[0].contains("server:") && keyValue[1].contains("user:") && keyValue[2].contains("password:")) {
-                    
-                    var serverUrl : String = keyValue[0].replacingOccurrences(of: "/server:", with: "")
-                    
-                    // Login Flow NC 12
-                    if (NCBrandOptions.sharedInstance.use_login_web_personalized == false && serverUrl.hasPrefix("http://") == false && serverUrl.hasPrefix("https://") == false) {
-                        serverUrl = urlBase
-                    }
-                    
-                    if (serverUrl.last == "/") {
-                        serverUrl = String(serverUrl.dropLast())
-                    }
-                    
-                    let username : String = keyValue[1].replacingOccurrences(of: "user:", with: "").replacingOccurrences(of: "+", with: " ")
-                    let token : String = keyValue[2].replacingOccurrences(of: "password:", with: "")
-                    
-                    let account : String = "\(username) \(serverUrl)"
-                    
-                    // NO account found, clear
-                    if NCManageDatabase.sharedInstance.getAccounts() == nil { NCUtility.sharedInstance.removeAllSettings() }
-                        
-                    // STOP Intro
-                    CCUtility.setIntro(true)
-                        
-                    // Add new account
-                    NCManageDatabase.sharedInstance.deleteAccount(account)
-                    NCManageDatabase.sharedInstance.addAccount(account, url: serverUrl, user: username, password: token)
-                        
-                    guard let tableAccount = NCManageDatabase.sharedInstance.setAccountActive(account) else {
-                        self.dismiss(animated: true, completion: nil)
-                        return
-                    }
-                        
-                    appDelegate.settingActiveAccount(account, activeUrl: serverUrl, activeUser: username, activeUserID: tableAccount.userID, activePassword: token)
-                        
-                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "initializeMain"), object: nil, userInfo: nil)
-                    
-                    self.dismiss(animated: true) {
-                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "dismissCCLogin"), object: nil, userInfo: nil)
-                    } 
+                self.dismiss(animated: true) {
+                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "dismissCCLogin"), object: nil, userInfo: nil)
                 }
             }
         }

+ 24 - 0
iOSClient/Main/CCMain.m

@@ -213,6 +213,15 @@
         
             // Read (file) Folder
             [self readFileReloadFolder];
+            
+            // TEST
+            /*
+            NSString *directoryPath = [CCUtility returnPathfromServerUrl:self.serverUrl activeUrl:appDelegate.activeUrl];
+            
+            [[NCCommunication sharedInstance] searchReadFolderWithServerUrl:appDelegate.activeUrl user:appDelegate.activeUserID directoryPath:directoryPath lastFileName:@"" limit:100 account:appDelegate.activeAccount completionHandler:^(NSString *account, NSArray *files, NSInteger errorCode, NSString *message) {
+                
+            }];
+            */
         }
     }
 
@@ -1478,6 +1487,13 @@
         
     } else  {
         
+        // verify permission
+        BOOL permission = [[NCUtility sharedInstance] permissionsContainsString:metadata.permissions permissions:@"RGD"]; // Update file
+        if (permission == false) {
+            [appDelegate messageNotification:@"_error_" description:@"_no_permission_modify_file_" visible:YES delay:k_dismissAfterSecond type:TWMessageBarMessageTypeError errorCode:k_CCErrorInternalError];
+            return;
+        }
+        
         // Plain
         
         NSString *fileNameNew = [CCUtility removeForbiddenCharactersServer:fileName];
@@ -1563,6 +1579,13 @@
 
 - (void)moveFileOrFolderMetadata:(tableMetadata *)metadata serverUrlTo:(NSString *)serverUrlTo numFile:(NSInteger)numFile ofFile:(NSInteger)ofFile
 {
+    // verify permission
+    BOOL permission = [[NCUtility sharedInstance] permissionsContainsString:metadata.permissions permissions:@"RGNVW"]; // Delete file
+    if (permission == false) {
+        [appDelegate messageNotification:@"_error_" description:@"_no_permission_modify_file_" visible:YES delay:k_dismissAfterSecond type:TWMessageBarMessageTypeError errorCode:k_CCErrorInternalError];
+        return;
+    }
+    
     [[OCNetworking sharedManager] readFileWithAccount:appDelegate.activeAccount serverUrl:serverUrlTo fileName:metadata.fileName completion:^(NSString *account, tableMetadata *metadataReadFile, NSString *message, NSInteger errorCode) {
         
         if (errorCode == 0 && [account isEqualToString:appDelegate.activeAccount]) {
@@ -1744,6 +1767,7 @@
 - (void)createFolder:(NSString *)fileNameFolder serverUrl:(NSString *)serverUrl
 {
     fileNameFolder = [CCUtility removeForbiddenCharactersServer:fileNameFolder];
+    fileNameFolder = [[NCUtility sharedInstance] createFileName:fileNameFolder serverUrl:self.serverUrl account:appDelegate.activeAccount];
     if (![fileNameFolder length]) return;
     NSString *ocIdTemp = [[NSUUID UUID] UUIDString];
     

+ 2 - 3
iOSClient/Main/CCSplit.h

@@ -25,13 +25,12 @@
 
 #import "CCLogin.h"
 #import "CCDetail.h"
-#import "CCIntro.h"
 
-@interface CCSplit : UISplitViewController <UISplitViewControllerDelegate, CCIntroDelegate>
+@interface CCSplit : UISplitViewController <UISplitViewControllerDelegate>
 
 @property (nonatomic, strong) NSString *version;
 @property (nonatomic, strong) NSString *build;
 
-@property (nonatomic, strong) CCIntro *intro;
+- (void)introFinishSelector:(NSInteger)selector;
 
 @end

+ 5 - 4
iOSClient/Main/CCSplit.m

@@ -136,10 +136,10 @@
     } else {
     
         if ([CCUtility getIntro] == NO) {
-        
-            _intro = [[CCIntro alloc] initWithDelegate:self delegateView:self.view];
-            [_intro show];
-        
+            IntroView *intro = [IntroView instanceFromNib];
+            intro.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
+            intro.delegate = self;
+            [self.view addSubview:intro];
         } else {
             
             if (appDelegate.activeAccount.length == 0) {
@@ -275,6 +275,7 @@
     // simply create a property of 'BOOL' type
     BOOL isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);
     
+    /*
     // detect Dark Mode
     /*
     if (@available(iOS 13.0, *)) {

+ 2 - 21
iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift

@@ -107,7 +107,7 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate, PhotoEdi
         var section : XLFormSectionDescriptor
         var row : XLFormRowDescriptor
         
-        // Section Photo Editor only for one photo & IMI
+        // Section Photo Editor only for one photo
         
         if assets.count == 1 && (assets[0] as! PHAsset).mediaType == PHAssetMediaType.image && self.imagePreview != nil {
             
@@ -124,18 +124,6 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate, PhotoEdi
             row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0)
             
             section.addFormRow(row)
-            
-            if NCBrandOptions.sharedInstance.use_imi_viewer {
-                
-                row = XLFormRowDescriptor(tag: "createIMI", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_im_create_new_file", tableName: "IMLocalizable", bundle: Bundle.main, value: "", comment: ""))
-                row.value = 0
-                row.cellConfig["backgroundColor"] = NCBrandColor.sharedInstance.backgroundForm
-                
-                row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0)
-                row.cellConfig["textLabel.textColor"] = NCBrandColor.sharedInstance.textView
-                
-                section.addFormRow(row)
-            }
         }
         
         // Section: Destination Folder
@@ -249,14 +237,7 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate, PhotoEdi
         
         super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue)
         
-        if formRow.tag == "createIMI" {
-            if (formRow.value! as AnyObject).boolValue  == true {
-                
-            } else {
-                
-            }
-        }
-        else if formRow.tag == "useFolderAutoUpload" {
+        if formRow.tag == "useFolderAutoUpload" {
             
             if (formRow.value! as AnyObject).boolValue  == true {
                 

+ 25 - 18
iOSClient/Main/Create cloud/NCCreateMenuAdd.swift

@@ -39,27 +39,31 @@ class NCCreateMenuAdd: NSObject {
         ActionSheetItemCell.appearance().backgroundColor = NCBrandColor.sharedInstance.backgroundForm
         ActionSheetItemCell.appearance().titleColor = NCBrandColor.sharedInstance.textView
         
-        items.append(ActionSheetItem(title: NSLocalizedString("_upload_photos_videos_", comment: ""), value: 1, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "file_photo"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
+        items.append(ActionSheetItem(title: NSLocalizedString("_upload_photos_videos_", comment: ""), value: 10, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "file_photo"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
         
-        items.append(ActionSheetItem(title: NSLocalizedString("_upload_file_", comment: ""), value: 2, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "file"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
+        items.append(ActionSheetItem(title: NSLocalizedString("_upload_file_", comment: ""), value: 20, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "file"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
         
-        items.append(ActionSheetItem(title: NSLocalizedString("_upload_file_text_", comment: ""), value: 3, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "file_txt"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
+        if NCBrandOptions.sharedInstance.use_imi_viewer {
+            items.append(ActionSheetItem(title: NSLocalizedString("_im_create_new_file", tableName: "IMLocalizable", bundle: Bundle.main, value: "", comment: ""), value: 21, image: CCGraphics.scale(UIImage.init(named: "imagemeter"), to: CGSize(width: 25, height: 25), isAspectRation: true)))
+        }
+        
+        items.append(ActionSheetItem(title: NSLocalizedString("_upload_file_text_", comment: ""), value: 30, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "file_txt"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
         
 #if !targetEnvironment(simulator)
         if #available(iOS 11.0, *) {
-            items.append(ActionSheetItem(title: NSLocalizedString("_scans_document_", comment: ""), value: 4, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "scan"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
+            items.append(ActionSheetItem(title: NSLocalizedString("_scans_document_", comment: ""), value: 40, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "scan"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
         }
 #endif
         
-        items.append(ActionSheetItem(title: NSLocalizedString("_create_voice_memo_", comment: ""), value: 5, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "microphone"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
+        items.append(ActionSheetItem(title: NSLocalizedString("_create_voice_memo_", comment: ""), value: 50, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "microphone"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)))
 
-        items.append(ActionSheetItem(title: NSLocalizedString("_create_folder_", comment: ""), value: 6, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "folder"), width: 50, height: 50, color: NCBrandColor.sharedInstance.brandElement)))
+        items.append(ActionSheetItem(title: NSLocalizedString("_create_folder_", comment: ""), value: 60, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "folder"), width: 50, height: 50, color: NCBrandColor.sharedInstance.brandElement)))
         
         if let richdocumentsMimetypes = NCManageDatabase.sharedInstance.getRichdocumentsMimetypes(account: appDelegate.activeAccount) {
             if richdocumentsMimetypes.count > 0 {
-                items.append(ActionSheetItem(title: NSLocalizedString("_create_new_document_", comment: ""), value: 7, image: UIImage.init(named: "create_file_document")))
-                items.append(ActionSheetItem(title: NSLocalizedString("_create_new_spreadsheet_", comment: ""), value: 8, image: UIImage(named: "create_file_xls")))
-                items.append(ActionSheetItem(title: NSLocalizedString("_create_new_presentation_", comment: ""), value: 9, image: UIImage(named: "create_file_ppt")))
+                items.append(ActionSheetItem(title: NSLocalizedString("_create_new_document_", comment: ""), value: 70, image: UIImage.init(named: "create_file_document")))
+                items.append(ActionSheetItem(title: NSLocalizedString("_create_new_spreadsheet_", comment: ""), value: 80, image: UIImage(named: "create_file_xls")))
+                items.append(ActionSheetItem(title: NSLocalizedString("_create_new_presentation_", comment: ""), value: 90, image: UIImage(named: "create_file_ppt")))
             }
         }
         
@@ -67,25 +71,28 @@ class NCCreateMenuAdd: NSObject {
         
         let actionSheet = ActionSheet(items: items) { sheet, item in
             
-            if item.value as? Int == 1 { self.appDelegate.activeMain.openAssetsPickerController() }
-            if item.value as? Int == 2 { self.appDelegate.activeMain.openImportDocumentPicker() }
-            if item.value as? Int == 3 {
+            if item.value as? Int == 10 { self.appDelegate.activeMain.openAssetsPickerController() }
+            if item.value as? Int == 20 { self.appDelegate.activeMain.openImportDocumentPicker() }
+            if item.value as? Int == 21 {
+                _ = IMCreate.init(serverUrl: self.appDelegate.activeMain.serverUrl)
+            }
+            if item.value as? Int == 30 {
                 let storyboard = UIStoryboard(name: "NCText", bundle: nil)
                 let controller = storyboard.instantiateViewController(withIdentifier: "NCText")
                 controller.modalPresentationStyle = UIModalPresentationStyle.pageSheet
                 self.appDelegate.activeMain.present(controller, animated: true, completion: nil)
             }
-            if item.value as? Int == 4 {
+            if item.value as? Int == 40 {
                 if #available(iOS 11.0, *) {
                     NCCreateScanDocument.sharedInstance.openScannerDocument(viewController: self.appDelegate.activeMain, openScan: true)
                 }
             }
             
-            if item.value as? Int == 5 { NCMainCommon.sharedInstance.startAudioRecorder() }
+            if item.value as? Int == 50 { NCMainCommon.sharedInstance.startAudioRecorder() }
             
-            if item.value as? Int == 6 { self.appDelegate.activeMain.createFolder() }
+            if item.value as? Int == 60 { self.appDelegate.activeMain.createFolder() }
             
-            if item.value as? Int == 7 {
+            if item.value as? Int == 70 {
                 guard let navigationController = UIStoryboard(name: "NCCreateFormUploadRichdocuments", bundle: nil).instantiateInitialViewController() else {
                     return
                 }
@@ -98,7 +105,7 @@ class NCCreateMenuAdd: NSObject {
                 
                 self.appDelegate.window.rootViewController?.present(navigationController, animated: true, completion: nil)
             }
-            if item.value as? Int == 8 {
+            if item.value as? Int == 80 {
                 guard let navigationController = UIStoryboard(name: "NCCreateFormUploadRichdocuments", bundle: nil).instantiateInitialViewController() else {
                     return
                 }
@@ -111,7 +118,7 @@ class NCCreateMenuAdd: NSObject {
                 
                 self.appDelegate.window.rootViewController?.present(navigationController, animated: true, completion: nil)
             }
-            if item.value as? Int == 9 {
+            if item.value as? Int == 90 {
                 guard let navigationController = UIStoryboard(name: "NCCreateFormUploadRichdocuments", bundle: nil).instantiateInitialViewController() else {
                     return
                 }

+ 14 - 23
iOSClient/Main/NCMainCommon.swift

@@ -947,7 +947,11 @@ class NCMainCommon: NSObject, PhotoEditorDelegate, NCAudioRecorderViewController
                 }
             }
         } else {
-            delete(metadatas: copyMetadatas, serverUrl:serverUrl, e2ee: e2ee, completion: completion)
+            delete(metadatas: copyMetadatas, serverUrl: serverUrl, e2ee: e2ee) { (errorCode, message) in
+                if errorCode != 0 {
+                    self.appDelegate.messageNotification("_delete_", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
+                }
+            }
         }
     }
     
@@ -959,6 +963,13 @@ class NCMainCommon: NSObject, PhotoEditorDelegate, NCAudioRecorderViewController
                 
         for metadata in metadatas {
             
+            // verify permission
+            let permission = NCUtility.sharedInstance.permissionsContainsString(metadata.permissions, permissions: "RGNVW")
+            if permission == false {
+                completion(Int(k_CCErrorInternalError), "_no_permission_delete_file_")
+                return
+            }
+            
             self.appDelegate.filterocId.add(metadata.ocId)
             
             let path = metadata.serverUrl + "/" + metadata.fileName
@@ -1310,31 +1321,11 @@ class NCNetworkingMain: NSObject, CCNetworkingDelegate {
                         return
                     }
                     
-                    let source = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))
-                    let destination =  URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
-                    
-                    try? FileManager().unzipItem(at: source, to: destination)
-                    
-                    let bundleDirectory = NCUtility.sharedInstance.IMGetBundleDirectory(metadata: metadata)
-                    
-                    if bundleDirectory.error {
-                        appDelegate.messageNotification("_error_", description: "Bundle imagemeter error. 🤷‍♂️", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
+                    if !NCUtility.sharedInstance.IMUnzip(metadata: metadata) {
+                        appDelegate.messageNotification("_error_", description: "Bundle imagemeter error. 🤷‍♂️", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: 0)
                         return
                     }
                     
-                    if let fileHandle = FileHandle(forReadingAtPath: bundleDirectory.immPath) {
-                        //                        let dataFormat = fileHandle.readData(ofLength: 1)
-                        //                        if dataFormat.starts(with: [0x01]) {
-                        //                            appDelegate.messageNotification("_error_", description: "File format binary error, library imagemeter not present. 🤷‍♂️", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
-                        //                            return;
-                        //                        }
-                        let dataZip = fileHandle.readData(ofLength: 4)
-                        if dataZip.starts(with: [0x50, 0x4b, 0x03, 0x04]) {
-                            try? FileManager().unzipItem(at: NSURL(fileURLWithPath: bundleDirectory.immPath) as URL, to: NSURL(fileURLWithPath: bundleDirectory.bundleDirectory) as URL)
-                        }
-                        fileHandle.closeFile()
-                    }
-                    
                     let storyboard = UIStoryboard(name: "IMImagemeter", bundle: nil)
                     let imiVC = storyboard.instantiateInitialViewController() as! IMImagemeterViewer
                     imiVC.metadata = metadata

+ 4 - 0
iOSClient/Main/NCPhotosPickerViewController.swift

@@ -48,6 +48,10 @@ class NCPhotosPickerViewController: NSObject {
         configure.maxSelectedAssets = self.maxSelectedAssets
         configure.selectedColor = NCBrandColor.sharedInstance.brand
         
+        if maxSelectedAssets == 1 {
+            configure.singleSelectedMode = true
+        }
+        
         let viewController = customPhotoPickerViewController(withTLPHAssets: { (assets) in
             
             for asset: TLPHAsset in assets {

+ 57 - 28
iOSClient/Networking/CCNetworking.m

@@ -1042,6 +1042,8 @@
     NSString *tempSession = metadata.session;
     NSString *errorMessage = @"";
     BOOL isE2EEDirectory = false;
+    BOOL isIMIFile = false;
+    if ([fileName.pathExtension.lowercaseString isEqualToString:@"imi"]) isIMIFile = true;
     
     tableAccount *tableAccount = [[NCManageDatabase sharedInstance] getAccountWithPredicate:[NSPredicate predicateWithFormat:@"account == %@", metadata.account]];
     if (tableAccount == nil) {
@@ -1102,40 +1104,67 @@
         }
         
     } else {
-            
-        // Replace Metadata
-        metadata.date = date;
-        if (isE2EEDirectory) {
-            metadata.e2eEncrypted = true;
-        } else {
-            metadata.e2eEncrypted = false;
-        }
-        metadata.etag = etag;
-        metadata.ocId = ocId;
-        metadata.session = @"";
-        metadata.sessionError = @"";
-        metadata.sessionTaskIdentifier = k_taskIdentifierDone;
-        metadata.status = k_metadataStatusNormal;
-        
-        [[NCManageDatabase sharedInstance] deleteMetadataWithPredicate:[NSPredicate predicateWithFormat:@"account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, metadata.fileName]];
-        metadata = [[NCManageDatabase sharedInstance] addMetadata:metadata];
-        
-        NSLog(@"[LOG] Insert new upload : %@ - ocId : %@", metadata.fileName, ocId);
-
+    
         // remove tempocId and adjust the directory provider storage
-        if ([tempocId isEqualToString:[CCUtility createMetadataIDFromAccount:metadata.account serverUrl:metadata.serverUrl fileNameView:metadata.fileNameView directory:metadata.directory]]) {
+        if (isIMIFile) {
+            
+            // Update metadata tempocId
+            [[NCManageDatabase sharedInstance] setMetadataSession:@"" sessionError:@"" sessionSelector:@"" sessionTaskIdentifier:k_taskIdentifierDone status:k_metadataStatusNormal predicate:[NSPredicate predicateWithFormat:@"ocId == %@", tempocId]];
+            
+            // Add metadata ocId
+            metadata.date = date;
+            if (isE2EEDirectory) {
+                metadata.e2eEncrypted = true;
+            } else {
+                metadata.e2eEncrypted = false;
+            }
+            metadata.etag = etag;
+            metadata.ocId = ocId;
+            metadata.session = @"";
+            metadata.sessionError = @"";
+            metadata.sessionTaskIdentifier = k_taskIdentifierDone;
+            metadata.status = k_metadataStatusNormal;
             
-            [[NCManageDatabase sharedInstance] deleteMetadataWithPredicate:[NSPredicate predicateWithFormat:@"ocId == %@", tempocId]];
+            metadata = [[NCManageDatabase sharedInstance] addMetadata:metadata];
             
-            // adjust file system Directory Provider Storage
-            if ([tempSession isEqualToString:k_upload_session_extension]) {
-                // this is for File Provider Extension [Apple Works and ... ?]
+            if (![tempocId isEqualToString:metadata.ocId]) {
                 [CCUtility copyFileAtPath:[NSString stringWithFormat:@"%@/%@", [CCUtility getDirectoryProviderStorage], tempocId] toPath:[NSString stringWithFormat:@"%@/%@", [CCUtility getDirectoryProviderStorage], metadata.ocId]];
+            }
+            
+        } else {
+            
+            // Replace Metadata
+            metadata.date = date;
+            if (isE2EEDirectory) {
+                metadata.e2eEncrypted = true;
             } else {
-                [CCUtility moveFileAtPath:[NSString stringWithFormat:@"%@/%@", [CCUtility getDirectoryProviderStorage], tempocId] toPath:[NSString stringWithFormat:@"%@/%@", [CCUtility getDirectoryProviderStorage], metadata.ocId]];
+                metadata.e2eEncrypted = false;
+            }
+            metadata.etag = etag;
+            metadata.ocId = ocId;
+            metadata.session = @"";
+            metadata.sessionError = @"";
+            metadata.sessionTaskIdentifier = k_taskIdentifierDone;
+            metadata.status = k_metadataStatusNormal;
+            
+            [[NCManageDatabase sharedInstance] deleteMetadataWithPredicate:[NSPredicate predicateWithFormat:@"account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, metadata.fileName]];
+            metadata = [[NCManageDatabase sharedInstance] addMetadata:metadata];
+            
+            NSLog(@"[LOG] Insert new upload : %@ - ocId : %@", metadata.fileName, ocId);
+            
+            if ([tempocId isEqualToString:[CCUtility createMetadataIDFromAccount:metadata.account serverUrl:metadata.serverUrl fileNameView:metadata.fileNameView directory:metadata.directory]]) {
+                
+                [[NCManageDatabase sharedInstance] deleteMetadataWithPredicate:[NSPredicate predicateWithFormat:@"ocId == %@", tempocId]];
+                
+                // adjust file system Directory Provider Storage
+                if ([tempSession isEqualToString:k_upload_session_extension]) {
+                    // this is for File Provider Extension [Apple Works and ... ?]
+                    [CCUtility copyFileAtPath:[NSString stringWithFormat:@"%@/%@", [CCUtility getDirectoryProviderStorage], tempocId] toPath:[NSString stringWithFormat:@"%@/%@", [CCUtility getDirectoryProviderStorage], metadata.ocId]];
+                } else {
+                    [CCUtility moveFileAtPath:[NSString stringWithFormat:@"%@/%@", [CCUtility getDirectoryProviderStorage], tempocId] toPath:[NSString stringWithFormat:@"%@/%@", [CCUtility getDirectoryProviderStorage], metadata.ocId]];
+                }
             }
         }
-        
 #ifndef EXTENSION
         
         // EXIF
@@ -1163,7 +1192,7 @@
  #endif
         
         // Add Local or Remove from cache
-        if ([CCUtility getDisableLocalCacheAfterUpload]) {
+        if ([CCUtility getDisableLocalCacheAfterUpload] && !isIMIFile) {
             [[NSFileManager defaultManager] removeItemAtPath:[CCUtility getDirectoryProviderStorageOcId:metadata.ocId] error:nil];
         } else {
             // Add Local

+ 3 - 4
iOSClient/Networking/NCNetworking.swift

@@ -29,10 +29,9 @@ import NCCommunication
     @objc optional func downloadProgress(_ progress: Double, fileName: String, ServerUrl: String, session: URLSession, task: URLSessionTask)
     @objc optional func uploadProgress(_ progress: Double, fileName: String, ServerUrl: String, session: URLSession, task: URLSessionTask)
     @objc optional func downloadComplete(fileName: String, serverUrl: String, etag: String?, date: NSDate?, dateLastModified: NSDate?, length: Double, description: String?, error: Error?, statusCode: Int)
-    @objc optional func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate? ,description: String?, error: Error?, statusCode: Int)
+    @objc optional func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, error: Error?, statusCode: Int)
 }
 
-
 @objc class NCNetworking: NSObject, NCCommunicationCommonDelegate {
     @objc public static let sharedInstance: NCNetworking = {
         let instance = NCNetworking()
@@ -69,8 +68,8 @@ import NCCommunication
         delegate?.uploadProgress?(progress, fileName: fileName, ServerUrl: ServerUrl, session: session, task: task)
     }
     
-    func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, description: String?, error: Error?, statusCode: Int) {
-        delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, description: description, error: error, statusCode: statusCode)
+    func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, error: Error?, statusCode: Int) {
+        delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size:size, description: description, error: error, statusCode: statusCode)
     }
     
     func downloadComplete(fileName: String, serverUrl: String, etag: String?, date: NSDate?, dateLastModified: NSDate?, length: Double, description: String?, error: Error?, statusCode: Int) {

+ 1 - 0
iOSClient/Nextcloud-Bridging-Header.h

@@ -27,3 +27,4 @@
 #import "NCRichDocumentTemplate.h"
 #import "HCFeatures.h"
 #import "NCComments.h"
+#import "CCSplit.h"

BIN
iOSClient/Supporting Files/ast.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/ca.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/da.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/de.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/el.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/Localizable.strings


+ 4 - 0
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -111,6 +111,10 @@
 "_screen_"                  = "Screen";
 "_wipe_account_"            = "Account wiped from server";
 "_appconfig_view_title_"    = "Account configuration in progress…";
+"_no_permission_add_file_"  = "You don't have permission to add files";
+"_no_permission_delete_file_" = "You don't have permission to delete files";
+"_no_permission_modify_file_" = "You don't have permission to modify files";
+"_request_upload_new_ver_"  = "The file has been modified, do you want to upload the new version ?";
 
 // App
 

BIN
iOSClient/Supporting Files/es-419.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-AR.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-HN.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-MX.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-NI.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-PA.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-PE.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-PR.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-PY.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-SV.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-UY.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/eu.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/fa.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/fr.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/gl.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/hr.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/hu.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/is.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/it.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/ko.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/nl.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/pl.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/ru.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/sl.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/sq.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/sr.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/sv.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/tr.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings


+ 1 - 0
iOSClient/Utility/CCUtility.h

@@ -222,6 +222,7 @@
 + (void)moveFileAtPath:(NSString *)atPath toPath:(NSString *)toPath;
 + (void)copyFileAtPath:(NSString *)atPath toPath:(NSString *)toPath;
 + (void)removeFileAtPath:(NSString *)atPath;
++ (void)createDirectoryAtPath:(NSString *)atPath;
 
 + (NSString *)deletingLastPathComponentFromServerUrl:(NSString *)serverUrl;
 + (NSString *)firtsPathComponentFromServerUrl:(NSString *)serverUrl activeUrl:(NSString *)activeUrl;

+ 23 - 1
iOSClient/Utility/CCUtility.m

@@ -819,8 +819,25 @@
     NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
     [formatter setDateFormat:@"yy-MM-dd HH-mm-ss"];
     NSString *fileNameDate = [formatter stringFromDate:[NSDate date]];
+    NSString *returnFileName;
     
-    return [NSString stringWithFormat:@"%@ %@.%@", fileName, fileNameDate, extension];
+    if ([fileName isEqualToString:@""] && ![extension isEqualToString:@""]) {
+        returnFileName = [NSString stringWithFormat:@"%@.%@", fileNameDate, extension];
+    }
+    
+    if (![fileName isEqualToString:@""] && [extension isEqualToString:@""]) {
+        returnFileName = [NSString stringWithFormat:@"%@ %@", fileName, fileNameDate];
+    }
+    
+    if ([fileName isEqualToString:@""] && [extension isEqualToString:@""]) {
+        returnFileName = fileNameDate;
+    }
+    
+    if (![fileName isEqualToString:@""] && ![extension isEqualToString:@""]) {
+        returnFileName = [NSString stringWithFormat:@"%@ %@.%@", fileName, fileNameDate, extension];
+    }
+    
+    return returnFileName;
 }
 
 + (NSString *)createFileName:(NSString *)fileName fileDate:(NSDate *)fileDate fileType:(PHAssetMediaType)fileType keyFileName:(NSString *)keyFileName keyFileNameType:(NSString *)keyFileNameType keyFileNameOriginal:(NSString *)keyFileNameOriginal
@@ -1221,6 +1238,11 @@
     }
 }
 
++ (void)createDirectoryAtPath:(NSString *)atPath
+{
+    [[NSFileManager defaultManager] createDirectoryAtPath:atPath withIntermediateDirectories:true attributes:nil error:nil];
+}
+
 + (NSString *)deletingLastPathComponentFromServerUrl:(NSString *)serverUrl
 {
     NSURL *url = [[NSURL URLWithString:[serverUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]] URLByDeletingLastPathComponent];

+ 87 - 4
iOSClient/Utility/NCUtility.swift

@@ -52,11 +52,14 @@ class NCUtility: NSObject {
                     
                     var name = NSString(string: resultFileName).deletingPathExtension
                     let ext = NSString(string: resultFileName).pathExtension
-                    
                     let characters = Array(name)
                     
                     if characters.count < 2 {
-                        resultFileName = name + " " + "1" + "." + ext
+                        if ext == "" {
+                            resultFileName = name + " " + "1"
+                        } else {
+                            resultFileName = name + " " + "1" + "." + ext
+                        }
                     } else {
                         let space = characters[characters.count-2]
                         let numChar = characters[characters.count-1]
@@ -64,9 +67,17 @@ class NCUtility: NSObject {
                         if (space == " " && num != nil) {
                             name = String(name.dropLast())
                             num = num! + 1
-                            resultFileName = name + "\(num!)" + "." + ext
+                            if ext == "" {
+                                resultFileName = name + "\(num!)"
+                            } else {
+                                resultFileName = name + "\(num!)" + "." + ext
+                            }
                         } else {
-                            resultFileName = name + " " + "1" + "." + ext
+                            if ext == "" {
+                                resultFileName = name + " " + "1"
+                            } else {
+                                resultFileName = name + " " + "1" + "." + ext
+                            }
                         }
                     }
                     
@@ -441,6 +452,68 @@ class NCUtility: NSObject {
         }
     }
     
+    func UIColorFromRGB(rgbValue: UInt32) -> UIColor {
+        return UIColor(
+            red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
+            green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
+            blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
+            alpha: CGFloat(1.0)
+        )
+    }
+    
+    func RGBFromUIColor(uicolorValue: UIColor) -> UInt32 {
+        
+        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
+
+        if uicolorValue.getRed(&red, green: &green, blue: &blue, alpha: &alpha) {
+
+            var colorAsUInt : UInt32 = 0
+
+            colorAsUInt += UInt32(red * 255.0) << 16 +
+                           UInt32(green * 255.0) << 8 +
+                           UInt32(blue * 255.0)
+
+            return colorAsUInt
+        }
+        
+        return 0
+    }
+    
+    func IMUnzip(metadata: tableMetadata) -> Bool {
+        
+        // bak
+        let atPathBak = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + metadata.fileNameView
+        let toPathBak = (CCUtility.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + metadata.fileNameView as NSString).deletingPathExtension + ".bak"
+        CCUtility.copyFile(atPath: atPathBak, toPath: toPathBak)
+        
+        let source = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))
+        let destination = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+        let removeAtPath = (CCUtility.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + metadata.fileNameView as NSString).deletingPathExtension
+        
+        try? FileManager.default.removeItem(atPath: removeAtPath)
+        try? FileManager().unzipItem(at: source, to: destination)
+        
+        let bundleDirectory = NCUtility.sharedInstance.IMGetBundleDirectory(metadata: metadata)
+        if bundleDirectory.error {
+            return false
+        }
+        
+        if let fileHandle = FileHandle(forReadingAtPath: bundleDirectory.immPath) {
+            //                        let dataFormat = fileHandle.readData(ofLength: 1)
+            //                        if dataFormat.starts(with: [0x01]) {
+            //                            appDelegate.messageNotification("_error_", description: "File format binary error, library imagemeter not present. 🤷‍♂️", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
+            //                            return;
+            //                        }
+            let dataZip = fileHandle.readData(ofLength: 4)
+            if dataZip.starts(with: [0x50, 0x4b, 0x03, 0x04]) {
+                try? FileManager().unzipItem(at: NSURL(fileURLWithPath: bundleDirectory.immPath) as URL, to: NSURL(fileURLWithPath: bundleDirectory.bundleDirectory) as URL)
+            }
+            fileHandle.closeFile()
+        }
+        
+        return true
+    }
+    
     func IMGetBundleDirectory(metadata: tableMetadata) -> bundleDirectoryType {
         
         var error = true
@@ -462,6 +535,16 @@ class NCUtility: NSObject {
         
         return bundleDirectoryType(error: error, bundleDirectory: bundleDirectory, immPath: immPath)
     }
+    
+    @objc func permissionsContainsString(_ metadataPermissions: String, permissions: String) -> Bool {
+        
+        for char in permissions {
+            if metadataPermissions.contains(char) == false {
+                return false
+            }
+        }
+        return true
+    }
 }
 
 class ActionSheetDeleteItem: ActionSheetItem {

+ 89 - 0
iOSClient/Utility/UIImage+fixedOrientation.swift

@@ -0,0 +1,89 @@
+//
+//  UIColor+fixedOrientation.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 27/11/2019.
+//  Copyright © 2019 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
+
+extension UIImage {
+    
+    /// Fix image orientaton to protrait up
+    func fixedOrientation() -> UIImage? {
+        guard imageOrientation != UIImage.Orientation.up else {
+            // This is default orientation, don't need to do anything
+            return self.copy() as? UIImage
+        }
+        
+        guard let cgImage = self.cgImage else {
+            // CGImage is not available
+            return nil
+        }
+        
+        guard let colorSpace = cgImage.colorSpace, let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
+            return nil // Not able to create CGContext
+        }
+        
+        var transform: CGAffineTransform = CGAffineTransform.identity
+        
+        switch imageOrientation {
+        case .down, .downMirrored:
+            transform = transform.translatedBy(x: size.width, y: size.height)
+            transform = transform.rotated(by: CGFloat.pi)
+        case .left, .leftMirrored:
+            transform = transform.translatedBy(x: size.width, y: 0)
+            transform = transform.rotated(by: CGFloat.pi / 2.0)
+        case .right, .rightMirrored:
+            transform = transform.translatedBy(x: 0, y: size.height)
+            transform = transform.rotated(by: CGFloat.pi / -2.0)
+        case .up, .upMirrored:
+            break
+        @unknown default:
+            break
+        }
+        
+        // Flip image one more time if needed to, this is to prevent flipped image
+        switch imageOrientation {
+        case .upMirrored, .downMirrored:
+            transform = transform.translatedBy(x: size.width, y: 0)
+            transform = transform.scaledBy(x: -1, y: 1)
+        case .leftMirrored, .rightMirrored:
+            transform = transform.translatedBy(x: size.height, y: 0)
+            transform = transform.scaledBy(x: -1, y: 1)
+        case .up, .down, .left, .right:
+            break
+        @unknown default:
+            break
+        }
+        
+        ctx.concatenate(transform)
+        
+        switch imageOrientation {
+        case .left, .leftMirrored, .right, .rightMirrored:
+            ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
+        default:
+            ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
+            break
+        }
+        
+        guard let newCGImage = ctx.makeImage() else { return nil }
+        return UIImage.init(cgImage: newCGImage, scale: 1, orientation: .up)
+    }
+}

+ 13 - 1
iOSClient/Viewer/NCViewerDocumentWeb.swift

@@ -55,7 +55,19 @@ class NCViewerDocumentWeb: NSObject {
         let preferences = WKPreferences()
         let configuration = WKWebViewConfiguration()
 
-        preferences.javaScriptEnabled = true
+        preferences.javaScriptEnabled = false
+
+        // Detect file xls, xlss for enable javascript
+        if fileNameExtension == "XLS" || fileNameExtension == "XLSX" {
+            if let fileHandle = FileHandle(forReadingAtPath: fileNamePath) {
+                let data = fileHandle.readData(ofLength: 4)
+                if data.starts(with: [0x50, 0x4b, 0x03, 0x04]) { // "PK\003\004"
+                    preferences.javaScriptEnabled = true
+                }
+                fileHandle.closeFile()
+            }
+        }
+        
         configuration.preferences = preferences
         
         let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: Int(detail.view.bounds.size.width), height: Int(detail.view.bounds.size.height) - Int(k_detail_Toolbar_Height) - safeAreaBottom - 1), configuration: configuration)