Browse Source

Merge pull request #2319 from nextcloud/improvedGUI

Improved GUI
Marino Faggiana 2 years ago
parent
commit
a3cfba3af3

+ 17 - 17
Nextcloud.xcodeproj/project.pbxproj

@@ -96,7 +96,6 @@
 		F70460522499061800BB98A7 /* NotificationCenter+MainThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70460512499061800BB98A7 /* NotificationCenter+MainThread.swift */; };
 		F70460532499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70460512499061800BB98A7 /* NotificationCenter+MainThread.swift */; };
 		F70460542499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70460512499061800BB98A7 /* NotificationCenter+MainThread.swift */; };
-		F704A950296EE1C200D0737A /* Mantis in Frameworks */ = {isa = PBXBuildFile; productRef = F704A94F296EE1C200D0737A /* Mantis */; };
 		F704B5E32430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F704B5E22430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard */; };
 		F704B5E52430AA8000632F5F /* NCCreateFormUploadConflict.swift in Sources */ = {isa = PBXBuildFile; fileRef = F704B5E42430AA8000632F5F /* NCCreateFormUploadConflict.swift */; };
 		F704B5E72430C06700632F5F /* NCCreateFormUploadConflictCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F704B5E62430C06700632F5F /* NCCreateFormUploadConflictCell.xib */; };
@@ -493,6 +492,7 @@
 		F7CBC31C24F78E79004D3812 /* NCSortMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC31B24F78E79004D3812 /* NCSortMenu.swift */; };
 		F7D0F33E264144FC0097D4A3 /* Background.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7D0F33D264144FC0097D4A3 /* Background.xcassets */; };
 		F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */; };
+		F7D56B1A2972405500FA46C4 /* Mantis in Frameworks */ = {isa = PBXBuildFile; productRef = F7D56B192972405500FA46C4 /* Mantis */; };
 		F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */; };
 		F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CA212B25F1333200826ABB /* NCAccountRequest.swift */; };
 		F7D68FCC28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; };
@@ -1259,7 +1259,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				F704A950296EE1C200D0737A /* Mantis in Frameworks */,
+				F7D56B1A2972405500FA46C4 /* Mantis in Frameworks */,
 				F76DA941277B75870082465B /* KTVHTTPCache.xcframework in Frameworks */,
 				F7ED547C25EEA65400956C55 /* QRCodeReader in Frameworks */,
 				F788ECC7263AAAFA00ADC67F /* MarkdownKit in Frameworks */,
@@ -2498,7 +2498,7 @@
 				F734B06528E75C0100E180D5 /* TLPhotoPicker */,
 				F77333872927A72100466E35 /* OpenSSL */,
 				F77BC3EA293E5268005F2B08 /* Swifter */,
-				F704A94F296EE1C200D0737A /* Mantis */,
+				F7D56B192972405500FA46C4 /* Mantis */,
 			);
 			productName = "Crypto Cloud";
 			productReference = F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */;
@@ -2657,7 +2657,7 @@
 				F734B06428E75C0100E180D5 /* XCRemoteSwiftPackageReference "TLPhotoPicker" */,
 				F77333862927A72100466E35 /* XCRemoteSwiftPackageReference "OpenSSL" */,
 				F77BC3E9293E5268005F2B08 /* XCRemoteSwiftPackageReference "swifter" */,
-				F704A94E296EE1C200D0737A /* XCRemoteSwiftPackageReference "Mantis" */,
+				F7D56B182972405400FA46C4 /* XCRemoteSwiftPackageReference "Mantis" */,
 			);
 			productRefGroup = F7F67B9F1A24D27800EE80DA;
 			projectDirPath = "";
@@ -3938,14 +3938,6 @@
 /* End XCConfigurationList section */
 
 /* Begin XCRemoteSwiftPackageReference section */
-		F704A94E296EE1C200D0737A /* XCRemoteSwiftPackageReference "Mantis" */ = {
-			isa = XCRemoteSwiftPackageReference;
-			repositoryURL = "https://github.com/guoyingtao/Mantis.git";
-			requirement = {
-				branch = master;
-				kind = branch;
-			};
-		};
 		F70B86732642CE3B00ED5349 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
 			isa = XCRemoteSwiftPackageReference;
 			repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
@@ -4098,6 +4090,14 @@
 				kind = branch;
 			};
 		};
