Files
MatchLiveTv/native/ios/MatchLiveTv/UI/Navigation/AppNavHost.swift
T
Emiliano FrascaroandCursor 45bdda7c95 Semplifica la home partite a un solo CTA e sistema la nav iOS.
Rimuove il pulsante ridondante «Partita programmata», migliora il padding dei bottoni e fa di splash/login/matches root vere così non compare più il chevron indietro spurio.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-08 18:54:44 +02:00

140 lines
4.8 KiB
Swift

import SwiftUI
struct AppNavHost: View {
private enum RootScreen {
case splash
case login
case matches
}
@StateObject private var container = AppContainer()
@State private var root: RootScreen = .splash
/// Solo destinazioni sopra la root (account, recupero password).
@State private var path: [Routes] = []
@State private var wizardRoute: WizardRoute?
@State private var broadcastRoute: BroadcastRoute?
/// Incrementato al ritorno da wizard/broadcast per ricaricare l'hub partite.
@State private var matchesRefreshToken = 0
@State private var languageTick = 0
/// Locale SwiftUI (DatePicker, ecc.) aggiornata al cambio lingua senza resettare la NavigationStack.
private var appLocale: Locale {
_ = languageTick
return AppLanguage.locale
}
var body: some View {
NavigationStack(path: $path) {
rootContent
.navigationDestination(for: Routes.self) { route in
switch route {
case .forgotPassword:
ForgotPasswordScreen(
container: container,
onBack: { path.removeLast() }
)
case .account:
AccountScreen(
container: container,
onBack: { path.removeLast() },
onLoggedOut: {
path = []
root = .login
}
)
case .splash, .login, .matches, .setup, .broadcast:
EmptyView()
}
}
}
.environment(\.locale, appLocale)
.onReceive(NotificationCenter.default.publisher(for: .appLanguageDidChange)) { _ in
languageTick += 1
}
.lockPortraitOrientation()
.fullScreenCover(item: $wizardRoute) { route in
WizardShellScreen(
container: container,
matchId: route.matchId,
step: route.step,
onClose: {
container.wizardSession.reset()
wizardRoute = nil
matchesRefreshToken += 1
},
onStartLive: { sessionId in
wizardRoute = nil
broadcastRoute = BroadcastRoute(sessionId: sessionId)
}
)
.lockPortraitOrientation()
}
.fullScreenCover(item: $broadcastRoute, onDismiss: {
Task { @MainActor in
container.sessionCable.disconnect()
await container.broadcastCoordinator.forceStopBroadcast()
}
AppOrientation.lockPortrait()
matchesRefreshToken += 1
}) { route in
BroadcastScreen(container: container, sessionId: route.sessionId) {
Task { @MainActor in
await container.broadcastCoordinator.stopBroadcast(sessionId: route.sessionId)
}
AppOrientation.lockPortrait()
container.wizardSession.reset()
broadcastRoute = nil
path = []
root = .matches
}
.keepScreenOn()
}
.onChange(of: broadcastRoute?.sessionId) { sessionId in
if sessionId == nil {
AppOrientation.lockPortrait()
}
}
.environmentObject(container)
}
@ViewBuilder
private var rootContent: some View {
switch root {
case .splash:
SplashScreen(
container: container,
onAuthenticated: {
path = []
root = .matches
},
onUnauthenticated: {
path = []
root = .login
}
)
case .login:
LoginScreen(
container: container,
onLoggedIn: {
path = []
root = .matches
},
onForgotPassword: { path.append(.forgotPassword) }
)
case .matches:
MatchesScreen(
container: container,
refreshToken: matchesRefreshToken,
onOpenSetup: { matchId in
wizardRoute = WizardRoute(matchId: matchId, step: 1)
},
onOpenBroadcast: { sessionId in
broadcastRoute = BroadcastRoute(sessionId: sessionId)
},
onOpenAccount: { path.append(.account) }
)
.lockPortraitOrientation()
}
}
}