1.2.0: offer code redemption + share link alongside export image

- "Redeem promo code" button in PremiumView via offerCodeRedemption
  (hidden on Mac where the sheet is unavailable); entitlement re-checked
  on success — unblocks influencer/blog promo campaigns
- System share sheet now includes a localized text with the mealmood.app
  link next to the exported image (viral loop no longer QR-only)
- 2 new strings × 6 languages

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtWT52pAE91D7mbDda1cAM
This commit is contained in:
alexandrev-tibco
2026-07-03 10:14:58 +02:00
parent f5cb67adc0
commit cbe0ca1326
8 changed files with 46 additions and 1 deletions
+3 -1
View File
@@ -62,7 +62,9 @@ struct SocialShareSheet: View {
}
.toast(isShowing: $showCopiedToast, message: String(localized: "share_copied"))
.sheet(isPresented: $showSystemShare) {
SystemShareSheet(activityItems: [imageURL])
// Ship the link as text alongside the image so the viral loop isn't
// limited to the QR baked into the rendered export.
SystemShareSheet(activityItems: [imageURL, String(localized: "share_link_text")])
}
}
+19
View File
@@ -8,6 +8,7 @@ struct PremiumView: View {
@State private var appearedAt: Date = Date()
@State private var didConvert: Bool = false
@State private var selectedPlan: PlanChoice = .yearly
@State private var showOfferCodeRedemption: Bool = false
let settings: AppSettings
var source: String = "unknown"
@@ -112,6 +113,17 @@ struct PremiumView: View {
}
.padding(.top, 4)
if !ProcessInfo.processInfo.isiOSAppOnMac {
Button {
showOfferCodeRedemption = true
} label: {
Text("premium_redeem_code")
.font(.mealMoodSmall)
.foregroundColor(.mealMoodCoral)
}
.padding(.top, 2)
}
Text("premium_terms_note")
.font(.mealMoodCaption)
.foregroundColor(.mealMoodTextSecondary)
@@ -129,6 +141,13 @@ struct PremiumView: View {
.task {
await storeManager.loadProducts()
}
.offerCodeRedemption(isPresented: $showOfferCodeRedemption) { result in
if case .success = result {
// Entitlement propagates via Transaction.updates; force a re-check
// so premium unlocks immediately after redeeming.
Task { await storeManager.restorePurchases() }
}
}
.onAppear {
appearedAt = Date()
AnalyticsService.logPaywallViewed(source: source)