Browse Source

Merge pull request #2307 from nextcloud/UploadScanDocument

Upload scan document
Marino Faggiana 2 years ago
parent
commit
9d70e6e39d
31 changed files with 979 additions and 1066 deletions
  1. 3 1
      .swiftlint.yml
  2. 96 90
      Nextcloud.xcodeproj/project.pbxproj
  3. 3 3
      iOSClient/AppDelegate.swift
  4. 0 37
      iOSClient/Brand/NCBrandSettings.swift
  5. 2 1
      iOSClient/Extensions/Array+Extension.swift
  6. 1 1
      iOSClient/Extensions/NSMutableAttributedString+Extension.swift
  7. 1 1
      iOSClient/Extensions/String+Extension.swift
  8. 1 1
      iOSClient/Extensions/UIApplication+Extension.swift
  9. 1 1
      iOSClient/Extensions/UIColor+Extension.swift
  10. 1 1
      iOSClient/Extensions/UIControl+Extension.swift
  11. 2 1
      iOSClient/Extensions/UIDevice+Extension.swift
  12. 1 1
      iOSClient/Extensions/UIFont+Extension.swift
  13. 3 2
      iOSClient/Extensions/UIImage+Extension.swift
  14. 1 1
      iOSClient/Extensions/UIView+Extension.swift
  15. 16 0
      iOSClient/Extensions/View+Extension.swift
  16. 1 1
      iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
  17. 0 779
      iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift
  18. 0 108
      iOSClient/Main/Create cloud/NCUploadScanDocument.swift
  19. 1 1
      iOSClient/Menu/AppDelegate+Menu.swift
  20. 2 0
      iOSClient/NCGlobal.swift
  21. 65 0
      iOSClient/Scan document/NCDocumentCamera.swift
  22. 0 0
      iOSClient/Scan document/NCScan+CollectionView.swift
  23. 3 3
      iOSClient/Scan document/NCScan.storyboard
  24. 9 3
      iOSClient/Scan document/NCScan.swift
  25. 0 0
      iOSClient/Scan document/NCScanCell.swift
  26. 623 0
      iOSClient/Scan document/NCUploadScanDocument.swift
  27. 0 12
      iOSClient/Settings/NCManageE2EE.swift
  28. 5 1
      iOSClient/Supporting Files/en.lproj/Localizable.strings
  29. 8 4
      iOSClient/Utility/CCUtility.h
  30. 34 12
      iOSClient/Utility/CCUtility.m
  31. 96 0
      iOSClient/Utility/HUDView.swift

+ 3 - 1
.swiftlint.yml

@@ -35,7 +35,9 @@ disabled_rules:
   - unused_setter_value
   - large_tuple
   - function_parameter_count
-
+  - multiple_closures_with_trailing_closure
+  - for_where
+  
 excluded:
   - Carthage
   - Pods

+ 96 - 90
Nextcloud.xcodeproj/project.pbxproj

@@ -73,8 +73,8 @@
 		AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.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 */; };
-		AFD33240276A02C100F5AE02 /* UIApplication+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD3323F276A02C000F5AE02 /* UIApplication+Extensions.swift */; };
-		D575039F27146F93008DC9DC /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
+		AFD33240276A02C100F5AE02 /* UIApplication+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD3323F276A02C000F5AE02 /* UIApplication+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 */; };
 		F700222C1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700222D1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
@@ -111,7 +111,7 @@
 		F70BFC7420E0FA7D00C67599 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
 		F70BFC7520E0FA7D00C67599 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
 		F70CAE3A1F8CF31A008125FD /* NCEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */; };
-		F70CEF5623E9C7E50007035B /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
+		F70CEF5623E9C7E50007035B /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
 		F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */; };
 		F70D87CF25EE6E58008CBBBD /* NCRenameFile.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F70D87CD25EE6E58008CBBBD /* NCRenameFile.storyboard */; };
 		F70D87D025EE6E58008CBBBD /* NCRenameFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70D87CE25EE6E58008CBBBD /* NCRenameFile.swift */; };
@@ -130,6 +130,7 @@
 		F711D63128F44801003F43C8 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9739428F17131002C43E2 /* IntentHandler.swift */; };
 		F7134186259747BA00768D21 /* NCPushNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = F7134185259747BA00768D21 /* NCPushNotification.m */; };
 		F713FF002472764100214AF6 /* UIImage+animatedGIF.m in Sources */ = {isa = PBXBuildFile; fileRef = F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */; };
+		F7145610296433C80038D028 /* NCDocumentCamera.swift in Sources */ = {isa = PBXBuildFile; fileRef = F714560F296433C80038D028 /* NCDocumentCamera.swift */; };
 		F71459D21D12E3B700CAFEEC /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
 		F7145A231D12E3B700CAFEEC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F7E70DE91A24DE4100E1B66A /* Localizable.strings */; };
 		F714803B262EBE3900693E51 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F714803A262EBE3900693E51 /* MainInterface.storyboard */; };
@@ -147,7 +148,6 @@
 		F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F719D9E1288D396100762E33 /* NCColorPicker.swift */; };
 		F71CD6CA2930D7B1006C95C1 /* NCApplicationHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71CD6C92930D7B1006C95C1 /* NCApplicationHandle.swift */; };
 		F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7226EDB1EE4089300EBECB1 /* Main.storyboard */; };
-		F7237DD1295463E700A9D8B7 /* NCBrandSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7237DD0295463E700A9D8B7 /* NCBrandSettings.swift */; };
 		F723985C253C95CE00257F49 /* NCViewerRichdocument.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */; };
 		F7239871253D86B600257F49 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7239870253D86B600257F49 /* NCEmptyDataSet.swift */; };
 		F7239877253D86D300257F49 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7239876253D86D300257F49 /* NCEmptyView.xib */; };
@@ -241,6 +241,8 @@
 		F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75AC2421F1F62450073EC19 /* NCManageAutoUploadFileName.swift */; };
 		F75B0ABD244C4DBB00E58DCA /* NCFunctionCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75B0ABC244C4DBB00E58DCA /* NCFunctionCenter.swift */; };
 		F75C0C4823D1FAE300163CC8 /* NCRichWorkspaceCommon.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75C0C4723D1FAE300163CC8 /* NCRichWorkspaceCommon.swift */; };
+		F75CA1472962F13700B01130 /* HUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75CA1462962F13700B01130 /* HUDView.swift */; };
+		F75CA1482962F13700B01130 /* HUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75CA1462962F13700B01130 /* HUDView.swift */; };
 		F75D19E325EFE09000D74598 /* NCTrash+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75D19E225EFE09000D74598 /* NCTrash+Menu.swift */; };
 		F75DD765290ABB25002EB562 /* Intent.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F75DD769290ABB25002EB562 /* Intent.intentdefinition */; };
 		F75DD766290ABB25002EB562 /* Intent.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = F75DD769290ABB25002EB562 /* Intent.intentdefinition */; };
@@ -256,7 +258,6 @@
 		F7651A8B23A2A3F2001403D2 /* NCCreateFormUploadDocuments.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7651A8923A2A3F2001403D2 /* NCCreateFormUploadDocuments.swift */; };
 		F765608F23BF813600765969 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; };
 		F765E9CD295C585800A09ED8 /* NCUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765E9CC295C585800A09ED8 /* NCUploadScanDocument.swift */; };
-		F765E9CF295C684F00A09ED8 /* Reasons to use Nextcloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = F765E9CE295C684F00A09ED8 /* Reasons to use Nextcloud.pdf */; };
 		F765F73125237E3F00391DBE /* NCRecent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765F72F25237E3F00391DBE /* NCRecent.swift */; };
 		F765F73225237E3F00391DBE /* NCRecent.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F765F73025237E3F00391DBE /* NCRecent.storyboard */; };
 		F76673ED22C901F6007ED366 /* FileProviderDomain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76673EC22C901F5007ED366 /* FileProviderDomain.swift */; };
@@ -289,7 +290,7 @@
 		F76DEE9828F808AF0041B1C9 /* LockscreenWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76DEE9528F808AF0041B1C9 /* LockscreenWidgetProvider.swift */; };
 		F76DEE9928F808AF0041B1C9 /* LockscreenWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76DEE9628F808AF0041B1C9 /* LockscreenWidgetView.swift */; };
 		F7707687263A853700A1BA94 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; };
-		F7707689263A896A00A1BA94 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
+		F7707689263A896A00A1BA94 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; };
 		F770768A263A8A2500A1BA94 /* NCUtilityFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */; };
 		F770768E263A8C3400A1BA94 /* FloatingPanel in Frameworks */ = {isa = PBXBuildFile; productRef = F770768D263A8C3400A1BA94 /* FloatingPanel */; };
 		F771E3D320E2392D00AFB62D /* FileProviderExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F771E3D220E2392D00AFB62D /* FileProviderExtension.swift */; };
@@ -342,12 +343,12 @@
 		F78302FE28B4C44700B84583 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
 		F78302FF28B4C45000B84583 /* NCUtilityFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */; };
 		F783030028B4C45800B84583 /* NCGlobal.swift in Sources */ = {isa = PBXBuildFile; fileRef = F702F2CE25EE5B5C008F8E80 /* NCGlobal.swift */; };
-		F783030128B4C49700B84583 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
+		F783030128B4C49700B84583 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; };
 		F783030228B4C4B800B84583 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
 		F783030328B4C4DD00B84583 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; };
 		F783030528B4C50600B84583 /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = F783030428B4C50600B84583 /* SVGKit */; };
-		F783030628B4C51E00B84583 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
-		F783030728B4C52800B84583 /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
+		F783030628B4C51E00B84583 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; };
+		F783030728B4C52800B84583 /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
 		F783030D28B4C59A00B84583 /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = F783030C28B4C59A00B84583 /* SwiftEntryKit */; };
 		F783031228B4C8EC00B84583 /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
 		F783034428B5142B00B84583 /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F783034328B5142B00B84583 /* NextcloudKit */; };
@@ -388,29 +389,29 @@
 		F793E5A028B7651B005E4B02 /* NCViewCertificateDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */; };
 		F793E5A128B76541005E4B02 /* NotificationCenter+MainThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70460512499061800BB98A7 /* NotificationCenter+MainThread.swift */; };
 		F793E5A228B76580005E4B02 /* NCNetworkingChunkedUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */; };
-		F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
-		F798F0E725880609000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
-		F798F0EC2588060A000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
+		F798F0E225880608000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
+		F798F0E725880609000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
+		F798F0EC2588060A000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
 		F79A65C32191D90F00FF6DCC /* NCSelect.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F79A65C22191D90F00FF6DCC /* NCSelect.storyboard */; };
 		F79A65C62191D95E00FF6DCC /* NCSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79A65C52191D95E00FF6DCC /* NCSelect.swift */; };
-		F79B646026CA661600838ACA /* UIControl+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extensions.swift */; };
-		F79B646126CA661600838ACA /* UIControl+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extensions.swift */; };
-		F79B646226CA661600838ACA /* UIControl+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extensions.swift */; };
-		F79B646326CA661600838ACA /* UIControl+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extensions.swift */; };
-		F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B869A265E19D40085C0E0 /* NSMutableAttributedString+Extensions.swift */; };
+		F79B646026CA661600838ACA /* UIControl+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extension.swift */; };
+		F79B646126CA661600838ACA /* UIControl+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extension.swift */; };
+		F79B646226CA661600838ACA /* UIControl+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extension.swift */; };
+		F79B646326CA661600838ACA /* UIControl+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B645F26CA661600838ACA /* UIControl+Extension.swift */; };
+		F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79B869A265E19D40085C0E0 /* NSMutableAttributedString+Extension.swift */; };
 		F79EC77F26316193004E59D6 /* NCRenameFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70D87CE25EE6E58008CBBBD /* NCRenameFile.swift */; };
 		F79EC784263161BA004E59D6 /* NCRenameFile.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F70D87CD25EE6E58008CBBBD /* NCRenameFile.storyboard */; };
 		F79EC78926316AC4004E59D6 /* NCPopupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F702F30725EE5D47008F8E80 /* NCPopupViewController.swift */; };
 		F79EDAA326B004980007D134 /* NCPlayerToolBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79EDA9F26B004980007D134 /* NCPlayerToolBar.swift */; };
 		F79EDAA526B004980007D134 /* NCPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79EDAA126B004980007D134 /* NCPlayer.swift */; };
-		F7A0D1352591FBC5008F8A13 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
-		F7A0D1362591FBC5008F8A13 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
-		F7A0D1372591FBC5008F8A13 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
+		F7A0D1352591FBC5008F8A13 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; };
+		F7A0D1362591FBC5008F8A13 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; };
+		F7A0D1372591FBC5008F8A13 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; };
 		F7A321AD1E9E6AD50069AD1B /* CCAdvanced.m in Sources */ = {isa = PBXBuildFile; fileRef = F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */; };
 		F7A60F86292D215000FCE1F2 /* NCTalkAccounts.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A60F84292D215000FCE1F2 /* NCTalkAccounts.swift */; };
 		F7A60F87292D215000FCE1F2 /* NCTalkAccounts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7A60F85292D215000FCE1F2 /* NCTalkAccounts.storyboard */; };
-		F7A76DC8256A71CD00119AB3 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
-		F7A76DCD256A71CE00119AB3 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
+		F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; };
+		F7A76DCD256A71CE00119AB3 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; };
 		F7A7FA6329265CF4000603EF /* NCManageE2EE.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A7FA6229265CF4000603EF /* NCManageE2EE.swift */; };
 		F7A8D72428F1771B008BBE1C /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F7A8D72328F1771B008BBE1C /* NextcloudKit */; };
 		F7A8D72628F17728008BBE1C /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = F7A8D72528F17728008BBE1C /* Realm */; };
@@ -430,18 +431,19 @@
 		F7A8D73D28F181D3008BBE1C /* NCUtilityFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */; };
 		F7A8D73E28F181E2008BBE1C /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
 		F7A8D73F28F181EF008BBE1C /* NCGlobal.swift in Sources */ = {isa = PBXBuildFile; fileRef = F702F2CE25EE5B5C008F8E80 /* NCGlobal.swift */; };
-		F7A8D74028F18212008BBE1C /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
-		F7A8D74128F18254008BBE1C /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
+		F7A8D74028F18212008BBE1C /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; };
+		F7A8D74128F18254008BBE1C /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; };
 		F7A8D74228F18261008BBE1C /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
-		F7A8D74328F1826F008BBE1C /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
+		F7A8D74328F1826F008BBE1C /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; };
 		F7A8D74428F1827B008BBE1C /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; };
 		F7A8D74528F1828E008BBE1C /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
-		F7AC1CB028AB94490032D99F /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AC1CAF28AB94490032D99F /* Array+Extensions.swift */; };
+		F7AC1CB028AB94490032D99F /* Array+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AC1CAF28AB94490032D99F /* Array+Extension.swift */; };
+		F7AC934A296193050002BC0F /* Reasons to use Nextcloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = F7AC9349296193050002BC0F /* Reasons to use Nextcloud.pdf */; };
 		F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F4230D5F9E007ACF8A /* NCLoginWeb.swift */; };
 		F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F7230E81CB007ACF8A /* NCBrowserWeb.swift */; };
 		F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7AE00F9230E81EB007ACF8A /* NCBrowserWeb.storyboard */; };
 		F7B6B70427C4E7FA00A7F6EB /* NCScan+CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */; };
