mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			467 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Swift
		
	
		
		
			
		
	
	
			467 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Swift
		
	
| 
											7 years ago
										 | // | ||
| 
											7 years ago
										 | //  Copyright (c) 2019 Open Whisper Systems. All rights reserved. | ||
| 
											7 years ago
										 | // | ||
|  | 
 | ||
|  | import Foundation | ||
|  | 
 | ||
| 
											7 years ago
										 | @objc | ||
| 
											7 years ago
										 | public class MenuAction: NSObject { | ||
|  |     let block: (MenuAction) -> Void | ||
|  |     let image: UIImage | ||
|  |     let title: String | ||
|  |     let subtitle: String? | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     public init(image: UIImage, title: String, subtitle: String?, block: @escaping (MenuAction) -> Void) { | ||
|  |         self.image = image | ||
|  |         self.title = title | ||
|  |         self.subtitle = subtitle | ||
|  |         self.block = block | ||
| 
											7 years ago
										 |     } | ||
| 
											7 years ago
										 | } | ||
|  | 
 | ||
| 
											7 years ago
										 | @objc | ||
|  | protocol MenuActionsViewControllerDelegate: class { | ||
| 
											7 years ago
										 |     func menuActionsWillPresent(_ menuActionsViewController: MenuActionsViewController) | ||
|  |     func menuActionsIsPresenting(_ menuActionsViewController: MenuActionsViewController) | ||
|  |     func menuActionsDidPresent(_ menuActionsViewController: MenuActionsViewController) | ||
|  | 
 | ||
|  |     func menuActionsIsDismissing(_ menuActionsViewController: MenuActionsViewController) | ||
|  |     func menuActionsDidDismiss(_ menuActionsViewController: MenuActionsViewController) | ||
| 
											7 years ago
										 | } | ||
|  | 
 | ||
| 
											7 years ago
										 | @objc | ||
