opt: pagesList style
This commit is contained in:
@ -1,35 +1,249 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/constants.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/models/video_detail_res.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
import '../models/common/video_episode_type.dart';
|
||||
import 'widgets/badge.dart';
|
||||
import 'widgets/stat/danmu.dart';
|
||||
import 'widgets/stat/view.dart';
|
||||
|
||||
class EpisodeBottomSheet {
|
||||
final List<dynamic> episodes;
|
||||
final int currentCid;
|
||||
final dynamic dataType;
|
||||
final BuildContext context;
|
||||
final Function changeFucCall;
|
||||
final int? cid;
|
||||
final double? sheetHeight;
|
||||
bool isFullScreen = false;
|
||||
final UgcSeason? ugcSeason;
|
||||
|
||||
EpisodeBottomSheet({
|
||||
required this.episodes,
|
||||
required this.currentCid,
|
||||
required this.dataType,
|
||||
required this.context,
|
||||
required this.changeFucCall,
|
||||
this.cid,
|
||||
this.sheetHeight,
|
||||
this.isFullScreen = false,
|
||||
this.ugcSeason,
|
||||
});
|
||||
|
||||
Widget buildEpisodeListItem(
|
||||
dynamic episode,
|
||||
int index,
|
||||
bool isCurrentIndex,
|
||||
) {
|
||||
Widget buildShowContent() {
|
||||
return PagesBottomSheet(
|
||||
episodes: episodes,
|
||||
currentCid: currentCid,
|
||||
dataType: dataType,
|
||||
changeFucCall: changeFucCall,
|
||||
cid: cid,
|
||||
sheetHeight: sheetHeight,
|
||||
isFullScreen: isFullScreen,
|
||||
ugcSeason: ugcSeason,
|
||||
);
|
||||
}
|
||||
|
||||
PersistentBottomSheetController show(BuildContext context) {
|
||||
final PersistentBottomSheetController btmSheetCtr = showBottomSheet(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return buildShowContent();
|
||||
},
|
||||
);
|
||||
return btmSheetCtr;
|
||||
}
|
||||
}
|
||||
|
||||
class PagesBottomSheet extends StatefulWidget {
|
||||
const PagesBottomSheet({
|
||||
super.key,
|
||||
required this.episodes,
|
||||
required this.currentCid,
|
||||
required this.dataType,
|
||||
required this.changeFucCall,
|
||||
this.cid,
|
||||
this.sheetHeight,
|
||||
this.isFullScreen = false,
|
||||
this.ugcSeason,
|
||||
});
|
||||
|
||||
final List<dynamic> episodes;
|
||||
final int currentCid;
|
||||
final dynamic dataType;
|
||||
final Function changeFucCall;
|
||||
final int? cid;
|
||||
final double? sheetHeight;
|
||||
final bool isFullScreen;
|
||||
final UgcSeason? ugcSeason;
|
||||
|
||||
@override
|
||||
State<PagesBottomSheet> createState() => _PagesBottomSheetState();
|
||||
}
|
||||
|
||||
class _PagesBottomSheetState extends State<PagesBottomSheet> {
|
||||
final ItemScrollController _itemScrollController = ItemScrollController();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
late int currentIndex;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
currentIndex =
|
||||
widget.episodes.indexWhere((dynamic e) => e.cid == widget.currentCid);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (widget.dataType == VideoEpidoesType.videoEpisode) {
|
||||
_itemScrollController.jumpTo(index: currentIndex);
|
||||
} else {
|
||||
double itemHeight = (widget.isFullScreen
|
||||
? 400
|
||||
: Get.size.width - 3 * StyleString.safeSpace) /
|
||||
5.2;
|
||||
double offset = ((currentIndex - 1) / 2).ceil() * itemHeight;
|
||||
_scrollController.jumpTo(offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String prefix() {
|
||||
switch (widget.dataType) {
|
||||
case VideoEpidoesType.videoEpisode:
|
||||
return '选集';
|
||||
case VideoEpidoesType.videoPart:
|
||||
return '分集';
|
||||
case VideoEpidoesType.bangumiEpisode:
|
||||
return '选集';
|
||||
}
|
||||
return '选集';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SizedBox(
|
||||
height: widget.sheetHeight,
|
||||
child: Column(
|
||||
children: [
|
||||
TitleBar(
|
||||
title: '${prefix()}(${widget.episodes.length})',
|
||||
isFullScreen: widget.isFullScreen,
|
||||
),
|
||||
if (widget.ugcSeason != null) ...[
|
||||
UgcSeasonBuild(ugcSeason: widget.ugcSeason!),
|
||||
],
|
||||
Expanded(
|
||||
child: Material(
|
||||
child: widget.dataType == VideoEpidoesType.videoEpisode
|
||||
? ScrollablePositionedList.builder(
|
||||
itemScrollController: _itemScrollController,
|
||||
itemCount: widget.episodes.length + 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
bool isLastItem = index == widget.episodes.length;
|
||||
bool isCurrentIndex = currentIndex == index;
|
||||
return isLastItem
|
||||
? SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).padding.bottom +
|
||||
20,
|
||||
)
|
||||
: EpisodeListItem(
|
||||
episode: widget.episodes[index],
|
||||
index: index,
|
||||
isCurrentIndex: isCurrentIndex,
|
||||
dataType: widget.dataType,
|
||||
changeFucCall: widget.changeFucCall,
|
||||
isFullScreen: widget.isFullScreen,
|
||||
);
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0), // 设置左右间距为12
|
||||
child: GridView.count(
|
||||
controller: _scrollController,
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: StyleString.safeSpace,
|
||||
childAspectRatio: 2.6,
|
||||
children: List.generate(
|
||||
widget.episodes.length,
|
||||
(index) {
|
||||
bool isCurrentIndex = currentIndex == index;
|
||||
return EpisodeGridItem(
|
||||
episode: widget.episodes[index],
|
||||
index: index,
|
||||
isCurrentIndex: isCurrentIndex,
|
||||
dataType: widget.dataType,
|
||||
changeFucCall: widget.changeFucCall,
|
||||
isFullScreen: widget.isFullScreen,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class TitleBar extends StatelessWidget {
|
||||
final String title;
|
||||
final bool isFullScreen;
|
||||
|
||||
const TitleBar({
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.isFullScreen,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppBar(
|
||||
toolbarHeight: 45,
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: false,
|
||||
title: Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
actions: !isFullScreen
|
||||
? [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, size: 20),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
]
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EpisodeListItem extends StatelessWidget {
|
||||
final dynamic episode;
|
||||
final int index;
|
||||
final bool isCurrentIndex;
|
||||
final dynamic dataType;
|
||||
final Function changeFucCall;
|
||||
final bool isFullScreen;
|
||||
|
||||
const EpisodeListItem({
|
||||
Key? key,
|
||||
required this.episode,
|
||||
required this.index,
|
||||
required this.isCurrentIndex,
|
||||
required this.dataType,
|
||||
required this.changeFucCall,
|
||||
required this.isFullScreen,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color primary = Theme.of(context).colorScheme.primary;
|
||||
Color onSurface = Theme.of(context).colorScheme.onSurface;
|
||||
|
||||
@ -45,9 +259,19 @@ class EpisodeBottomSheet {
|
||||
title = '第${episode.title}话 ${episode.longTitle!}';
|
||||
break;
|
||||
}
|
||||
|
||||
return isFullScreen || episode?.cover == null || episode?.cover == ''
|
||||
? ListTile(
|
||||
? _buildListTile(context, title, primary, onSurface)
|
||||
: _buildInkWell(context, title, primary, onSurface);
|
||||
}
|
||||
|
||||
Widget _buildListTile(
|
||||
BuildContext context, String title, Color primary, Color onSurface) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
if (isCurrentIndex) {
|
||||
return;
|
||||
}
|
||||
SmartDialog.showToast('切换至「$title」');
|
||||
changeFucCall.call(episode, index);
|
||||
},
|
||||
@ -59,114 +283,284 @@ class EpisodeBottomSheet {
|
||||
height: 12,
|
||||
)
|
||||
: null,
|
||||
title: Text(title,
|
||||
title: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isCurrentIndex ? primary : onSurface,
|
||||
)))
|
||||
: InkWell(
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInkWell(
|
||||
BuildContext context, String title, Color primary, Color onSurface) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
if (isCurrentIndex) {
|
||||
return;
|
||||
}
|
||||
SmartDialog.showToast('切换至「$title」');
|
||||
changeFucCall.call(episode, index);
|
||||
},
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 14, right: 14, top: 8, bottom: 8),
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
StyleString.safeSpace, 6, StyleString.safeSpace, 6),
|
||||
child: LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints boxConstraints) {
|
||||
const double width = 160;
|
||||
return Container(
|
||||
constraints: const BoxConstraints(minHeight: 88),
|
||||
height: width / StyleString.aspectRatio,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(
|
||||
builder: (BuildContext context,
|
||||
BoxConstraints boxConstraints) {
|
||||
final double maxWidth = boxConstraints.maxWidth;
|
||||
final double maxHeight = boxConstraints.maxHeight;
|
||||
return Stack(
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
width: 130, height: 75, src: episode?.cover ?? ''),
|
||||
const SizedBox(width: 10),
|
||||
src: episode?.cover ?? '',
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
),
|
||||
if (episode.duration != 0)
|
||||
PBadge(
|
||||
text: Utils.timeFormat(episode.duration!),
|
||||
right: 6.0,
|
||||
bottom: 6.0,
|
||||
type: 'gray',
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(10, 2, 6, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
episode.title as String,
|
||||
textAlign: TextAlign.start,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: isCurrentIndex ? primary : onSurface,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
if (dataType != VideoEpidoesType.videoPart) ...[
|
||||
if (episode?.pubdate != null ||
|
||||
episode.pubTime != null)
|
||||
Text(
|
||||
Utils.dateFormat(
|
||||
episode?.pubdate ?? episode.pubTime),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTitle() {
|
||||
return AppBar(
|
||||
toolbarHeight: 45,
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: false,
|
||||
title: Text(
|
||||
'合集(${episodes.length})',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
actions: !isFullScreen
|
||||
? [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, size: 20),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
]
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildShowContent(BuildContext context) {
|
||||
final ItemScrollController itemScrollController = ItemScrollController();
|
||||
int currentIndex = episodes.indexWhere((dynamic e) => e.cid == currentCid);
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
itemScrollController.jumpTo(index: currentIndex);
|
||||
});
|
||||
return Container(
|
||||
height: sheetHeight,
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Column(
|
||||
const SizedBox(height: 2),
|
||||
if (episode.stat != null)
|
||||
Row(
|
||||
children: [
|
||||
buildTitle(),
|
||||
Expanded(
|
||||
child: Material(
|
||||
child: PageStorage(
|
||||
bucket: PageStorageBucket(),
|
||||
child: ScrollablePositionedList.builder(
|
||||
itemScrollController: itemScrollController,
|
||||
itemCount: episodes.length + 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
bool isLastItem = index == episodes.length;
|
||||
bool isCurrentIndex = currentIndex == index;
|
||||
return isLastItem
|
||||
? SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).padding.bottom + 20,
|
||||
StatView(view: episode.stat.view),
|
||||
const SizedBox(width: 8),
|
||||
StatDanMu(danmu: episode.stat.danmaku),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: buildEpisodeListItem(
|
||||
episodes[index],
|
||||
index,
|
||||
isCurrentIndex,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// The [BuildContext] of the widget that calls the bottom sheet.
|
||||
PersistentBottomSheetController show(BuildContext context) {
|
||||
final PersistentBottomSheetController btmSheetCtr = showBottomSheet(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return buildShowContent(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EpisodeGridItem extends StatelessWidget {
|
||||
final dynamic episode;
|
||||
final int index;
|
||||
final bool isCurrentIndex;
|
||||
final dynamic dataType;
|
||||
final Function changeFucCall;
|
||||
final bool isFullScreen;
|
||||
|
||||
const EpisodeGridItem({
|
||||
Key? key,
|
||||
required this.episode,
|
||||
required this.index,
|
||||
required this.isCurrentIndex,
|
||||
required this.dataType,
|
||||
required this.changeFucCall,
|
||||
required this.isFullScreen,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ColorScheme colorScheme = Theme.of(context).colorScheme;
|
||||
TextStyle textStyle = TextStyle(
|
||||
color: isCurrentIndex ? colorScheme.primary : colorScheme.onSurface,
|
||||
fontSize: 14,
|
||||
);
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.only(top: StyleString.safeSpace),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: BoxDecoration(
|
||||
color: isCurrentIndex
|
||||
? colorScheme.primaryContainer.withOpacity(0.6)
|
||||
: colorScheme.secondaryContainer.withOpacity(0.4),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: isCurrentIndex
|
||||
? colorScheme.primary.withOpacity(0.8)
|
||||
: Colors.transparent,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
onTap: () {
|
||||
if (isCurrentIndex) {
|
||||
return;
|
||||
}
|
||||
SmartDialog.showToast('切换至「${episode.title}」');
|
||||
changeFucCall.call(episode, index);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text(
|
||||
dataType == VideoEpidoesType.bangumiEpisode
|
||||
? '第${index + 1}话'
|
||||
: '第${index + 1}p',
|
||||
style: textStyle),
|
||||
const SizedBox(height: 1),
|
||||
Text(
|
||||
episode.title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: textStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (dataType == VideoEpidoesType.bangumiEpisode &&
|
||||
episode.badge != '' &&
|
||||
episode.badge != null)
|
||||
Positioned(
|
||||
right: 8,
|
||||
top: 18,
|
||||
child: Text(
|
||||
episode.badge,
|
||||
style: const TextStyle(fontSize: 11, color: Color(0xFFFF6699)),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UgcSeasonBuild extends StatelessWidget {
|
||||
final UgcSeason ugcSeason;
|
||||
|
||||
const UgcSeasonBuild({
|
||||
Key? key,
|
||||
required this.ugcSeason,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(12, 0, 12, 8),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Divider(
|
||||
height: 1,
|
||||
thickness: 1,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'合集:${ugcSeason.title}',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
if (ugcSeason.intro != null && ugcSeason.intro != '') ...[
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(ugcSeason.intro ?? '',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.outline)),
|
||||
),
|
||||
// SizedBox(
|
||||
// height: 32,
|
||||
// child: FilledButton.tonal(
|
||||
// onPressed: () {},
|
||||
// style: ButtonStyle(
|
||||
// padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
// ),
|
||||
// child: const Text('订阅'),
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(width: 6),
|
||||
],
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: '${Utils.numFormat(ugcSeason.stat!.view)}播放'),
|
||||
const TextSpan(text: ' · '),
|
||||
TextSpan(text: '${Utils.numFormat(ugcSeason.stat!.danmaku)}弹幕'),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Divider(
|
||||
height: 1,
|
||||
thickness: 1,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
return btmSheetCtr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,6 +144,7 @@ class EpisodeItem {
|
||||
this.link,
|
||||
this.longTitle,
|
||||
this.pubTime,
|
||||
this.pubdate,
|
||||
this.pv,
|
||||
this.releaseDate,
|
||||
this.rights,
|
||||
@ -155,6 +156,7 @@ class EpisodeItem {
|
||||
this.subtitle,
|
||||
this.title,
|
||||
this.vid,
|
||||
this.stat,
|
||||
});
|
||||
|
||||
int? aid;
|
||||
@ -173,6 +175,7 @@ class EpisodeItem {
|
||||
String? link;
|
||||
String? longTitle;
|
||||
int? pubTime;
|
||||
int? pubdate;
|
||||
int? pv;
|
||||
String? releaseDate;
|
||||
Map? rights;
|
||||
@ -184,6 +187,7 @@ class EpisodeItem {
|
||||
String? subtitle;
|
||||
String? title;
|
||||
String? vid;
|
||||
String? stat;
|
||||
|
||||
EpisodeItem.fromJson(Map<String, dynamic> json) {
|
||||
aid = json['aid'];
|
||||
@ -202,6 +206,7 @@ class EpisodeItem {
|
||||
link = json['link'];
|
||||
longTitle = json['long_title'];
|
||||
pubTime = json['pub_time'];
|
||||
pubdate = json['pub_time'];
|
||||
pv = json['pv'];
|
||||
releaseDate = json['release_date'];
|
||||
rights = json['rights'];
|
||||
@ -211,7 +216,7 @@ class EpisodeItem {
|
||||
skip = json['skip'];
|
||||
status = json['status'];
|
||||
subtitle = json['subtitle'];
|
||||
title = json['title'];
|
||||
title = json['long_title'];
|
||||
vid = json['vid'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,6 +377,7 @@ class Part {
|
||||
int? page;
|
||||
String? from;
|
||||
String? pagePart;
|
||||
String? title;
|
||||
int? duration;
|
||||
String? vid;
|
||||
String? weblink;
|
||||
@ -389,6 +390,7 @@ class Part {
|
||||
this.page,
|
||||
this.from,
|
||||
this.pagePart,
|
||||
this.title,
|
||||
this.duration,
|
||||
this.vid,
|
||||
this.weblink,
|
||||
@ -406,6 +408,7 @@ class Part {
|
||||
page = json["page"];
|
||||
from = json["from"];
|
||||
pagePart = json["part"];
|
||||
title = json["part"];
|
||||
duration = json["duration"];
|
||||
vid = json["vid"];
|
||||
weblink = json["weblink"];
|
||||
@ -649,6 +652,9 @@ class EpisodeItem {
|
||||
Part? page;
|
||||
String? bvid;
|
||||
String? cover;
|
||||
int? pubdate;
|
||||
int? duration;
|
||||
Stat? stat;
|
||||
|
||||
EpisodeItem.fromJson(Map<String, dynamic> json) {
|
||||
seasonId = json['season_id'];
|
||||
@ -661,6 +667,9 @@ class EpisodeItem {
|
||||
page = Part.fromJson(json['page']);
|
||||
bvid = json['bvid'];
|
||||
cover = json['arc']['pic'];
|
||||
pubdate = json['arc']['pubdate'];
|
||||
duration = json['arc']['duration'];
|
||||
stat = Stat.fromJson(json['arc']['stat']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -302,14 +302,13 @@ class BangumiIntroController extends GetxController {
|
||||
episodes: episodes,
|
||||
currentCid: videoDetailCtr.cid.value,
|
||||
dataType: dataType,
|
||||
context: Get.context!,
|
||||
sheetHeight: Get.size.height,
|
||||
isFullScreen: true,
|
||||
changeFucCall: (item, index) {
|
||||
changeSeasonOrbangu(item.bvid, item.cid, item.aid, item.cover);
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
).buildShowContent(Get.context!),
|
||||
).buildShowContent(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -151,7 +151,6 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
||||
changeFucCall: changeFucCall,
|
||||
sheetHeight: widget.sheetHeight,
|
||||
dataType: VideoEpidoesType.bangumiEpisode,
|
||||
context: context,
|
||||
).show(context);
|
||||
},
|
||||
child: Text(
|
||||
|
||||
@ -62,6 +62,7 @@ class VideoIntroController extends GetxController {
|
||||
late ModelResult modelResult;
|
||||
PersistentBottomSheetController? bottomSheetController;
|
||||
late bool enableRelatedVideo;
|
||||
UgcSeason? ugcSeason;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
@ -87,6 +88,7 @@ class VideoIntroController extends GetxController {
|
||||
var result = await VideoHttp.videoIntro(bvid: bvid);
|
||||
if (result['status']) {
|
||||
videoDetail.value = result['data']!;
|
||||
ugcSeason = result['data']!.ugcSeason;
|
||||
if (videoDetail.value.pages!.isNotEmpty && lastPlayCid.value == 0) {
|
||||
lastPlayCid.value = videoDetail.value.pages!.first.cid!;
|
||||
}
|
||||
@ -608,9 +610,9 @@ class VideoIntroController extends GetxController {
|
||||
episodes: episodes,
|
||||
currentCid: lastPlayCid.value,
|
||||
dataType: dataType,
|
||||
context: Get.context!,
|
||||
sheetHeight: Get.size.height,
|
||||
isFullScreen: true,
|
||||
ugcSeason: ugcSeason,
|
||||
changeFucCall: (item, index) {
|
||||
if (dataType == VideoEpidoesType.videoEpisode) {
|
||||
changeSeasonOrbangu(
|
||||
@ -621,7 +623,7 @@ class VideoIntroController extends GetxController {
|
||||
}
|
||||
SmartDialog.dismiss();
|
||||
},
|
||||
).buildShowContent(Get.context!),
|
||||
).buildShowContent(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -116,7 +116,6 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
changeFucCall: changeFucCall,
|
||||
sheetHeight: widget.sheetHeight,
|
||||
dataType: VideoEpidoesType.videoPart,
|
||||
context: context,
|
||||
).show(context);
|
||||
},
|
||||
child: Text(
|
||||
|
||||
@ -124,7 +124,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
changeFucCall: changeFucCall,
|
||||
sheetHeight: widget.sheetHeight,
|
||||
dataType: VideoEpidoesType.videoEpisode,
|
||||
context: context,
|
||||
ugcSeason: widget.ugcSeason,
|
||||
).show(context);
|
||||
},
|
||||
child: Padding(
|
||||
|
||||
Reference in New Issue
Block a user