Initial commit: monorepo Match Live TV.
Rails API, app Flutter, infrastruttura Docker/MediaMTX, sito marketing e documentazione di deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
158
mobile/lib/features/camera_mode/camera_screen_portrait.dart
Normal file
158
mobile/lib/features/camera_mode/camera_screen_portrait.dart
Normal file
@@ -0,0 +1,158 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../app/theme.dart';
|
||||
import '../../shared/models/score_state.dart';
|
||||
import '../../shared/widgets/destructive_cta.dart';
|
||||
import '../../shared/widgets/live_badge.dart';
|
||||
import '../../shared/widgets/metric_card.dart';
|
||||
import '../../shared/widgets/score_overlay_bar.dart';
|
||||
import '../../platform/streaming_preview.dart';
|
||||
|
||||
class CameraScreenPortrait extends StatelessWidget {
|
||||
const CameraScreenPortrait({
|
||||
super.key,
|
||||
required this.elapsed,
|
||||
required this.batteryLevel,
|
||||
required this.homeName,
|
||||
required this.awayName,
|
||||
required this.score,
|
||||
required this.networkType,
|
||||
required this.bitrateMbps,
|
||||
required this.fps,
|
||||
required this.viewerCount,
|
||||
required this.sessionId,
|
||||
this.platformLabel = 'LIVE',
|
||||
required this.onStop,
|
||||
});
|
||||
|
||||
final Duration elapsed;
|
||||
final int batteryLevel;
|
||||
final String homeName;
|
||||
final String awayName;
|
||||
final ScoreState score;
|
||||
final String networkType;
|
||||
final double bitrateMbps;
|
||||
final int fps;
|
||||
final int viewerCount;
|
||||
final String sessionId;
|
||||
final String platformLabel;
|
||||
final VoidCallback onStop;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppTheme.background,
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
LiveBadge(elapsed: elapsed),
|
||||
const Spacer(),
|
||||
const Icon(Icons.battery_std, size: 18, color: AppTheme.textSecondary),
|
||||
const SizedBox(width: 4),
|
||||
Text('$batteryLevel%', style: theme.textTheme.labelLarge),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: NativeStreamingPreview(
|
||||
showGrid: true,
|
||||
platformLabel: platformLabel,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: ScoreOverlayBar(
|
||||
homeName: homeName,
|
||||
awayName: awayName,
|
||||
homePoints: score.homePoints,
|
||||
awayPoints: score.awayPoints,
|
||||
currentSet: score.currentSet,
|
||||
homeSets: score.homeSets,
|
||||
awaySets: score.awaySets,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
MetricCard(
|
||||
label: 'Segnale',
|
||||
value: networkType,
|
||||
icon: Icons.signal_cellular_alt,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
MetricCard(
|
||||
label: 'Mbps',
|
||||
value: bitrateMbps.toStringAsFixed(1),
|
||||
icon: Icons.speed,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
MetricCard(label: 'fps', value: '$fps', icon: Icons.movie),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.surface,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.play_circle, color: AppTheme.primaryRed),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(platformLabel, style: theme.textTheme.titleMedium),
|
||||
Text(
|
||||
viewerCount > 0
|
||||
? '$viewerCount spettatori'
|
||||
: 'IN DIRETTA',
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
|
||||
child: Text(
|
||||
'Registrazione locale attiva: /sd/match_$sessionId',
|
||||
style: theme.textTheme.bodyMedium?.copyWith(fontSize: 11),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: DestructiveCta(label: 'INTERROMPI', onPressed: onStop),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user