Initial commit: nightly iOS app + Supabase backend
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>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
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")
|
||||
}
|
||||
Reference in New Issue
Block a user