|
@@ -262,6 +262,9 @@ class ViewController: NSViewController {
|
|
|
private var selectedPremiumPlan: PremiumPlan = .monthly
|
|
private var selectedPremiumPlan: PremiumPlan = .monthly
|
|
|
private var paywallPlanViews: [PremiumPlan: NSView] = [:]
|
|
private var paywallPlanViews: [PremiumPlan: NSView] = [:]
|
|
|
private var premiumPlanByView = [ObjectIdentifier: PremiumPlan]()
|
|
private var premiumPlanByView = [ObjectIdentifier: PremiumPlan]()
|
|
|
|
|
+ private var paywallPlanPriceLabels: [PremiumPlan: NSTextField] = [:]
|
|
|
|
|
+ private var paywallPlanSubtitleLabels: [PremiumPlan: NSTextField] = [:]
|
|
|
|
|
+ private var paywallPlanStrikeLabels: [PremiumPlan: NSTextField] = [:]
|
|
|
private weak var paywallOfferLabel: NSTextField?
|
|
private weak var paywallOfferLabel: NSTextField?
|
|
|
private weak var paywallContinueLabel: NSTextField?
|
|
private weak var paywallContinueLabel: NSTextField?
|
|
|
private weak var paywallContinueButton: NSView?
|
|
private weak var paywallContinueButton: NSView?
|
|
@@ -3169,6 +3172,9 @@ class ViewController: NSViewController {
|
|
|
|
|
|
|
|
private func makePaywallContent() -> NSView {
|
|
private func makePaywallContent() -> NSView {
|
|
|
paywallPlanViews.removeAll()
|
|
paywallPlanViews.removeAll()
|
|
|
|
|
+ paywallPlanPriceLabels.removeAll()
|
|
|
|
|
+ paywallPlanSubtitleLabels.removeAll()
|
|
|
|
|
+ paywallPlanStrikeLabels.removeAll()
|
|
|
premiumPlanByView.removeAll()
|
|
premiumPlanByView.removeAll()
|
|
|
paywallOfferLabel = nil
|
|
paywallOfferLabel = nil
|
|
|
paywallContinueLabel = nil
|
|
paywallContinueLabel = nil
|
|
@@ -3223,10 +3229,10 @@ class ViewController: NSViewController {
|
|
|
|
|
|
|
|
let weeklyCard = paywallPlanCard(
|
|
let weeklyCard = paywallPlanCard(
|
|
|
title: "Weekly",
|
|
title: "Weekly",
|
|
|
- price: "PKR 1,100.00",
|
|
|
|
|
|
|
+ price: paywallDisplayPrice(for: .weekly),
|
|
|
badge: "Basic Deal",
|
|
badge: "Basic Deal",
|
|
|
badgeColor: NSColor(calibratedRed: 1.0, green: 0.60, blue: 0.20, alpha: 1),
|
|
badgeColor: NSColor(calibratedRed: 1.0, green: 0.60, blue: 0.20, alpha: 1),
|
|
|
- subtitle: nil,
|
|
|
|
|
|
|
+ subtitle: "Billed weekly",
|
|
|
plan: .weekly,
|
|
plan: .weekly,
|
|
|
strikePrice: nil
|
|
strikePrice: nil
|
|
|
)
|
|
)
|
|
@@ -3234,10 +3240,10 @@ class ViewController: NSViewController {
|
|
|
|
|
|
|
|
let monthlyCard = paywallPlanCard(
|
|
let monthlyCard = paywallPlanCard(
|
|
|
title: "Monthly",
|
|
title: "Monthly",
|
|
|
- price: "PKR 2,500.00",
|
|
|
|
|
|
|
+ price: paywallDisplayPrice(for: .monthly),
|
|
|
badge: "Free Trial",
|
|
badge: "Free Trial",
|
|
|
badgeColor: NSColor(calibratedRed: 0.19, green: 0.82, blue: 0.39, alpha: 1),
|
|
badgeColor: NSColor(calibratedRed: 0.19, green: 0.82, blue: 0.39, alpha: 1),
|
|
|
- subtitle: "625.00/week",
|
|
|
|
|
|
|
+ subtitle: "7-day free trial, then monthly",
|
|
|
plan: .monthly,
|
|
plan: .monthly,
|
|
|
strikePrice: nil
|
|
strikePrice: nil
|
|
|
)
|
|
)
|
|
@@ -3245,10 +3251,10 @@ class ViewController: NSViewController {
|
|
|
|
|
|
|
|
let yearlyCard = paywallPlanCard(
|
|
let yearlyCard = paywallPlanCard(
|
|
|
title: "Yearly",
|
|
title: "Yearly",
|
|
|
- price: "PKR 9,900.00",
|
|
|
|
|
|
|
+ price: paywallDisplayPrice(for: .yearly),
|
|
|
badge: "Best Deal",
|
|
badge: "Best Deal",
|
|
|
badgeColor: NSColor(calibratedRed: 1.0, green: 0.60, blue: 0.20, alpha: 1),
|
|
badgeColor: NSColor(calibratedRed: 1.0, green: 0.60, blue: 0.20, alpha: 1),
|
|
|
- subtitle: "190.38/week",
|
|
|
|
|
|
|
+ subtitle: "Billed yearly",
|
|
|
plan: .yearly,
|
|
plan: .yearly,
|
|
|
strikePrice: nil
|
|
strikePrice: nil
|
|
|
)
|
|
)
|
|
@@ -3256,12 +3262,12 @@ class ViewController: NSViewController {
|
|
|
|
|
|
|
|
let lifetimeCard = paywallPlanCard(
|
|
let lifetimeCard = paywallPlanCard(
|
|
|
title: "Lifetime",
|
|
title: "Lifetime",
|
|
|
- price: "PKR 14,900.00",
|
|
|
|
|
|
|
+ price: paywallDisplayPrice(for: .lifetime),
|
|
|
badge: "Save 50%",
|
|
badge: "Save 50%",
|
|
|
badgeColor: NSColor(calibratedRed: 1.0, green: 0.60, blue: 0.20, alpha: 1),
|
|
badgeColor: NSColor(calibratedRed: 1.0, green: 0.60, blue: 0.20, alpha: 1),
|
|
|
- subtitle: nil,
|
|
|
|
|
|
|
+ subtitle: "One-time purchase",
|
|
|
plan: .lifetime,
|
|
plan: .lifetime,
|
|
|
- strikePrice: "PKR 29,800.00"
|
|
|
|
|
|
|
+ strikePrice: nil
|
|
|
)
|
|
)
|
|
|
contentStack.addArrangedSubview(lifetimeCard)
|
|
contentStack.addArrangedSubview(lifetimeCard)
|
|
|
updatePaywallPlanSelection()
|
|
updatePaywallPlanSelection()
|
|
@@ -3453,6 +3459,7 @@ class ViewController: NSViewController {
|
|
|
card.addSubview(titleLabel)
|
|
card.addSubview(titleLabel)
|
|
|
let priceLabel = textLabel(price, font: NSFont.systemFont(ofSize: 12, weight: .bold), color: primaryText)
|
|
let priceLabel = textLabel(price, font: NSFont.systemFont(ofSize: 12, weight: .bold), color: primaryText)
|
|
|
card.addSubview(priceLabel)
|
|
card.addSubview(priceLabel)
|
|
|
|
|
+ paywallPlanPriceLabels[plan] = priceLabel
|
|
|
|
|
|
|
|
NSLayoutConstraint.activate([
|
|
NSLayoutConstraint.activate([
|
|
|
badgeWrap.centerXAnchor.constraint(equalTo: card.centerXAnchor),
|
|
badgeWrap.centerXAnchor.constraint(equalTo: card.centerXAnchor),
|
|
@@ -3468,6 +3475,7 @@ class ViewController: NSViewController {
|
|
|
if let subtitle {
|
|
if let subtitle {
|
|
|
let sub = textLabel(subtitle, font: NSFont.systemFont(ofSize: 10, weight: .semibold), color: secondaryText)
|
|
let sub = textLabel(subtitle, font: NSFont.systemFont(ofSize: 10, weight: .semibold), color: secondaryText)
|
|
|
card.addSubview(sub)
|
|
card.addSubview(sub)
|
|
|
|
|
+ paywallPlanSubtitleLabels[plan] = sub
|
|
|
NSLayoutConstraint.activate([
|
|
NSLayoutConstraint.activate([
|
|
|
sub.trailingAnchor.constraint(equalTo: priceLabel.trailingAnchor),
|
|
sub.trailingAnchor.constraint(equalTo: priceLabel.trailingAnchor),
|
|
|
sub.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 0)
|
|
sub.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 0)
|
|
@@ -3477,6 +3485,7 @@ class ViewController: NSViewController {
|
|
|
if let strikePrice {
|
|
if let strikePrice {
|
|
|
let strike = textLabel(strikePrice, font: NSFont.systemFont(ofSize: 12, weight: .medium), color: NSColor.systemRed)
|
|
let strike = textLabel(strikePrice, font: NSFont.systemFont(ofSize: 12, weight: .medium), color: NSColor.systemRed)
|
|
|
card.addSubview(strike)
|
|
card.addSubview(strike)
|
|
|
|
|
+ paywallPlanStrikeLabels[plan] = strike
|
|
|
NSLayoutConstraint.activate([
|
|
NSLayoutConstraint.activate([
|
|
|
strike.trailingAnchor.constraint(equalTo: priceLabel.trailingAnchor),
|
|
strike.trailingAnchor.constraint(equalTo: priceLabel.trailingAnchor),
|
|
|
strike.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 4)
|
|
strike.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 4)
|
|
@@ -3510,22 +3519,39 @@ class ViewController: NSViewController {
|
|
|
if storeKitCoordinator.hasPremiumAccess {
|
|
if storeKitCoordinator.hasPremiumAccess {
|
|
|
return "Premium is active on this Apple ID."
|
|
return "Premium is active on this Apple ID."
|
|
|
}
|
|
}
|
|
|
- if let product = storeKitCoordinator.productsByID[plan.rawValue] {
|
|
|
|
|
- return "\(product.displayPrice) purchase"
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ let price = paywallDisplayPrice(for: plan)
|
|
|
switch plan {
|
|
switch plan {
|
|
|
- case .weekly: return "PKR 1,100.00/week"
|
|
|
|
|
- case .monthly: return "PKR 2,500.00/month"
|
|
|
|
|
- case .yearly: return "PKR 9,900.00/year"
|
|
|
|
|
- case .lifetime: return "PKR 14,900.00 one-time purchase"
|
|
|
|
|
|
|
+ case .weekly: return "\(price)/week"
|
|
|
|
|
+ case .monthly: return "7-day free trial, then \(price)/month"
|
|
|
|
|
+ case .yearly: return "\(price)/year"
|
|
|
|
|
+ case .lifetime: return "\(price) one-time purchase"
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private func refreshPaywallStoreUI() {
|
|
private func refreshPaywallStoreUI() {
|
|
|
|
|
+ refreshPaywallPlanPrices()
|
|
|
updatePaywallPlanSelection()
|
|
updatePaywallPlanSelection()
|
|
|
updatePaywallContinueState(isLoading: false)
|
|
updatePaywallContinueState(isLoading: false)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private func refreshPaywallPlanPrices() {
|
|
|
|
|
+ for plan in PremiumPlan.allCases {
|
|
|
|
|
+ paywallPlanPriceLabels[plan]?.stringValue = paywallDisplayPrice(for: plan)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private func paywallDisplayPrice(for plan: PremiumPlan) -> String {
|
|
|
|
|
+ if let product = storeKitCoordinator.productsByID[plan.rawValue] {
|
|
|
|
|
+ return product.displayPrice
|
|
|
|
|
+ }
|
|
|
|
|
+ switch plan {
|
|
|
|
|
+ case .weekly: return "1,100.00"
|
|
|
|
|
+ case .monthly: return "2,500.00"
|
|
|
|
|
+ case .yearly: return "9,900.00"
|
|
|
|
|
+ case .lifetime: return "14,900.00"
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@objc private func paywallContinueClicked(_ sender: Any?) {
|
|
@objc private func paywallContinueClicked(_ sender: Any?) {
|
|
|
startSelectedPlanPurchase()
|
|
startSelectedPlanPurchase()
|
|
|
}
|
|
}
|