Billing upgrade/downgrade, inviti in app e diretta YouTube da mobile.

Upgrade Stripe con addebito immediato; downgrade programmato a fine periodo.
UX billing più sobria con box info; icone piani. API inviti e OAuth YouTube
per staff trasmissione; deep link join; scelta partita programmata o nuova.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-02 22:15:27 +02:00
parent 2cb267f991
commit 566104aff4
49 changed files with 1615 additions and 173 deletions

View File

@@ -1,6 +1,7 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../app/theme.dart';
import '../../providers/session_provider.dart';
@@ -74,16 +75,53 @@ class _StepTransmissionState extends ConsumerState<StepTransmission> {
}
}
Future<void> _connectYoutube(Team team) async {
try {
final url = await ref.read(apiClientProvider).youtubeAuthorizeUrl(team.id);
final uri = Uri.parse(url);
if (!await canLaunchUrl(uri)) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Impossibile aprire il browser per Google')),
);
}
return;
}
await launchUrl(uri, mode: LaunchMode.externalApplication);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Completa il consenso Google, poi torna qui e seleziona YouTube Live.',
),
duration: Duration(seconds: 5),
),
);
}
} on DioException catch (e) {
final apiErr = ApiException.fromDio(e);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(apiErr?.message ?? 'Errore collegamento YouTube')),
);
}
}
}
void _onYoutubeTap(Team? team) {
if (team == null) return;
if (team.isYoutubeReady) {
setState(() => _platform = 'youtube');
return;
}
if (team.canUseYoutube && team.youtubeMode == 'team' && team.canConnectYoutube) {
_connectYoutube(team);
return;
}
if (team.canUseYoutube && team.youtubeMode == 'team') {
showPremiumRequiredDialog(
context,
message: 'Collega il canale YouTube dalla pagina Dettagli squadra sul sito, poi seleziona YouTube qui.',
message: 'Collega il canale YouTube (Premium Full) per trasmettere sul tuo canale.',
billingUrl: team.staffManageUrl ?? team.billingUrl,
);
return;
@@ -119,7 +157,10 @@ class _StepTransmissionState extends ConsumerState<StepTransmission> {
if (team.youtubeMode == 'matchlivetv_light') {
return 'Canale Match Live TV (in attivazione)';
}
return 'Collega canale sul sito';
if (team.canConnectYoutube) {
return 'Tocca per collegare il tuo canale YouTube';
}
return 'Collega canale (Premium Full)';
}
void _onExternalPremiumTap(String platform, Team? team) {