NCViewerQuickLookView.swift 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //
  2. // NCViewerQuickLookView.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 12/01/23.
  6. // Copyright © 2023 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import SwiftUI
  24. import QuickLook
  25. import Mantis
  26. import NextcloudKit
  27. struct NCViewerQuickLookView: UIViewControllerRepresentable {
  28. let url: URL
  29. @Binding var index: Int
  30. @Binding var isPresentedQuickLook: Bool
  31. @ObservedObject var model: NCUploadAssetsModel
  32. func makeUIViewController(context: Context) -> UINavigationController {
  33. let controller = QLPreviewController()
  34. controller.dataSource = context.coordinator
  35. controller.delegate = context.coordinator
  36. context.coordinator.viewController = controller
  37. let buttonDone = UIBarButtonItem(barButtonSystemItem: .done, target: context.coordinator, action: #selector(context.coordinator.dismiss))
  38. let buttonCrop = UIBarButtonItem(image: NCUtility().loadImage(named: "crop"), style: .plain, target: context.coordinator, action: #selector(context.coordinator.crop))
  39. controller.navigationItem.leftBarButtonItems = [buttonDone, buttonCrop]
  40. model.startTimer(navigationItem: controller.navigationItem)
  41. DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
  42. if model.previewStore[index].assetType == .livePhoto && model.previewStore[index].asset.type == .livePhoto && model.previewStore[index].data == nil {
  43. let error = NKError(errorCode: NCGlobal.shared.errorCharactersForbidden, errorDescription: "_message_disable_livephoto_")
  44. NCContentPresenter().showInfo(error: error)
  45. }
  46. }
  47. let navigationController = UINavigationController(rootViewController: controller)
  48. return navigationController
  49. }
  50. func updateUIViewController(_ uiViewController: UINavigationController, context: Context) { }
  51. func makeCoordinator() -> Coordinator {
  52. return Coordinator(parent: self)
  53. }
  54. class Coordinator: NSObject, QLPreviewControllerDataSource, QLPreviewControllerDelegate, CropViewControllerDelegate {
  55. weak var viewController: QLPreviewController?
  56. let parent: NCViewerQuickLookView
  57. var image: UIImage?
  58. var hasChange = false
  59. init(parent: NCViewerQuickLookView) {
  60. self.parent = parent
  61. }
  62. @objc func dismiss() {
  63. parent.model.stopTimer()
  64. parent.isPresentedQuickLook = false
  65. if let imageData = image, let image = image?.resizeImage(size: CGSize(width: 300, height: 300), isAspectRation: true) {
  66. parent.model.previewStore[parent.index].image = image
  67. parent.model.previewStore[parent.index].data = imageData.jpegData(compressionQuality: 0.9)
  68. }
  69. }
  70. // MARK: -
  71. func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
  72. return 1
  73. }
  74. func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode {
  75. return .createCopy
  76. }
  77. func previewController(_ controller: QLPreviewController, didSaveEditedCopyOf previewItem: QLPreviewItem, at modifiedContentsURL: URL) {
  78. guard NCUtilityFileSystem().moveFile(atPath: modifiedContentsURL.path, toPath: parent.url.path) else { return }
  79. if let image = UIImage(contentsOfFile: parent.url.path) {
  80. self.image = image
  81. self.hasChange = true
  82. }
  83. }
  84. func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
  85. return parent.url as NSURL
  86. }
  87. // MARK: -
  88. func cropViewControllerDidCrop(_ cropViewController: Mantis.CropViewController, cropped: UIImage, transformation: Mantis.Transformation, cropInfo: Mantis.CropInfo) {
  89. cropViewController.dismiss(animated: true)
  90. guard let data = cropped.pngData() else { return }
  91. do {
  92. try data.write(to: parent.url)
  93. self.image = cropped
  94. self.hasChange = true
  95. viewController?.reloadData()
  96. } catch { }
  97. }
  98. func cropViewControllerDidCancel(_ cropViewController: Mantis.CropViewController, original: UIImage) {
  99. cropViewController.dismiss(animated: true)
  100. }
  101. func cropViewControllerDidFailToCrop(_ cropViewController: Mantis.CropViewController, original: UIImage) {}
  102. func cropViewControllerDidBeginResize(_ cropViewController: Mantis.CropViewController) {}
  103. func cropViewControllerDidEndResize(_ cropViewController: Mantis.CropViewController, original: UIImage, cropInfo: Mantis.CropInfo) {}
  104. func cropViewControllerDidImageTransformed(_ cropViewController: Mantis.CropViewController) { }
  105. @objc func crop() {
  106. guard let image = UIImage(contentsOfFile: parent.url.path) else { return }
  107. var toolbarConfig = CropToolbarConfig()
  108. toolbarConfig.heightForVerticalOrientation = 80
  109. toolbarConfig.widthForHorizontalOrientation = 100
  110. toolbarConfig.optionButtonFontSize = 16
  111. toolbarConfig.optionButtonFontSizeForPad = 21
  112. toolbarConfig.backgroundColor = .systemGray6
  113. toolbarConfig.foregroundColor = .systemBlue
  114. var viewConfig = CropViewConfig()
  115. viewConfig.cropMaskVisualEffectType = .none
  116. viewConfig.cropBorderColor = .red
  117. var config = Mantis.Config()
  118. if let bundleIdentifier = Bundle.main.bundleIdentifier {
  119. config.localizationConfig.bundle = Bundle(identifier: bundleIdentifier)
  120. config.localizationConfig.tableName = "Localizable"
  121. }
  122. config.cropToolbarConfig = toolbarConfig
  123. config.cropViewConfig = viewConfig
  124. let toolbar = CropToolbar()
  125. toolbar.iconProvider = CropToolbarIcon()
  126. let cropViewController = Mantis.cropViewController(image: image, config: config, cropToolbar: toolbar)
  127. cropViewController.delegate = self
  128. cropViewController.backgroundColor = .systemBackground
  129. cropViewController.modalPresentationStyle = .fullScreen
  130. viewController?.present(cropViewController, animated: true)
  131. }
  132. }
  133. class CropToolbarIcon: CropToolbarIconProvider {
  134. func getCropIcon() -> UIImage? {
  135. return NCUtility().loadImage(named: "checkmark.circle")
  136. }
  137. func getCancelIcon() -> UIImage? {
  138. return NCUtility().loadImage(named: "xmark.circle")
  139. }
  140. }
  141. }