mod: 合集season数据解析
This commit is contained in:
@ -60,6 +60,7 @@ class VideoDetailData {
|
||||
List<Page>? pages;
|
||||
Subtitle? subtitle;
|
||||
// Label? label;
|
||||
UgcSeason? ugcSeason;
|
||||
bool? isSeasonDisplay;
|
||||
UserGarb? userGarb;
|
||||
HonorReply? honorReply;
|
||||
@ -94,6 +95,7 @@ class VideoDetailData {
|
||||
this.noCache,
|
||||
this.pages,
|
||||
this.subtitle,
|
||||
this.ugcSeason,
|
||||
this.isSeasonDisplay,
|
||||
this.userGarb,
|
||||
this.honorReply,
|
||||
@ -137,6 +139,9 @@ class VideoDetailData {
|
||||
: List<Page>.from(json["pages"]!.map((e) => Page.fromJson(e)));
|
||||
subtitle =
|
||||
json["subtitle"] == null ? null : Subtitle.fromJson(json["subtitle"]);
|
||||
ugcSeason = json["ugc_season"] != null
|
||||
? UgcSeason.fromJson(json["ugc_season"])
|
||||
: null;
|
||||
isSeasonDisplay = json["is_season_display"];
|
||||
userGarb =
|
||||
json["user_garb"] == null ? null : UserGarb.fromJson(json["user_garb"]);
|
||||
@ -522,3 +527,111 @@ class UserGarb {
|
||||
}
|
||||
|
||||
class Label {}
|
||||
|
||||
class UgcSeason {
|
||||
UgcSeason({
|
||||
this.id,
|
||||
this.title,
|
||||
this.cover,
|
||||
this.mid,
|
||||
this.intro,
|
||||
this.signState,
|
||||
this.attribute,
|
||||
this.sections,
|
||||
this.stat,
|
||||
this.epCount,
|
||||
this.seasonType,
|
||||
this.isPaySeason,
|
||||
});
|
||||
|
||||
int? id;
|
||||
String? title;
|
||||
String? cover;
|
||||
int? mid;
|
||||
String? intro;
|
||||
int? signState;
|
||||
int? attribute;
|
||||
List<SectionItem>? sections;
|
||||
Stat? stat;
|
||||
int? epCount;
|
||||
int? seasonType;
|
||||
bool? isPaySeason;
|
||||
|
||||
UgcSeason.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
title = json['title'];
|
||||
cover = json['cover'];
|
||||
mid = json['mid'];
|
||||
intro = json['intro'];
|
||||
signState = json['sign_state'];
|
||||
attribute = json['attribute'];
|
||||
sections = json['sections']
|
||||
.map<SectionItem>((e) => SectionItem.fromJson(e))
|
||||
.toList();
|
||||
stat = Stat.fromJson(json['stat']);
|
||||
epCount = json['ep_count'];
|
||||
seasonType = json['season_type'];
|
||||
isPaySeason = json['is_pay_count'];
|
||||
}
|
||||
}
|
||||
|
||||
class SectionItem {
|
||||
SectionItem({
|
||||
this.seasonId,
|
||||
this.id,
|
||||
this.title,
|
||||
this.type,
|
||||
this.episodes,
|
||||
});
|
||||
|
||||
int? seasonId;
|
||||
int? id;
|
||||
String? title;
|
||||
int? type;
|
||||
List<EpisodeItem>? episodes;
|
||||
|
||||
SectionItem.fromJson(Map<String, dynamic> json) {
|
||||
seasonId = json['season_id'];
|
||||
id = json['id'];
|
||||
title = json['title'];
|
||||
type = json['type'];
|
||||
episodes = json['episodes']
|
||||
.map<EpisodeItem>((e) => EpisodeItem.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
class EpisodeItem {
|
||||
EpisodeItem({
|
||||
this.seasonId,
|
||||
this.sectionId,
|
||||
this.id,
|
||||
this.aid,
|
||||
this.cid,
|
||||
this.title,
|
||||
this.attribute,
|
||||
this.page,
|
||||
this.bvid,
|
||||
});
|
||||
int? seasonId;
|
||||
int? sectionId;
|
||||
int? id;
|
||||
int? aid;
|
||||
int? cid;
|
||||
String? title;
|
||||
int? attribute;
|
||||
Page? page;
|
||||
String? bvid;
|
||||
|
||||
EpisodeItem.fromJson(Map<String, dynamic> json) {
|
||||
seasonId = json['season_id'];
|
||||
sectionId = json['sectionId'];
|
||||
id = json['id'];
|
||||
aid = json['aid'];
|
||||
cid = json['cid'];
|
||||
title = json['title'];
|
||||
attribute = json['attribute'];
|
||||
page = Page.fromJson(json['page']);
|
||||
bvid = json['bvid'];
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
@ -11,7 +12,10 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) {
|
||||
itemBuilder: (context, index) {
|
||||
var i = list![index];
|
||||
return InkWell(
|
||||
onTap: () {},
|
||||
onTap: () {
|
||||
Get.toNamed('/video?bvid=${i.bvid}&cid=${i.cid}',
|
||||
arguments: {'videoItem': i, 'heroTag': Utils.makeHeroTag(i.id)});
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
child: Row(
|
||||
|
@ -113,7 +113,6 @@ class VideoDetailController extends GetxController {
|
||||
|
||||
// 视频链接
|
||||
queryVideoUrl() async {
|
||||
print('🐶🐶🐶');
|
||||
var result = await VideoHttp.videoUrl(cid: cid, bvid: bvid);
|
||||
// log('result: ${result.toString()}');
|
||||
if (result['status']) {
|
||||
|
@ -76,7 +76,7 @@ class VideoIntroController extends GetxController {
|
||||
userLogin = user.get(UserBoxKey.userLogin) != null;
|
||||
}
|
||||
|
||||
// 获取视频简介
|
||||
// 获取视频简介&分p
|
||||
Future queryVideoIntro() async {
|
||||
var result = await VideoHttp.videoIntro(bvid: bvid);
|
||||
if (result['status']) {
|
||||
|
@ -16,6 +16,8 @@ import 'package:pilipala/pages/video/detail/introduction/controller.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
import 'widgets/season.dart';
|
||||
|
||||
class VideoIntroPanel extends StatefulWidget {
|
||||
const VideoIntroPanel({Key? key}) : super(key: key);
|
||||
|
||||
@ -342,7 +344,14 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// 点赞收藏转发
|
||||
_actionGrid(context, videoIntroController),
|
||||
// 合集
|
||||
if (!widget.loadingStatus &&
|
||||
widget.videoDetail!.ugcSeason != null) ...[
|
||||
seasonPanel(widget.videoDetail!.ugcSeason!,
|
||||
widget.videoDetail!.pages!.first.cid)
|
||||
],
|
||||
Divider(
|
||||
height: 26,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
|
99
lib/pages/video/detail/introduction/widgets/season.dart
Normal file
99
lib/pages/video/detail/introduction/widgets/season.dart
Normal file
@ -0,0 +1,99 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/models/video_detail_res.dart';
|
||||
|
||||
Widget seasonPanel(UgcSeason ugcSeason, cid) {
|
||||
return Builder(builder: (context) {
|
||||
List<EpisodeItem> episodes = ugcSeason.sections!.first.episodes!;
|
||||
int currentIndex = episodes.indexWhere((e) => e.cid == cid);
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(
|
||||
top: 15,
|
||||
left: 2,
|
||||
right: 2,
|
||||
),
|
||||
child: Material(
|
||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
onTap: () => showBottomSheet(
|
||||
context: context,
|
||||
builder: (_) => Container(
|
||||
height: Get.size.height - Get.size.width * 9 / 16 - 45,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 45,
|
||||
padding: const EdgeInsets.only(left: 14, right: 14),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'合集(${episodes.length})',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
child: ListView.builder(
|
||||
itemCount: episodes.length,
|
||||
itemBuilder: (context, index) {
|
||||
return InkWell(
|
||||
onTap: () {},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10, bottom: 10, left: 15, right: 15),
|
||||
child: Text(
|
||||
episodes[index].title!,
|
||||
style: TextStyle(
|
||||
color: index == currentIndex
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Text('合集:${ugcSeason.title!}'),
|
||||
const Spacer(),
|
||||
Text(
|
||||
'${currentIndex + 1} / ${ugcSeason.epCount}',
|
||||
style: Theme.of(context).textTheme.labelSmall,
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios_outlined,
|
||||
size: 13,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
@ -59,6 +59,10 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
setState(() {});
|
||||
Wakelock.disable();
|
||||
}
|
||||
// 播放完成停止 or 切换下一个
|
||||
if (status == PlayerStatus.completed) {
|
||||
_meeduPlayerController!.pause();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@ -67,8 +71,6 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
|
||||
_extendNestCtr.addListener(
|
||||
() {
|
||||
print(_extendNestCtr.position.pixels);
|
||||
|
||||
double offset = _extendNestCtr.position.pixels;
|
||||
if (offset > doubleOffset) {
|
||||
animationController.forward();
|
||||
|
Reference in New Issue
Block a user