import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/network/ws_client.dart'; import '../../../../core/theme/app_theme.dart'; import '../../../../core/widgets/game_ui.dart'; import '../bloc/game_bloc.dart'; import '../bloc/game_state.dart'; import 'game_screen.dart'; /// میز خصوصی: اتاق انتظار (کد، بازیکنان، شروع) سپس صحنه‌ی بازی (روی همان اتصال). class PrivateTableScreen extends StatelessWidget { const PrivateTableScreen({super.key}); @override Widget build(BuildContext context) { return BlocConsumer( listenWhen: (a, b) => (a.notice != b.notice && b.notice != null) || (!a.tableClosed && b.tableClosed), listener: (context, state) { if (state.tableClosed) { if (context.canPop()) context.pop(); return; } if (state.notice != null) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(state.notice!), duration: const Duration(seconds: 2))); context.read().clearNotice(); } }, builder: (context, state) { if (state.state != null) { return const GameScreen(prize: 0); } return _LobbyView(state: state); }, ); } } class _LobbyView extends StatelessWidget { final GameUiState state; const _LobbyView({required this.state}); @override Widget build(BuildContext context) { final lobby = state.lobby; final connecting = state.connection != WsStatus.connected || lobby == null; return PopScope( canPop: false, onPopInvokedWithResult: (didPop, _) { if (didPop) return; context.read().leaveTable(); if (context.canPop()) context.pop(); }, child: Scaffold( body: GameBackground( child: SafeArea( child: Stack( children: [ Column( children: [ Align( alignment: Alignment.centerRight, child: Padding( padding: const EdgeInsets.all(10), child: GestureDetector( onTap: () { context.read().leaveTable(); if (context.canPop()) context.pop(); }, child: Container( width: 46, height: 46, decoration: BoxDecoration( color: AppColors.panel, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.gold, width: 1.5), ), child: const Icon(Icons.arrow_back, color: AppColors.gold), ), ), ), ), Expanded( child: connecting ? const Center( child: CircularProgressIndicator( color: AppColors.gold)) : _content(context, lobby), ), ], ), if (state.countdown != null) _CountdownOverlay(seconds: state.countdown!), ], ), ), ), ), ); } Widget _content(BuildContext context, TableLobby lobby) { return SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 20), child: Column( children: [ const GlowText('میز دورهمی', size: 26), const SizedBox(height: 16), GamePanel( child: Column(children: [ const Text('شماره میز', style: TextStyle(color: Colors.white70)), const SizedBox(height: 6), Row(mainAxisAlignment: MainAxisAlignment.center, children: [ SelectableText(lobby.code, style: const TextStyle( color: AppColors.gold, fontSize: 40, fontWeight: FontWeight.bold, letterSpacing: 8)), IconButton( onPressed: () { Clipboard.setData(ClipboardData(text: lobby.code)); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('کد کپی شد'))); }, icon: const Icon(Icons.copy, color: AppColors.gold), ), ]), const Text('این کد را برای دوستانت بفرست', style: TextStyle(color: Colors.white54, fontSize: 12)), ]), ), const SizedBox(height: 16), GamePanel( child: Column(children: [ for (var i = 0; i < 4; i++) _seatRow(i, lobby), ]), ), const SizedBox(height: 20), if (lobby.isHost) GameButton( label: 'شروع بازی', icon: Icons.play_arrow, width: double.infinity, colors: const [Color(0xFF3FA34D), Color(0xFF1B5E20)], onTap: () => context.read().startTable(), ) else const Text('در انتظار شروع توسط میزبان…', style: TextStyle(color: AppColors.gold, fontSize: 15)), const SizedBox(height: 8), if (lobby.isHost) const Text('جای‌های خالی با ربات پر می‌شوند', style: TextStyle(color: Colors.white54, fontSize: 12)), const SizedBox(height: 24), ], ), ); } Widget _seatRow(int i, TableLobby lobby) { final filled = i < lobby.players.length; final p = filled ? lobby.players[i] : null; return Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Row(children: [ Icon(filled ? Icons.person : Icons.person_outline, color: filled ? AppColors.gold : Colors.white24, size: 24), const SizedBox(width: 10), Text( filled ? p!.name : 'در انتظار بازیکن…', style: TextStyle( color: filled ? Colors.white : Colors.white38, fontSize: 15, fontWeight: filled ? FontWeight.bold : FontWeight.normal), ), const Spacer(), if (p?.host == true) const Icon(Icons.star, color: AppColors.gold, size: 18), ]), ); } } /// اوورلی شمارش معکوس ۳، ۲، ۱ پیش از شروع بازی. class _CountdownOverlay extends StatefulWidget { final int seconds; const _CountdownOverlay({required this.seconds}); @override State<_CountdownOverlay> createState() => _CountdownOverlayState(); } class _CountdownOverlayState extends State<_CountdownOverlay> { late int _n; Timer? _timer; @override void initState() { super.initState(); _n = widget.seconds; _timer = Timer.periodic(const Duration(seconds: 1), (_) { if (!mounted) return; setState(() => _n--); if (_n <= 0) _timer?.cancel(); }); } @override void dispose() { _timer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Container( color: Colors.black.withValues(alpha: 0.7), alignment: Alignment.center, child: TweenAnimationBuilder( key: ValueKey(_n), tween: Tween(begin: 0.4, end: 1.2), duration: const Duration(milliseconds: 700), curve: Curves.easeOut, builder: (context, scale, child) => Transform.scale(scale: scale, child: child), child: GlowText(_n > 0 ? '$_n' : 'شروع!', size: 96), ), ); } }