+		F7D56B182972405400FA46C4 /* XCRemoteSwiftPackageReference "Mantis" */ = {
+			isa = XCRemoteSwiftPackageReference;
+			repositoryURL = "https://github.com/marinofaggiana/Mantis";
+			requirement = {
+				kind = exactVersion;
+				version = 1.0.0;
+			};
+		};
 		F7ED547A25EEA65400956C55 /* XCRemoteSwiftPackageReference "QRCodeReader" */ = {
 			isa = XCRemoteSwiftPackageReference;
 			repositoryURL = "https://github.com/yannickl/QRCodeReader.swift";
@@ -4109,11 +4109,6 @@
 /* End XCRemoteSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
-		F704A94F296EE1C200D0737A /* Mantis */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = F704A94E296EE1C200D0737A /* XCRemoteSwiftPackageReference "Mantis" */;
-			productName = Mantis;
-		};
 		F70B86742642CE3B00ED5349 /* FirebaseCrashlytics */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = F70B86732642CE3B00ED5349 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
@@ -4374,6 +4369,11 @@
 			package = F7BB7E4527A18C56009B9F29 /* XCRemoteSwiftPackageReference "Parchment" */;
 			productName = Parchment;
 		};
+		F7D56B192972405500FA46C4 /* Mantis */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = F7D56B182972405400FA46C4 /* XCRemoteSwiftPackageReference "Mantis" */;
+			productName = Mantis;
+		};
 		F7EBCDCE277B81FF00A4EF67 /* UICKeyChainStore */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = F76DA964277B76F10082465B /* XCRemoteSwiftPackageReference "UICKeyChainStore" */;

+ 1 - 0
iOSClient/GUI/ComponentView.swift

@@ -54,5 +54,6 @@ struct ButtonRounded: ButtonStyle {
             .background(disabled ? Color(UIColor.placeholderText) : Color(NCBrandColor.shared.brand))
             .foregroundColor(disabled ? Color(UIColor.placeholderText) : Color(NCBrandColor.shared.brandText))
             .clipShape(Capsule())
+            .opacity(configuration.isPressed ? 0.5 : 1.0)
     }
 }

+ 1 - 1
iOSClient/GUI/HUDView.swift

