Browse Source

V 4.9.3 (#2695)

* biometry
* improved / fix forbidden charactes
* fix media deleteFile
* Livephoto Server NC 28 (#2683)
* NextcloudKit 2.9.2
* fix(i18n): Improved grammar and fixed typos (#2692)

---------

Co-authored-by: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com>
Co-authored-by: Milen Pivchev <milen.pivchev@gmail.com>
Co-authored-by: rakekniven <2069590+rakekniven@users.noreply.github.com>
Marino Faggiana 1 year ago
parent
commit
dd7b55eb93
100 changed files with 466 additions and 535 deletions
  1. 6 6
      .github/workflows/additional-targets.yml
  2. 2 6
      .github/workflows/xcode.yml
  3. 1 1
      Brand/Database.swift
  4. 71 153
      Nextcloud.xcodeproj/project.pbxproj
  5. 44 42
      Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme
  6. 1 1
      Share/NCShareExtension+DataSource.swift
  7. 0 1
      Share/NCShareExtension+Files.swift
  8. 17 10
      iOSClient/AppDelegate.swift
  9. 5 16
      iOSClient/Data/NCDataSource.swift
  10. 6 6
      iOSClient/Data/NCManageDatabase+Capabilities.swift
  11. 13 0
      iOSClient/Data/NCManageDatabase+LocalFile.swift
  12. 41 92
      iOSClient/Data/NCManageDatabase+Metadata.swift
  13. 1 1
      iOSClient/Data/NCManageDatabase+Video.swift
  14. 7 3
      iOSClient/Data/NCManageDatabase.swift
  15. 12 3
      iOSClient/Diagnostics/NCCapabilitiesView.swift
  16. 1 1
      iOSClient/Extensions/UIAlertController+Extension.swift
  17. 0 1
      iOSClient/Favorites/NCFavorite.swift
  18. 15 2
      iOSClient/Files/NCFiles.swift
  19. 0 1
      iOSClient/Groupfolders/NCGroupfolders.swift
  20. 4 4
      iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
  21. 4 1
      iOSClient/Main/Create cloud/NCUploadAssets.swift
  22. 38 43
      iOSClient/Media/NCMedia.swift
  23. 25 66
      iOSClient/Menu/NCMedia+Menu.swift
  24. 11 2
      iOSClient/NCGlobal.swift
  25. 27 28
      iOSClient/NCImageCache.swift
  26. 7 1
      iOSClient/Networking/E2EE/NCNetworkingE2EECreateFolder.swift
  27. 6 3
      iOSClient/Networking/NCAutoUpload.swift
  28. 85 10
      iOSClient/Networking/NCNetworking.swift
  29. 5 4
      iOSClient/Networking/NCNetworkingProcessUpload.swift
  30. 1 1
      iOSClient/Networking/NCService.swift
  31. 0 1
      iOSClient/Offline/NCOffline.swift
  32. 1 2
      iOSClient/Select/NCSelect.swift
  33. 0 13
      iOSClient/Settings/NCKeychain.swift
  34. 3 2
      iOSClient/Settings/NCManageAutoUploadFileName.swift
  35. 2 2
      iOSClient/Settings/NCSettings.m
  36. 0 1
      iOSClient/Shares/NCShares.swift
  37. BIN
      iOSClient/Supporting Files/af.lproj/Localizable.strings
  38. BIN
      iOSClient/Supporting Files/an.lproj/Localizable.strings
  39. BIN
      iOSClient/Supporting Files/ar.lproj/Localizable.strings
  40. BIN
      iOSClient/Supporting Files/ast.lproj/Localizable.strings
  41. BIN
      iOSClient/Supporting Files/az.lproj/Localizable.strings
  42. BIN
      iOSClient/Supporting Files/be.lproj/Localizable.strings
  43. BIN
      iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings
  44. BIN
      iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings
  45. BIN
      iOSClient/Supporting Files/br.lproj/Localizable.strings
  46. BIN
      iOSClient/Supporting Files/bs.lproj/Localizable.strings
  47. BIN
      iOSClient/Supporting Files/ca.lproj/Localizable.strings
  48. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
  49. BIN
      iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings
  50. BIN
      iOSClient/Supporting Files/da.lproj/Localizable.strings
  51. BIN
      iOSClient/Supporting Files/de.lproj/Localizable.strings
  52. BIN
      iOSClient/Supporting Files/el.lproj/Localizable.strings
  53. BIN
      iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
  54. 4 5
      iOSClient/Supporting Files/en.lproj/Localizable.strings
  55. BIN
      iOSClient/Supporting Files/eo.lproj/Localizable.strings
  56. BIN
      iOSClient/Supporting Files/es-419.lproj/Localizable.strings
  57. BIN
      iOSClient/Supporting Files/es-AR.lproj/Localizable.strings
  58. BIN
      iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
  59. BIN
      iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
  60. BIN
      iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
  61. BIN
      iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
  62. BIN
      iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
  63. BIN
      iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
  64. BIN
      iOSClient/Supporting Files/es-HN.lproj/Localizable.strings
  65. BIN
      iOSClient/Supporting Files/es-MX.lproj/Localizable.strings
  66. BIN
      iOSClient/Supporting Files/es-NI.lproj/Localizable.strings
  67. BIN
      iOSClient/Supporting Files/es-PA.lproj/Localizable.strings
  68. BIN
      iOSClient/Supporting Files/es-PE.lproj/Localizable.strings
  69. BIN
      iOSClient/Supporting Files/es-PR.lproj/Localizable.strings
  70. BIN
      iOSClient/Supporting Files/es-PY.lproj/Localizable.strings
  71. BIN
      iOSClient/Supporting Files/es-SV.lproj/Localizable.strings
  72. BIN
      iOSClient/Supporting Files/es-UY.lproj/Localizable.strings
  73. BIN
      iOSClient/Supporting Files/es.lproj/Localizable.strings
  74. BIN
      iOSClient/Supporting Files/et_EE.lproj/Localizable.strings
  75. BIN
      iOSClient/Supporting Files/eu.lproj/Localizable.strings
  76. BIN
      iOSClient/Supporting Files/fa.lproj/Localizable.strings
  77. BIN
      iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings
  78. BIN
      iOSClient/Supporting Files/fo.lproj/Localizable.strings
  79. BIN
      iOSClient/Supporting Files/fr.lproj/Localizable.strings
  80. BIN
      iOSClient/Supporting Files/gd.lproj/Localizable.strings
  81. BIN
      iOSClient/Supporting Files/gl.lproj/Localizable.strings
  82. BIN
      iOSClient/Supporting Files/he.lproj/Localizable.strings
  83. BIN
      iOSClient/Supporting Files/hi_IN.lproj/Localizable.strings
  84. BIN
      iOSClient/Supporting Files/hr.lproj/Localizable.strings
  85. BIN
      iOSClient/Supporting Files/hsb.lproj/Localizable.strings
  86. BIN
      iOSClient/Supporting Files/hu.lproj/Localizable.strings
  87. BIN
      iOSClient/Supporting Files/hy.lproj/Localizable.strings
  88. BIN
      iOSClient/Supporting Files/ia.lproj/Localizable.strings
  89. BIN
      iOSClient/Supporting Files/id.lproj/Localizable.strings
  90. BIN
      iOSClient/Supporting Files/ig.lproj/Localizable.strings
  91. BIN
      iOSClient/Supporting Files/is.lproj/Localizable.strings
  92. BIN
      iOSClient/Supporting Files/it.lproj/Localizable.strings
  93. BIN
      iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings
  94. BIN
      iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings
  95. BIN
      iOSClient/Supporting Files/ka.lproj/Localizable.strings
  96. BIN
      iOSClient/Supporting Files/kab.lproj/Localizable.strings
  97. BIN
      iOSClient/Supporting Files/km.lproj/Localizable.strings
  98. BIN
      iOSClient/Supporting Files/kn.lproj/Localizable.strings
  99. BIN
      iOSClient/Supporting Files/ko.lproj/Localizable.strings
  100. BIN
      iOSClient/Supporting Files/la.lproj/Localizable.strings

+ 6 - 6
.github/workflows/additional-targets.yml

@@ -14,7 +14,7 @@ on:
 jobs:
 jobs:
   build-and-test:
   build-and-test:
     name: Build and Test
     name: Build and Test
-    runs-on: macOS-latest
+    runs-on: macos-latest
     if: github.event.pull_request.draft == false
     if: github.event.pull_request.draft == false
     env:
     env:
       PROJECT: Nextcloud.xcodeproj
       PROJECT: Nextcloud.xcodeproj
@@ -43,26 +43,26 @@ jobs:
       run: wget "https://raw.githubusercontent.com/firebase/quickstart-ios/master/mock-GoogleService-Info.plist" -O GoogleService-Info.plist
       run: wget "https://raw.githubusercontent.com/firebase/quickstart-ios/master/mock-GoogleService-Info.plist" -O GoogleService-Info.plist
     - name: Build iOS Share
     - name: Build iOS Share
       run: |
       run: |
-        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION"
+        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION" | xcpretty
       env:
       env:
           SCHEME: Share
           SCHEME: Share
     - name: Build iOS File Extension
     - name: Build iOS File Extension
       run: |
       run: |
-        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION"
+        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION" | xcpretty
       env:
       env:
           SCHEME: File Provider Extension
           SCHEME: File Provider Extension
     - name: Build iOS Notification Extension
     - name: Build iOS Notification Extension
       run: |
       run: |
-        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION"
+        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION" | xcpretty
       env:
       env:
           SCHEME: Notification Service Extension
           SCHEME: Notification Service Extension
     - name: Build iOS Widget
     - name: Build iOS Widget
       run: |
       run: |
-        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION"
+        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION" | xcpretty
       env:
       env:
           SCHEME: Widget
           SCHEME: Widget
     - name: Build iOS Widget Dashboard IntentHandler
     - name: Build iOS Widget Dashboard IntentHandler
       run: |
       run: |
-        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION"
+        xcodebuild build -project $PROJECT -scheme "$SCHEME" -destination "$DESTINATION" | xcpretty
       env:
       env:
           SCHEME: WidgetDashboardIntentHandler
           SCHEME: WidgetDashboardIntentHandler

+ 2 - 6
.github/workflows/xcode.yml

@@ -14,7 +14,7 @@ on:
 jobs:
 jobs:
   build-and-test:
   build-and-test:
     name: Build and Test
     name: Build and Test
-    runs-on: macOS-latest
+    runs-on: macos-latest
     if: github.event.pull_request.draft == false
     if: github.event.pull_request.draft == false
     env:
     env:
       PROJECT: Nextcloud.xcodeproj
       PROJECT: Nextcloud.xcodeproj
@@ -44,11 +44,7 @@ jobs:
       run: wget "https://raw.githubusercontent.com/firebase/quickstart-ios/master/mock-GoogleService-Info.plist" -O GoogleService-Info.plist
       run: wget "https://raw.githubusercontent.com/firebase/quickstart-ios/master/mock-GoogleService-Info.plist" -O GoogleService-Info.plist
     - name: Install docker
     - name: Install docker
       run: |
       run: |
-        # Workaround for https://github.com/actions/runner-images/issues/8104
-        brew remove --ignore-dependencies qemu
-        curl -o ./qemu.rb https://raw.githubusercontent.com/Homebrew/homebrew-core/dc0669eca9479e9eeb495397ba3a7480aaa45c2e/Formula/qemu.rb
-        brew install ./qemu.rb
-
+        brew install colima
         brew install docker
         brew install docker
         colima start
         colima start
     - name: Create docker test server and export enviroment variables
     - name: Create docker test server and export enviroment variables

+ 1 - 1
Brand/Database.swift

@@ -26,4 +26,4 @@ import Foundation
 // Database Realm
 // Database Realm
 //
 //
 let databaseName                    = "nextcloud.realm"
 let databaseName                    = "nextcloud.realm"
-let databaseSchemaVersion: UInt64   = 324
+let databaseSchemaVersion: UInt64   = 331

+ 71 - 153
Nextcloud.xcodeproj/project.pbxproj

@@ -68,34 +68,22 @@
 		AFCE353727E4ED7B00FEA6C2 /* NCShareCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */; };
 		AFCE353727E4ED7B00FEA6C2 /* NCShareCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */; };
 		AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; };
 		AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; };
 		C0046CDD2A17B98400D87C9D /* LoginUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0046CDC2A17B98400D87C9D /* LoginUITests.swift */; };
 		C0046CDD2A17B98400D87C9D /* LoginUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0046CDC2A17B98400D87C9D /* LoginUITests.swift */; };
-		C03BA14A2A17BC57002C8BA3 /* XLForm in Frameworks */ = {isa = PBXBuildFile; productRef = C03BA1492A17BC57002C8BA3 /* XLForm */; };
-		C04E2F192A17BA78001BAD85 /* XLForm in Frameworks */ = {isa = PBXBuildFile; productRef = C04E2F182A17BA78001BAD85 /* XLForm */; };
 		C04E2F232A17BB4D001BAD85 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */; };
 		C04E2F232A17BB4D001BAD85 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */; };
 		D575039F27146F93008DC9DC /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; };
 		D575039F27146F93008DC9DC /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; };
 		D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; };
 		D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; };
 		F30A962F2A27ADF900D7BCFE /* EnvVars.stencil in Resources */ = {isa = PBXBuildFile; fileRef = F30A962E2A27ADF900D7BCFE /* EnvVars.stencil */; };
 		F30A962F2A27ADF900D7BCFE /* EnvVars.stencil in Resources */ = {isa = PBXBuildFile; fileRef = F30A962E2A27ADF900D7BCFE /* EnvVars.stencil */; };
 		F30A96312A27AEBF00D7BCFE /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; };
 		F30A96312A27AEBF00D7BCFE /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; };
 		F30A96322A27AEDD00D7BCFE /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; };
 		F30A96322A27AEDD00D7BCFE /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; };
-		F30A96342A2DFCD000D7BCFE /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = F30A96332A2DFCD000D7BCFE /* Realm */; };
-		F30A96362A2DFCD000D7BCFE /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F30A96352A2DFCD000D7BCFE /* RealmSwift */; };
-		F30A96382A2DFD2900D7BCFE /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = F30A96372A2DFD2900D7BCFE /* FirebaseDatabase */; };
-		F30A963A2A2DFD3100D7BCFE /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F30A96392A2DFD3100D7BCFE /* JGProgressHUD */; };
-		F30A963C2A2DFD3600D7BCFE /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = F30A963B2A2DFD3600D7BCFE /* SVGKit */; };
+		F3131EDD2B038E4A0018DB28 /* XLForm in Frameworks */ = {isa = PBXBuildFile; productRef = F3131EDC2B038E4A0018DB28 /* XLForm */; };
+		F3131EDF2B038F2A0018DB28 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = F3131EDE2B038F2A0018DB28 /* SnapshotTesting */; };
+		F3131EE12B038F560018DB28 /* SnapshotTestingHEIC in Frameworks */ = {isa = PBXBuildFile; productRef = F3131EE02B038F560018DB28 /* SnapshotTestingHEIC */; };
+		F3131EE32B038F9B0018DB28 /* PreviewSnapshotsTesting in Frameworks */ = {isa = PBXBuildFile; productRef = F3131EE22B038F9B0018DB28 /* PreviewSnapshotsTesting */; };
 		F314F1112A30C11200BC7FAB /* PreviewSnapshots in Frameworks */ = {isa = PBXBuildFile; productRef = F314F1102A30C11200BC7FAB /* PreviewSnapshots */; };
 		F314F1112A30C11200BC7FAB /* PreviewSnapshots in Frameworks */ = {isa = PBXBuildFile; productRef = F314F1102A30C11200BC7FAB /* PreviewSnapshots */; };
 		F314F1142A30E2DE00BC7FAB /* View+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E8A390295DC5E0006CB2D0 /* View+Extension.swift */; };
 		F314F1142A30E2DE00BC7FAB /* View+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E8A390295DC5E0006CB2D0 /* View+Extension.swift */; };
 		F31F69452A2F6D4600162F76 /* NextcloudSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F69442A2F6D4600162F76 /* NextcloudSnapshotTests.swift */; };
 		F31F69452A2F6D4600162F76 /* NextcloudSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F69442A2F6D4600162F76 /* NextcloudSnapshotTests.swift */; };
-		F31F694D2A2F6EFB00162F76 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = F31F694C2A2F6EFB00162F76 /* SnapshotTesting */; };
 		F31F69502A2F707E00162F76 /* SwiftUIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F694F2A2F707E00162F76 /* SwiftUIView+Extensions.swift */; };
 		F31F69502A2F707E00162F76 /* SwiftUIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31F694F2A2F707E00162F76 /* SwiftUIView+Extensions.swift */; };
-		F31F69522A2F89C400162F76 /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69512A2F89C400162F76 /* SVGKit */; };
-		F31F69542A2F89C400162F76 /* SwiftRichString in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69532A2F89C400162F76 /* SwiftRichString */; };
-		F31F69562A2F89C400162F76 /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69552A2F89C400162F76 /* FirebaseDatabase */; };
-		F31F69582A2F89C400162F76 /* XLForm in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69572A2F89C400162F76 /* XLForm */; };
-		F31F695C2A2F89C400162F76 /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = F31F695B2A2F89C400162F76 /* Realm */; };
-		F31F695E2A2F89C400162F76 /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F31F695D2A2F89C400162F76 /* JGProgressHUD */; };
 		F31F69612A2F907800162F76 /* __Snapshots__ in Resources */ = {isa = PBXBuildFile; fileRef = F31F69602A2F907800162F76 /* __Snapshots__ */; };
 		F31F69612A2F907800162F76 /* __Snapshots__ in Resources */ = {isa = PBXBuildFile; fileRef = F31F69602A2F907800162F76 /* __Snapshots__ */; };
 		F31F69642A2F929600162F76 /* PreviewSnapshots in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69632A2F929600162F76 /* PreviewSnapshots */; };
 		F31F69642A2F929600162F76 /* PreviewSnapshots in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69632A2F929600162F76 /* PreviewSnapshots */; };
-		F31F69662A2F929600162F76 /* PreviewSnapshotsTesting in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69652A2F929600162F76 /* PreviewSnapshotsTesting */; };
-		F31F69692A2F92F000162F76 /* SnapshotTestingHEIC in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69682A2F92F000162F76 /* SnapshotTestingHEIC */; };
 		F32ED5062A2F254400EABA81 /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; };
 		F32ED5062A2F254400EABA81 /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; };
 		F33AAF9A2A60394C006ECCBD /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F33AAF992A60394C006ECCBD /* NCMoreUserCell.xib */; };
 		F33AAF9A2A60394C006ECCBD /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F33AAF992A60394C006ECCBD /* NCMoreUserCell.xib */; };
 		F343A4B32A1E01FF00DDA874 /* PHAsset+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */; };
 		F343A4B32A1E01FF00DDA874 /* PHAsset+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */; };
