Commit 7b9c9f69 by Dmitry Stepanets

Finished subscriptions UI

parent 616e3d2e
...@@ -50,9 +50,6 @@ ...@@ -50,9 +50,6 @@
ReferencedContainer = "container:1Weather.xcodeproj"> ReferencedContainer = "container:1Weather.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
<StoreKitConfigurationFileReference
identifier = "../1Weather/InApps/Configuration.storekit">
</StoreKitConfigurationFileReference>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release" buildConfiguration = "Release"
......
{
"images" : [
{
"filename" : "subscription_cross.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
...@@ -227,12 +227,19 @@ ...@@ -227,12 +227,19 @@
"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.pro" = "Hourly forecasts";
"subscription.description.items.hourly.crossed" = "24 hours"; "subscription.description.items.hourly.crossed" = "24 hours";
"subscription.description.items.hourly.pro.opt" = "12 hours";
"subscription.description.items.hourly.premium.opt" = "48 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.pro" = "Daily forecasts";
"subscription.description.items.daily.crossed" = "7 days"; "subscription.description.items.daily.crossed" = "7 days";
"subscription.description.items.daily.pro.opt" = "7 days";
"subscription.description.items.daily.premium.opt" = "10 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";
"subscription.description.items.minutely" = "Minutely Forecast"; "subscription.description.items.minutely" = "Minutely Forecast";
......
...@@ -193,6 +193,8 @@ extension SubscriptionDescriptionView { ...@@ -193,6 +193,8 @@ extension SubscriptionDescriptionView {
} }
textView.attributedText = attributedText textView.attributedText = attributedText
textView.adjustsFontSizeToFitWidth = true
textView.minimumScaleFactor = 0.2
iconView.image = image iconView.image = image
addSubview(iconView) addSubview(iconView)
......
...@@ -43,6 +43,8 @@ private extension SubscriptionProDescriptionView { ...@@ -43,6 +43,8 @@ private extension SubscriptionProDescriptionView {
addSubview(proMemeberContainer) addSubview(proMemeberContainer)
proMemberTopLabel.text = "subscription.proMember.already.top".localized() proMemberTopLabel.text = "subscription.proMember.already.top".localized()
proMemberTopLabel.lineBreakMode = .byWordWrapping
proMemberTopLabel.numberOfLines = 0
proMemberTopLabel.font = AppFont.SFPro.semibold(size: 16) proMemberTopLabel.font = AppFont.SFPro.semibold(size: 16)
proMemberTopLabel.textColor = ThemeManager.currentTheme.secondaryTextColor proMemberTopLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
proMemeberContainer.addSubview(proMemberTopLabel) proMemeberContainer.addSubview(proMemberTopLabel)
...@@ -59,7 +61,7 @@ private extension SubscriptionProDescriptionView { ...@@ -59,7 +61,7 @@ private extension SubscriptionProDescriptionView {
} }
proMemberTopLabel.snp.makeConstraints { make in proMemberTopLabel.snp.makeConstraints { make in
make.left.equalToSuperview().inset(14) make.left.right.equalToSuperview().inset(14)
make.top.equalToSuperview().inset(14) make.top.equalToSuperview().inset(14)
} }
...@@ -122,14 +124,14 @@ private extension SubscriptionProDescriptionView { ...@@ -122,14 +124,14 @@ private extension SubscriptionProDescriptionView {
func prepareHorizontalStackView() { func prepareHorizontalStackView() {
horizontalStackView.axis = .horizontal horizontalStackView.axis = .horizontal
horizontalStackView.distribution = .fill horizontalStackView.distribution = .fillProportionally
horizontalStackView.spacing = 20 horizontalStackView.spacing = 20
addSubview(horizontalStackView) addSubview(horizontalStackView)
horizontalStackView.snp.makeConstraints { make in horizontalStackView.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalToSuperview()
make.top.equalTo(proUsersContainer.snp.bottom).offset(25) make.top.equalTo(proUsersContainer.snp.bottom).offset(25)
make.bottom.equalToSuperview().inset(26) make.bottom.equalToSuperview()
} }
} }
...@@ -137,7 +139,9 @@ private extension SubscriptionProDescriptionView { ...@@ -137,7 +139,9 @@ private extension SubscriptionProDescriptionView {
let namesStackView = UIStackView() let namesStackView = UIStackView()
namesStackView.spacing = 22 namesStackView.spacing = 22
namesStackView.axis = .vertical namesStackView.axis = .vertical
namesStackView.distribution = .fillProportionally namesStackView.distribution = .fillEqually
namesStackView.isLayoutMarginsRelativeArrangement = true
namesStackView.layoutMargins = .init(top: 34, left: 0, bottom: 0, right: 0)
namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.adFree")) namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.adFree"))
namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.aqi")) namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.aqi"))
namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.hourly.pro")) namesStackView.addArrangedSubview(DescriptionItemView(textShortLocalizedKey: "items.hourly.pro"))
...@@ -148,50 +152,67 @@ private extension SubscriptionProDescriptionView { ...@@ -148,50 +152,67 @@ private extension SubscriptionProDescriptionView {
let proStackView = UIStackView() let proStackView = UIStackView()
proStackView.spacing = 22 proStackView.spacing = 22
proStackView.axis = .vertical proStackView.axis = .vertical
proStackView.distribution = .fillProportionally proStackView.distribution = .fillEqually
proStackView.alignment = .center
proStackView.addArrangedSubview(DescriptionItemView(withHeader: "PRO")) 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_cross")))
proStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark"))) proStackView.addArrangedSubview(DescriptionItemView(withText: "subscription.description.items.hourly.pro.opt".localized(),
proStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark"))) isBold: false))
proStackView.addArrangedSubview(DescriptionItemView(withText: "subscription.description.items.daily.pro.opt".localized(),
isBold: false))
proStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_cross")))
proStackView.setCustomSpacing(13, after: proStackView.arrangedSubviews[0])
horizontalStackView.addArrangedSubview(proStackView) horizontalStackView.addArrangedSubview(proStackView)
let premiumStackView = UIStackView() let premiumStackView = UIStackView()
premiumStackView.spacing = 22 premiumStackView.spacing = 22
premiumStackView.axis = .vertical premiumStackView.axis = .vertical
premiumStackView.distribution = .fillProportionally premiumStackView.distribution = .fillEqually
premiumStackView.alignment = .center
premiumStackView.addArrangedSubview(DescriptionItemView(withHeader: "PREMIUM")) 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")))
premiumStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark"))) premiumStackView.addArrangedSubview(DescriptionItemView(withText: "subscription.description.items.hourly.premium.opt".localized(),
premiumStackView.addArrangedSubview(DescriptionItemView(withImage: UIImage(named: "subscription_checkmark"))) isBold: true))
premiumStackView.addArrangedSubview(DescriptionItemView(withText: "subscription.description.items.daily.premium.opt".localized(),
isBold: true))
premiumStackView.addArrangedSubview(DescriptionItemView(withMarker: "subscription.description.items.comingSoon".localized()))
premiumStackView.setCustomSpacing(13, after: premiumStackView.arrangedSubviews[0])
horizontalStackView.addArrangedSubview(premiumStackView) horizontalStackView.addArrangedSubview(premiumStackView)
} }
} }
private extension SubscriptionProDescriptionView { private extension SubscriptionProDescriptionView {
private class DescriptionItemView: UIView { private class DescriptionItemView: UIView {
init(textShortLocalizedKey: String) { init() {
super.init(frame: .zero) super.init(frame: .zero)
self.snp.makeConstraints { make in
make.height.equalTo(20)
}
}
convenience init(textShortLocalizedKey: String) {
self.init()
let label = UILabel() let label = UILabel()
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.2
label.font = AppFont.SFPro.medium(size: 16) label.font = AppFont.SFPro.medium(size: 16)
label.textColor = ThemeManager.currentTheme.primaryTextColor label.textColor = ThemeManager.currentTheme.primaryTextColor
label.text = ("subscription.description." + textShortLocalizedKey).localized() label.text = ("subscription.description." + textShortLocalizedKey).localized()
addSubview(label) addSubview(label)
self.snp.makeConstraints { make in
make.height.equalTo(20)
}
label.snp.makeConstraints { make in label.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalToSuperview()
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
} }
} }
init(withImage: UIImage?) { convenience init(withImage: UIImage?) {
super.init(frame: .zero) self.init()
let imageView = UIImageView() let imageView = UIImageView()
imageView.image = withImage imageView.image = withImage
...@@ -200,12 +221,34 @@ private extension SubscriptionProDescriptionView { ...@@ -200,12 +221,34 @@ private extension SubscriptionProDescriptionView {
imageView.snp.makeConstraints { make in imageView.snp.makeConstraints { make in
make.width.height.equalTo(20) make.width.height.equalTo(20)
make.edges.equalToSuperview() make.center.equalToSuperview()
} }
} }
init(withHeader: String) { convenience init(withText: String, isBold: Bool) {
super.init(frame: .zero) self.init()
let label = UILabel()
label.textAlignment = .center
label.text = withText
label.textColor = ThemeManager.currentTheme.primaryTextColor
if isBold {
label.font = AppFont.SFPro.bold(size: 14)
}
else {
label.font = AppFont.SFPro.regular(size: 14)
}
addSubview(label)
label.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.centerY.equalToSuperview()
}
}
convenience init(withHeader: String) {
self.init()
let label = UILabel() let label = UILabel()
label.textAlignment = .center label.textAlignment = .center
...@@ -215,7 +258,6 @@ private extension SubscriptionProDescriptionView { ...@@ -215,7 +258,6 @@ private extension SubscriptionProDescriptionView {
addSubview(label) addSubview(label)
self.snp.makeConstraints { make in self.snp.makeConstraints { make in
make.height.equalTo(20)
make.width.equalTo(70) make.width.equalTo(70)
} }
...@@ -225,6 +267,34 @@ private extension SubscriptionProDescriptionView { ...@@ -225,6 +267,34 @@ private extension SubscriptionProDescriptionView {
} }
} }
convenience init(withMarker text: String) {
self.init()
let container = UIView()
container.backgroundColor = UIColor(hex: 0xffb820).withAlphaComponent(0.3)
container.layer.cornerRadius = 4
addSubview(container)
let label = UILabel()
label.text = text
label.font = AppFont.SFPro.semibold(size: 10)
label.textColor = .black
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.2
container.addSubview(label)
//Contraints
container.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
label.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(6)
make.top.bottom.equalToSuperview().inset(3)
}
}
@available(*, unavailable) @available(*, unavailable)
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
......
...@@ -28,8 +28,13 @@ class SubscriptionPurchaseButton: UIButton { ...@@ -28,8 +28,13 @@ class SubscriptionPurchaseButton: UIButton {
self.subscription = subscription self.subscription = subscription
self.subscriptionType = type self.subscriptionType = type
super.init(frame: .zero) super.init(frame: .zero)
self.titleLabel?.adjustsFontSizeToFitWidth = true
self.titleLabel?.minimumScaleFactor = 0.2
self.translatesAutoresizingMaskIntoConstraints = false self.translatesAutoresizingMaskIntoConstraints = false
self.setAttributedTitle(buildTitle(), for: .normal) self.titleEdgeInsets = .init(top: 0, left: 16, bottom: 0, right: 16)
self.setAttributedTitle(buildTitle(forType: type), for: .normal)
if type == .yearly { if type == .yearly {
self.setTitleColor(ThemeManager.currentTheme.subscriptionPurchaseColor, for: .normal) self.setTitleColor(ThemeManager.currentTheme.subscriptionPurchaseColor, for: .normal)
self.backgroundColor = ThemeManager.currentTheme.subscriptionPurchaseBackgroundColor self.backgroundColor = ThemeManager.currentTheme.subscriptionPurchaseBackgroundColor
...@@ -55,7 +60,7 @@ class SubscriptionPurchaseButton: UIButton { ...@@ -55,7 +60,7 @@ class SubscriptionPurchaseButton: UIButton {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
private func buildTitle() -> NSAttributedString { private func buildTitle(forType type: SubscriptionPurchaseButton.SubscriptionType) -> NSAttributedString {
guard let price = subscription.localizedPrice else { guard let price = subscription.localizedPrice else {
return NSAttributedString() return NSAttributedString()
} }
...@@ -95,6 +100,20 @@ class SubscriptionPurchaseButton: UIButton { ...@@ -95,6 +100,20 @@ class SubscriptionPurchaseButton: UIButton {
} }
result.replaceCharacters(in: discountPriceRange, with: discountPrice) result.replaceCharacters(in: discountPriceRange, with: discountPrice)
} }
if type == .yearly {
result.addAttribute(.foregroundColor,
value: ThemeManager.currentTheme.subscriptionPurchaseColor,
range: .init(location: 0, length: result.string.count))
self.setTitleColor(ThemeManager.currentTheme.subscriptionPurchaseColor, for: .normal)
}
else {
result.addAttribute(.foregroundColor,
value: ThemeManager.currentTheme.subscriptionPurchaseBackgroundColor,
range: .init(location: 0, length: result.string.count))
self.setTitleColor(ThemeManager.currentTheme.subscriptionPurchaseBackgroundColor, for: .normal)
}
return result return result
} }
......
...@@ -31,9 +31,9 @@ class SubscriptionTopView: UIView { ...@@ -31,9 +31,9 @@ class SubscriptionTopView: UIView {
logoView.image = UIImage(named: "subscription_logo") logoView.image = UIImage(named: "subscription_logo")
logoView.contentMode = .scaleAspectFit logoView.contentMode = .scaleAspectFit
addSubview(logoView)
addSubview(oneWeatherLabel) addSubview(oneWeatherLabel)
addSubview(premiumLabel) addSubview(premiumLabel)
addSubview(logoView)
oneWeatherLabel.snp.makeConstraints { make in oneWeatherLabel.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(28) make.leading.equalToSuperview().offset(28)
......
...@@ -22,12 +22,7 @@ class SubscriptionViewModel: ViewModelProtocol { ...@@ -22,12 +22,7 @@ class SubscriptionViewModel: ViewModelProtocol {
} }
public var isProUser: Bool { public var isProUser: Bool {
#if DEBUG storeManager.removeAdsPurchased
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