Skip to content
Snippets Groups Projects
ScanDisplayShareView.swift 6.54 KiB
Newer Older
Bruno Muniz's avatar
Bruno Muniz committed
import UIKit
import Shared
Ahmed Shehata's avatar
Ahmed Shehata committed
import SnapKit
import Combine
Bruno Muniz's avatar
Bruno Muniz committed

final class ScanDisplayShareView: UIView {
Ahmed Shehata's avatar
Ahmed Shehata committed
    enum Action {
        case info
        case addEmail
        case addPhone
        case toggleEmail
        case togglePhone
    }

    private var isExpanded = false {
        didSet { updateBottomConstraint() }
    }

    private let upperView = UIView()
    private let lowerView = UIView()
    private var bottomConstraint: Constraint?
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
    private let imageView = UIImageView()
    private let titleView = TextWithInfoView()
    private let emailView = AttributeSwitcher()
    private let phoneView = AttributeSwitcher()
    private var cancellables = Set<AnyCancellable>()

    private var currentConstraintConstant: CGFloat = 0.0 {
        didSet { bottomConstraint?.update(offset: currentConstraintConstant) }
    }

    private var bottomConstraintExpanded: CGFloat {
        -lowerView.frame.height
    }

    private var bottomConstraintNotExpanded: CGFloat {
        0
    }

    var actionPublisher: AnyPublisher<Action, Never> {
        actionSubject.eraseToAnyPublisher()
    }

    private let actionSubject = PassthroughSubject<Action, Never>()
Bruno Muniz's avatar
Bruno Muniz committed

    init() {
        super.init(frame: .zero)
Ahmed Shehata's avatar
Ahmed Shehata committed

        upperView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(didPan(_:))))
        lowerView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(didPan(_:))))

        layer.cornerRadius = 30
        imageView.image = Asset.scanDropdown.image
Bruno Muniz's avatar
Bruno Muniz committed
        backgroundColor = Asset.neutralWhite.color
Ahmed Shehata's avatar
Ahmed Shehata committed
        clipsToBounds = true
        layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
        addSubview(upperView)
        addSubview(lowerView)

        upperView.addSubview(imageView)
        upperView.addSubview(titleView)
        lowerView.addSubview(emailView)
        lowerView.addSubview(phoneView)
Bruno Muniz's avatar
Bruno Muniz committed

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = .byWordWrapping

Ahmed Shehata's avatar
Ahmed Shehata committed
        titleView.setup(
Bruno Muniz's avatar
Bruno Muniz committed
            text: Localized.Scan.Display.Share.title,
            attributes: [
                .foregroundColor: Asset.neutralBody.color,
                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
                .paragraphStyle: paragraphStyle
            ],
Ahmed Shehata's avatar
Ahmed Shehata committed
            didTapInfo: { [weak self] in self?.actionSubject.send(.info) }
Bruno Muniz's avatar
Bruno Muniz committed
        )

Ahmed Shehata's avatar
Ahmed Shehata committed
        emailView.switcherView
            .publisher(for: .valueChanged)
            .sink { [unowned self] in actionSubject.send(.toggleEmail) }
            .store(in: &cancellables)

        phoneView.switcherView
            .publisher(for: .valueChanged)
            .sink { [unowned self] in actionSubject.send(.togglePhone) }
            .store(in: &cancellables)

        emailView.addButton
            .publisher(for: .touchUpInside)
            .sink { [unowned self] in actionSubject.send(.addEmail) }
            .store(in: &cancellables)

        phoneView.addButton
            .publisher(for: .touchUpInside)
            .sink { [unowned self] in actionSubject.send(.addPhone) }
            .store(in: &cancellables)

        emailView.setup(state: nil, title: Localized.Scan.Display.Share.email)
        phoneView.setup(state: nil, title: Localized.Scan.Display.Share.phone)
        emailView.alpha = 0.0
        phoneView.alpha = 0.0

        imageView.snp.makeConstraints {
            $0.top.equalToSuperview().offset(15)
            $0.centerX.equalToSuperview()
        }
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
        titleView.snp.makeConstraints {
            $0.top.equalTo(imageView.snp.bottom).offset(10)
            $0.left.equalToSuperview().offset(40)
            $0.right.lessThanOrEqualToSuperview().offset(-40)
            $0.centerY.equalToSuperview()
        }
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
        emailView.snp.makeConstraints {
            $0.top.equalToSuperview()
            $0.left.equalToSuperview().offset(40)
            $0.right.equalToSuperview().offset(-40)
Ahmed Shehata's avatar
Ahmed Shehata committed
        phoneView.snp.makeConstraints {
            $0.top.equalTo(emailView.snp.bottom).offset(25)
            $0.left.equalToSuperview().offset(40)
            $0.right.equalToSuperview().offset(-40)
            $0.bottom.equalToSuperview().offset(-40)
Ahmed Shehata's avatar
Ahmed Shehata committed
        upperView.snp.makeConstraints {
            $0.top.equalToSuperview()
            $0.left.equalToSuperview()
            $0.right.equalToSuperview()
            bottomConstraint = $0.bottom
                .equalTo(safeAreaLayoutGuide)
                .constraint
        }
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
        lowerView.snp.makeConstraints {
            $0.top.equalTo(upperView.snp.bottom).offset(-30)
            $0.left.equalToSuperview()
            $0.right.equalToSuperview()
        }
    }
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
    required init?(coder: NSCoder) { nil }
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
    func setup(email state: AttributeSwitcher.State?) {
        emailView.setup(state: state, title: Localized.Scan.Display.Share.email)
Ahmed Shehata's avatar
Ahmed Shehata committed
    func setup(phone state: AttributeSwitcher.State?) {
        phoneView.setup(state: state, title: Localized.Scan.Display.Share.phone)
    }
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
    @objc private func didPan(_ sender: UIPanGestureRecognizer) {
        switch sender.state {
        case .began, .changed:
            let isUpwards = sender.translation(in: self).y < 0
            let result = currentConstraintConstant + sender.translation(in: self).y

            if isUpwards {
                currentConstraintConstant = max(bottomConstraintExpanded, result)
            } else {
                currentConstraintConstant = min(bottomConstraintNotExpanded, result)
            }

            let currentMinusExpanded = currentConstraintConstant - bottomConstraintExpanded
            let notExpandedMinusExpanded = bottomConstraintNotExpanded - bottomConstraintExpanded
            let alpha = 1 - (currentMinusExpanded / abs(notExpandedMinusExpanded))
            emailView.alpha = alpha
            phoneView.alpha = alpha

        case .cancelled, .ended, .failed:
            let currentMinusExpanded = currentConstraintConstant - bottomConstraintExpanded
            let notExpandedMinusExpanded = bottomConstraintNotExpanded - bottomConstraintExpanded
            let percentage = currentMinusExpanded / abs(notExpandedMinusExpanded)
            isExpanded = percentage < 0.5

        case .possible:
            break
        @unknown default:
            break
        }
    }
Bruno Muniz's avatar
Bruno Muniz committed

Ahmed Shehata's avatar
Ahmed Shehata committed
    private func updateBottomConstraint() {
        if isExpanded {
            emailView.alpha = 1.0
            phoneView.alpha = 1.0
            currentConstraintConstant = bottomConstraintExpanded
        } else {
            emailView.alpha = 0.0
            phoneView.alpha = 0.0
            currentConstraintConstant = bottomConstraintNotExpanded
        }
Bruno Muniz's avatar
Bruno Muniz committed
    }
}