From a4aedffd5a651619656b5e2c94771a30ef83c1eb Mon Sep 17 00:00:00 2001 From: alexandrev-tibco Date: Sun, 26 Jul 2026 08:34:05 +0200 Subject: [PATCH] 2.0: banner export solo en semana completa + compartir desde toolbar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - El banner "ready to export" ya no aparece con la semana incompleta; solo cuando no quedan slots vacíos (y sigue siendo descartable con la X). - Se añade un icono de compartir en la toolbar (cuando hay algo planificado) para no perder el acceso a exportar en semanas parciales; misma lógica de premium/paywall que el banner. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01A3HaWmmtTQ1vdTERtSYU6p --- MealMood/Views/Home/HomeView.swift | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/MealMood/Views/Home/HomeView.swift b/MealMood/Views/Home/HomeView.swift index 266454b..39b38a9 100644 --- a/MealMood/Views/Home/HomeView.swift +++ b/MealMood/Views/Home/HomeView.swift @@ -202,6 +202,15 @@ struct HomeView: View { HStack(spacing: 10) { if let settings = settings, let plan = fetchWeekPlan(for: viewModel.currentWeekStart) { + if plan.slotList.contains(where: { $0.dishId != nil || $0.isEatingOut }) { + Button { + requestWeekShare(plan: plan, settings: settings) + } label: { + Image(systemName: "square.and.arrow.up") + .foregroundColor(.mealMoodTextPrimary) + } + .accessibilityLabel(Text("share_week_button")) + } if viewModel.canEditCurrentWeek { Button { viewModel.autoComplete(plan: plan, dishes: dishes, tags: tags, settings: settings, allPlans: weekPlans) @@ -330,7 +339,10 @@ struct HomeView: View { } let filledCount = plan.slotList.filter { $0.dishId != nil || $0.isEatingOut }.count - if filledCount > 0 && !isExportCalloutDismissed(plan) { + let emptyCount = plan.slotList.filter { $0.dishId == nil && !$0.isEatingOut }.count + // Only surface the export banner once the week is actually + // complete (no empty slots) — and let the user dismiss it. + if filledCount > 0 && emptyCount == 0 && !isExportCalloutDismissed(plan) { exportCallout(plan: plan, settings: settings) } @@ -338,7 +350,6 @@ struct HomeView: View { weekRatingRow(plan: plan) } - let emptyCount = plan.slotList.filter { $0.dishId == nil && !$0.isEatingOut }.count if viewModel.canEditCurrentWeek && !dishes.isEmpty && emptyCount > 0 { autoAssignBanner(emptyCount: emptyCount, plan: plan, settings: settings) } @@ -1013,6 +1024,17 @@ struct HomeView: View { ) } + /// Entry point for the toolbar share action: premium shares directly, free + /// is routed to the paywall (same gating as the export banner). + private func requestWeekShare(plan: WeekPlan, settings: AppSettings) { + if settings.isPremium { + startShareFlow(plan: plan, settings: settings) + } else { + paywallSource = "share_week" + showPremiumFromExport = true + } + } + private func startShareFlow(plan: WeekPlan, settings: AppSettings) { if settings.weekExportStyle == nil { pendingExportPlan = plan