session-ios/Session/Sheets & Modals/ConfirmationModal.swift
2022-08-26 16:23:39 +10:00

181 lines
5.9 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 stateToShow: State
let confirmTitle: String?
let confirmStyle: ThemeValue
let cancelTitle: String
let cancelStyle: ThemeValue
let onConfirm: (() -> ())?
init(
title: String,
explanation: String? = nil,
stateToShow: State = .always,
confirmTitle: String? = nil,
confirmStyle: ThemeValue = .textPrimary,
cancelTitle: String = "TXT_CANCEL_TITLE".localized(),
cancelStyle: ThemeValue = .danger,
onConfirm: (() -> ())? = nil
) {
self.title = title
self.explanation = explanation
self.stateToShow = stateToShow
self.confirmTitle = confirmTitle
self.confirmStyle = confirmStyle
self.cancelTitle = cancelTitle
self.cancelStyle = cancelStyle
self.onConfirm = onConfirm
}
public static func == (lhs: ConfirmationModal.Info, rhs: ConfirmationModal.Info) -> Bool {
return (
lhs.title == rhs.title &&
lhs.explanation == rhs.explanation &&
lhs.stateToShow == rhs.stateToShow &&
lhs.confirmTitle == rhs.confirmTitle &&
lhs.confirmStyle == rhs.confirmStyle &&
lhs.cancelTitle == rhs.cancelTitle &&
lhs.cancelStyle == rhs.cancelStyle
)
}
public func hash(into hasher: inout Hasher) {
title.hash(into: &hasher)
explanation.hash(into: &hasher)
stateToShow.hash(into: &hasher)
confirmTitle.hash(into: &hasher)
confirmStyle.hash(into: &hasher)
cancelTitle.hash(into: &hasher)
cancelStyle.hash(into: &hasher)
}
}
private let onConfirm: (UIViewController) -> ()
// MARK: - Components
private lazy var titleLabel: UILabel = {
let result: UILabel = UILabel()
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
result.themeTextColor = .textPrimary
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 = .textPrimary
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, onConfirm: ((UIViewController) -> ())? = nil) {
self.onConfirm = { viewController in
onConfirm?(viewController)
info.onConfirm?()
}
super.init(nibName: nil, bundle: nil)
self.modalPresentationStyle = .overFullScreen
self.modalTransitionStyle = .crossDissolve
// Set the content based on the provided info
titleLabel.text = info.title
explanationLabel.text = info.explanation
explanationLabel.isHidden = (info.explanation == 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() {
onConfirm(self)
}
}