Files
bible/Bible-Week/AppRouter.swift
Matheus A Silveira 80185726af Adiciona Plano Bíblia em 180 Dias com lembrete diário e ícone do app
- Leitor bíblico consumindo a API NBV (bible.falehandix.com.br): lista de
  livros por testamento e leitura de capítulos
- Plano de 180 dias com três trilhas diárias (História, Sabedoria e
  Profetas, Novo Testamento) geradas deterministicamente sobre o cânon
  embutido (1.189 capítulos, cobertura testada)
- Lembrete diário via notificação local recorrente (UNCalendarNotificationTrigger,
  identificador fixo, sem duplicatas), com pedido de autorização em contexto,
  configurações de horário/som, e deep link da notificação para a Leitura de Hoje
- Estado do plano em SwiftData: progresso, pausa/retomada, reinício e
  conclusão preservando preferências do lembrete
- 15 testes unitários (Testing) e 2 testes de UI (XCUIAutomation)
- Ícone do app a partir do logo biblia.png

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-04 18:54:48 -03:00

60 lines
1.8 KiB
Swift

//
// AppRouter.swift
// Bible-Week
//
// Navegação global do app e tratamento do toque em notificações:
// tocar no lembrete abre diretamente o Plano de Leitura Leitura de Hoje.
//
import Foundation
import Observation
import UserNotifications
@MainActor
@Observable
final class AppRouter {
enum Tab: Hashable {
case bible
case plan
}
var selectedTab: Tab = .bible
/// A tela principal do plano já é a "Leitura de Hoje".
func openTodayReading() {
selectedTab = .plan
}
}
/// Delegate do UNUserNotificationCenter. Precisa ser registrado no launch
/// (init do App) para capturar o toque na notificação mesmo com o app fechado.
final class NotificationCoordinator: NSObject, UNUserNotificationCenterDelegate {
private let router: AppRouter
init(router: AppRouter) {
self.router = router
}
/// Usuário tocou na notificação (app fechado, em background ou aberto).
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse
) async {
let userInfo = response.notification.request.content.userInfo
let destination = userInfo[NotificationUserInfo.destinationKey] as? String
guard destination == NotificationUserInfo.destinationReadingPlan else { return }
await MainActor.run {
router.openTodayReading()
}
}
/// Notificação chegou com o app em foreground: apresentação normal,
/// sem navegar automaticamente nem interromper uma leitura em andamento.
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification
) async -> UNNotificationPresentationOptions {
[.banner, .sound]
}
}