Files
Vorrania/ios/Sources/VorraniaApp.swift
Scarriffle 62a1e7c469 iOS-App heisst jetzt Vorrania
Web, Backend, Deploy und Docs trugen den neuen Namen bereits - iOS war der
letzte Rest. Umgestellt sind Projekt- und Targetname, die Bundle-ID
(com.scarriffle.vorrania), das URL-Schema, die Schnellaktionen, der
Keychain-Service und die Anleitungen. ProjectGoodApp.swift heisst
VorraniaApp.swift.

Zwei Nebenwirkungen, die sich nicht vermeiden lassen: Die neue Bundle-ID
macht die App fuer iOS zu einer anderen App. Die alte bleibt auf dem
Home-Bildschirm liegen und muss von Hand weg, und das Token im Keychain
haengt an der alten Bundle-ID - die neue kommt nicht daran, also einmal neu
anmelden. Wer sich Kurzbefehle mit projectgood://checkin angelegt hat, traegt
dort vorrania://checkin ein.

Das Xcode-Projekt ist ab jetzt eingecheckt statt ignoriert, damit man ohne
XcodeGen bauen kann; nur xcuserdata und DerivedData bleiben draussen.
Gegengeprueft mit einem Simulator-Build: Bundle-ID, Anzeigename, Schema und
Schnellaktionen stehen im fertigen Bundle richtig drin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 17:35:45 +02:00

76 lines
2.8 KiB
Swift

import SwiftUI
import UIKit
/// Zielbildschirm, der über Home-Screen-Shortcut oder URL angesprungen wird.
enum Route: String {
case checkin
case checkout
}
final class Router: ObservableObject {
@Published var route: Route?
func handle(shortcut type: String) {
if type.hasSuffix("checkin") { route = .checkin }
if type.hasSuffix("checkout") { route = .checkout }
}
/// vorrania://checkin bzw. vorrania://checkout
func handle(url: URL) {
guard url.scheme == "vorrania" else { return }
let target = (url.host ?? url.path.replacingOccurrences(of: "/", with: "")).lowercased()
if let route = Route(rawValue: target) { self.route = route }
}
}
@main
struct VorraniaApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
@StateObject private var session = Session.shared
@StateObject private var router = Router()
@StateObject private var display = DisplaySettings.shared
var body: some Scene {
WindowGroup {
RootView()
.environmentObject(session)
.environmentObject(router)
.environmentObject(display)
.onOpenURL { router.handle(url: $0) }
.onAppear {
if let type = AppDelegate.pendingShortcut {
router.handle(shortcut: type)
AppDelegate.pendingShortcut = nil
}
}
.onReceive(NotificationCenter.default.publisher(for: AppDelegate.shortcutNotification)) { note in
if let type = note.object as? String { router.handle(shortcut: type) }
}
}
}
}
/// Nimmt Home-Screen-Quick-Actions entgegen (auch beim Kaltstart).
final class AppDelegate: NSObject, UIApplicationDelegate {
static let shortcutNotification = Notification.Name("VorraniaShortcut")
static var pendingShortcut: String?
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
if let item = launchOptions?[.shortcutItem] as? UIApplicationShortcutItem {
AppDelegate.pendingShortcut = item.type
}
return true
}
// Bewusst die Variante mit Completion-Handler: Bei der async-Fassung muesste
// das nicht-Sendable UIApplicationShortcutItem ueber eine Actor-Grenze
// gereicht werden (Warnung heute, Fehler im Swift-6-Sprachmodus).
func application(_ application: UIApplication,
performActionFor shortcutItem: UIApplicationShortcutItem,
completionHandler: @escaping (Bool) -> Void) {
NotificationCenter.default.post(name: AppDelegate.shortcutNotification, object: shortcutItem.type)
completionHandler(true)
}
}