diff --git a/.swiftlint.yml b/.swiftlint.yml index 81cba9076a..c1a42f37f6 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -44,6 +44,7 @@ excluded: - Pods # iOS Files Quarantine + - File Provider Extension/FileProviderData.swift - File Provider Extension/FileProviderDomain.swift - File Provider Extension/FileProviderEnumerator.swift @@ -60,6 +61,7 @@ excluded: - Widget/Lockscreen/LockscreenData.swift - Widget/Lockscreen/LockscreenWidgetView.swift - Widget/Lockscreen/LockscreenWidgetProvider.swift + - iOSClient/GUI - iOSClient/ExternalResources - iOSClient/Activity/NCActivity.swift - iOSClient/Activity/NCActivityTableViewCell.swift diff --git a/Nextcloud Hub.png b/Nextcloud Hub.png new file mode 100644 index 0000000000..6ace095e72 Binary files /dev/null and b/Nextcloud Hub.png differ diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index f32e15d753..0f5b62515c 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -96,6 +96,7 @@ 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 */; }; @@ -412,6 +413,8 @@ 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 */; }; + F7A48413297022E000BD1B49 /* ViewerQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A48412297022E000BD1B49 /* ViewerQuickLook.swift */; }; + F7A48415297028FC00BD1B49 /* Nextcloud Hub.png in Resources */ = {isa = PBXBuildFile; fileRef = F7A48414297028FC00BD1B49 /* Nextcloud Hub.png */; }; F7A60F86292D215000FCE1F2 /* NCTalkAccounts.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A60F84292D215000FCE1F2 /* NCTalkAccounts.swift */; }; F7A60F87292D215000FCE1F2 /* NCTalkAccounts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7A60F85292D215000FCE1F2 /* NCTalkAccounts.storyboard */; }; F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; }; @@ -498,7 +501,6 @@ F7D68FCF28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; }; 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 */; }; F7E0710128B13BB00001B882 /* DashboardData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E0710028B13BB00001B882 /* DashboardData.swift */; }; F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */; }; F7E41316294A19B300839300 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; @@ -986,6 +988,8 @@ F7A0D1342591FBC5008F8A13 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; }; F7A321AB1E9E6AD50069AD1B /* CCAdvanced.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAdvanced.h; sourceTree = ""; }; F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAdvanced.m; sourceTree = ""; }; + F7A48412297022E000BD1B49 /* ViewerQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewerQuickLook.swift; sourceTree = ""; }; + F7A48414297028FC00BD1B49 /* Nextcloud Hub.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Nextcloud Hub.png"; sourceTree = SOURCE_ROOT; }; F7A60F84292D215000FCE1F2 /* NCTalkAccounts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCTalkAccounts.swift; sourceTree = ""; }; F7A60F85292D215000FCE1F2 /* NCTalkAccounts.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCTalkAccounts.storyboard; sourceTree = ""; }; F7A7FA6229265CF4000603EF /* NCManageE2EE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCManageE2EE.swift; sourceTree = ""; }; @@ -1149,7 +1153,6 @@ F7D96FCB246ED7E100536D73 /* NCNetworkingCheckRemoteUser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCNetworkingCheckRemoteUser.swift; sourceTree = ""; }; F7DBD82B23E46A4700ECB7C6 /* MarkdownKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MarkdownKit.framework; path = Carthage/Build/iOS/MarkdownKit.framework; sourceTree = ""; }; F7DE9AB01F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; - F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadAssets.swift; sourceTree = ""; }; F7E0710028B13BB00001B882 /* DashboardData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardData.swift; sourceTree = ""; }; F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCUserStatus.storyboard; sourceTree = ""; }; F7E41315294A19B300839300 /* UIView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = ""; }; @@ -1256,6 +1259,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F704A950296EE1C200D0737A /* Mantis in Frameworks */, F76DA941277B75870082465B /* KTVHTTPCache.xcframework in Frameworks */, F7ED547C25EEA65400956C55 /* QRCodeReader in Frameworks */, F788ECC7263AAAFA00ADC67F /* MarkdownKit in Frameworks */, @@ -1471,6 +1475,7 @@ isa = PBXGroup; children = ( F7C7B488245EBA4100D93E60 /* NCViewerQuickLook.swift */, + F7A48412297022E000BD1B49 /* ViewerQuickLook.swift */, ); path = NCViewerQuickLook; sourceTree = ""; @@ -2043,7 +2048,6 @@ isa = PBXGroup; children = ( F769CA162965AB7C00039397 /* NCUploadAssets.swift */, - F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */, F704B5E22430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard */, F704B5E42430AA8000632F5F /* NCCreateFormUploadConflict.swift */, F704B5E82430C0B800632F5F /* NCCreateFormUploadConflictCell.swift */, @@ -2190,6 +2194,7 @@ isa = PBXGroup; children = ( F7AC9349296193050002BC0F /* Reasons to use Nextcloud.pdf */, + F7A48414297028FC00BD1B49 /* Nextcloud Hub.png */, F7F4F0FB27ECDBDA008676F9 /* Font */, F72B60941A24F04E004EF66F /* Localizations */, ); @@ -2493,6 +2498,7 @@ F734B06528E75C0100E180D5 /* TLPhotoPicker */, F77333872927A72100466E35 /* OpenSSL */, F77BC3EA293E5268005F2B08 /* Swifter */, + F704A94F296EE1C200D0737A /* Mantis */, ); productName = "Crypto Cloud"; productReference = F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */; @@ -2651,6 +2657,7 @@ F734B06428E75C0100E180D5 /* XCRemoteSwiftPackageReference "TLPhotoPicker" */, F77333862927A72100466E35 /* XCRemoteSwiftPackageReference "OpenSSL" */, F77BC3E9293E5268005F2B08 /* XCRemoteSwiftPackageReference "swifter" */, + F704A94E296EE1C200D0737A /* XCRemoteSwiftPackageReference "Mantis" */, ); productRefGroup = F7F67B9F1A24D27800EE80DA; projectDirPath = ""; @@ -2757,6 +2764,7 @@ F710E8111EF95C9C00DC2427 /* ImagesIntro.xcassets in Resources */, F76032A0252F0F8E0015A421 /* NCTransferCell.xib in Resources */, F7F4F10527ECDBDB008676F9 /* Inconsolata-SemiBold.ttf in Resources */, + F7A48415297028FC00BD1B49 /* Nextcloud Hub.png in Resources */, F74C0437253F1CDC009762AB /* NCShares.storyboard in Resources */, F7F4F10C27ECDBDB008676F9 /* Inconsolata-Regular.ttf in Resources */, F7B8B83025681C3400967775 /* GoogleService-Info.plist in Resources */, @@ -3067,7 +3075,6 @@ F702F2CF25EE5B5C008F8E80 /* NCGlobal.swift in Sources */, F72CD63A25C19EBF00F46F9A /* NCAutoUpload.swift in Sources */, AF93471D27E2361E002537EE /* NCShareAdvancePermissionFooter.swift in Sources */, - F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */, AF1A9B6427D0CA1E00F17A9E /* UIAlertController+Extension.swift in Sources */, F73B422C2476764F00A30FD3 /* NCNotification.swift in Sources */, 371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */, @@ -3206,6 +3213,7 @@ F7D68FCC28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, F70CEF5623E9C7E50007035B /* UIColor+Extension.swift in Sources */, F75CA1472962F13700B01130 /* HUDView.swift in Sources */, + F7A48413297022E000BD1B49 /* ViewerQuickLook.swift in Sources */, F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */, F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */, F7A7FA6329265CF4000603EF /* NCManageE2EE.swift in Sources */, @@ -3930,6 +3938,14 @@ /* 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"; @@ -4093,6 +4109,11 @@ /* 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" */; diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift deleted file mode 100644 index 5f0f8dfe26..0000000000 --- a/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift +++ /dev/null @@ -1,457 +0,0 @@ -// -// NCCreateFormUploadAssets.swift -// Nextcloud -// -// Created by Marino Faggiana on 14/11/2018. -// Copyright © 2018 Marino Faggiana. All rights reserved. -// -// Author Marino Faggiana -// -// 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 . -// - -import UIKit -import Queuer -import NextcloudKit -import XLForm -import Photos - -class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate { - - var serverUrl: String = "" - var titleServerUrl: String? - var assets: [PHAsset] = [] - var cryptated: Bool = false - var session: String = "" - let requestOptions = PHImageRequestOptions() - var imagePreview: UIImage? - let targetSizeImagePreview = CGSize(width: 100, height: 100) - let appDelegate = UIApplication.shared.delegate as! AppDelegate - - var cellBackgoundColor = UIColor.secondarySystemGroupedBackground - - // MARK: - View Life Cycle - - convenience init(serverUrl: String, assets: [PHAsset], cryptated: Bool, session: String) { - - self.init() - - if serverUrl == NCUtilityFileSystem.shared.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) { - titleServerUrl = "/" - } else { - if let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl)) { - if let metadata = NCManageDatabase.shared.getMetadataFromOcId(tableDirectory.ocId) { - titleServerUrl = metadata.fileNameView - } else { titleServerUrl = (serverUrl as NSString).lastPathComponent } - } else { titleServerUrl = (serverUrl as NSString).lastPathComponent } - } - - self.serverUrl = serverUrl - self.assets = assets - self.cryptated = cryptated - self.session = session - - requestOptions.resizeMode = PHImageRequestOptionsResizeMode.exact - requestOptions.deliveryMode = PHImageRequestOptionsDeliveryMode.highQualityFormat - requestOptions.isSynchronous = true - } - - override func viewDidLoad() { - - super.viewDidLoad() - - self.title = NSLocalizedString("_upload_photos_videos_", comment: "") - - view.backgroundColor = .systemGroupedBackground - tableView.backgroundColor = .systemGroupedBackground - cellBackgoundColor = .secondarySystemGroupedBackground - - self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(cancel)) - self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_save_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(save)) - - self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none - - if assets.count == 1 && assets[0].mediaType == PHAssetMediaType.image { - PHImageManager.default().requestImage(for: assets[0], targetSize: targetSizeImagePreview, contentMode: PHImageContentMode.aspectFill, options: requestOptions, resultHandler: { image, _ in - self.imagePreview = image - }) - } - - initializeForm() - reloadForm() - } - - // 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) - - // User folder Autoupload - row = XLFormRowDescriptor(tag: "useFolderAutoUpload", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_use_folder_auto_upload_", comment: "")) - row.value = 0 - row.cellConfig["backgroundColor"] = cellBackgoundColor - - row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0) - row.cellConfig["textLabel.textColor"] = UIColor.label - - section.addFormRow(row) - - // Use Sub folder - row = XLFormRowDescriptor(tag: "useSubFolder", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_autoupload_create_subfolder_", comment: "")) - let activeAccount = NCManageDatabase.shared.getActiveAccount() - if activeAccount?.autoUploadCreateSubfolder == true { - row.value = 1 - } else { - row.value = 0 - } - row.hidden = "$\("useFolderAutoUpload") == 0" - - row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0) - row.cellConfig["textLabel.textColor"] = UIColor.label - - section.addFormRow(row) - - // Section Mode filename - - section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_mode_filename_", comment: "")) - form.addFormSection(section) - - // Maintain the original fileName - - row = XLFormRowDescriptor(tag: "maintainOriginalFileName", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_maintain_original_filename_", comment: "")) - row.value = CCUtility.getOriginalFileName(NCGlobal.shared.keyFileNameOriginal) - row.cellConfig["backgroundColor"] = cellBackgoundColor - - row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0) - row.cellConfig["textLabel.textColor"] = UIColor.label - - section.addFormRow(row) - - // Add File Name Type - - row = XLFormRowDescriptor(tag: "addFileNameType", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_add_filenametype_", comment: "")) - row.value = CCUtility.getFileNameType(NCGlobal.shared.keyFileNameType) - row.hidden = "$\("maintainOriginalFileName") == 1" - row.cellConfig["backgroundColor"] = cellBackgoundColor - - row.cellConfig["textLabel.font"] = UIFont.systemFont(ofSize: 15.0) - row.cellConfig["textLabel.textColor"] = UIColor.label - - section.addFormRow(row) - - // Section: Rename File Name - - section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("_filename_", comment: "")) - form.addFormSection(section) - - row = XLFormRowDescriptor(tag: "maskFileName", rowType: XLFormRowDescriptorTypeText, title: (NSLocalizedString("_filename_", comment: ""))) - let fileNameMask: String = CCUtility.getFileNameMask(NCGlobal.shared.keyFileNameMask) - if fileNameMask.count > 0 { - row.value = fileNameMask - } - row.hidden = "$\("maintainOriginalFileName") == 1" - 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: Preview File Name - - row = XLFormRowDescriptor(tag: "previewFileName", rowType: XLFormRowDescriptorTypeTextView, title: "") - row.height = 180 - row.disabled = true - row.cellConfig["backgroundColor"] = cellBackgoundColor - - row.cellConfig["textView.backgroundColor"] = cellBackgoundColor - row.cellConfig["textView.font"] = UIFont.systemFont(ofSize: 14.0) - row.cellConfig["textView.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 == "useFolderAutoUpload" { - - if (formRow.value! as AnyObject).boolValue == true { - - let buttonDestinationFolder: XLFormRowDescriptor = self.form.formRow(withTag: "ButtonDestinationFolder")! - buttonDestinationFolder.hidden = true - - } else { - - let buttonDestinationFolder: XLFormRowDescriptor = self.form.formRow(withTag: "ButtonDestinationFolder")! - buttonDestinationFolder.hidden = false - } - } else if formRow.tag == "useSubFolder" { - - if (formRow.value! as AnyObject).boolValue == true { - - } else { - - } - } else if formRow.tag == "maintainOriginalFileName" { - CCUtility.setOriginalFileName((formRow.value! as AnyObject).boolValue, key: NCGlobal.shared.keyFileNameOriginal) - self.reloadForm() - } else if formRow.tag == "addFileNameType" { - CCUtility.setFileNameType((formRow.value! as AnyObject).boolValue, key: NCGlobal.shared.keyFileNameType) - self.reloadForm() - } else if formRow.tag == "maskFileName" { - - let fileName = formRow.value as? String - - self.form.delegate = nil - - if let fileName = fileName { - formRow.value = CCUtility.removeForbiddenCharactersServer(fileName) - } - - self.form.delegate = self - - let previewFileName: XLFormRowDescriptor = self.form.formRow(withTag: "previewFileName")! - previewFileName.value = self.previewFileName(valueRename: formRow.value as? String) - - // reload cell - if fileName != nil { - - if newValue as! String != formRow.value as! String { - - self.reloadFormRow(formRow) - - let error = NKError(errorCode: NCGlobal.shared.errorCharactersForbidden, errorDescription: "_forbidden_characters_") - NCContentPresenter.shared.showInfo(error: error) - } - } - - self.reloadFormRow(previewFileName) - } - } - - func reloadForm() { - - self.form.delegate = nil - - let buttonDestinationFolder: XLFormRowDescriptor = self.form.formRow(withTag: "ButtonDestinationFolder")! - buttonDestinationFolder.title = self.titleServerUrl - - let maskFileName: XLFormRowDescriptor = self.form.formRow(withTag: "maskFileName")! - let previewFileName: XLFormRowDescriptor = self.form.formRow(withTag: "previewFileName")! - previewFileName.value = self.previewFileName(valueRename: maskFileName.value as? String) - - self.tableView.reloadData() - self.form.delegate = self - } - - // MARK: - Action - - func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], overwrite: Bool, copy: Bool, move: Bool) { - - if serverUrl != nil { - - self.serverUrl = serverUrl! - - if serverUrl == NCUtilityFileSystem.shared.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId) { - self.titleServerUrl = "/" - } else { - if let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, self.serverUrl)) { - if let metadata = NCManageDatabase.shared.getMetadataFromOcId(tableDirectory.ocId) { - titleServerUrl = metadata.fileNameView - } else { titleServerUrl = (self.serverUrl as NSString).lastPathComponent } - } else { titleServerUrl = (self.serverUrl as NSString).lastPathComponent } - } - - // Update - let row: XLFormRowDescriptor = self.form.formRow(withTag: "ButtonDestinationFolder")! - row.title = self.titleServerUrl - self.updateFormRow(row) - } - } - - @objc func save() { - - DispatchQueue.global().async { - - let useFolderPhotoRow: XLFormRowDescriptor = self.form.formRow(withTag: "useFolderAutoUpload")! - let useSubFolderRow: XLFormRowDescriptor = self.form.formRow(withTag: "useSubFolder")! - var useSubFolder: Bool = false - var metadatasNOConflict: [tableMetadata] = [] - var metadatasUploadInConflict: [tableMetadata] = [] - let autoUploadPath = NCManageDatabase.shared.getAccountAutoUploadPath(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId, account: self.appDelegate.account) - - if (useFolderPhotoRow.value! as AnyObject).boolValue == true { - self.serverUrl = NCManageDatabase.shared.getAccountAutoUploadPath(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId, account: self.appDelegate.account) - useSubFolder = (useSubFolderRow.value! as AnyObject).boolValue - } - - if autoUploadPath == self.serverUrl { - if !NCNetworking.shared.createFolder(assets: self.assets, selector: NCGlobal.shared.selectorUploadFile, useSubFolder: useSubFolder, account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) { - - let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_error_createsubfolders_upload_") - NCContentPresenter.shared.showError(error: error) - return - } - } - - for asset in self.assets { - - var serverUrl = self.serverUrl - var livePhoto: Bool = false - let creationDate = asset.creationDate ?? Date() - let fileName = CCUtility.createFileName(asset.value(forKey: "filename") as? String, fileDate: creationDate, fileType: asset.mediaType, keyFileName: NCGlobal.shared.keyFileNameMask, keyFileNameType: NCGlobal.shared.keyFileNameType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal, forcedNewFileName: false)! - - if asset.mediaSubtypes.contains(.photoLive) && CCUtility.getLivePhoto() { - livePhoto = true - } - - if useSubFolder { - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy" - let yearString = dateFormatter.string(from: creationDate) - dateFormatter.dateFormat = "MM" - let monthString = dateFormatter.string(from: creationDate) - serverUrl = autoUploadPath + "/" + yearString + "/" + monthString - } - - // Check if is in upload - let isRecordInSessions = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@ AND session != ''", self.appDelegate.account, serverUrl, fileName), sorted: "fileName", ascending: false) - if isRecordInSessions.count > 0 { continue } - - let metadataForUpload = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: self.appDelegate.urlBase, url: "", contentType: "", isLivePhoto: livePhoto) - - metadataForUpload.assetLocalIdentifier = asset.localIdentifier - metadataForUpload.session = self.session - metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile - metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload - - if let result = NCManageDatabase.shared.getMetadataConflict(account: self.appDelegate.account, serverUrl: serverUrl, fileNameView: fileName) { - metadataForUpload.fileName = result.fileName - metadatasUploadInConflict.append(metadataForUpload) - } else { - metadatasNOConflict.append(metadataForUpload) - } - } - - // Verify if file(s) exists - if metadatasUploadInConflict.count > 0 { - - DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { - if let conflict = UIStoryboard(name: "NCCreateFormUploadConflict", bundle: nil).instantiateInitialViewController() as? NCCreateFormUploadConflict { - - conflict.serverUrl = self.serverUrl - conflict.metadatasNOConflict = metadatasNOConflict - conflict.metadatasUploadInConflict = metadatasUploadInConflict - conflict.delegate = self.appDelegate - - self.appDelegate.window?.rootViewController?.present(conflict, animated: true, completion: nil) - } - } - - } else { - NCNetworkingProcessUpload.shared.createProcessUploads(metadatas: metadatasNOConflict, completion: { _ in }) - } - - DispatchQueue.main.async {self.dismiss(animated: true, completion: nil) } - } - } - - @objc func cancel() { - - self.dismiss(animated: true, completion: nil) - } - - // MARK: - Utility - - func previewFileName(valueRename: String?) -> String { - - var returnString: String = "" - let asset = assets[0] - let creationDate = asset.creationDate ?? Date() - - if CCUtility.getOriginalFileName(NCGlobal.shared.keyFileNameOriginal) { - - return (NSLocalizedString("_filename_", comment: "") + ": " + (asset.value(forKey: "filename") as! String)) - - } else if let valueRename = valueRename { - - let valueRenameTrimming = valueRename.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - - if valueRenameTrimming.count > 0 { - - self.form.delegate = nil - CCUtility.setFileNameMask(valueRename, key: NCGlobal.shared.keyFileNameMask) - self.form.delegate = self - - returnString = CCUtility.createFileName(asset.value(forKey: "filename") as! String?, fileDate: creationDate, fileType: asset.mediaType, keyFileName: NCGlobal.shared.keyFileNameMask, keyFileNameType: NCGlobal.shared.keyFileNameType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal, forcedNewFileName: false) - - } else { - - CCUtility.setFileNameMask("", key: NCGlobal.shared.keyFileNameMask) - returnString = CCUtility.createFileName(asset.value(forKey: "filename") as! String?, fileDate: creationDate, fileType: asset.mediaType, keyFileName: nil, keyFileNameType: NCGlobal.shared.keyFileNameType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal, forcedNewFileName: false) - } - - } else { - - CCUtility.setFileNameMask("", key: NCGlobal.shared.keyFileNameMask) - returnString = CCUtility.createFileName(asset.value(forKey: "filename") as! String?, fileDate: creationDate, fileType: asset.mediaType, keyFileName: nil, keyFileNameType: NCGlobal.shared.keyFileNameType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal, forcedNewFileName: false) - } - - return String(format: NSLocalizedString("_preview_filename_", comment: ""), "MM, MMM, DD, YY, YYYY, HH, hh, mm, ss, ampm") + ":" + "\n\n" + returnString - } - - @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) - } -} diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift index 361355adfd..4b558cec5f 100644 --- a/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift +++ b/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift @@ -254,7 +254,7 @@ class NCCreateFormUploadConflict: UIViewController { metadata.fileNameView = newFileName // This is not an asset - [file] - if metadata.assetLocalIdentifier == "" { + if metadata.assetLocalIdentifier == "" || metadata.isExtractFile { let newPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: newFileName) CCUtility.moveFile(atPath: oldPath, toPath: newPath) } diff --git a/iOSClient/Main/Create cloud/NCUploadAssets.swift b/iOSClient/Main/Create cloud/NCUploadAssets.swift index c90e7af50a..af8cdabd29 100644 --- a/iOSClient/Main/Create cloud/NCUploadAssets.swift +++ b/iOSClient/Main/Create cloud/NCUploadAssets.swift @@ -24,6 +24,8 @@ import SwiftUI import NextcloudKit import TLPhotoPicker +import Mantis +import Photos class NCHostingUploadAssetsView: NSObject { @@ -37,15 +39,31 @@ class NCHostingUploadAssetsView: NSObject { // MARK: - Class -class NCUploadAssets: ObservableObject, NCCreateFormUploadConflictDelegate { +struct PreviewStore { + var id: String + var image: UIImage + var asset: TLPHAsset + var hasChanges: Bool +} + +class NCUploadAssets: NSObject, ObservableObject, NCCreateFormUploadConflictDelegate { @Published var serverUrl: String @Published var assets: [TLPHAsset] @Published var userBaseUrl: NCUserBaseUrl @Published var dismiss = false + @Published var previewStore: [PreviewStore] = [] var metadatasNOConflict: [tableMetadata] = [] var metadatasUploadInConflict: [tableMetadata] = [] + var timer: Timer? + + /* + + */ + let resizeImagePreview: Double = 200 + let sizeImagePreview: Double = 100 + let compressionQuality: CGFloat = 0.5 init(assets: [TLPHAsset], serverUrl: String, userBaseUrl: NCUserBaseUrl) { @@ -54,6 +72,39 @@ class NCUploadAssets: ObservableObject, NCCreateFormUploadConflictDelegate { self.userBaseUrl = userBaseUrl } + 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 } + 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 + } + } + } + }) + } + + func stopTimer() { + self.timer?.invalidate() + } + func dismissCreateFormUploadConflict(metadatas: [tableMetadata]?) { if let metadatas = metadatas { @@ -75,6 +126,12 @@ struct UploadAssetsView: View { @State private var isAddFilenametype: Bool = CCUtility.getFileNameType(NCGlobal.shared.keyFileNameType) @State private var isPresentedSelect = false @State private var isPresentedUploadConflict = false + @State private var isPresentedQuickLook = false + @State private var fileNamePath = NSTemporaryDirectory() + "Photo.jpg" + @State private var metadata: tableMetadata? + @State private var index: Int = 0 + + var gridItems: [GridItem] = [GridItem()] @ObservedObject var uploadAssets: NCUploadAssets @@ -82,6 +139,7 @@ struct UploadAssetsView: View { init(uploadAssets: NCUploadAssets) { self.uploadAssets = uploadAssets + uploadAssets.loadImages() } func getOriginalFilename() -> String { @@ -179,6 +237,24 @@ struct UploadAssetsView: View { metadata.sessionSelector = NCGlobal.shared.selectorUploadFile metadata.status = NCGlobal.shared.metadataStatusWaitUpload + // Modified + if let previewStore = uploadAssets.previewStore.first(where: { $0.id == asset.localIdentifier }), previewStore.hasChanges, let data = previewStore.image.jpegData(compressionQuality: 1) { + if metadata.contentType == "image/heic" { + let fileNameNoExtension = (fileName as NSString).deletingPathExtension + metadata.contentType = "image/jpeg" + metadata.fileName = fileNameNoExtension + ".jpg" + metadata.fileNameView = fileNameNoExtension + ".jpg" + } + let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)! + do { + try data.write(to: URL(fileURLWithPath: fileNamePath)) + metadata.isExtractFile = true + metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath) + metadata.creationDate = asset.creationDate as? NSDate ?? (Date() as NSDate) + metadata.date = asset.modificationDate as? NSDate ?? (Date() as NSDate) + } catch { } + } + if let result = NCManageDatabase.shared.getMetadataConflict(account: uploadAssets.userBaseUrl.account, serverUrl: serverUrl, fileNameView: fileName) { metadata.fileName = result.fileName metadatasUploadInConflict.append(metadata) @@ -196,95 +272,143 @@ struct UploadAssetsView: View { } } + func presentedQuickLook(size: 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)) { + image = fullResolutionImage + } + } + + if let data = image.jpegData(compressionQuality: uploadAssets.compressionQuality) { + do { + try data.write(to: URL(fileURLWithPath: fileNamePath)) + self.index = index + isPresentedQuickLook = true + } catch { + } + } + } + var body: some View { - NavigationView { - List { - Section(header: Text(NSLocalizedString("_save_path_", comment: ""))) { - - HStack { - Label { - if NCUtilityFileSystem.shared.getHomeServer(urlBase: uploadAssets.userBaseUrl.urlBase, userId: uploadAssets.userBaseUrl.userId) == uploadAssets.serverUrl { - Text("/") - .frame(maxWidth: .infinity, alignment: .trailing) - } else { - Text((uploadAssets.serverUrl as NSString).lastPathComponent) - .frame(maxWidth: .infinity, alignment: .trailing) + + 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.. // Author Henrik Storch @@ -26,6 +27,12 @@ import UIKit import QuickLook import NextcloudKit +import Mantis +import SwiftUI + +protocol NCViewerQuickLookDelegate: AnyObject { + func dismiss(url: URL, hasChanges: Bool) +} @objc class NCViewerQuickLook: QLPreviewController { @@ -33,6 +40,7 @@ import NextcloudKit var previewItems: [PreviewItem] = [] var isEditingEnabled: Bool var metadata: tableMetadata? + var delegateViewer: NCViewerQuickLookDelegate? // if the document has any changes (annotations) var hasChanges = false @@ -40,6 +48,9 @@ import NextcloudKit // used to display the save alert var parentVC: UIViewController? + // if the Crop is presented + var isPresentCrop = false + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -70,6 +81,8 @@ import NextcloudKit let error = NKError(errorCode: NCGlobal.shared.errorCharactersForbidden, errorDescription: "_message_disable_overwrite_livephoto_") NCContentPresenter.shared.showInfo(error: error) } + + navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_crop_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(crop)) } override func viewDidAppear(_ animated: Bool) { @@ -81,6 +94,8 @@ import NextcloudKit override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) + guard !isPresentCrop else { return } + delegateViewer?.dismiss(url: url, hasChanges: hasChanges) guard isEditingEnabled, hasChanges, let metadata = metadata else { return } let alertController = UIAlertController(title: NSLocalizedString("_save_", comment: ""), message: nil, preferredStyle: .alert) @@ -102,6 +117,24 @@ import NextcloudKit alertController.addAction(UIAlertAction(title: NSLocalizedString("_discard_changes_", comment: ""), style: .destructive) { _ in }) parentVC?.present(alertController, animated: true) } + + @objc func crop() { + + guard let image = UIImage(contentsOfFile: url.path) else { return } + let 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) + + cropViewController.delegate = self + cropViewController.modalPresentationStyle = .fullScreen + + self.isPresentCrop = true + self.present(cropViewController, animated: true) + } } extension NCViewerQuickLook: QLPreviewControllerDataSource, QLPreviewControllerDelegate { @@ -165,6 +198,29 @@ extension NCViewerQuickLook: QLPreviewControllerDataSource, QLPreviewControllerD } } +extension NCViewerQuickLook: CropViewControllerDelegate { + + func cropViewControllerDidCrop(_ cropViewController: Mantis.CropViewController, cropped: UIImage, transformation: Mantis.Transformation, cropInfo: Mantis.CropInfo) { + cropViewController.dismiss(animated: true) { + self.isPresentCrop = false + } + + guard let data = cropped.jpegData(compressionQuality: 1) else { return } + + do { + try data.write(to: self.url) + reloadData() + } catch { } + } + + func cropViewControllerDidCancel(_ cropViewController: Mantis.CropViewController, original: UIImage) { + + cropViewController.dismiss(animated: true) { + self.isPresentCrop = false + } + } +} + class PreviewItem: NSObject, QLPreviewItem { var previewItemURL: URL? } diff --git a/iOSClient/Viewer/NCViewerQuickLook/ViewerQuickLook.swift b/iOSClient/Viewer/NCViewerQuickLook/ViewerQuickLook.swift new file mode 100644 index 0000000000..5bb8528c1f --- /dev/null +++ b/iOSClient/Viewer/NCViewerQuickLook/ViewerQuickLook.swift @@ -0,0 +1,131 @@ +// +// ViewerQuickLook.swift +// Nextcloud +// +// Created by Marino Faggiana on 12/01/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import SwiftUI +import QuickLook +import Mantis + +struct ViewerQuickLook: UIViewControllerRepresentable { + + let url: URL + + @Binding var index: Int + @Binding var isPresentedQuickLook: Bool + @ObservedObject var uploadAssets: NCUploadAssets + + func makeUIViewController(context: Context) -> UINavigationController { + let controller = QLPreviewController() + + controller.dataSource = context.coordinator + 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) + ) + + uploadAssets.startTimer(navigationItem: controller.navigationItem) + + let navigationController = UINavigationController(rootViewController: controller) + return navigationController + } + + func updateUIViewController(_ uiViewController: UINavigationController, context: Context) { } + + func makeCoordinator() -> Coordinator { + return Coordinator(parent: self) + } + + class Coordinator: NSObject, QLPreviewControllerDataSource, QLPreviewControllerDelegate, CropViewControllerDelegate { + + weak var viewController: QLPreviewController? + let parent: ViewerQuickLook + + var image: UIImage? + var hasChange = false + + init(parent: ViewerQuickLook) { + self.parent = parent + } + + @objc func dismiss() { + parent.uploadAssets.stopTimer() + parent.isPresentedQuickLook = false + if let image = image { + parent.uploadAssets.previewStore[parent.index].image = image + parent.uploadAssets.previewStore[parent.index].hasChanges = hasChange + } + } + + // MARK: - + + func numberOfPreviewItems(in controller: QLPreviewController) -> Int { + return 1 + } + + func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode { + return .createCopy + } + + func previewController(_ controller: QLPreviewController, didSaveEditedCopyOf previewItem: QLPreviewItem, at modifiedContentsURL: URL) { + guard NCUtilityFileSystem.shared.moveFile(atPath: modifiedContentsURL.path, toPath: parent.url.path) else { return } + if let image = UIImage(contentsOfFile: parent.url.path) { + self.image = image + self.hasChange = true + } + } + + func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem { + return parent.url as NSURL + } + + // MARK: - + + func cropViewControllerDidCrop(_ cropViewController: Mantis.CropViewController, cropped: UIImage, transformation: Mantis.Transformation, cropInfo: Mantis.CropInfo) { + cropViewController.dismiss(animated: true) + guard let data = cropped.jpegData(compressionQuality: 1) else { return } + do { + try data.write(to: parent.url) + self.image = cropped + self.hasChange = true + viewController?.reloadData() + } catch { } + } + func cropViewControllerDidCancel(_ cropViewController: Mantis.CropViewController, original: UIImage) { + cropViewController.dismiss(animated: true) + } + + func cropViewControllerDidFailToCrop(_ cropViewController: Mantis.CropViewController, original: UIImage) {} + func cropViewControllerDidBeginResize(_ cropViewController: Mantis.CropViewController) {} + func cropViewControllerDidEndResize(_ cropViewController: Mantis.CropViewController, original: UIImage, cropInfo: Mantis.CropInfo) {} + func cropViewControllerDidImageTransformed(_ cropViewController: Mantis.CropViewController) { } + + @objc func crop() { + + guard let image = UIImage(contentsOfFile: parent.url.path) else { return } + let 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) + + cropViewController.delegate = self + cropViewController.modalPresentationStyle = .fullScreen + + viewController?.present(cropViewController, animated: true) + } + } +}