@@ -36,7 +36,7 @@ struct HUDView: View {
             }
         }) {
             Label(textLabel, systemImage: image)
-                .foregroundColor(Color(NCBrandColor.shared.brandText))
+                .foregroundColor(.white)
                 .padding(.horizontal, 10)
                 .padding(14)
                 .background(

+ 56 - 31
iOSClient/Main/Create cloud/NCUploadAssets.swift

@@ -26,6 +26,7 @@ import NextcloudKit
 import TLPhotoPicker
 import Mantis
 import Photos
+import QuickLook
 
 class NCHostingUploadAssetsView: NSObject {
 
@@ -61,7 +62,7 @@ class NCUploadAssets: NSObject, ObservableObject, NCCreateFormUploadConflictDele
     /*
 
      */
-    let resizeImagePreview: Double = 200
+    let resizeImagePreview: Double = 300
     let sizeImagePreview: Double = 100
     let compressionQuality: CGFloat = 0.5
 
@@ -75,26 +76,24 @@ class NCUploadAssets: NSObject, ObservableObject, NCCreateFormUploadConflictDele
     func loadImages() {
         DispatchQueue.global().async {
             for asset in self.assets {
-                guard asset.type == .photo, let image = asset.fullResolutionImage?.resizeImage(size: CGSize(width: self.resizeImagePreview, height: self.resizeImagePreview), isAspectRation: true), let localIdentifier = asset.phAsset?.localIdentifier else { continue }
+                guard let image = asset.fullResolutionImage?.resizeImage(size: CGSize(width: self.resizeImagePreview, height: self.resizeImagePreview), isAspectRation: true), let localIdentifier = asset.phAsset?.localIdentifier else { continue }
                 self.previewStore.append(PreviewStore(id: localIdentifier, image: image, asset: asset, hasChanges: false))
             }
         }
     }
 
     func startTimer(navigationItem: UINavigationItem) {
-        self.timer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: true, block: { _ in
-            let numItemsRight = navigationItem.rightBarButtonItems?.count ?? 0
-            if let buttonCrop = navigationItem.leftBarButtonItems?.first {
-                if numItemsRight > 1 && buttonCrop.isEnabled {
-                    buttonCrop.isEnabled = false
-                    if let buttonDone = navigationItem.rightBarButtonItems?.last {
-                        buttonDone.isEnabled = false
-                    }
-                }
-                if numItemsRight == 1 && !buttonCrop.isEnabled {
-                    buttonCrop.isEnabled = true
-                    if let buttonDone = navigationItem.rightBarButtonItems?.first {
-                        buttonDone.isEnabled = true
+        self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { _ in
+            guard let buttonDone = navigationItem.leftBarButtonItems?.first, let buttonCrop = navigationItem.leftBarButtonItems?.last else { return }
+            buttonCrop.isEnabled = true
+            buttonDone.isEnabled = true
+            if let markup = navigationItem.rightBarButtonItems?.first(where: { $0.accessibilityIdentifier == "QLOverlayMarkupButtonAccessibilityIdentifier" }) {
+                if let originalButton = markup.value(forKey: "originalButton") as AnyObject? {
+                    if let symbolImageName = originalButton.value(forKey: "symbolImageName") as? String {
+                        if symbolImageName == "pencil.tip.crop.circle.on" {
+                            buttonCrop.isEnabled = false
+                            buttonDone.isEnabled = false
+                        }
                     }
                 }
             }
@@ -147,7 +146,7 @@ struct UploadAssetsView: View {
         CCUtility.setOriginalFileName(isMaintainOriginalFilename, key: NCGlobal.shared.keyFileNameOriginal)
 
         if let asset = uploadAssets.assets.first?.phAsset, let name = (asset.value(forKey: "filename") as? String) {
-            return name
+            return (name as NSString).deletingPathExtension
         } else {
             return ""
         }
@@ -200,7 +199,7 @@ struct UploadAssetsView: View {
                                                forcedNewFileName: false)
         }
 
-        return String(format: NSLocalizedString("_preview_filename_", comment: ""), "MM, MMM, DD, YY, YYYY, HH, hh, mm, ss, ampm") + ":" + "\n\n" + preview
+        return String(format: NSLocalizedString("_preview_filename_", comment: ""), "MM, MMM, DD, YY, YYYY, HH, hh, mm, ss, ampm") + ":" + "\n\n" + (preview as NSString).deletingPathExtension
     }
 
     func save(completion: @escaping (_ metadatasNOConflict: [tableMetadata], _ metadatasUploadInConflict: [tableMetadata]) -> Void) {
@@ -209,7 +208,7 @@ struct UploadAssetsView: View {
         var metadatasUploadInConflict: [tableMetadata] = []
 
         for asset in uploadAssets.assets {
-            guard let asset = asset.phAsset else { continue }
+            guard let asset = asset.phAsset, let previewStore = uploadAssets.previewStore.first(where: { $0.id == asset.localIdentifier }) else { continue }
 
             let serverUrl = uploadAssets.serverUrl
             var livePhoto: Bool = false
@@ -222,7 +221,7 @@ struct UploadAssetsView: View {
                                                     keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal,
                                                     forcedNewFileName: false)!
 
-            if asset.mediaSubtypes.contains(.photoLive) && CCUtility.getLivePhoto() {
+            if asset.mediaSubtypes.contains(.photoLive) && CCUtility.getLivePhoto() && !previewStore.hasChanges {
                 livePhoto = true
             }
 
@@ -272,13 +271,15 @@ struct UploadAssetsView: View {
         }
     }
 
-    func presentedQuickLook(size: CGFloat, index: Int) {
+    func presentedQuickLook(geoSizeWidth: CGFloat, geoSizeHeight: CGFloat, index: Int) {
 
         let previewStore = uploadAssets.previewStore[index]
         var image = previewStore.image
 
-        if !previewStore.hasChanges {
-            if let fullResolutionImage = previewStore.asset.fullResolutionImage?.resizeImage(size: CGSize(width: size, height: size)) {
+        if !previewStore.hasChanges, let sizePhotoWidth = previewStore.asset.phAsset?.pixelWidth, let sizePhotoHeight = previewStore.asset.phAsset?.pixelHeight {
+            let width = min(geoSizeWidth * 2, CGFloat(sizePhotoWidth))
+            let height = min(geoSizeHeight * 2, CGFloat(sizePhotoHeight))
+            if let fullResolutionImage = previewStore.asset.fullResolutionImage?.resizeImage(size: CGSize(width: width, height: height)) {
                 image = fullResolutionImage
             }
         }
@@ -298,24 +299,44 @@ struct UploadAssetsView: View {
         GeometryReader { geo in
             NavigationView {
                 List {
-
                     if !uploadAssets.previewStore.isEmpty {
                         Section(header: Text(NSLocalizedString("_modify_photo_", comment: "")), footer: Text(NSLocalizedString("_modify_photo_desc_", comment: ""))) {
                             ScrollView(.horizontal) {
                                 LazyHGrid(rows: gridItems, alignment: .center, spacing: 10) {
                                     ForEach(0..<uploadAssets.previewStore.count, id: \.self) { index in
-                                        VStack {
-                                            Image(uiImage: uploadAssets.previewStore[index].image)
+                                        let item = uploadAssets.previewStore[index]
+                                        ZStack(alignment: .bottomTrailing) {
+                                            Image(uiImage: item.image)
                                                 .resizable()
                                                 .frame(width: uploadAssets.sizeImagePreview, height: uploadAssets.sizeImagePreview, alignment: .center)
                                                 .cornerRadius(10)
                                                 .scaledToFit()
-                                                .onTapGesture {
-                                                    presentedQuickLook(size: max(geo.size.height, geo.size.height), index: index)
-                                                }.fullScreenCover(isPresented: $isPresentedQuickLook) {
-                                                    ViewerQuickLook(url: URL(fileURLWithPath: fileNamePath), index: $index, isPresentedQuickLook: $isPresentedQuickLook, uploadAssets: uploadAssets)
-                                                        .ignoresSafeArea()
-                                                }
+                                            if item.asset.type == .livePhoto && !item.hasChanges {
+                                                Image(systemName: "livephoto")
+                                                    .resizable()
+                                                    .scaledToFit()
+                                                    .frame(width: 15, height: 15)
+                                                    .foregroundColor(.white)
+                                                    .padding(.horizontal, 5)
+                                                    .padding(.vertical, 5)
+                                            } else if item.asset.type == .video {
+                                                Image(systemName: "video.fill")
+                                                    .resizable()
+                                                    .scaledToFit()
+                                                    .frame(width: 15, height: 15)
+                                                    .foregroundColor(.white)
+                                                    .padding(.horizontal, 5)
+                                                    .padding(.vertical, 5)
+                                            }
+                                        }
+                                        .onTapGesture {
+                                            if item.asset.type == .photo || item.asset.type == .livePhoto {
+                                                presentedQuickLook(geoSizeWidth: geo.size.width, geoSizeHeight: geo.size.height, index: index)
+                                            }
+                                        }
+                                        .fullScreenCover(isPresented: $isPresentedQuickLook) {
+                                            ViewerQuickLook(url: URL(fileURLWithPath: fileNamePath), index: $index, isPresentedQuickLook: $isPresentedQuickLook, uploadAssets: uploadAssets)
+                                                .ignoresSafeArea()
                                         }
                                     }
                                 }
@@ -363,6 +384,7 @@ struct UploadAssetsView: View {
                             if isMaintainOriginalFilename {
                                 Text(getOriginalFilename())
                                     .frame(maxWidth: .infinity, alignment: .trailing)
+                                    .foregroundColor(Color.gray)
                             } else {
                                 TextField(NSLocalizedString("_enter_filename_", comment: ""), text: $fileName)
                                     .modifier(TextFieldClearButton(text: $fileName))
@@ -399,6 +421,7 @@ struct UploadAssetsView: View {
                 .navigationTitle(NSLocalizedString("_upload_photos_videos_", comment: ""))
                 .navigationBarTitleDisplayMode(.inline)
             }
+            .navigationViewStyle(StackNavigationViewStyle())
             .sheet(isPresented: $isPresentedSelect) {
                 SelectView(serverUrl: $uploadAssets.serverUrl)
             }
@@ -410,6 +433,8 @@ struct UploadAssetsView: View {
                     presentationMode.wrappedValue.dismiss()
                 }
             }
+        }.onTapGesture {
+            UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.endEditing(true)
         }
     }
 }

+ 1 - 5
iOSClient/Scan document/NCUploadScanDocument.swift

@@ -502,13 +502,9 @@ struct UploadScanDocumentView: View {
         .sheet(isPresented: $isPresentedUploadConflict) {
             UploadConflictView(delegate: uploadScanDocument, serverUrl: uploadScanDocument.serverUrl, metadatasUploadInConflict: [uploadScanDocument.metadata], metadatasNOConflict: [])
         }.onTapGesture {
-            dismissKeyboard()
+            UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.endEditing(true)
         }
     }
-
-    func dismissKeyboard() {
-        UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.endEditing(true)
-    }
 }
 
 // MARK: - UIViewControllerRepresentable

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

@@ -919,6 +919,7 @@
 "_preview_"                 = "Preview";
 "_crop_"                    = "Crop";
 "_modify_photo_desc_"       = "Tap the image for modify photo";
+"_message_disable_livephoto_" = "This image is a Live Photo, changing it will lose the Live effect";
 
 // Video
 "_select_trace_"            = "Select the trace";

+ 42 - 11
iOSClient/Viewer/NCViewerQuickLook/ViewerQuickLook.swift

@@ -9,6 +9,7 @@
 import SwiftUI
 import QuickLook
 import Mantis
+import NextcloudKit
 
 struct ViewerQuickLook: UIViewControllerRepresentable {
 
@@ -25,18 +26,19 @@ struct ViewerQuickLook: UIViewControllerRepresentable {
         controller.delegate = context.coordinator
         context.coordinator.viewController = controller
 
-        controller.navigationItem.rightBarButtonItem = UIBarButtonItem(
-            barButtonSystemItem: .done, target: context.coordinator,
-            action: #selector(context.coordinator.dismiss)
-        )
-
-        controller.navigationItem.leftBarButtonItem = UIBarButtonItem(
-            title: NSLocalizedString("_crop_", comment: ""), style: UIBarButtonItem.Style.plain, target: context.coordinator,
-            action: #selector(context.coordinator.crop)
-        )
+        let buttonDone = UIBarButtonItem(barButtonSystemItem: .done, target: context.coordinator, action: #selector(context.coordinator.dismiss))
+        let buttonCrop = UIBarButtonItem(image: UIImage(systemName: "crop"), style: .plain, target: context.coordinator, action: #selector(context.coordinator.crop))
+        controller.navigationItem.leftBarButtonItems = [buttonDone, buttonCrop]
 
         uploadAssets.startTimer(navigationItem: controller.navigationItem)
 
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+            if uploadAssets.previewStore[index].asset.type == .livePhoto && !uploadAssets.previewStore[index].hasChanges {
+                let error = NKError(errorCode: NCGlobal.shared.errorCharactersForbidden, errorDescription: "_message_disable_livephoto_")
+                NCContentPresenter.shared.showInfo(error: error)
+            }
+        }
+
         let navigationController = UINavigationController(rootViewController: controller)
         return navigationController
     }
@@ -114,18 +116,47 @@ struct ViewerQuickLook: UIViewControllerRepresentable {
         @objc func crop() {
 
             guard let image = UIImage(contentsOfFile: parent.url.path) else { return }
-            let config = Mantis.Config()
 
+            var toolbarConfig = CropToolbarConfig()
+            toolbarConfig.heightForVerticalOrientation = 80
+            toolbarConfig.widthForHorizontalOrientation = 100
+            toolbarConfig.optionButtonFontSize = 16
+            toolbarConfig.optionButtonFontSizeForPad = 21
+            toolbarConfig.backgroundColor = .systemGray6
+            toolbarConfig.foregroundColor = .systemBlue
+
+            var viewConfig = CropViewConfig()
+            viewConfig.cropMaskVisualEffectType = .none
+            viewConfig.cropBorderColor = .red
+
+            var config = Mantis.Config()
             if let bundleIdentifier = Bundle.main.bundleIdentifier {
                 config.localizationConfig.bundle = Bundle(identifier: bundleIdentifier)
                 config.localizationConfig.tableName = "Localizable"
             }
-            let cropViewController = Mantis.cropViewController(image: image, config: config)
+            config.cropToolbarConfig = toolbarConfig
+            config.cropViewConfig = viewConfig
+
+            let toolbar = CropToolbar()
+            toolbar.iconProvider = CropToolbarIcon()
+
+            let cropViewController = Mantis.cropViewController(image: image, config: config, cropToolbar: toolbar)
 
             cropViewController.delegate = self
+            cropViewController.backgroundColor = .systemBackground
             cropViewController.modalPresentationStyle = .fullScreen
 
             viewController?.present(cropViewController, animated: true)
         }
     }
+
+    class CropToolbarIcon: CropToolbarIconProvider {
+        func getCropIcon() -> UIImage? {
+           return UIImage(systemName: "checkmark.circle")
+        }
+
+        func getCancelIcon() -> UIImage? {
+            return UIImage(systemName: "xmark.circle")
+        }
+    }
 }