-		F7B7504B2397D38F004E13EC /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
+		F7B7504B2397D38F004E13EC /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; };
 		F7B8B83025681C3400967775 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F7B8B82F25681C3400967775 /* GoogleService-Info.plist */; };
 		F7B8CD91261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */; };
 		F7B8CD96261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */; };
@@ -493,11 +495,11 @@
 		F7D68FD028CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; };
 		F7D96FCC246ED7E200536D73 /* NCNetworkingCheckRemoteUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D96FCB246ED7E100536D73 /* NCNetworkingCheckRemoteUser.swift */; };
 		F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */; };
-		F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */; };
 		F7E0710128B13BB00001B882 /* DashboardData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E0710028B13BB00001B882 /* DashboardData.swift */; };
 		F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */; };
-		F7E41316294A19B300839300 /* UIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extensions.swift */; };
+		F7E41316294A19B300839300 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; };
 		F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */; };
+		F7E8A391295DC5E0006CB2D0 /* View+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E8A390295DC5E0006CB2D0 /* View+Extension.swift */; };
 		F7E98C1627E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; };
 		F7E98C1727E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; };
 		F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; };
@@ -529,7 +531,7 @@
 		F7F4F10A27ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F10227ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf */; };
 		F7F4F10B27ECDBDB008676F9 /* Inconsolata-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F10327ECDBDB008676F9 /* Inconsolata-Light.ttf */; };
 		F7F4F10C27ECDBDB008676F9 /* Inconsolata-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F10427ECDBDB008676F9 /* Inconsolata-Regular.ttf */; };
-		F7F4F11027ECDC4A008676F9 /* UIDevice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F10F27ECDC4A008676F9 /* UIDevice+Extensions.swift */; };
+		F7F4F11027ECDC4A008676F9 /* UIDevice+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F10F27ECDC4A008676F9 /* UIDevice+Extension.swift */; };
 		F7F4F11227ECDC52008676F9 /* UIFont+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */; };
 		F7F878AE1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */; };
 		F7F878AF1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */; };
@@ -667,7 +669,7 @@
 		AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extension.swift"; sourceTree = "<group>"; };
 		AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCells.swift; sourceTree = "<group>"; };
 		AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = "<group>"; };
-		AFD3323F276A02C000F5AE02 /* UIApplication+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIApplication+Extensions.swift"; sourceTree = "<group>"; };
+		AFD3323F276A02C000F5AE02 /* UIApplication+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIApplication+Extension.swift"; sourceTree = "<group>"; };
 		D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityTableViewCell.swift; sourceTree = "<group>"; };
 		F700222B1EC479840080073F /* Custom.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Custom.xcassets; sourceTree = "<group>"; };
 		F700510022DF63AC003A3356 /* NCShare.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCShare.storyboard; sourceTree = "<group>"; };
@@ -733,7 +735,7 @@
 		F70BFC7320E0FA7C00C67599 /* NCUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUtility.swift; sourceTree = "<group>"; };
 		F70CAE381F8CF31A008125FD /* NCEndToEndEncryption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCEndToEndEncryption.h; sourceTree = "<group>"; };
 		F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NCEndToEndEncryption.m; sourceTree = "<group>"; };
-		F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extensions.swift"; sourceTree = "<group>"; };
+		F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
 		F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCCollectionViewCommon.swift; sourceTree = "<group>"; };
 		F70D87CD25EE6E58008CBBBD /* NCRenameFile.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCRenameFile.storyboard; sourceTree = "<group>"; };
 		F70D87CE25EE6E58008CBBBD /* NCRenameFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCRenameFile.swift; sourceTree = "<group>"; };
@@ -748,6 +750,7 @@
 		F7134185259747BA00768D21 /* NCPushNotification.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCPushNotification.m; sourceTree = "<group>"; };
 		F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+animatedGIF.h"; sourceTree = "<group>"; };
 		F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+animatedGIF.m"; sourceTree = "<group>"; };
+		F714560F296433C80038D028 /* NCDocumentCamera.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCDocumentCamera.swift; sourceTree = "<group>"; };
 		F714803A262EBE3900693E51 /* MainInterface.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainInterface.storyboard; sourceTree = "<group>"; };
 		F7148040262EBE4000693E51 /* NCShareExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareExtension.swift; sourceTree = "<group>"; };
 		F7148046262EBE4B00693E51 /* Share-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Share-Bridging-Header.h"; sourceTree = "<group>"; };
@@ -776,7 +779,6 @@
 		F719D9E1288D396100762E33 /* NCColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCColorPicker.swift; sourceTree = "<group>"; };
 		F71CD6C92930D7B1006C95C1 /* NCApplicationHandle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCApplicationHandle.swift; sourceTree = "<group>"; };
 		F7226EDB1EE4089300EBECB1 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
-		F7237DD0295463E700A9D8B7 /* NCBrandSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCBrandSettings.swift; sourceTree = "<group>"; };
 		F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichdocument.storyboard; sourceTree = "<group>"; };
 		F7239870253D86B600257F49 /* NCEmptyDataSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEmptyDataSet.swift; sourceTree = "<group>"; };
 		F7239876253D86D300257F49 /* NCEmptyView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCEmptyView.xib; sourceTree = "<group>"; };
@@ -858,6 +860,7 @@
 		F75B91F71ECAE26300199C96 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F75B923D1ECAE55E00199C96 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F75C0C4723D1FAE300163CC8 /* NCRichWorkspaceCommon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCRichWorkspaceCommon.swift; sourceTree = "<group>"; };
+		F75CA1462962F13700B01130 /* HUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDView.swift; sourceTree = "<group>"; };
 		F75D19E225EFE09000D74598 /* NCTrash+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCTrash+Menu.swift"; sourceTree = "<group>"; };
 		F75DD768290ABB25002EB562 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intent.intentdefinition; sourceTree = "<group>"; };
 		F75EDFBC1E8C112F00E6F369 /* libsqlite3.0.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; };
@@ -870,7 +873,6 @@
 		F765608A23BF80A400765969 /* SwiftEntryKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftEntryKit.framework; path = Carthage/Build/iOS/SwiftEntryKit.framework; sourceTree = "<group>"; };
 		F765608E23BF813500765969 /* NCContentPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCContentPresenter.swift; sourceTree = "<group>"; };
 		F765E9CC295C585800A09ED8 /* NCUploadScanDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUploadScanDocument.swift; sourceTree = "<group>"; };
-		F765E9CE295C684F00A09ED8 /* Reasons to use Nextcloud.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "Reasons to use Nextcloud.pdf"; sourceTree = SOURCE_ROOT; };
 		F765F72F25237E3F00391DBE /* NCRecent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCRecent.swift; sourceTree = "<group>"; };
 		F765F73025237E3F00391DBE /* NCRecent.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCRecent.storyboard; sourceTree = "<group>"; };
 		F76673EC22C901F5007ED366 /* FileProviderDomain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileProviderDomain.swift; sourceTree = "<group>"; };
@@ -969,12 +971,12 @@
 		F79918A72199840500C2E308 /* Sheeeeeeeeet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sheeeeeeeeet.framework; path = Carthage/Build/iOS/Sheeeeeeeeet.framework; sourceTree = "<group>"; };
 		F79A65C22191D90F00FF6DCC /* NCSelect.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCSelect.storyboard; sourceTree = "<group>"; };
 		F79A65C52191D95E00FF6DCC /* NCSelect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSelect.swift; sourceTree = "<group>"; };
-		F79B645F26CA661600838ACA /* UIControl+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIControl+Extensions.swift"; sourceTree = "<group>"; };
-		F79B869A265E19D40085C0E0 /* NSMutableAttributedString+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSMutableAttributedString+Extensions.swift"; sourceTree = "<group>"; };
+		F79B645F26CA661600838ACA /* UIControl+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIControl+Extension.swift"; sourceTree = "<group>"; };
+		F79B869A265E19D40085C0E0 /* NSMutableAttributedString+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSMutableAttributedString+Extension.swift"; sourceTree = "<group>"; };
 		F79BCEEA270B49C800B5B71F /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
 		F79EDA9F26B004980007D134 /* NCPlayerToolBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPlayerToolBar.swift; sourceTree = "<group>"; };
 		F79EDAA126B004980007D134 /* NCPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPlayer.swift; sourceTree = "<group>"; };
-		F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
+		F7A0D1342591FBC5008F8A13 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
 		F7A321AB1E9E6AD50069AD1B /* CCAdvanced.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAdvanced.h; sourceTree = "<group>"; };
 		F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAdvanced.m; sourceTree = "<group>"; };
 		F7A60F84292D215000FCE1F2 /* NCTalkAccounts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCTalkAccounts.swift; sourceTree = "<group>"; };
@@ -1025,7 +1027,8 @@
 		F7AA41DF27C7CF7E00494705 /* es-PY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-PY"; path = "es-PY.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
 		F7AA41E027C7CF8000494705 /* es-NI */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-NI"; path = "es-NI.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
 		F7AA41E127C7CF8100494705 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
-		F7AC1CAF28AB94490032D99F /* Array+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extensions.swift"; sourceTree = "<group>"; };
+		F7AC1CAF28AB94490032D99F /* Array+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extension.swift"; sourceTree = "<group>"; };
+		F7AC9349296193050002BC0F /* Reasons to use Nextcloud.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "Reasons to use Nextcloud.pdf"; sourceTree = SOURCE_ROOT; };
 		F7ACE4291BAC0268006C0017 /* Acknowledgements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Acknowledgements.h; sourceTree = "<group>"; };
 		F7ACE42A1BAC0268006C0017 /* Acknowledgements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Acknowledgements.m; sourceTree = "<group>"; };
 		F7ACE42B1BAC0268006C0017 /* Acknowledgements.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Acknowledgements.rtf; sourceTree = "<group>"; };
@@ -1042,7 +1045,7 @@
 		F7B1076C25D3CF2800E72DE2 /* BackgroundTasks.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTasks.framework; path = System/Library/Frameworks/BackgroundTasks.framework; sourceTree = SDKROOT; };
 		F7B1A7761EBB3C8000BFB6D1 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCScan+CollectionView.swift"; sourceTree = "<group>"; };
-		F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extensions.swift"; sourceTree = "<group>"; };
+		F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = "<group>"; };
 		F7B8B82F25681C3400967775 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; };
 		F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingChunkedUpload.swift; sourceTree = "<group>"; };
 		F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCDatabase.swift; sourceTree = "<group>"; };
@@ -1140,13 +1143,13 @@
 		F7DBD82B23E46A4700ECB7C6 /* MarkdownKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MarkdownKit.framework; path = Carthage/Build/iOS/MarkdownKit.framework; sourceTree = "<group>"; };
 		F7DE9AB01F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadAssets.swift; sourceTree = "<group>"; };
-		F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadScanDocument.swift; sourceTree = "<group>"; };
 		F7E0710028B13BB00001B882 /* DashboardData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardData.swift; sourceTree = "<group>"; };
 		F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCUserStatus.storyboard; sourceTree = "<group>"; };
-		F7E41315294A19B300839300 /* UIView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Extensions.swift"; sourceTree = "<group>"; };
+		F7E41315294A19B300839300 /* UIView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = "<group>"; };
 		F7E45E6D21E75BF200579249 /* ja-JP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ja-JP"; path = "ja-JP.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCommentsCell.swift; sourceTree = "<group>"; };
 		F7E856182351D7BE009A3330 /* SwiftyXMLParser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyXMLParser.framework; path = Carthage/Build/iOS/SwiftyXMLParser.framework; sourceTree = "<group>"; };
+		F7E8A390295DC5E0006CB2D0 /* View+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extension.swift"; sourceTree = "<group>"; };
 		F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Video.swift"; sourceTree = "<group>"; };
 		F7EDE508262DA9D600414FE6 /* NCSelectCommandViewSelect.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSelectCommandViewSelect.xib; sourceTree = "<group>"; };
 		F7EDE513262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "NCSelectCommandViewSelect+CreateFolder.xib"; sourceTree = "<group>"; };
@@ -1166,7 +1169,7 @@
 		F7F4F10227ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-ExtraBold.ttf"; sourceTree = "<group>"; };
 		F7F4F10327ECDBDB008676F9 /* Inconsolata-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Light.ttf"; sourceTree = "<group>"; };
 		F7F4F10427ECDBDB008676F9 /* Inconsolata-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Regular.ttf"; sourceTree = "<group>"; };
-		F7F4F10F27ECDC4A008676F9 /* UIDevice+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Extensions.swift"; sourceTree = "<group>"; };
+		F7F4F10F27ECDC4A008676F9 /* UIDevice+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Extension.swift"; sourceTree = "<group>"; };
 		F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+Extension.swift"; sourceTree = "<group>"; };
 		F7F67BB81A24D27800EE80DA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
 		F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEndToEndMetadata.swift; sourceTree = "<group>"; };
@@ -1583,15 +1586,17 @@
 			path = Networking;
 			sourceTree = "<group>";
 		};
-		F758B41E212C516300515F55 /* ScanDocument */ = {
+		F758B41E212C516300515F55 /* Scan document */ = {
 			isa = PBXGroup;
 			children = (
 				F758B457212C564000515F55 /* NCScan.storyboard */,
 				F758B45D212C569C00515F55 /* NCScanCell.swift */,
 				F758B45F212C56A400515F55 /* NCScan.swift */,
 				F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */,
+				F765E9CC295C585800A09ED8 /* NCUploadScanDocument.swift */,
+				F714560F296433C80038D028 /* NCDocumentCamera.swift */,
 			);
-			path = ScanDocument;
+			path = "Scan document";
 			sourceTree = "<group>";
 		};
 		F75DD764290AB369002EB562 /* Intent */ = {
@@ -1773,27 +1778,28 @@
 			isa = PBXGroup;
 			children = (
 				F70460512499061800BB98A7 /* NotificationCenter+MainThread.swift */,
-				F79B869A265E19D40085C0E0 /* NSMutableAttributedString+Extensions.swift */,
+				F79B869A265E19D40085C0E0 /* NSMutableAttributedString+Extension.swift */,
 				F78071071EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.h */,
 				F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */,
-				F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */,
-				AFD3323F276A02C000F5AE02 /* UIApplication+Extensions.swift */,
+				F7A0D1342591FBC5008F8A13 /* String+Extension.swift */,
+				AFD3323F276A02C000F5AE02 /* UIApplication+Extension.swift */,
 				AFCE353227E4ED1900FEA6C2 /* UIToolbar+Extension.swift */,
 				AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */,
 				AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */,
 				AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */,
-				F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */,
-				F79B645F26CA661600838ACA /* UIControl+Extensions.swift */,
-				F7AC1CAF28AB94490032D99F /* Array+Extensions.swift */,
-				F7F4F10F27ECDC4A008676F9 /* UIDevice+Extensions.swift */,
+				F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */,
+				F79B645F26CA661600838ACA /* UIControl+Extension.swift */,
+				F7AC1CAF28AB94490032D99F /* Array+Extension.swift */,
+				F7F4F10F27ECDC4A008676F9 /* UIDevice+Extension.swift */,
 				F77BB747289985270090FC19 /* UITabBarController+Extension.swift */,
 				F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */,
 				F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */,
 				F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */,
-				F7E41315294A19B300839300 /* UIView+Extensions.swift */,
+				F7E41315294A19B300839300 /* UIView+Extension.swift */,
+				F7E8A390295DC5E0006CB2D0 /* View+Extension.swift */,
 				F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */,
 				F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */,
-				F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */,
+				F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */,
 			);
 			path = Extensions;
 			sourceTree = "<group>";
@@ -1895,6 +1901,7 @@
 				F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */,
 				F702F30725EE5D47008F8E80 /* NCPopupViewController.swift */,
 				F707C26421A2DC5200F6181E /* NCStoreReview.swift */,
+				F75CA1462962F13700B01130 /* HUDView.swift */,
 				AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */,
 				F70BFC7320E0FA7C00C67599 /* NCUtility.swift */,
 				AF93474B27E34120002537EE /* NCUtility+Image.swift */,
@@ -1931,7 +1938,6 @@
 				F70F96AF2874394B006C8379 /* Nextcloud-Bridging-Header.h */,
 				F73CB5771ED46807005F2A5A /* NCBridgeSwift.h */,
 				F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */,
-				F7237DD0295463E700A9D8B7 /* NCBrandSettings.swift */,
 			);
 			path = Brand;
 			sourceTree = "<group>";
@@ -2027,8 +2033,6 @@
 				F704B5E62430C06700632F5F /* NCCreateFormUploadConflictCell.xib */,
 				F7651A8823A2A3F2001403D2 /* NCCreateFormUploadDocuments.storyboard */,
 				F7651A8923A2A3F2001403D2 /* NCCreateFormUploadDocuments.swift */,
-				F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */,
-				F765E9CC295C585800A09ED8 /* NCUploadScanDocument.swift */,
 				F747BA1E22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard */,
 				F7020FCD2233D7F700B7297D /* NCCreateFormUploadVoiceNote.swift */,
 			);