@@ -126,6 +114,7 @@
 		F3BB464F2A39EBE500461F6E /* NCMoreUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB464E2A39EBE500461F6E /* NCMoreUserCell.swift */; };
 		F3BB464F2A39EBE500461F6E /* NCMoreUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB464E2A39EBE500461F6E /* NCMoreUserCell.swift */; };
 		F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */; };
 		F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */; };
 		F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */; };
 		F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */; };
+		F3C6D0972B0F9BA40078DD25 /* XLForm in Frameworks */ = {isa = PBXBuildFile; productRef = F3C6D0962B0F9BA40078DD25 /* XLForm */; };
 		F700222C1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700222C1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700222D1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700222D1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F700510022DF63AC003A3356 /* NCShare.storyboard */; };
 		F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F700510022DF63AC003A3356 /* NCShare.storyboard */; };
@@ -446,9 +435,6 @@
 		F760DE0B2AE66ED80027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE0A2AE66ED80027D78A /* KeychainAccess */; };
 		F760DE0B2AE66ED80027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE0A2AE66ED80027D78A /* KeychainAccess */; };
 		F760DE0D2AE66EDF0027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE0C2AE66EDF0027D78A /* KeychainAccess */; };
 		F760DE0D2AE66EDF0027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE0C2AE66EDF0027D78A /* KeychainAccess */; };
 		F760DE0F2AE66EE60027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE0E2AE66EE60027D78A /* KeychainAccess */; };
 		F760DE0F2AE66EE60027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE0E2AE66EE60027D78A /* KeychainAccess */; };
-		F760DE112AE66EF00027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE102AE66EF00027D78A /* KeychainAccess */; };
-		F760DE132AE66EF80027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE122AE66EF80027D78A /* KeychainAccess */; };
-		F760DE152AE66F020027D78A /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F760DE142AE66F020027D78A /* KeychainAccess */; };
 		F760DE172AE66F350027D78A /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F760DE162AE66F350027D78A /* NCKeychain.swift */; };
 		F760DE172AE66F350027D78A /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F760DE162AE66F350027D78A /* NCKeychain.swift */; };
 		F761856A29E98543006EB3B0 /* NCIntro.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F761856629E98543006EB3B0 /* NCIntro.storyboard */; };
 		F761856A29E98543006EB3B0 /* NCIntro.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F761856629E98543006EB3B0 /* NCIntro.storyboard */; };
 		F761856B29E98543006EB3B0 /* NCIntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F761856729E98543006EB3B0 /* NCIntroViewController.swift */; };
 		F761856B29E98543006EB3B0 /* NCIntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F761856729E98543006EB3B0 /* NCIntroViewController.swift */; };
@@ -927,6 +913,8 @@
 		F30A96042A27299D00D7BCFE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
 		F30A96042A27299D00D7BCFE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
 		F30A962E2A27ADF900D7BCFE /* EnvVars.stencil */ = {isa = PBXFileReference; lastKnownFileType = text; path = EnvVars.stencil; sourceTree = "<group>"; };
 		F30A962E2A27ADF900D7BCFE /* EnvVars.stencil */ = {isa = PBXFileReference; lastKnownFileType = text; path = EnvVars.stencil; sourceTree = "<group>"; };
 		F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EnvVars.generated.swift; path = Sourcery/EnvVars.generated.swift; sourceTree = "<group>"; };
 		F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EnvVars.generated.swift; path = Sourcery/EnvVars.generated.swift; sourceTree = "<group>"; };
+		F3131ED82B038DB20018DB28 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/System/iOSSupport/System/Library/Frameworks/SwiftUI.framework; sourceTree = DEVELOPER_DIR; };
+		F3131EDA2B038DB90018DB28 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/System/iOSSupport/System/Library/Frameworks/WidgetKit.framework; sourceTree = DEVELOPER_DIR; };
 		F31F69422A2F6D4500162F76 /* NextcloudSnapshotTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudSnapshotTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		F31F69422A2F6D4500162F76 /* NextcloudSnapshotTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudSnapshotTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		F31F69442A2F6D4600162F76 /* NextcloudSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudSnapshotTests.swift; sourceTree = "<group>"; };
 		F31F69442A2F6D4600162F76 /* NextcloudSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudSnapshotTests.swift; sourceTree = "<group>"; };
 		F31F694F2A2F707E00162F76 /* SwiftUIView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftUIView+Extensions.swift"; sourceTree = "<group>"; };
 		F31F694F2A2F707E00162F76 /* SwiftUIView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftUIView+Extensions.swift"; sourceTree = "<group>"; };
@@ -1481,6 +1469,7 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				F3C6D0972B0F9BA40078DD25 /* XLForm in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -1488,8 +1477,7 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				C04E2F192A17BA78001BAD85 /* XLForm in Frameworks */,
-				F760DE152AE66F020027D78A /* KeychainAccess in Frameworks */,
+				F3131EDD2B038E4A0018DB28 /* XLForm in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -1497,13 +1485,6 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				F30A96382A2DFD2900D7BCFE /* FirebaseDatabase in Frameworks */,
-				F30A963C2A2DFD3600D7BCFE /* SVGKit in Frameworks */,
-				F30A96362A2DFCD000D7BCFE /* RealmSwift in Frameworks */,
-				F30A96342A2DFCD000D7BCFE /* Realm in Frameworks */,
-				F760DE112AE66EF00027D78A /* KeychainAccess in Frameworks */,
-				F30A963A2A2DFD3100D7BCFE /* JGProgressHUD in Frameworks */,
-				C03BA14A2A17BC57002C8BA3 /* XLForm in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -1511,16 +1492,9 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				F31F695C2A2F89C400162F76 /* Realm in Frameworks */,
-				F31F69582A2F89C400162F76 /* XLForm in Frameworks */,
-				F31F69542A2F89C400162F76 /* SwiftRichString in Frameworks */,
-				F760DE132AE66EF80027D78A /* KeychainAccess in Frameworks */,
-				F31F69662A2F929600162F76 /* PreviewSnapshotsTesting in Frameworks */,
-				F31F695E2A2F89C400162F76 /* JGProgressHUD in Frameworks */,
-				F31F69522A2F89C400162F76 /* SVGKit in Frameworks */,
-				F31F69562A2F89C400162F76 /* FirebaseDatabase in Frameworks */,
-				F31F69692A2F92F000162F76 /* SnapshotTestingHEIC in Frameworks */,
-				F31F694D2A2F6EFB00162F76 /* SnapshotTesting in Frameworks */,
+				F3131EE12B038F560018DB28 /* SnapshotTestingHEIC in Frameworks */,
+				F3131EE32B038F9B0018DB28 /* PreviewSnapshotsTesting in Frameworks */,
+				F3131EDF2B038F2A0018DB28 /* SnapshotTesting in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -2628,6 +2602,8 @@
 		F7FC7D541DC1F93700BB2C6A /* Frameworks */ = {
 		F7FC7D541DC1F93700BB2C6A /* Frameworks */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				F3131EDA2B038DB90018DB28 /* WidgetKit.framework */,
+				F3131ED82B038DB20018DB28 /* SwiftUI.framework */,
 				F30A96042A27299D00D7BCFE /* XCTest.framework */,
 				F30A96042A27299D00D7BCFE /* XCTest.framework */,
 				F7792DE429EEE02D005930CE /* MobileVLCKit.xcframework */,
 				F7792DE429EEE02D005930CE /* MobileVLCKit.xcframework */,
 				F783031028B4C86200B84583 /* libc++.1.tbd */,
 				F783031028B4C86200B84583 /* libc++.1.tbd */,
@@ -2781,6 +2757,9 @@
 				AF8ED1FE2757821000B8DBC4 /* PBXTargetDependency */,
 				AF8ED1FE2757821000B8DBC4 /* PBXTargetDependency */,
 			);
 			);
 			name = NextcloudUnitTests;
 			name = NextcloudUnitTests;
+			packageProductDependencies = (
+				F3C6D0962B0F9BA40078DD25 /* XLForm */,
+			);
 			productName = NextcloudTests;
 			productName = NextcloudTests;
 			productReference = AF8ED1F92757821000B8DBC4 /* NextcloudUnitTests.xctest */;
 			productReference = AF8ED1F92757821000B8DBC4 /* NextcloudUnitTests.xctest */;
 			productType = "com.apple.product-type.bundle.unit-test";
 			productType = "com.apple.product-type.bundle.unit-test";
@@ -2800,8 +2779,7 @@
 			);
 			);
 			name = NextcloudUITests;
 			name = NextcloudUITests;
 			packageProductDependencies = (
 			packageProductDependencies = (
-				C04E2F182A17BA78001BAD85 /* XLForm */,
-				F760DE142AE66F020027D78A /* KeychainAccess */,
+				F3131EDC2B038E4A0018DB28 /* XLForm */,
 			);
 			);
 			productName = NextcloudUITests;
 			productName = NextcloudUITests;
 			productReference = C0046CDA2A17B98400D87C9D /* NextcloudUITests.xctest */;
 			productReference = C0046CDA2A17B98400D87C9D /* NextcloudUITests.xctest */;
@@ -2822,13 +2800,6 @@
 			);
 			);
 			name = NextcloudIntegrationTests;
 			name = NextcloudIntegrationTests;
 			packageProductDependencies = (
 			packageProductDependencies = (
-				C03BA1492A17BC57002C8BA3 /* XLForm */,
-				F30A96332A2DFCD000D7BCFE /* Realm */,
-				F30A96352A2DFCD000D7BCFE /* RealmSwift */,
-				F30A96372A2DFD2900D7BCFE /* FirebaseDatabase */,
-				F30A96392A2DFD3100D7BCFE /* JGProgressHUD */,
-				F30A963B2A2DFD3600D7BCFE /* SVGKit */,
-				F760DE102AE66EF00027D78A /* KeychainAccess */,
 			);
 			);
 			productName = NextcloudIntegrationTests;
 			productName = NextcloudIntegrationTests;
 			productReference = C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */;
 			productReference = C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */;
@@ -2849,16 +2820,9 @@
 			);
 			);
 			name = NextcloudSnapshotTests;
 			name = NextcloudSnapshotTests;
 			packageProductDependencies = (
 			packageProductDependencies = (
-				F31F694C2A2F6EFB00162F76 /* SnapshotTesting */,
-				F31F69512A2F89C400162F76 /* SVGKit */,
-				F31F69532A2F89C400162F76 /* SwiftRichString */,
-				F31F69552A2F89C400162F76 /* FirebaseDatabase */,
-				F31F69572A2F89C400162F76 /* XLForm */,
-				F31F695B2A2F89C400162F76 /* Realm */,
-				F31F695D2A2F89C400162F76 /* JGProgressHUD */,
-				F31F69652A2F929600162F76 /* PreviewSnapshotsTesting */,
-				F31F69682A2F92F000162F76 /* SnapshotTestingHEIC */,
-				F760DE122AE66EF80027D78A /* KeychainAccess */,
+				F3131EDE2B038F2A0018DB28 /* SnapshotTesting */,
+				F3131EE02B038F560018DB28 /* SnapshotTestingHEIC */,
+				F3131EE22B038F9B0018DB28 /* PreviewSnapshotsTesting */,
 			);
 			);
 			productName = NextcloudSnapshotTests;
 			productName = NextcloudSnapshotTests;
 			productReference = F31F69422A2F6D4500162F76 /* NextcloudSnapshotTests.xctest */;
 			productReference = F31F69422A2F6D4500162F76 /* NextcloudSnapshotTests.xctest */;
@@ -4310,6 +4274,7 @@
 					EXTENSION_NOTIFICATION_SERVICE,
 					EXTENSION_NOTIFICATION_SERVICE,
 				);
 				);
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/Notification_Service_Extension.plist";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/Notification_Service_Extension.plist";
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_NOTIFICATION_SERVICE";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_NOTIFICATION_SERVICE";
@@ -4327,6 +4292,7 @@
 					EXTENSION_NOTIFICATION_SERVICE,
 					EXTENSION_NOTIFICATION_SERVICE,
 				);
 				);
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/Notification_Service_Extension.plist";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/Notification_Service_Extension.plist";
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_NOTIFICATION_SERVICE";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_NOTIFICATION_SERVICE";
@@ -4337,37 +4303,41 @@
 		AF8ED1FF2757821000B8DBC4 /* Debug */ = {
 		AF8ED1FF2757821000B8DBC4 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
 				"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
 				ENABLE_HARDENED_RUNTIME = YES;
 				ENABLE_HARDENED_RUNTIME = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
 				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h";
 				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h";
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nextcloud.app/Nextcloud";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nextcloud.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Nextcloud";
 			};
 			};
 			name = Debug;
 			name = Debug;
 		};
 		};
 		AF8ED2002757821000B8DBC4 /* Release */ = {
 		AF8ED2002757821000B8DBC4 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
 				"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
 				ENABLE_HARDENED_RUNTIME = YES;
 				ENABLE_HARDENED_RUNTIME = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
 				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h";
 				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h";
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nextcloud.app/Nextcloud";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nextcloud.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Nextcloud";
 			};
 			};
 			name = Release;
 			name = Release;
 		};
 		};
 		C0046CE22A17B98400D87C9D /* Debug */ = {
 		C0046CE22A17B98400D87C9D /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = YES;
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
@@ -4394,6 +4364,7 @@
 				MARKETING_VERSION = 1.0;
 				MARKETING_VERSION = 1.0;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudUITests.NextcloudUITests;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudUITests.NextcloudUITests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
@@ -4408,7 +4379,7 @@
 		C0046CE32A17B98400D87C9D /* Release */ = {
 		C0046CE32A17B98400D87C9D /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = YES;
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
@@ -4431,6 +4402,7 @@
 				MARKETING_VERSION = 1.0;
 				MARKETING_VERSION = 1.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudUITests.NextcloudUITests;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudUITests.NextcloudUITests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = NO;
 				SWIFT_EMIT_LOC_STRINGS = NO;
@@ -4445,7 +4417,7 @@
 		C04E2F272A17BB4E001BAD85 /* Debug */ = {
 		C04E2F272A17BB4E001BAD85 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = YES;
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
@@ -4473,6 +4445,7 @@
 				MARKETING_VERSION = 1.0;
 				MARKETING_VERSION = 1.0;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudIntegrationTests.NextcloudIntegrationTests;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudIntegrationTests.NextcloudIntegrationTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
@@ -4487,7 +4460,7 @@
 		C04E2F282A17BB4E001BAD85 /* Release */ = {
 		C04E2F282A17BB4E001BAD85 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = YES;
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
 				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
@@ -4511,6 +4484,7 @@
 				MARKETING_VERSION = 1.0;
 				MARKETING_VERSION = 1.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudIntegrationTests.NextcloudIntegrationTests;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudIntegrationTests.NextcloudIntegrationTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = NO;
 				SWIFT_EMIT_LOC_STRINGS = NO;
@@ -4548,10 +4522,11 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GENERATE_INFOPLIST_FILE = YES;
 				GENERATE_INFOPLIST_FILE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 16.4;
+				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
 				MARKETING_VERSION = 1.0;
 				MARKETING_VERSION = 1.0;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudSnapshotTests;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudSnapshotTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
@@ -4586,10 +4561,11 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GENERATE_INFOPLIST_FILE = YES;
 				GENERATE_INFOPLIST_FILE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 16.4;
+				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
 				MARKETING_VERSION = 1.0;
 				MARKETING_VERSION = 1.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudSnapshotTests;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudSnapshotTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = NO;
 				SWIFT_EMIT_LOC_STRINGS = NO;
@@ -4614,6 +4590,7 @@
 				INFOPLIST_KEY_CFBundleDisplayName = "File Provider Extension UI";
 				INFOPLIST_KEY_CFBundleDisplayName = "File Provider Extension UI";
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension-UI";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension-UI";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION_UI";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION_UI";
@@ -4634,6 +4611,7 @@
 				INFOPLIST_KEY_CFBundleDisplayName = "File Provider Extension UI";
 				INFOPLIST_KEY_CFBundleDisplayName = "File Provider Extension UI";
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension-UI";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension-UI";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION_UI";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION_UI";
@@ -4651,6 +4629,7 @@
 					EXTENSION_SHARE,
 					EXTENSION_SHARE,
 				);
 				);
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/Share.plist";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/Share.plist";
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_SHARE";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_SHARE";
@@ -4668,6 +4647,7 @@
 					EXTENSION_SHARE,
 					EXTENSION_SHARE,
 				);
 				);
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/Share.plist";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/Share.plist";
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_SHARE";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_SHARE";
@@ -4694,6 +4674,7 @@
 				INFOPLIST_KEY_CFBundleDisplayName = Nextcloud;
 				INFOPLIST_KEY_CFBundleDisplayName = Nextcloud;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Widget;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Widget;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGET";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGET";
@@ -4721,6 +4702,7 @@
 				INFOPLIST_KEY_CFBundleDisplayName = Nextcloud;
 				INFOPLIST_KEY_CFBundleDisplayName = Nextcloud;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Widget;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Widget;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGET";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGET";
@@ -4740,6 +4722,7 @@
 					EXTENSION_FILE_PROVIDER_EXTENSION,
 					EXTENSION_FILE_PROVIDER_EXTENSION,
 				);
 				);
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/File_Provider_Extension.plist";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/File_Provider_Extension.plist";
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION";
@@ -4757,6 +4740,7 @@
 					EXTENSION_FILE_PROVIDER_EXTENSION,
 					EXTENSION_FILE_PROVIDER_EXTENSION,
 				);
 				);
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/File_Provider_Extension.plist";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/File_Provider_Extension.plist";
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION";
@@ -4771,6 +4755,7 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Brand/iOSClient.entitlements";
 				CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Brand/iOSClient.entitlements";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/iOSClient.plist";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/iOSClient.plist";
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h";
 				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h";
@@ -4784,6 +4769,7 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Brand/iOSClient.entitlements";
 				CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/Brand/iOSClient.entitlements";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/iOSClient.plist";
 				INFOPLIST_FILE = "$(SRCROOT)/Brand/iOSClient.plist";
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)";
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h";
 				SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Nextcloud-Bridging-Header.h";
@@ -4815,6 +4801,7 @@
 				INFOPLIST_KEY_CFBundleDisplayName = WidgetDashboardIntentHandler;
 				INFOPLIST_KEY_CFBundleDisplayName = WidgetDashboardIntentHandler;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.WidgetDashboardIntentHandler;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.WidgetDashboardIntentHandler;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGETDASHBOARDINTENTHANDLER";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGETDASHBOARDINTENTHANDLER";
