- 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>
60 lines
1.8 KiB
Swift
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]
|
|
}
|
|
}
|