@@ -2149,7 +2153,7 @@
 				F765F72E25237E3F00391DBE /* Recent */,
 				F70D87CC25EE6E58008CBBBD /* Rename file */,
 				F7CADB3D23CCDDA1000EEC78 /* RichWorkspace */,
-				F758B41E212C516300515F55 /* ScanDocument */,
+				F758B41E212C516300515F55 /* Scan document */,
 				F7FE125B1BAC03FB0041924B /* Security */,
 				F79A65C12191D8DC00FF6DCC /* Select */,
 				F7ACE4281BAC0268006C0017 /* Settings */,
@@ -2167,7 +2171,7 @@
 		F7F67BAB1A24D27800EE80DA /* Supporting Files */ = {
 			isa = PBXGroup;
 			children = (
-				F765E9CE295C684F00A09ED8 /* Reasons to use Nextcloud.pdf */,
+				F7AC9349296193050002BC0F /* Reasons to use Nextcloud.pdf */,
 				F7F4F0FB27ECDBDA008676F9 /* Font */,
 				F72B60941A24F04E004EF66F /* Localizations */,
 			);
@@ -2753,7 +2757,7 @@
 				F70753F72542A9C000972D44 /* NCViewerMediaPage.storyboard in Resources */,
 				F70A58C024D0545100DED00D /* NCCapabilitiesViewController.storyboard in Resources */,
 				F7F4F10627ECDBDB008676F9 /* Inconsolata-Medium.ttf in Resources */,
-				F765E9CF295C684F00A09ED8 /* Reasons to use Nextcloud.pdf in Resources */,
+				F7AC934A296193050002BC0F /* Reasons to use Nextcloud.pdf in Resources */,
 				F749C10D23C4A5340027D966 /* NCIntro.storyboard in Resources */,
 				F7A60F87292D215000FCE1F2 /* NCTalkAccounts.storyboard in Resources */,
 				F7239877253D86D300257F49 /* NCEmptyView.xib in Resources */,
@@ -2831,7 +2835,7 @@
 				F746EC50273906BA0052598D /* NCViewCertificateDetails.swift in Sources */,
 				AF4BF62127562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */,
 				F702F2D225EE5B5C008F8E80 /* NCGlobal.swift in Sources */,
-				F7707689263A896A00A1BA94 /* UIImage+Extensions.swift in Sources */,
+				F7707689263A896A00A1BA94 /* UIImage+Extension.swift in Sources */,
 				2C1D5D7523E2DE3300334ABB /* NCDatabase.swift in Sources */,
 				F7E98C1927E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
 				2C1D5D7623E2DE3300334ABB /* NCManageDatabase.swift in Sources */,
@@ -2840,13 +2844,14 @@
 				2C33C48223E2C475005F963B /* NotificationService.swift in Sources */,
 				AF4BF617275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
 				F7BF9D872934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
-				D575039F27146F93008DC9DC /* String+Extensions.swift in Sources */,
+				D575039F27146F93008DC9DC /* String+Extension.swift in Sources */,
 				F73D5E4A246DE09200DF6467 /* NCElementsJSON.swift in Sources */,
-				F79B646326CA661600838ACA /* UIControl+Extensions.swift in Sources */,
+				F79B646326CA661600838ACA /* UIControl+Extension.swift in Sources */,
 				F78A10C429322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */,
+				F75CA1482962F13700B01130 /* HUDView.swift in Sources */,
 				AF4BF61C27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
 				AF817EF4274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
-				F798F0EC2588060A000DAFFD /* UIColor+Extensions.swift in Sources */,
+				F798F0EC2588060A000DAFFD /* UIColor+Extension.swift in Sources */,
 				2CB7D1CA23E2EDCB00376EF9 /* NCPushNotificationEncryption.m in Sources */,
 				F782FDC424E6933900666099 /* NCUtility.swift in Sources */,
 			);
@@ -2876,20 +2881,20 @@
 				F79EC78926316AC4004E59D6 /* NCPopupViewController.swift in Sources */,
 				F7C30DFB291BCF790017149B /* NCNetworkingE2EECreateFolder.swift in Sources */,
 				AF4BF61F27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */,
-				F7A0D1362591FBC5008F8A13 /* String+Extensions.swift in Sources */,
+				F7A0D1362591FBC5008F8A13 /* String+Extension.swift in Sources */,
 				F7EDE4D6262D7B9600414FE6 /* NCListCell.swift in Sources */,
 				F7707687263A853700A1BA94 /* NCContentPresenter.swift in Sources */,
 				F70460532499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
 				F70BFC7520E0FA7D00C67599 /* NCUtility.swift in Sources */,
 				AF22B20C277C6F4D00DAB0CC /* NCShareCell.swift in Sources */,
 				F7E98C1727E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
-				F79B646126CA661600838ACA /* UIControl+Extensions.swift in Sources */,
+				F79B646126CA661600838ACA /* UIControl+Extension.swift in Sources */,
 				F77C973A2953143A00FDDD09 /* NCCameraRoll.swift in Sources */,
 				F7EDE4CC262D7B6F00414FE6 /* NCEmptyDataSet.swift in Sources */,
 				F7C30E01291BD2610017149B /* NCNetworkingE2EERename.swift in Sources */,
 				AF4BF61A27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
 				AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
-				F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */,
+				F798F0E225880608000DAFFD /* UIColor+Extension.swift in Sources */,
 				AF3FDCC32796F3FB00710F60 /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */,
 				AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */,
@@ -2907,7 +2912,7 @@
 				F75A9EE723796C6F0044CFCE /* NCNetworking.swift in Sources */,
 				AF730AFA27843E4C00B7520E /* NCShareExtension+NCDelegate.swift in Sources */,
 				F7EDE4E0262D7BAF00414FE6 /* NCGridCell.swift in Sources */,
-				F7A76DC8256A71CD00119AB3 /* UIImage+Extensions.swift in Sources */,
+				F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */,
 				F7B8CD96261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F7BAADC91ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
 				F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */,
@@ -2949,12 +2954,12 @@
 				F76DEE9828F808AF0041B1C9 /* LockscreenWidgetProvider.swift in Sources */,
 				F78A10C029322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */,
 				F78302FA28B4C3EA00B84583 /* NCManageDatabase+Metadata.swift in Sources */,
-				F783030728B4C52800B84583 /* UIColor+Extensions.swift in Sources */,
+				F783030728B4C52800B84583 /* UIColor+Extension.swift in Sources */,
 				F783030028B4C45800B84583 /* NCGlobal.swift in Sources */,
 				F793E59D28B761E7005E4B02 /* NCNetworking.swift in Sources */,
 				F78302FC28B4C3F300B84583 /* NCElementsJSON.swift in Sources */,
 				F7BF9D832934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
-				F783030628B4C51E00B84583 /* String+Extensions.swift in Sources */,
+				F783030628B4C51E00B84583 /* String+Extension.swift in Sources */,
 				F77ED59328C9CEA000E24ED0 /* ToolbarWidgetProvider.swift in Sources */,
 				F72A17D828B221E300F3F159 /* DashboardWidgetView.swift in Sources */,
 				F77ED59528C9CEA400E24ED0 /* ToolbarWidgetView.swift in Sources */,
@@ -2968,7 +2973,7 @@
 				F75DD766290ABB25002EB562 /* Intent.intentdefinition in Sources */,
 				F78302F628B4C3C500B84583 /* NCDatabase.swift in Sources */,
 				F7D68FCD28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
-				F783030128B4C49700B84583 /* UIImage+Extensions.swift in Sources */,
+				F783030128B4C49700B84583 /* UIImage+Extension.swift in Sources */,
 				F72EA95428B7BABA00C88F0C /* FilesWidgetProvider.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -2991,7 +2996,7 @@
 				F771E3D520E2392D00AFB62D /* FileProviderItem.swift in Sources */,
 				AF4BF616275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
 				F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */,
-				F798F0E725880609000DAFFD /* UIColor+Extensions.swift in Sources */,
+				F798F0E725880609000DAFFD /* UIColor+Extension.swift in Sources */,
 				F7D68FCF28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
 				AF4BF61B27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
 				F70460542499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
@@ -2999,14 +3004,14 @@
 				F7BF9D862934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
 				F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
 				F785EEA42461A4A600B3F945 /* NCUtility.swift in Sources */,
-				F79B646226CA661600838ACA /* UIControl+Extensions.swift in Sources */,
+				F79B646226CA661600838ACA /* UIControl+Extension.swift in Sources */,
 				AF817EF3274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				F771E3F320E239A600AFB62D /* FileProviderData.swift in Sources */,
 				F7B8CD9B261AF401007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
-				F7A0D1372591FBC5008F8A13 /* String+Extensions.swift in Sources */,
+				F7A0D1372591FBC5008F8A13 /* String+Extension.swift in Sources */,
 				F771E3D720E2392D00AFB62D /* FileProviderEnumerator.swift in Sources */,
 				F74AF3A6247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
-				F7A76DCD256A71CE00119AB3 /* UIImage+Extensions.swift in Sources */,
+				F7A76DCD256A71CE00119AB3 /* UIImage+Extension.swift in Sources */,
 				F771E3F820E239B500AFB62D /* FileProviderExtension+Thumbnail.swift in Sources */,
 				AF4BF62027562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */,
 				F785EEA62461A4FB00B3F945 /* CCUtility.m in Sources */,
@@ -3080,7 +3085,6 @@
 				F76673ED22C901F6007ED366 /* FileProviderDomain.swift in Sources */,
 				F7A321AD1E9E6AD50069AD1B /* CCAdvanced.m in Sources */,
 				F77B0E4F1D118A16002130FE /* CCManageAutoUpload.m in Sources */,
-				F7237DD1295463E700A9D8B7 /* NCBrandSettings.swift in Sources */,
 				F7BAADC81ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
 				F75C0C4823D1FAE300163CC8 /* NCRichWorkspaceCommon.swift in Sources */,
 				F78ACD4A21903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */,
@@ -3088,7 +3092,7 @@
 				F760329F252F0F8E0015A421 /* NCTransferCell.swift in Sources */,
 				AF68326A27BE65A90010BF0B /* NCMenuAction.swift in Sources */,
 				F7682FE023C36B0500983A04 /* NCMainTabBar.swift in Sources */,
-				F7A0D1352591FBC5008F8A13 /* String+Extensions.swift in Sources */,
+				F7A0D1352591FBC5008F8A13 /* String+Extension.swift in Sources */,
 				F77B0E5F1D118A16002130FE /* NCSettings.m in Sources */,
 				F7F9D1BB25397CE000D9BFF5 /* NCViewer.swift in Sources */,
 				AF730AF827834B1400B7520E /* NCShare+NCCellDelegate.swift in Sources */,
@@ -3096,7 +3100,7 @@
 				F78F74362163781100C2ADAD /* NCTrash.swift in Sources */,
 				AF817EF1274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				AF2D7C7C2742556F00ADF566 /* NCShareLinkCell.swift in Sources */,
-				F7E41316294A19B300839300 /* UIView+Extensions.swift in Sources */,
+				F7E41316294A19B300839300 /* UIView+Extension.swift in Sources */,
 				F7C30E00291BD2610017149B /* NCNetworkingE2EERename.swift in Sources */,
 				F7F4F0F927ECDBA4008676F9 /* NCSubtitlePlayer.swift in Sources */,
 				F7651A8B23A2A3F2001403D2 /* NCCreateFormUploadDocuments.swift in Sources */,
@@ -3123,10 +3127,11 @@
 				F749C10B23C4A5340027D966 /* NCIntroCollectionViewCell.swift in Sources */,
 				AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */,
 				F718C24E254D507B00C5C256 /* NCViewerMediaDetailView.swift in Sources */,
+				F7145610296433C80038D028 /* NCDocumentCamera.swift in Sources */,
 				F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */,
 				F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */,
 				F78071091EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */,
-				F79B646026CA661600838ACA /* UIControl+Extensions.swift in Sources */,
+				F79B646026CA661600838ACA /* UIControl+Extension.swift in Sources */,
 				F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */,
 				F765F73125237E3F00391DBE /* NCRecent.swift in Sources */,
 				F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */,
@@ -3140,12 +3145,12 @@
 				AF93471227E2341B002537EE /* NCShare+Menu.swift in Sources */,
 				F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */,
 				F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */,
-				AFD33240276A02C100F5AE02 /* UIApplication+Extensions.swift in Sources */,
-				F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extensions.swift in Sources */,
-				F7B7504B2397D38F004E13EC /* UIImage+Extensions.swift in Sources */,
+				F7E8A391295DC5E0006CB2D0 /* View+Extension.swift in Sources */,
+				AFD33240276A02C100F5AE02 /* UIApplication+Extension.swift in Sources */,
+				F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extension.swift in Sources */,
+				F7B7504B2397D38F004E13EC /* UIImage+Extension.swift in Sources */,
 				F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */,
 				AF3FDCC22796ECC300710F60 /* NCTrash+CollectionView.swift in Sources */,
-				F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */,
 				F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */,
 				F76D364628A4F8BF00214537 /* NCActivityIndicator.swift in Sources */,
 				F7020FCE2233D7F700B7297D /* NCCreateFormUploadVoiceNote.swift in Sources */,
@@ -3159,7 +3164,7 @@
 				F70753EB2542A99800972D44 /* NCViewerMediaPage.swift in Sources */,
 				F7FAFD3A28BFA948000777FE /* NCNotification+Menu.swift in Sources */,
 				F74C0436253F1CDC009762AB /* NCShares.swift in Sources */,
-				F7AC1CB028AB94490032D99F /* Array+Extensions.swift in Sources */,
+				F7AC1CB028AB94490032D99F /* Array+Extension.swift in Sources */,
 				F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */,
 				F707C26521A2DC5200F6181E /* NCStoreReview.swift in Sources */,
 				F7BAADCB1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */,
@@ -3177,14 +3182,15 @@
 				F704B5E52430AA8000632F5F /* NCCreateFormUploadConflict.swift in Sources */,
 				F765608F23BF813600765969 /* NCContentPresenter.swift in Sources */,
 				F7D68FCC28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */,
