|  |  |  | // | 
					
						
							|  |  |  | //  Copyright (c) 2018 Open Whisper Systems. All rights reserved. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import UIKit | 
					
						
							|  |  |  | import SessionUIKit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public enum PhotoGridItemType { | 
					
						
							|  |  |  |     case photo, animated, video | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public protocol PhotoGridItem: AnyObject { | 
					
						
							|  |  |  |     var type: PhotoGridItemType { get } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     func asyncThumbnail(completion: @escaping (UIImage?) -> Void) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public class PhotoGridViewCell: UICollectionViewCell { | 
					
						
							|  |  |  |     public let imageView: UIImageView | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private let contentTypeBadgeView: UIImageView | 
					
						
							|  |  |  |     private let selectedBadgeView: UIImageView | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private let highlightedView: UIView | 
					
						
							|  |  |  |     private let selectedView: UIView | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var item: PhotoGridItem? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static let videoBadgeImage = #imageLiteral(resourceName: "ic_gallery_badge_video") | 
					
						
							|  |  |  |     private static let animatedBadgeImage = #imageLiteral(resourceName: "ic_gallery_badge_gif") | 
					
						
							|  |  |  |     private static let selectedBadgeImage = UIImage(systemName: "checkmark.circle.fill") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public var loadingColor: ThemeValue = .textSecondary | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     override public var isSelected: Bool { | 
					
						
							|  |  |  |         didSet { | 
					
						
							|  |  |  |             self.selectedBadgeView.isHidden = !self.isSelected | 
					
						
							|  |  |  |             self.selectedView.isHidden = !self.isSelected | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     override public var isHighlighted: Bool { | 
					
						
							|  |  |  |         didSet { | 
					
						
							|  |  |  |             self.highlightedView.isHidden = !self.isHighlighted | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     override init(frame: CGRect) { | 
					
						
							|  |  |  |         self.imageView = UIImageView() | 
					
						
							|  |  |  |         imageView.contentMode = .scaleAspectFill | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.contentTypeBadgeView = UIImageView() | 
					
						
							|  |  |  |         contentTypeBadgeView.isHidden = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let kSelectedBadgeSize = CGSize(width: 32, height: 32) | 
					
						
							|  |  |  |         self.selectedBadgeView = UIImageView() | 
					
						
							|  |  |  |         selectedBadgeView.image = PhotoGridViewCell.selectedBadgeImage?.withRenderingMode(.alwaysTemplate) | 
					
						
							|  |  |  |         selectedBadgeView.themeTintColor = .primary | 
					
						
							|  |  |  |         selectedBadgeView.themeBorderColor = .textPrimary | 
					
						
							|  |  |  |         selectedBadgeView.themeBackgroundColor = .textPrimary | 
					
						
							|  |  |  |         selectedBadgeView.isHidden = true | 
					
						
							|  |  |  |         selectedBadgeView.layer.cornerRadius = (kSelectedBadgeSize.width / 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.highlightedView = UIView() | 
					
						
							|  |  |  |         highlightedView.alpha = 0.2 | 
					
						
							|  |  |  |         highlightedView.themeBackgroundColor = .black | 
					
						
							|  |  |  |         highlightedView.isHidden = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.selectedView = UIView() | 
					
						
							|  |  |  |         selectedView.alpha = 0.3 | 
					
						
							|  |  |  |         selectedView.themeBackgroundColor = .black | 
					
						
							|  |  |  |         selectedView.isHidden = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         super.init(frame: frame) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.clipsToBounds = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.contentView.addSubview(imageView) | 
					
						
							|  |  |  |         self.contentView.addSubview(contentTypeBadgeView) | 
					
						
							|  |  |  |         self.contentView.addSubview(highlightedView) | 
					
						
							|  |  |  |         self.contentView.addSubview(selectedView) | 
					
						
							|  |  |  |         self.contentView.addSubview(selectedBadgeView) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         imageView.autoPinEdgesToSuperviewEdges() | 
					
						
							|  |  |  |         highlightedView.autoPinEdgesToSuperviewEdges() | 
					
						
							|  |  |  |         selectedView.autoPinEdgesToSuperviewEdges() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Note assets were rendered to match exactly. We don't want to re-size with | 
					
						
							|  |  |  |         // content mode lest they become less legible. | 
					
						
							|  |  |  |         let kContentTypeBadgeSize = CGSize(width: 18, height: 12) | 
					
						
							|  |  |  |         contentTypeBadgeView.autoPinEdge(toSuperviewEdge: .leading, withInset: 3) | 
					
						
							|  |  |  |         contentTypeBadgeView.autoPinEdge(toSuperviewEdge: .bottom, withInset: 3) | 
					
						
							|  |  |  |         contentTypeBadgeView.autoSetDimensions(to: kContentTypeBadgeSize) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         selectedBadgeView.autoPinEdge(toSuperviewEdge: .trailing, withInset: Values.verySmallSpacing) | 
					
						
							|  |  |  |         selectedBadgeView.autoPinEdge(toSuperviewEdge: .bottom, withInset: Values.verySmallSpacing) | 
					
						
							|  |  |  |         selectedBadgeView.autoSetDimensions(to: kSelectedBadgeSize) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @available(*, unavailable, message: "Unimplemented") | 
					
						
							|  |  |  |     required public init?(coder aDecoder: NSCoder) { | 
					
						
							|  |  |  |         notImplemented() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var image: UIImage? { | 
					
						
							|  |  |  |         get { return imageView.image } | 
					
						
							|  |  |  |         set { | 
					
						
							|  |  |  |             imageView.image = newValue | 
					
						
							|  |  |  |             imageView.themeBackgroundColor = (newValue == nil ? loadingColor : .clear) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var contentTypeBadgeImage: UIImage? { | 
					
						
							|  |  |  |         get { return contentTypeBadgeView.image } | 
					
						
							|  |  |  |         set { | 
					
						
							|  |  |  |             contentTypeBadgeView.image = newValue | 
					
						
							|  |  |  |             contentTypeBadgeView.isHidden = newValue == nil | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public func configure(item: PhotoGridItem) { | 
					
						
							|  |  |  |         self.item = item | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         item.asyncThumbnail { [weak self] image in | 
					
						
							|  |  |  |             guard let currentItem = self?.item else { return } | 
					
						
							|  |  |  |             guard currentItem === item else { return } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if image == nil { | 
					
						
							|  |  |  |                 Logger.debug("image == nil") | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             DispatchQueue.main.async { | 
					
						
							|  |  |  |                 self?.image = image | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch item.type { | 
					
						
							|  |  |  |             case .video: self.contentTypeBadgeImage = PhotoGridViewCell.videoBadgeImage | 
					
						
							|  |  |  |             case .animated: self.contentTypeBadgeImage = PhotoGridViewCell.animatedBadgeImage | 
					
						
							|  |  |  |             case .photo: self.contentTypeBadgeImage = nil | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     override public func prepareForReuse() { | 
					
						
							|  |  |  |         super.prepareForReuse() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.item = nil | 
					
						
							|  |  |  |         self.imageView.image = nil | 
					
						
							|  |  |  |         self.contentTypeBadgeView.isHidden = true | 
					
						
							|  |  |  |         self.highlightedView.isHidden = true | 
					
						
							|  |  |  |         self.selectedView.isHidden = true | 
					
						
							|  |  |  |         self.selectedBadgeView.isHidden = true | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |