// // AvailabilityView.swift // Poche // // Author: Simon-Pierre Boucher // Contact: contact@spboucher.ai // import SwiftUI import FoundationModels /// Unavailability screens. Careful, apologetic, never guilt-tripping, /// and never offering a replacement LLM (CLAUDE.md §2). struct AvailabilityView: View { let reason: SystemLanguageModel.Availability.UnavailableReason let retry: () -> Void var body: some View { ZStack { AppBackground() VStack(spacing: Theme.spacingLarge) { Spacer() ZStack { Circle() .fill(Theme.accentGradient.opacity(0.14)) .frame(width: 108, height: 108) Image(systemName: symbolName) .font(.system(size: 44, weight: .light)) .foregroundStyle(Theme.accentGradient) } Text(title) .font(.title2.weight(.bold)) .multilineTextAlignment(.center) .padding(.horizontal, Theme.spacingLarge) Text(message) .font(.body) .foregroundStyle(.secondary) .multilineTextAlignment(.center) .padding(.horizontal, Theme.spacingLarge + 8) actionButton Spacer() HStack(spacing: Theme.spacingSmall) { BrandMark(size: 20) Text("Poche — ton agent, sur ton appareil") .font(.footnote) .foregroundStyle(.secondary) } .padding(.bottom, Theme.spacingLarge) } } .fontDesign(.rounded) } private var symbolName: String { switch reason { case .deviceNotEligible: "iphone.slash" case .appleIntelligenceNotEnabled: "gearshape" case .modelNotReady: "arrow.down.circle" @unknown default: "questionmark.circle" } } private var title: String { switch reason { case .deviceNotEligible: "Cet iPhone ne peut pas faire tourner Poche" case .appleIntelligenceNotEnabled: "Apple Intelligence est désactivé" case .modelNotReady: "Le modèle se prépare" @unknown default: "L’intelligence sur l’appareil est indisponible" } } private var message: String { switch reason { case .deviceNotEligible: "Poche fonctionne entièrement sur l’appareil, sans serveur. Cela demande la puce A17 Pro ou plus récente (iPhone 15 Pro et suivants). Sur cet iPhone, le modèle n’est pas disponible — et Poche ne le remplacera jamais par un service en ligne." case .appleIntelligenceNotEnabled: "Active Apple Intelligence dans Réglages pour que Poche puisse fonctionner, entièrement sur ton iPhone." case .modelNotReady: "Le modèle est en cours de téléchargement ou de préparation par le système. Cela peut prendre quelques minutes, notamment après une mise à jour ou en mode économie d’énergie." @unknown default: "Le modèle sur l’appareil n’est pas disponible pour le moment. Réessaie dans un instant." } } @ViewBuilder private var actionButton: some View { switch reason { case .deviceNotEligible: EmptyView() case .appleIntelligenceNotEnabled: Button { if let url = URL(string: UIApplication.openSettingsURLString) { UIApplication.shared.open(url) } } label: { Text("Ouvrir Réglages") .font(.subheadline.weight(.semibold)) .foregroundStyle(.white) .padding(.horizontal, Theme.spacingLarge) .padding(.vertical, Theme.spacingMedium - 2) .background(Theme.accentGradient) .clipShape(Capsule()) } .buttonStyle(.plain) default: Button(action: retry) { Text("Réessayer") .font(.subheadline.weight(.semibold)) .foregroundStyle(.white) .padding(.horizontal, Theme.spacingLarge) .padding(.vertical, Theme.spacingMedium - 2) .background(Theme.accentGradient) .clipShape(Capsule()) } .buttonStyle(.plain) } } }