5bc81d5b3b
iOS SwiftUI app with Supabase auth/realtime, Node.js backend, Docker/Supabase self-hosted infrastructure, and APNs scheduler. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
68 lines
2.2 KiB
Swift
68 lines
2.2 KiB
Swift
import SwiftUI
|
||
|
||
@main
|
||
struct NightlyApp: App {
|
||
@StateObject private var appState = AppState()
|
||
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||
|
||
var body: some Scene {
|
||
WindowGroup {
|
||
RootView()
|
||
.environmentObject(appState)
|
||
.preferredColorScheme(.dark)
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - App Delegate
|
||
|
||
class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
|
||
|
||
func application(
|
||
_ application: UIApplication,
|
||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
||
) -> Bool {
|
||
UNUserNotificationCenter.current().delegate = self
|
||
return true
|
||
}
|
||
|
||
// ⚠️ Push Notifications: erfordert bezahlten Apple Developer Account ($99/Jahr)
|
||
// Ohne Developer-Account kann dieser Code nicht getestet werden (nur Simulator ohne Pushs)
|
||
func application(
|
||
_ application: UIApplication,
|
||
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
||
) {
|
||
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
|
||
Task { try? await supabase.savePushToken(token) }
|
||
}
|
||
|
||
func application(
|
||
_ application: UIApplication,
|
||
didFailToRegisterForRemoteNotificationsWithError error: Error
|
||
) {
|
||
print("APNs Registrierung fehlgeschlagen:", error.localizedDescription)
|
||
// Häufige Ursache: kein bezahlter Developer Account
|
||
}
|
||
|
||
func userNotificationCenter(
|
||
_ center: UNUserNotificationCenter,
|
||
willPresent notification: UNNotification,
|
||
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
||
) {
|
||
completionHandler([.banner, .sound, .badge])
|
||
}
|
||
|
||
func userNotificationCenter(
|
||
_ center: UNUserNotificationCenter,
|
||
didReceive response: UNNotificationResponse,
|
||
withCompletionHandler completionHandler: @escaping () -> Void
|
||
) {
|
||
NotificationCenter.default.post(name: .nightlyPingReceived, object: nil)
|
||
completionHandler()
|
||
}
|
||
}
|
||
|
||
extension Notification.Name {
|
||
static let nightlyPingReceived = Notification.Name("nightlyPingReceived")
|
||
}
|