-				F70CEF5623E9C7E50007035B /* UIColor+Extensions.swift in Sources */,
+				F70CEF5623E9C7E50007035B /* UIColor+Extension.swift in Sources */,
+				F75CA1472962F13700B01130 /* HUDView.swift in Sources */,
 				F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */,
 				F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */,
 				F7A7FA6329265CF4000603EF /* NCManageE2EE.swift in Sources */,
 				F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */,
 				F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */,
 				F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */,
-				F7F4F11027ECDC4A008676F9 /* UIDevice+Extensions.swift in Sources */,
+				F7F4F11027ECDC4A008676F9 /* UIDevice+Extension.swift in Sources */,
 				F77B0ED11D118A16002130FE /* Acknowledgements.m in Sources */,
 				F70D8D8124A4A9BF000A5756 /* NCNetworkingProcessUpload.swift in Sources */,
 				F7D96FCC246ED7E200536D73 /* NCNetworkingCheckRemoteUser.swift in Sources */,
@@ -3210,7 +3216,7 @@
 				F7A8D74528F1828E008BBE1C /* CCUtility.m in Sources */,
 				F75DD767290ABB25002EB562 /* Intent.intentdefinition in Sources */,
 				F7A8D73F28F181EF008BBE1C /* NCGlobal.swift in Sources */,
-				F7A8D74328F1826F008BBE1C /* String+Extensions.swift in Sources */,
+				F7A8D74328F1826F008BBE1C /* String+Extension.swift in Sources */,
 				F7A8D73728F17E1E008BBE1C /* NCManageDatabase+Account.swift in Sources */,
 				F7A8D73B28F17E2C008BBE1C /* NCElementsJSON.swift in Sources */,
 				F7BF9D842934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */,
@@ -3219,9 +3225,9 @@
 				F7A8D73A28F17E28008BBE1C /* NCManageDatabase+Video.swift in Sources */,
 				F7A8D73828F17E21008BBE1C /* NCManageDatabase+DashboardWidget.swift in Sources */,
 				F7A8D73928F17E25008BBE1C /* NCManageDatabase+Metadata.swift in Sources */,
-				F7A8D74128F18254008BBE1C /* UIColor+Extensions.swift in Sources */,
+				F7A8D74128F18254008BBE1C /* UIColor+Extension.swift in Sources */,
 				F7A8D73428F17E12008BBE1C /* NCDatabase.swift in Sources */,
-				F7A8D74028F18212008BBE1C /* UIImage+Extensions.swift in Sources */,
+				F7A8D74028F18212008BBE1C /* UIImage+Extension.swift in Sources */,
 				F7A8D73628F17E1A008BBE1C /* NCManageDatabase+Activity.swift in Sources */,
 				F7A8D73E28F181E2008BBE1C /* NCUserBaseUrl.swift in Sources */,
 			);
@@ -3726,7 +3732,7 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 2;
+				CURRENT_PROJECT_VERSION = 3;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
@@ -3789,7 +3795,7 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 2;
+				CURRENT_PROJECT_VERSION = 3;
 				DEVELOPMENT_TEAM = NKUJUXUJ3B;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;

+ 3 - 3
iOSClient/AppDelegate.swift

@@ -842,9 +842,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
                     }
                     
                 case NCGlobal.shared.actionScanDocument:
-                    
-                    NCCreateScanDocument.shared.openScannerDocument(viewController: rootViewController)
-                    
+
+                    NCDocumentCamera.shared.openScannerDocument(viewController: rootViewController)
+
                 case NCGlobal.shared.actionTextDocument:
                     
                     guard let navigationController = UIStoryboard(name: "NCCreateFormUploadDocuments", bundle: nil).instantiateInitialViewController(), let directEditingCreators = NCManageDatabase.shared.getDirectEditingCreators(account: account), let directEditingCreator = directEditingCreators.first(where: { $0.editor == NCGlobal.shared.editorText}) else { return false }

+ 0 - 37
iOSClient/Brand/NCBrandSettings.swift

@@ -1,37 +0,0 @@
-//
-//  NCBrandSettings.swift
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 22/12/22.
-//  Copyright © 2022 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import Foundation
-import SwiftUI
-
-class NCBrandSettings: NSObject {
-    static let shared: NCBrandSettings = {
-        let instance = NCBrandSettings()
-        return instance
-    }()
-
-    // MARK: - Settings views
-
-    let settingsSizeImage: CGFloat = 25
-    let settingsFont: Font = .subheadline
-}

+ 2 - 1
iOSClient/Extensions/Array+Extensions.swift → iOSClient/Extensions/Array+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  Array+Extensions.swift
+//  Array+Extension.swift
 //  Nextcloud
 //
 //  Created by Marino Faggiana on 16/08/22.
