import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:madari_client/features/streamio_addons/models/stremio_base_types.dart'; import '../../../../library/container/add_to_list_button.dart'; import 'stream_list.dart'; final _logger = Logger('StreamioComponents'); Future openVideoStream(BuildContext context, Meta meta) async { return showModalBottomSheet( enableDrag: true, constraints: const BoxConstraints( maxWidth: 780, ), isScrollControlled: true, useSafeArea: true, context: context, builder: (context) { return Scaffold( body: StreamioStreamList( meta: meta, ), ); }, ); } class StreamioBackground extends StatelessWidget { final String? imageUrl; const StreamioBackground({super.key, this.imageUrl}); @override Widget build(BuildContext context) { if (imageUrl == null) return const SizedBox.shrink(); return SizedBox.expand( child: Stack( fit: StackFit.expand, children: [ CachedNetworkImage( imageUrl: imageUrl!, fit: BoxFit.cover, errorWidget: (context, url, error) { _logger.warning('Error loading background image', error); return const SizedBox.shrink(); }, ), Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.black.withValues(alpha: 0.8), Colors.black.withValues(alpha: 0.9), Colors.black, ], ), ), ), ], ), ); } } class StreamioHeroSection extends StatelessWidget { final Meta meta; final String type; final String? prefix; const StreamioHeroSection({ super.key, required this.meta, required this.type, this.prefix, }); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.only( top: 160, left: 16.0, right: 16.0, ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ if (meta.poster != null) Expanded( flex: 2, child: SizedBox( height: 220, width: 130, child: Stack( alignment: Alignment.center, children: [ Hero( tag: prefix ?? "", child: ClipRRect( borderRadius: BorderRadius.circular(8), child: CachedNetworkImage( imageUrl: "https://proxy-image.syncws.com/insecure/plain/${Uri.encodeQueryComponent(meta.poster!)}@webp", fit: BoxFit.cover, errorWidget: (context, url, error) { _logger.warning( 'Error loading poster image', error); return const Icon(Icons.error); }, ), ), ), IconButton.filled( onPressed: () { _logger.info('Play button pressed for ${meta.name}'); openVideoStream(context, meta); }, icon: const Icon(Icons.play_arrow, size: 32), style: IconButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.primary, foregroundColor: Theme.of(context).colorScheme.onPrimary, ), ), ], ), ), ), Expanded( flex: 3, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( meta.name ?? 'Unknown Title', style: Theme.of(context).textTheme.headlineLarge?.copyWith( color: Colors.white, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( '${meta.year ?? ''} • ${meta.runtime ?? ''} • ${meta.genres?.join(', ') ?? ''}', style: Theme.of(context).textTheme.titleMedium?.copyWith( color: Colors.white.withValues(alpha: 0.7), ), ), if (meta.imdbRating.isNotEmpty && meta.imdbRating.toString() != "null") ...[ const SizedBox(height: 16), Row( children: [ const Icon(Icons.star, color: Colors.amber), const SizedBox(width: 8), Text( meta.imdbRating, style: Theme.of(context).textTheme.titleMedium?.copyWith( color: Colors.white, ), ), ], ), ], const SizedBox( height: 12, ), OutlinedButton.icon( onPressed: () { openVideoStream( context, meta, ); }, icon: const Icon(Icons.play_arrow), label: const Text("Play"), ), const SizedBox( height: 12, ), SizedBox( height: 40, child: ListView( scrollDirection: Axis.horizontal, children: [ AddToListButton( meta: meta, listName: "Favourites", minimal: true, ), const SizedBox( width: 8, ), AddToListButton( meta: meta, listName: "Watchlist", minimal: true, ), const SizedBox( width: 8, ), AddToListButton( label: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.playlist_add_outlined), SizedBox( width: 8, ), Text("Add to list"), ], ), meta: meta, icon: Icons.add, ), ], ), ), ], ), ), ), ], ), ); } } class StreamioSeasonSelector extends StatelessWidget { final List