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>
140 lines
4.8 KiB
Swift
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()
|
|
}
|
|
}
|
|
}
|