import 'package:flutter/material.dart'; import 'package:skywood/global/client/play_client.dart'; import 'package:skywood/main/lib_file.dart'; import 'package:skywood/pages/home/players/widget/sky_player_view.dart'; import 'package:skywood/utils/models/drama/skywood_detail.dart'; import 'package:skywood/utils/models/drama/skywood_drama.dart'; import 'package:skywood/utils/models/drama/skywood_episode.dart'; import 'package:skywood/utils/tools/app_toast.dart'; import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; class DramaDetailPage extends StatefulWidget { const DramaDetailPage({super.key, required this.dramaBean}); final SkywoodDrama dramaBean; @override State createState() { return _DramaDetailPageState(); } } class _DramaDetailPageState extends State { SkywoodDetail? _detailBean; SkywoodEpisode? _selectedEpisode; final PageController _pageController = PageController(); int _currentPageIndex = 0; int? _requestingVideoId; @override void initState() { super.initState(); _getDetailDrama( shortPlayId: widget.dramaBean.shortPlayId ?? 0, shortPlayVideoId: widget.dramaBean.shortPlayVideoId ?? 0, ); } @override void dispose() { _pageController.dispose(); super.dispose(); } void _getDetailDrama({ required int shortPlayId, required int shortPlayVideoId, bool showLoading = true, }) { _requestingVideoId = shortPlayVideoId; if (showLoading) { AppToast.showLottieLoading(); } PlayClient.getVideoDetail( shortPlayId: shortPlayId, shortPlayVideoId: shortPlayVideoId, ).then((value) { if (showLoading) { AppToast.dismiss(); } if (!mounted) return; if (_requestingVideoId != shortPlayVideoId) return; setState(() { _detailBean = value; if (value != null) { _selectedEpisode ??= _resolveCurrentEpisode(value); _currentPageIndex = _indexOfEpisode(_selectedEpisode); } }); _jumpToCurrentPage(); }); } void _onSelectedEpisode(SkywoodEpisode episode) { setState(() { _selectedEpisode = episode; _currentPageIndex = _indexOfEpisode(episode); }); _jumpToCurrentPage(); _getDetailDrama( shortPlayId: episode.shortPlayId, shortPlayVideoId: episode.shortPlayVideoId, showLoading: false, ); } void _onPageChanged(int index) { final episodes = _detailBean?.episodeList ?? []; if (index < 0 || index >= episodes.length) return; final episode = episodes[index]; if (_selectedEpisode?.shortPlayVideoId == episode.shortPlayVideoId) { _currentPageIndex = index; return; } setState(() { _selectedEpisode = episode; _currentPageIndex = index; }); _getDetailDrama( shortPlayId: episode.shortPlayId, shortPlayVideoId: episode.shortPlayVideoId, showLoading: false, ); } SkywoodEpisode? _resolveCurrentEpisode(SkywoodDetail detail) { if (detail.episodeList.isEmpty) return null; final int? episode = _selectedEpisode?.episode ?? detail.videoInfo?.episode ?? detail.videoInfo?.currentEpisode ?? detail.shortPlayInfo?.episode ?? detail.shortPlayInfo?.currentEpisode ?? widget.dramaBean.currentEpisode ?? widget.dramaBean.episode; if (episode != null && episode > 0) { for (final item in detail.episodeList) { if (item.episode == episode) return item; } } return detail.episodeList.first; } int _indexOfEpisode(SkywoodEpisode? episode) { final episodes = _detailBean?.episodeList ?? []; if (episode == null || episodes.isEmpty) return 0; final index = episodes.indexWhere( (item) => item.shortPlayVideoId == episode.shortPlayVideoId, ); return index < 0 ? 0 : index; } void _jumpToCurrentPage() { WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted || !_pageController.hasClients) return; final episodes = _detailBean?.episodeList ?? []; if (episodes.isEmpty) return; final page = _currentPageIndex.clamp(0, episodes.length - 1); if ((_pageController.page ?? _pageController.initialPage).round() == page) { return; } _pageController.jumpToPage(page); }); } @override Widget build(BuildContext context) { return Scaffold(backgroundColor: Colors.black, body: _bodyWidget()); } Widget _bodyWidget() { return Stack( children: [ SizedBox(width: double.infinity, height: double.infinity), if (_detailBean != null) Positioned( bottom: 0, left: 0, right: 0, top: 0, child: _buildPlayerPager(), ), Positioned( top: AppScreen.statusBarHeight + 5, left: 0, right: 0, child: _headerWidget(), ), ], ); } Widget _buildPlayerPager() { final detail = _detailBean!; final episodes = detail.episodeList; if (episodes.isEmpty) { return SkyPlayerView( detailBean: detail, dramaBean: widget.dramaBean, currentEpisode: _selectedEpisode?.episode, onSelectedEpisode: _onSelectedEpisode, ); } return PageView.builder( controller: _pageController, scrollDirection: Axis.vertical, onPageChanged: _onPageChanged, itemCount: episodes.length, itemBuilder: (context, index) { final episode = episodes[index]; final isCurrent = index == _currentPageIndex; return SkyPlayerView( key: ValueKey( '${episode.shortPlayVideoId}-$isCurrent-${detail.videoInfo?.shortPlayVideoId}', ), autoPlay: isCurrent, detailBean: detail, dramaBean: widget.dramaBean, currentEpisode: episode.episode, onSelectedEpisode: _onSelectedEpisode, ); }, ); } Widget _headerWidget() { return Container( height: 40, padding: const EdgeInsets.only(right: 15, left: 5), child: Row( children: [ IconButton( icon: HelpImg.asset(ConstImg.back, width: 32), onPressed: () => HelpNav.back(), ), Expanded( child: SkyText( text: widget.dramaBean.name, color: Colors.white, fontSize: 16, textAlign: TextAlign.center, fontWeight: FontWeight.bold, ), ), SizedBox(width: 40), ], ), ); } }