Files
ios-gitea-prs/GiteaPR/AppDelegate.swift
T
Hermes bae531f850
Build iOS App / Build .ipa and publish source (push) Successful in 31s
Add push-equivalent notifications via background polling; bump to 3.6
Sideloaded apps can't use APNs (no push entitlement without Apple signing),
so deliver notifications via an iOS BGAppRefreshTask that polls the monitored
repos every ~15 min and fires local notifications (no Apple push needed):
- new PRs that appear in the open set
- CI status changes on existing PRs

Persistence: NotificationState tracks announced PR ids + last-known CI status
so we only fire on actual changes, not every poll. AppDelegate registers the
background task and reschedules the next one. Info.plist gets UIBackgroundModes
fetch + the BGTask identifier. Settings gains a Notifications toggle; also
poll after a foreground inbox load so state seeds and changes are caught
promptly. Bump to 3.6.
2026-08-24 08:18:29 +00:00

51 lines
1.7 KiB
Swift

import UIKit
import BackgroundTasks
/// App delegate that schedules the background refresh task which drives the
/// push-equivalent notifications (polling the monitored repos).
///
/// iOS runs BGAppRefreshTask opportunistically (~every 15 min at best, often
/// slower), and only when the app has been used recently and isn't force-quit.
final class AppDelegate: NSObject, UIApplicationDelegate {
static let taskIdentifier = "com.bueso.giteapr.refresh"
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
registerBackgroundTask()
return true
}
private func registerBackgroundTask() {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: Self.taskIdentifier,
using: nil
) { task in
// Handle the background refresh.
self.handle(task)
}
}
private func handle(_ task: BGTask) {
// Reschedule the next refresh so the chain continues.
scheduleNextRefresh()
let pollTask = Task { @MainActor in
await NotificationService.shared.poll()
}
task.expirationHandler = {
pollTask.cancel()
}
Task {
await pollTask.value
task.setTaskCompleted(success: true)
}
}
/// Schedule the next background refresh (~15 min from now, earliest).
func scheduleNextRefresh() {
let request = BGAppRefreshTaskRequest(identifier: Self.taskIdentifier)
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
try? BGTaskScheduler.shared.submit(request)
}
}