Files
MatchLiveTv/native/ios/MatchLiveTv/UI/Wizard/StepTransmissionScreen.swift
Emiliano Frascaro 585332e32e Aggiunge app iOS nativa con parità multi-sport e test unitari.
Porting SwiftUI da Android (auth, hub, wizard, broadcast RTMP, overlay, scoring board-aware), reload hub al ritorno da diretta, decodifica score tollerante e documentazione allineata.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 21:37:32 +02:00

148 lines
5.2 KiB
Swift

import SwiftUI
struct StepTransmissionScreen: View {
@ObservedObject var container: AppContainer
let match: Match
let onBack: () -> Void
let onNext: () -> Void
let onError: (String) -> Void
@State private var team: Team?
@State private var platform = "matchlivetv"
@State private var privacy = "public"
@State private var creating = false
private var youtubeReady: Bool {
team?.isYoutubeReady == true
}
private var youtubeSubtitle: String {
guard let team else { return "Canale in attivazione" }
if !team.canUseYoutube { return "Premium Light o Full" }
if !team.isYoutubeReady { return "Canale in attivazione" }
return team.youtubeDestinationLabel
}
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 0) {
if let plan = team?.planName {
Text("Piano \(plan)")
.font(MatchTypography.bodyMedium)
.foregroundStyle(MatchColors.textSecondary)
.padding(.bottom, 12)
}
Text("Piattaforma")
.font(MatchTypography.headlineMedium)
WizardPlatformCard(
title: "Match Live TV",
subtitle: "Diretta sul nostro sito (incluso)",
selected: platform == "matchlivetv",
onClick: { platform = "matchlivetv" }
)
.padding(.top, 12)
WizardPlatformCard(
title: "YouTube Live",
subtitle: youtubeSubtitle,
selected: platform == "youtube",
enabled: youtubeReady,
badge: team?.canUseYoutube == false ? "Premium" : nil,
onClick: selectYoutube
)
.padding(.top, 8)
Text("Visibilità")
.font(MatchTypography.headlineMedium)
.padding(.top, 24)
HStack(spacing: 8) {
WizardChoiceButton(
label: "PUBBLICO",
selected: privacy == "public",
action: { privacy = "public" }
)
.frame(maxWidth: .infinity)
WizardChoiceButton(
label: "NON IN ELENCO",
selected: privacy == "unlisted",
action: { privacy = "unlisted" }
)
.frame(maxWidth: .infinity)
}
.padding(.top, 12)
Text(visibilityDescription)
.font(MatchTypography.bodyMedium)
.foregroundStyle(MatchColors.textSecondary)
.fixedSize(horizontal: false, vertical: true)
.padding(.top, 8)
Text("La partita resta sempre visibile nel backend della squadra per tutta la durata dell'abbonamento.")
.font(MatchTypography.bodyMedium)
.foregroundStyle(MatchColors.textSecondary)
.fixedSize(horizontal: false, vertical: true)
.padding(.top, 6)
WizardFooterButtons(
onBack: onBack,
forwardLabel: "AVANTI >",
forwardLoading: creating,
onForward: createSessionAndContinue
)
.padding(.top, 32)
}
.padding(.horizontal, 20)
.padding(.top, 12)
.padding(.bottom, 32)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.task {
if let cached = container.wizardSession.team {
team = cached
} else {
team = await container.matchRepository.fetchTeam(teamId: match.teamId)
container.wizardSession.team = team
}
}
}
private var visibilityDescription: String {
if privacy == "public" {
return "Compare nell'elenco dirette su MatchLiveTV.it, nelle ricerche e sul canale YouTube (se selezionato)."
}
return "Non compare negli elenchi pubblici né nelle ricerche. Solo chi ha il link può guardare."
}
private func selectYoutube() {
if youtubeReady {
platform = "youtube"
} else {
onError("YouTube non disponibile per questa squadra")
}
}
private func createSessionAndContinue() {
creating = true
Task {
do {
let session = try await container.sessionRepository.createSession(
matchId: match.id,
platform: platform,
privacyStatus: privacy,
youtubeChannel: platform == "youtube" ? team?.effectiveYoutubeChannel : nil
)
container.wizardSession.session = session
onNext()
} catch {
if let message = UserFacingError.message(for: error) {
onError(message)
}
}
creating = false
}
}
}