Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/Signal/src/ViewControllers/Donations/DonateViewController+MonthlySubscriptionLevelView.swift
1 views
//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import SignalServiceKit
import SignalUI

extension DonateViewController {
    class MonthlySubscriptionLevelView: UIStackView {
        private let background: UIView = {
            let result = UIView()
            result.backgroundColor = DonationViewsUtil.bubbleBackgroundColor
            result.layer.borderWidth = DonationViewsUtil.bubbleBorderWidth
            result.layer.borderColor = result.backgroundColor?.cgColor
            if #available(iOS 26, *) {
                result.cornerConfiguration = .uniformCorners(radius: 26)
            } else {
                result.layer.cornerRadius = DonateViewController.cornerRadius
            }
            return result
        }()

        private let headingStackView: UIStackView = {
            let result = UIStackView()
            result.axis = .horizontal
            result.distribution = .fill
            result.spacing = 4
            return result
        }()

        private let headingLabel: UILabel = {
            let result = UILabel()
            result.font = .dynamicTypeBody
            result.numberOfLines = 0
            result.setContentHuggingHorizontalHigh()
            result.setCompressionResistanceHorizontalHigh()
            return result
        }()

        private let subheadingLabel: UILabel = {
            let result = UILabel()
            result.font = .dynamicTypeSubheadline
            result.numberOfLines = 0
            return result
        }()

        let subscriptionLevel: DonationSubscriptionLevel
        let animationName: String

        init(subscriptionLevel: DonationSubscriptionLevel, animationName: String) {
            self.subscriptionLevel = subscriptionLevel
            self.animationName = animationName

            super.init(frame: .zero)

            axis = .horizontal
            alignment = .center
            layoutMargins = UIEdgeInsets(hMargin: 12, vMargin: 9)
            isLayoutMarginsRelativeArrangement = true
            spacing = 10

            addSubview(background)
            background.autoPinEdgesToSuperviewEdges()

            let badge = subscriptionLevel.badge
            let imageView = UIImageView()
            if let badgeImage = badge.assets?.universal64 {
                imageView.image = badgeImage
            } else {
                Logger.warn("[Donations] Badge image failed to load")
            }
            addArrangedSubview(imageView)
            imageView.autoSetDimensions(to: .init(square: 40))

            let textStackView = UIStackView(arrangedSubviews: [headingStackView, subheadingLabel])
            textStackView.axis = .vertical
            textStackView.alignment = .fill
            textStackView.isLayoutMarginsRelativeArrangement = true
            textStackView.spacing = 4
            addArrangedSubview(textStackView)
        }

        required init(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }

        func render(
            currencyCode: Currency.Code,
            currentSubscription: Subscription?,
            selectedSubscriptionLevel: DonationSubscriptionLevel?,
        ) {
            let isCurrentSubscription: Bool = {
                guard let currentSubscription else { return false }
                return
                    currentSubscription.active &&
                    currentSubscription.level == subscriptionLevel.level &&
                    currentSubscription.amount.currencyCode == currencyCode

            }()
            let isSelectedInUi = selectedSubscriptionLevel?.level == subscriptionLevel.level

            background.layer.borderColor = isSelectedInUi
                ? DonateViewController.selectedColor
                : background.backgroundColor?.cgColor

            headingLabel.text = {
                let format = OWSLocalizedString(
                    "DONATE_SCREEN_MONTHLY_SUBSCRIPTION_TITLE",
                    comment: "On the donation screen, you can see a list of monthly subscription levels. This text will be shown as the title for each level, telling you the price per month. Embeds {{currency string}}, such as \"$5\".",
                )
                guard let price = subscriptionLevel.amounts[currencyCode] else {
                    owsFail("[Donations] No price for this currency code. This should be impossible in the UI")
                }
                let currencyString = CurrencyFormatter.format(money: price)
                return String.nonPluralLocalizedStringWithFormat(format, currencyString)
            }()
            headingStackView.removeAllSubviews()
            headingStackView.addArrangedSubview(headingLabel)
            if isCurrentSubscription {
                let checkmark = UIImageView(image: UIImage(named: "check-20"))
                checkmark.tintColor = .Signal.label
                headingStackView.addArrangedSubview(checkmark)
                checkmark.setCompressionResistanceHorizontalHigh()
                checkmark.autoSetDimensions(to: CGSize(square: 15))
            }

            subheadingLabel.text = {
                if isCurrentSubscription, let currentSubscription {
                    let format: String
                    if currentSubscription.cancelAtEndOfPeriod {
                        format = OWSLocalizedString(
                            "DONATE_SCREEN_MONTHLY_SUBSCRIPTION_EXPIRES_ON_DATE",
                            comment: "On the donation screen, you can see a list of monthly subscription levels. If you already have one of these and it expires soon, this text is shown below it indicating when it will expire. Embeds {{formatted renewal date}}, such as \"June 9, 2010\".",
                        )
                    } else {
                        format = OWSLocalizedString(
                            "DONATE_SCREEN_MONTHLY_SUBSCRIPTION_RENEWS_ON_DATE",
                            comment: "On the donation screen, you can see a list of monthly subscription levels. If you already have one of these, this text is shown below it indicating when it will renew. Embeds {{formatted renewal date}}, such as \"June 9, 2010\".",
                        )
                    }

                    let dateFormatter = DateFormatter()
                    dateFormatter.dateStyle = .medium
                    let dateString = dateFormatter.string(from: currentSubscription.endOfCurrentPeriod)

                    return String.nonPluralLocalizedStringWithFormat(format, dateString)
                } else {
                    let format = OWSLocalizedString(
                        "DONATE_SCREEN_MONTHLY_SUBSCRIPTION_SUBTITLE",
                        comment: "On the donation screen, you can see a list of monthly subscription levels. This text will be shown in the subtitle of each level, telling you which badge you'll get. Embeds {{localized badge name}}, such as \"Planet\".",
                    )
                    return String.nonPluralLocalizedStringWithFormat(format, subscriptionLevel.badge.localizedName)
                }
            }()
        }
    }
}