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.
		
		
		
		
		
			
		
			
				
	
	
		
			234 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			234 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Swift
		
	
| // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
 | |
| 
 | |
| import UIKit
 | |
| import SessionUIKit
 | |
| 
 | |
| public class ConfirmationModal: Modal {
 | |
|     public struct Info: Equatable, Hashable {
 | |
|         enum State {
 | |
|             case whenEnabled
 | |
|             case whenDisabled
 | |
|             case always
 | |
|             
 | |
|             func shouldShow(for value: Bool) -> Bool {
 | |
|                 switch self {
 | |
|                     case .whenEnabled: return (value == true)
 | |
|                     case .whenDisabled: return (value == false)
 | |
|                     case .always: return true
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         let title: String
 | |
|         let explanation: String?
 | |
|         let attributedExplanation: NSAttributedString?
 | |
|         let stateToShow: State
 | |
|         let confirmTitle: String?
 | |
|         let confirmStyle: ThemeValue
 | |
|         let cancelTitle: String
 | |
|         let cancelStyle: ThemeValue
 | |
|         let dismissOnConfirm: Bool
 | |
|         let onConfirm: ((UIViewController) -> ())?
 | |
|         let afterClosed: (() -> ())?
 | |
|         
 | |
|         // MARK: - Initialization
 | |
|         
 | |
|         init(
 | |
|             title: String,
 | |
|             explanation: String? = nil,
 | |
|             attributedExplanation: NSAttributedString? = nil,
 | |
|             stateToShow: State = .always,
 | |
|             confirmTitle: String? = nil,
 | |
|             confirmStyle: ThemeValue = .alert_text,
 | |
|             cancelTitle: String = "TXT_CANCEL_TITLE".localized(),
 | |
|             cancelStyle: ThemeValue = .danger,
 | |
|             dismissOnConfirm: Bool = true,
 | |
|             onConfirm: ((UIViewController) -> ())? = nil,
 | |
|             afterClosed: (() -> ())? = nil
 | |
|         ) {
 | |
|             self.title = title
 | |
|             self.explanation = explanation
 | |
|             self.attributedExplanation = attributedExplanation
 | |
|             self.stateToShow = stateToShow
 | |
|             self.confirmTitle = confirmTitle
 | |
|             self.confirmStyle = confirmStyle
 | |
|             self.cancelTitle = cancelTitle
 | |
|             self.cancelStyle = cancelStyle
 | |
|             self.dismissOnConfirm = dismissOnConfirm
 | |
|             self.onConfirm = onConfirm
 | |
|             self.afterClosed = afterClosed
 | |
|         }
 | |
|         
 | |
|         // MARK: - Mutation
 | |
|         
 | |
|         public func with(
 | |
|             onConfirm: ((UIViewController) -> ())? = nil,
 | |
|             afterClosed: (() -> ())? = nil
 | |
|         ) -> Info {
 | |
|             return Info(
 | |
|                 title: self.title,
 | |
|                 explanation: self.explanation,
 | |
|                 stateToShow: self.stateToShow,
 | |
|                 confirmTitle: self.confirmTitle,
 | |
|                 confirmStyle: self.confirmStyle,
 | |
|                 cancelTitle: self.cancelTitle,
 | |
|                 cancelStyle: self.cancelStyle,
 | |
|                 dismissOnConfirm: self.dismissOnConfirm,
 | |
|                 onConfirm: (onConfirm ?? self.onConfirm),
 | |
|                 afterClosed: (afterClosed ?? self.afterClosed)
 | |
|             )
 | |
|         }
 | |
|         
 | |
|         // MARK: - Confirmance
 | |
|         
 | |
|         public static func == (lhs: ConfirmationModal.Info, rhs: ConfirmationModal.Info) -> Bool {
 | |
|             return (
 | |
|                 lhs.title == rhs.title &&
 | |
|                 lhs.explanation == rhs.explanation &&
 | |
|                 lhs.attributedExplanation == rhs.attributedExplanation &&
 | |
|                 lhs.stateToShow == rhs.stateToShow &&
 | |
|                 lhs.confirmTitle == rhs.confirmTitle &&
 | |
|                 lhs.confirmStyle == rhs.confirmStyle &&
 | |
|                 lhs.cancelTitle == rhs.cancelTitle &&
 | |
|                 lhs.cancelStyle == rhs.cancelStyle &&
 | |
|                 lhs.dismissOnConfirm == rhs.dismissOnConfirm
 | |
|             )
 | |
|         }
 | |
|         
 | |
|         public func hash(into hasher: inout Hasher) {
 | |
|             title.hash(into: &hasher)
 | |
|             explanation.hash(into: &hasher)
 | |
|             attributedExplanation.hash(into: &hasher)
 | |
|             stateToShow.hash(into: &hasher)
 | |
|             confirmTitle.hash(into: &hasher)
 | |
|             confirmStyle.hash(into: &hasher)
 | |
|             cancelTitle.hash(into: &hasher)
 | |
|             cancelStyle.hash(into: &hasher)
 | |
|             dismissOnConfirm.hash(into: &hasher)
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     private let internalOnConfirm: (UIViewController) -> ()
 | |
|     
 | |
|     // MARK: - Components
 | |
|     
 | |
|     private lazy var titleLabel: UILabel = {
 | |
|         let result: UILabel = UILabel()
 | |
|         result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
 | |
|         result.themeTextColor = .alert_text
 | |
|         result.textAlignment = .center
 | |
|         result.lineBreakMode = .byWordWrapping
 | |
|         result.numberOfLines = 0
 | |
|         
 | |
|         return result
 | |
|     }()
 | |
|     
 | |
|     private lazy var explanationLabel: UILabel = {
 | |
|         let result: UILabel = UILabel()
 | |
|         result.font = .systemFont(ofSize: Values.smallFontSize)
 | |
|         result.themeTextColor = .alert_text
 | |
|         result.textAlignment = .center
 | |
|         result.lineBreakMode = .byWordWrapping
 | |
|         result.numberOfLines = 0
 | |
|         
 | |
|         return result
 | |
|     }()
 | |
|     
 | |
|     private lazy var confirmButton: UIButton = {
 | |
|         let result: UIButton = Modal.createButton(
 | |
|             title: "",
 | |
|             titleColor: .danger
 | |
|         )
 | |
|         result.addTarget(self, action: #selector(confirmationPressed), for: .touchUpInside)
 | |
|         
 | |
|         return result
 | |
|     }()
 | |
|     
 | |
|     private lazy var buttonStackView: UIStackView = {
 | |
|         let result = UIStackView(arrangedSubviews: [ confirmButton, cancelButton ])
 | |
|         result.axis = .horizontal
 | |
|         result.distribution = .fillEqually
 | |
|         
 | |
|         return result
 | |
|     }()
 | |
|     
 | |
|     private lazy var contentStackView: UIStackView = {
 | |
|         let result = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel ])
 | |
|         result.axis = .vertical
 | |
|         result.spacing = Values.smallSpacing
 | |
|         result.isLayoutMarginsRelativeArrangement = true
 | |
|         result.layoutMargins = UIEdgeInsets(
 | |
|             top: Values.largeSpacing,
 | |
|             leading: Values.largeSpacing,
 | |
|             bottom: Values.verySmallSpacing,
 | |
|             trailing: Values.largeSpacing
 | |
|         )
 | |
|         
 | |
|         return result
 | |
|     }()
 | |
|     
 | |
|     private lazy var mainStackView: UIStackView = {
 | |
|         let result = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ])
 | |
|         result.axis = .vertical
 | |
|         result.spacing = Values.largeSpacing - Values.smallFontSize / 2
 | |
|         
 | |
|         return result
 | |
|     }()
 | |
|     
 | |
|     // MARK: - Lifecycle
 | |
|     
 | |
|     init(info: Info) {
 | |
|         self.internalOnConfirm = { viewController in
 | |
|             if info.dismissOnConfirm {
 | |
|                 viewController.dismiss(animated: true)
 | |
|             }
 | |
|             
 | |
|             info.onConfirm?(viewController)
 | |
|         }
 | |
|         
 | |
|         super.init(afterClosed: info.afterClosed)
 | |
|         
 | |
|         self.modalPresentationStyle = .overFullScreen
 | |
|         self.modalTransitionStyle = .crossDissolve
 | |
|         
 | |
|         // Set the content based on the provided info
 | |
|         titleLabel.text = info.title
 | |
|         
 | |
|         // Note: We should only set the appropriate explanation/attributedExplanation value (as
 | |
|         // setting both when one is null can result in the other being removed)
 | |
|         if let explanation: String = info.explanation {
 | |
|             explanationLabel.text = explanation
 | |
|         }
 | |
|         
 | |
|         if let attributedExplanation: NSAttributedString = info.attributedExplanation {
 | |
|             explanationLabel.attributedText = attributedExplanation
 | |
|         }
 | |
|     
 | |
|         explanationLabel.isHidden = (
 | |
|             info.explanation == nil &&
 | |
|             info.attributedExplanation == nil
 | |
|         )
 | |
|         confirmButton.setTitle(info.confirmTitle, for: .normal)
 | |
|         confirmButton.setThemeTitleColor(info.confirmStyle, for: .normal)
 | |
|         confirmButton.isHidden = (info.confirmTitle == nil)
 | |
|         cancelButton.setTitle(info.cancelTitle, for: .normal)
 | |
|         cancelButton.setThemeTitleColor(info.cancelStyle, for: .normal)
 | |
|     }
 | |
|     
 | |
|     required init?(coder: NSCoder) {
 | |
|         fatalError("init(coder:) has not been implemented")
 | |
|     }
 | |
|     
 | |
|     public override func populateContentView() {
 | |
|         contentView.addSubview(mainStackView)
 | |
|         
 | |
|         mainStackView.pin(to: contentView)
 | |
|     }
 | |
|     
 | |
|     // MARK: - Interaction
 | |
|     
 | |
|     @objc private func confirmationPressed() {
 | |
|         internalOnConfirm(self)
 | |
|     }
 | |
| }
 |