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:
@@ -380,3 +380,7 @@
|
|||||||
/* Widget promo (1.2.0) */
|
/* Widget promo (1.2.0) */
|
||||||
"widget_promo_title" = "Die heutigen Mahlzeiten auf deinem Home-Bildschirm";
|
"widget_promo_title" = "Die heutigen Mahlzeiten auf deinem Home-Bildschirm";
|
||||||
"widget_promo_body" = "Halte den Home-Bildschirm gedrückt, tippe auf + und suche nach MealMood, um das Widget hinzuzufügen.";
|
"widget_promo_body" = "Halte den Home-Bildschirm gedrückt, tippe auf + und suche nach MealMood, um das Widget hinzuzufügen.";
|
||||||
|
|
||||||
|
/* Offer codes + share link (1.2.0) */
|
||||||
|
"premium_redeem_code" = "Promo-Code einlösen";
|
||||||
|
"share_link_text" = "Unsere Woche, geplant mit MealMood → https://mealmood.app";
|
||||||
|
|||||||
@@ -380,3 +380,7 @@
|
|||||||
/* Widget promo (1.2.0) */
|
/* Widget promo (1.2.0) */
|
||||||
"widget_promo_title" = "Today's meals on your Home Screen";
|
"widget_promo_title" = "Today's meals on your Home Screen";
|
||||||
"widget_promo_body" = "Long-press your Home Screen, tap +, and search for MealMood to add the widget.";
|
"widget_promo_body" = "Long-press your Home Screen, tap +, and search for MealMood to add the widget.";
|
||||||
|
|
||||||
|
/* Offer codes + share link (1.2.0) */
|
||||||
|
"premium_redeem_code" = "Redeem promo code";
|
||||||
|
"share_link_text" = "Our week, planned with MealMood → https://mealmood.app";
|
||||||
|
|||||||
@@ -380,3 +380,7 @@
|
|||||||
/* Widget promo (1.2.0) */
|
/* Widget promo (1.2.0) */
|
||||||
"widget_promo_title" = "Las comidas de hoy en tu pantalla de inicio";
|
"widget_promo_title" = "Las comidas de hoy en tu pantalla de inicio";
|
||||||
"widget_promo_body" = "Mantén pulsada la pantalla de inicio, toca + y busca MealMood para añadir el widget.";
|
"widget_promo_body" = "Mantén pulsada la pantalla de inicio, toca + y busca MealMood para añadir el widget.";
|
||||||
|
|
||||||
|
/* Offer codes + share link (1.2.0) */
|
||||||
|
"premium_redeem_code" = "Canjear código promocional";
|
||||||
|
"share_link_text" = "Nuestra semana, planificada con MealMood → https://mealmood.app";
|
||||||
|
|||||||
@@ -380,3 +380,7 @@
|
|||||||
/* Widget promo (1.2.0) */
|
/* Widget promo (1.2.0) */
|
||||||
"widget_promo_title" = "Les repas du jour sur votre écran d'accueil";
|
"widget_promo_title" = "Les repas du jour sur votre écran d'accueil";
|
||||||
"widget_promo_body" = "Appuyez longuement sur l'écran d'accueil, touchez + et cherchez MealMood pour ajouter le widget.";
|
"widget_promo_body" = "Appuyez longuement sur l'écran d'accueil, touchez + et cherchez MealMood pour ajouter le widget.";
|
||||||
|
|
||||||
|
/* Offer codes + share link (1.2.0) */
|
||||||
|
"premium_redeem_code" = "Utiliser un code promo";
|
||||||
|
"share_link_text" = "Notre semaine, planifiée avec MealMood → https://mealmood.app";
|
||||||
|
|||||||
@@ -380,3 +380,7 @@
|
|||||||
/* Widget promo (1.2.0) */
|
/* Widget promo (1.2.0) */
|
||||||
"widget_promo_title" = "I pasti di oggi sulla schermata Home";
|
"widget_promo_title" = "I pasti di oggi sulla schermata Home";
|
||||||
"widget_promo_body" = "Tieni premuta la schermata Home, tocca + e cerca MealMood per aggiungere il widget.";
|
"widget_promo_body" = "Tieni premuta la schermata Home, tocca + e cerca MealMood per aggiungere il widget.";
|
||||||
|
|
||||||
|
/* Offer codes + share link (1.2.0) */
|
||||||
|
"premium_redeem_code" = "Riscatta codice promo";
|
||||||
|
"share_link_text" = "La nostra settimana, pianificata con MealMood → https://mealmood.app";
|
||||||
|
|||||||
@@ -380,3 +380,7 @@
|
|||||||
/* Widget promo (1.2.0) */
|
/* Widget promo (1.2.0) */
|
||||||
"widget_promo_title" = "As refeições de hoje na sua tela de início";
|
"widget_promo_title" = "As refeições de hoje na sua tela de início";
|
||||||
"widget_promo_body" = "Pressione a tela de início, toque em + e procure MealMood para adicionar o widget.";
|
"widget_promo_body" = "Pressione a tela de início, toque em + e procure MealMood para adicionar o widget.";
|
||||||
|
|
||||||
|
/* Offer codes + share link (1.2.0) */
|
||||||
|
"premium_redeem_code" = "Resgatar código promocional";
|
||||||
|
"share_link_text" = "Nossa semana, planejada com MealMood → https://mealmood.app";
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ struct SocialShareSheet: View {
|
|||||||
}
|
}
|
||||||
.toast(isShowing: $showCopiedToast, message: String(localized: "share_copied"))
|
.toast(isShowing: $showCopiedToast, message: String(localized: "share_copied"))
|
||||||
.sheet(isPresented: $showSystemShare) {
|
.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")])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ struct PremiumView: View {
|
|||||||
@State private var appearedAt: Date = Date()
|
@State private var appearedAt: Date = Date()
|
||||||
@State private var didConvert: Bool = false
|
@State private var didConvert: Bool = false
|
||||||
@State private var selectedPlan: PlanChoice = .yearly
|
@State private var selectedPlan: PlanChoice = .yearly
|
||||||
|
@State private var showOfferCodeRedemption: Bool = false
|
||||||
|
|
||||||
let settings: AppSettings
|
let settings: AppSettings
|
||||||
var source: String = "unknown"
|
var source: String = "unknown"
|
||||||
@@ -112,6 +113,17 @@ struct PremiumView: View {
|
|||||||
}
|
}
|
||||||
.padding(.top, 4)
|
.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")
|
Text("premium_terms_note")
|
||||||
.font(.mealMoodCaption)
|
.font(.mealMoodCaption)
|
||||||
.foregroundColor(.mealMoodTextSecondary)
|
.foregroundColor(.mealMoodTextSecondary)
|
||||||
@@ -129,6 +141,13 @@ struct PremiumView: View {
|
|||||||
.task {
|
.task {
|
||||||
await storeManager.loadProducts()
|
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 {
|
.onAppear {
|
||||||
appearedAt = Date()
|
appearedAt = Date()
|
||||||
AnalyticsService.logPaywallViewed(source: source)
|
AnalyticsService.logPaywallViewed(source: source)
|
||||||
|
|||||||
Reference in New Issue
Block a user