Commit 616e3d2e by Dmitry Stepanets

Working on Pro subscription UI

parent a8afcfb6
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
"color-space" : "srgb", "color-space" : "srgb",
"components" : { "components" : {
"alpha" : "1.000", "alpha" : "1.000",
"blue" : "243", "blue" : "0xF3",
"green" : "103", "green" : "0x67",
"red" : "31" "red" : "0x1F"
} }
}, },
"idiom" : "universal" "idiom" : "universal"
......
...@@ -192,8 +192,8 @@ ...@@ -192,8 +192,8 @@
//Menu //Menu
"menu.goPremium" = "Go premium"; "menu.goPremium" = "Go Premium";
"menu.premium.desc" = "Experience app without ads"; "menu.premium.desc" = "Subcribe to 1Weather premium for a unique experience.";
"menu.tv" = "1Weather TV"; "menu.tv" = "1Weather TV";
"menu.radar" = "Radar"; "menu.radar" = "Radar";
"menu.buyNow" = "Buy now"; "menu.buyNow" = "Buy now";
...@@ -216,15 +216,22 @@ ...@@ -216,15 +216,22 @@
//Subscriptions //Subscriptions
"subscription.header.oneWeather" = "1Weather"; "subscription.header.oneWeather" = "1Weather";
"subscription.header.premium" = "PREMIUM"; "subscription.header.premium" = "PREMIUM";
"subscription.proMember.already.top" = "You are a Pro member currently";
"subscription.proMember.already.bottom" = "Ad free experience";
"subscription.description.upgradePremium" = "Upgrade to Premium";
"subscription.description.forPro" = "For Pro users";
"subscription.description.discount" = "%@ OFF";
"subscription.description.header" = "Get the best of 1 Weather"; "subscription.description.header" = "Get the best of 1 Weather";
"subscription.description.header.purchased" = "Thank you for subscribing to 1Weather Premium"; "subscription.description.header.purchased" = "Thank you for subscribing to 1Weather Premium";
"subscription.description.items.youGet" = "You get:"; "subscription.description.items.youGet" = "You get:";
"subscription.description.items.adFree" = "Ad free experience"; "subscription.description.items.adFree" = "Ad free experience";
"subscription.description.items.adFree.forever" = "Forever"; "subscription.description.items.adFree.forever" = "Forever";
"subscription.description.items.hourly" = " 48 hours of Hourly forecasts"; "subscription.description.items.hourly" = " 48 hours of Hourly forecasts";
"subscription.description.items.hourly.pro" = "Hourly forecasts";
"subscription.description.items.hourly.crossed" = "24 hours"; "subscription.description.items.hourly.crossed" = "24 hours";
"subscription.description.items.daily" = " 10 Days of Daily forecasts"; "subscription.description.items.daily" = " 10 Days of Daily forecasts";
"subscription.description.items.daily.pro" = "Daily forecasts";
"subscription.description.items.daily.crossed" = "7 days"; "subscription.description.items.daily.crossed" = "7 days";
"subscription.description.items.aqi" = "AQI card"; "subscription.description.items.aqi" = "AQI card";
"subscription.description.items.comingSoon" = "Coming Soon"; "subscription.description.items.comingSoon" = "Coming Soon";
......
...@@ -12,7 +12,7 @@ class MenuHeaderView: UIView { ...@@ -12,7 +12,7 @@ class MenuHeaderView: UIView {
private let premiumContainer = UIView() private let premiumContainer = UIView()
private let premiumHeadingLabel = UILabel() private let premiumHeadingLabel = UILabel()
private let premiumDescriptionLabel = UILabel() private let premiumDescriptionLabel = UILabel()
private let buyButton = MenuBuyButton() private let buyButton = UIButton()
private let premiumImageView = UIImageView() private let premiumImageView = UIImageView()
public var onTapBuy: (() -> ())? public var onTapBuy: (() -> ())?
...@@ -37,22 +37,6 @@ class MenuHeaderView: UIView { ...@@ -37,22 +37,6 @@ class MenuHeaderView: UIView {
//Prvaite //Prvaite
private func updateUI() { private func updateUI() {
backgroundColor = ThemeManager.currentTheme.baseBackgroundColor backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
premiumContainer.backgroundColor = ThemeManager.currentTheme.containerBackgroundColor
premiumHeadingLabel.textColor = ThemeManager.currentTheme.primaryTextColor
premiumDescriptionLabel.textColor = ThemeManager.currentTheme.primaryTextColor
switch interfaceStyle {
case .light:
premiumContainer.layer.shadowColor = UIColor(hex: 0x020116).cgColor
premiumContainer.layer.shadowOffset = .init(width: 0, height: 10)
premiumContainer.layer.shadowRadius = 20
premiumContainer.layer.shadowOpacity = 0.12
case .dark:
premiumContainer.layer.shadowColor = UIColor.black.cgColor
premiumContainer.layer.shadowOffset = .init(width: 8, height: 8)
premiumContainer.layer.shadowRadius = 8
premiumContainer.layer.shadowOpacity = 1.0
}
} }
@objc private func handleBuyButton() { @objc private func handleBuyButton() {
...@@ -71,28 +55,40 @@ private extension MenuHeaderView { ...@@ -71,28 +55,40 @@ private extension MenuHeaderView {
} }
func preparePremium() { func preparePremium() {
premiumContainer.backgroundColor = ThemeManager.currentTheme.graphTintColor
premiumContainer.layer.cornerRadius = 12 premiumContainer.layer.cornerRadius = 12
addSubview(premiumContainer) addSubview(premiumContainer)
premiumHeadingLabel.font = AppFont.SFPro.bold(size: 34) premiumImageView.contentMode = .scaleAspectFit
premiumImageView.image = UIImage(named: "subscription_logo")
premiumContainer.addSubview(premiumImageView)
premiumHeadingLabel.textColor = .white
premiumHeadingLabel.font = AppFont.SFPro.bold(size: 23)
premiumHeadingLabel.text = "menu.goPremium".localized() premiumHeadingLabel.text = "menu.goPremium".localized()
premiumHeadingLabel.setContentHuggingPriority(.fittingSizeLevel, for: .vertical) premiumHeadingLabel.setContentHuggingPriority(.fittingSizeLevel, for: .vertical)
premiumContainer.addSubview(premiumHeadingLabel) premiumContainer.addSubview(premiumHeadingLabel)
let descParagpraphStyle = NSMutableParagraphStyle()
descParagpraphStyle.minimumLineHeight = 20
let descriptionAttrString = NSAttributedString(string: "menu.premium.desc".localized(),
attributes: [.foregroundColor : UIColor.white,
.paragraphStyle : descParagpraphStyle,
.font : AppFont.SFPro.regular(size: 14)])
premiumDescriptionLabel.lineBreakMode = .byWordWrapping premiumDescriptionLabel.lineBreakMode = .byWordWrapping
premiumDescriptionLabel.numberOfLines = 0 premiumDescriptionLabel.numberOfLines = 0
premiumDescriptionLabel.font = AppFont.SFPro.regular(size: 16) premiumDescriptionLabel.attributedText = descriptionAttrString
premiumDescriptionLabel.text = "menu.premium.desc".localized()
premiumDescriptionLabel.setContentHuggingPriority(.defaultLow, for: .horizontal) premiumDescriptionLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
premiumContainer.addSubview(premiumDescriptionLabel) premiumContainer.addSubview(premiumDescriptionLabel)
buyButton.backgroundColor = .white
buyButton.setTitle("menu.buyNow".localized(), for: .normal)
buyButton.setTitleColor(ThemeManager.currentTheme.graphTintColor, for: .normal)
buyButton.titleLabel?.font = AppFont.SFPro.semibold(size: 15)
buyButton.layer.cornerRadius = 4
buyButton.addTarget(self, action: #selector(handleBuyButton), for: .touchUpInside) buyButton.addTarget(self, action: #selector(handleBuyButton), for: .touchUpInside)
premiumContainer.addSubview(buyButton) premiumContainer.addSubview(buyButton)
premiumImageView.contentMode = .scaleAspectFit
premiumImageView.image = UIImage(named: "premium")
premiumContainer.addSubview(premiumImageView)
//Constraints //Constraints
premiumContainer.snp.makeConstraints { (make) in premiumContainer.snp.makeConstraints { (make) in
make.top.equalTo(30) make.top.equalTo(30)
...@@ -102,24 +98,28 @@ private extension MenuHeaderView { ...@@ -102,24 +98,28 @@ private extension MenuHeaderView {
} }
premiumImageView.snp.makeConstraints { (make) in premiumImageView.snp.makeConstraints { (make) in
make.width.height.equalTo(140) make.top.equalToSuperview().inset(20)
make.right.bottom.equalToSuperview() make.bottom.equalToSuperview().inset(12)
make.right.equalToSuperview().inset(15)
} }
premiumHeadingLabel.snp.makeConstraints { (make) in premiumHeadingLabel.snp.makeConstraints { (make) in
make.left.top.equalToSuperview().inset(18) make.left.equalToSuperview().inset(18)
make.top.equalToSuperview().inset(26)
} }
premiumDescriptionLabel.snp.makeConstraints { (make) in premiumDescriptionLabel.snp.makeConstraints { (make) in
make.left.equalToSuperview().inset(18) make.left.equalToSuperview().inset(18)
make.top.equalTo(premiumHeadingLabel.snp.bottom) make.top.equalTo(premiumHeadingLabel.snp.bottom).offset(10)
make.right.equalTo(premiumImageView.snp.left) make.width.equalToSuperview().multipliedBy(0.53)
} }
buyButton.snp.makeConstraints { (make) in buyButton.snp.makeConstraints { (make) in
make.width.equalTo(100)
make.height.equalTo(35)
make.top.equalTo(premiumDescriptionLabel.snp.bottom).offset(18).priority(999) make.top.equalTo(premiumDescriptionLabel.snp.bottom).offset(18).priority(999)
make.left.equalToSuperview().inset(18) make.left.equalToSuperview().inset(18)
make.bottom.equalToSuperview().inset(24) make.bottom.equalToSuperview().inset(21)
} }
} }
} }
...@@ -11,9 +11,9 @@ import OneWeatherAnalytics ...@@ -11,9 +11,9 @@ import OneWeatherAnalytics
class SettingsViewController: UIViewController { class SettingsViewController: UIViewController {
//Private //Private
private let coordinator:SettingsCoordinator private let coordinator: SettingsCoordinator
private let settingsCellFactory:SettingsCellFactory private let settingsCellFactory: SettingsCellFactory
private let viewModel:SettingsViewModel private let viewModel: SettingsViewModel
private let tableView = UITableView(frame: .zero, style: .grouped) private let tableView = UITableView(frame: .zero, style: .grouped)
......
...@@ -10,9 +10,23 @@ import UIKit ...@@ -10,9 +10,23 @@ import UIKit
/// A view containing decription of features of upgrade to premium subscription for pro users (users who have previously purchased an in-app to remove ads). /// A view containing decription of features of upgrade to premium subscription for pro users (users who have previously purchased an in-app to remove ads).
class SubscriptionProDescriptionView: UIView { class SubscriptionProDescriptionView: UIView {
//Private
private let proMemeberContainer = UIView()
private let proMemberTopLabel = UILabel()
private let proMemberBottomLabel = UILabel()
private let upgradeLabel = UILabel()
private let proUsersContainer = UIView()
private let proUsersLabel = UILabel()
private let discountLabel = UILabel()
private let horizontalStackView = UIStackView()
public init() { public init() {
super.init(frame: .zero) super.init(frame: .zero)
self.translatesAutoresizingMaskIntoConstraints = false
prepareProMemberContainer()
prepareUpgradeLabels()
prepareHorizontalStackView()
prepareItems()
} }
@available(*, unavailable) @available(*, unavailable)
...@@ -20,3 +34,200 @@ class SubscriptionProDescriptionView: UIView { ...@@ -20,3 +34,200 @@ class SubscriptionProDescriptionView: UIView {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
} }
private extension SubscriptionProDescriptionView {
func prepareProMemberContainer() {
proMemeberContainer.layer.cornerRadius = 8
proMemeberContainer.layer.borderWidth = 1
proMemeberContainer.layer.borderColor = UIColor(hex: 0xd8ddfa).withAlphaComponent(0.8).cgColor
addSubview(proMemeberContainer)
proMemberTopLabel.text = "subscription.proMember.already.top".localized()
proMemberTopLabel.font = AppFont.SFPro.semibold(size: 16)
proMemberTopLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
proMemeberContainer.addSubview(proMemberTopLabel)
proMemberBottomLabel.text = "subscription.proMember.already.bottom".localized()
proMemberBottomLabel.font = AppFont.SFPro.regular(size: 14)
proMemberBottomLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
proMemeberContainer.addSubview(proMemberBottomLabel)
//Constraints
proMemeberContainer.snp.makeConstraints { make in
make.top.equalToSuperview().inset(24)
make.left.right.equalToSuperview().inset(24)
}
proMemberTopLabel.snp.makeConstraints { make in
make.left.equalToSuperview().inset(14)
make.top.equalToSuperview().inset(14)
}
proMemberBottomLabel.snp.makeConstraints { make in
make.left.equalToSuperview().inset(14)
make.top.equalTo(proMemberTopLabel.snp.bottom).offset(6)
make.bottom.equalToSuperview().inset(14)
}
}
func prepareUpgradeLabels() {
upgradeLabel.text = "subscription.description.upgradePremium".localized()
upgradeLabel.textColor = ThemeManager.currentTheme.primaryTextColor
upgradeLabel.font = AppFont.SFPro.bold(size: 24)
addSubview(upgradeLabel)
addSubview(proUsersContainer)
proUsersLabel.text = "subscription.description.forPro".localized()
proUsersLabel.textColor = ThemeManager.currentTheme.primaryTextColor
proUsersLabel.font = AppFont.SFPro.bold(size: 16)
proUsersContainer.addSubview(proUsersLabel)
let discountMarkerView = UIView()
discountMarkerView.layer.cornerRadius = 4
discountMarkerView.backgroundColor = UIColor(hex: 0xffc933)
proUsersContainer.addSubview(discountMarkerView)
discountLabel.textColor = ThemeManager.currentTheme.primaryTextColor
discountLabel.font = AppFont.SFPro.bold(size: 14)
discountLabel.text = "subscription.description.discount".localizedFormat("30%")
discountMarkerView.addSubview(discountLabel)
//Constarints
upgradeLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(proMemeberContainer.snp.bottom).offset(20)
}
proUsersContainer.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(upgradeLabel.snp.bottom).offset(8)
}
proUsersLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalToSuperview()
}
discountMarkerView.snp.makeConstraints { make in
make.top.right.bottom.equalToSuperview()
make.left.equalTo(proUsersLabel.snp.right).offset(8)
}
discountLabel.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(10)
make.top.bottom.equalToSuperview().inset(5)
}
}
func prepareHorizontalStackView() {
horizontalStackView.axis = .horizontal
horizontalStackView.distribution = .fill
horizontalStackView.spacing = 20
addSubview(horizontalStackView)
horizontalStackView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(proUsersContainer.snp.bottom).offset(25)
make.bottom.equalToSuperview().inset(26)
}
}
func prepareItems() {
let namesStackView = UIStackView()
namesStackView.spacing = 22
namesStackView.axis = .vertical
namesStackView.distribution = .fillProportionally
namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.adFree"))
namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.aqi"))
namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.hourly.pro"))
namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.daily.pro"))
namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.minutely"))
horizontalStackView.addArrangedSubview(namesStackView)
let proStackView = UIStackView()
proStackView.spacing = 22
proStackView.axis = .vertical
proStackView.distribution = .fillProportionally
proStackView.addArrangedSubview(DescriptionItemView(withHeader: "PRO"))
proStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark")))
proStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark")))
proStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark")))
proStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark")))
horizontalStackView.addArrangedSubview(proStackView)
let premiumStackView = UIStackView()
premiumStackView.spacing = 22
premiumStackView.axis = .vertical
premiumStackView.distribution = .fillProportionally
premiumStackView.addArrangedSubview(DescriptionItemView(withHeader: "PREMIUM"))
premiumStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark")))
premiumStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark")))
premiumStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark")))
premiumStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark")))
horizontalStackView.addArrangedSubview(premiumStackView)
}
}
private extension SubscriptionProDescriptionView {
private class DescriptionItemView: UIView {
init(textShortLocalizedKey: String) {
super.init(frame: .zero)
let label = UILabel()
label.font = AppFont.SFPro.medium(size: 16)
label.textColor = ThemeManager.currentTheme.primaryTextColor
label.text = ("subscription.description." + textShortLocalizedKey).localized()
addSubview(label)
self.snp.makeConstraints { make in
make.height.equalTo(20)
}
label.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.centerY.equalToSuperview()
}
}
init(withImage: UIImage?) {
super.init(frame: .zero)
let imageView = UIImageView()
imageView.image = withImage
imageView.contentMode = .scaleAspectFit
addSubview(imageView)
imageView.snp.makeConstraints { make in
make.width.height.equalTo(20)
make.edges.equalToSuperview()
}
}
init(withHeader: String) {
super.init(frame: .zero)
let label = UILabel()
label.textAlignment = .center
label.font = AppFont.SFPro.bold(size: 14)
label.textColor = ThemeManager.currentTheme.graphTintColor
label.text = withHeader
addSubview(label)
self.snp.makeConstraints { make in
make.height.equalTo(20)
make.width.equalTo(70)
}
label.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.centerY.equalToSuperview()
}
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}
...@@ -22,7 +22,12 @@ class SubscriptionViewModel: ViewModelProtocol { ...@@ -22,7 +22,12 @@ class SubscriptionViewModel: ViewModelProtocol {
} }
public var isProUser: Bool { public var isProUser: Bool {
storeManager.removeAdsPurchased #if DEBUG
return true
#else
fatalError("Remove in production")
#endif
// storeManager.removeAdsPurchased
} }
public func purchase(subscription: SKProduct) { public func purchase(subscription: SKProduct) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment