// // PlanSettingsView.swift // Bible-Week // // Configurações do Plano de 180 Dias: lembrete diário (horário, som), // pausar/continuar e reiniciar. // import SwiftUI import UserNotifications struct PlanSettingsView: View { @Bindable var plan: ReadingPlanState @Environment(\.dismiss) private var dismiss @Environment(\.scenePhase) private var scenePhase @State private var authorizationStatus: UNAuthorizationStatus = .notDetermined @State private var showRestartConfirmation = false var body: some View { NavigationStack { Form { remindersSection planSection legalSection } .navigationTitle("Plano de Leitura") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .confirmationAction) { Button("OK") { dismiss() } } } // Re-verifica a permissão sempre que o app volta ao primeiro plano — // essencial para refletir mudanças feitas nos Ajustes do iPhone. .task(id: scenePhase) { guard scenePhase == .active else { return } authorizationStatus = await ReadingReminderService.authorizationStatus() if authorizationStatus == .authorized, plan.reminderEnabled { await ReadingReminderService.refresh(for: plan) } } .confirmationDialog( "Reiniciar o plano do dia 1? Seu progresso atual será apagado, mas a preferência de lembrete será mantida.", isPresented: $showRestartConfirmation, titleVisibility: .visible ) { Button("Reiniciar plano", role: .destructive) { plan.restart() Task { await ReadingReminderService.refresh(for: plan) } } } } } // MARK: - Lembretes @ViewBuilder private var remindersSection: some View { Section("Lembretes") { if authorizationStatus == .denied { VStack(alignment: .leading, spacing: 8) { Text("Notificações desativadas") .font(.headline) Text("Para receber lembretes de leitura, habilite as notificações nos Ajustes do iPhone.") .font(.caption) .foregroundStyle(.secondary) Button("Abrir Ajustes") { openNotificationSettings() } } .padding(.vertical, 4) } else { Toggle("Lembrete diário", isOn: reminderEnabledBinding) if plan.reminderEnabled { DatePicker( "Horário", selection: reminderTimeBinding, displayedComponents: .hourAndMinute ) Toggle("Som", isOn: soundEnabledBinding) } } } .accessibilityElement(children: .contain) } /// Ligar pede autorização se necessário; desligar cancela o agendamento. private var reminderEnabledBinding: Binding { Binding { plan.reminderEnabled } set: { newValue in if newValue { // Otimista: liga já, para o switch responder ao toque; // reverte se a autorização for negada. plan.reminderEnabled = true Task { let status = await ReadingReminderService.authorizationStatus() var granted = status == .authorized || status == .provisional if status == .notDetermined { granted = (try? await ReadingReminderService.requestAuthorization()) ?? false } if granted { await ReadingReminderService.refresh(for: plan) } else { plan.reminderEnabled = false authorizationStatus = .denied } } } else { plan.reminderEnabled = false ReadingReminderService.cancelDailyReminder() } } } /// Alterar o horário substitui o agendamento anterior (mesmo identificador, /// nunca duplica) e persiste o novo valor. private var reminderTimeBinding: Binding { Binding { Calendar.current.date( bySettingHour: plan.reminderHour, minute: plan.reminderMinute, second: 0, of: .now ) ?? .now } set: { newValue in let components = Calendar.current.dateComponents([.hour, .minute], from: newValue) plan.reminderHour = components.hour ?? 20 plan.reminderMinute = components.minute ?? 0 Task { await ReadingReminderService.refresh(for: plan) } } } private var soundEnabledBinding: Binding { Binding { plan.reminderSoundEnabled } set: { newValue in plan.reminderSoundEnabled = newValue Task { await ReadingReminderService.refresh(for: plan) } } } // MARK: - Legal private var legalSection: some View { Section("Legal") { NavigationLink { LegalDocumentView( title: "Política de Privacidade", htmlFileName: "politicadeprivacidade" ) } label: { Label("Política de Privacidade", systemImage: "hand.raised.fill") } NavigationLink { LegalDocumentView( title: "Termos e Condições", htmlFileName: "termosecondicoes" ) } label: { Label("Termos e Condições", systemImage: "doc.text.fill") } } } // MARK: - Plano private var planSection: some View { Section("Plano") { LabeledContent("Progresso", value: "\(plan.completedDaysCount) de \(PlanSchedule.totalDays) dias") Button(plan.isPaused ? "Continuar plano" : "Pausar plano") { plan.isPaused.toggle() // Pausar remove o agendamento sem apagar a preferência; // continuar restaura automaticamente o horário salvo. Task { await ReadingReminderService.refresh(for: plan) } } Button("Reiniciar plano", role: .destructive) { showRestartConfirmation = true } } } }