@@ -26,6 +26,7 @@ import Foundation
 
 // https://stackoverflow.com/questions/33861036/unique-objects-inside-a-array-swift/45023247#45023247
 extension Array {
+
     func unique<T: Hashable>(map: ((Element) -> (T))) -> [Element] {
         var set = Set<T>() // the unique list kept in a Set for fast retrieval
         var arrayOrdered = [Element]() // keeping the unique list of elements but ordered

+ 1 - 1
iOSClient/Extensions/NSMutableAttributedString+Extensions.swift → iOSClient/Extensions/NSMutableAttributedString+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  NSMutableAttributedString+Extensions.swift
+//  NSMutableAttributedString+Extension.swift
 //  Nextcloud
 //
 //  Created by Marino Faggiana on 26/05/21.

+ 1 - 1
iOSClient/Extensions/String+Extensions.swift → iOSClient/Extensions/String+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  String+Extensions.swift
+//  String+Extension.swift
 //  Nextcloud
 //
 //  Created by Marino Faggiana on 22/12/20.

+ 1 - 1
iOSClient/Extensions/UIApplication+Extensions.swift → iOSClient/Extensions/UIApplication+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  UIApplication+Extensions.swift
+//  UIApplication+Extension.swift
 //  Nextcloud
 //
 //  Created by Henrik Storch on 15.12.2021.

+ 1 - 1
iOSClient/Extensions/UIColor+Extensions.swift → iOSClient/Extensions/UIColor+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  UIColor+Extensions.swift
+//  UIColor+Extension.swift
 //  Nextcloud
 //
 //  Created by Marino Faggiana on 04/02/2020.

+ 1 - 1
iOSClient/Extensions/UIControl+Extensions.swift → iOSClient/Extensions/UIControl+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  UIControl+Extensions.swift
+//  UIControl+Extension.swift
 //  Nextcloud
 //
 //  Created by Marino Faggiana on 16/08/21.

+ 2 - 1
iOSClient/Extensions/UIDevice+Extensions.swift → iOSClient/Extensions/UIDevice+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  UIDevice+Extensions.swift
+//  UIDevice+Extension.swift
 //  Nextcloud
 //
 //  Created by Federico Malagoni on 23/02/22.
@@ -22,6 +22,7 @@
 //
 
 import Foundation
+
 extension UIDevice {
 
     var hasNotch: Bool {

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

@@ -1,5 +1,5 @@
 //
-//  UIFont+Extensions.swift
+//  UIFont+Extension.swift
 //  Nextcloud
 //
 //  Created by Federico Malagoni on 23/02/22.

+ 3 - 2
iOSClient/Extensions/UIImage+Extensions.swift → iOSClient/Extensions/UIImage+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  UIColor+fixedOrientation.swift
+//  UIImage+Extensions.swift
 //  Nextcloud
 //
 //  Created by Marino Faggiana on 27/11/2019.
@@ -65,7 +65,8 @@ extension UIImage {
             return nil
         }
 
-        guard let colorSpace = cgImage.colorSpace, let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
+        guard let colorSpace = cgImage.colorSpace,
+              let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
             return nil // Not able to create CGContext
         }
 

+ 1 - 1
iOSClient/Extensions/UIView+Extensions.swift → iOSClient/Extensions/UIView+Extension.swift

@@ -1,5 +1,5 @@
 //
-//  UIView+Extensions.swift
+//  UIView+Extension.swift
 //  Nextcloud
 //
 //  Created by Marino Faggiana on 14/12/2022.

+ 16 - 0
iOSClient/Extensions/View+Extension.swift

@@ -0,0 +1,16 @@
+//
+//  View+Extension.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 29/12/22.
+//  Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+
+import SwiftUI
+
+extension View {
+    
+    func complexModifier<V: View>(@ViewBuilder _ closure: (Self) -> V) -> some View {
+        closure(self)
+    }
+}

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

@@ -878,7 +878,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     func tapButton3(_ sender: Any) {
 
         if let viewController = appDelegate.window?.rootViewController {
-            NCCreateScanDocument.shared.openScannerDocument(viewController: viewController)
+            NCDocumentCamera.shared.openScannerDocument(viewController: viewController)
         }
     }
 

+ 0 - 779
iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift

@@ -1,779 +0,0 @@
-//
-//  NCCreateFormUploadScanDocument.swift
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 14/11/2018.
-//  Copyright © 2018 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-import NextcloudKit
-import Vision
-import VisionKit
-import Photos
-import XLForm
-
-class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NCCreateFormUploadConflictDelegate {
-
-    let appDelegate = UIApplication.shared.delegate as! AppDelegate
-
-    enum typeQuality {
-        case low
-        case medium
-        case high
-    }
-    var quality: typeQuality = .medium
-
-    var serverUrl = ""
-    var titleServerUrl = ""
-    var arrayImages: [UIImage] = []
-    var fileName = CCUtility.createFileNameDate("scan", extension: "pdf")
-    var password: String = ""
-    var fileType = "PDF"
-
-    var cellBackgoundColor = UIColor.secondarySystemGroupedBackground
-
-    // MARK: - View Life Cycle
-
-    convenience init(serverUrl: String, arrayImages: [UIImage]) {
-
-        self.init()
-
-        if serverUrl == NCUtilityFileSystem.shared.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) {
-            titleServerUrl = "/"
-        } else {
-            titleServerUrl = (serverUrl as NSString).lastPathComponent
-        }
-
-        self.serverUrl = serverUrl
-        self.arrayImages = arrayImages
-    }
-
-    override func viewDidLoad() {
-
-        super.viewDidLoad()
-
-        self.title = NSLocalizedString("_save_settings_", comment: "")
-
-        view.backgroundColor = .systemGroupedBackground
-        tableView.backgroundColor = .systemGroupedBackground
-        cellBackgoundColor = .secondarySystemGroupedBackground
-
-        let saveButton: UIBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_save_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(save))
-        self.navigationItem.rightBarButtonItem = saveButton
-
-        NCUtility.shared.colorNavigationController(navigationController, backgroundColor: .systemBackground, titleColor: .label, tintColor: nil, withoutShadow: false)
-
-        tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
-
-        //        self.tableView.sectionHeaderHeight = 10
-        //        self.tableView.sectionFooterHeight = 10        
-
-        //        let row : XLFormRowDescriptor  = self.form.formRow(withTag: "fileName")!
-        //        let rowCell = row.cell(forForm: self)
-        //        rowCell.becomeFirstResponder()
-
-        initializeForm()
-
-        let value = CCUtility.getTextRecognitionStatus()
-        setTextRecognition(newValue: value)
-    }
-
-    // MARK: XLForm
-
-    func initializeForm() {
-
-        let form: XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor
-        form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow
-
-        var section: XLFormSectionDescriptor
-        var row: XLFormRowDescriptor
-
-        // Section: Destination Folder
-
-        section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_save_path_", comment: ""))
-        form.addFormSection(section)
-
-        row = XLFormRowDescriptor(tag: "ButtonDestinationFolder", rowType: XLFormRowDescriptorTypeButton, title: self.titleServerUrl)
-        row.action.formSelector = #selector(changeDestinationFolder(_:))
-        row.cellConfig["backgroundColor"] = cellBackgoundColor
-
-        row.cellConfig["imageView.image"] =  UIImage(named: "folder")!.image(color: NCBrandColor.shared.brandElement, size: 25)
-
-        row.cellConfig["textLabel.textAlignment"] = NSTextAlignment.right.rawValue
-        row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0)
-        row.cellConfig["textLabel.textColor"] = UIColor.label
-
-        section.addFormRow(row)
-
-        // Section: Quality
-
-        section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_quality_image_title_", comment: ""))
-        form.addFormSection(section)
-
-        row = XLFormRowDescriptor(tag: "compressionQuality", rowType: XLFormRowDescriptorTypeSlider)
-        row.value = 0.5
-        row.title = NSLocalizedString("_quality_medium_", comment: "")
-        row.cellConfig["backgroundColor"] = cellBackgoundColor
-
-        row.cellConfig["slider.minimumTrackTintColor"] = NCBrandColor.shared.brandElement
-
-        row.cellConfig["slider.maximumValue"] = 1
-        row.cellConfig["slider.minimumValue"] = 0
-        row.cellConfig["steps"] = 2
-
-        row.cellConfig["textLabel.textAlignment"] = NSTextAlignment.center.rawValue
-        row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0)
-        row.cellConfig["textLabel.textColor"] = UIColor.label
-
-        section.addFormRow(row)
-
-        // Section: Password
-
-        section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_pdf_password_", comment: ""))
-        form.addFormSection(section)
-
-        row = XLFormRowDescriptor(tag: "password", rowType: XLFormRowDescriptorTypePassword, title: NSLocalizedString("_password_", comment: ""))
-        row.cellConfig["backgroundColor"] = cellBackgoundColor
-
-        row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0)
-        row.cellConfig["textLabel.textColor"] = UIColor.label
-
-        row.cellConfig["textField.textAlignment"] = NSTextAlignment.right.rawValue
-        row.cellConfig["textField.font"] = UIFont.systemFont(ofSize: 15.0)
-        row.cellConfig["textField.textColor"] = UIColor.label
-
-        section.addFormRow(row)
-
-        // Section: Text recognition
-
-        section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_text_recognition_", comment: ""))
-        form.addFormSection(section)
-
-        row = XLFormRowDescriptor(tag: "textRecognition", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_text_recognition_", comment: ""))
-        row.value = 0
-        row.cellConfig["backgroundColor"] = cellBackgoundColor
-
-        row.cellConfig["imageView.image"] = UIImage(named: "textRecognition")!.image(color: NCBrandColor.shared.brandElement, size: 25)
-
-        row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0)
-        row.cellConfig["textLabel.textColor"] = UIColor.label
-
-        section.addFormRow(row)
-
-        // Section: File
-
-        section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_file_creation_", comment: ""))
-        form.addFormSection(section)
-
-        row = XLFormRowDescriptor(tag: "filetype", rowType: XLFormRowDescriptorTypeSelectorSegmentedControl, title: NSLocalizedString("_file_type_", comment: ""))
-        if arrayImages.count == 1 {
-            row.selectorOptions = ["PDF", "JPG"]
-        } else {
-            row.selectorOptions = ["PDF"]
-        }
-        row.value = "PDF"
-        row.cellConfig["backgroundColor"] = cellBackgoundColor
-
-        row.cellConfig["tintColor"] = NCBrandColor.shared.brandElement
-        row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0)
-        row.cellConfig["textLabel.textColor"] = UIColor.label
-
-        section.addFormRow(row)
-
-        row = XLFormRowDescriptor(tag: "fileName", rowType: XLFormRowDescriptorTypeText, title: NSLocalizedString("_filename_", comment: ""))
-        row.value = self.fileName
-        row.cellConfig["backgroundColor"] = cellBackgoundColor
-
-        row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0)
-        row.cellConfig["textLabel.textColor"] = UIColor.label
-
-        row.cellConfig["textField.textAlignment"] = NSTextAlignment.right.rawValue
-        row.cellConfig["textField.font"] = UIFont.systemFont(ofSize: 15.0)
-        row.cellConfig["textField.textColor"] = UIColor.label
-
-        section.addFormRow(row)
-
-        self.form = form
-    }
-
-    override func formRowDescriptorValueHasChanged(_ formRow: XLFormRowDescriptor!, oldValue: Any!, newValue: Any!) {
-
-        super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue)
-
-        if formRow.tag == "textRecognition" {
-
-            self.setTextRecognition(newValue: newValue as! Int)
-        }
-
-        if formRow.tag == "fileName" {
-
-            self.form.delegate = nil
-
-            let fileNameNew = newValue as? String
-
-            if fileNameNew != nil {
-                self.fileName = CCUtility.removeForbiddenCharactersServer(fileNameNew)
-            } else {
-                self.fileName = ""
-            }
-
-            formRow.value = self.fileName
-
-            self.updateFormRow(formRow)
-
-            self.form.delegate = self
-        }
-
-        if formRow.tag == "compressionQuality" {
-
-            self.form.delegate = nil
-
-            // let row : XLFormRowDescriptor  = self.form.formRow(withTag: "descriptionQuality")!
-            let newQuality = newValue as? NSNumber
-            let compressionQuality = (newQuality?.doubleValue)!
-
-            if compressionQuality >= 0.0 && compressionQuality <= 0.3 {
-                formRow.title = NSLocalizedString("_quality_low_", comment: "")
-                quality = typeQuality.low
-            } else if compressionQuality > 0.3 && compressionQuality <= 0.6 {
-                formRow.title = NSLocalizedString("_quality_medium_", comment: "")
-                quality = typeQuality.medium
-            } else if compressionQuality > 0.6 && compressionQuality <= 1.0 {
-                formRow.title = NSLocalizedString("_quality_high_", comment: "")
-                quality = typeQuality.high
-            }
-
-            self.updateFormRow(formRow)
-
-            self.form.delegate = self
-        }
-
-        if formRow.tag == "password" {
-            let stringPassword = newValue as? String
-            if stringPassword != nil {
-                password = stringPassword!
-            } else {
-                password = ""
-            }
-        }
-
-        if formRow.tag == "filetype" {
-            fileType = newValue as! String
-
-            let rowFileName: XLFormRowDescriptor  = self.form.formRow(withTag: "fileName")!
-            let rowPassword: XLFormRowDescriptor  = self.form.formRow(withTag: "password")!
-
-            rowFileName.value = createFileName(rowFileName.value as? String)
-
-            self.updateFormRow(rowFileName)
-
-            // rowPassword
-            if fileType == "JPG" || fileType == "TXT" {
-                rowPassword.value = ""
-                password = ""
-                rowPassword.disabled = true
-            } else {
-                rowPassword.disabled = false
-            }
-
-            self.updateFormRow(rowPassword)
-        }
-    }
-
-    func setTextRecognition(newValue: Int) {
-
-        let rowCompressionQuality: XLFormRowDescriptor = self.form.formRow(withTag: "compressionQuality")!
-        let rowFileTape: XLFormRowDescriptor = self.form.formRow(withTag: "filetype")!
-        let rowFileName: XLFormRowDescriptor = self.form.formRow(withTag: "fileName")!
-        let rowPassword: XLFormRowDescriptor = self.form.formRow(withTag: "password")!
-        let rowTextRecognition: XLFormRowDescriptor = self.form.formRow(withTag: "textRecognition")!
-
-        self.form.delegate = nil
-
-        if newValue == 1 {
-            rowFileTape.selectorOptions = ["PDF", "TXT"]
-            rowFileTape.value = "PDF"
-            fileType = "PDF"
-            rowPassword.disabled = true
-            rowCompressionQuality.disabled = false
-        } else {
-            if arrayImages.count == 1 {
-                rowFileTape.selectorOptions = ["PDF", "JPG"]
-            } else {
-                rowFileTape.selectorOptions = ["PDF"]
-            }
-            rowFileTape.value = "PDF"
-            fileType = "PDF"
-            rowPassword.disabled = false
-            rowCompressionQuality.disabled = false
-        }
-
-        rowFileName.value = createFileName(rowFileName.value as? String)
-        self.updateFormRow(rowFileName)
-        self.tableView.reloadData()
-
-        CCUtility.setTextRecognitionStatus(newValue)
-        rowTextRecognition.value = newValue
-
-        self.form.delegate = self
-    }
-
-    func createFileName(_ fileName: String?) -> String {
-
-        var name: String = ""
-        var newFileName: String = ""
-
-        if fileName == nil || fileName == "" {
-            name = CCUtility.createFileNameDate("scan", extension: "pdf") ?? "scan.pdf"
-        } else {
-            name = fileName!
-        }
-
-        let ext = (name as NSString).pathExtension.uppercased()
-
-        if ext == "" {
-            newFileName = name + "." + fileType.lowercased()
-        } else {
-            newFileName = (name as NSString).deletingPathExtension + "." + fileType.lowercased()
-        }
-
-        return newFileName
-    }
-
-    // MARK: - Action
-
-    func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], overwrite: Bool, copy: Bool, move: Bool) {
-
-        if serverUrl != nil {
-
-            CCUtility.setDirectoryScanDocuments(serverUrl!)
-            self.serverUrl = serverUrl!
-
-            if serverUrl == NCUtilityFileSystem.shared.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) {
-                self.titleServerUrl = "/"
-            } else {
-                self.titleServerUrl = (serverUrl! as NSString).lastPathComponent
-            }
-
-            // Update
-            let row: XLFormRowDescriptor  = self.form.formRow(withTag: "ButtonDestinationFolder")!
-            row.title = self.titleServerUrl
-            self.updateFormRow(row)
-        }
-    }
-
-    @objc func save() {
-
-        let rowFileName: XLFormRowDescriptor  = self.form.formRow(withTag: "fileName")!
-        guard let name = rowFileName.value else {
-            return
-        }
-        if name as! String == "" {
-            return
-        }
-
-        let ext = (name as! NSString).pathExtension.uppercased()
-        var fileNameSave = ""
-
-        if ext == "" {
-            fileNameSave = name as! String + "." + fileType.lowercased()
-        } else {
-            fileNameSave = (name as! NSString).deletingPathExtension + "." + fileType.lowercased()
-        }
-
-        // Create metadata for upload
-        let metadataForUpload = NCManageDatabase.shared.createMetadata(account: appDelegate.account, user: appDelegate.user, userId: appDelegate.userId, fileName: fileNameSave, fileNameView: fileNameSave, ocId: UUID().uuidString, serverUrl: serverUrl, urlBase: appDelegate.urlBase, url: "", contentType: "")
-
-        metadataForUpload.session = NCNetworking.shared.sessionIdentifierBackground
-        metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
-        metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
-
-        if NCManageDatabase.shared.getMetadataConflict(account: appDelegate.account, serverUrl: serverUrl, fileNameView: fileNameSave) != nil {
-
-            guard let conflict = UIStoryboard(name: "NCCreateFormUploadConflict", bundle: nil).instantiateInitialViewController() as? NCCreateFormUploadConflict else { return }
-
-            conflict.textLabelDetailNewFile = NSLocalizedString("_now_", comment: "")
-            conflict.serverUrl = serverUrl
-            conflict.metadatasUploadInConflict = [metadataForUpload]
-            conflict.delegate = self
-
-            self.present(conflict, animated: true, completion: nil)
-
-        } else {
-
-            NCActivityIndicator.shared.start(backgroundView: self.view)
-
-            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
-                self.dismissAndUpload(metadataForUpload)
-            }
-        }
-    }
-
-    func dismissCreateFormUploadConflict(metadatas: [tableMetadata]?) {
-
-        if metadatas != nil && metadatas!.count > 0 {
-
-            NCActivityIndicator.shared.start(backgroundView: self.view)
-
-            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
-                self.dismissAndUpload(metadatas![0])
-            }
-        }
-    }
-
-    func dismissAndUpload(_ metadata: tableMetadata) {
-
-        guard let fileNameGenerateExport = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView) else {
-            NCActivityIndicator.shared.stop()
-
-            let error = NKError(errorCode: NCGlobal.shared.errorCreationFile, errorDescription: "_error_creation_file_")
-            NCContentPresenter.shared.showError(error: error)
-            return
-        }
-        let fileUrl = URL(fileURLWithPath: fileNameGenerateExport)
-
-        // Text Recognition TXT
-        if fileType == "TXT" && self.form.formRow(withTag: "textRecognition")!.value as! Int == 1 {
-
-            var textFile = ""
-            for image in self.arrayImages {
-
-                let requestHandler = VNImageRequestHandler(cgImage: image.cgImage!, options: [:])
-
-                let request = VNRecognizeTextRequest { request, _ in
-                    guard let observations = request.results as? [VNRecognizedTextObservation] else {
-                        NCActivityIndicator.shared.stop()
-                        return
-                    }
-                    for observation in observations {
-                        guard let textLine = observation.topCandidates(1).first else {
-                            continue
-                        }
-
-                        textFile += textLine.string
-                        textFile += "\n"
-                    }
-                }
-
-                request.recognitionLevel = .accurate
-                request.usesLanguageCorrection = true
-                try? requestHandler.perform([request])
-            }
-
-            do {
-                try textFile.write(to: fileUrl, atomically: true, encoding: .utf8)
-            } catch {
-                NCActivityIndicator.shared.stop()
-                let error = NKError(errorCode: NCGlobal.shared.errorCreationFile, errorDescription: "_error_creation_file_")
-                NCContentPresenter.shared.showError(error: error)
-                return
-            }
-        }
-
-        if fileType == "PDF" {
-
-            let pdfData = NSMutableData()
-
-            if !password.isEmpty {
-                for char in password.unicodeScalars {
-                    if !char.isASCII {
-                        NCActivityIndicator.shared.stop()
-                        let error = NKError(errorCode: NCGlobal.shared.errorForbidden, errorDescription: "_password_ascii_")
-                        NCContentPresenter.shared.showError(error: error)
-                        return
-                    }
-                }
-                let info: [AnyHashable: Any] = [kCGPDFContextUserPassword as String: password, kCGPDFContextOwnerPassword as String: password]
-                UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, info)
-            } else {
-                UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
-            }
-            var fontColor = UIColor.clear
-#if targetEnvironment(simulator)
-            fontColor = UIColor.red
-#endif
-
-            for var image in self.arrayImages {
-
-                image = changeCompressionImage(image)
-
-                let bounds = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
-
-                if self.form.formRow(withTag: "textRecognition")!.value as! Int == 1 {
-
-                    UIGraphicsBeginPDFPageWithInfo(bounds, nil)
-                    image.draw(in: bounds)
-
-                    let requestHandler = VNImageRequestHandler(cgImage: image.cgImage!, options: [:])
-
-                    let request = VNRecognizeTextRequest { request, _ in
-                        guard let observations = request.results as? [VNRecognizedTextObservation] else {
-                            NCActivityIndicator.shared.stop()
-                            return
-                        }
-                        for observation in observations {
-                            guard let textLine = observation.topCandidates(1).first else {
-                                continue
-                            }
-
-                            var t: CGAffineTransform = CGAffineTransform.identity
-                            t = t.scaledBy(x: image.size.width, y: -image.size.height)
-                            t = t.translatedBy(x: 0, y: -1)
-                            let rect = observation.boundingBox.applying(t)
-                            let text = textLine.string
-
-                            let font = UIFont.systemFont(ofSize: rect.size.height, weight: .regular)
-                            let attributes = self.bestFittingFont(for: text, in: rect, fontDescriptor: font.fontDescriptor, fontColor: fontColor)
-
-                            text.draw(with: rect, options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
-                        }
-                    }
-
-                    request.recognitionLevel = .accurate
-                    request.usesLanguageCorrection = true
-                    try? requestHandler.perform([request])
-
-                } else {
-
-                    UIGraphicsBeginPDFPageWithInfo(bounds, nil)
-                    image.draw(in: bounds)
-                }
-            }
-
-            UIGraphicsEndPDFContext()
-
-            do {
-                try pdfData.write(to: fileUrl, options: .atomic)
-            } catch {
-                print("error catched")
-            }
-        }
-
-        if fileType == "JPG" {
-
-            let image = changeCompressionImage(self.arrayImages[0])
-
-            guard let data = image.jpegData(compressionQuality: CGFloat(0.5)) else {
-                NCActivityIndicator.shared.stop()
-                let error = NKError(errorCode: NCGlobal.shared.errorCreationFile, errorDescription: "_error_creation_file_")
-                NCContentPresenter.shared.showError(error: error)
-                return
-            }
-
-            do {
-                try data.write(to: fileUrl, options: .atomic)
-            } catch {
-                NCActivityIndicator.shared.stop()
-                let error = NKError(errorCode: NCGlobal.shared.errorCreationFile, errorDescription: "_error_creation_file_")
-                NCContentPresenter.shared.showError(error: error)
-                return
-            }
-        }
-        metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNameGenerateExport)
-
-        NCActivityIndicator.shared.stop()
-
-        NCNetworkingProcessUpload.shared.createProcessUploads(metadatas: [metadata], completion: { _ in })
-
-        // Request delete all image scanned
-        let alertController = UIAlertController(title: "", message: NSLocalizedString("_delete_all_scanned_images_", comment: ""), preferredStyle: .alert)
-
-        let actionYes = UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in
-
-            let path = CCUtility.getDirectoryScan()!
-
-            do {
-                let filePaths = try FileManager.default.contentsOfDirectory(atPath: path)
-                for filePath in filePaths {
-                    try FileManager.default.removeItem(atPath: path + "/" + filePath)
-                }
-            } catch let error as NSError {
-                print("Error: \(error.debugDescription)")
-            }
-
-            self.dismiss(animated: true, completion: nil)
-        }
-
-        let actionNo = UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (_: UIAlertAction) in
-            self.dismiss(animated: true, completion: nil)
-        }
-
-        alertController.addAction(actionYes)
-        alertController.addAction(actionNo)
-        self.present(alertController, animated: true, completion: nil)
-    }
-
-    func cancel() {
-
-        self.dismiss(animated: true, completion: nil)
-    }
-
-    @objc func changeDestinationFolder(_ sender: XLFormRowDescriptor) {
-
-        self.deselectFormRow(sender)
-
-        let storyboard = UIStoryboard(name: "NCSelect", bundle: nil)
-        let navigationController = storyboard.instantiateInitialViewController() as! UINavigationController
-        let viewController = navigationController.topViewController as! NCSelect
-
-        viewController.delegate = self
-        viewController.typeOfCommandView = .selectCreateFolder
-        viewController.includeDirectoryE2EEncryption = true
-
-        self.present(navigationController, animated: true, completion: nil)
-    }
-
-    func changeCompressionImage(_ image: UIImage) -> UIImage {
-
-        var compressionQuality: CGFloat = 0.5
-        var baseHeight: Float = 595.2    // A4
-        var baseWidth: Float = 841.8     // A4
-
-        switch quality {
-        case .low:
-            baseHeight *= 1
-            baseWidth *= 1
-            compressionQuality = 0.3
-        case .medium:
-            baseHeight *= 2
-            baseWidth *= 2
-            compressionQuality = 0.6
-        case .high:
-            baseHeight *= 4
-            baseWidth *= 4
-            compressionQuality = 0.9
-        }
-
-        var newHeight = Float(image.size.height)
-        var newWidth = Float(image.size.width)
-        var imgRatio: Float = newWidth / newHeight
-        let baseRatio: Float = baseWidth / baseHeight
-
-        if newHeight > baseHeight || newWidth > baseWidth {
-            if imgRatio < baseRatio {
-                imgRatio = baseHeight / newHeight
-                newWidth = imgRatio * newWidth
-                newHeight = baseHeight
-            } else if imgRatio > baseRatio {
-                imgRatio = baseWidth / newWidth
-                newHeight = imgRatio * newHeight
-                newWidth = baseWidth
-            } else {
-                newHeight = baseHeight
-                newWidth = baseWidth
-            }
-        }
-
-        let rect = CGRect(x: 0.0, y: 0.0, width: CGFloat(newWidth), height: CGFloat(newHeight))
-        UIGraphicsBeginImageContext(rect.size)
-        image.draw(in: rect)
-        let img = UIGraphicsGetImageFromCurrentImageContext()
-        let imageData = img?.jpegData(compressionQuality: CGFloat(compressionQuality))
-        UIGraphicsEndImageContext()
-        return UIImage(data: imageData!) ?? image
-    }
-
-    func bestFittingFont(for text: String, in bounds: CGRect, fontDescriptor: UIFontDescriptor, fontColor: UIColor) -> [NSAttributedString.Key: Any] {
-
-        let constrainingDimension = min(bounds.width, bounds.height)
-        let properBounds = CGRect(origin: .zero, size: bounds.size)
-        var attributes: [NSAttributedString.Key: Any] = [:]
-
-        let infiniteBounds = CGSize(width: CGFloat.infinity, height: CGFloat.infinity)
-        var bestFontSize: CGFloat = constrainingDimension
-
-        // Search font (H)
-        for fontSize in stride(from: bestFontSize, through: 0, by: -1) {
-            let newFont = UIFont(descriptor: fontDescriptor, size: fontSize)
-            attributes[.font] = newFont
-
-            let currentFrame = text.boundingRect(with: infiniteBounds, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attributes, context: nil)
-
-            if properBounds.contains(currentFrame) {
-                bestFontSize = fontSize
-                break
-            }
-        }
-
-        // Search kern (W)
-        let font = UIFont(descriptor: fontDescriptor, size: bestFontSize)
-        attributes = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: fontColor, NSAttributedString.Key.kern: 0] as [NSAttributedString.Key: Any]
-        for kern in stride(from: 0, through: 100, by: 0.1) {
-            let attributesTmp = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: fontColor, NSAttributedString.Key.kern: kern] as [NSAttributedString.Key: Any]
-            let size = text.size(withAttributes: attributesTmp).width
-            if size <= bounds.width {
-                attributes = attributesTmp
-            } else {
-                break
-            }
-        }
-
-        return attributes
-    }
-
-}
-
-class NCCreateScanDocument: NSObject, VNDocumentCameraViewControllerDelegate {
-    @objc static let shared: NCCreateScanDocument = {
-        let instance = NCCreateScanDocument()
-        return instance
-    }()
-
-    var viewController: UIViewController?
-
-    func openScannerDocument(viewController: UIViewController) {
-
-        self.viewController = viewController
-
-        guard VNDocumentCameraViewController.isSupported else { return }
-
-        let controller = VNDocumentCameraViewController()
-        controller.delegate = self
-
-        self.viewController?.present(controller, animated: true)
-    }
-
-    func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
-
-        for pageNumber in 0..<scan.pageCount {
-            let fileName = CCUtility.createFileName("scan.png", fileDate: Date(), fileType: PHAssetMediaType.image, keyFileName: NCGlobal.shared.keyFileNameMask, keyFileNameType: NCGlobal.shared.keyFileNameType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal, forcedNewFileName: true)!
-            let fileNamePath = CCUtility.getDirectoryScan() + "/" + fileName
-            let image = scan.imageOfPage(at: pageNumber)
-            do {
-                try image.pngData()?.write(to: NSURL.fileURL(withPath: fileNamePath))
-            } catch { }
-        }
-
-        controller.dismiss(animated: true) {
-            if let viewController = self.viewController as? NCScan {
-                viewController.loadImage()
-            } else {
-                let storyboard = UIStoryboard(name: "NCScan", bundle: nil)
-                let controller = storyboard.instantiateInitialViewController()!
-
-                controller.modalPresentationStyle = UIModalPresentationStyle.pageSheet
-                self.viewController?.present(controller, animated: true, completion: nil)
-            }
-        }
-    }
-
-    func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
-        controller.dismiss(animated: true, completion: nil)
-    }
-}

