NCSharePaging.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. //
  2. // NCSharePaging.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 25/07/2019.
  6. // Copyright © 2019 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. // Author Henrik Storch <henrik.storch@nextcloud.com>
  10. //
  11. // This program is free software: you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published by
  13. // the Free Software Foundation, either version 3 of the License, or
  14. // (at your option) any later version.
  15. //
  16. // This program is distributed in the hope that it will be useful,
  17. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. // GNU General Public License for more details.
  20. //
  21. // You should have received a copy of the GNU General Public License
  22. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. //
  24. import UIKit
  25. import Parchment
  26. import NextcloudKit
  27. import MarqueeLabel
  28. import TagListView
  29. protocol NCSharePagingContent {
  30. var textField: UIView? { get }
  31. }
  32. class NCSharePaging: UIViewController {
  33. private let pagingViewController = NCShareHeaderViewController()
  34. private weak var appDelegate = UIApplication.shared.delegate as? AppDelegate
  35. private var currentVC: NCSharePagingContent?
  36. private let applicationHandle = NCApplicationHandle()
  37. var metadata = tableMetadata()
  38. var pages: [NCBrandOptions.NCInfoPagingTab] = []
  39. var page: NCBrandOptions.NCInfoPagingTab = .activity
  40. // MARK: - View Life Cycle
  41. override func viewDidLoad() {
  42. super.viewDidLoad()
  43. view.backgroundColor = .systemBackground
  44. title = NSLocalizedString("_details_", comment: "")
  45. navigationController?.navigationBar.tintColor = NCBrandColor.shared.iconImageColor
  46. navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_close_", comment: ""), style: .done, target: self, action: #selector(exitTapped))
  47. NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
  48. NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
  49. NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(notification:)), name: UIApplication.didEnterBackgroundNotification, object: nil)
  50. // *** MUST BE THE FIRST ONE ***
  51. pagingViewController.metadata = metadata
  52. pagingViewController.backgroundColor = .systemBackground
  53. pagingViewController.menuBackgroundColor = .systemBackground
  54. pagingViewController.selectedBackgroundColor = .systemBackground
  55. pagingViewController.indicatorColor = NCBrandColor.shared.getElement(account: metadata.account)
  56. pagingViewController.textColor = NCBrandColor.shared.textColor
  57. pagingViewController.selectedTextColor = NCBrandColor.shared.getElement(account: metadata.account)
  58. // Pagination
  59. addChild(pagingViewController)
  60. view.addSubview(pagingViewController.view)
  61. pagingViewController.didMove(toParent: self)
  62. // Customization
  63. pagingViewController.indicatorOptions = .visible(
  64. height: 1,
  65. zIndex: Int.max,
  66. spacing: .zero,
  67. insets: .zero
  68. )
  69. pagingViewController.borderOptions = .visible(height: 1, zIndex: Int.max, insets: .zero)
  70. // Contrain the paging view to all edges.
  71. pagingViewController.view.translatesAutoresizingMaskIntoConstraints = false
  72. NSLayoutConstraint.activate([
  73. pagingViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
  74. pagingViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
  75. pagingViewController.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
  76. pagingViewController.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
  77. ])
  78. pagingViewController.dataSource = self
  79. pagingViewController.delegate = self
  80. if page.rawValue < pages.count {
  81. pagingViewController.select(index: page.rawValue)
  82. } else {
  83. pagingViewController.select(index: 0)
  84. }
  85. pagingViewController.reloadMenu()
  86. }
  87. override func viewDidAppear(_ animated: Bool) {
  88. super.viewDidAppear(animated)
  89. currentVC = pagingViewController.pageViewController.selectedViewController as? NCSharePagingContent
  90. }
  91. override func viewWillAppear(_ animated: Bool) {
  92. super.viewWillAppear(animated)
  93. if NCCapabilities.shared.disableSharesView(account: metadata.account) {
  94. self.dismiss(animated: false, completion: nil)
  95. }
  96. // pagingViewController.menuItemSize = .fixed(
  97. // width: self.view.bounds.width / CGFloat(self.pages.count),
  98. // height: 40)
  99. }
  100. override func viewWillDisappear(_ animated: Bool) {
  101. super.viewWillDisappear(animated)
  102. NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
  103. }
  104. deinit {
  105. NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidShowNotification, object: nil)
  106. NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
  107. NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil)
  108. }
  109. override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
  110. super.viewWillTransition(to: size, with: coordinator)
  111. self.currentVC?.textField?.resignFirstResponder()
  112. }
  113. // MARK: - NotificationCenter & Keyboard & TextField
  114. @objc func keyboardWillShow(notification: Notification) {
  115. let frameEndUserInfoKey = UIResponder.keyboardFrameEndUserInfoKey
  116. guard let info = notification.userInfo,
  117. let textField = currentVC?.textField,
  118. let centerObject = textField.superview?.convert(textField.center, to: nil),
  119. let keyboardFrame = info[frameEndUserInfoKey] as? CGRect
  120. else { return }
  121. let diff = keyboardFrame.origin.y - centerObject.y - textField.frame.height
  122. if diff < 0 {
  123. view.frame.origin.y = diff
  124. }
  125. }
  126. @objc func keyboardWillHide(notification: NSNotification) {
  127. view.frame.origin.y = 0
  128. }
  129. @objc func exitTapped() {
  130. self.dismiss(animated: true, completion: nil)
  131. }
  132. @objc func applicationDidEnterBackground(notification: Notification) {
  133. self.dismiss(animated: false, completion: nil)
  134. }
  135. }
  136. // MARK: - PagingViewController Delegate
  137. extension NCSharePaging: PagingViewControllerDelegate {
  138. func pagingViewController(_ pagingViewController: PagingViewController, willScrollToItem pagingItem: PagingItem, startingViewController: UIViewController, destinationViewController: UIViewController) {
  139. currentVC?.textField?.resignFirstResponder()
  140. self.currentVC = destinationViewController as? NCSharePagingContent
  141. }
  142. }
  143. // MARK: - PagingViewController DataSource
  144. extension NCSharePaging: PagingViewControllerDataSource {
  145. func pagingViewController(_: PagingViewController, viewControllerAt index: Int) -> UIViewController {
  146. let height: CGFloat = 50
  147. if pages[index] == .activity {
  148. guard let viewController = UIStoryboard(name: "NCActivity", bundle: nil).instantiateInitialViewController() as? NCActivity else {
  149. return UIViewController()
  150. }
  151. viewController.height = height
  152. viewController.showComments = true
  153. viewController.didSelectItemEnable = false
  154. viewController.metadata = metadata
  155. viewController.objectType = "files"
  156. viewController.account = metadata.account
  157. return viewController
  158. } else if pages[index] == .sharing {
  159. guard let viewController = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "sharing") as? NCShare else {
  160. return UIViewController()
  161. }
  162. viewController.metadata = metadata
  163. viewController.height = height
  164. return viewController
  165. } else {
  166. return applicationHandle.pagingViewController(pagingViewController, viewControllerAt: index, metadata: metadata, topHeight: height)
  167. }
  168. }
  169. func pagingViewController(_: PagingViewController, pagingItemAt index: Int) -> PagingItem {
  170. if pages[index] == .activity {
  171. return PagingIndexItem(index: index, title: NSLocalizedString("_activity_", comment: ""))
  172. } else if pages[index] == .sharing {
  173. return PagingIndexItem(index: index, title: NSLocalizedString("_sharing_", comment: ""))
  174. } else {
  175. return applicationHandle.pagingViewController(pagingViewController, pagingItemAt: index)
  176. }
  177. }
  178. func numberOfViewControllers(in pagingViewController: PagingViewController) -> Int {
  179. return self.pages.count
  180. }
  181. }
  182. // MARK: - Header
  183. class NCShareHeaderViewController: PagingViewController {
  184. public var image: UIImage?
  185. public var metadata = tableMetadata()
  186. public var activityEnabled = true
  187. public var commentsEnabled = true
  188. public var sharingEnabled = true
  189. override func loadView() {
  190. view = NCSharePagingView(
  191. options: options,
  192. collectionView: collectionView,
  193. pageView: pageViewController.view,
  194. metadata: metadata
  195. )
  196. }
  197. }
  198. class NCSharePagingView: PagingView {
  199. var metadata = tableMetadata()
  200. let utilityFileSystem = NCUtilityFileSystem()
  201. let utility = NCUtility()
  202. public var headerHeightConstraint: NSLayoutConstraint?
  203. var header: NCShareHeader?
  204. // MARK: - View Life Cycle
  205. public init(options: Parchment.PagingOptions, collectionView: UICollectionView, pageView: UIView, metadata: tableMetadata) {
  206. super.init(options: options, collectionView: collectionView, pageView: pageView)
  207. self.metadata = metadata
  208. }
  209. required init?(coder: NSCoder) {
  210. fatalError("init(coder:) has not been implemented")
  211. }
  212. override func setupConstraints() {
  213. guard let headerView = Bundle.main.loadNibNamed("NCShareHeader", owner: self, options: nil)?.first as? NCShareHeader else { return }
  214. header = headerView
  215. headerView.backgroundColor = .systemBackground
  216. let dateFormatter = DateFormatter()
  217. dateFormatter.dateStyle = .short
  218. dateFormatter.timeStyle = .short
  219. dateFormatter.locale = Locale.current
  220. headerView.setupUI(with: metadata)
  221. addSubview(headerView)
  222. collectionView.translatesAutoresizingMaskIntoConstraints = false
  223. headerView.translatesAutoresizingMaskIntoConstraints = false
  224. pageView.translatesAutoresizingMaskIntoConstraints = false
  225. NSLayoutConstraint.activate([
  226. collectionView.leadingAnchor.constraint(equalTo: leadingAnchor),
  227. collectionView.trailingAnchor.constraint(equalTo: trailingAnchor),
  228. collectionView.heightAnchor.constraint(equalToConstant: options.menuHeight),
  229. collectionView.topAnchor.constraint(equalTo: headerView.bottomAnchor),
  230. headerView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
  231. headerView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
  232. headerView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
  233. pageView.leadingAnchor.constraint(equalTo: leadingAnchor),
  234. pageView.trailingAnchor.constraint(equalTo: trailingAnchor),
  235. pageView.bottomAnchor.constraint(equalTo: bottomAnchor),
  236. pageView.topAnchor.constraint(equalTo: headerView.bottomAnchor)
  237. ])
  238. }
  239. }
  240. class NCShareHeaderView: UIView {
  241. @IBOutlet weak var imageView: UIImageView!
  242. @IBOutlet weak var path: MarqueeLabel!
  243. @IBOutlet weak var info: UILabel!
  244. @IBOutlet weak var creation: UILabel!
  245. @IBOutlet weak var upload: UILabel!
  246. @IBOutlet weak var favorite: UIButton!
  247. @IBOutlet weak var details: UIButton!
  248. @IBOutlet weak var tagListView: TagListView!
  249. var ocId = ""
  250. override func awakeFromNib() {
  251. super.awakeFromNib()
  252. let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longTap))
  253. path.addGestureRecognizer(longGesture)
  254. }
  255. @IBAction func touchUpInsideFavorite(_ sender: UIButton) {
  256. guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return }
  257. NCNetworking.shared.favoriteMetadata(metadata) { error in
  258. if error == .success {
  259. guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) else { return }
  260. self.favorite.setImage(NCUtility().loadImage(
  261. named: "star.fill",
  262. colors: metadata.favorite ? [NCBrandColor.shared.yellowFavorite] : [NCBrandColor.shared.iconImageColor2],
  263. size: 20), for: .normal)
  264. } else {
  265. NCContentPresenter().showError(error: error)
  266. }
  267. }
  268. }
  269. @IBAction func touchUpInsideDetails(_ sender: UIButton) {
  270. creation.isHidden = !creation.isHidden
  271. upload.isHidden = !upload.isHidden
  272. }
  273. @objc func longTap(sender: UIGestureRecognizer) {
  274. UIPasteboard.general.string = path.text
  275. let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_copied_path_")
  276. NCContentPresenter().showInfo(error: error)
  277. }
  278. }