import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../services/iptv_provider.dart'; import '../models/xtream_models.dart'; import 'player_screen.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { int _selectedTab = 0; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { _loadInitialData(); }); } Future _loadInitialData() async { final provider = context.read(); await provider.loadLiveStreams(); await provider.loadVodStreams(); await provider.loadSeries(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, appBar: AppBar( backgroundColor: Colors.red, title: Consumer( builder: (context, provider, _) { return Text( provider.userInfo != null ? 'XStream TV - ${provider.userInfo!.username}' : 'XStream TV', ); }, ), actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: _loadInitialData, ), IconButton( icon: const Icon(Icons.logout), onPressed: () { context.read().logout(); }, ), ], ), body: Row( children: [ NavigationRail( selectedIndex: _selectedTab, onDestinationSelected: (index) { setState(() => _selectedTab = index); }, backgroundColor: Colors.grey[900], selectedIconTheme: const IconThemeData(color: Colors.red), unselectedIconTheme: const IconThemeData(color: Colors.grey), labelType: NavigationRailLabelType.all, destinations: const [ NavigationRailDestination( icon: Icon(Icons.live_tv), selectedIcon: Icon(Icons.live_tv, color: Colors.red), label: Text('Live', style: TextStyle(color: Colors.white)), ), NavigationRailDestination( icon: Icon(Icons.movie), selectedIcon: Icon(Icons.movie, color: Colors.red), label: Text('Movies', style: TextStyle(color: Colors.white)), ), NavigationRailDestination( icon: Icon(Icons.tv), selectedIcon: Icon(Icons.tv, color: Colors.red), label: Text('Series', style: TextStyle(color: Colors.white)), ), ], ), Expanded( child: _buildContent(), ), ], ), ); } Widget _buildContent() { switch (_selectedTab) { case 0: return _LiveTab(); case 1: return _MoviesTab(); case 2: return _SeriesTab(); default: return _LiveTab(); } } } class _LiveTab extends StatelessWidget { @override Widget build(BuildContext context) { return Consumer( builder: (context, provider, _) { if (provider.isLoading) { return const Center(child: CircularProgressIndicator(color: Colors.red)); } return Column( children: [ _CategoryDropdown( categories: provider.liveCategories, selectedCategory: provider.selectedLiveCategory, onCategorySelected: (categoryId) { provider.loadLiveStreams(categoryId); }, ), Expanded( child: _StreamList( streams: provider.liveStreams, onStreamSelected: (stream) { Navigator.push( context, MaterialPageRoute( builder: (_) => PlayerScreen(stream: stream), ), ); }, ), ), ], ); }, ); } } class _MoviesTab extends StatelessWidget { @override Widget build(BuildContext context) { return Consumer( builder: (context, provider, _) { if (provider.isLoading) { return const Center(child: CircularProgressIndicator(color: Colors.red)); } return Column( children: [ _CategoryDropdown( categories: provider.vodCategories, selectedCategory: provider.selectedVodCategory, onCategorySelected: (categoryId) { provider.loadVodStreams(categoryId); }, ), Expanded( child: _StreamList( streams: provider.vodStreams, onStreamSelected: (stream) { Navigator.push( context, MaterialPageRoute( builder: (_) => PlayerScreen(stream: stream), ), ); }, ), ), ], ); }, ); } } class _SeriesTab extends StatelessWidget { @override Widget build(BuildContext context) { return Consumer( builder: (context, provider, _) { if (provider.isLoading) { return const Center(child: CircularProgressIndicator(color: Colors.red)); } if (provider.selectedSeries != null) { return _SeriesDetailScreen(series: provider.selectedSeries!); } return _StreamList( streams: provider.seriesList.map((s) => XtreamStream( streamId: s.seriesId, name: s.name, streamIcon: s.cover, plot: s.plot, rating: s.rating, )).toList(), isSeries: true, onStreamSelected: (stream) { final series = provider.seriesList.firstWhere( (s) => s.seriesId == stream.streamId, ); provider.loadSeriesEpisodes(series); }, ); }, ); } } class _SeriesDetailScreen extends StatelessWidget { final XtreamSeries series; const _SeriesDetailScreen({required this.series}); @override Widget build(BuildContext context) { return Consumer( builder: (context, provider, _) { final episodes = provider.seriesEpisodes; return Column( children: [ Padding( padding: const EdgeInsets.all(16), child: Row( children: [ IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: () { provider.loadSeries(); }, ), Expanded( child: Text( series.name, style: const TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), ), ), ], ), ), Expanded( child: ListView.builder( itemCount: episodes.length, itemBuilder: (context, index) { final episode = episodes[index]; return ListTile( leading: const Icon(Icons.play_circle_outline, color: Colors.red), title: Text( 'S${episode.seasonNumber}E${episode.episodeNumber} - ${episode.title}', style: const TextStyle(color: Colors.white), ), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (_) => PlayerScreen( stream: XtreamStream( streamId: episode.episodeId, name: episode.title, containerExtension: episode.containerExtension, url: episode.url, ), isLive: false, ), ), ); }, ); }, ), ), ], ); }, ); } } class _CategoryDropdown extends StatelessWidget { final List categories; final String selectedCategory; final Function(String) onCategorySelected; const _CategoryDropdown({ required this.categories, required this.selectedCategory, required this.onCategorySelected, }); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(16), color: Colors.grey[900], child: DropdownButton( value: selectedCategory.isEmpty ? null : selectedCategory, hint: const Text('All Categories', style: TextStyle(color: Colors.white)), dropdownColor: Colors.grey[800], isExpanded: true, items: [ const DropdownMenuItem( value: '', child: Text('All Categories', style: TextStyle(color: Colors.white)), ), ...categories.map((c) => DropdownMenuItem( value: c.id, child: Text(c.name, style: const TextStyle(color: Colors.white)), )), ], onChanged: (value) { onCategorySelected(value ?? ''); }, ), ); } } class _StreamList extends StatelessWidget { final List streams; final Function(XtreamStream) onStreamSelected; final bool isSeries; const _StreamList({ required this.streams, required this.onStreamSelected, this.isSeries = false, }); @override Widget build(BuildContext context) { if (streams.isEmpty) { return const Center( child: Text( 'No content available', style: TextStyle(color: Colors.grey), ), ); } return ListView.builder( itemCount: streams.length, itemBuilder: (context, index) { final stream = streams[index]; return ListTile( leading: isSeries && stream.streamIcon != null ? ClipRRect( borderRadius: BorderRadius.circular(4), child: Image.network( stream.streamIcon!, width: 40, height: 60, fit: BoxFit.cover, errorBuilder: (_, __, ___) => const Icon( Icons.tv, color: Colors.red, size: 40, ), ), ) : Icon( isSeries ? Icons.tv : Icons.play_circle_outline, color: Colors.red, size: 40, ), title: Text( stream.name, style: const TextStyle(color: Colors.white), maxLines: 2, overflow: TextOverflow.ellipsis, ), subtitle: stream.rating != null ? Row( children: [ const Icon(Icons.star, color: Colors.amber, size: 14), Text( stream.rating ?? '', style: const TextStyle(color: Colors.amber), ), ], ) : null, onTap: () => onStreamSelected(stream), ); }, ); } }