pageta-native/Sources/Core/URLRouter.swift
Till JS a62bfe2297 π-5: Universal Links + pageta:// scheme → Reader-Sheet
Phase 2 startet. Server-AASA + Entitlements waren schon live, jetzt
das Native-Side-Routing. Tap auf pageta.com/article/X in Safari/Mail
öffnet die App und präsentiert den Reader als Sheet (kontextfrei —
bleibt egal in welchem Tab der User war).

- Sources/Core/URLRouter.swift: `PagetaRoute.parse(_:)` als pure
  function. Akzeptiert https://pageta.com/article/{id} (AASA-matched)
  und pageta://article/{id} (eigenes Scheme, für ShareExt-π-6 und
  Widget-π-7 vorbereitet). Bewusst ohne pageta.mana.how — Lead-Domain
  ist pageta.com seit 2026-05-18.
- PagetaNativeApp:
  - `.onContinueUserActivity(NSUserActivityTypeBrowsingWeb)` für
    Universal Links
  - `.onOpenURL` für pageta:// scheme
  - `.sheet(item: $presentedRoute)` → NavigationStack { ArticleDetailView }
    mit „Fertig"-Cancel-Button. Sheet-State über separate PresentedRoute-
    Enum (Identifiable-Wrapper um PagetaRoute, damit der Pure-Type
    SwiftUI-frei bleibt).
  - OSLog-Trace mit URL-Quelle (universal-link | scheme) + matched ID.

7 neue URL-Tests (20/20 total grün): Pageta-com-Match, Scheme-Match,
Case-Insensitive, Reject pageta.mana.how (Drift-Guard), Reject
foreign host, Reject empty id, Reject unknown path.

Real-Device-Test braucht Apple-Dev-Portal-Capability "Associated
Domains" + Re-Provisioning — Simulator macht Universal Links nur
eingeschränkt mit. pageta:// scheme funktioniert auch im Simulator
direkt (xcrun simctl openurl).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 16:46:29 +02:00

41 lines
1.4 KiB
Swift

import Foundation
/// Pure URL-Parser für die App-Routing-Entscheidungen.
///
/// Akzeptierte URL-Formen:
/// - `https://pageta.com/article/{id}` (Universal Link, AASA-matched)
/// - `pageta://article/{id}` (eigenes URL-Scheme, ShareExt + Widget-Deep-Links)
///
/// Andere Hosts (z.B. pageta.mana.how) werden bewusst NICHT geroutet —
/// `pageta.com` ist seit 2026-05-18 die Lead-Domain. Wenn die alte
/// mana.how-Domain mal in Universal-Links auftaucht, hier ergänzen.
enum PagetaRoute: Equatable, Sendable {
case article(id: String)
static func parse(_ url: URL) -> PagetaRoute? {
guard let scheme = url.scheme?.lowercased() else { return nil }
switch scheme {
case "https":
guard url.host?.lowercased() == "pageta.com" else { return nil }
return parsePath(url.pathComponents.dropFirst())
case "pageta":
// Bei custom-scheme ist `host` der erste Pfad-Bestandteil:
// `pageta://article/abc` → host="article", path="/abc"
var parts: [String] = []
if let host = url.host { parts.append(host) }
parts.append(contentsOf: url.pathComponents.filter { $0 != "/" })
return parsePath(parts[...])
default:
return nil
}
}
private static func parsePath(_ parts: ArraySlice<String>) -> PagetaRoute? {
let segments = Array(parts)
guard segments.count >= 2, segments[0] == "article" else { return nil }
let id = segments[1]
guard !id.isEmpty else { return nil }
return .article(id: id)
}
}