+ 0 - 108
iOSClient/Main/Create cloud/NCUploadScanDocument.swift

@@ -1,108 +0,0 @@
-//
-//  NCUploadScanDocument.swift
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 28/12/22.
-//  Copyright © 2022 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import SwiftUI
-import NextcloudKit
-import Vision
-import VisionKit
-import Photos
-import PDFKit
-
-// MARK: - Preview / Test
-
-struct NCUploadScanDocumentTest: View {
-
-    @State private var currentValue = 1.0
-
-    var body: some View {
-
-        VStack {
-            List {
-                Section(header: Text(NSLocalizedString("_save_path_", comment: ""))) {
-                    HStack {
-                        Label {
-                            Text("/")
-                                .frame(maxWidth: .infinity, alignment: .trailing)
-                        } icon: {
-                            Image("folder")
-                                .renderingMode(.template)
-                                .resizable()
-                                .scaledToFit()
-                                .frame(width: NCBrandSettings.shared.settingsSizeImage, height: NCBrandSettings.shared.settingsSizeImage)
-                                .foregroundColor(Color(NCBrandColor.shared.brand))
-                        }
-
-                        Spacer()
-                    }
-                    .contentShape(Rectangle())
-                    .onTapGesture {
-                        //
-                    }
-                }
-
-                Section(header: Text(NSLocalizedString("_quality_image_title_", comment: ""))) {
-                    VStack {
-                        Text("Current slider value")
-                        Slider(value: $currentValue, in: 0...3, step: 1) { didChange in
-                            //
-                        }
-                        .accentColor(Color(NCBrandColor.shared.brand))
-                    }
-                }
-
-                Section(header: Text(NSLocalizedString("_preview_", comment: ""))) {
-                    let fileUrl = Bundle.main.url(forResource: "Reasons to use Nextcloud", withExtension: "pdf")!
-                    PDFKitRepresentedView(fileUrl)
-                        .frame(width: .infinity, height: 200)
-                }
-            }
-        }
-    }
-}
-
-struct PDFKitRepresentedView: UIViewRepresentable {
-
-    let url: URL
-    init(_ url: URL) {
-        self.url = url
-    }
-
-    func makeUIView(context: UIViewRepresentableContext<PDFKitRepresentedView>) -> PDFKitRepresentedView.UIViewType {
-        let pdfView = PDFView()
-        pdfView.document = PDFDocument(url: self.url)
-        pdfView.autoScales = true
-        pdfView.backgroundColor = .clear
-        return pdfView
-    }
-
-    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PDFKitRepresentedView>) {
-
-    }
-}
-
-struct NCUploadScanDocument_Previews: PreviewProvider {
-    static var previews: some View {
-        // let account = (UIApplication.shared.delegate as! AppDelegate).account
-        NCUploadScanDocumentTest()
-    }
-}

+ 1 - 1
iOSClient/Menu/AppDelegate+Menu.swift

@@ -88,7 +88,7 @@ extension AppDelegate {
             NCMenuAction(
                 title: NSLocalizedString("_scans_document_", comment: ""), icon: NCUtility.shared.loadImage(named: "scan"), action: { _ in
                     if let viewController = appDelegate.window?.rootViewController {
-                        NCCreateScanDocument.shared.openScannerDocument(viewController: viewController)
+                        NCDocumentCamera.shared.openScannerDocument(viewController: viewController)
                     }
                 }
             )

+ 2 - 0
iOSClient/NCGlobal.swift

@@ -374,6 +374,8 @@ class NCGlobal: NSObject {
     let notificationCenterPlayMedia                             = "playMedia"
     let notificationCenterPauseMedia                            = "pauseMedia"
 
+    let notificationCenterDismissScanDocument                   = "dismissScanDocument"
+
     // TIP
     //
     let tipNCViewerPDFThumbnail                                 = "tipncviewerpdfthumbnail"

+ 65 - 0
iOSClient/Scan document/NCDocumentCamera.swift

@@ -0,0 +1,65 @@
+//
+//  NCDocumentCamera.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 03/01/23.
+//  Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+import VisionKit
+
+class NCDocumentCamera: NSObject, VNDocumentCameraViewControllerDelegate {
+    static let shared: NCDocumentCamera = {
+        let instance = NCDocumentCamera()
+        return instance
+    }()
+
+    var viewController: UIViewController?
+
+    func openScannerDocument(viewController: UIViewController) {
+
+        self.viewController = viewController
+
+        guard VNDocumentCameraViewController.isSupported else { return }
+
+        let controller = VNDocumentCameraViewController()
+        controller.delegate = self
+
+        self.viewController?.present(controller, animated: true)
+    }
+
+    func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
+
+        for pageNumber in 0..<scan.pageCount {
+            let fileName = CCUtility.createFileName("scan.png",
+                                                    fileDate: Date(),
+                                                    fileType: PHAssetMediaType.image,
+                                                    keyFileName: NCGlobal.shared.keyFileNameMask,
+                                                    keyFileNameType: NCGlobal.shared.keyFileNameType,
+                                                    keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal,
+                                                    forcedNewFileName: true)!
+            let fileNamePath = CCUtility.getDirectoryScan() + "/" + fileName
+            let image = scan.imageOfPage(at: pageNumber)
+            do {
+                try image.pngData()?.write(to: NSURL.fileURL(withPath: fileNamePath))
+            } catch { }
+        }
+
+        controller.dismiss(animated: true) {
+            if let viewController = self.viewController as? NCScan {
+                viewController.loadImage()
+            } else {
+                let storyboard = UIStoryboard(name: "NCScan", bundle: nil)
+                let controller = storyboard.instantiateInitialViewController()!
+
+                controller.modalPresentationStyle = UIModalPresentationStyle.pageSheet
+                self.viewController?.present(controller, animated: true, completion: nil)
+            }
+        }
+    }
+
+    func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
+        controller.dismiss(animated: true, completion: nil)
+    }
+}

+ 0 - 0
iOSClient/ScanDocument/NCScan+CollectionView.swift → iOSClient/Scan document/NCScan+CollectionView.swift


+ 3 - 3
iOSClient/ScanDocument/NCScan.storyboard → iOSClient/Scan document/NCScan.storyboard

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bdK-eL-mz4">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bdK-eL-mz4">
     <device id="retina4_7" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -250,7 +250,7 @@
             <objects>
                 <navigationController automaticallyAdjustsScrollViewInsets="NO" modalPresentationStyle="fullScreen" id="bdK-eL-mz4" sceneMemberID="viewController">
                     <toolbarItems/>
-                    <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" translucent="NO" id="xl6-fB-rBw">
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="xl6-fB-rBw">
                         <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
                         <autoresizingMask key="autoresizingMask"/>
                     </navigationBar>

+ 9 - 3
iOSClient/ScanDocument/NCScan.swift → iOSClient/Scan document/NCScan.swift

@@ -111,6 +111,8 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
         collectionViewSource.reloadData()
         collectionViewDestination.reloadData()
 
+        NotificationCenter.default.addObserver(self, selector: #selector(dismiss(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDismissScanDocument), object: nil)
+
         loadImage()
     }
 
@@ -156,6 +158,10 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
         return false
     }
 
+    @objc func dismiss(_ notification: NSNotification) {
+        self.dismiss(animated: true, completion: nil)
+    }
+
     @IBAction func cancelAction(sender: UIBarButtonItem) {
         self.dismiss(animated: true, completion: nil)
     }
@@ -171,8 +177,8 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
                 images.append(filter(image: image)!)
             }
 
-            let formViewController = NCCreateFormUploadScanDocument(serverUrl: serverUrl, arrayImages: images)
-            self.navigationController?.pushViewController(formViewController, animated: true)
+            let  vc = NCHostingUploadScanDocumentView().makeShipDetailsUI(images: images, userBaseUrl: appDelegate, serverUrl: serverUrl)
+            self.navigationController?.pushViewController(vc, animated: true)
         }
     }
 
@@ -181,7 +187,7 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
         // TIP
         dismissTip()
 
