import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/views/home/main/main_page_state.dart'; import 'package:didvan/views/widgets/skeleton_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:carousel_slider/carousel_slider.dart'; class MediaBannerWithThumbnails extends StatefulWidget { final bool isFirst; const MediaBannerWithThumbnails({super.key, required this.isFirst}); @override State createState() => _MediaBannerWithThumbnailsState(); } class _MediaBannerWithThumbnailsState extends State { int _currentIndex = 0; int _thumbnailStartIndex = 0; final CarouselSliderController _carouselController = CarouselSliderController(); @override Widget build(BuildContext context) { final state = context.read(); final banners = state.content!.banners[widget.isFirst ? 0 : 1]; return Column( children: [ // Top Banner - only show on first section if (widget.isFirst && state.topBanner != null) ...[ Padding( padding: const EdgeInsets.symmetric(horizontal: 5), child: ClipRRect( borderRadius: BorderRadius.circular(16), child: SkeletonImage( imageUrl: state.topBanner!.image, borderRadius: BorderRadius.circular(16), ), ), ), const SizedBox(height: 12), ], CarouselSlider.builder( carouselController: _carouselController, itemCount: banners.length, itemBuilder: (context, index, realIndex) { final item = banners[index]; return Padding( padding: const EdgeInsets.symmetric(horizontal: 5), child: GestureDetector( onTap: () => item.link == null || item.link!.isEmpty ? ActionSheetUtils(context) .openInteractiveViewer(context, item.image, false) : launchUrlString(item.link!, mode: LaunchMode.inAppWebView), child: ClipRRect( borderRadius: BorderRadius.circular(16), child: SkeletonImage( imageUrl: item.image, borderRadius: BorderRadius.circular(16), ), ), ), ); }, options: CarouselOptions( height: (MediaQuery.of(context).size.width - 8) * 9.0 / 16.0, viewportFraction: 1.0, enableInfiniteScroll: true, autoPlay: true, autoPlayInterval: const Duration(seconds: 5), onPageChanged: (index, reason) { setState(() { _currentIndex = index; if (index >= _thumbnailStartIndex + 3) { _thumbnailStartIndex = index - 2; } else if (index < _thumbnailStartIndex) { _thumbnailStartIndex = index; } }); }, ), ), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.center, children: banners.asMap().entries.map((entry) { return AnimatedContainer( duration: const Duration(milliseconds: 300), width: _currentIndex == entry.key ? 10 : 5, height: _currentIndex == entry.key ? 10 : 5, margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( borderRadius: BorderRadius.circular(300), boxShadow: [ BoxShadow( color: _currentIndex == entry.key ? const Color.fromARGB(100, 0, 126, 167) : const Color.fromARGB(0, 0, 0, 0), spreadRadius: 2.5, offset: const Offset(0, 0), ), ], color: _currentIndex == entry.key ? const Color.fromARGB(255, 0, 126, 167) : const Color.fromARGB(255, 200, 200, 200), ), ); }).toList(), ), const SizedBox(height: 16), Row( children: [ IconButton( icon: SvgPicture.asset( 'lib/assets/icons/arrow-right.svg', width: 24, height: 24, colorFilter: ColorFilter.mode( _thumbnailStartIndex > 0 ? const Color.fromARGB(255, 0, 126, 167) : const Color.fromARGB(255, 200, 200, 200), BlendMode.srcIn, ), ), onPressed: _thumbnailStartIndex > 0 ? () { setState(() { _thumbnailStartIndex = (_thumbnailStartIndex - 1).clamp(0, banners.length - 3); }); } : null, ), Expanded( child: SizedBox( height: 60, width: double.infinity, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(3, (index) { if (_thumbnailStartIndex + index >= banners.length) { return const SizedBox(width: 0); } final actualIndex = _thumbnailStartIndex + index; final item = banners[actualIndex]; final isSelected = actualIndex == _currentIndex; return Expanded( child: GestureDetector( onTap: () { if (actualIndex == _currentIndex) return; _carouselController.animateToPage( actualIndex, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, ); setState(() { _currentIndex = actualIndex; if (actualIndex < _thumbnailStartIndex) { _thumbnailStartIndex = actualIndex; } else if (actualIndex >= _thumbnailStartIndex + 3) { _thumbnailStartIndex = (actualIndex - 2).clamp(0, banners.length - 3); } }); }, child: AnimatedContainer( duration: const Duration(milliseconds: 200), margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), border: Border.all( color: isSelected ? const Color.fromARGB(255, 0, 126, 167) : Colors.transparent, width: 2, ), ), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: AnimatedOpacity( duration: const Duration(milliseconds: 200), opacity: isSelected ? 1.0 : 0.6, child: ColorFiltered( colorFilter: isSelected ? const ColorFilter.mode( Colors.transparent, BlendMode.multiply, ) : const ColorFilter.matrix([ 0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0, 0, 0, 1, 0, ]), child: AspectRatio( aspectRatio: 19 / 13, child: SkeletonImage( imageUrl: item.image, borderRadius: BorderRadius.circular(8), ), ), ), ), ), ), ), ); }), ), ), ), // فلش چپ (برای رفتن به جلو) IconButton( icon: SvgPicture.asset( 'lib/assets/icons/arrow-left.svg', width: 24, height: 24, colorFilter: ColorFilter.mode( _thumbnailStartIndex < banners.length - 3 ? const Color.fromARGB(255, 0, 126, 167) : const Color.fromARGB(255, 200, 200, 200), BlendMode.srcIn, ), ), onPressed: _thumbnailStartIndex < banners.length - 3 ? () { setState(() { _thumbnailStartIndex = (_thumbnailStartIndex + 1).clamp(0, banners.length - 3); }); } : null, ), ], ), ], ); } }