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>
This commit is contained in:
Robin Kutesa
2026-06-18 22:17:41 +03:00
parent e6ab2242f0
commit 3388eb7944
9 changed files with 720 additions and 0 deletions

View File

@@ -23,6 +23,7 @@ struct SignalFeedView: View {
@Query private var cachedStories: [CachedStory]
@Query private var cachedArticles: [CachedArticle]
@State private var showFeeds = false
@State private var showSettings = false
/// Stories that have full article content cached eligible for the green dot.
private var cachedStoryIds: Set<String> { Set(cachedArticles.map(\.storyId)) }
@@ -64,6 +65,9 @@ struct SignalFeedView: View {
.sheet(isPresented: $showFeeds) {
FeedManagerView()
}
.sheet(isPresented: $showSettings) {
SettingsView()
}
}
.preferredColorScheme(.dark)
.onChange(of: store.stories) { _, newValue in
@@ -86,6 +90,14 @@ struct SignalFeedView: View {
.foregroundStyle(Color(hex: "888888"))
.frame(width: 44, height: 44)
}
Button {
showSettings = true
} label: {
Image(systemName: "gearshape")
.font(.system(size: 17, weight: .semibold))
.foregroundStyle(Color(hex: "888888"))
.frame(width: 44, height: 44)
}
}
.padding(.horizontal, 16)
.padding(.top, 8)