mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
refa: list sheet
Closes #369 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
library video_detail;
|
||||
|
||||
export './controller.dart';
|
||||
export './view.dart';
|
||||
export './view_v.dart';
|
||||
|
||||
@@ -778,7 +778,11 @@ class VideoIntroController extends GetxController
|
||||
|
||||
final int currentIndex = episodes.indexWhere((e) =>
|
||||
e.cid ==
|
||||
(skipPages ? videoDetail.value.pages!.first.cid : lastPlayCid.value));
|
||||
(skipPages
|
||||
? videoDetail.value.isPageReversed == true
|
||||
? videoDetail.value.pages!.last.cid
|
||||
: videoDetail.value.pages!.first.cid
|
||||
: lastPlayCid.value));
|
||||
int prevIndex = currentIndex - 1;
|
||||
final PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
||||
|
||||
@@ -838,8 +842,11 @@ class VideoIntroController extends GetxController
|
||||
final int currentIndex = episodes.indexWhere((e) =>
|
||||
e.cid ==
|
||||
(skipPages
|
||||
? videoDetail.value.pages!.first.cid
|
||||
? videoDetail.value.isPageReversed == true
|
||||
? videoDetail.value.pages!.last.cid
|
||||
: videoDetail.value.pages!.first.cid
|
||||
: videoDetailCtr.cid.value));
|
||||
|
||||
int nextIndex = currentIndex + 1;
|
||||
|
||||
if (isPages.not &&
|
||||
|
||||
@@ -627,7 +627,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(!widget.loadingStatus
|
||||
? videoDetail.stat?.danmu ?? '-'
|
||||
? videoDetail.stat?.danmaku ?? '-'
|
||||
: videoItem['stat']?.danmu ?? '-'),
|
||||
size: 'medium',
|
||||
textColor: t.colorScheme.outline,
|
||||
@@ -858,7 +858,6 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
heroTag: widget.heroTag,
|
||||
videoIntroController: videoIntroController,
|
||||
bvid: videoIntroController.bvid,
|
||||
changeFuc: videoIntroController.changeSeasonOrbangu,
|
||||
showEpisodes: widget.showEpisodes,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -12,16 +12,20 @@ import '../../../../../utils/id_utils.dart';
|
||||
class PagesPanel extends StatefulWidget {
|
||||
const PagesPanel({
|
||||
super.key,
|
||||
this.list,
|
||||
this.cover,
|
||||
required this.bvid,
|
||||
required this.changeFuc,
|
||||
required this.heroTag,
|
||||
required this.showEpisodes,
|
||||
this.showEpisodes,
|
||||
required this.videoIntroController,
|
||||
});
|
||||
|
||||
final List<Part>? list;
|
||||
final String? cover;
|
||||
|
||||
final String bvid;
|
||||
final Function changeFuc;
|
||||
final String heroTag;
|
||||
final Function showEpisodes;
|
||||
final Function? showEpisodes;
|
||||
final VideoIntroController videoIntroController;
|
||||
|
||||
@override
|
||||
@@ -30,36 +34,46 @@ class PagesPanel extends StatefulWidget {
|
||||
|
||||
class _PagesPanelState extends State<PagesPanel> {
|
||||
late int cid;
|
||||
late int pageIndex;
|
||||
int pageIndex = -1;
|
||||
late VideoDetailController _videoDetailController;
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
StreamSubscription? _listener;
|
||||
|
||||
List<Part> get pages => widget.videoIntroController.videoDetail.value.pages!;
|
||||
List<Part> get pages =>
|
||||
widget.list ?? widget.videoIntroController.videoDetail.value.pages!;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
cid = widget.videoIntroController.lastPlayCid.value;
|
||||
_videoDetailController =
|
||||
Get.find<VideoDetailController>(tag: widget.heroTag);
|
||||
pageIndex = pages.indexWhere((Part e) => e.cid == cid);
|
||||
_listener = _videoDetailController.cid.listen((int cid) {
|
||||
this.cid = cid;
|
||||
pageIndex = max(0, pages.indexWhere((Part e) => e.cid == cid));
|
||||
if (!mounted) return;
|
||||
setState(() {});
|
||||
const double itemWidth = 150; // 每个列表项的宽度
|
||||
final double targetOffset = (pageIndex * itemWidth - itemWidth / 2).clamp(
|
||||
_scrollController.position.minScrollExtent,
|
||||
_scrollController.position.maxScrollExtent);
|
||||
// 滑动至目标位置
|
||||
_scrollController.animateTo(
|
||||
targetOffset,
|
||||
duration: const Duration(milliseconds: 300), // 滑动动画持续时间
|
||||
curve: Curves.easeInOut, // 滑动动画曲线
|
||||
);
|
||||
});
|
||||
if (widget.list == null) {
|
||||
cid = widget.videoIntroController.lastPlayCid.value;
|
||||
_videoDetailController =
|
||||
Get.find<VideoDetailController>(tag: widget.heroTag);
|
||||
pageIndex = pages.indexWhere((Part e) => e.cid == cid);
|
||||
_listener = _videoDetailController.cid.listen((int cid) {
|
||||
this.cid = cid;
|
||||
pageIndex = max(0, pages.indexWhere((Part e) => e.cid == cid));
|
||||
if (!mounted) return;
|
||||
setState(() {});
|
||||
jumpToCurr();
|
||||
});
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
jumpToCurr();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void jumpToCurr() {
|
||||
const double itemWidth = 150; // 每个列表项的宽度
|
||||
final double targetOffset = (pageIndex * itemWidth - itemWidth / 2).clamp(
|
||||
_scrollController.position.minScrollExtent,
|
||||
_scrollController.position.maxScrollExtent);
|
||||
// 滑动至目标位置
|
||||
_scrollController.animateTo(
|
||||
targetOffset,
|
||||
duration: const Duration(milliseconds: 300), // 滑动动画持续时间
|
||||
curve: Curves.easeInOut, // 滑动动画曲线
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -73,46 +87,47 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8, bottom: 2),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('视频选集 '),
|
||||
Expanded(
|
||||
child: Text(
|
||||
' 正在播放:${pages[pageIndex].pagePart}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
SizedBox(
|
||||
height: 34,
|
||||
child: TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () => widget.showEpisodes(
|
||||
null,
|
||||
null,
|
||||
pages,
|
||||
widget.bvid,
|
||||
IdUtils.bv2av(widget.bvid),
|
||||
cid,
|
||||
),
|
||||
if (widget.showEpisodes != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8, bottom: 2),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('视频选集 '),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'共${pages.length}集',
|
||||
style: const TextStyle(fontSize: 13),
|
||||
' 正在播放:${pages[pageIndex].pagePart}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
SizedBox(
|
||||
height: 34,
|
||||
child: TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () => widget.showEpisodes!(
|
||||
null,
|
||||
null,
|
||||
pages,
|
||||
widget.bvid,
|
||||
IdUtils.bv2av(widget.bvid),
|
||||
cid,
|
||||
),
|
||||
child: Text(
|
||||
'共${pages.length}集',
|
||||
style: const TextStyle(fontSize: 13),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 35,
|
||||
child: ListView.builder(
|
||||
@@ -132,14 +147,17 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
onTap: () => {
|
||||
widget.changeFuc(
|
||||
onTap: () {
|
||||
if (widget.showEpisodes == null) {
|
||||
Get.back();
|
||||
}
|
||||
widget.videoIntroController.changeSeasonOrbangu(
|
||||
null,
|
||||
widget.bvid,
|
||||
pages[i].cid,
|
||||
IdUtils.bv2av(widget.bvid),
|
||||
null,
|
||||
)
|
||||
widget.cover,
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
@@ -160,10 +178,11 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
pages[i].pagePart!,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: isCurrentIndex
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onSurface),
|
||||
fontSize: 13,
|
||||
color: isCurrentIndex
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))
|
||||
],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@ import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/list_sheet.dart';
|
||||
import 'package:PiliPlus/common/widgets/episode_panel.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/main.dart';
|
||||
import 'package:PiliPlus/models/common/reply_type.dart';
|
||||
@@ -2075,18 +2075,23 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
heroTag: heroTag,
|
||||
videoIntroController: videoIntroController,
|
||||
bvid: videoIntroController.bvid,
|
||||
changeFuc: videoIntroController.changeSeasonOrbangu,
|
||||
showEpisodes: showEpisodes,
|
||||
),
|
||||
)
|
||||
else
|
||||
Expanded(
|
||||
child: Obx(
|
||||
() => ListSheetContent(
|
||||
episodes: videoIntroController.videoDetail.value.pages,
|
||||
() => EpisodePanel(
|
||||
heroTag: heroTag,
|
||||
videoIntroController: videoIntroController,
|
||||
type: EpisodeType.part,
|
||||
list: [videoIntroController.videoDetail.value.pages!],
|
||||
cover: videoDetailController.videoItem['pic'],
|
||||
bvid: videoDetailController.bvid,
|
||||
aid: IdUtils.bv2av(videoDetailController.bvid),
|
||||
currentCid: videoDetailController.cid.value,
|
||||
cid: videoDetailController.cid.value,
|
||||
// count: videoIntroController.videoDetail.value.pages!.length,
|
||||
// name: videoIntroController.videoDetail.value.pages!,
|
||||
isReversed:
|
||||
videoIntroController.videoDetail.value.isPageReversed,
|
||||
changeFucCall: videoDetailController.videoType ==
|
||||
@@ -2127,12 +2132,23 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
),
|
||||
Expanded(
|
||||
child: Obx(
|
||||
() => ListSheetContent(
|
||||
index: videoDetailController.seasonIndex.value,
|
||||
season: videoIntroController.videoDetail.value.ugcSeason,
|
||||
() => EpisodePanel(
|
||||
heroTag: heroTag,
|
||||
videoIntroController: videoIntroController,
|
||||
type: EpisodeType.season,
|
||||
initialTabIndex: videoDetailController.seasonIndex.value,
|
||||
cover: videoDetailController.videoItem['pic'],
|
||||
seasonId:
|
||||
videoIntroController.videoDetail.value.ugcSeason!.id,
|
||||
list: videoIntroController
|
||||
.videoDetail.value.ugcSeason!.sections!,
|
||||
// count: videoIntroController
|
||||
// .videoDetail.value.ugcSeason!.epCount!,
|
||||
// name:
|
||||
// videoIntroController.videoDetail.value.ugcSeason!.title!,
|
||||
bvid: videoDetailController.bvid,
|
||||
aid: IdUtils.bv2av(videoDetailController.bvid),
|
||||
currentCid: videoDetailController.seasonCid ?? 0,
|
||||
cid: videoDetailController.seasonCid ?? 0,
|
||||
isReversed:
|
||||
videoIntroController.videoDetail.value.isSeasonReversed,
|
||||
changeFucCall: videoDetailController.videoType ==
|
||||
@@ -2243,14 +2259,22 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
videoDetailController.showMediaListPanel(context);
|
||||
return;
|
||||
}
|
||||
Widget listSheetContent([bool? enableSlide]) => ListSheetContent(
|
||||
Widget listSheetContent([bool? enableSlide]) => EpisodePanel(
|
||||
heroTag: heroTag,
|
||||
videoIntroController: videoIntroController,
|
||||
type: season != null
|
||||
? EpisodeType.season
|
||||
: episodes is List<video.Part>
|
||||
? EpisodeType.part
|
||||
: EpisodeType.bangumi,
|
||||
cover: videoDetailController.videoItem['pic'],
|
||||
enableSlide: enableSlide,
|
||||
index: index,
|
||||
season: season,
|
||||
initialTabIndex: index ?? 0,
|
||||
bvid: bvid,
|
||||
aid: aid,
|
||||
currentCid: cid,
|
||||
episodes: episodes,
|
||||
cid: cid,
|
||||
seasonId: season?.id,
|
||||
list: season != null ? season.sections : [episodes],
|
||||
isReversed:
|
||||
videoDetailController.videoType == SearchType.media_bangumi
|
||||
? null
|
||||
|
||||
Reference in New Issue
Block a user