@@ -4849,6 +4836,7 @@
 				INFOPLIST_KEY_CFBundleDisplayName = WidgetDashboardIntentHandler;
 				INFOPLIST_KEY_CFBundleDisplayName = WidgetDashboardIntentHandler;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "";
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.WidgetDashboardIntentHandler;
 				PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.WidgetDashboardIntentHandler;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGETDASHBOARDINTENTHANDLER";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_WIDGETDASHBOARDINTENTHANDLER";
@@ -4885,7 +4873,7 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 20;
+				CURRENT_PROJECT_VERSION = 2;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -4911,7 +4899,7 @@
 					"@executable_path/Frameworks",
 					"@executable_path/Frameworks",
 					"@executable_path/../../Frameworks",
 					"@executable_path/../../Frameworks",
 				);
 				);
-				MARKETING_VERSION = 4.9.2;
+				MARKETING_VERSION = 4.9.3;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_LDFLAGS = "";
 				OTHER_LDFLAGS = "";
 				SDKROOT = iphoneos;
 				SDKROOT = iphoneos;
@@ -4950,7 +4938,7 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 20;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				ENABLE_TESTABILITY = YES;
@@ -4973,7 +4961,7 @@
 					"@executable_path/Frameworks",
 					"@executable_path/Frameworks",
 					"@executable_path/../../Frameworks",
 					"@executable_path/../../Frameworks",
 				);
 				);
-				MARKETING_VERSION = 4.9.2;
+				MARKETING_VERSION = 4.9.3;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				OTHER_LDFLAGS = "";
 				OTHER_LDFLAGS = "";
 				SDKROOT = iphoneos;
 				SDKROOT = iphoneos;
@@ -5265,7 +5253,7 @@
 			repositoryURL = "https://github.com/nextcloud/NextcloudKit";
 			repositoryURL = "https://github.com/nextcloud/NextcloudKit";
 			requirement = {
 			requirement = {
 				kind = exactVersion;
 				kind = exactVersion;
-				version = 2.9.1;
+				version = 2.9.2;
 			};
 			};
 		};
 		};
 		F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {
 		F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {
@@ -5319,95 +5307,40 @@
 /* End XCRemoteSwiftPackageReference section */
 /* End XCRemoteSwiftPackageReference section */
 
 
 /* Begin XCSwiftPackageProductDependency section */
 /* Begin XCSwiftPackageProductDependency section */
-		C03BA1492A17BC57002C8BA3 /* XLForm */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F74E771E277A2EF40013B958 /* XCRemoteSwiftPackageReference "XLForm" */;
-			productName = XLForm;
-		};
-		C04E2F182A17BA78001BAD85 /* XLForm */ = {
+		F3131EDC2B038E4A0018DB28 /* XLForm */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
 			package = F74E771E277A2EF40013B958 /* XCRemoteSwiftPackageReference "XLForm" */;
 			package = F74E771E277A2EF40013B958 /* XCRemoteSwiftPackageReference "XLForm" */;
 			productName = XLForm;
 			productName = XLForm;
 		};
 		};
-		F30A96332A2DFCD000D7BCFE /* Realm */ = {
+		F3131EDE2B038F2A0018DB28 /* SnapshotTesting */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
-			package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */;
-			productName = Realm;
-		};
-		F30A96352A2DFCD000D7BCFE /* RealmSwift */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */;
-			productName = RealmSwift;
-		};
-		F30A96372A2DFD2900D7BCFE /* FirebaseDatabase */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F70B86732642CE3B00ED5349 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
-			productName = FirebaseDatabase;
+			package = F31F694B2A2F6EFA00162F76 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */;
+			productName = SnapshotTesting;
 		};
 		};
-		F30A96392A2DFD3100D7BCFE /* JGProgressHUD */ = {
+		F3131EE02B038F560018DB28 /* SnapshotTestingHEIC */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
-			package = F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */;
-			productName = JGProgressHUD;
+			package = F31F69672A2F92F000162F76 /* XCRemoteSwiftPackageReference "SnapshotTestingHEIC" */;
+			productName = SnapshotTestingHEIC;
 		};
 		};
-		F30A963B2A2DFD3600D7BCFE /* SVGKit */ = {
+		F3131EE22B038F9B0018DB28 /* PreviewSnapshotsTesting */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
-			package = F75E57A725BF0D61002B72C2 /* XCRemoteSwiftPackageReference "SVGKit" */;
-			productName = SVGKit;
+			package = F31F69622A2F929600162F76 /* XCRemoteSwiftPackageReference "swiftui-preview-snapshots" */;
+			productName = PreviewSnapshotsTesting;
 		};
 		};
 		F314F1102A30C11200BC7FAB /* PreviewSnapshots */ = {
 		F314F1102A30C11200BC7FAB /* PreviewSnapshots */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
 			package = F31F69622A2F929600162F76 /* XCRemoteSwiftPackageReference "swiftui-preview-snapshots" */;
 			package = F31F69622A2F929600162F76 /* XCRemoteSwiftPackageReference "swiftui-preview-snapshots" */;
 			productName = PreviewSnapshots;
 			productName = PreviewSnapshots;
 		};
 		};
-		F31F694C2A2F6EFB00162F76 /* SnapshotTesting */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F31F694B2A2F6EFA00162F76 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */;
-			productName = SnapshotTesting;
-		};
-		F31F69512A2F89C400162F76 /* SVGKit */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F75E57A725BF0D61002B72C2 /* XCRemoteSwiftPackageReference "SVGKit" */;
-			productName = SVGKit;
-		};
-		F31F69532A2F89C400162F76 /* SwiftRichString */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F72DA9B225F53E4E00B87DB1 /* XCRemoteSwiftPackageReference "SwiftRichString" */;
-			productName = SwiftRichString;
-		};
-		F31F69552A2F89C400162F76 /* FirebaseDatabase */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F70B86732642CE3B00ED5349 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
-			productName = FirebaseDatabase;
-		};
-		F31F69572A2F89C400162F76 /* XLForm */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F74E771E277A2EF40013B958 /* XCRemoteSwiftPackageReference "XLForm" */;
-			productName = XLForm;
-		};
-		F31F695B2A2F89C400162F76 /* Realm */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */;
-			productName = Realm;
-		};
-		F31F695D2A2F89C400162F76 /* JGProgressHUD */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */;
-			productName = JGProgressHUD;
-		};
 		F31F69632A2F929600162F76 /* PreviewSnapshots */ = {
 		F31F69632A2F929600162F76 /* PreviewSnapshots */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
 			package = F31F69622A2F929600162F76 /* XCRemoteSwiftPackageReference "swiftui-preview-snapshots" */;
 			package = F31F69622A2F929600162F76 /* XCRemoteSwiftPackageReference "swiftui-preview-snapshots" */;
 			productName = PreviewSnapshots;
 			productName = PreviewSnapshots;
 		};
 		};
-		F31F69652A2F929600162F76 /* PreviewSnapshotsTesting */ = {
+		F3C6D0962B0F9BA40078DD25 /* XLForm */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
-			package = F31F69622A2F929600162F76 /* XCRemoteSwiftPackageReference "swiftui-preview-snapshots" */;
-			productName = PreviewSnapshotsTesting;
-		};
-		F31F69682A2F92F000162F76 /* SnapshotTestingHEIC */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F31F69672A2F92F000162F76 /* XCRemoteSwiftPackageReference "SnapshotTestingHEIC" */;
-			productName = SnapshotTestingHEIC;
+			package = F74E771E277A2EF40013B958 /* XCRemoteSwiftPackageReference "XLForm" */;
+			productName = XLForm;
 		};
 		};
 		F70821D729E59E6D001CA2D7 /* TagListView */ = {
 		F70821D729E59E6D001CA2D7 /* TagListView */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
@@ -5594,21 +5527,6 @@
 			package = F760DE012AE66E860027D78A /* XCRemoteSwiftPackageReference "KeychainAccess" */;
 			package = F760DE012AE66E860027D78A /* XCRemoteSwiftPackageReference "KeychainAccess" */;
 			productName = KeychainAccess;
 			productName = KeychainAccess;
 		};
 		};
-		F760DE102AE66EF00027D78A /* KeychainAccess */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F760DE012AE66E860027D78A /* XCRemoteSwiftPackageReference "KeychainAccess" */;
-			productName = KeychainAccess;
-		};
-		F760DE122AE66EF80027D78A /* KeychainAccess */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F760DE012AE66E860027D78A /* XCRemoteSwiftPackageReference "KeychainAccess" */;
-			productName = KeychainAccess;
-		};
-		F760DE142AE66F020027D78A /* KeychainAccess */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F760DE012AE66E860027D78A /* XCRemoteSwiftPackageReference "KeychainAccess" */;
-			productName = KeychainAccess;
-		};
 		F76B649D2ADFFDEC00014640 /* LRUCache */ = {
 		F76B649D2ADFFDEC00014640 /* LRUCache */ = {
 			isa = XCSwiftPackageProductDependency;
 			isa = XCSwiftPackageProductDependency;
 			package = F76B649A2ADFFAD200014640 /* XCRemoteSwiftPackageReference "LRUCache" */;
 			package = F76B649A2ADFFAD200014640 /* XCRemoteSwiftPackageReference "LRUCache" */;

+ 44 - 42
Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme

@@ -20,6 +20,48 @@
                ReferencedContainer = "container:Nextcloud.xcodeproj">
                ReferencedContainer = "container:Nextcloud.xcodeproj">
             </BuildableReference>
             </BuildableReference>
          </BuildActionEntry>
          </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "NO"
+            buildForRunning = "NO"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "C0046CD92A17B98400D87C9D"
+               BuildableName = "NextcloudUITests.xctest"
+               BlueprintName = "NextcloudUITests"
+               ReferencedContainer = "container:Nextcloud.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "NO"
+            buildForRunning = "NO"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "C04E2F1F2A17BB4D001BAD85"
+               BuildableName = "NextcloudIntegrationTests.xctest"
+               BlueprintName = "NextcloudIntegrationTests"
+               ReferencedContainer = "container:Nextcloud.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "NO"
+            buildForRunning = "NO"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "F31F69412A2F6D4500162F76"
+               BuildableName = "NextcloudSnapshotTests.xctest"
+               BlueprintName = "NextcloudSnapshotTests"
+               ReferencedContainer = "container:Nextcloud.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
       </BuildActionEntries>
       </BuildActionEntries>
    </BuildAction>
    </BuildAction>
    <TestAction
    <TestAction
@@ -40,7 +82,8 @@
       </MacroExpansion>
       </MacroExpansion>
       <Testables>
       <Testables>
          <TestableReference
          <TestableReference
-            skipped = "NO">
+            skipped = "NO"
+            parallelizable = "YES">
             <BuildableReference
             <BuildableReference
                BuildableIdentifier = "primary"
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "AF8ED1F82757821000B8DBC4"
                BlueprintIdentifier = "AF8ED1F82757821000B8DBC4"
@@ -49,47 +92,6 @@
                ReferencedContainer = "container:Nextcloud.xcodeproj">
                ReferencedContainer = "container:Nextcloud.xcodeproj">
             </BuildableReference>
             </BuildableReference>
          </TestableReference>
          </TestableReference>
-         <TestableReference
-            skipped = "NO">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "C0046CD92A17B98400D87C9D"
-               BuildableName = "NextcloudUITests.xctest"
-               BlueprintName = "NextcloudUITests"
-               ReferencedContainer = "container:Nextcloud.xcodeproj">
-            </BuildableReference>
-         </TestableReference>
-         <TestableReference
-            skipped = "NO">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "C04E2F1F2A17BB4D001BAD85"
-               BuildableName = "NextcloudIntegrationTests.xctest"
-               BlueprintName = "NextcloudIntegrationTests"
-               ReferencedContainer = "container:Nextcloud.xcodeproj">
-            </BuildableReference>
-         </TestableReference>
-         <TestableReference
-            skipped = "NO">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "C04E2F2C2A17BB77001BAD85"
-               BuildableName = "NextcloudEndToEndTests.xctest"
-               BlueprintName = "NextcloudEndToEndTests"
-               ReferencedContainer = "container:Nextcloud.xcodeproj">
-            </BuildableReference>
-         </TestableReference>
-         <TestableReference
-            skipped = "NO"
-            parallelizable = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "F31F69412A2F6D4500162F76"
-               BuildableName = "NextcloudSnapshotTests.xctest"
-               BlueprintName = "NextcloudSnapshotTests"
-               ReferencedContainer = "container:Nextcloud.xcodeproj">
-            </BuildableReference>
-         </TestableReference>
       </Testables>
       </Testables>
    </TestAction>
    </TestAction>
    <LaunchAction
    <LaunchAction

+ 1 - 1
Share/NCShareExtension+DataSource.swift

@@ -94,7 +94,7 @@ extension NCShareExtension: UICollectionViewDataSource {
         cell.selectMode(false)
         cell.selectMode(false)
 
 
         // Live Photo
         // Live Photo
-        if metadata.livePhoto {
+        if metadata.isLivePhoto {
             cell.imageStatus.image = NCImageCache.images.livePhoto
             cell.imageStatus.image = NCImageCache.images.livePhoto
         }
         }
 
 

+ 0 - 1
Share/NCShareExtension+Files.swift

@@ -45,7 +45,6 @@ extension NCShareExtension {
             ascending: layoutForView?.ascending,
             ascending: layoutForView?.ascending,
             directoryOnTop: layoutForView?.directoryOnTop,
             directoryOnTop: layoutForView?.directoryOnTop,
             favoriteOnTop: true,
             favoriteOnTop: true,
-            filterLivePhoto: true,
             groupByField: groupByField)
             groupByField: groupByField)
 
 
         if withLoadFolder {
         if withLoadFolder {

+ 17 - 10
iOSClient/AppDelegate.swift

@@ -251,6 +251,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
 
 
         enableTouchFaceID()
         enableTouchFaceID()
 
 
+        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterApplicationWillEnterForeground)
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterRichdocumentGrabFocus)
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterRichdocumentGrabFocus)
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetwork, second: 2)
         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetwork, second: 2)
     }
     }
@@ -614,9 +615,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Initialize Auto upload with \(items) uploads")
             NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Initialize Auto upload with \(items) uploads")
         }
         }
 
 
-        DispatchQueue.global().async { NCImageCache.shared.createMediaCache(account: self.account) }
-
-        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeUser)
+        DispatchQueue.global().async {
+            NCImageCache.shared.createMediaCache(account: self.account)
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeUser)
+        }
     }
     }
 
 
     @objc func deleteAccount(_ account: String, wipe: Bool) {
     @objc func deleteAccount(_ account: String, wipe: Bool) {
@@ -685,7 +687,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
 
 
     func requestAccount() {
     func requestAccount() {
 
 
-        if isPasscodePresented() { return }
+        if isPasscodePresented { return }
         if !NCKeychain().accountRequest { return }
         if !NCKeychain().accountRequest { return }
 
 
         let accounts = NCManageDatabase.shared.getAllAccount()
         let accounts = NCManageDatabase.shared.getAllAccount()
@@ -727,6 +729,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         return passcodeCounterFail > 0 && passcodeCounterFail.isMultiple(of: 3)
         return passcodeCounterFail > 0 && passcodeCounterFail.isMultiple(of: 3)
     }
     }
 
 
+    var isPasscodePresented: Bool {
+        return privacyProtectionWindow?.rootViewController?.presentedViewController is TOPasscodeViewController
+    }
+
     func presentPasscode(completion: @escaping () -> Void) {
     func presentPasscode(completion: @escaping () -> Void) {
 
 
         var error: NSError?
         var error: NSError?
@@ -760,10 +766,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         })
         })
     }
     }
 
 
