Integrazione YouTube Live: OAuth squadra, canale piattaforma Light e UI.

Collegamento da Dettagli squadra e admin per il refresh token Match Live TV; API e app mobile allineate ai piani Light/Full.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-02 19:36:56 +02:00
parent 1a84d6ae42
commit 994c1e3c09
28 changed files with 557 additions and 28 deletions

View File

@@ -76,25 +76,52 @@ class _StepTransmissionState extends ConsumerState<StepTransmission> {
void _onYoutubeTap(Team? team) {
if (team == null) return;
if (team.canUseYoutube && team.youtubeConnected) {
if (team.isYoutubeReady) {
setState(() => _platform = 'youtube');
return;
}
if (team.canUseYoutube && !team.youtubeConnected) {
if (team.canUseYoutube && team.youtubeMode == 'team') {
showPremiumRequiredDialog(
context,
message: 'Collega il canale YouTube dalla dashboard sul sito, poi seleziona YouTube qui.',
billingUrl: team.billingUrl,
message: 'Collega il canale YouTube dalla pagina Dettagli squadra sul sito, poi seleziona YouTube qui.',
billingUrl: team.staffManageUrl ?? team.billingUrl,
);
return;
}
if (team.canUseYoutube && team.youtubeMode == 'matchlivetv_light') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'YouTube sul canale Match Live TV non è ancora attivo. Riprova più tardi o usa Match Live TV.',
),
),
);
return;
}
showPremiumRequiredDialog(
context,
message: 'YouTube Live è incluso nel piano Premium Full.',
message: 'YouTube Live richiede Premium Light o Full.',
billingUrl: team.billingUrl,
);
}
String _youtubeSubtitle(Team? team) {
if (team == null || !team.canUseYoutube) {
return 'Premium Light o Full';
}
if (team.isYoutubeReady) {
final label = team.youtubeChannelTitle;
if (team.youtubeUsesPlatformChannel) {
return label != null ? 'Canale $label' : 'Canale Match Live TV';
}
return label != null ? 'Canale $label' : 'Canale collegato';
}
if (team.youtubeMode == 'matchlivetv_light') {
return 'Canale Match Live TV (in attivazione)';
}
return 'Collega canale sul sito';
}
void _onExternalPremiumTap(String platform, Team? team) {
showPremiumRequiredDialog(
context,
@@ -112,7 +139,7 @@ class _StepTransmissionState extends ConsumerState<StepTransmission> {
loading: () => const Center(child: CircularProgressIndicator(color: AppTheme.primaryRed)),
error: (_, __) => const Center(child: Text('Errore caricamento squadra')),
data: (team) {
final youtubeSelectable = team != null && team.canUseYoutube && team.youtubeConnected;
final youtubeSelectable = team != null && team.isYoutubeReady;
return SingleChildScrollView(
padding: ScreenInsets.contentPadding(context, horizontal: 20, vertical: 12),
@@ -147,14 +174,10 @@ class _StepTransmissionState extends ConsumerState<StepTransmission> {
const SizedBox(height: 8),
_PlatformCard(
title: 'YouTube Live',
subtitle: team?.canUseYoutube == true
? (team!.youtubeConnected
? 'Canale collegato'
: 'Collega canale sul sito')
: 'Premium Full — collegamento canale',
subtitle: _youtubeSubtitle(team),
selected: _platform == 'youtube',
enabled: youtubeSelectable,
badge: team?.canUseYoutube == true ? null : 'Full',
badge: team?.canUseYoutube == true ? null : 'Premium',
onTap: () => _onYoutubeTap(team),
),
const SizedBox(height: 8),

View File

@@ -5,6 +5,9 @@ class Team {
required this.sport,
this.logoUrl,
this.youtubeConnected = false,
this.youtubeSelectable = false,
this.youtubeChannelTitle,
this.youtubeUsesPlatformChannel = false,
this.planSlug = 'free',
this.planName = 'Free',
this.premiumActive = false,
@@ -36,6 +39,9 @@ class Team {
final bool canStream;
final String? logoUrl;
final bool youtubeConnected;
final bool youtubeSelectable;
final String? youtubeChannelTitle;
final bool youtubeUsesPlatformChannel;
final String planSlug;
final String planName;
final bool premiumActive;
@@ -55,7 +61,9 @@ class Team {
final bool youtubeEnabled;
final String? youtubeMode;
bool get canUseYoutube => premiumFull && youtubeEnabled;
bool get canUseYoutube => youtubeEnabled && (premiumFull || youtubeMode == 'matchlivetv_light');
bool get isYoutubeReady => youtubeSelectable;
bool get canUseRecordings => recordingsEnabled;
bool get canDownloadOnPhone => phoneDownloadEnabled;
@@ -76,6 +84,9 @@ class Team {
canStream: json['can_stream'] as bool? ?? true,
logoUrl: json['logo_url'] as String?,
youtubeConnected: json['youtube_connected'] as bool? ?? false,
youtubeSelectable: json['youtube_selectable'] as bool? ?? false,
youtubeChannelTitle: json['youtube_channel_title'] as String?,
youtubeUsesPlatformChannel: json['youtube_uses_platform_channel'] as bool? ?? false,
planSlug: json['plan_slug'] as String? ?? 'free',
planName: json['plan_name'] as String? ?? 'Free',
premiumActive: json['premium_active'] as bool? ?? false,