-        NCCreateScanDocument.shared.openScannerDocument(viewController: self)
+        NCDocumentCamera.shared.openScannerDocument(viewController: self)
     }
 
     @IBAction func transferDown(sender: UIButton) {

+ 0 - 0
iOSClient/ScanDocument/NCScanCell.swift → iOSClient/Scan document/NCScanCell.swift


+ 623 - 0
iOSClient/Scan document/NCUploadScanDocument.swift

@@ -0,0 +1,623 @@
+//
+//  NCUploadScanDocument.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 28/12/22.
+//  Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import SwiftUI
+import NextcloudKit
+import Vision
+import VisionKit
+import Photos
+import PDFKit
+
+class NCHostingUploadScanDocumentView: NSObject {
+
+    @objc func makeShipDetailsUI(images: [UIImage], userBaseUrl: NCUserBaseUrl, serverUrl: String) -> UIViewController {
+
+        let uploadScanDocument = NCUploadScanDocument(images: images, userBaseUrl: userBaseUrl, serverUrl: serverUrl)
+        let details = UploadScanDocumentView(uploadScanDocument)
+        let vc = UIHostingController(rootView: details)
+        vc.title = NSLocalizedString("_save_", comment: "")
+        return vc
+    }
+}
+
+// MARK: - Class
+
+class NCUploadScanDocument: ObservableObject {
+
+    internal var userBaseUrl: NCUserBaseUrl
+    internal var serverUrl: String
+    internal var metadata = tableMetadata()
+    internal var images: [UIImage]
+
+    internal var password: String = ""
+    internal var isTextRecognition: Bool = false
+    internal var quality: Double = 0
+    internal var removeAllFiles: Bool = false
+
+    @Published var showHUD: Bool = false
+
+    init(images: [UIImage], userBaseUrl: NCUserBaseUrl, serverUrl: String) {
+        self.images = images
+        self.userBaseUrl = userBaseUrl
+        self.serverUrl = serverUrl
+    }
+
+    func save(fileName: String, password: String = "", isTextRecognition: Bool = false, removeAllFiles: Bool, quality: Double, completion: @escaping (_ openConflictViewController: Bool, _ error: Bool) -> Void) {
+
+        self.password = password
+        self.isTextRecognition = isTextRecognition
+        self.quality = quality
+        self.removeAllFiles = removeAllFiles
+
+        metadata = NCManageDatabase.shared.createMetadata(account: userBaseUrl.account,
+                                                          user: userBaseUrl.user,
+                                                          userId: userBaseUrl.userId,
+                                                          fileName: fileName,
+                                                          fileNameView: fileName,
+                                                          ocId: UUID().uuidString,
+                                                          serverUrl: serverUrl,
+                                                          urlBase: userBaseUrl.urlBase,
+                                                          url: "",
+                                                          contentType: "")
+
+        metadata.session = NCNetworking.shared.sessionIdentifierBackground
+        metadata.sessionSelector = NCGlobal.shared.selectorUploadFile
+        metadata.status = NCGlobal.shared.metadataStatusWaitUpload
+
+        if NCManageDatabase.shared.getMetadataConflict(account: userBaseUrl.account, serverUrl: serverUrl, fileNameView: fileName) != nil {
+            completion(true, false)
+        } else {
+            createPDF(metadata: metadata) { error in
+                if !error {
+                    completion(false, false)
+                }
+            }
+        }
+    }
+
+    func createPDF(metadata: tableMetadata, completion: @escaping (_ error: Bool) -> Void) {
+
+        DispatchQueue.global().async {
+            let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
+            let pdfData = NSMutableData()
+
+            if self.password.isEmpty {
+                UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
+            } else {
+                for char in self.password.unicodeScalars {
+                    if !char.isASCII {
+                        let error = NKError(errorCode: NCGlobal.shared.errorForbidden, errorDescription: "_password_ascii_")
+                        NCContentPresenter.shared.showError(error: error)
+                        return DispatchQueue.main.async { completion(true) }
+                    }
+                }
+                let info: [AnyHashable: Any] = [kCGPDFContextUserPassword as String: self.password, kCGPDFContextOwnerPassword as String: self.password]
+                UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, info)
+            }
+
+            for image in self.images {
+                self.drawImage(image: image, quality: self.quality, isTextRecognition: self.isTextRecognition, fontColor: UIColor.clear)
+            }
+
+            UIGraphicsEndPDFContext()
+
+            do {
+                try pdfData.write(to: URL(fileURLWithPath: fileNamePath), options: .atomic)
+                metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
+                NCNetworkingProcessUpload.shared.createProcessUploads(metadatas: [metadata], completion: { _ in })
+                if self.removeAllFiles {
+                    let path = CCUtility.getDirectoryScan()!
+                    let filePaths = try FileManager.default.contentsOfDirectory(atPath: path)
+                    for filePath in filePaths {
+                        try FileManager.default.removeItem(atPath: path + "/" + filePath)
+                    }
+                }
+            } catch {
+                print("Error: \(error)")
+            }
+
+            DispatchQueue.main.async { completion(false) }
+        }
+    }
+
+    func createPDFPreview(quality: Double, isTextRecognition: Bool, completion: @escaping (_ data: Data) -> Void) {
+
+        DispatchQueue.global().async {
+            if let image = self.images.first {
+
+                let pdfData = NSMutableData()
+
+                UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
+
+                self.drawImage(image: image, quality: quality, isTextRecognition: isTextRecognition, fontColor: UIColor.red)
+
+                UIGraphicsEndPDFContext()
+
+                DispatchQueue.main.async { completion(pdfData as Data) }
+
+            } else {
+
+                let url = Bundle.main.url(forResource: "Reasons to use Nextcloud", withExtension: "pdf")!
+                let data = try? Data(contentsOf: url)
+
+                DispatchQueue.main.async { completion(data!) }
+            }
+        }
+    }
+
+    func fileName(_ fileName: String) -> String {
+
+        let fileName = fileName.trimmingCharacters(in: .whitespacesAndNewlines)
+        guard !fileName.isEmpty, fileName != ".", fileName.lowercased() != ".pdf" else { return "" }
+
+        let ext = (fileName as NSString).pathExtension.uppercased()
+        if ext.isEmpty {
+            return fileName + ".pdf"
+        } else {
+            return (fileName as NSString).deletingPathExtension + ".pdf"
+        }
+    }
+
+    private func changeCompressionImage(_ image: UIImage, quality: Double) -> UIImage {
+
+        var compressionQuality: CGFloat = 0.0
+        var baseHeight: Float = 595.2    // A4
+        var baseWidth: Float = 841.8     // A4
+
+        switch quality {
+        case 0:
+            baseHeight *= 2
+            baseWidth *= 2
+            compressionQuality = 0.3
+        case 1:
+            baseHeight *= 3
+            baseWidth *= 3
+            compressionQuality = 0.4
+        case 2:
+            baseHeight *= 4
+            baseWidth *= 4
+            compressionQuality = 0.5
+        case 3:
+            baseHeight *= 5
+            baseWidth *= 5
+            compressionQuality = 0.6
+        case 4:
+            baseHeight = Float(image.size.height)
+            baseWidth = Float(image.size.width)
+            compressionQuality = 0.6
+        default:
+            break
+        }
+
+        var newHeight = Float(image.size.height)
+        var newWidth = Float(image.size.width)
+        var imgRatio: Float = newWidth / newHeight
+        let baseRatio: Float = baseWidth / baseHeight
+
+        if newHeight > baseHeight || newWidth > baseWidth {
+            if imgRatio < baseRatio {
+                imgRatio = baseHeight / newHeight
+                newWidth = imgRatio * newWidth
+                newHeight = baseHeight
+            } else if imgRatio > baseRatio {
+                imgRatio = baseWidth / newWidth
+                newHeight = imgRatio * newHeight
+                newWidth = baseWidth
+            } else {
+                newHeight = baseHeight
+                newWidth = baseWidth
+            }
+        }
+
+        let rect = CGRect(x: 0.0, y: 0.0, width: CGFloat(newWidth), height: CGFloat(newHeight))
+        UIGraphicsBeginImageContext(rect.size)
+        image.draw(in: rect)
+        let img = UIGraphicsGetImageFromCurrentImageContext()
+        let imageData = img?.jpegData(compressionQuality: CGFloat(compressionQuality))
+        UIGraphicsEndImageContext()
+        if let imageData = imageData, let image = UIImage(data: imageData) {
+            return image
+        }
+        return image
+    }
+
+    private func bestFittingFont(for text: String, in bounds: CGRect, fontDescriptor: UIFontDescriptor, fontColor: UIColor) -> [NSAttributedString.Key: Any] {
+
+        let constrainingDimension = min(bounds.width, bounds.height)
+        let properBounds = CGRect(origin: .zero, size: bounds.size)
+        var attributes: [NSAttributedString.Key: Any] = [:]
+
+        let infiniteBounds = CGSize(width: CGFloat.infinity, height: CGFloat.infinity)
+        var bestFontSize: CGFloat = constrainingDimension
+
+        // Search font (H)
+        for fontSize in stride(from: bestFontSize, through: 0, by: -1) {
+            let newFont = UIFont(descriptor: fontDescriptor, size: fontSize)
+            attributes[.font] = newFont
+
+            let currentFrame = text.boundingRect(with: infiniteBounds, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attributes, context: nil)
+
+            if properBounds.contains(currentFrame) {
+                bestFontSize = fontSize
+                break
+            }
+        }
+
+        // Search kern (W)
+        let font = UIFont(descriptor: fontDescriptor, size: bestFontSize)
+        attributes = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: fontColor, NSAttributedString.Key.kern: 0] as [NSAttributedString.Key: Any]
+        for kern in stride(from: 0, through: 100, by: 0.1) {
+            let attributesTmp = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: fontColor, NSAttributedString.Key.kern: kern] as [NSAttributedString.Key: Any]
+            let size = text.size(withAttributes: attributesTmp).width
+            if size <= bounds.width {
+                attributes = attributesTmp
+            } else {
+                break
+            }
+        }
+
+        return attributes
+    }
+
+    private func drawImage(image: UIImage, quality: Double, isTextRecognition: Bool, fontColor: UIColor) {
+
+        let image = changeCompressionImage(image, quality: quality)
+        let bounds = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
+
+        if isTextRecognition {
+
+            UIGraphicsBeginPDFPageWithInfo(bounds, nil)
+            image.draw(in: bounds)
+
+            let requestHandler = VNImageRequestHandler(cgImage: image.cgImage!, options: [:])
+
+            let request = VNRecognizeTextRequest { request, _ in
+                guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
+                for observation in observations {
+                    guard let textLine = observation.topCandidates(1).first else { continue }
+
+                    var t: CGAffineTransform = CGAffineTransform.identity
+                    t = t.scaledBy(x: image.size.width, y: -image.size.height)
+                    t = t.translatedBy(x: 0, y: -1)
+                    let rect = observation.boundingBox.applying(t)
+                    let text = textLine.string
+
+                    let font = UIFont.systemFont(ofSize: rect.size.height, weight: .regular)
+                    let attributes = self.bestFittingFont(for: text, in: rect, fontDescriptor: font.fontDescriptor, fontColor: fontColor)
+
+                    text.draw(with: rect, options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
+                }
+            }
+
+            request.recognitionLevel = .accurate
+            request.usesLanguageCorrection = true
+            try? requestHandler.perform([request])
+
+        } else {
+
+            UIGraphicsBeginPDFPageWithInfo(bounds, nil)
+            image.draw(in: bounds)
+        }
+    }
+}
+
+// MARK: - Delegate
+
+extension NCUploadScanDocument: NCSelectDelegate {
+
+    func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], overwrite: Bool, copy: Bool, move: Bool) {
+
+        if let serverUrl = serverUrl {
+            CCUtility.setDirectoryScanDocument(serverUrl)
+            self.serverUrl = serverUrl
+        }
+    }
+}
+
+extension NCUploadScanDocument: NCCreateFormUploadConflictDelegate {
+
+    func dismissCreateFormUploadConflict(metadatas: [tableMetadata]?) {
+
+        if let metadata = metadatas?.first {
+            self.showHUD.toggle()
+            createPDF(metadata: metadata) { error in
+                if !error {
+                    self.showHUD.toggle()
+                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDismissScanDocument)
+                }
+            }
+        }
+    }
+}
+
+// MARK: - View
+
+struct UploadScanDocumentView: View {
+
+    @State var fileName = "Scan"
+    @State var password: String = ""
+    @State var isSecuredPassword: Bool = true
+    @State var isTextRecognition: Bool = CCUtility.getTextRecognitionStatus()
+    @State var quality = CCUtility.getQualityScanDocument()
+    @State var removeAllFiles: Bool = CCUtility.getDeleteAllScanImages()
+    @State var isPresentedSelect = false
+    @State var isPresentedUploadConflict = false
+
+    var metadatasConflict: [tableMetadata] = []
+
+    @ObservedObject var uploadScanDocument: NCUploadScanDocument
+
+    init(_ uploadScanDocument: NCUploadScanDocument) {
+        self.uploadScanDocument = uploadScanDocument
+    }
+
+    var body: some View {
+
+        GeometryReader { geo in
+            ZStack(alignment: .top) {
+                List {
+                    Section(header: Text(NSLocalizedString("_file_creation_", comment: ""))) {
+                        HStack {
+                            Label {
+                                if NCUtilityFileSystem.shared.getHomeServer(urlBase: uploadScanDocument.userBaseUrl.urlBase, userId: uploadScanDocument.userBaseUrl.userId) == uploadScanDocument.serverUrl {
+                                    Text("/")
+                                        .frame(maxWidth: .infinity, alignment: .trailing)
+                                } else {
+                                    Text((uploadScanDocument.serverUrl as NSString).lastPathComponent)
+                                        .frame(maxWidth: .infinity, alignment: .trailing)
+                                }
+                            } icon: {
+                                Image("folder")
+                                    .renderingMode(.template)
+                                    .resizable()
+                                    .scaledToFit()
+                                    .foregroundColor(Color(NCBrandColor.shared.brand))
+                            }
+                        }
+                        .contentShape(Rectangle())
+                        .onTapGesture {
+                            isPresentedSelect = true
+                        }
+                        .complexModifier { view in
+                            if #available(iOS 16, *) {
+                                view.alignmentGuide(.listRowSeparatorLeading) { _ in
+                                    return 0
+                                }
+                            }
+                        }
+
+                        HStack {
+                            Text(NSLocalizedString("_filename_", comment: ""))
+                            TextField(NSLocalizedString("_enter_filename_", comment: ""), text: $fileName)
+                                .modifier(TextFieldClearButton(text: $fileName))
+                                .multilineTextAlignment(.trailing)
+                        }
+
+                        HStack {
+                            Group {
+                                Text(NSLocalizedString("_password_", comment: ""))
+                                if isSecuredPassword {
+                                    SecureField(NSLocalizedString("_enter_password_", comment: ""), text: $password)
+                                        .multilineTextAlignment(.trailing)
+                                } else {
+                                    TextField(NSLocalizedString("_enter_password_", comment: ""), text: $password)
+                                        .multilineTextAlignment(.trailing)
+                                }
+                            }
+                            Button(action: {
+                                isSecuredPassword.toggle()
+                            }) {
+                                Image(systemName: self.isSecuredPassword ? "eye.slash" : "eye")
+                                    .foregroundColor(Color(UIColor.opaqueSeparator))
+                            }
+                            .buttonStyle(BorderlessButtonStyle())
+                        }
+
+                        HStack {
+                            Toggle(NSLocalizedString("_text_recognition_", comment: ""), isOn: $isTextRecognition)
+                                .toggleStyle(SwitchToggleStyle(tint: Color(NCBrandColor.shared.brand)))
+                                .onChange(of: isTextRecognition) { newValue in
+                                    CCUtility.setTextRecognitionStatus(newValue)
+                                }
+                        }
+                    }
+
+                    VStack(spacing: 20) {
+
+                        Toggle(NSLocalizedString("_delete_all_scanned_images_", comment: ""), isOn: $removeAllFiles)
+                            .toggleStyle(SwitchToggleStyle(tint: Color(NCBrandColor.shared.brand)))
+                            .onChange(of: removeAllFiles) { newValue in
+                                CCUtility.setDeleteAllScanImages(newValue)
+
+                            }
+
+                        Button(NSLocalizedString("_save_", comment: "")) {
+                            let fileName = uploadScanDocument.fileName(fileName)
+                            if !fileName.isEmpty {
+                                uploadScanDocument.showHUD.toggle()
+                                uploadScanDocument.save(fileName: fileName, password: password, isTextRecognition: isTextRecognition, removeAllFiles: removeAllFiles, quality: quality) { openConflictViewController, error in
+                                    uploadScanDocument.showHUD.toggle()
+                                    if error {
+                                        print("error")
+                                    } else if openConflictViewController {
+                                        isPresentedUploadConflict = true
+                                    } else {
+                                        NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDismissScanDocument)
+                                    }
+                                }
+                            }
+                        }
+                        .buttonStyle(ButtonUploadScanDocumenStyle(disabled: fileName.isEmpty))
+                    }
+
+                    Section(header: Text(NSLocalizedString("_quality_image_title_", comment: ""))) {
+
+                        VStack {
+                            Slider(value: $quality, in: 0...4, step: 1, onEditingChanged: { touch in
+                                if !touch {
+                                    CCUtility.setQualityScanDocument(quality)
+                                }
+                            })
+                            .accentColor(Color(NCBrandColor.shared.brand))
+                        }
+                        PDFKitRepresentedView(quality: $quality, isTextRecognition: $isTextRecognition, uploadScanDocument: uploadScanDocument)
+                            .frame(maxWidth: .infinity, minHeight: geo.size.height / 2)
+                    }
+                    .complexModifier { view in
+                        if #available(iOS 15, *) {
+                            view.listRowSeparator(.hidden)
+                        }
+                    }
+                }
+                HUDView(showHUD: $uploadScanDocument.showHUD, textLabel: NSLocalizedString("_wait_", comment: ""), image: "doc.badge.arrow.up")
+                    .offset(y: uploadScanDocument.showHUD ? 0 : -200)
+                    .animation(.easeOut)
+            }
+        }
+        .background(Color(UIColor.systemGroupedBackground))
+        .sheet(isPresented: $isPresentedSelect) {
+            NCSelectRepresentedView(uploadScanDocument: uploadScanDocument)
+        }
+        .sheet(isPresented: $isPresentedUploadConflict) {
+            NCUploadConflictRepresentedView(uploadScanDocument: uploadScanDocument)
+        }.onTapGesture {
+            dismissKeyboard()
+        }
+    }
+
+    func dismissKeyboard() {
+        UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.endEditing(true)
+    }
+}
+
+struct TextFieldClearButton: ViewModifier {
+    @Binding var text: String
+
+    func body(content: Content) -> some View {
+        HStack {
+            content
+            if !text.isEmpty {
+                Button(
+                    action: { self.text = "" },
+                    label: {
+                        Image(systemName: "delete.left")
+                            .foregroundColor(Color(UIColor.opaqueSeparator))
+                    }
+                ).buttonStyle(BorderlessButtonStyle())
+            }
+        }
+    }
+}
+
+struct ButtonUploadScanDocumenStyle: ButtonStyle {
+    var disabled = false
+    func makeBody(configuration: Configuration) -> some View {
+        configuration.label
+            .padding(.horizontal, 40)
+            .padding(.vertical, 10)
+            .background(disabled ? Color(UIColor.opaqueSeparator) : Color(NCBrandColor.shared.brand))
+            .foregroundColor(.white)
+            .clipShape(Capsule())
+    }
+}
+
+// MARK: - UIViewControllerRepresentable
+
+struct NCSelectRepresentedView: UIViewControllerRepresentable {
+
+    typealias UIViewControllerType = UINavigationController
+    @ObservedObject var uploadScanDocument: NCUploadScanDocument
+
+    func makeUIViewController(context: Context) -> UINavigationController {
+
+        let storyboard = UIStoryboard(name: "NCSelect", bundle: nil)
+        let navigationController = storyboard.instantiateInitialViewController() as? UINavigationController
+        let viewController = navigationController?.topViewController as? NCSelect
+
+        viewController?.delegate = uploadScanDocument
+        viewController?.typeOfCommandView = .selectCreateFolder
+        viewController?.includeDirectoryE2EEncryption = true
+
+        return navigationController!
+    }
+
+    func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
+    }
+}
+
+struct NCUploadConflictRepresentedView: UIViewControllerRepresentable {
+
+    typealias UIViewControllerType = NCCreateFormUploadConflict
+    @ObservedObject var uploadScanDocument: NCUploadScanDocument
+
+    func makeUIViewController(context: Context) -> NCCreateFormUploadConflict {
+
+        let storyboard = UIStoryboard(name: "NCCreateFormUploadConflict", bundle: nil)
+        let viewController = storyboard.instantiateInitialViewController() as? NCCreateFormUploadConflict
+
+        viewController?.delegate = uploadScanDocument
+        viewController?.textLabelDetailNewFile = NSLocalizedString("_now_", comment: "")
+        viewController?.serverUrl = uploadScanDocument.serverUrl
+        viewController?.metadatasUploadInConflict = [uploadScanDocument.metadata]
+
+        return viewController!
+    }
+
+    func updateUIViewController(_ uiViewController: NCCreateFormUploadConflict, context: Context) {
+    }
+}
+
+struct PDFKitRepresentedView: UIViewRepresentable {
+
+    typealias UIView = PDFView
+    @Binding var quality: Double
+    @Binding var isTextRecognition: Bool
+    @ObservedObject var uploadScanDocument: NCUploadScanDocument
+
+    func makeUIView(context: UIViewRepresentableContext<PDFKitRepresentedView>) -> PDFKitRepresentedView.UIViewType {
+        let pdfView = PDFView()
+        pdfView.autoScales = true
+        pdfView.backgroundColor = .clear
+        pdfView.displayMode = .singlePage
+        pdfView.displayDirection = .vertical
+        return pdfView
+    }
+
+    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PDFKitRepresentedView>) {
+        uploadScanDocument.createPDFPreview(quality: quality, isTextRecognition: isTextRecognition) { data in
+            uiView.document = PDFDocument(data: data)
+            uiView.autoScales = true
+        }
+    }
+}
+
+// MARK: - Preview
+
+struct UploadScanDocumentView_Previews: PreviewProvider {
+    static var previews: some View {
+        if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
+            let uploadScanDocument = NCUploadScanDocument(images: [], userBaseUrl: appDelegate, serverUrl: "ABCD")
+            UploadScanDocumentView(uploadScanDocument)
+        }
+    }
+}

