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 '../game/game_cubit.dart'; import '../game/game_screen.dart'; /// میز خصوصی: اتاق انتظار (نمایش کد، بازیکنان، شروع) و سپس صحنه‌ی بازی. /// از همان اتصال WebSocket برای لابی و بازی استفاده می‌شود (بدون اتصال مجدد). class PrivateTableScreen extends StatelessWidget { final String token; final bool create; final String? joinCode; const PrivateTableScreen({ super.key, required this.token, required this.create, this.joinCode, }); @override Widget build(BuildContext context) { return BlocProvider( create: (_) => create ? GameCubit.createPrivate(WsClient(token)) : GameCubit.joinPrivate(WsClient(token), joinCode ?? ''), child: const _PrivateTableView(), ); } } class _PrivateTableView extends StatelessWidget { const _PrivateTableView(); @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), ), ); } }