import 'package:flutter/material.dart'; import '../models/channel.dart'; import '../services/api_service.dart'; import '../services/auth_service.dart'; import 'channel_screen.dart'; import 'login_screen.dart'; class ChannelListScreen extends StatefulWidget { const ChannelListScreen({super.key}); @override State createState() => _ChannelListScreenState(); } class _ChannelListScreenState extends State { final _authService = AuthService(); late final ApiService _api; List _channels = []; bool _loading = true; String? _error; @override void initState() { super.initState(); _api = ApiService(_authService); _loadChannels(); } Future _loadChannels() async { setState(() { _loading = true; _error = null; }); final channels = await _api.getChannels(); if (!mounted) return; if (channels.isEmpty && _channels.isEmpty) { setState(() { _loading = false; _error = 'کانالی یافت نشد'; }); } else { setState(() { _channels = channels; _loading = false; }); } } Future _logout() async { await _authService.logout(); if (!mounted) return; Navigator.pushReplacement( context, MaterialPageRoute(builder: (_) => const LoginScreen()), ); } void _enterChannel(Channel ch) { Navigator.push( context, MaterialPageRoute(builder: (_) => ChannelScreen(channel: ch)), ); } Future _showPrivateJoin() async { final keyCtrl = TextEditingController(); bool joining = false; String? joinError; await showDialog( context: context, builder: (ctx) { return StatefulBuilder(builder: (ctx, setDialog) { return Dialog( backgroundColor: const Color(0xFF1C1C1E), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.lock_outline, color: Color(0xFFFFAB00), size: 22), const SizedBox(height: 6), const Text( 'کانال خصوصی', style: TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold), ), const SizedBox(height: 10), SizedBox( height: 34, child: TextField( controller: keyCtrl, style: const TextStyle(color: Colors.white, fontSize: 12), textAlign: TextAlign.center, decoration: InputDecoration( hintText: 'کلید ورود', hintStyle: const TextStyle( color: Colors.white38, fontSize: 11), filled: true, fillColor: const Color(0xFF2C2C2E), border: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide.none, ), contentPadding: const EdgeInsets.symmetric( horizontal: 10, vertical: 0), ), ), ), if (joinError != null) ...[ const SizedBox(height: 4), Text(joinError!, style: const TextStyle( color: Color(0xFFFF1744), fontSize: 10)), ], const SizedBox(height: 10), Row( children: [ Expanded( child: TextButton( onPressed: () => Navigator.pop(ctx), style: TextButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 8), ), child: const Text('انصراف', style: TextStyle( color: Colors.white54, fontSize: 11)), ), ), const SizedBox(width: 8), Expanded( child: ElevatedButton( onPressed: joining ? null : () async { final key = keyCtrl.text.trim(); if (key.isEmpty) { setDialog( () => joinError = 'کلید را وارد کنید'); return; } setDialog(() { joining = true; joinError = null; }); final ch = await _api.joinPrivateChannel(key); if (!ctx.mounted) return; if (ch != null) { Navigator.pop(ctx); _enterChannel(ch); } else { setDialog(() { joining = false; joinError = 'کلید نادرست'; }); } }, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFFFFAB00), foregroundColor: Colors.black, padding: const EdgeInsets.symmetric(vertical: 8), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14)), ), child: joining ? const SizedBox( width: 14, height: 14, child: CircularProgressIndicator( color: Colors.black, strokeWidth: 2), ) : const Text('ورود', style: TextStyle( fontSize: 11, fontWeight: FontWeight.bold)), ), ), ], ), ], ), ), ); }); }, ); keyCtrl.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: SafeArea( child: Column( children: [ // Header Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), child: Row( children: [ const SizedBox(width: 4), const Icon(Icons.settings_input_antenna, color: Color(0xFF00C853), size: 16), const SizedBox(width: 4), const Expanded( child: Text( 'کانال‌ها', style: TextStyle( color: Colors.white, fontSize: 13, fontWeight: FontWeight.bold), ), ), // Refresh IconButton( onPressed: _loading ? null : _loadChannels, padding: EdgeInsets.zero, constraints: const BoxConstraints(minWidth: 32, minHeight: 32), icon: const Icon(Icons.refresh, color: Colors.white54, size: 18), ), // Logout IconButton( onPressed: _logout, padding: EdgeInsets.zero, constraints: const BoxConstraints(minWidth: 32, minHeight: 32), icon: const Icon(Icons.logout, color: Colors.white38, size: 16), ), ], ), ), // Content Expanded( child: _loading ? const Center( child: CircularProgressIndicator( color: Color(0xFF00C853), strokeWidth: 2), ) : _error != null && _channels.isEmpty ? Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.wifi_off, color: Colors.white38, size: 24), const SizedBox(height: 6), Text(_error!, style: const TextStyle( color: Colors.white38, fontSize: 11)), const SizedBox(height: 8), TextButton( onPressed: _loadChannels, child: const Text('تلاش مجدد', style: TextStyle( color: Color(0xFF00C853), fontSize: 11)), ), ], ), ) : ListView.builder( padding: const EdgeInsets.only(bottom: 4), itemCount: _channels.length + 1, itemBuilder: (ctx, i) { if (i == _channels.length) { // Private join button return _PrivateJoinTile( onTap: _showPrivateJoin); } return _ChannelTile( channel: _channels[i], onTap: () => _enterChannel(_channels[i]), ); }, ), ), ], ), ), ); } } class _ChannelTile extends StatelessWidget { final Channel channel; final VoidCallback onTap; const _ChannelTile({required this.channel, required this.onTap}); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), height: 44, decoration: BoxDecoration( color: const Color(0xFF1C1C1E), borderRadius: BorderRadius.circular(14), ), padding: const EdgeInsets.symmetric(horizontal: 12), child: Row( children: [ const Icon(Icons.radio, color: Color(0xFF00C853), size: 16), const SizedBox(width: 8), Expanded( child: Text( channel.name, style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis, ), ), if (channel.memberCount > 0) ...[ Text( '${channel.memberCount}', style: const TextStyle(color: Colors.white38, fontSize: 10), ), const SizedBox(width: 2), const Icon(Icons.person_outline, color: Colors.white38, size: 11), ], const SizedBox(width: 4), const Icon(Icons.chevron_right, color: Colors.white24, size: 16), ], ), ), ); } } class _PrivateJoinTile extends StatelessWidget { final VoidCallback onTap; const _PrivateJoinTile({required this.onTap}); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), height: 44, decoration: BoxDecoration( color: const Color(0xFF2C2400), borderRadius: BorderRadius.circular(14), border: Border.all( color: const Color(0xFFFFAB00).withValues(alpha: 0.4), width: 1, ), ), padding: const EdgeInsets.symmetric(horizontal: 12), child: const Row( children: [ Icon(Icons.lock_open_outlined, color: Color(0xFFFFAB00), size: 16), SizedBox(width: 8), Expanded( child: Text( 'ورود به کانال خصوصی', style: TextStyle( color: Color(0xFFFFAB00), fontSize: 11, fontWeight: FontWeight.w500), ), ), Icon(Icons.chevron_right, color: Color(0xFFFFAB00), size: 16), ], ), ), ); } }