-    func isPasscodePresented() -> Bool {
-        return privacyProtectionWindow?.rootViewController?.presentedViewController is TOPasscodeViewController
-    }
-
     func enableTouchFaceID() {
     func enableTouchFaceID() {
         guard !account.isEmpty,
         guard !account.isEmpty,
               NCKeychain().touchFaceID,
               NCKeychain().touchFaceID,
@@ -790,8 +792,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
                     if let error = evaluateError {
                     if let error = evaluateError {
                         switch error._code {
                         switch error._code {
                         case LAError.userFallback.rawValue, LAError.authenticationFailed.rawValue:
                         case LAError.userFallback.rawValue, LAError.authenticationFailed.rawValue:
-                            NCKeychain().passcodeCounterFail = 3
-                            NCKeychain().passcodeCounterFailReset += 1
+                            if LAContext().biometryType == .faceID {
+                                NCKeychain().passcodeCounterFail = 2
+                                NCKeychain().passcodeCounterFailReset += 2
+                            } else {
+                                NCKeychain().passcodeCounterFail = 3
+                                NCKeychain().passcodeCounterFailReset += 3
+                            }
                             self.openAlert(passcodeViewController: passcodeViewController)
                             self.openAlert(passcodeViewController: passcodeViewController)
                         case LAError.biometryLockout.rawValue:
                         case LAError.biometryLockout.rawValue:
                             LAContext().evaluatePolicy(LAPolicy.deviceOwnerAuthentication, localizedReason: NSLocalizedString("_deviceOwnerAuthentication_", comment: ""), reply: { success, _ in
                             LAContext().evaluatePolicy(LAPolicy.deviceOwnerAuthentication, localizedReason: NSLocalizedString("_deviceOwnerAuthentication_", comment: ""), reply: { success, _ in

+ 5 - 16
iOSClient/Data/NCDataSource.swift

@@ -40,13 +40,12 @@ class NCDataSource: NSObject {
     private var sort: String = ""
     private var sort: String = ""
     private var directoryOnTop: Bool = true
     private var directoryOnTop: Bool = true
     private var favoriteOnTop: Bool = true
     private var favoriteOnTop: Bool = true
-    private var filterLivePhoto: Bool = true
 
 
     override init() {
     override init() {
         super.init()
         super.init()
     }
     }
 
 
-    init(metadatas: [tableMetadata], account: String, directory: tableDirectory? = nil, sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, filterLivePhoto: Bool? = true, groupByField: String = "name", providers: [NKSearchProvider]? = nil, searchResults: [NKSearchResult]? = nil) {
+    init(metadatas: [tableMetadata], account: String, directory: tableDirectory? = nil, sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, groupByField: String = "name", providers: [NKSearchProvider]? = nil, searchResults: [NKSearchResult]? = nil) {
         super.init()
         super.init()
 
 
         self.metadatas = metadatas.filter({
         self.metadatas = metadatas.filter({
@@ -57,7 +56,6 @@ class NCDataSource: NSObject {
         self.ascending = ascending ?? false
         self.ascending = ascending ?? false
         self.directoryOnTop = directoryOnTop ?? true
         self.directoryOnTop = directoryOnTop ?? true
         self.favoriteOnTop = favoriteOnTop ?? true
         self.favoriteOnTop = favoriteOnTop ?? true
-        self.filterLivePhoto = filterLivePhoto ?? true
         self.groupByField = groupByField
         self.groupByField = groupByField
         // unified search
         // unified search
         self.providers = providers
         self.providers = providers
@@ -110,10 +108,7 @@ class NCDataSource: NSObject {
         // get all Section
         // get all Section
         for metadata in self.metadatas {
         for metadata in self.metadatas {
             // skipped livePhoto VIDEO part
             // skipped livePhoto VIDEO part
-            if filterLivePhoto && metadata.livePhoto && metadata.classFile == NKCommon.TypeClassFile.video.rawValue {
-                if let metadataImage = self.metadatas.filter({ $0.fileNoExtension == metadata.fileNoExtension && $0.classFile == NKCommon.TypeClassFile.image.rawValue }).first {
-                    NCLivePhoto().setLivePhoto(metadata1: metadataImage, metadata2: metadata)
-                }
+            if metadata.isLivePhoto && metadata.classFile == NKCommon.TypeClassFile.video.rawValue {
                 continue
                 continue
             }
             }
             let section = NSLocalizedString(self.getSectionValue(metadata: metadata), comment: "")
             let section = NSLocalizedString(self.getSectionValue(metadata: metadata), comment: "")
@@ -179,8 +174,7 @@ class NCDataSource: NSObject {
                                                       sort: self.sort,
                                                       sort: self.sort,
                                                       ascending: self.ascending,
                                                       ascending: self.ascending,
                                                       directoryOnTop: self.directoryOnTop,
                                                       directoryOnTop: self.directoryOnTop,
-                                                      favoriteOnTop: self.favoriteOnTop,
-                                                      filterLivePhoto: self.filterLivePhoto)
+                                                      favoriteOnTop: self.favoriteOnTop)
         metadatasForSection.append(metadataForSection)
         metadatasForSection.append(metadataForSection)
     }
     }
 
 
@@ -347,7 +341,6 @@ class NCMetadataForSection: NSObject {
     private var ascending: Bool
     private var ascending: Bool
     private var directoryOnTop: Bool
     private var directoryOnTop: Bool
     private var favoriteOnTop: Bool
     private var favoriteOnTop: Bool
-    private var filterLivePhoto: Bool
 
 
     private var metadatasSorted: [tableMetadata] = []
     private var metadatasSorted: [tableMetadata] = []
     private var metadatasFavoriteDirectory: [tableMetadata] = []
     private var metadatasFavoriteDirectory: [tableMetadata] = []
@@ -359,7 +352,7 @@ class NCMetadataForSection: NSObject {
     public var numFile: Int = 0
     public var numFile: Int = 0
     public var totalSize: Int64 = 0
     public var totalSize: Int64 = 0
 
 
-    init(sectionValue: String, metadatas: [tableMetadata], lastSearchResult: NKSearchResult?, sort: String, ascending: Bool, directoryOnTop: Bool, favoriteOnTop: Bool, filterLivePhoto: Bool) {
+    init(sectionValue: String, metadatas: [tableMetadata], lastSearchResult: NKSearchResult?, sort: String, ascending: Bool, directoryOnTop: Bool, favoriteOnTop: Bool) {
 
 
         self.sectionValue = sectionValue
         self.sectionValue = sectionValue
         self.metadatas = metadatas
         self.metadatas = metadatas
@@ -368,7 +361,6 @@ class NCMetadataForSection: NSObject {
         self.ascending = ascending
         self.ascending = ascending
         self.directoryOnTop = directoryOnTop
         self.directoryOnTop = directoryOnTop
         self.favoriteOnTop = favoriteOnTop
         self.favoriteOnTop = favoriteOnTop
-        self.filterLivePhoto = filterLivePhoto
 
 
         super.init()
         super.init()
 
 
@@ -432,10 +424,7 @@ class NCMetadataForSection: NSObject {
             }
             }
 
 
             // skipped livePhoto
             // skipped livePhoto
-            if filterLivePhoto && metadata.livePhoto && metadata.classFile == NKCommon.TypeClassFile.video.rawValue {
-                if let metadataImage = self.metadatas.filter({ $0.fileNoExtension == metadata.fileNoExtension && $0.classFile == NKCommon.TypeClassFile.image.rawValue }).first {
-                    NCLivePhoto().setLivePhoto(metadata1: metadataImage, metadata2: metadata)
-                }
+            if metadata.isLivePhoto && metadata.classFile == NKCommon.TypeClassFile.video.rawValue {
                 continue
                 continue
             }
             }
 
 

+ 6 - 6
iOSClient/Data/NCManageDatabase+Capabilities.swift

@@ -128,12 +128,12 @@ extension NCManageDatabase {
                             }
                             }
 
 
                             struct Public: Codable {
                             struct Public: Codable {
-                                let upload: Bool
                                 let enabled: Bool
                                 let enabled: Bool
+                                let upload: Bool?
                                 let password: Password?
                                 let password: Password?
-                                let sendmail: Bool
-                                let uploadfilesdrop: Bool
-                                let multiplelinks: Bool
+                                let sendmail: Bool?
+                                let uploadfilesdrop: Bool?
+                                let multiplelinks: Bool?
                                 let expiredate: ExpireDate?
                                 let expiredate: ExpireDate?
                                 let expiredateinternal: ExpireDate?
                                 let expiredateinternal: ExpireDate?
                                 let expiredateremote: ExpireDate?
                                 let expiredateremote: ExpireDate?
@@ -281,7 +281,7 @@ extension NCManageDatabase {
                 }
                 }
                 jsonData = data
                 jsonData = data
             } catch let error as NSError {
             } catch let error as NSError {
-                NextcloudKit.shared.nkCommonInstance.writeLog("I cannot access to database: \(error)")
+                NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)")
                 return
                 return
             }
             }
         }
         }
@@ -348,7 +348,7 @@ extension NCManageDatabase {
             }
             }
             NCGlobal.shared.capabilityGroupfoldersEnabled = json.ocs.data.capabilities.groupfolders?.hasGroupFolders ?? false
             NCGlobal.shared.capabilityGroupfoldersEnabled = json.ocs.data.capabilities.groupfolders?.hasGroupFolders ?? false
         } catch let error as NSError {
         } catch let error as NSError {
-            NextcloudKit.shared.nkCommonInstance.writeLog("I cannot access to database: \(error)")
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)")
             return
             return
         }
         }
     }
     }

+ 13 - 0
iOSClient/Data/NCManageDatabase+LocalFile.swift

@@ -194,6 +194,19 @@ extension NCManageDatabase {
         return nil
         return nil
     }
     }
 
 
+    func getResultsTableLocalFile(predicate: NSPredicate) -> Results<tableLocalFile>? {
+
+        do {
+            let realm = try Realm()
+            realm.refresh()
+            return realm.objects(tableLocalFile.self).filter(predicate)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)")
+        }
+
+        return nil
+    }
+
     func getTableLocalFiles(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableLocalFile] {
     func getTableLocalFiles(predicate: NSPredicate, sorted: String, ascending: Bool) -> [tableLocalFile] {
 
 
         do {
         do {

+ 41 - 92
iOSClient/Data/NCManageDatabase+Metadata.swift

@@ -60,8 +60,8 @@ class tableMetadata: Object, NCUserBaseUrl {
     @objc dynamic var hidden: Bool = false
     @objc dynamic var hidden: Bool = false
     @objc dynamic var iconName = ""
     @objc dynamic var iconName = ""
     @objc dynamic var iconUrl = ""
     @objc dynamic var iconUrl = ""
+    @objc dynamic var isFlaggedAsLivePhotoByServer: Bool = false
     @objc dynamic var isExtractFile: Bool = false
     @objc dynamic var isExtractFile: Bool = false
-    @objc dynamic var livePhoto: Bool = false
     @objc dynamic var livePhotoFile = ""
     @objc dynamic var livePhotoFile = ""
     @objc dynamic var mountType = ""
     @objc dynamic var mountType = ""
     @objc dynamic var name = ""                                             // for unifiedSearch is the provider.id
     @objc dynamic var name = ""                                             // for unifiedSearch is the provider.id
@@ -249,6 +249,10 @@ extension tableMetadata {
         NCUtilityFileSystem().isDirectoryE2EETop(account: account, serverUrl: serverUrl)
         NCUtilityFileSystem().isDirectoryE2EETop(account: account, serverUrl: serverUrl)
     }
     }
 
 
+    var isLivePhoto: Bool {
+        !livePhotoFile.isEmpty
+    }
+
     /// Returns false if the user is lokced out of the file. I.e. The file is locked but by somone else
     /// Returns false if the user is lokced out of the file. I.e. The file is locked but by somone else
     func canUnlock(as user: String) -> Bool {
     func canUnlock(as user: String) -> Bool {
         return !lock || (lockOwner == user && lockOwnerType == 0)
         return !lock || (lockOwner == user && lockOwnerType == 0)
@@ -342,9 +346,7 @@ extension NCManageDatabase {
         metadata.height = file.height
         metadata.height = file.height
         metadata.width = file.width
         metadata.width = file.width
         metadata.livePhotoFile = file.livePhotoFile
         metadata.livePhotoFile = file.livePhotoFile
-        if !metadata.livePhotoFile.isEmpty {
-            metadata.livePhoto = true
-        }
+        metadata.isFlaggedAsLivePhotoByServer = file.isFlaggedAsLivePhotoByServer
 
 
         // E2EE find the fileName for fileNameView
         // E2EE find the fileName for fileNameView
         if isDirectoryE2EE || file.e2eEncrypted {
         if isDirectoryE2EE || file.e2eEncrypted {
@@ -393,30 +395,10 @@ extension NCManageDatabase {
             counter += 1
             counter += 1
         }
         }
 
 
-        //
-        // Detect Live photo
-        //
-        var metadataOutput: [tableMetadata] = []
-        metadatas = metadatas.sorted(by: {$0.fileNameView < $1.fileNameView})
-
-        for index in metadatas.indices {
-            let metadata = metadatas[index]
-            if index < metadatas.count - 1,
-                metadata.fileNoExtension == metadatas[index + 1].fileNoExtension,
-                ((metadata.classFile == NKCommon.TypeClassFile.image.rawValue && metadatas[index + 1].classFile == NKCommon.TypeClassFile.video.rawValue) || (metadata.classFile == NKCommon.TypeClassFile.video.rawValue && metadatas[index + 1].classFile == NKCommon.TypeClassFile.image.rawValue)) {
-                metadata.livePhoto = true
-                metadatas[index + 1].livePhoto = true
-                let metadata1 = metadata
-                let metadata2 = metadatas[index + 1]
-                NCLivePhoto().setLivePhoto(metadata1: metadata1, metadata2: metadata2)
-            }
-            metadataOutput.append(metadata)
-        }
-
-        completion(metadataFolder, metadataFolders, metadataOutput)
+        completion(metadataFolder, metadataFolders, metadatas)
     }
     }
 
 
-    func createMetadata(account: String, user: String, userId: String, fileName: String, fileNameView: String, ocId: String, serverUrl: String, urlBase: String, url: String, contentType: String, isLivePhoto: Bool = false, isUrl: Bool = false, name: String = NCGlobal.shared.appName, subline: String? = nil, iconName: String? = nil, iconUrl: String? = nil) -> tableMetadata {
+    func createMetadata(account: String, user: String, userId: String, fileName: String, fileNameView: String, ocId: String, serverUrl: String, urlBase: String, url: String, contentType: String, isUrl: Bool = false, name: String = NCGlobal.shared.appName, subline: String? = nil, iconName: String? = nil, iconUrl: String? = nil) -> tableMetadata {
 
 
         let metadata = tableMetadata()
         let metadata = tableMetadata()
         if isUrl {
         if isUrl {
@@ -451,7 +433,6 @@ extension NCManageDatabase {
         metadata.etag = ocId
         metadata.etag = ocId
         metadata.fileName = fileName
         metadata.fileName = fileName
         metadata.fileNameView = fileName
         metadata.fileNameView = fileName
-        metadata.livePhoto = isLivePhoto
         metadata.name = name
         metadata.name = name
         metadata.ocId = ocId
         metadata.ocId = ocId
         metadata.permissions = "RGDNVW"
         metadata.permissions = "RGDNVW"
@@ -546,7 +527,7 @@ extension NCManageDatabase {
     }
     }
 
 
     @discardableResult
     @discardableResult
-    func updateMetadatas(_ metadatas: [tableMetadata], metadatasResult: [tableMetadata], addCompareLivePhoto: Bool = true, addExistsInLocal: Bool = false, addCompareEtagLocal: Bool = false) -> (metadatasUpdate: [tableMetadata], metadatasLocalUpdate: [tableMetadata], metadatasDelete: [tableMetadata]) {
+    func updateMetadatas(_ metadatas: [tableMetadata], metadatasResult: [tableMetadata], addExistsInLocal: Bool = false, addCompareEtagLocal: Bool = false) -> (metadatasUpdate: [tableMetadata], metadatasLocalUpdate: [tableMetadata], metadatasDelete: [tableMetadata]) {
 
 
         var ocIdsUdate: [String] = []
         var ocIdsUdate: [String] = []
         var ocIdsLocalUdate: [String] = []
         var ocIdsLocalUdate: [String] = []
@@ -590,7 +571,7 @@ extension NCManageDatabase {
                              result.tags != metadata.tags) {
                              result.tags != metadata.tags) {
                             ocIdsUdate.append(metadata.ocId)
                             ocIdsUdate.append(metadata.ocId)
                             realm.add(tableMetadata.init(value: metadata), update: .all)
                             realm.add(tableMetadata.init(value: metadata), update: .all)
-                        } else if result.status == NCGlobal.shared.metadataStatusNormal && addCompareLivePhoto && result.livePhoto != metadata.livePhoto {
+                        } else if result.status == NCGlobal.shared.metadataStatusNormal {
                             ocIdsUdate.append(metadata.ocId)
                             ocIdsUdate.append(metadata.ocId)
                             realm.add(tableMetadata.init(value: metadata), update: .all)
                             realm.add(tableMetadata.init(value: metadata), update: .all)
                         }
                         }
@@ -734,6 +715,19 @@ extension NCManageDatabase {
         }
         }
     }
     }
 
 
+    func setMetadataLivePhotoByServer(account: String, ocId: String) {
+
+        do {
+            let realm = try Realm()
+            try realm.write {
+                let result = realm.objects(tableMetadata.self).filter("account == %@ AND ocId == %@", account, ocId).first
+                result?.isFlaggedAsLivePhotoByServer = true
+            }
+        } catch let error {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
+        }
+    }
+
     func updateMetadatasFavorite(account: String, metadatas: [tableMetadata]) {
     func updateMetadatasFavorite(account: String, metadatas: [tableMetadata]) {
 
 
         do {
         do {
@@ -820,6 +814,18 @@ extension NCManageDatabase {
         return []
         return []
     }
     }
 
 
+    func getResultsMetadatas(predicate: NSPredicate) -> Results<tableMetadata>? {
+
+        do {
+            let realm = try Realm()
+            return realm.objects(tableMetadata.self).filter(predicate)
+        } catch let error as NSError {
+            NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)")
+        }
+
+        return nil
+    }
+
     func getAdvancedMetadatas(predicate: NSPredicate, page: Int = 0, limit: Int = 0, sorted: String, ascending: Bool) -> [tableMetadata] {
     func getAdvancedMetadatas(predicate: NSPredicate, page: Int = 0, limit: Int = 0, sorted: String, ascending: Bool) -> [tableMetadata] {
 
 
         var metadatas: [tableMetadata] = []
         var metadatas: [tableMetadata] = []
@@ -992,7 +998,6 @@ extension NCManageDatabase {
 
 
         do {
         do {
             let realm = try Realm()
             let realm = try Realm()
-            realm.refresh()
             let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier != '' AND deleteAssetLocalIdentifier == true", account)
             let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier != '' AND deleteAssetLocalIdentifier == true", account)
             for result in results {
             for result in results {
                 assetLocalIdentifiers.append(result.assetLocalIdentifier)
                 assetLocalIdentifiers.append(result.assetLocalIdentifier)
@@ -1008,7 +1013,6 @@ extension NCManageDatabase {
 
 
         do {
         do {
             let realm = try Realm()
             let realm = try Realm()
-            realm.refresh()
             try realm.write {
             try realm.write {
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier IN %@", account, assetLocalIdentifiers)
                 let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier IN %@", account, assetLocalIdentifiers)
                 for result in results {
                 for result in results {
@@ -1023,25 +1027,11 @@ extension NCManageDatabase {
 
 
     func getMetadataLivePhoto(metadata: tableMetadata) -> tableMetadata? {
     func getMetadataLivePhoto(metadata: tableMetadata) -> tableMetadata? {
 
 
-        var classFile = metadata.classFile
-        var fileName = (metadata.fileNameView as NSString).deletingPathExtension
-
-        if !metadata.livePhoto || !NCKeychain().livePhoto {
-            return nil
-        }
-
-        if classFile == NKCommon.TypeClassFile.image.rawValue {
-            classFile = NKCommon.TypeClassFile.video.rawValue
-            fileName = fileName + ".mov"
-        } else {
-            classFile = NKCommon.TypeClassFile.image.rawValue
-            fileName = fileName + ".jpg"
-        }
+        guard metadata.isLivePhoto else { return nil }
 
 
         do {
         do {
             let realm = try Realm()
             let realm = try Realm()
-            realm.refresh()
-            guard let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView CONTAINS[cd] %@ AND ocId != %@ AND classFile == %@", metadata.account, metadata.serverUrl, fileName, metadata.ocId, classFile)).first else { return nil }
+            guard let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, metadata.livePhotoFile)).first else { return nil }
             return tableMetadata.init(value: result)
             return tableMetadata.init(value: result)
         } catch let error as NSError {
         } catch let error as NSError {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)")
@@ -1050,48 +1040,17 @@ extension NCManageDatabase {
         return nil
         return nil
     }
     }
 
 
-    func getMetadatasMedia(predicate: NSPredicate, livePhoto: Bool) -> [tableMetadata] {
-
-        var metadatas: [tableMetadata] = []
+    func getMetadatasMedia(predicate: NSPredicate) -> [tableMetadata] {
 
 
         do {
         do {
             let realm = try Realm()
             let realm = try Realm()
-            realm.refresh()
-            try realm.write {
-                let sortProperties = [SortDescriptor(keyPath: "serverUrl", ascending: false), SortDescriptor(keyPath: "fileNameView", ascending: false)]
-                let results = realm.objects(tableMetadata.self).filter(predicate).sorted(by: sortProperties)
-                if livePhoto {
-                    for index in results.indices {
-                        let metadata = results[index]
-                        if index < results.count - 1, metadata.fileNoExtension == results[index + 1].fileNoExtension {
-                            if !metadata.livePhoto {
-                                metadata.livePhoto = true
-                            }
-                            if !results[index + 1].livePhoto {
-                                results[index + 1].livePhoto = true
-                            }
-                            let metadata1 = tableMetadata(value: results[index + 1])
-                            let metadata2 = tableMetadata(value: results[index])
-                            NCLivePhoto().setLivePhoto(metadata1: metadata1, metadata2: metadata2)
-                        }
-                        if metadata.livePhoto {
-                            if metadata.classFile == NKCommon.TypeClassFile.image.rawValue {
-                                metadatas.append(tableMetadata.init(value: metadata))
-                            }
-                            continue
-                        } else {
-                            metadatas.append(tableMetadata.init(value: metadata))
-                        }
-                    }
-                } else {
-                    metadatas = Array(results.map { tableMetadata.init(value: $0) })
-                }
-            }
+            let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: "date", ascending: false)
+            return Array(results.map { tableMetadata.init(value: $0) })
         } catch let error {
         } catch let error {
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
             NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)")
         }
         }
 
 
-        return metadatas
+        return []
     }
     }
 
 
     func isMetadataShareOrMounted(metadata: tableMetadata, metadataFolder: tableMetadata?) -> Bool {
     func isMetadataShareOrMounted(metadata: tableMetadata, metadataFolder: tableMetadata?) -> Bool {
@@ -1117,16 +1076,6 @@ extension NCManageDatabase {
         }
         }
     }
     }
 
 
-    func isDownloadMetadata(_ metadata: tableMetadata, download: Bool) -> Bool {
-
-        let localFile = getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-        let fileSize = utilityFileSystem.fileProviderStorageSize(metadata.ocId, fileNameView: metadata.fileNameView)
-        if (localFile != nil || download) && (localFile?.etag != metadata.etag || fileSize == 0) {
-            return true
-        }
-        return false
-    }
-
     func getMetadataConflict(account: String, serverUrl: String, fileNameView: String) -> tableMetadata? {
     func getMetadataConflict(account: String, serverUrl: String, fileNameView: String) -> tableMetadata? {
 
 
         // verify exists conflict
         // verify exists conflict

+ 1 - 1
iOSClient/Data/NCManageDatabase+Video.swift

@@ -48,7 +48,7 @@ extension NCManageDatabase {
 
 
     func addVideo(metadata: tableMetadata, position: Float? = nil, width: Int? = nil, height: Int? = nil, length: Int? = nil, currentAudioTrackIndex: Int? = nil, currentVideoSubTitleIndex: Int? = nil) {
     func addVideo(metadata: tableMetadata, position: Float? = nil, width: Int? = nil, height: Int? = nil, length: Int? = nil, currentAudioTrackIndex: Int? = nil, currentVideoSubTitleIndex: Int? = nil) {
 
 
-        if metadata.livePhoto { return }
+        if metadata.isLivePhoto { return }
 
 
         do {
         do {
             let realm = try Realm()
             let realm = try Realm()

+ 7 - 3
iOSClient/Data/NCManageDatabase.swift

@@ -110,8 +110,6 @@ class NCManageDatabase: NSObject {
                             migration.deleteData(forType: tableActivityLatestId.className())
                             migration.deleteData(forType: tableActivityLatestId.className())
                             migration.deleteData(forType: tableActivityPreview.className())
                             migration.deleteData(forType: tableActivityPreview.className())
                             migration.deleteData(forType: tableActivitySubjectRich.className())
                             migration.deleteData(forType: tableActivitySubjectRich.className())
-                            migration.deleteData(forType: tableDirectory.className())
-                            migration.deleteData(forType: tableMetadata.className())
                         }
                         }
 
 
                         if oldSchemaVersion < 292 {
                         if oldSchemaVersion < 292 {
@@ -120,12 +118,18 @@ class NCManageDatabase: NSObject {
 
 
                         if oldSchemaVersion < 319 {
                         if oldSchemaVersion < 319 {
                             migration.deleteData(forType: tableChunk.className())
                             migration.deleteData(forType: tableChunk.className())
-                            migration.deleteData(forType: tableMetadata.className())
                             migration.deleteData(forType: tableDirectory.className())
                             migration.deleteData(forType: tableDirectory.className())
                             migration.deleteData(forType: tableE2eEncryptionLock.className())
                             migration.deleteData(forType: tableE2eEncryptionLock.className())
                             migration.deleteData(forType: tableGPS.className())
                             migration.deleteData(forType: tableGPS.className())
                         }
                         }
 
 
+                        if oldSchemaVersion < 331 {
+                            migration.deleteData(forType: tableMetadata.className())
+                            migration.enumerateObjects(ofType: tableDirectory.className()) { _, newObject in
+                                newObject?["etag"] = ""
+                            }
+                        }
+
                     }, shouldCompactOnLaunch: { totalBytes, usedBytes in
                     }, shouldCompactOnLaunch: { totalBytes, usedBytes in
 
 
                         // totalBytes refers to the size of the file on disk in bytes (data + free space)
                         // totalBytes refers to the size of the file on disk in bytes (data + free space)

+ 12 - 3
iOSClient/Diagnostics/NCCapabilitiesView.swift

@@ -52,10 +52,19 @@ class NCCapabilitiesViewOO: ObservableObject {
     let utilityFileSystem = NCUtilityFileSystem()
     let utilityFileSystem = NCUtilityFileSystem()
 
 
     init() {
     init() {
+        loadCapabilities()
+        NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeUser), object: nil, queue: nil) { _ in
+            self.loadCapabilities()
+        }
+    }
+
+    func loadCapabilities() {
         guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else { return }
         guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else { return }
         var textEditor = false
         var textEditor = false
         var onlyofficeEditors = false
         var onlyofficeEditors = false
 
 
+        capabililies.removeAll()
+
         if let image = UIImage(named: "share") {
         if let image = UIImage(named: "share") {
             capabililies.append(Capability(text: "File sharing", image: image, resize: true, available: NCGlobal.shared.capabilityFileSharingApiEnabled))
             capabililies.append(Capability(text: "File sharing", image: image, resize: true, available: NCGlobal.shared.capabilityFileSharingApiEnabled))
         }
         }
@@ -125,13 +134,13 @@ struct NCCapabilitiesView: View {
                 Section {
                 Section {
                     ForEach(capabilitiesViewOO.capabililies, id: \.id) { capability in
                     ForEach(capabilitiesViewOO.capabililies, id: \.id) { capability in
                         HStack {
                         HStack {
-                            CapabilityName(text: capability.text, image: Image(uiImage: capability.image), resize: capability.resize)
+                            CapabilityName(text: Binding.constant(capability.text), image: Image(uiImage: capability.image), resize: capability.resize)
                             CapabilityStatus(available: capability.available)
                             CapabilityStatus(available: capability.available)
                         }
                         }
                     }
                     }
                 }
                 }
                 Section {
                 Section {
-                    CapabilityName(text: capabilitiesViewOO.homeServer, image: Image(systemName: "house"), resize: false)
+                    CapabilityName(text: $capabilitiesViewOO.homeServer, image: Image(systemName: "house"), resize: false)
                 }
                 }
             }
             }
         }
         }
@@ -140,7 +149,7 @@ struct NCCapabilitiesView: View {
 
 
     struct CapabilityName: View {
     struct CapabilityName: View {
 
 
-        @State var text: String = ""
+        @Binding var text: String
         @State var image: Image
         @State var image: Image
         @State var resize: Bool
         @State var resize: Bool
 
 

+ 1 - 1
iOSClient/Extensions/UIAlertController+Extension.swift

@@ -74,7 +74,7 @@ extension UIAlertController {
             object: alertController.textFields?.first,
             object: alertController.textFields?.first,
             queue: .main) { _ in
             queue: .main) { _ in
                 guard let text = alertController.textFields?.first?.text else { return }
                 guard let text = alertController.textFields?.first?.text else { return }
-                let folderName = NCUtility().removeForbiddenCharacters(text).trimmingCharacters(in: .whitespaces)
+                let folderName = text.trimmingCharacters(in: .whitespaces)
                 okAction.isEnabled = !folderName.isEmpty && folderName != "." && folderName != ".."
                 okAction.isEnabled = !folderName.isEmpty && folderName != "." && folderName != ".."
             }
             }
 
 

+ 0 - 1
iOSClient/Favorites/NCFavorite.swift

@@ -65,7 +65,6 @@ class NCFavorite: NCCollectionViewCommon {
                                        ascending: self.layoutForView?.ascending,
                                        ascending: self.layoutForView?.ascending,
                                        directoryOnTop: self.layoutForView?.directoryOnTop,
                                        directoryOnTop: self.layoutForView?.directoryOnTop,
                                        favoriteOnTop: true,
                                        favoriteOnTop: true,
-                                       filterLivePhoto: true,
                                        groupByField: self.groupByField,
                                        groupByField: self.groupByField,
                                        providers: self.providers,
                                        providers: self.providers,
                                        searchResults: self.searchResults)
                                        searchResults: self.searchResults)

+ 15 - 2
iOSClient/Files/NCFiles.swift

@@ -123,7 +123,6 @@ class NCFiles: NCCollectionViewCommon {
             ascending: self.layoutForView?.ascending,
             ascending: self.layoutForView?.ascending,
             directoryOnTop: self.layoutForView?.directoryOnTop,
             directoryOnTop: self.layoutForView?.directoryOnTop,
             favoriteOnTop: true,
             favoriteOnTop: true,
-            filterLivePhoto: true,
             groupByField: self.groupByField,
             groupByField: self.groupByField,
             providers: self.providers,
             providers: self.providers,
             searchResults: self.searchResults)
             searchResults: self.searchResults)
@@ -157,6 +156,20 @@ class NCFiles: NCCollectionViewCommon {
             return
             return
         }
         }
 
 
+        func downloadMetadata(_ metadata: tableMetadata) -> Bool {
+
+            let fileSize = utilityFileSystem.fileProviderStorageSize(metadata.ocId, fileNameView: metadata.fileNameView)
+            guard fileSize > 0 else { return false }
+
+            if let localFile = NCManageDatabase.shared.getResultsTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))?.first {
+                if localFile.etag != metadata.etag {
+                    return true
+                }
+            }
+
+            return false
+        }
+
         NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Reload data source network files forced \(isForced)")
         NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Reload data source network files forced \(isForced)")
 
 
         isReloadDataSourceNetworkInProgress = true
         isReloadDataSourceNetworkInProgress = true
@@ -164,7 +177,7 @@ class NCFiles: NCCollectionViewCommon {
 
 
         networkReadFolder(isForced: isForced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, error in
         networkReadFolder(isForced: isForced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, error in
             if error == .success {
             if error == .success {
-                for metadata in metadatas ?? [] where !metadata.directory && NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) {
+                for metadata in metadatas ?? [] where !metadata.directory && downloadMetadata(metadata) {
                     if self.appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty {
                     if self.appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty {
                         self.appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile))
                         self.appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile))
                     }
                     }

+ 0 - 1
iOSClient/Groupfolders/NCGroupfolders.swift

@@ -66,7 +66,6 @@ class NCGroupfolders: NCCollectionViewCommon {
             ascending: self.layoutForView?.ascending,
             ascending: self.layoutForView?.ascending,
             directoryOnTop: self.layoutForView?.directoryOnTop,
             directoryOnTop: self.layoutForView?.directoryOnTop,
             favoriteOnTop: true,
             favoriteOnTop: true,
-            filterLivePhoto: true,
             groupByField: self.groupByField,
             groupByField: self.groupByField,
             providers: self.providers,
             providers: self.providers,
             searchResults: self.searchResults)
             searchResults: self.searchResults)

+ 4 - 4
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -935,7 +935,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                     ascending: self.layoutForView?.ascending,
                     ascending: self.layoutForView?.ascending,
                     directoryOnTop: self.layoutForView?.directoryOnTop,
                     directoryOnTop: self.layoutForView?.directoryOnTop,
                     favoriteOnTop: true,
                     favoriteOnTop: true,
-                    filterLivePhoto: true,
                     providers: self.providers,
                     providers: self.providers,
                     searchResults: self.searchResults)
                     searchResults: self.searchResults)
             } update: { _, _, searchResult, metadatas in
             } update: { _, _, searchResult, metadatas in
@@ -960,7 +959,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
                     ascending: self.layoutForView?.ascending,
                     ascending: self.layoutForView?.ascending,
                     directoryOnTop: self.layoutForView?.directoryOnTop,
                     directoryOnTop: self.layoutForView?.directoryOnTop,
                     favoriteOnTop: true,
                     favoriteOnTop: true,
-                    filterLivePhoto: true,
                     groupByField: self.groupByField,
                     groupByField: self.groupByField,
                     providers: self.providers,
                     providers: self.providers,
                     searchResults: self.searchResults)
                     searchResults: self.searchResults)
@@ -1380,8 +1378,10 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
 
 
         } else {
         } else {
 
 
+            let tableLocalFile = NCManageDatabase.shared.getResultsTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))?.first
+
             // image local
             // image local
-            if NCManageDatabase.shared.getTableLocalFile(ocId: metadata.ocId) != nil {
+            if let tableLocalFile, tableLocalFile.offline {
                 a11yValues.append(NSLocalizedString("_offline_", comment: ""))
                 a11yValues.append(NSLocalizedString("_offline_", comment: ""))
                 cell.fileLocalImage?.image = NCImageCache.images.offlineFlag
                 cell.fileLocalImage?.image = NCImageCache.images.offlineFlag
             } else if utilityFileSystem.fileProviderStorageExists(metadata) {
             } else if utilityFileSystem.fileProviderStorageExists(metadata) {
@@ -1447,7 +1447,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
         }
         }
 
 
         // Live Photo
         // Live Photo
-        if metadata.livePhoto {
+        if metadata.isLivePhoto {
             cell.fileStatusImage?.image = NCImageCache.images.livePhoto
             cell.fileStatusImage?.image = NCImageCache.images.livePhoto
             a11yValues.append(NSLocalizedString("_upload_mov_livephoto_", comment: ""))
             a11yValues.append(NSLocalizedString("_upload_mov_livephoto_", comment: ""))
         }
         }

+ 4 - 1
iOSClient/Main/Create cloud/NCUploadAssets.swift

@@ -257,8 +257,11 @@ struct UploadAssetsView: View {
             let isRecordInSessions = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@ AND session != ''", uploadAssets.userBaseUrl.account, serverUrl, fileName), sorted: "fileName", ascending: false)
             let isRecordInSessions = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@ AND session != ''", uploadAssets.userBaseUrl.account, serverUrl, fileName), sorted: "fileName", ascending: false)
             if !isRecordInSessions.isEmpty { continue }
             if !isRecordInSessions.isEmpty { continue }
 
 
-            let metadata = NCManageDatabase.shared.createMetadata(account: uploadAssets.userBaseUrl.account, user: uploadAssets.userBaseUrl.user, userId: uploadAssets.userBaseUrl.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: uploadAssets.userBaseUrl.urlBase, url: "", contentType: "", isLivePhoto: livePhoto)
+            let metadata = NCManageDatabase.shared.createMetadata(account: uploadAssets.userBaseUrl.account, user: uploadAssets.userBaseUrl.user, userId: uploadAssets.userBaseUrl.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: uploadAssets.userBaseUrl.urlBase, url: "", contentType: "")
 
 
+            if livePhoto {
+                metadata.livePhotoFile = (metadata.fileName as NSString).deletingPathExtension + ".mov"
+            }
             metadata.assetLocalIdentifier = asset.localIdentifier
             metadata.assetLocalIdentifier = asset.localIdentifier
             metadata.session = NCNetworking.shared.sessionIdentifierBackground
             metadata.session = NCNetworking.shared.sessionIdentifierBackground
             metadata.sessionSelector = NCGlobal.shared.selectorUploadFile
             metadata.sessionSelector = NCGlobal.shared.selectorUploadFile

+ 38 - 43
iOSClient/Media/NCMedia.swift

@@ -39,6 +39,7 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
     internal let utilityFileSystem = NCUtilityFileSystem()
     internal let utilityFileSystem = NCUtilityFileSystem()
     internal let utility = NCUtility()
     internal let utility = NCUtility()
 
 
+    internal var metadatas: [tableMetadata] = []
     internal var isEditMode = false
     internal var isEditMode = false
     internal var selectOcId: [String] = []
     internal var selectOcId: [String] = []
     internal var selectIndexPath: [IndexPath] = []
     internal var selectIndexPath: [IndexPath] = []
@@ -122,6 +123,9 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
         NotificationCenter.default.addObserver(self, selector: #selector(renameFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(renameFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil)
 
 
+        if let metadatas = NCImageCache.shared.initialMetadatas() {
+            self.metadatas = metadatas
+        }
         timerSearchNewMedia?.invalidate()
         timerSearchNewMedia?.invalidate()
         timerSearchNewMedia = Timer.scheduledTimer(timeInterval: timeIntervalSearchNewMedia, target: self, selector: #selector(searchNewMediaTimer), userInfo: nil, repeats: false)
         timerSearchNewMedia = Timer.scheduledTimer(timeInterval: timeIntervalSearchNewMedia, target: self, selector: #selector(searchNewMediaTimer), userInfo: nil, repeats: false)
 
 
@@ -160,22 +164,13 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
 
 
         guard let userInfo = notification.userInfo as NSDictionary?,
         guard let userInfo = notification.userInfo as NSDictionary?,
               let error = userInfo["error"] as? NKError else { return }
               let error = userInfo["error"] as? NKError else { return }
-        let onlyLocalCache: Bool = userInfo["onlyLocalCache"] as? Bool ?? false
 
 
-        NCImageCache.shared.getMediaMetadatas(account: appDelegate.account, predicate: getPredicate())
+        self.metadatas = NCImageCache.shared.getMediaMetadatas(account: appDelegate.account, predicate: getPredicate())
 
 
-        if error == .success, let indexPath = userInfo["indexPath"] as? [IndexPath], !indexPath.isEmpty, !onlyLocalCache {
-            collectionView?.performBatchUpdates({
-                collectionView?.deleteItems(at: indexPath)
-            }, completion: { _ in
-                self.collectionView?.reloadData()
-            })
-        } else {
-            if error != .success {
-                NCContentPresenter().showError(error: error)
-            }
-            self.collectionView?.reloadData()
+        if error != .success {
+            NCContentPresenter().showError(error: error)
         }
         }
+        self.collectionView?.reloadData()
 
 
         if let hud = userInfo["hud"] as? JGProgressHUD {
         if let hud = userInfo["hud"] as? JGProgressHUD {
             hud.dismiss()
             hud.dismiss()
@@ -203,7 +198,7 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
               account == appDelegate.account
               account == appDelegate.account
         else { return }
         else { return }
 
 
-        self.reloadDataSourceWithCompletion { _ in }
+        self.reloadDataSource { }
     }
     }
 
 
     @objc func uploadedFile(_ notification: NSNotification) {
     @objc func uploadedFile(_ notification: NSNotification) {
@@ -215,7 +210,7 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
               account == appDelegate.account
               account == appDelegate.account
         else { return }
         else { return }
 
 
-        self.reloadDataSourceWithCompletion { _ in }
+        self.reloadDataSource { }
     }
     }
 
 
     // MARK: - Command
     // MARK: - Command
@@ -278,7 +273,7 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
         let home = utilityFileSystem.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId)
         let home = utilityFileSystem.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId)
         mediaPath = serverUrl.replacingOccurrences(of: home, with: "")
         mediaPath = serverUrl.replacingOccurrences(of: home, with: "")
         NCManageDatabase.shared.setAccountMediaPath(mediaPath, account: appDelegate.account)
         NCManageDatabase.shared.setAccountMediaPath(mediaPath, account: appDelegate.account)
-        reloadDataSourceWithCompletion { _ in
+        reloadDataSource {
             self.searchNewMedia()
             self.searchNewMedia()
         }
         }
     }
     }
@@ -303,7 +298,7 @@ extension NCMedia: UICollectionViewDelegate {
 
 
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
 
 
-        let metadata = NCImageCache.shared.metadatas[indexPath.row]
+        let metadata = self.metadatas[indexPath.row]
         if isEditMode {
         if isEditMode {
             if let index = selectOcId.firstIndex(of: metadata.ocId) {
             if let index = selectOcId.firstIndex(of: metadata.ocId) {
                 selectOcId.remove(at: index)
                 selectOcId.remove(at: index)
@@ -319,14 +314,14 @@ extension NCMedia: UICollectionViewDelegate {
             // ACTIVE SERVERURL
             // ACTIVE SERVERURL
             appDelegate.activeServerUrl = metadata.serverUrl
             appDelegate.activeServerUrl = metadata.serverUrl
             let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridMediaCell
             let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridMediaCell
-            NCViewer().view(viewController: self, metadata: metadata, metadatas: NCImageCache.shared.metadatas, imageIcon: cell?.imageItem.image)
+            NCViewer().view(viewController: self, metadata: metadata, metadatas: self.metadatas, imageIcon: cell?.imageItem.image)
         }
         }
     }
     }
 
 
     func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
     func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
 
 
         guard let cell = collectionView.cellForItem(at: indexPath) as? NCGridMediaCell else { return nil }
         guard let cell = collectionView.cellForItem(at: indexPath) as? NCGridMediaCell else { return nil }
-        let metadata = NCImageCache.shared.metadatas[indexPath.row]
+        let metadata = self.metadatas[indexPath.row]
         let identifier = indexPath as NSCopying
         let identifier = indexPath as NSCopying
         let image = cell.imageItem.image
         let image = cell.imageItem.image
 
 
@@ -362,13 +357,13 @@ extension NCMedia: UICollectionViewDataSource {
     }
     }
 
 
     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        emptyDataSet?.numberOfItemsInSection(NCImageCache.shared.metadatas.count, section: section)
-        return NCImageCache.shared.metadatas.count
+        emptyDataSet?.numberOfItemsInSection(self.metadatas.count, section: section)
+        return self.metadatas.count
     }
     }
 
 
     func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
     func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
-        if !collectionView.indexPathsForVisibleItems.contains(indexPath) && indexPath.row < NCImageCache.shared.metadatas.count {
-            let metadata = NCImageCache.shared.metadatas[indexPath.row]
+        if !collectionView.indexPathsForVisibleItems.contains(indexPath) && indexPath.row < self.metadatas.count {
+            let metadata = self.metadatas[indexPath.row]
             for case let operation as NCMediaDownloadThumbnaill in appDelegate.downloadThumbnailQueue.operations where operation.metadata.ocId == metadata.ocId {
             for case let operation as NCMediaDownloadThumbnaill in appDelegate.downloadThumbnailQueue.operations where operation.metadata.ocId == metadata.ocId {
                 operation.cancel()
                 operation.cancel()
             }
             }
@@ -379,9 +374,9 @@ extension NCMedia: UICollectionViewDataSource {
 
 
         guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridMediaCell else { return UICollectionViewCell() }
         guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridMediaCell else { return UICollectionViewCell() }
 
 
-        if indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section) && indexPath.row < NCImageCache.shared.metadatas.count {
+        if indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section) && indexPath.row < self.metadatas.count {
 
 
-            let metadata = NCImageCache.shared.metadatas[indexPath.row]
+            let metadata = self.metadatas[indexPath.row]
 
 
             self.cellHeigth = cell.frame.size.height
             self.cellHeigth = cell.frame.size.height
 
 
@@ -410,7 +405,7 @@ extension NCMedia: UICollectionViewDataSource {
 
 
             if metadata.isAudioOrVideo {
             if metadata.isAudioOrVideo {
                 cell.imageStatus.image = cacheImages.cellPlayImage
                 cell.imageStatus.image = cacheImages.cellPlayImage
-            } else if metadata.livePhoto && NCImageCache.shared.livePhoto {
+            } else if metadata.isLivePhoto {
                 cell.imageStatus.image = cacheImages.cellLivePhotoImage
                 cell.imageStatus.image = cacheImages.cellLivePhotoImage
             } else {
             } else {
                 cell.imageStatus.image = nil
                 cell.imageStatus.image = nil
@@ -449,31 +444,31 @@ extension NCMedia: UICollectionViewDelegateFlowLayout {
 
 
 extension NCMedia {
 extension NCMedia {
 
 
-    func getPredicate(_ predicatedefault: Bool = false) -> NSPredicate {
+    func getPredicate(_ predicateShowBoth: Bool = false) -> NSPredicate {
 
 
         let startServerUrl = NCUtilityFileSystem().getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) + mediaPath
         let startServerUrl = NCUtilityFileSystem().getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) + mediaPath
-        let showAll = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND (classFile == %@ OR classFile == %@) AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue, NKCommon.TypeClassFile.video.rawValue)
+        let showBoth = NSPredicate(format: NCImageCache.shared.showBothPredicateMediaString, appDelegate.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue, NKCommon.TypeClassFile.video.rawValue, NKCommon.TypeClassFile.video.rawValue)
 
 
-        if predicatedefault { return showAll }
+        if predicateShowBoth { return showBoth }
         if showOnlyImages {
         if showOnlyImages {
-            return NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue)
+            return NSPredicate(format: NCImageCache.shared.showOnlyPredicateMediaString, appDelegate.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue, NKCommon.TypeClassFile.video.rawValue)
         } else if showOnlyVideos {
         } else if showOnlyVideos {
-            return NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload')", appDelegate.account, startServerUrl, NKCommon.TypeClassFile.video.rawValue)
+            return NSPredicate(format: NCImageCache.shared.showOnlyPredicateMediaString, appDelegate.account, startServerUrl, NKCommon.TypeClassFile.video.rawValue, NKCommon.TypeClassFile.video.rawValue)
         } else {
         } else {
-           return showAll
+           return showBoth
         }
         }
     }
     }
 
 
-    @objc func reloadDataSourceWithCompletion(_ completion: @escaping (_ metadatas: [tableMetadata]) -> Void) {
+    @objc func reloadDataSource(completion: @escaping () -> Void) {
         guard !appDelegate.account.isEmpty else { return }
         guard !appDelegate.account.isEmpty else { return }
 
 
         DispatchQueue.global().async {
         DispatchQueue.global().async {
-            NCImageCache.shared.getMediaMetadatas(account: self.appDelegate.account, predicate: self.getPredicate())
+            self.metadatas = NCImageCache.shared.getMediaMetadatas(account: self.appDelegate.account, predicate: self.getPredicate())
             DispatchQueue.main.sync {
             DispatchQueue.main.sync {
                 self.reloadDataThenPerform {
                 self.reloadDataThenPerform {
                     self.updateMediaControlVisibility()
                     self.updateMediaControlVisibility()
                     self.mediaCommandTitle()
                     self.mediaCommandTitle()
-                    completion(NCImageCache.shared.metadatas)
+                    completion()
                 }
                 }
             }
             }
         }
         }
@@ -481,7 +476,7 @@ extension NCMedia {
 
 
     func updateMediaControlVisibility() {
     func updateMediaControlVisibility() {
 
 
-        if NCImageCache.shared.metadatas.isEmpty {
+        if self.metadatas.isEmpty {
             if !self.showOnlyImages && !self.showOnlyVideos {
             if !self.showOnlyImages && !self.showOnlyVideos {
                 self.mediaCommandView?.toggleEmptyView(isEmpty: true)
                 self.mediaCommandView?.toggleEmptyView(isEmpty: true)
                 self.mediaCommandView?.isHidden = false
                 self.mediaCommandView?.isHidden = false
@@ -538,11 +533,11 @@ extension NCMedia {
                         let predicateDate = NSPredicate(format: "date > %@ AND date < %@", greaterDate as NSDate, lessDate as NSDate)
                         let predicateDate = NSPredicate(format: "date > %@ AND date < %@", greaterDate as NSDate, lessDate as NSDate)
                         let predicateResult = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateDate, self.getPredicate(true)])
                         let predicateResult = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateDate, self.getPredicate(true)])
                         let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: predicateResult)
                         let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: predicateResult)
-                        let metadatasChanged = NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult, addCompareLivePhoto: false)
+                        let metadatasChanged = NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult)
                         if metadatasChanged.metadatasUpdate.isEmpty {
                         if metadatasChanged.metadatasUpdate.isEmpty {
                             self.researchOldMedia(value: value, limit: limit, withElseReloadDataSource: true)
                             self.researchOldMedia(value: value, limit: limit, withElseReloadDataSource: true)
                         } else {
                         } else {
-                            self.reloadDataSourceWithCompletion { _ in }
+                            self.reloadDataSource { }
                         }
                         }
                     }
                     }
                 } else {
                 } else {
@@ -566,7 +561,7 @@ extension NCMedia {
             searchOldMedia(value: -999, limit: 0)
             searchOldMedia(value: -999, limit: 0)
         } else {
         } else {
             if withElseReloadDataSource {
             if withElseReloadDataSource {
-                self.reloadDataSourceWithCompletion { _ in }
+                self.reloadDataSource { }
             }
             }
         }
         }
     }
     }
@@ -590,7 +585,7 @@ extension NCMedia {
         if let visibleCells = self.collectionView?.indexPathsForVisibleItems.sorted(by: { $0.row < $1.row }).compactMap({ self.collectionView?.cellForItem(at: $0) }) {
         if let visibleCells = self.collectionView?.indexPathsForVisibleItems.sorted(by: { $0.row < $1.row }).compactMap({ self.collectionView?.cellForItem(at: $0) }) {
             if let cell = visibleCells.first as? NCGridMediaCell {
             if let cell = visibleCells.first as? NCGridMediaCell {
                 if cell.date != nil {
                 if cell.date != nil {
-                    if cell.date != NCImageCache.shared.metadatas.first?.date as Date? {
+                    if cell.date != self.metadatas.first?.date as Date? {
                         lessDate = Calendar.current.date(byAdding: .second, value: 1, to: cell.date!)!
                         lessDate = Calendar.current.date(byAdding: .second, value: 1, to: cell.date!)!
                         limit = 0
                         limit = 0
                     }
                     }
@@ -619,12 +614,12 @@ extension NCMedia {
                         let predicate = NSPredicate(format: "date > %@ AND date < %@", greaterDate as NSDate, lessDate as NSDate)
                         let predicate = NSPredicate(format: "date > %@ AND date < %@", greaterDate as NSDate, lessDate as NSDate)
                         let predicateResult = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, self.getPredicate(true)])
                         let predicateResult = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, self.getPredicate(true)])
                         let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: predicateResult)
                         let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: predicateResult)
-                        let updateMetadatas = NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult, addCompareLivePhoto: false)
+                        let updateMetadatas = NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult)
                         if !updateMetadatas.metadatasUpdate.isEmpty || !updateMetadatas.metadatasDelete.isEmpty {
                         if !updateMetadatas.metadatasUpdate.isEmpty || !updateMetadatas.metadatasDelete.isEmpty {
-                            self.reloadDataSourceWithCompletion { _ in }
+                            self.reloadDataSource { }
                         }
                         }
                     }
                     }
-                } else if error == .success, files.isEmpty, NCImageCache.shared.metadatas.isEmpty {
+                } else if error == .success, files.isEmpty, self.metadatas.isEmpty {
                     self.searchOldMedia()
                     self.searchOldMedia()
                 } else if error != .success {
                 } else if error != .success {
                     NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Media search new media error code \(error.errorCode) " + error.errorDescription)
                     NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Media search new media error code \(error.errorCode) " + error.errorDescription)

+ 25 - 66
iOSClient/Menu/NCMedia+Menu.swift

@@ -40,7 +40,7 @@ extension NCMedia {
         defer { presentMenu(with: actions) }
         defer { presentMenu(with: actions) }
 
 
         if !isEditMode {
         if !isEditMode {
-            if !NCImageCache.shared.metadatas.isEmpty {
+            if !self.metadatas.isEmpty {
                 actions.append(
                 actions.append(
                     NCMenuAction(
                     NCMenuAction(
                         title: NSLocalizedString("_select_", comment: ""),
                         title: NSLocalizedString("_select_", comment: ""),
@@ -54,6 +54,27 @@ extension NCMedia {
 
 
             actions.append(.seperator(order: 0))
             actions.append(.seperator(order: 0))
 
 
+            actions.append(
+                NCMenuAction(
+                    title: NSLocalizedString("_select_media_folder_", comment: ""),
+                    icon: utility.loadImage(named: "folder"),
+                    action: { _ in
+                        if let navigationController = UIStoryboard(name: "NCSelect", bundle: nil).instantiateInitialViewController() as? UINavigationController,
+                           let viewController = navigationController.topViewController as? NCSelect {
+
+                            viewController.delegate = self
+                            viewController.typeOfCommandView = .select
+                            viewController.type = "mediaFolder"
+                            viewController.selectIndexPath = self.selectIndexPath
+
+                            self.present(navigationController, animated: true, completion: nil)
+                        }
+                    }
+                )
+            )
+
+            actions.append(.seperator(order: 0))
+
             actions.append(
             actions.append(
                 NCMenuAction(
                 NCMenuAction(
                     title: NSLocalizedString("_media_viewimage_show_", comment: ""),
                     title: NSLocalizedString("_media_viewimage_show_", comment: ""),
@@ -63,7 +84,7 @@ extension NCMedia {
                     action: { _ in
                     action: { _ in
                         self.showOnlyImages = true
                         self.showOnlyImages = true
                         self.showOnlyVideos = false
                         self.showOnlyVideos = false
-                        self.reloadDataSourceWithCompletion { _ in }
+                        self.reloadDataSource { }
                     }
                     }
                 )
                 )
             )
             )
@@ -77,7 +98,7 @@ extension NCMedia {
                     action: { _ in
                     action: { _ in
                         self.showOnlyImages = false
                         self.showOnlyImages = false
                         self.showOnlyVideos = true
                         self.showOnlyVideos = true
-                        self.reloadDataSourceWithCompletion { _ in }
+                        self.reloadDataSource { }
                     }
                     }
                 )
                 )
             )
             )
@@ -91,28 +112,7 @@ extension NCMedia {
                     action: { _ in
                     action: { _ in
                         self.showOnlyImages = false
                         self.showOnlyImages = false
                         self.showOnlyVideos = false
                         self.showOnlyVideos = false
-                        self.reloadDataSourceWithCompletion { _ in }
-                    }
-                )
-            )
-
-            actions.append(.seperator(order: 0))
-
-            actions.append(
-                NCMenuAction(
-                    title: NSLocalizedString("_select_media_folder_", comment: ""),
-                    icon: utility.loadImage(named: "folder"),
-                    action: { _ in
-                        if let navigationController = UIStoryboard(name: "NCSelect", bundle: nil).instantiateInitialViewController() as? UINavigationController,
-                           let viewController = navigationController.topViewController as? NCSelect {
-
-                            viewController.delegate = self
-                            viewController.typeOfCommandView = .select
-                            viewController.type = "mediaFolder"
-                            viewController.selectIndexPath = self.selectIndexPath
-
-                            self.present(navigationController, animated: true, completion: nil)
-                        }
+                        self.reloadDataSource { }
                     }
                     }
                 )
                 )
             )
             )
@@ -158,47 +158,6 @@ extension NCMedia {
                 )
                 )
             )
             )
 
 
-            actions.append(.seperator(order: 0))
-
-            actions.append(
-                NCMenuAction(
-                    title: NSLocalizedString("_media_by_modified_date_", comment: ""),
-                    icon: utility.loadImage(named: "circle.grid.cross.up.fill"),
-                    selected: NCKeychain().mediaSortDate == "date",
-                    on: true,
-                    action: { _ in
-                        NCKeychain().mediaSortDate = "date"
-                        self.reloadDataSourceWithCompletion { _ in }
-                    }
-                )
-            )
-
-            actions.append(
-                NCMenuAction(
-                    title: NSLocalizedString("_media_by_created_date_", comment: ""),
-                    icon: utility.loadImage(named: "circle.grid.cross.down.fill"),
-                    selected: NCKeychain().mediaSortDate == "creationDate",
-                    on: true,
-                    action: { _ in
-                        NCKeychain().mediaSortDate = "creationDate"
-                        self.reloadDataSourceWithCompletion { _ in }
-                    }
-                )
-            )
-
-            actions.append(
-                NCMenuAction(
-                    title: NSLocalizedString("_media_by_upload_date_", comment: ""),
-                    icon: utility.loadImage(named: "circle.grid.cross.right.fill"),
-                    selected: NCKeychain().mediaSortDate == "uploadDate",
-                    on: true,
-                    action: { _ in
-                        NCKeychain().mediaSortDate = "uploadDate"
-                        self.reloadDataSourceWithCompletion { _ in }
-                    }
-                )
-            )
-
         } else {
         } else {
 
 
             //
             //

+ 11 - 2
iOSClient/NCGlobal.swift

@@ -104,7 +104,6 @@ class NCGlobal: NSObject {
     let nextcloudVersion26: Int                     = 26
     let nextcloudVersion26: Int                     = 26
     let nextcloudVersion27: Int                     = 27
     let nextcloudVersion27: Int                     = 27
     let nextcloudVersion28: Int                     = 28
     let nextcloudVersion28: Int                     = 28
-    let nextcloudVersion29: Int                     = 29
 
 
     // Nextcloud unsupported
     // Nextcloud unsupported
     //
     //
@@ -253,7 +252,6 @@ class NCGlobal: NSObject {
     @objc let errorE2EENoUserFound: Int             = -98015
     @objc let errorE2EENoUserFound: Int             = -98015
     @objc let errorE2EEUploadInProgress: Int        = -98016
     @objc let errorE2EEUploadInProgress: Int        = -98016
 
 
-
     // Constants to identify the different permissions of a file
     // Constants to identify the different permissions of a file
     //
     //
     @objc let permissionShared                      = "S"
     @objc let permissionShared                      = "S"
@@ -351,6 +349,7 @@ class NCGlobal: NSObject {
     @objc let notificationCenterApplicationDidEnterBackground   = "applicationDidEnterBackground"
     @objc let notificationCenterApplicationDidEnterBackground   = "applicationDidEnterBackground"
     @objc let notificationCenterApplicationDidBecomeActive      = "applicationDidBecomeActive"
     @objc let notificationCenterApplicationDidBecomeActive      = "applicationDidBecomeActive"
     @objc let notificationCenterApplicationWillResignActive     = "applicationWillResignActive"
     @objc let notificationCenterApplicationWillResignActive     = "applicationWillResignActive"
+    @objc let notificationCenterApplicationWillEnterForeground  = "applicationWillEnterForeground"
 
 
     @objc let notificationCenterChangeUser                      = "changeUser"
     @objc let notificationCenterChangeUser                      = "changeUser"
     @objc let notificationCenterChangeTheming                   = "changeTheming"
     @objc let notificationCenterChangeTheming                   = "changeTheming"
@@ -396,6 +395,8 @@ class NCGlobal: NSObject {
     let notificationCenterEnableSwipeGesture                    = "enableSwipeGesture"
     let notificationCenterEnableSwipeGesture                    = "enableSwipeGesture"
     let notificationCenterDisableSwipeGesture                   = "disableSwipeGesture"
     let notificationCenterDisableSwipeGesture                   = "disableSwipeGesture"
 
 
+    let notificationCenterFinishedMediaInProcess                = "finishedMediaInProcess"
+
     // TIP
     // TIP
     //
     //
     let tipNCViewerPDFThumbnail                                 = "tipncviewerpdfthumbnail"
     let tipNCViewerPDFThumbnail                                 = "tipncviewerpdfthumbnail"
@@ -473,6 +474,9 @@ class NCGlobal: NSObject {
     @objc var capabilityUserStatusEnabled: Bool                 = false
     @objc var capabilityUserStatusEnabled: Bool                 = false
     var capabilityExternalSites: Bool                           = false
     var capabilityExternalSites: Bool                           = false
     var capabilityGroupfoldersEnabled: Bool                     = false // NC27
     var capabilityGroupfoldersEnabled: Bool                     = false // NC27
+    var isLivePhotoServerAvailable: Bool {                              // NC28
+        return capabilityServerVersionMajor >= nextcloudVersion28
+    }
 
 
     // MORE NEXTCLOUD APPS
     // MORE NEXTCLOUD APPS
     let talkSchemeUrl                                           = "nextcloudtalk://"
     let talkSchemeUrl                                           = "nextcloudtalk://"
@@ -482,5 +486,10 @@ class NCGlobal: NSObject {
     let moreAppsUrl                                             = "itms-apps://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/search?media=software&term=nextcloud"
     let moreAppsUrl                                             = "itms-apps://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/search?media=software&term=nextcloud"
 
 
     // SNAPSHOT PREVIEW
     // SNAPSHOT PREVIEW
+    //
     let defaultSnapshotConfiguration = "DefaultPreviewConfiguration"
     let defaultSnapshotConfiguration = "DefaultPreviewConfiguration"
+
+    // FORBIDDEN CHARACTERS
+    //
+    let forbiddenCharacters = ["/", "\\", ":", "\"", "|", "?", "*", "<", ">"]
 }
 }

+ 27 - 28
iOSClient/NCImageCache.swift

@@ -47,8 +47,11 @@ import NextcloudKit
         return ThumbnailLRUCache(countLimit: limit)
         return ThumbnailLRUCache(countLimit: limit)
     }()
     }()
     private var ocIdEtag: [String: String] = [:]
     private var ocIdEtag: [String: String] = [:]
-    public var metadatas: [tableMetadata] = []
-    public var livePhoto: Bool = false
+    private var metadatas: [tableMetadata]?
+
+    let showBothPredicateMediaString = "account == %@ AND serverUrl BEGINSWITH %@ AND (classFile == %@ OR classFile == %@) AND NOT (session CONTAINS[c] 'upload') AND NOT (livePhotoFile != '' AND classFile == %@)"
+    let showOnlyPredicateMediaString = "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload') AND NOT (livePhotoFile != '' AND classFile == %@)"
+    var isMediaMetadatasInProcess: Bool = false
 
 
     override private init() {}
     override private init() {}
 
 
@@ -58,10 +61,9 @@ import NextcloudKit
         self.account = account
         self.account = account
 
 
         ocIdEtag.removeAll()
         ocIdEtag.removeAll()
-        metadatas.removeAll()
-        getMediaMetadatas(account: account)
-
-        guard !metadatas.isEmpty else { return }
+        self.metadatas = []
+        self.metadatas = getMediaMetadatas(account: account)
+        guard let metadatas = self.metadatas, !metadatas.isEmpty else { return }
         let ext = ".preview.ico"
         let ext = ".preview.ico"
         let manager = FileManager.default
         let manager = FileManager.default
         let resourceKeys = Set<URLResourceKey>([.nameKey, .pathKey, .fileSizeKey, .creationDateKey])
         let resourceKeys = Set<URLResourceKey>([.nameKey, .pathKey, .fileSizeKey, .creationDateKey])
@@ -117,6 +119,12 @@ import NextcloudKit
         NextcloudKit.shared.nkCommonInstance.writeLog("--------- ThumbnailLRUCache image process ---------")
         NextcloudKit.shared.nkCommonInstance.writeLog("--------- ThumbnailLRUCache image process ---------")
     }
     }
 
 
+    func initialMetadatas() -> [tableMetadata]? {
+        let metadatas = self.metadatas
+        self.metadatas = nil
+        return metadatas
+    }
+
     func getMediaImage(ocId: String) -> ImageType? {
     func getMediaImage(ocId: String) -> ImageType? {
         return cache.value(forKey: ocId)
         return cache.value(forKey: ocId)
     }
     }
@@ -127,35 +135,26 @@ import NextcloudKit
 
 
     @objc func clearMediaCache() {
     @objc func clearMediaCache() {
 
 
-        ocIdEtag.removeAll()
-        metadatas.removeAll()
+        self.ocIdEtag.removeAll()
+        self.metadatas?.removeAll()
+        self.metadatas = nil
         cache.removeAllValues()
         cache.removeAllValues()
     }
     }
 
 
-    func getMediaMetadatas(account: String, predicate: NSPredicate? = nil) {
+    func getMediaMetadatas(account: String, predicate: NSPredicate? = nil) -> [tableMetadata] {
 
 
-        guard let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) else { return }
-        let startServerUrl = NCUtilityFileSystem().getHomeServer(urlBase: account.urlBase, userId: account.userId) + account.mediaPath
+        defer {
+            self.isMediaMetadatasInProcess = false
+            NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterFinishedMediaInProcess)
+        }
+        self.isMediaMetadatasInProcess = true
 
 
-        let predicateDefault = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND (classFile == %@ OR classFile == %@) AND NOT (session CONTAINS[c] 'upload')", account.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue, NKCommon.TypeClassFile.video.rawValue)
+        guard let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) else { return [] }
+        let startServerUrl = NCUtilityFileSystem().getHomeServer(urlBase: account.urlBase, userId: account.userId) + account.mediaPath
 
 
-        livePhoto = NCKeychain().livePhoto
+        let predicateDefault = NSPredicate(format: showBothPredicateMediaString, account.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue, NKCommon.TypeClassFile.video.rawValue, NKCommon.TypeClassFile.video.rawValue)
 
 
-        let newMetadatas = NCManageDatabase.shared.getMetadatasMedia(predicate: predicate ?? predicateDefault, livePhoto: livePhoto)
-        if metadatas != newMetadatas {
-            metadatas = newMetadatas
-        }
-
-        switch NCKeychain().mediaSortDate {
-        case "date":
-            metadatas = self.metadatas.sorted(by: {($0.date as Date) > ($1.date as Date)})
-        case "creationDate":
-            metadatas = self.metadatas.sorted(by: {($0.creationDate as Date) > ($1.creationDate as Date)})
-        case "uploadDate":
-            metadatas = self.metadatas.sorted(by: {($0.uploadDate as Date) > ($1.uploadDate as Date)})
-        default:
-            break
-        }
+        return NCManageDatabase.shared.getMetadatasMedia(predicate: predicate ?? predicateDefault)
     }
     }
 
 
     // MARK: -
     // MARK: -

+ 7 - 1
iOSClient/Networking/E2EE/NCNetworkingE2EECreateFolder.swift

@@ -34,9 +34,15 @@ class NCNetworkingE2EECreateFolder: NSObject {
 
 
     func createFolder(fileName: String, serverUrl: String, account: String, urlBase: String, userId: String, withPush: Bool) async -> NKError {
     func createFolder(fileName: String, serverUrl: String, account: String, urlBase: String, userId: String, withPush: Bool) async -> NKError {
 
 
+        var fileNameFolder = utility.removeForbiddenCharacters(fileName)
+        if fileName != fileNameFolder {
+            let errorDescription = String(format: NSLocalizedString("_forbidden_characters_", comment: ""), NCGlobal.shared.forbiddenCharacters.joined(separator: " "))
+            let error = NKError(errorCode: NCGlobal.shared.errorConflict, errorDescription: errorDescription)
+            return error
+        }
         let fileNameIdentifier = networkingE2EE.generateRandomIdentifier()
         let fileNameIdentifier = networkingE2EE.generateRandomIdentifier()
         let serverUrlFileName = serverUrl + "/" + fileNameIdentifier
         let serverUrlFileName = serverUrl + "/" + fileNameIdentifier
-        let fileNameFolder = utilityFileSystem.createFileName(utility.removeForbiddenCharacters(fileName), serverUrl: serverUrl, account: account)
+        fileNameFolder = utilityFileSystem.createFileName(fileNameFolder, serverUrl: serverUrl, account: account)
         if fileNameFolder.isEmpty {
         if fileNameFolder.isEmpty {
             return NKError(errorCode: NCGlobal.shared.errorUnexpectedResponseFromDB, errorDescription: NSLocalizedString("_e2e_error_", comment: ""))
             return NKError(errorCode: NCGlobal.shared.errorUnexpectedResponseFromDB, errorDescription: NSLocalizedString("_e2e_error_", comment: ""))
         }
         }

+ 6 - 3
iOSClient/Networking/NCAutoUpload.swift

@@ -103,7 +103,7 @@ class NCAutoUpload: NSObject {
 
 
             for asset in assets {
             for asset in assets {
 
 
-                var livePhoto = false
+                var isLivePhoto = false
                 var session: String = ""
                 var session: String = ""
                 let dateFormatter = DateFormatter()
                 let dateFormatter = DateFormatter()
                 let assetDate = asset.creationDate ?? Date()
                 let assetDate = asset.creationDate ?? Date()
@@ -118,7 +118,7 @@ class NCAutoUpload: NSObject {
                 let fileName = CCUtility.createFileName(asset.originalFilename as String, fileDate: assetDate, fileType: assetMediaType, keyFileName: NCGlobal.shared.keyFileNameAutoUploadMask, keyFileNameType: NCGlobal.shared.keyFileNameAutoUploadType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginalAutoUpload, forcedNewFileName: false)!
                 let fileName = CCUtility.createFileName(asset.originalFilename as String, fileDate: assetDate, fileType: assetMediaType, keyFileName: NCGlobal.shared.keyFileNameAutoUploadMask, keyFileNameType: NCGlobal.shared.keyFileNameAutoUploadType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginalAutoUpload, forcedNewFileName: false)!
 
 
                 if asset.mediaSubtypes.contains(.photoLive), NCKeychain().livePhoto {
                 if asset.mediaSubtypes.contains(.photoLive), NCKeychain().livePhoto {
-                    livePhoto = true
+                    isLivePhoto = true
                 }
                 }
 
 
                 if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
                 if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
@@ -160,7 +160,10 @@ class NCAutoUpload: NSObject {
                         NCManageDatabase.shared.addPhotoLibrary([asset], account: account.account)
                         NCManageDatabase.shared.addPhotoLibrary([asset], account: account.account)
                     }
                     }
                 } else {
                 } else {
-                    let metadata = NCManageDatabase.shared.createMetadata(account: account.account, user: account.user, userId: account.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: account.urlBase, url: "", contentType: "", isLivePhoto: livePhoto)
+                    let metadata = NCManageDatabase.shared.createMetadata(account: account.account, user: account.user, userId: account.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: account.urlBase, url: "", contentType: "")
+                    if isLivePhoto {
+                        metadata.livePhotoFile = (metadata.fileName as NSString).deletingPathExtension + ".mov"
+                    }
                     metadata.assetLocalIdentifier = asset.localIdentifier
                     metadata.assetLocalIdentifier = asset.localIdentifier
                     metadata.session = session
                     metadata.session = session
                     metadata.sessionSelector = selector
                     metadata.sessionSelector = selector

+ 85 - 10
iOSClient/Networking/NCNetworking.swift

@@ -691,7 +691,7 @@ class NCNetworking: NSObject, NKCommonDelegate {
                 utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp))
                 utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp))
             }
             }
 
 
-            NCLivePhoto().setLivephotoUpload(metadata: metadata)
+            uploadLivePhoto(metadata: metadata)
 
 
             NextcloudKit.shared.nkCommonInstance.writeLog("[SUCCESS] Upload complete " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
             NextcloudKit.shared.nkCommonInstance.writeLog("[SUCCESS] Upload complete " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": error])
             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "error": error])
@@ -790,6 +790,52 @@ class NCNetworking: NSObject, NKCommonDelegate {
         })
         })
     }
     }
 
 
+    // MARK: - Live Photo
+
+    func uploadLivePhoto(metadata: tableMetadata) {
+
+        guard NCGlobal.shared.isLivePhotoServerAvailable,
+              metadata.isLivePhoto,
+              let metadata1 = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND urlBase == %@ AND path == %@ AND fileName == %@ AND status == %d", metadata.account, metadata.urlBase, metadata.path, metadata.livePhotoFile, NCGlobal.shared.metadataStatusNormal)) else {
+            return
+        }
+
+        Task {
+            let serverUrlfileNamePath = metadata.urlBase + metadata.path + metadata.livePhotoFile
+            var results = await NextcloudKit.shared.setLivephoto(serverUrlfileNamePath: serverUrlfileNamePath, livePhotoFile: metadata1.livePhotoFile)
+            if results.error == .success {
+                NCManageDatabase.shared.setMetadataLivePhotoByServer(account: metadata.account, ocId: metadata.ocId)
+            }
+
+            let serverUrlfileNamePath1 = metadata1.urlBase + metadata1.path + metadata1.livePhotoFile
+            results = await NextcloudKit.shared.setLivephoto(serverUrlfileNamePath: serverUrlfileNamePath1, livePhotoFile: metadata.livePhotoFile)
+            if results.error == .success {
+                NCManageDatabase.shared.setMetadataLivePhotoByServer(account: metadata1.account, ocId: metadata1.ocId)
+            }
+        }
+    }
+
+    func convertLivePhoto() {
+
+        guard NCGlobal.shared.isLivePhotoServerAvailable else { return }
+
+        if let results = NCManageDatabase.shared.getResultsMetadatas(predicate: NSPredicate(format: "isFlaggedAsLivePhotoByServer == false AND livePhotoFile != ''")) {
+            var index: Int = 0
+            for result in results {
+                index += 1
+                let serverUrlfileNamePath = result.urlBase + result.path + result.fileName
+                NextcloudKit.shared.setLivephoto(serverUrlfileNamePath: serverUrlfileNamePath, livePhotoFile: result.livePhotoFile) { _, error in
+                    if error == .success {
+                        NCManageDatabase.shared.setMetadataLivePhotoByServer(account: result.account, ocId: result.ocId)
+                    }
+                    print("Convert LivePhoto with error \(error.errorCode)")
+                }
+                if index >= 20 { break }
+            }
+        }
+
+    }
+
     // MARK: - Cancel (Download Upload)
     // MARK: - Cancel (Download Upload)
 
 
     // sessionIdentifierDownload: String = "com.nextcloud.nextcloudkit.session.download"
     // sessionIdentifierDownload: String = "com.nextcloud.nextcloudkit.session.download"
@@ -1042,7 +1088,7 @@ class NCNetworking: NSObject, NKCommonDelegate {
                             let serverUrl = metadata.serverUrl + "/" + metadata.fileName
                             let serverUrl = metadata.serverUrl + "/" + metadata.fileName
                             NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: metadata.etag, permissions: metadata.permissions, serverUrl: serverUrl, account: metadata.account)
                             NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: metadata.etag, permissions: metadata.permissions, serverUrl: serverUrl, account: metadata.account)
                         } else if selector == NCGlobal.shared.selectorSynchronizationOffline,
                         } else if selector == NCGlobal.shared.selectorSynchronizationOffline,
-                                  NCManageDatabase.shared.isDownloadMetadata(metadata, download: true),
+                                  self.synchronizeMetadata(metadata),
                                   let appDelegate = (UIApplication.shared.delegate as? AppDelegate),
                                   let appDelegate = (UIApplication.shared.delegate as? AppDelegate),
                                   appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty {
                                   appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty {
                             appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: selector))
                             appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: selector))
@@ -1054,6 +1100,15 @@ class NCNetworking: NSObject, NKCommonDelegate {
 #endif
 #endif
     }
     }
 
 
+    func synchronizeMetadata(_ metadata: tableMetadata) -> Bool {
+
+        let localFile = NCManageDatabase.shared.getResultsTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))?.first
+        if localFile?.etag != metadata.etag || utilityFileSystem.fileProviderStorageSize(metadata.ocId, fileNameView: metadata.fileNameView) == 0 {
+            return true
+        }
+        return false
+    }
+
     // MARK: - Search
     // MARK: - Search
 
 
     /// WebDAV search
     /// WebDAV search
@@ -1253,6 +1308,11 @@ class NCNetworking: NSObject, NKCommonDelegate {
     private func createFolderPlain(fileName: String, serverUrl: String, account: String, urlBase: String, overwrite: Bool, withPush: Bool, completion: @escaping (_ error: NKError) -> Void) {
     private func createFolderPlain(fileName: String, serverUrl: String, account: String, urlBase: String, overwrite: Bool, withPush: Bool, completion: @escaping (_ error: NKError) -> Void) {
 
 
         var fileNameFolder = utility.removeForbiddenCharacters(fileName)
         var fileNameFolder = utility.removeForbiddenCharacters(fileName)
+        if fileName != fileNameFolder {
+            let errorDescription = String(format: NSLocalizedString("_forbidden_characters_", comment: ""), NCGlobal.shared.forbiddenCharacters.joined(separator: " "))
+            let error = NKError(errorCode: NCGlobal.shared.errorConflict, errorDescription: errorDescription)
+            return completion(error)
+        }
 
 
         if !overwrite {
         if !overwrite {
             fileNameFolder = utilityFileSystem.createFileName(fileNameFolder, serverUrl: serverUrl, account: account)
             fileNameFolder = utilityFileSystem.createFileName(fileNameFolder, serverUrl: serverUrl, account: account)
@@ -1371,23 +1431,22 @@ class NCNetworking: NSObject, NKCommonDelegate {
 
 
             for metadata in metadatas {
             for metadata in metadatas {
 
 
+                let metadataLive = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata)
                 NCManageDatabase.shared.deleteVideo(metadata: metadata)
                 NCManageDatabase.shared.deleteVideo(metadata: metadata)
                 NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
                 NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
                 utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
                 utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
 
 
-                if let metadataLivePhoto = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) {
-                    NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadataLivePhoto.ocId))
-                    utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadataLivePhoto.ocId))
+                if let metadataLive {
+                    NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadataLive.ocId))
+                    utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadataLive.ocId))
                 }
                 }
             }
             }
             return NKError()
             return NKError()
         }
         }
 
 
-        let metadataLive = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata)
-
         if metadata.isDirectoryE2EE {
         if metadata.isDirectoryE2EE {
 #if !EXTENSION
 #if !EXTENSION
-            if let metadataLive = metadataLive {
+            if let metadataLive = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) {
                 let error = await NCNetworkingE2EEDelete().delete(metadata: metadataLive)
                 let error = await NCNetworkingE2EEDelete().delete(metadata: metadataLive)
                 if error == .success {
                 if error == .success {
                     return await NCNetworkingE2EEDelete().delete(metadata: metadata)
                     return await NCNetworkingE2EEDelete().delete(metadata: metadata)
@@ -1401,7 +1460,7 @@ class NCNetworking: NSObject, NKCommonDelegate {
             return NKError()
             return NKError()
 #endif
 #endif
         } else {
         } else {
-            if let metadataLive = metadataLive {
+            if let metadataLive = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) {
                 let error = await deleteMetadataPlain(metadataLive)
                 let error = await deleteMetadataPlain(metadataLive)
                 if error == .success {
                 if error == .success {
                     return await deleteMetadataPlain(metadata)
                     return await deleteMetadataPlain(metadata)
@@ -1437,6 +1496,16 @@ class NCNetworking: NSObject, NKCommonDelegate {
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
             NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
             NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
             NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
 
 
+            if let metadataLive = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) {
+                do {
+                    try FileManager.default.removeItem(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(metadataLive.ocId))
+                } catch { }
+
+                NCManageDatabase.shared.deleteVideo(metadata: metadataLive)
+                NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadataLive.ocId))
+                NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadataLive.ocId))
+            }
+
             if metadata.directory {
             if metadata.directory {
                 NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: utilityFileSystem.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName), account: metadata.account)
                 NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: utilityFileSystem.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName), account: metadata.account)
             }
             }
@@ -1545,7 +1614,13 @@ class NCNetworking: NSObject, NKCommonDelegate {
         if !metadata.permissions.isEmpty && !permission {
         if !metadata.permissions.isEmpty && !permission {
             return completion(NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_no_permission_modify_file_"))
             return completion(NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_no_permission_modify_file_"))
         }
         }
-        let fileNameNew = utility.removeForbiddenCharacters(fileNameNew)
+        let fileName = utility.removeForbiddenCharacters(fileNameNew)
+        if fileName != fileNameNew {
+            let errorDescription = String(format: NSLocalizedString("_forbidden_characters_", comment: ""), NCGlobal.shared.forbiddenCharacters.joined(separator: " "))
+            let error = NKError(errorCode: NCGlobal.shared.errorConflict, errorDescription: errorDescription)
+            return completion(error)
+        }
+        let fileNameNew = fileName
         if fileNameNew.isEmpty || fileNameNew == metadata.fileNameView {
         if fileNameNew.isEmpty || fileNameNew == metadata.fileNameView {
             return completion(NKError())
             return completion(NKError())
         }
         }

+ 5 - 4
iOSClient/Networking/NCNetworkingProcessUpload.swift

@@ -34,6 +34,8 @@ class NCNetworkingProcessUpload: NSObject {
     }()
     }()
 
 
     private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
     private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
+    private lazy var rootViewController = appDelegate.window?.rootViewController
+    private lazy var hudView = rootViewController?.view
     private var notificationToken: NotificationToken?
     private var notificationToken: NotificationToken?
     private var timerProcess: Timer?
     private var timerProcess: Timer?
     private var pauseProcess: Bool = false
     private var pauseProcess: Bool = false
@@ -100,7 +102,6 @@ class NCNetworkingProcessUpload: NSObject {
         let applicationState = UIApplication.shared.applicationState
         let applicationState = UIApplication.shared.applicationState
         let queue = DispatchQueue.global()
         let queue = DispatchQueue.global()
         var maxConcurrentOperationUpload = NCBrandOptions.shared.maxConcurrentOperationUpload
         var maxConcurrentOperationUpload = NCBrandOptions.shared.maxConcurrentOperationUpload
-        let viewController = appDelegate.window?.rootViewController
         let hud = JGProgressHUD()
         let hud = JGProgressHUD()
 
 
         queue.async {
         queue.async {
@@ -155,7 +156,7 @@ class NCNetworkingProcessUpload: NSObject {
 
 
                         let semaphore = DispatchSemaphore(value: 0)
                         let semaphore = DispatchSemaphore(value: 0)
                         let cameraRoll = NCCameraRoll()
                         let cameraRoll = NCCameraRoll()
-                        cameraRoll.extractCameraRoll(from: metadata, viewController: viewController, hud: hud) { metadatas in
+                        cameraRoll.extractCameraRoll(from: metadata, viewController: self.rootViewController, hud: hud) { metadatas in
                             if metadatas.isEmpty {
                             if metadatas.isEmpty {
                                 NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
                                 NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
                             }
                             }
@@ -174,7 +175,7 @@ class NCNetworkingProcessUpload: NSObject {
                                 }
                                 }
 
 
                                 if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
                                 if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
-                                    NCNetworking.shared.upload(metadata: metadata, hudView: self.appDelegate.window?.rootViewController?.view)
+                                    NCNetworking.shared.upload(metadata: metadata, hudView: self.hudView)
                                     if isInDirectoryE2EE || metadata.chunk > 0 {
                                     if isInDirectoryE2EE || metadata.chunk > 0 {
                                         maxConcurrentOperationUpload = 1
                                         maxConcurrentOperationUpload = 1
                                     }
                                     }
@@ -224,7 +225,7 @@ class NCNetworkingProcessUpload: NSObject {
 
 
         DispatchQueue.main.async {
         DispatchQueue.main.async {
 
 
-            guard !self.appDelegate.isPasscodePresented() else {
+            guard !self.appDelegate.isPasscodePresented else {
                 return completition()
                 return completition()
             }
             }
 
 

+ 1 - 1
iOSClient/Networking/NCService.swift

@@ -301,7 +301,7 @@ class NCService: NSObject {
         let files = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", account), sorted: "fileName", ascending: true)
         let files = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", account), sorted: "fileName", ascending: true)
         for file: tableLocalFile in files {
         for file: tableLocalFile in files {
             guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(file.ocId) else { continue }
             guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(file.ocId) else { continue }
-            if NCManageDatabase.shared.isDownloadMetadata(metadata, download: true),
+            if NCNetworking.shared.synchronizeMetadata(metadata),
                appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty {
                appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty {
                 appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile))
                 appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile))
             }
             }

+ 0 - 1
iOSClient/Offline/NCOffline.swift

@@ -76,7 +76,6 @@ class NCOffline: NCCollectionViewCommon {
             ascending: self.layoutForView?.ascending,
             ascending: self.layoutForView?.ascending,
             directoryOnTop: self.layoutForView?.directoryOnTop,
             directoryOnTop: self.layoutForView?.directoryOnTop,
             favoriteOnTop: true,
             favoriteOnTop: true,
-            filterLivePhoto: true,
             groupByField: self.groupByField,
             groupByField: self.groupByField,
             providers: self.providers,
             providers: self.providers,
             searchResults: self.searchResults)
             searchResults: self.searchResults)

+ 1 - 2
iOSClient/Select/NCSelect.swift

@@ -415,7 +415,7 @@ extension NCSelect: UICollectionViewDataSource {
         cell.selectMode(false)
         cell.selectMode(false)
 
 
         // Live Photo
         // Live Photo
-        if metadata.livePhoto {
+        if metadata.isLivePhoto {
             cell.imageStatus.image = NCImageCache.images.livePhoto
             cell.imageStatus.image = NCImageCache.images.livePhoto
         }
         }
 
 
@@ -545,7 +545,6 @@ extension NCSelect {
                                        ascending: true,
                                        ascending: true,
                                        directoryOnTop: true,
                                        directoryOnTop: true,
                                        favoriteOnTop: true,
                                        favoriteOnTop: true,
-                                       filterLivePhoto: true,
                                        groupByField: "none")
                                        groupByField: "none")
 
 
         if withLoadFolder {
         if withLoadFolder {

+ 0 - 13
iOSClient/Settings/NCKeychain.swift

@@ -291,19 +291,6 @@ import KeychainAccess
         }
         }
     }
     }
 
 
-    var mediaSortDate: String {
-        get {
-            migrate(key: "mediaSortDate")
-            if let value = try? keychain.get("mediaSortDate") {
-                return value
-            }
-            return "date"
-        }
-        set {
-            keychain["mediaSortDate"] = newValue
-        }
-    }
-
     var textRecognitionStatus: Bool {
     var textRecognitionStatus: Bool {
         get {
         get {
             migrate(key: "textRecognitionStatus")
             migrate(key: "textRecognitionStatus")

+ 3 - 2
iOSClient/Settings/NCManageAutoUploadFileName.swift

@@ -144,7 +144,7 @@ class NCManageAutoUploadFileName: XLFormViewController {
         super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue)
         super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue)
 
 
         if formRow.tag == "addFileNameType" {
         if formRow.tag == "addFileNameType" {
-            NCKeychain().setFileNameType(key: NCGlobal.shared.keyFileNameAutoUploadType, prefix: (formRow.value! as AnyObject).boolValue) 
+            NCKeychain().setFileNameType(key: NCGlobal.shared.keyFileNameAutoUploadType, prefix: (formRow.value! as AnyObject).boolValue)
             self.reloadForm()
             self.reloadForm()
         } else if formRow.tag == "maintainOriginalFileName" {
         } else if formRow.tag == "maintainOriginalFileName" {
             NCKeychain().setOriginalFileName(key: NCGlobal.shared.keyFileNameOriginalAutoUpload, value: (formRow.value! as AnyObject).boolValue)
             NCKeychain().setOriginalFileName(key: NCGlobal.shared.keyFileNameOriginalAutoUpload, value: (formRow.value! as AnyObject).boolValue)
@@ -171,7 +171,8 @@ class NCManageAutoUploadFileName: XLFormViewController {
 
 
                     self.reloadFormRow(formRow)
                     self.reloadFormRow(formRow)
 
 
-                    let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_forbidden_characters_")
+                    let errorDescription = String(format: NSLocalizedString("_forbidden_characters_", comment: ""), NCGlobal.shared.forbiddenCharacters.joined(separator: " "))
+                    let error = NKError(errorCode: NCGlobal.shared.errorConflict, errorDescription: errorDescription)
                     NCContentPresenter().showInfo(error: error)
                     NCContentPresenter().showInfo(error: error)
                 }
                 }
             }
             }

+ 2 - 2
iOSClient/Settings/NCSettings.m

@@ -472,9 +472,9 @@
     NSInteger numSections = [tableView numberOfSections] - 1;
     NSInteger numSections = [tableView numberOfSections] - 1;
 
 
     if (section == 1) {
     if (section == 1) {
-        NSString *reset = [NSString stringWithFormat:NSLocalizedString(@"_reset_wrong_passcode_desc_", nil), NCBrandOptions.shared.resetAppPasscodeAttempts];
         NSString *lock = NSLocalizedString(@"_lock_protection_no_screen_footer_", nil);
         NSString *lock = NSLocalizedString(@"_lock_protection_no_screen_footer_", nil);
-        sectionName = [NSString stringWithFormat:@"%@\n%@", reset, lock];
+        NSString *reset = [NSString stringWithFormat:NSLocalizedString(@"_reset_wrong_passcode_desc_", nil), NCBrandOptions.shared.resetAppPasscodeAttempts];
+        sectionName = [NSString stringWithFormat:@"%@\n%@", lock, reset];
     } else if (section == 2 && !NCBrandOptions.shared.disable_mobileconfig) {
     } else if (section == 2 && !NCBrandOptions.shared.disable_mobileconfig) {
         sectionName = NSLocalizedString(@"_calendar_contacts_footer_", nil);
         sectionName = NSLocalizedString(@"_calendar_contacts_footer_", nil);
     } else if (section == numSections) {
     } else if (section == numSections) {

+ 0 - 1
iOSClient/Shares/NCShares.swift

@@ -60,7 +60,6 @@ class NCShares: NCCollectionViewCommon {
                                            ascending: layoutForView?.ascending,
                                            ascending: layoutForView?.ascending,
                                            directoryOnTop: layoutForView?.directoryOnTop,
                                            directoryOnTop: layoutForView?.directoryOnTop,
                                            favoriteOnTop: true,
                                            favoriteOnTop: true,
-                                           filterLivePhoto: true,
                                            groupByField: groupByField,
                                            groupByField: groupByField,
                                            providers: providers,
                                            providers: providers,
                                            searchResults: searchResults)
                                            searchResults: searchResults)

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


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


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


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


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


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


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


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


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


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


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


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


BIN
iOSClient/Supporting Files/cy_GB.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 - 5
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -477,7 +477,7 @@
 "_connection_internet_offline_" = "The internet connection appears to be offline or Wi-Fi is required";
 "_connection_internet_offline_" = "The internet connection appears to be offline or Wi-Fi is required";
 "_insert_password_"             = "Enter password";
 "_insert_password_"             = "Enter password";
 "_update_in_progress_"          = "Version upgrade, please wait …";
 "_update_in_progress_"          = "Version upgrade, please wait …";
-"_forbidden_characters_"        = "The file or folder name contains invalid characters";
+"_forbidden_characters_"        = "Forbidden characters: %@";
 "_cannot_send_mail_error_"      = "No account set up, or wrong email address entered";
 "_cannot_send_mail_error_"      = "No account set up, or wrong email address entered";
 "_open_url_error_"              = "Cannot open the URL for this action";
 "_open_url_error_"              = "Cannot open the URL for this action";
 "_photo_camera_"                = "Photos";
 "_photo_camera_"                = "Photos";
@@ -686,7 +686,6 @@
 "_filename_"                        = "Filename";
 "_filename_"                        = "Filename";
 "_enter_filename_"                  = "Enter filename …";
 "_enter_filename_"                  = "Enter filename …";
 "_preview_filename_"                = "Example preview of filename. You can use the mask %@ for date/time";
 "_preview_filename_"                = "Example preview of filename. You can use the mask %@ for date/time";
-"_forbidden_characters_"            = "Invalid character in filename";
 "_add_filenametype_"                = "Specify type in filename";
 "_add_filenametype_"                = "Specify type in filename";
 "_filenametype_photo_video_"        = "Photo/Video";
 "_filenametype_photo_video_"        = "Photo/Video";
 "_maintain_original_filename_"      = "Maintain original filename";
 "_maintain_original_filename_"      = "Maintain original filename";
@@ -943,13 +942,13 @@
 "_chunk_enough_memory_"     = "It seems there is not enough space to send the file";
 "_chunk_enough_memory_"     = "It seems there is not enough space to send the file";
 "_chunk_create_folder_"     = "The file could not be sent, please check the server log";
 "_chunk_create_folder_"     = "The file could not be sent, please check the server log";
 "_chunk_files_null_"        = "The file for sending could not be created";
 "_chunk_files_null_"        = "The file for sending could not be created";
-"_chunk_file_null_"         = "The file could not be sended";
+"_chunk_file_null_"         = "The file could not be sent";
 "_chunk_move_"              = "The sent file could not be reassembled, please check the server log";
 "_chunk_move_"              = "The sent file could not be reassembled, please check the server log";
 "_download_image_"          = "Download image";
 "_download_image_"          = "Download image";
 "_download_video_"          = "Download video";
 "_download_video_"          = "Download video";
 "_reset_wrong_passcode_"    = "Reset application";
 "_reset_wrong_passcode_"    = "Reset application";
-"_reset_wrong_passcode_desc_" = "Use \"Reset application\" for remove all accounts and local data after %d failed code entry attempts.";
-"_deviceOwnerAuthentication_" = "Biometric sensor has been locked out due to few fail attemps. Enter device passcode to enable sensor.";
+"_reset_wrong_passcode_desc_" = "Use \"Reset application\" to remove all accounts and local data after %d failed code entry attempts.";
+"_deviceOwnerAuthentication_" = "The biometric sensor has been temporarily disabled due to multiple failed attempts. Enter the device passcode to re-enable the sensor.";
 
 
 // Video
 // Video
 "_select_trace_"            = "Select the trace";
 "_select_trace_"            = "Select the trace";

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


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/et_EE.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/fo.lproj/Localizable.strings


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


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


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


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


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


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


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


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


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


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


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


BIN
iOSClient/Supporting Files/ig.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/ka.lproj/Localizable.strings


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


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


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


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


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


Some files were not shown because too many files changed in this diff