NCListCell.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. //
  2. // NCListCell.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 24/10/2018.
  6. // Copyright © 2018 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 UIKit
  24. class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol {
  25. @IBOutlet weak var imageItem: UIImageView!
  26. @IBOutlet weak var imageSelect: UIImageView!
  27. @IBOutlet weak var imageStatus: UIImageView!
  28. @IBOutlet weak var imageFavorite: UIImageView!
  29. @IBOutlet weak var imageFavoriteBackground: UIImageView!
  30. @IBOutlet weak var imageLocal: UIImageView!
  31. @IBOutlet weak var labelTitle: UILabel!
  32. @IBOutlet weak var labelInfo: UILabel!
  33. @IBOutlet weak var labelSubinfo: UILabel!
  34. @IBOutlet weak var imageShared: UIImageView!
  35. @IBOutlet weak var buttonShared: UIButton!
  36. @IBOutlet weak var imageMore: UIImageView!
  37. @IBOutlet weak var buttonMore: UIButton!
  38. @IBOutlet weak var progressView: UIProgressView!
  39. @IBOutlet weak var separator: UIView!
  40. @IBOutlet weak var tag0: UILabel!
  41. @IBOutlet weak var tag1: UILabel!
  42. @IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint!
  43. @IBOutlet weak var separatorHeightConstraint: NSLayoutConstraint!
  44. @IBOutlet weak var titleTrailingConstraint: NSLayoutConstraint!
  45. @IBOutlet weak var subInfoTrailingConstraint: NSLayoutConstraint!
  46. private var objectId = ""
  47. private var user = ""
  48. var indexPath = IndexPath()
  49. weak var listCellDelegate: NCListCellDelegate?
  50. var namedButtonMore = ""
  51. var fileAvatarImageView: UIImageView? {
  52. return imageShared
  53. }
  54. var fileObjectId: String? {
  55. get { return objectId }
  56. set { objectId = newValue ?? "" }
  57. }
  58. var filePreviewImageView: UIImageView? {
  59. get { return imageItem }
  60. set { imageItem = newValue }
  61. }
  62. var fileUser: String? {
  63. get { return user }
  64. set { user = newValue ?? "" }
  65. }
  66. var fileTitleLabel: UILabel? {
  67. get { return labelTitle }
  68. set { labelTitle = newValue }
  69. }
  70. var fileInfoLabel: UILabel? {
  71. get { return labelInfo }
  72. set { labelInfo = newValue }
  73. }
  74. var fileSubinfoLabel: UILabel? {
  75. get { return labelSubinfo }
  76. set { labelSubinfo = newValue }
  77. }
  78. var fileProgressView: UIProgressView? {
  79. get { return progressView }
  80. set { progressView = newValue }
  81. }
  82. var fileStatusImage: UIImageView? {
  83. get { return imageStatus }
  84. set { imageStatus = newValue }
  85. }
  86. var fileLocalImage: UIImageView? {
  87. get { return imageLocal }
  88. set { imageLocal = newValue }
  89. }
  90. var fileFavoriteImage: UIImageView? {
  91. get { return imageFavorite }
  92. set { imageFavorite = newValue }
  93. }
  94. var fileSharedImage: UIImageView? {
  95. get { return imageShared }
  96. set { imageShared = newValue }
  97. }
  98. var fileMoreImage: UIImageView? {
  99. get { return imageMore }
  100. set { imageMore = newValue }
  101. }
  102. var cellSeparatorView: UIView? {
  103. get { return separator }
  104. set { separator = newValue }
  105. }
  106. override func awakeFromNib() {
  107. super.awakeFromNib()
  108. imageItem.layer.cornerRadius = 6
  109. imageItem.layer.masksToBounds = true
  110. // use entire cell as accessibility element
  111. accessibilityHint = nil
  112. accessibilityLabel = nil
  113. accessibilityValue = nil
  114. isAccessibilityElement = true
  115. progressView.tintColor = NCBrandColor.shared.brandElement
  116. progressView.transform = CGAffineTransform(scaleX: 1.0, y: 0.5)
  117. progressView.trackTintColor = .clear
  118. let longPressedGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPress(gestureRecognizer:)))
  119. longPressedGesture.minimumPressDuration = 0.5
  120. longPressedGesture.delegate = self
  121. longPressedGesture.delaysTouchesBegan = true
  122. self.addGestureRecognizer(longPressedGesture)
  123. separator.backgroundColor = .separator
  124. separatorHeightConstraint.constant = 0.5
  125. labelTitle.text = ""
  126. labelInfo.text = ""
  127. labelSubinfo.text = ""
  128. labelTitle.textColor = NCBrandColor.shared.textColor
  129. labelInfo.textColor = NCBrandColor.shared.textColor2
  130. labelSubinfo.textColor = NCBrandColor.shared.textColor2
  131. imageFavoriteBackground.isHidden = true
  132. }
  133. override func prepareForReuse() {
  134. super.prepareForReuse()
  135. imageItem.backgroundColor = nil
  136. if fileFavoriteImage?.image != nil {
  137. imageFavoriteBackground.isHidden = false
  138. } else {
  139. imageFavoriteBackground.isHidden = true
  140. }
  141. accessibilityHint = nil
  142. accessibilityLabel = nil
  143. accessibilityValue = nil
  144. }
  145. override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? {
  146. return nil
  147. }
  148. @IBAction func touchUpInsideShare(_ sender: Any) {
  149. listCellDelegate?.tapShareListItem(with: objectId, indexPath: indexPath, sender: sender)
  150. }
  151. @IBAction func touchUpInsideMore(_ sender: Any) {
  152. listCellDelegate?.tapMoreListItem(with: objectId, namedButtonMore: namedButtonMore, image: imageItem.image, indexPath: indexPath, sender: sender)
  153. }
  154. @objc func longPress(gestureRecognizer: UILongPressGestureRecognizer) {
  155. listCellDelegate?.longPressListItem(with: objectId, indexPath: indexPath, gestureRecognizer: gestureRecognizer)
  156. }
  157. fileprivate func setA11yActions() {
  158. let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_"
  159. self.accessibilityCustomActions = [
  160. UIAccessibilityCustomAction(
  161. name: NSLocalizedString("_share_", comment: ""),
  162. target: self,
  163. selector: #selector(touchUpInsideShare)),
  164. UIAccessibilityCustomAction(
  165. name: NSLocalizedString(moreName, comment: ""),
  166. target: self,
  167. selector: #selector(touchUpInsideMore))
  168. ]
  169. }
  170. func titleInfoTrailingFull() {
  171. titleTrailingConstraint.constant = 10
  172. subInfoTrailingConstraint.constant = 10
  173. }
  174. func titleInfoTrailingDefault() {
  175. titleTrailingConstraint.constant = 90
  176. subInfoTrailingConstraint.constant = 90
  177. }
  178. func setButtonMore(named: String, image: UIImage) {
  179. namedButtonMore = named
  180. imageMore.image = image
  181. setA11yActions()
  182. }
  183. func hideButtonMore(_ status: Bool) {
  184. imageMore.isHidden = status
  185. buttonMore.isHidden = status
  186. }
  187. func hideButtonShare(_ status: Bool) {
  188. imageShared.isHidden = status
  189. buttonShared.isHidden = status
  190. }
  191. func hideSeparator(_ status: Bool) {
  192. separator.isHidden = status
  193. }
  194. func selected(_ status: Bool, isEditMode: Bool) {
  195. if isEditMode {
  196. imageItemLeftConstraint.constant = 45
  197. imageSelect.isHidden = false
  198. imageShared.isHidden = true
  199. imageMore.isHidden = true
  200. buttonShared.isHidden = true
  201. buttonMore.isHidden = true
  202. accessibilityCustomActions = nil
  203. } else {
  204. imageItemLeftConstraint.constant = 10
  205. imageSelect.isHidden = true
  206. imageShared.isHidden = false
  207. imageMore.isHidden = false
  208. buttonShared.isHidden = false
  209. buttonMore.isHidden = false
  210. backgroundView = nil
  211. setA11yActions()
  212. }
  213. if status {
  214. var blurEffectView: UIView?
  215. blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial))
  216. blurEffectView?.backgroundColor = .lightGray
  217. blurEffectView?.frame = self.bounds
  218. blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  219. imageSelect.image = NCImageCache.images.checkedYes
  220. backgroundView = blurEffectView
  221. separator.isHidden = true
  222. } else {
  223. imageSelect.image = NCImageCache.images.checkedNo
  224. backgroundView = nil
  225. separator.isHidden = false
  226. }
  227. }
  228. func writeInfoDateSize(date: NSDate, size: Int64) {
  229. labelInfo.text = NCUtility().dateDiff(date as Date)
  230. labelSubinfo.text = " · " + NCUtilityFileSystem().transformedSize(size)
  231. }
  232. func setAccessibility(label: String, value: String) {
  233. accessibilityLabel = label
  234. accessibilityValue = value
  235. }
  236. func setTags(tags: [String]) {
  237. if tags.isEmpty {
  238. tag0.isHidden = true
  239. tag1.isHidden = true
  240. labelInfo.isHidden = false
  241. labelSubinfo.isHidden = false
  242. } else {
  243. tag0.isHidden = false
  244. tag1.isHidden = true
  245. labelInfo.isHidden = true
  246. labelSubinfo.isHidden = true
  247. if let tag = tags.first {
  248. tag0.text = tag
  249. if tags.count > 1 {
  250. tag1.isHidden = false
  251. tag1.text = "+\(tags.count - 1)"
  252. }
  253. }
  254. }
  255. }
  256. func setIconOutlines() {
  257. imageFavoriteBackground.isHidden = fileFavoriteImage?.image == nil
  258. if imageStatus.image != nil {
  259. imageStatus.makeCircularBackground(withColor: .systemBackground)
  260. } else {
  261. imageStatus.backgroundColor = .clear
  262. }
  263. if imageLocal.image != nil {
  264. imageLocal.makeCircularBackground(withColor: .systemBackground)
  265. } else {
  266. imageLocal.backgroundColor = .clear
  267. }
  268. }
  269. }
  270. protocol NCListCellDelegate: AnyObject {
  271. func tapShareListItem(with objectId: String, indexPath: IndexPath, sender: Any)
  272. func tapMoreListItem(with objectId: String, namedButtonMore: String, image: UIImage?, indexPath: IndexPath, sender: Any)
  273. func longPressListItem(with objectId: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer)
  274. }
  275. // MARK: - List Layout
  276. class NCListLayout: UICollectionViewFlowLayout {
  277. var itemHeight: CGFloat = 60
  278. override init() {
  279. super.init()
  280. sectionHeadersPinToVisibleBounds = false
  281. minimumInteritemSpacing = 0
  282. minimumLineSpacing = 1
  283. self.scrollDirection = .vertical
  284. self.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
  285. }
  286. required init?(coder aDecoder: NSCoder) {
  287. fatalError("init(coder:) has not been implemented")
  288. }
  289. override var itemSize: CGSize {
  290. get {
  291. if let collectionView = collectionView {
  292. let itemWidth: CGFloat = collectionView.frame.width
  293. return CGSize(width: itemWidth, height: self.itemHeight)
  294. }
  295. return CGSize(width: 100, height: 100)
  296. }
  297. set {
  298. super.itemSize = newValue
  299. }
  300. }
  301. override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
  302. return proposedContentOffset
  303. }
  304. }