| 
											7 years ago
										 | class MenuActionsViewController: UIViewController, MenuActionSheetDelegate { | ||
| 
											7 years ago
										 | 
 | ||
|  |     @objc | ||
| 
											7 years ago
										 |     weak var delegate: MenuActionsViewControllerDelegate? | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     @objc | ||
| 
											7 years ago
										 |     public let focusedInteraction: TSInteraction | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     private let focusedView: UIView | ||
| 
											7 years ago
										 |     private let actionSheetView: MenuActionSheetView | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     deinit { | ||
| 
											7 years ago
										 |         Logger.verbose("") | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     @objc | ||
| 
											7 years ago
										 |     required init(focusedInteraction: TSInteraction, focusedView: UIView, actions: [MenuAction]) { | ||
| 
											7 years ago
										 |         self.focusedView = focusedView | ||
| 
											7 years ago
										 |         self.focusedInteraction = focusedInteraction | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |         self.actionSheetView = MenuActionSheetView(actions: actions) | ||
| 
											7 years ago
										 |         super.init(nibName: nil, bundle: nil) | ||
| 
											7 years ago
										 | 
 | ||
|  |         actionSheetView.delegate = self | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
|  |     required init?(coder aDecoder: NSCoder) { | ||
| 
											7 years ago
										 |         notImplemented() | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     // MARK: View LifeCycle | ||
|  | 
 | ||
| 
											7 years ago
										 |     var actionSheetViewVerticalConstraint: NSLayoutConstraint? | ||
|  | 
 | ||
| 
											7 years ago
										 |     override func loadView() { | ||
|  |         self.view = UIView() | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |         view.addSubview(actionSheetView) | ||
| 
											7 years ago
										 | 
 | ||
|  |         actionSheetView.autoPinWidthToSuperview() | ||
| 
											7 years ago
										 |         actionSheetView.setContentHuggingVerticalHigh() | ||
|  |         actionSheetView.setCompressionResistanceHigh() | ||
| 
											7 years ago
										 |         self.actionSheetViewVerticalConstraint = actionSheetView.autoPinEdge(.top, to: .bottom, of: self.view) | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |         let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapBackground)) | ||
|  |         self.view.addGestureRecognizer(tapGesture) | ||
| 
											7 years ago
										 |     } | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     override func viewDidAppear(_ animated: Bool) { | ||
|  |         super.viewDidAppear(true) | ||
|  | 
 | ||
| 
											7 years ago
										 |         self.animatePresentation() | ||
|  |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     override func viewDidDisappear(_ animated: Bool) { | ||
| 
											7 years ago
										 |         Logger.debug("") | ||
| 
											7 years ago
										 |         super.viewDidDisappear(animated) | ||
|  | 
 | ||
|  |         // When the user has manually dismissed the menu, we do a nice animation | ||
|  |         // but if the view otherwise disappears (e.g. due to resigning active), | ||
|  |         // we still want to give the delegate the information it needs to restore it's UI. | ||
| 
											7 years ago
										 |         delegate?.menuActionsDidDismiss(self) | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     // MARK: Orientation | ||
|  | 
 | ||
| 
											7 years ago
										 |     override public var supportedInterfaceOrientations: UIInterfaceOrientationMask { | ||
| 
											7 years ago
										 |         return DefaultUIInterfaceOrientationMask() | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     // MARK: Present / Dismiss animations | ||
|  | 
 | ||
|  |     var snapshotView: UIView? | ||
|  | 
 | ||
|  |     private func addSnapshotFocusedView() -> UIView? { | ||
|  |         guard let snapshotView = self.focusedView.snapshotView(afterScreenUpdates: false) else { | ||
| 
											7 years ago
										 |             owsFailDebug("snapshotView was unexpectedly nil") | ||
| 
											7 years ago
										 |             return nil | ||
|  |         } | ||
|  |         view.addSubview(snapshotView) | ||
|  | 
 | ||
|  |         guard let focusedViewSuperview = focusedView.superview else { | ||
| 
											7 years ago
										 |             owsFailDebug("focusedViewSuperview was unexpectedly nil") | ||
| 
											7 years ago
										 |             return nil | ||
|  |         } | ||
|  | 
 | ||
|  |         let convertedFrame = view.convert(focusedView.frame, from: focusedViewSuperview) | ||
|  |         snapshotView.frame = convertedFrame | ||
|  | 
 | ||
|  |         return snapshotView | ||
|  |     } | ||
|  | 
 | ||
|  |     private func animatePresentation() { | ||
| 
											7 years ago
										 |         guard let actionSheetViewVerticalConstraint = self.actionSheetViewVerticalConstraint else { | ||
| 
											7 years ago
										 |             owsFailDebug("actionSheetViewVerticalConstraint was unexpectedly nil") | ||
| 
											7 years ago
										 |             return | ||
|  |         } | ||
|  | 
 | ||
| 
											7 years ago
										 |         guard let focusedViewSuperview = focusedView.superview else { | ||
| 
											7 years ago
										 |             owsFailDebug("focusedViewSuperview was unexpectedly nil") | ||
| 
											7 years ago
										 |             return | ||
|  |         } | ||
|  | 
 | ||
| 
											7 years ago
										 |         // darken background | ||
| 
											7 years ago
										 |         guard let snapshotView = addSnapshotFocusedView() else { | ||
| 
											7 years ago
										 |             owsFailDebug("snapshotView was unexpectedly nil") | ||
| 
											7 years ago
										 |             return | ||
|  |         } | ||
|  | 
 | ||
|  |         self.snapshotView = snapshotView | ||
|  |         snapshotView.superview?.layoutIfNeeded() | ||
|  | 
 | ||
| 
											7 years ago
										 |         let backgroundDuration: TimeInterval = 0.1 | ||
|  |         UIView.animate(withDuration: backgroundDuration) { | ||
| 
											5 years ago
										 |             let alpha: CGFloat = isDarkMode ? 0.7 : 0.4 | ||
| 
											7 years ago
										 |             self.view.backgroundColor = UIColor.black.withAlphaComponent(alpha) | ||
| 
											7 years ago
										 |         } | ||
|  | 
 | ||
| 
											7 years ago
										 |         self.actionSheetView.superview?.layoutIfNeeded() | ||
| 
											7 years ago
										 | 
 | ||
|  |         let oldFocusFrame = self.view.convert(focusedView.frame, from: focusedViewSuperview) | ||
| 
											7 years ago
										 |         NSLayoutConstraint.deactivate([actionSheetViewVerticalConstraint]) | ||
|  |         self.actionSheetViewVerticalConstraint = self.actionSheetView.autoPinEdge(toSuperviewEdge: .bottom) | ||
| 
											7 years ago
										 |         self.delegate?.menuActionsWillPresent(self) | ||
| 
											7 years ago
										 |         UIView.animate(withDuration: 0.2, | ||
| 
											7 years ago
										 |                        delay: backgroundDuration, | ||
|  |                        options: .curveEaseOut, | ||
|  |                        animations: { | ||
| 
											7 years ago
										 |                         self.actionSheetView.superview?.layoutIfNeeded() | ||
|  |                         let newSheetFrame = self.actionSheetView.frame | ||
|  | 
 | ||
|  |                         var newFocusFrame = oldFocusFrame | ||
|  | 
 | ||
|  |                         // Position focused item just over the action sheet. | ||
| 
											7 years ago
										 |                         let overlap: CGFloat = (oldFocusFrame.maxY + self.vSpacing) - newSheetFrame.minY | ||
| 
											7 years ago
										 |                         newFocusFrame.origin.y = oldFocusFrame.origin.y - overlap | ||
|  | 
 | ||
|  |                         snapshotView.frame = newFocusFrame | ||
|  | 
 | ||
| 
											7 years ago
										 |                         self.delegate?.menuActionsIsPresenting(self) | ||
| 
											7 years ago
										 |         }, | ||
| 
											7 years ago
										 |                        completion: { (_) in | ||
|  |                         self.delegate?.menuActionsDidPresent(self) | ||
|  |         }) | ||
|  |     } | ||
|  | 
 | ||
|  |     @objc | ||
|  |     public let vSpacing: CGFloat = 10 | ||
|  | 
 | ||
|  |     @objc | ||
| 
											7 years ago
										 |     public var focusUI: UIView { | ||
| 
											7 years ago
										 |         return actionSheetView | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     private func animateDismiss(action: MenuAction?) { | ||
| 
											7 years ago
										 |         guard let actionSheetViewVerticalConstraint = self.actionSheetViewVerticalConstraint else { | ||
| 
											7 years ago
										 |             owsFailDebug("actionSheetVerticalConstraint was unexpectedly nil") | ||
| 
											7 years ago
										 |             delegate?.menuActionsDidDismiss(self) | ||
| 
											7 years ago
										 |             return | ||
| 
											7 years ago
										 |         } | ||
|  | 
 | ||
| 
											7 years ago
										 |         guard let snapshotView = self.snapshotView else { | ||
| 
											7 years ago
										 |             owsFailDebug("snapshotView was unexpectedly nil") | ||
| 
											7 years ago
										 |             delegate?.menuActionsDidDismiss(self) | ||
| 
											7 years ago
										 |             return | ||
|  |         } | ||
|  | 
 | ||
|  |         self.actionSheetView.superview?.layoutIfNeeded() | ||
|  |         NSLayoutConstraint.deactivate([actionSheetViewVerticalConstraint]) | ||
|  | 
 | ||
| 
											7 years ago
										 |         let dismissDuration: TimeInterval = 0.2 | ||
| 
											7 years ago
										 |         self.actionSheetViewVerticalConstraint = self.actionSheetView.autoPinEdge(.top, to: .bottom, of: self.view) | ||
| 
											7 years ago
										 |         UIView.animate(withDuration: dismissDuration, | ||
| 
											7 years ago
										 |                        delay: 0, | ||
|  |                        options: .curveEaseOut, | ||
|  |                        animations: { | ||
|  |                         self.view.backgroundColor = UIColor.clear | ||
|  |                         self.actionSheetView.superview?.layoutIfNeeded() | ||
| 
											7 years ago
										 |                         // this helps when focused view is above navbars, etc. | ||
|  |                         snapshotView.alpha = 0 | ||
| 
											7 years ago
										 | 
 | ||
|  |                         self.delegate?.menuActionsIsDismissing(self) | ||
| 
											7 years ago
										 |         }, | ||
|  |                        completion: { _ in | ||
| 
											7 years ago
										 |                         self.view.isHidden = true | ||
| 
											7 years ago
										 |                         self.delegate?.menuActionsDidDismiss(self) | ||
| 
											7 years ago
										 |                         if let action = action { | ||
|  |                             action.block(action) | ||
|  |                         } | ||
| 
											7 years ago
										 |         }) | ||
| 
											7 years ago
										 |     } | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     // MARK: Actions | ||
|  | 
 | ||
|  |     @objc | ||
|  |     func didTapBackground() { | ||
|  |         animateDismiss(action: nil) | ||
|  |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     // MARK: MenuActionSheetDelegate | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     func actionSheet(_ actionSheet: MenuActionSheetView, didSelectAction action: MenuAction) { | ||
| 
											7 years ago
										 |         animateDismiss(action: action) | ||
| 
											7 years ago
										 |     } | ||
| 
											7 years ago
										 | } | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 | protocol MenuActionSheetDelegate: class { | ||
|  |     func actionSheet(_ actionSheet: MenuActionSheetView, didSelectAction action: MenuAction) | ||
|  | } | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 | class MenuActionSheetView: UIView, MenuActionViewDelegate { | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     private let actionStackView: UIStackView | ||
|  |     private var actions: [MenuAction] | ||
| 
											7 years ago
										 |     private var actionViews: [MenuActionView] | ||
| 
											7 years ago
										 |     private var hapticFeedback: SelectionHapticFeedback | ||
| 
											7 years ago
										 |     private var hasEverHighlightedAction = false | ||
|  | 
 | ||
| 
											7 years ago
										 |     weak var delegate: MenuActionSheetDelegate? | ||
|  | 
 | ||
|  |     override var bounds: CGRect { | ||
|  |         didSet { | ||
|  |             updateMask() | ||
|  |         } | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     convenience init(actions: [MenuAction]) { | ||
|  |         self.init(frame: CGRect.zero) | ||
|  |         actions.forEach { self.addAction($0) } | ||
|  |     } | ||
|  | 
 | ||
|  |     override init(frame: CGRect) { | ||
|  |         actionStackView = UIStackView() | ||
|  |         actionStackView.axis = .vertical | ||
|  |         actionStackView.spacing = CGHairlineWidth() | ||
|  | 
 | ||
|  |         actions = [] | ||
| 
											7 years ago
										 |         actionViews = [] | ||
| 
											7 years ago
										 |         hapticFeedback = SelectionHapticFeedback() | ||
| 
											7 years ago
										 | 
 | ||
|  |         super.init(frame: frame) | ||
|  | 
 | ||
| 
											5 years ago
										 |         backgroundColor = (isDarkMode | ||
| 
											7 years ago
										 |             ? UIColor.ows_gray90 | ||
|  |             : UIColor.ows_gray05) | ||
| 
											7 years ago
										 |         addSubview(actionStackView) | ||
| 
											7 years ago
										 |         actionStackView.autoPinEdgesToSuperviewEdges() | ||
| 
											7 years ago
										 | 
 | ||
|  |         self.clipsToBounds = true | ||
|  | 
 | ||
| 
											7 years ago
										 |         let touchGesture = UILongPressGestureRecognizer(target: self, action: #selector(didTouch(gesture:))) | ||
|  |         touchGesture.minimumPressDuration = 0.0 | ||
|  |         touchGesture.allowableMovement = CGFloat.greatestFiniteMagnitude | ||
|  |         self.addGestureRecognizer(touchGesture) | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
|  |     required init?(coder aDecoder: NSCoder) { | ||
| 
											7 years ago
										 |         notImplemented() | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     @objc | ||
|  |     public func didTouch(gesture: UIGestureRecognizer) { | ||
|  |         switch gesture.state { | ||
|  |         case .possible: | ||
|  |             break | ||
|  |         case .began: | ||
|  |             let location = gesture.location(in: self) | ||
|  |             highlightActionView(location: location, fromView: self) | ||
|  |         case .changed: | ||
|  |             let location = gesture.location(in: self) | ||
|  |             highlightActionView(location: location, fromView: self) | ||
|  |         case .ended: | ||
| 
											7 years ago
										 |             Logger.debug("ended") | ||
| 
											7 years ago
										 |             let location = gesture.location(in: self) | ||
|  |             selectActionView(location: location, fromView: self) | ||
|  |         case .cancelled: | ||
| 
											7 years ago
										 |             Logger.debug("canceled") | ||
| 
											7 years ago
										 |             unhighlightAllActionViews() | ||
|  |         case .failed: | ||
| 
											7 years ago
										 |             Logger.debug("failed") | ||
| 
											7 years ago
										 |             unhighlightAllActionViews() | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     public func addAction(_ action: MenuAction) { | ||
| 
											7 years ago
										 |         actions.append(action) | ||
|  | 
 | ||
| 
											7 years ago
										 |         let actionView = MenuActionView(action: action) | ||
|  |         actionView.delegate = self | ||
| 
											7 years ago
										 |         actionViews.append(actionView) | ||
|  | 
 | ||
| 
											7 years ago
										 |         self.actionStackView.addArrangedSubview(actionView) | ||
|  |     } | ||
|  | 
 | ||
|  |     // MARK: MenuActionViewDelegate | ||
|  | 
 | ||
|  |     func actionView(_ actionView: MenuActionView, didSelectAction action: MenuAction) { | ||
|  |         self.delegate?.actionSheet(self, didSelectAction: action) | ||
|  |     } | ||
|  | 
 | ||
|  |     // MARK:  | ||
|  | 
 | ||
|  |     private func updateMask() { | ||
|  |         let cornerRadius: CGFloat = 16 | ||
|  |         let path: UIBezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius)) | ||
|  |         let mask = CAShapeLayer() | ||
|  |         mask.path = path.cgPath | ||
|  |         self.layer.mask = mask | ||
|  |     } | ||
| 
											7 years ago
										 | 
 | ||
|  |     private func unhighlightAllActionViews() { | ||
|  |         for actionView in actionViews { | ||
|  |             actionView.isHighlighted = false | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     private func actionView(touchedBy touchPoint: CGPoint, fromView: UIView) -> MenuActionView? { | ||
|  |         for actionView in actionViews { | ||
|  |             let convertedPoint = actionView.convert(touchPoint, from: fromView) | ||
|  |             if actionView.point(inside: convertedPoint, with: nil) { | ||
|  |                 return actionView | ||
|  |             } | ||
|  |         } | ||
|  |         return nil | ||
|  |     } | ||
|  | 
 | ||
|  |     private func highlightActionView(location: CGPoint, fromView: UIView) { | ||
|  |         guard let touchedView = actionView(touchedBy: location, fromView: fromView) else { | ||
|  |             unhighlightAllActionViews() | ||
|  |             return | ||
|  |         } | ||
| 
											7 years ago
										 | 
 | ||
|  |         if hasEverHighlightedAction, !touchedView.isHighlighted { | ||
|  |             self.hapticFeedback.selectionChanged() | ||
|  |         } | ||
| 
											7 years ago
										 |         touchedView.isHighlighted = true | ||
| 
											7 years ago
										 |         hasEverHighlightedAction = true | ||
|  | 
 | ||
| 
											7 years ago
										 |         self.actionViews.filter { $0 != touchedView }.forEach {  $0.isHighlighted = false } | ||
|  |     } | ||
|  | 
 | ||
|  |     private func selectActionView(location: CGPoint, fromView: UIView) { | ||
|  |         guard let selectedView: MenuActionView = actionView(touchedBy: location, fromView: fromView) else { | ||
|  |             unhighlightAllActionViews() | ||
|  |             return | ||
|  |         } | ||
|  |         selectedView.isHighlighted = true | ||
|  |         self.actionViews.filter { $0 != selectedView }.forEach {  $0.isHighlighted = false } | ||
|  |         delegate?.actionSheet(self, didSelectAction: selectedView.action) | ||
|  |     } | ||
| 
											7 years ago
										 | } | ||
|  | 
 | ||
| 
											7 years ago
										 | protocol MenuActionViewDelegate: class { | ||
|  |     func actionView(_ actionView: MenuActionView, didSelectAction action: MenuAction) | ||
| 
											7 years ago
										 | } | ||
|  | 
 | ||
| 
											7 years ago
										 | class MenuActionView: UIButton { | ||
|  |     public weak var delegate: MenuActionViewDelegate? | ||
| 
											7 years ago
										 |     public let action: MenuAction | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |     required init(action: MenuAction) { | ||
| 
											7 years ago
										 |         self.action = action | ||
|  | 
 | ||
|  |         super.init(frame: CGRect.zero) | ||
|  | 
 | ||
| 
											7 years ago
										 |         isUserInteractionEnabled = true | ||
| 
											7 years ago
										 |         backgroundColor = defaultBackgroundColor | ||
| 
											7 years ago
										 | 
 | ||
| 
											5 years ago
										 |         let textColor = isLightMode ? UIColor.black : UIColor.white | ||
|  | 
 | ||
| 
											7 years ago
										 |         var image = action.image | ||
| 
											5 years ago
										 |         image = image.withRenderingMode(.alwaysTemplate) | ||
| 
											7 years ago
										 |         let imageView = UIImageView(image: image) | ||
| 
											5 years ago
										 |         imageView.tintColor = textColor.withAlphaComponent(Values.unimportantElementOpacity) | ||
| 
											7 years ago
										 |         let imageWidth: CGFloat = 24 | ||
|  |         imageView.autoSetDimensions(to: CGSize(width: imageWidth, height: imageWidth)) | ||
| 
											7 years ago
										 |         imageView.isUserInteractionEnabled = false | ||
| 
											7 years ago
										 | 
 | ||
|  |         let titleLabel = UILabel() | ||
| 
											6 years ago
										 |         titleLabel.font = .systemFont(ofSize: Values.mediumFontSize) | ||
| 
											5 years ago
										 |         titleLabel.textColor = textColor | ||
| 
											7 years ago
										 |         titleLabel.text = action.title | ||
| 
											7 years ago
										 |         titleLabel.isUserInteractionEnabled = false | ||
| 
											7 years ago
										 | 
 | ||
|  |         let subtitleLabel = UILabel() | ||
| 
											6 years ago
										 |         subtitleLabel.font = .systemFont(ofSize: Values.smallFontSize) | ||
| 
											5 years ago
										 |         subtitleLabel.textColor = textColor.withAlphaComponent(Values.unimportantElementOpacity) | ||
| 
											7 years ago
										 |         subtitleLabel.text = action.subtitle | ||
| 
											7 years ago
										 |         subtitleLabel.isUserInteractionEnabled = false | ||
| 
											7 years ago
										 | 
 | ||
|  |         let textColumn = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) | ||
|  |         textColumn.axis = .vertical | ||
|  |         textColumn.alignment = .leading | ||
| 
											7 years ago
										 |         textColumn.isUserInteractionEnabled = false | ||
| 
											7 years ago
										 | 
 | ||
|  |         let contentRow  = UIStackView(arrangedSubviews: [imageView, textColumn]) | ||
|  |         contentRow.axis = .horizontal | ||
|  |         contentRow.alignment = .center | ||
|  |         contentRow.spacing = 12 | ||
|  |         contentRow.isLayoutMarginsRelativeArrangement = true | ||
| 
											7 years ago
										 |         contentRow.layoutMargins = UIEdgeInsets(top: 7, left: 16, bottom: 7, right: 16) | ||
| 
											7 years ago
										 |         contentRow.isUserInteractionEnabled = false | ||
| 
											7 years ago
										 | 
 | ||
|  |         self.addSubview(contentRow) | ||
| 
											7 years ago
										 |         contentRow.autoPinEdgesToSuperviewMargins() | ||
| 
											7 years ago
										 |         contentRow.autoSetDimension(.height, toSize: 56, relation: .greaterThanOrEqual) | ||
| 
											7 years ago
										 | 
 | ||
| 
											7 years ago
										 |         self.isUserInteractionEnabled = false | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     private var defaultBackgroundColor: UIColor { | ||
| 
											5 years ago
										 |         return isLightMode ? UIColor(hex: 0xFCFCFC) : UIColor(hex: 0x1B1B1B) | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
|  |     private var highlightedBackgroundColor: UIColor { | ||
| 
											5 years ago
										 |         return isLightMode ? UIColor(hex: 0xDFDFDF) : UIColor(hex: 0x0C0C0C) | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
| 
											7 years ago
										 |     override var isHighlighted: Bool { | ||
|  |         didSet { | ||
| 
											7 years ago
										 |             self.backgroundColor = isHighlighted ? highlightedBackgroundColor : defaultBackgroundColor | ||
| 
											7 years ago
										 |         } | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
|  |     @objc | ||
| 
											7 years ago
										 |     func didPress(sender: Any) { | ||
| 
											7 years ago
										 |         Logger.debug("") | ||
| 
											7 years ago
										 |         self.delegate?.actionView(self, didSelectAction: action) | ||
| 
											7 years ago
										 |     } | ||
|  | 
 | ||
|  |     required init?(coder aDecoder: NSCoder) { | ||
| 
											7 years ago
										 |         notImplemented() | ||
| 
											7 years ago
										 |     } | ||
|  | } |