fix: 问题处理~
This commit is contained in:
parent
a6b0a2ae95
commit
fc445e7c80
@ -71,21 +71,39 @@ class _MainRootState extends State<HomePage> {
|
|||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: _homeData.isEmpty
|
child: _homeData.isEmpty
|
||||||
? const SizedBox()
|
? const SizedBox()
|
||||||
: EasyRefresh(
|
: _newBodyWidget(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _newBodyWidget() {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 204.h,
|
||||||
|
padding: EdgeInsets.only(left: 25.w, top: 3.h, right: 25.w),
|
||||||
|
child: HelpImg.asset(ConstImg.homeTopBg, fit: BoxFit.fill),
|
||||||
|
).addInkWell(onTap: () {
|
||||||
|
// 去到搜索页面
|
||||||
|
HelpNav.to(ResultPage(keyword: ''));
|
||||||
|
}),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Expanded(child: EasyRefresh(
|
||||||
controller: _refreshController,
|
controller: _refreshController,
|
||||||
header: const GifHeader(),
|
header: const GifHeader(),
|
||||||
onRefresh: _refreshHome,
|
onRefresh: _refreshHome,
|
||||||
child: _bodyWidget(),
|
child: _bodyWidget(),
|
||||||
),
|
))
|
||||||
),
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _bodyWidget() {
|
Widget _bodyWidget() {
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
_buildTopTwoImgs(),
|
// _buildTopTwoImgs(),
|
||||||
_buildSpace(),
|
// _buildSpace(),
|
||||||
|
_buildTitleImg(ConstImg.homeTitleDaily),
|
||||||
DailyQuestWidget(
|
DailyQuestWidget(
|
||||||
dramaList: _homeData
|
dramaList: _homeData
|
||||||
.firstWhere((element) => element.moduleKey == 'home_v3_recommand')
|
.firstWhere((element) => element.moduleKey == 'home_v3_recommand')
|
||||||
|
|||||||
@ -22,6 +22,9 @@ class DramaDetailPage extends StatefulWidget {
|
|||||||
class _DramaDetailPageState extends State<DramaDetailPage> {
|
class _DramaDetailPageState extends State<DramaDetailPage> {
|
||||||
SkywoodDetail? _detailBean;
|
SkywoodDetail? _detailBean;
|
||||||
SkywoodEpisode? _selectedEpisode;
|
SkywoodEpisode? _selectedEpisode;
|
||||||
|
final PageController _pageController = PageController();
|
||||||
|
int _currentPageIndex = 0;
|
||||||
|
int? _requestingVideoId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -33,33 +36,120 @@ class _DramaDetailPageState extends State<DramaDetailPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_pageController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
void _getDetailDrama({
|
void _getDetailDrama({
|
||||||
required int shortPlayId,
|
required int shortPlayId,
|
||||||
required int shortPlayVideoId,
|
required int shortPlayVideoId,
|
||||||
|
bool showLoading = true,
|
||||||
}) {
|
}) {
|
||||||
|
_requestingVideoId = shortPlayVideoId;
|
||||||
|
if (showLoading) {
|
||||||
AppToast.showLottieLoading();
|
AppToast.showLottieLoading();
|
||||||
|
}
|
||||||
PlayClient.getVideoDetail(
|
PlayClient.getVideoDetail(
|
||||||
shortPlayId: shortPlayId,
|
shortPlayId: shortPlayId,
|
||||||
shortPlayVideoId: shortPlayVideoId,
|
shortPlayVideoId: shortPlayVideoId,
|
||||||
).then((value) {
|
).then((value) {
|
||||||
|
if (showLoading) {
|
||||||
AppToast.dismiss();
|
AppToast.dismiss();
|
||||||
|
}
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
if (_requestingVideoId != shortPlayVideoId) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
_detailBean = value;
|
_detailBean = value;
|
||||||
|
if (value != null) {
|
||||||
|
_selectedEpisode ??= _resolveCurrentEpisode(value);
|
||||||
|
_currentPageIndex = _indexOfEpisode(_selectedEpisode);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
_jumpToCurrentPage();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSelectedEpisode(SkywoodEpisode episode) {
|
void _onSelectedEpisode(SkywoodEpisode episode) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedEpisode = episode;
|
_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(
|
_getDetailDrama(
|
||||||
shortPlayId: episode.shortPlayId,
|
shortPlayId: episode.shortPlayId,
|
||||||
shortPlayVideoId: episode.shortPlayVideoId,
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(backgroundColor: Colors.black, body: _bodyWidget());
|
return Scaffold(backgroundColor: Colors.black, body: _bodyWidget());
|
||||||
@ -76,17 +166,7 @@ class _DramaDetailPageState extends State<DramaDetailPage> {
|
|||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
child: SkyPlayerView(
|
child: _buildPlayerPager(),
|
||||||
key: ValueKey(
|
|
||||||
_selectedEpisode?.shortPlayVideoId ??
|
|
||||||
_detailBean?.videoInfo?.shortPlayVideoId ??
|
|
||||||
widget.dramaBean.shortPlayVideoId,
|
|
||||||
),
|
|
||||||
detailBean: _detailBean,
|
|
||||||
dramaBean: widget.dramaBean,
|
|
||||||
currentEpisode: _selectedEpisode?.episode,
|
|
||||||
onSelectedEpisode: _onSelectedEpisode,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
|
||||||
Positioned(
|
Positioned(
|
||||||
@ -99,6 +179,42 @@ class _DramaDetailPageState extends State<DramaDetailPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
Widget _headerWidget() {
|
||||||
return Container(
|
return Container(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
|||||||
@ -59,6 +59,17 @@ class _VideoPlayerWidgetState extends State<SkyPlayerView> {
|
|||||||
oldWidget.currentEpisode != widget.currentEpisode) {
|
oldWidget.currentEpisode != widget.currentEpisode) {
|
||||||
_disposeController();
|
_disposeController();
|
||||||
_initializePlayer();
|
_initializePlayer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldWidget.autoPlay != widget.autoPlay &&
|
||||||
|
_controllerCreated &&
|
||||||
|
_isInitialized) {
|
||||||
|
if (widget.autoPlay) {
|
||||||
|
_controller.play();
|
||||||
|
} else {
|
||||||
|
_controller.pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +81,7 @@ class _VideoPlayerWidgetState extends State<SkyPlayerView> {
|
|||||||
_currentPosition = Duration.zero;
|
_currentPosition = Duration.zero;
|
||||||
_totalDuration = Duration.zero;
|
_totalDuration = Duration.zero;
|
||||||
_isLiked = widget.dramaBean.isCollect ?? false;
|
_isLiked = widget.dramaBean.isCollect ?? false;
|
||||||
|
_isReportedHis = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
_currentEpisode = _resolveCurrentEpisode();
|
_currentEpisode = _resolveCurrentEpisode();
|
||||||
@ -105,8 +117,10 @@ class _VideoPlayerWidgetState extends State<SkyPlayerView> {
|
|||||||
|
|
||||||
final videoController = _controller;
|
final videoController = _controller;
|
||||||
final position = videoController.value.position;
|
final position = videoController.value.position;
|
||||||
final duration = videoController.value.duration;
|
if (_isPlaying &&
|
||||||
if (_isPlaying && !_isReportedHis && position.inSeconds > 1) {
|
!_isReportedHis &&
|
||||||
|
_currentEpisode != null &&
|
||||||
|
position.inSeconds > 1) {
|
||||||
_isReportedHis = true;
|
_isReportedHis = true;
|
||||||
EventClient.eventCreateHis(
|
EventClient.eventCreateHis(
|
||||||
shortPlayId: _currentEpisode!.shortPlayId.toString(),
|
shortPlayId: _currentEpisode!.shortPlayId.toString(),
|
||||||
@ -380,12 +394,12 @@ class _VideoPlayerWidgetState extends State<SkyPlayerView> {
|
|||||||
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 3,
|
height: 28,
|
||||||
child: SliderTheme(
|
child: SliderTheme(
|
||||||
data: SliderThemeData(
|
data: SliderThemeData(
|
||||||
trackHeight: 3, // ✅ 进度条高度 3
|
trackHeight: 3, // ✅ 进度条高度 3
|
||||||
thumbShape: _ImageThumbShape(imagePath: ConstImg.playTag),
|
thumbShape: _ImageThumbShape(imagePath: ConstImg.playTag),
|
||||||
overlayShape: const RoundSliderOverlayShape(overlayRadius: 3),
|
overlayShape: const RoundSliderOverlayShape(overlayRadius: 10),
|
||||||
activeTrackColor: Colors.white, // ✅ 已播放 = 白色
|
activeTrackColor: Colors.white, // ✅ 已播放 = 白色
|
||||||
inactiveTrackColor: Colors.white.withAlpha(126), // ✅ 未播放 = 灰色
|
inactiveTrackColor: Colors.white.withAlpha(126), // ✅ 未播放 = 灰色
|
||||||
thumbColor: Colors.white,
|
thumbColor: Colors.white,
|
||||||
@ -396,28 +410,46 @@ class _VideoPlayerWidgetState extends State<SkyPlayerView> {
|
|||||||
value: progress,
|
value: progress,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1,
|
max: 1,
|
||||||
onChangeStart: (_) {
|
onChangeStart: (value) {
|
||||||
|
if (totalMilliseconds <= 0) return;
|
||||||
|
setState(() {
|
||||||
_isSeeking = true;
|
_isSeeking = true;
|
||||||
|
_currentPosition = _durationFromProgress(
|
||||||
|
value,
|
||||||
|
totalMilliseconds,
|
||||||
|
);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
if (totalMilliseconds <= 0) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
_currentPosition = Duration(
|
_currentPosition = _durationFromProgress(
|
||||||
milliseconds: (totalMilliseconds * value).round(),
|
value,
|
||||||
|
totalMilliseconds,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onChangeEnd: (value) {
|
onChangeEnd: (value) {
|
||||||
final position = Duration(
|
if (totalMilliseconds <= 0 || !_controllerCreated) return;
|
||||||
milliseconds: (totalMilliseconds * value).round(),
|
final position = _durationFromProgress(value, totalMilliseconds);
|
||||||
);
|
setState(() {
|
||||||
_controller.seekTo(position);
|
_currentPosition = position;
|
||||||
|
});
|
||||||
|
_controller.seekTo(position).whenComplete(() {
|
||||||
|
if (!mounted) return;
|
||||||
_isSeeking = false;
|
_isSeeking = false;
|
||||||
|
_syncPlayerValue();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Duration _durationFromProgress(double value, int totalMilliseconds) {
|
||||||
|
return Duration(milliseconds: (totalMilliseconds * value).round());
|
||||||
|
}
|
||||||
|
|
||||||
String _formatDuration(Duration duration) {
|
String _formatDuration(Duration duration) {
|
||||||
final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0');
|
final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0');
|
||||||
final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0');
|
final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0');
|
||||||
|
|||||||
@ -70,7 +70,9 @@ class _CollectionPageState extends State<MineCollectionPage> {
|
|||||||
|
|
||||||
},
|
},
|
||||||
key: Key(item.shortPlayId.toString()),
|
key: Key(item.shortPlayId.toString()),
|
||||||
child: MineItemView(drama: _collectionList[index]),
|
child: MineItemView(drama: item, onTap: () {
|
||||||
|
HelpNav.to(DramaDetailPage(dramaBean: item));
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) {
|
separatorBuilder: (context, index) {
|
||||||
|
|||||||
@ -140,7 +140,7 @@ class ResultItemView extends StatelessWidget {
|
|||||||
Spacer(),
|
Spacer(),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
_tipView(true, text: '10.0'),
|
_tipView(true, text: SkyTimeTool.formatNum(drama.collectTotal, unit: 'k')),
|
||||||
const SizedBox(width: 15),
|
const SizedBox(width: 15),
|
||||||
_tipView(false, text: SkyTimeTool.formatNum(drama.watchTotal, unit: 'k')),
|
_tipView(false, text: SkyTimeTool.formatNum(drama.watchTotal, unit: 'k')),
|
||||||
],
|
],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user