+ 0 - 12
iOSClient/Settings/NCManageE2EE.swift

@@ -175,12 +175,10 @@ struct NCViewE2EE: View {
                     Section(header: Text(""), footer: Text(manageE2EE.statusOfService + "\n\n" + "End-to-End Encryption " + versionE2EE)) {
                         Label {
                             Text(NSLocalizedString("_e2e_settings_activated_", comment: ""))
-                                .font(NCBrandSettings.shared.settingsFont)
                         } icon: {
                             Image(systemName: "checkmark.circle.fill")
                                 .resizable()
                                 .scaledToFit()
-                                .frame(width: NCBrandSettings.shared.settingsSizeImage, height: NCBrandSettings.shared.settingsSizeImage)
                                 .foregroundColor(.green)
                         }
                     }
@@ -188,12 +186,10 @@ struct NCViewE2EE: View {
                     HStack {
                         Label {
                             Text(NSLocalizedString("_e2e_settings_read_passphrase_", comment: ""))
-                                .font(NCBrandSettings.shared.settingsFont)
                         } icon: {
                             Image(systemName: "eye")
                                 .resizable()
                                 .scaledToFit()
-                                .frame(width: NCBrandSettings.shared.settingsSizeImage, height: NCBrandSettings.shared.settingsSizeImage)
                                 .foregroundColor(Color(UIColor.systemGray))
                         }
                         Spacer()
@@ -210,12 +206,10 @@ struct NCViewE2EE: View {
                     HStack {
                         Label {
                             Text(NSLocalizedString("_e2e_settings_remove_", comment: ""))
-                                .font(NCBrandSettings.shared.settingsFont)
                         } icon: {
                             Image(systemName: "trash.circle")
                                 .resizable()
                                 .scaledToFit()
-                                .frame(width: NCBrandSettings.shared.settingsSizeImage, height: NCBrandSettings.shared.settingsSizeImage)
                                 .foregroundColor(Color.red)
                         }
                         Spacer()
@@ -242,12 +236,10 @@ struct NCViewE2EE: View {
                         HStack {
                             Label {
                                 Text(NSLocalizedString("_e2e_settings_start_", comment: ""))
-                                    .font(NCBrandSettings.shared.settingsFont)
                             } icon: {
                                 Image(systemName: "play.circle")
                                     .resizable()
                                     .scaledToFit()
-                                    .frame(width: NCBrandSettings.shared.settingsSizeImage, height: NCBrandSettings.shared.settingsSizeImage)
                                     .foregroundColor(.green)
                             }
                             Spacer()
@@ -281,12 +273,10 @@ struct DeleteCerificateSection: View {
             HStack {
                 Label {
                     Text("Delete Certificate")
-                        .font(NCBrandSettings.shared.settingsFont)
                 } icon: {
                     Image(systemName: "exclamationmark.triangle")
                         .resizable()
                         .scaledToFit()
-                        .frame(width: NCBrandSettings.shared.settingsSizeImage, height: NCBrandSettings.shared.settingsSizeImage)
                         .foregroundColor(Color(UIColor.systemGray))
                 }
                 Spacer()
@@ -305,12 +295,10 @@ struct DeleteCerificateSection: View {
             HStack {
                 Label {
                     Text("Delete PrivateKey")
-                        .font(NCBrandSettings.shared.settingsFont)
                 } icon: {
                     Image(systemName: "exclamationmark.triangle")
                         .resizable()
                         .scaledToFit()
-                        .frame(width: NCBrandSettings.shared.settingsSizeImage, height: NCBrandSettings.shared.settingsSizeImage)
                         .foregroundColor(Color(UIColor.systemGray))
                 }
                 Spacer()

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

@@ -176,6 +176,7 @@
 "_automatic_Download_Image_" = "Use images in full resolution";
 "_automatic_Download_Image_footer_" = "When viewing images always download, if not available locally, the images in full resolution";
 "_size_"                    = "Size";
+"_file_size_"               = "Exported file size";
 "_dimension_"               = "Dimension";
 "_duration_"                = "Duration";
 "_model_"                   = "Model";
@@ -287,6 +288,7 @@
 "_acknowledgements_"            = "Acknowledgements";
 "_settings_"                    = "Settings";
 "_passcode_"                    = "Password";
+"_enter_password_"              = "Enter password …";
 "_lock_"                        = "Lock";
 "_lock_active_"                 = "Lock: On";
 "_lock_not_active_"             = "Lock: Off";
@@ -672,6 +674,7 @@
 "_use_folder_auto_upload_"          = "Use the \"Auto upload\" folder as destination";
 "_rename_filename_"                 = "Rename";
 "_filename_"                        = "Filename";
+"_enter_filename_"                  = "Enter filename …";
 "_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";
@@ -730,7 +733,7 @@
 "_file_type_"                       = "File type";
 "_pdf_password_"                    = "PDF Password";
 "_file_creation_"                   = "File creation";
-"_delete_all_scanned_images_"       = "Do you want to delete all scanned images?";
+"_delete_all_scanned_images_"       = "Delete all scanned images";
 "_text_recognition_"                = "Text recognition";
 
 /* The title on the navigation bar of the Scanning screen. */
@@ -913,6 +916,7 @@
 "_calendar_contacts_"       = "Calendar and Contacts";
 "_mobile_config_"           = "Download the configuration profile";
 "_calendar_contacts_footer_"    = "After the downloading you need to go to the Settings app to install it. If a profile is not installed within 8 minutes of downloading it, it is automatically deleted";
+"_preview_"                 = "Preview";
 
 // Video
 "_select_trace_"            = "Select the trace";

+ 8 - 4
iOSClient/Utility/CCUtility.h

@@ -154,10 +154,14 @@
 + (NSString *)getMediaSortDate;
 + (void)setMediaSortDate:(NSString *)value;
 
-+ (NSInteger)getTextRecognitionStatus;
-+ (void)setTextRecognitionStatus:(NSInteger)value;
-+ (NSString *)getDirectoryScanDocuments;
-+ (void)setDirectoryScanDocuments:(NSString *)value;
++ (BOOL)getTextRecognitionStatus;
++ (void)setTextRecognitionStatus:(BOOL)value;
++ (BOOL)getDeleteAllScanImages;
++ (void)setDeleteAllScanImages:(BOOL)value;
++ (NSString *)getDirectoryScanDocument;
++ (void)setDirectoryScanDocument:(NSString *)value;
++ (double)getQualityScanDocument;
++ (void)setQualityScanDocument:(double)value;
 
 + (NSInteger)getLogLevel;
 + (void)setLogLevel:(NSInteger)value;

+ 34 - 12
iOSClient/Utility/CCUtility.m

@@ -593,33 +593,55 @@
     [UICKeyChainStore setString:value forKey:@"mediaSortDate" service:NCGlobal.shared.serviceShareKeyChain];
 }
 
-+ (NSInteger)getTextRecognitionStatus
++ (BOOL)getTextRecognitionStatus
 {
-    NSString *value = [UICKeyChainStore stringForKey:@"textRecognitionStatus" service:NCGlobal.shared.serviceShareKeyChain];
-    
-    if (value == nil) {
-        return 0;
-    } else {
-        return [value integerValue];
-    }
+    return [[UICKeyChainStore stringForKey:@"textRecognitionStatus" service:NCGlobal.shared.serviceShareKeyChain] boolValue];
 }
 
-+ (void)setTextRecognitionStatus:(NSInteger)value
++ (void)setTextRecognitionStatus:(BOOL)value
 {
-    NSString *valueString = [@(value) stringValue];
+    NSString *valueString = (value) ? @"true" : @"false";
     [UICKeyChainStore setString:valueString forKey:@"textRecognitionStatus" service:NCGlobal.shared.serviceShareKeyChain];
 }
 
-+ (NSString *)getDirectoryScanDocuments
++ (BOOL)getDeleteAllScanImages
+{
+    return [[UICKeyChainStore stringForKey:@"deleteAllScanImages" service:NCGlobal.shared.serviceShareKeyChain] boolValue];
+}
+
++ (void)setDeleteAllScanImages:(BOOL)value
+{
+    NSString *valueString = (value) ? @"true" : @"false";
+    [UICKeyChainStore setString:valueString forKey:@"deleteAllScanImages" service:NCGlobal.shared.serviceShareKeyChain];
+}
+
++ (NSString *)getDirectoryScanDocument
 {
     return [UICKeyChainStore stringForKey:@"directoryScanDocuments" service:NCGlobal.shared.serviceShareKeyChain];
 }
 
-+ (void)setDirectoryScanDocuments:(NSString *)value
++ (void)setDirectoryScanDocument:(NSString *)value
 {
     [UICKeyChainStore setString:value forKey:@"directoryScanDocuments" service:NCGlobal.shared.serviceShareKeyChain];
 }
 
++ (double)getQualityScanDocument
+{
+    NSString *value = [UICKeyChainStore stringForKey:@"qualityScanDocument" service:NCGlobal.shared.serviceShareKeyChain];
+
+    if (value == nil) {
+        return 2;
+    } else {
+        return [value doubleValue];
+    }
+}
+
++ (void)setQualityScanDocument:(double)value
+{
+    NSString *valueString = [@(value) stringValue];
+    [UICKeyChainStore setString:valueString forKey:@"qualityScanDocument" service:NCGlobal.shared.serviceShareKeyChain];
+}
+
 + (NSInteger)getLogLevel
 {
     NSString *value = [UICKeyChainStore stringForKey:@"logLevel" service:NCGlobal.shared.serviceShareKeyChain];

+ 96 - 0
iOSClient/Utility/HUDView.swift

@@ -0,0 +1,96 @@
+//
+//  HUDView.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 02/01/23.
+//  Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import SwiftUI
+
+struct HUDView: View {
+
+    @Binding var showHUD: Bool
+    @State var textLabel: String
+    @State var image: String
+
+    var body: some View {
+        Button(action: {
+            withAnimation {
+                self.showHUD = false
+            }
+        }) {
+            Label(textLabel, systemImage: image)
+                .foregroundColor(.gray)
+                .padding(.horizontal, 10)
+                .padding(14)
+                .background(
+                    Blur(style: .systemMaterial)
+                        .clipShape(Capsule())
+                        .shadow(color: Color(.black).opacity(0.22), radius: 12, x: 0, y: 5)
+                    )
+        }.buttonStyle(PlainButtonStyle())
+    }
+}
+
+struct Blur: UIViewRepresentable {
+
+    var style: UIBlurEffect.Style
+
+    func makeUIView(context: Context) -> UIVisualEffectView {
+        return UIVisualEffectView(effect: UIBlurEffect(style: style))
+    }
+
+    func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
+        uiView.effect = UIBlurEffect(style: style)
+    }
+}
+
+struct ContentView: View {
+
+    @State private var showHUD = false
+    @Namespace var hudAnimation
+
+    func dismissHUDAfterTime() {
+        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
+            self.showHUD = false
+        }
+    }
+
+    var body: some View {
+        GeometryReader { geo in
+            ZStack(alignment: .top) {
+                NavigationView {
+                    Button("Save image") {
+                        self.showHUD.toggle()
+                    }
+                    .navigationTitle("Content View")
+                }
+                HUDView(showHUD: $showHUD, textLabel: NSLocalizedString("_wait_", comment: ""), image: "doc.badge.arrow.up")
+                    .offset(y: showHUD ? (geo.size.height / 2) : -200)
+                    .animation(.easeOut)
+            }
+        }
+    }
+}
+
+struct HUDView_Previews: PreviewProvider {
+    static var previews: some View {
+        ContentView()
+    }
+}