Files
jarvis/Jarvis/JarvisApp.swift
Robin Kutesa 3388eb7944 Add notifications: morning/evening briefings + breaking alerts
- Settings hub (gear → SettingsView) hosting Notifications and Connectivity
  (Connectivity previously had no entry point).
- NotificationsView: permission flow, breaking/new-story alerts with a
  min-signal threshold, morning & evening briefings with time pickers, and a
  weather toggle + location, plus a "send test briefing" action.
- NotificationManager: schedules daily briefings, builds "Jarvis" content
  (weather + top signal stories), fires breaking alerts off WebSocket
  story.created events, and refreshes via a BGAppRefresh task.
- WeatherService: Open-Meteo geocoding + daily forecast (no API key/entitlement).
- AppDelegate registers the background-refresh handler at launch; Info.plist
  gains UIBackgroundModes + BGTaskSchedulerPermittedIdentifiers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 22:17:41 +03:00

57 lines
2.0 KiB
Swift

// JarvisApp.swift
import SwiftUI
import SwiftData
import UIKit
import BackgroundTasks
final class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
// Register the briefing background-refresh handler before launch completes.
BGTaskScheduler.shared.register(forTaskWithIdentifier: jarvisBriefingRefreshID, using: nil) { task in
Task { @MainActor in
await NotificationManager.shared.applySettings()
NotificationManager.shared.scheduleBackgroundRefresh()
task.setTaskCompleted(success: true)
}
}
return true
}
}
@main
struct JarvisApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
@StateObject private var settings = ServerSettings.shared
@StateObject private var store = StoryStore.shared
@StateObject private var ws = WebSocketManager.shared
@StateObject private var connectivity = ConnectivitySettings.shared
@StateObject private var connManager = ConnectivityManager.shared
@StateObject private var notifications = NotificationManager.shared
var body: some Scene {
WindowGroup {
Group {
if settings.isConfigured {
RootTabView()
} else {
OnboardingView()
}
}
.environmentObject(settings)
.environmentObject(store)
.environmentObject(ws)
.environmentObject(connectivity)
.environmentObject(connManager)
.environmentObject(notifications)
.task {
connManager.start()
await connManager.resolveAndActivate()
await notifications.bootstrap()
}
}
.modelContainer(for: [CachedStory.self, CachedArticle.self])
}
}