Files
FamilyMealPlanner/MealMood/Views/Home/SocialShareSheet.swift
T
alexandrev-tibco 110807d239 1.0.5: Eating out slots, rule violations panel, Crashlytics, search bar fix
- Eating out: tap any empty slot → "Mark as eating out"; shows teal indicator,
  skipped by auto-assign, counts as complete, tap again to unmark
- Rule violations panel: access via wand long-press context menu when conflicts exist;
  shows all isRuleOverridden slots with Fix (clear) or Ignore (acknowledge) actions
- Firebase Crashlytics integrated: CrashlyticsService + dSYM upload build phase,
  isPremium property tracked per session
- PremiumSyncService: extracted premium state machine, StoreKit Transaction.updates
  listener, isPremium no longer synced via iCloud to avoid stale state
- StoreManager: analytics on purchase/restore, bundle ID fallback for product ID lookup
- Search bar contrast bug fixed: TextField now has explicit foreground color for dark mode
- WelcomeStepView: redesigned onboarding welcome screen with week preview
- Version bump: 1.0.5 build 22

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 09:48:20 +02:00

139 lines
5.0 KiB
Swift

import SwiftUI
import UIKit
struct SocialShareSheet: View {
let imageURL: URL
@State private var showSystemShare = false
@State private var showCopiedToast = false
@Environment(\.dismiss) private var dismiss
private var image: UIImage? { UIImage(contentsOfFile: imageURL.path) }
var body: some View {
NavigationStack {
VStack(spacing: 24) {
if let img = image {
Image(uiImage: img)
.resizable()
.scaledToFit()
.frame(maxHeight: 220)
.clipShape(RoundedRectangle(cornerRadius: 14))
.shadow(color: .black.opacity(0.12), radius: 14, x: 0, y: 6)
}
VStack(spacing: 10) {
if canOpenInstagram {
shareOptionRow(
title: "Instagram Stories",
subtitle: String(localized: "share_instagram_subtitle"),
icon: "camera.fill",
color: Color(red: 0.80, green: 0.18, blue: 0.75),
action: shareToInstagramStories
)
}
shareOptionRow(
title: String(localized: "share_copy_image"),
subtitle: String(localized: "share_copy_subtitle"),
icon: "doc.on.doc.fill",
color: .mealMoodCoral,
action: copyImage
)
shareOptionRow(
title: String(localized: "share_more_options"),
subtitle: String(localized: "share_more_subtitle"),
icon: "square.and.arrow.up.fill",
color: Color(hex: "#4A6CF7"),
action: { showSystemShare = true }
)
}
Spacer()
}
.padding(20)
.navigationTitle(String(localized: "share_export_sheet_title"))
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button(String(localized: "dish_cancel")) { dismiss() }
}
}
}
.toast(isShowing: $showCopiedToast, message: String(localized: "share_copied"))
.sheet(isPresented: $showSystemShare) {
SystemShareSheet(activityItems: [imageURL])
}
}
// MARK: - Row view
private func shareOptionRow(title: String, subtitle: String, icon: String, color: Color, action: @escaping () -> Void) -> some View {
Button(action: action) {
HStack(spacing: 14) {
Image(systemName: icon)
.font(.system(size: 18, weight: .semibold))
.foregroundColor(.white)
.frame(width: 44, height: 44)
.background(color)
.clipShape(RoundedRectangle(cornerRadius: 12))
VStack(alignment: .leading, spacing: 2) {
Text(title)
.font(.mealMoodBodyBold)
.foregroundColor(.mealMoodTextPrimary)
Text(subtitle)
.font(.mealMoodCaption)
.foregroundColor(.mealMoodTextSecondary)
}
Spacer()
Image(systemName: "chevron.right")
.font(.system(size: 12, weight: .semibold))
.foregroundColor(.mealMoodTextSecondary)
}
.padding(12)
.background(Color.mealMoodSurface)
.clipShape(RoundedRectangle(cornerRadius: 14))
}
.buttonStyle(.plain)
}
// MARK: - Actions
private var canOpenInstagram: Bool {
guard let url = URL(string: "instagram-stories://share") else { return false }
return UIApplication.shared.canOpenURL(url)
}
private func shareToInstagramStories() {
guard let img = image,
let data = img.pngData(),
let url = URL(string: "instagram-stories://share?source_application=com.alexandrevazquez.mealmood")
else { return }
UIPasteboard.general.setData(data, forPasteboardType: "com.instagram.sharedSticker.backgroundImage")
UIApplication.shared.open(url)
dismiss()
}
private func copyImage() {
guard let img = image else { return }
UIPasteboard.general.image = img
showCopiedToast = true
HapticManager.shared.notification(type: .success)
}
}
// MARK: - System share wrapper (private)
private struct SystemShareSheet: UIViewControllerRepresentable {
let activityItems: [Any]
func makeUIViewController(context: Context) -> UIActivityViewController {
UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
}
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
}