mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-18 16:16:14 +08:00
refa: pgc intro
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -3,13 +3,10 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:PiliPlus/http/constants.dart';
|
import 'package:PiliPlus/http/constants.dart';
|
||||||
import 'package:PiliPlus/http/init.dart';
|
import 'package:PiliPlus/http/init.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
|
||||||
import 'package:PiliPlus/http/search.dart';
|
|
||||||
import 'package:PiliPlus/http/user.dart';
|
import 'package:PiliPlus/http/user.dart';
|
||||||
import 'package:PiliPlus/http/video.dart';
|
import 'package:PiliPlus/http/video.dart';
|
||||||
import 'package:PiliPlus/models/bangumi/info.dart';
|
import 'package:PiliPlus/models/bangumi/info.dart';
|
||||||
import 'package:PiliPlus/models/user/fav_folder.dart';
|
import 'package:PiliPlus/models/user/fav_folder.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_data_controller.dart';
|
|
||||||
import 'package:PiliPlus/pages/dynamics_repost/view.dart';
|
import 'package:PiliPlus/pages/dynamics_repost/view.dart';
|
||||||
import 'package:PiliPlus/pages/video/controller.dart';
|
import 'package:PiliPlus/pages/video/controller.dart';
|
||||||
import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart';
|
import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart';
|
||||||
@@ -28,8 +25,7 @@ import 'package:get/get.dart';
|
|||||||
import 'package:html/dom.dart' as dom;
|
import 'package:html/dom.dart' as dom;
|
||||||
import 'package:html/parser.dart' as html_parser;
|
import 'package:html/parser.dart' as html_parser;
|
||||||
|
|
||||||
class BangumiIntroController
|
class BangumiIntroController extends GetxController {
|
||||||
extends CommonDataController<BangumiInfoModel, BangumiInfoModel> {
|
|
||||||
// 视频bvid
|
// 视频bvid
|
||||||
String bvid = Get.parameters['bvid'] ?? '';
|
String bvid = Get.parameters['bvid'] ?? '';
|
||||||
var seasonId = Get.parameters['seasonId'] != null
|
var seasonId = Get.parameters['seasonId'] != null
|
||||||
@@ -44,15 +40,7 @@ class BangumiIntroController
|
|||||||
? '追番'
|
? '追番'
|
||||||
: '追剧';
|
: '追剧';
|
||||||
|
|
||||||
// 是否预渲染 骨架屏
|
BangumiInfoModel bangumiItem = Get.arguments['bangumiItem'];
|
||||||
bool preRender = false;
|
|
||||||
|
|
||||||
// 视频详情 上个页面传入
|
|
||||||
Map? videoItem = {};
|
|
||||||
BangumiInfoModel? bangumiItem;
|
|
||||||
|
|
||||||
// up主粉丝数
|
|
||||||
Map userStat = {'follower': '-'};
|
|
||||||
|
|
||||||
// 是否点赞
|
// 是否点赞
|
||||||
RxBool hasLike = false.obs;
|
RxBool hasLike = false.obs;
|
||||||
@@ -62,11 +50,14 @@ class BangumiIntroController
|
|||||||
bool get hasCoin => _coinNum.value != 0;
|
bool get hasCoin => _coinNum.value != 0;
|
||||||
// 是否收藏
|
// 是否收藏
|
||||||
RxBool hasFav = false.obs;
|
RxBool hasFav = false.obs;
|
||||||
|
|
||||||
dynamic videoTags;
|
dynamic videoTags;
|
||||||
bool isLogin = false;
|
|
||||||
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
|
||||||
List? favIds;
|
List? favIds;
|
||||||
dynamic userInfo;
|
Rx<FavFolderData> favFolderData = FavFolderData().obs;
|
||||||
|
|
||||||
|
bool isLogin = Accounts.main.isLogin;
|
||||||
|
int mid = Accounts.main.mid;
|
||||||
|
|
||||||
late final enableQuickFav =
|
late final enableQuickFav =
|
||||||
GStorage.setting.get(SettingBoxKey.enableQuickFav, defaultValue: false);
|
GStorage.setting.get(SettingBoxKey.enableQuickFav, defaultValue: false);
|
||||||
@@ -74,30 +65,15 @@ class BangumiIntroController
|
|||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
if (Get.arguments.isNotEmpty as bool) {
|
if (isLogin) {
|
||||||
if (Get.arguments.containsKey('bangumiItem') as bool) {
|
if (seasonId != null) {
|
||||||
preRender = true;
|
queryIsFollowed();
|
||||||
bangumiItem = Get.arguments['bangumiItem'];
|
}
|
||||||
|
if (epId != null) {
|
||||||
|
queryBangumiLikeCoinFav();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
userInfo = GStorage.userInfo.get('userInfoCache');
|
queryVideoTags();
|
||||||
isLogin = userInfo != null;
|
|
||||||
|
|
||||||
if (isLogin && epId != null) {
|
|
||||||
queryBangumiLikeCoinFav();
|
|
||||||
}
|
|
||||||
|
|
||||||
queryData();
|
|
||||||
|
|
||||||
if (isLogin && seasonId != null) {
|
|
||||||
queryIsFollowed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> queryData([bool isRefresh = true]) async {
|
|
||||||
await queryVideoTags();
|
|
||||||
return super.queryData(isRefresh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> queryVideoTags() async {
|
Future<void> queryVideoTags() async {
|
||||||
@@ -107,18 +83,6 @@ class BangumiIntroController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
bool customHandleResponse(
|
|
||||||
bool isRefresh, Success<BangumiInfoModel> response) {
|
|
||||||
epId ??= response.response.episodes?.firstOrNull?.id;
|
|
||||||
loadingState.value = response;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<LoadingState<BangumiInfoModel>> customGetData() =>
|
|
||||||
SearchHttp.bangumiInfoNew(seasonId: seasonId, epId: epId);
|
|
||||||
|
|
||||||
// 获取点赞/投币/收藏状态
|
// 获取点赞/投币/收藏状态
|
||||||
Future<void> queryBangumiLikeCoinFav() async {
|
Future<void> queryBangumiLikeCoinFav() async {
|
||||||
var result = await VideoHttp.bangumiLikeCoinFav(epId: epId);
|
var result = await VideoHttp.bangumiLikeCoinFav(epId: epId);
|
||||||
@@ -136,9 +100,8 @@ class BangumiIntroController
|
|||||||
var result = await VideoHttp.likeVideo(bvid: bvid, type: !hasLike.value);
|
var result = await VideoHttp.likeVideo(bvid: bvid, type: !hasLike.value);
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
SmartDialog.showToast(!hasLike.value ? result['data']['toast'] : '取消赞');
|
SmartDialog.showToast(!hasLike.value ? result['data']['toast'] : '取消赞');
|
||||||
BangumiInfoModel bangumiDetail = (loadingState.value as Success).response;
|
bangumiItem.stat!['likes'] =
|
||||||
bangumiDetail.stat!['likes'] =
|
bangumiItem.stat!['likes'] + (!hasLike.value ? 1 : -1);
|
||||||
bangumiDetail.stat!['likes'] + (!hasLike.value ? 1 : -1);
|
|
||||||
hasLike.value = !hasLike.value;
|
hasLike.value = !hasLike.value;
|
||||||
} else {
|
} else {
|
||||||
SmartDialog.showToast(result['msg']);
|
SmartDialog.showToast(result['msg']);
|
||||||
@@ -153,11 +116,10 @@ class BangumiIntroController
|
|||||||
);
|
);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
SmartDialog.showToast('投币成功');
|
SmartDialog.showToast('投币成功');
|
||||||
BangumiInfoModel bangumiDetail = (loadingState.value as Success).response;
|
bangumiItem.stat!['coins'] = bangumiItem.stat!['coins'] + coin;
|
||||||
bangumiDetail.stat!['coins'] = bangumiDetail.stat!['coins'] + coin;
|
|
||||||
if (selectLike && hasLike.value.not) {
|
if (selectLike && hasLike.value.not) {
|
||||||
hasLike.value = true;
|
hasLike.value = true;
|
||||||
bangumiDetail.stat!['likes'] = bangumiDetail.stat!['likes'] + 1;
|
bangumiItem.stat!['likes'] = bangumiItem.stat!['likes'] + 1;
|
||||||
}
|
}
|
||||||
_coinNum.value += coin;
|
_coinNum.value += coin;
|
||||||
GlobalData().afterCoin(coin);
|
GlobalData().afterCoin(coin);
|
||||||
@@ -168,7 +130,7 @@ class BangumiIntroController
|
|||||||
|
|
||||||
// 投币
|
// 投币
|
||||||
Future<void> actionCoinVideo() async {
|
Future<void> actionCoinVideo() async {
|
||||||
if (userInfo == null) {
|
if (!isLogin) {
|
||||||
SmartDialog.showToast('账号未登录');
|
SmartDialog.showToast('账号未登录');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -306,7 +268,7 @@ class BangumiIntroController
|
|||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Get.back();
|
Get.back();
|
||||||
EpisodeItem? item = bangumiItem?.episodes
|
EpisodeItem? item = bangumiItem.episodes
|
||||||
?.firstWhereOrNull((item) => item.epId == epId);
|
?.firstWhereOrNull((item) => item.epId == epId);
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -331,9 +293,9 @@ class BangumiIntroController
|
|||||||
'5' || '7' => 4099,
|
'5' || '7' => 4099,
|
||||||
_ => -1,
|
_ => -1,
|
||||||
},
|
},
|
||||||
pic: bangumiItem?.cover,
|
pic: bangumiItem.cover,
|
||||||
title:
|
title:
|
||||||
'${bangumiItem?.title}${item != null ? '\n${item.showTitle}' : ''}',
|
'${bangumiItem.title}${item != null ? '\n${item.showTitle}' : ''}',
|
||||||
uname: '',
|
uname: '',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -348,9 +310,9 @@ class BangumiIntroController
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
Get.back();
|
Get.back();
|
||||||
try {
|
try {
|
||||||
EpisodeItem item = bangumiItem!.episodes!
|
EpisodeItem item = bangumiItem.episodes!
|
||||||
.firstWhere((item) => item.epId == epId);
|
.firstWhere((item) => item.epId == epId);
|
||||||
final title = '${bangumiItem!.title!} ${item.showTitle}';
|
final title = '${bangumiItem.title!} ${item.showTitle}';
|
||||||
PageUtils.pmShare(
|
PageUtils.pmShare(
|
||||||
context,
|
context,
|
||||||
content: {
|
content: {
|
||||||
@@ -360,7 +322,7 @@ class BangumiIntroController
|
|||||||
"headline": title,
|
"headline": title,
|
||||||
"source": 16,
|
"source": 16,
|
||||||
"thumb": item.cover,
|
"thumb": item.cover,
|
||||||
"source_desc": switch (bangumiItem!.type) {
|
"source_desc": switch (bangumiItem.type) {
|
||||||
1 => '番剧',
|
1 => '番剧',
|
||||||
2 => '电影',
|
2 => '电影',
|
||||||
3 => '纪录片',
|
3 => '纪录片',
|
||||||
@@ -439,8 +401,7 @@ class BangumiIntroController
|
|||||||
|
|
||||||
// 追番
|
// 追番
|
||||||
Future<void> bangumiAdd() async {
|
Future<void> bangumiAdd() async {
|
||||||
var result = await VideoHttp.bangumiAdd(
|
var result = await VideoHttp.bangumiAdd(seasonId: bangumiItem.seasonId);
|
||||||
seasonId: (loadingState.value as Success).response.seasonId);
|
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
isFollowed.value = true;
|
isFollowed.value = true;
|
||||||
followStatus.value = 2;
|
followStatus.value = 2;
|
||||||
@@ -450,8 +411,7 @@ class BangumiIntroController
|
|||||||
|
|
||||||
// 取消追番
|
// 取消追番
|
||||||
Future<void> bangumiDel() async {
|
Future<void> bangumiDel() async {
|
||||||
var result = await VideoHttp.bangumiDel(
|
var result = await VideoHttp.bangumiDel(seasonId: bangumiItem.seasonId);
|
||||||
seasonId: (loadingState.value as Success).response.seasonId);
|
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
isFollowed.value = false;
|
isFollowed.value = false;
|
||||||
}
|
}
|
||||||
@@ -460,7 +420,7 @@ class BangumiIntroController
|
|||||||
|
|
||||||
Future<void> bangumiUpdate(status) async {
|
Future<void> bangumiUpdate(status) async {
|
||||||
var result = await VideoHttp.bangumiUpdate(
|
var result = await VideoHttp.bangumiUpdate(
|
||||||
seasonId: [(loadingState.value as Success).response.seasonId],
|
seasonId: [bangumiItem.seasonId],
|
||||||
status: status,
|
status: status,
|
||||||
);
|
);
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
@@ -472,7 +432,7 @@ class BangumiIntroController
|
|||||||
Future queryVideoInFolder() async {
|
Future queryVideoInFolder() async {
|
||||||
favIds = null;
|
favIds = null;
|
||||||
var result = await VideoHttp.videoInFolder(
|
var result = await VideoHttp.videoInFolder(
|
||||||
mid: userInfo.mid,
|
mid: mid,
|
||||||
rid: epId, // bangumi
|
rid: epId, // bangumi
|
||||||
type: 24, // bangumi
|
type: 24, // bangumi
|
||||||
);
|
);
|
||||||
@@ -487,10 +447,7 @@ class BangumiIntroController
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool prevPlay() {
|
bool prevPlay() {
|
||||||
late List episodes;
|
List episodes = bangumiItem.episodes!;
|
||||||
if ((loadingState.value as Success).response.episodes != null) {
|
|
||||||
episodes = (loadingState.value as Success).response.episodes!;
|
|
||||||
}
|
|
||||||
VideoDetailController videoDetailCtr =
|
VideoDetailController videoDetailCtr =
|
||||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
||||||
int currentIndex =
|
int currentIndex =
|
||||||
@@ -516,21 +473,11 @@ class BangumiIntroController
|
|||||||
/// 列表循环或者顺序播放时,自动播放下一个;自动连播时,播放相关视频
|
/// 列表循环或者顺序播放时,自动播放下一个;自动连播时,播放相关视频
|
||||||
bool nextPlay() {
|
bool nextPlay() {
|
||||||
try {
|
try {
|
||||||
late List episodes;
|
List episodes = bangumiItem.episodes!;
|
||||||
VideoDetailController videoDetailCtr =
|
VideoDetailController videoDetailCtr =
|
||||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
||||||
PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
||||||
|
|
||||||
if ((loadingState.value as Success<BangumiInfoModel>).response.episodes !=
|
|
||||||
null) {
|
|
||||||
episodes = (loadingState.value as Success<BangumiInfoModel>)
|
|
||||||
.response
|
|
||||||
.episodes!;
|
|
||||||
} else {
|
|
||||||
if (playRepeat == PlayRepeat.autoPlayRelated) {
|
|
||||||
return playRelated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int currentIndex =
|
int currentIndex =
|
||||||
episodes.indexWhere((e) => e.cid == videoDetailCtr.cid.value);
|
episodes.indexWhere((e) => e.cid == videoDetailCtr.cid.value);
|
||||||
int nextIndex = currentIndex + 1;
|
int nextIndex = currentIndex + 1;
|
||||||
@@ -539,7 +486,7 @@ class BangumiIntroController
|
|||||||
if (playRepeat == PlayRepeat.listCycle) {
|
if (playRepeat == PlayRepeat.listCycle) {
|
||||||
nextIndex = 0;
|
nextIndex = 0;
|
||||||
} else if (playRepeat == PlayRepeat.autoPlayRelated) {
|
} else if (playRepeat == PlayRepeat.autoPlayRelated) {
|
||||||
return playRelated();
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -556,15 +503,10 @@ class BangumiIntroController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool playRelated() {
|
|
||||||
SmartDialog.showToast('番剧暂无相关视频');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 一键三连
|
// 一键三连
|
||||||
Future<void> actionOneThree() async {
|
Future<void> actionOneThree() async {
|
||||||
feedBack();
|
feedBack();
|
||||||
if (userInfo == null) {
|
if (!isLogin) {
|
||||||
SmartDialog.showToast('账号未登录');
|
SmartDialog.showToast('账号未登录');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -610,7 +552,7 @@ class BangumiIntroController
|
|||||||
|
|
||||||
// 收藏
|
// 收藏
|
||||||
void showFavBottomSheet(BuildContext context, {type = 'tap'}) {
|
void showFavBottomSheet(BuildContext context, {type = 'tap'}) {
|
||||||
if (userInfo == null) {
|
if (!isLogin) {
|
||||||
SmartDialog.showToast('账号未登录');
|
SmartDialog.showToast('账号未登录');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import 'package:PiliPlus/common/constants.dart';
|
|||||||
import 'package:PiliPlus/common/widgets/badge.dart';
|
import 'package:PiliPlus/common/widgets/badge.dart';
|
||||||
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
||||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||||
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
|
||||||
import 'package:PiliPlus/common/widgets/stat/stat.dart';
|
import 'package:PiliPlus/common/widgets/stat/stat.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
|
||||||
import 'package:PiliPlus/models/bangumi/info.dart';
|
import 'package:PiliPlus/models/bangumi/info.dart';
|
||||||
import 'package:PiliPlus/models/common/image_preview_type.dart';
|
import 'package:PiliPlus/models/common/image_preview_type.dart';
|
||||||
import 'package:PiliPlus/pages/video/controller.dart';
|
import 'package:PiliPlus/pages/video/controller.dart';
|
||||||
@@ -15,7 +13,6 @@ import 'package:PiliPlus/pages/video/introduction/pgc/widgets/bangumi_panel.dart
|
|||||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_item.dart';
|
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_item.dart';
|
||||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_row_item.dart';
|
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_row_item.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/feed_back.dart';
|
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -44,95 +41,10 @@ class _BangumiIntroPanelState extends State<BangumiIntroPanel>
|
|||||||
with AutomaticKeepAliveClientMixin {
|
with AutomaticKeepAliveClientMixin {
|
||||||
late BangumiIntroController bangumiIntroController;
|
late BangumiIntroController bangumiIntroController;
|
||||||
late VideoDetailController videoDetailCtr;
|
late VideoDetailController videoDetailCtr;
|
||||||
late int cid;
|
|
||||||
StreamSubscription? _listener;
|
|
||||||
|
|
||||||
// 添加页面缓存
|
late final _coinKey = GlobalKey<ActionItemState>();
|
||||||
@override
|
late final _favKey = GlobalKey<ActionItemState>();
|
||||||
bool get wantKeepAlive => true;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
cid = widget.cid!;
|
|
||||||
bangumiIntroController =
|
|
||||||
Get.put(BangumiIntroController(), tag: widget.heroTag);
|
|
||||||
videoDetailCtr = Get.find<VideoDetailController>(tag: widget.heroTag);
|
|
||||||
_listener = videoDetailCtr.cid.listen((int p0) {
|
|
||||||
cid = p0;
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_listener?.cancel();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
super.build(context);
|
|
||||||
return Obx(() => _buildBody(bangumiIntroController.loadingState.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildBody(LoadingState loadingState) {
|
|
||||||
return switch (loadingState) {
|
|
||||||
Loading() => BangumiInfo(
|
|
||||||
heroTag: widget.heroTag,
|
|
||||||
isLoading: true,
|
|
||||||
bangumiDetail: null,
|
|
||||||
cid: cid,
|
|
||||||
showEpisodes: widget.showEpisodes,
|
|
||||||
showIntroDetail: () {},
|
|
||||||
),
|
|
||||||
Success(:var response) => BangumiInfo(
|
|
||||||
heroTag: widget.heroTag,
|
|
||||||
isLoading: false,
|
|
||||||
bangumiDetail: response,
|
|
||||||
cid: cid,
|
|
||||||
showEpisodes: widget.showEpisodes,
|
|
||||||
showIntroDetail: () => widget.showIntroDetail(
|
|
||||||
response,
|
|
||||||
bangumiIntroController.videoTags,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Error(:var errMsg) => HttpError(
|
|
||||||
errMsg: errMsg,
|
|
||||||
onReload: bangumiIntroController.onReload,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BangumiInfo extends StatefulWidget {
|
|
||||||
const BangumiInfo({
|
|
||||||
super.key,
|
|
||||||
this.isLoading = false,
|
|
||||||
this.bangumiDetail,
|
|
||||||
this.cid,
|
|
||||||
required this.showEpisodes,
|
|
||||||
required this.showIntroDetail,
|
|
||||||
required this.heroTag,
|
|
||||||
});
|
|
||||||
|
|
||||||
final bool isLoading;
|
|
||||||
final BangumiInfoModel? bangumiDetail;
|
|
||||||
final int? cid;
|
|
||||||
final Function showEpisodes;
|
|
||||||
final Function showIntroDetail;
|
|
||||||
final String heroTag;
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<BangumiInfo> createState() => _BangumiInfoState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BangumiInfoState extends State<BangumiInfo> {
|
|
||||||
late final BangumiIntroController bangumiIntroController;
|
|
||||||
late final VideoDetailController videoDetailCtr;
|
|
||||||
late final BangumiInfoModel? bangumiItem;
|
|
||||||
int? cid;
|
|
||||||
bool isProcessing = false;
|
bool isProcessing = false;
|
||||||
Future<void> handleState(Future Function() action) async {
|
Future<void> handleState(Future Function() action) async {
|
||||||
if (isProcessing.not) {
|
if (isProcessing.not) {
|
||||||
@@ -142,10 +54,8 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
late final _coinKey = GlobalKey<ActionItemState>();
|
@override
|
||||||
late final _favKey = GlobalKey<ActionItemState>();
|
bool get wantKeepAlive => true;
|
||||||
|
|
||||||
StreamSubscription? _listener;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -153,32 +63,14 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
bangumiIntroController =
|
bangumiIntroController =
|
||||||
Get.put(BangumiIntroController(), tag: widget.heroTag);
|
Get.put(BangumiIntroController(), tag: widget.heroTag);
|
||||||
videoDetailCtr = Get.find<VideoDetailController>(tag: widget.heroTag);
|
videoDetailCtr = Get.find<VideoDetailController>(tag: widget.heroTag);
|
||||||
bangumiItem = bangumiIntroController.bangumiItem;
|
|
||||||
cid = widget.cid!;
|
|
||||||
debugPrint('cid: $cid');
|
|
||||||
_listener = videoDetailCtr.cid.listen((p0) {
|
|
||||||
cid = p0;
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_listener?.cancel();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 视频介绍
|
|
||||||
void showIntroDetail() {
|
|
||||||
feedBack();
|
|
||||||
widget.showIntroDetail();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
bool isLandscape =
|
final bangumiItem = bangumiIntroController.bangumiItem;
|
||||||
|
final isLandscape =
|
||||||
MediaQuery.of(context).orientation == Orientation.landscape;
|
MediaQuery.of(context).orientation == Orientation.landscape;
|
||||||
return SliverPadding(
|
return SliverPadding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
@@ -188,246 +80,196 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
bottom: StyleString.safeSpace + MediaQuery.paddingOf(context).bottom,
|
bottom: StyleString.safeSpace + MediaQuery.paddingOf(context).bottom,
|
||||||
),
|
),
|
||||||
sliver: SliverToBoxAdapter(
|
sliver: SliverToBoxAdapter(
|
||||||
child: !widget.isLoading || bangumiItem != null
|
child: Column(
|
||||||
? Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
Row(
|
||||||
Row(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
Stack(
|
||||||
Stack(
|
clipBehavior: Clip.none,
|
||||||
clipBehavior: Clip.none,
|
children: [
|
||||||
children: [
|
GestureDetector(
|
||||||
GestureDetector(
|
onTap: () {
|
||||||
onTap: () {
|
videoDetailCtr.onViewImage();
|
||||||
videoDetailCtr.onViewImage();
|
context.imageView(
|
||||||
context.imageView(
|
imgList: [
|
||||||
imgList: [
|
SourceModel(
|
||||||
SourceModel(
|
url: bangumiItem.cover!,
|
||||||
url: !widget.isLoading
|
)
|
||||||
? widget.bangumiDetail!.cover!
|
],
|
||||||
: bangumiItem!.cover!,
|
onDismissed: videoDetailCtr.onDismissed,
|
||||||
)
|
);
|
||||||
],
|
},
|
||||||
onDismissed: videoDetailCtr.onDismissed,
|
child: Hero(
|
||||||
);
|
tag: bangumiItem.cover!,
|
||||||
},
|
child: NetworkImgLayer(
|
||||||
child: Hero(
|
width: isLandscape ? 115 / 0.75 : 115,
|
||||||
tag: !widget.isLoading
|
height: isLandscape ? 115 : 115 / 0.75,
|
||||||
? widget.bangumiDetail!.cover!
|
src: bangumiItem.cover!,
|
||||||
: bangumiItem!.cover!,
|
semanticsLabel: '封面',
|
||||||
child: NetworkImgLayer(
|
|
||||||
width: isLandscape ? 115 / 0.75 : 115,
|
|
||||||
height: isLandscape ? 115 : 115 / 0.75,
|
|
||||||
src: !widget.isLoading
|
|
||||||
? widget.bangumiDetail!.cover!
|
|
||||||
: bangumiItem!.cover!,
|
|
||||||
semanticsLabel: '封面',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (bangumiItem != null &&
|
|
||||||
bangumiItem!.rating != null)
|
|
||||||
PBadge(
|
|
||||||
text:
|
|
||||||
'评分 ${!widget.isLoading ? widget.bangumiDetail!.rating!['score']! : bangumiItem!.rating!['score']!}',
|
|
||||||
top: null,
|
|
||||||
right: 6,
|
|
||||||
bottom: 6,
|
|
||||||
left: null,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Expanded(
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: showIntroDetail,
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
child: SizedBox(
|
|
||||||
height: isLandscape ? 115 : 115 / 0.75,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
!widget.isLoading
|
|
||||||
? widget.bangumiDetail!.title!
|
|
||||||
: bangumiItem!.title!,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 20),
|
|
||||||
Obx(
|
|
||||||
() => FilledButton.tonal(
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
tapTargetSize:
|
|
||||||
MaterialTapTargetSize.shrinkWrap,
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 20,
|
|
||||||
vertical: 10,
|
|
||||||
),
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
foregroundColor:
|
|
||||||
bangumiIntroController
|
|
||||||
.isFollowed.value
|
|
||||||
? theme.colorScheme.outline
|
|
||||||
: null,
|
|
||||||
backgroundColor:
|
|
||||||
bangumiIntroController
|
|
||||||
.isFollowed.value
|
|
||||||
? theme.colorScheme
|
|
||||||
.onInverseSurface
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
onPressed: bangumiIntroController
|
|
||||||
.followStatus.value ==
|
|
||||||
-1
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
if (bangumiIntroController
|
|
||||||
.isFollowed.value) {
|
|
||||||
showPgcFollowDialog(
|
|
||||||
context: context,
|
|
||||||
type: bangumiIntroController
|
|
||||||
.type,
|
|
||||||
followStatus:
|
|
||||||
bangumiIntroController
|
|
||||||
.followStatus.value,
|
|
||||||
onUpdateStatus:
|
|
||||||
(followStatus) {
|
|
||||||
if (followStatus == -1) {
|
|
||||||
bangumiIntroController
|
|
||||||
.bangumiDel();
|
|
||||||
} else {
|
|
||||||
bangumiIntroController
|
|
||||||
.bangumiUpdate(
|
|
||||||
followStatus);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
bangumiIntroController
|
|
||||||
.bangumiAdd();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
bangumiIntroController
|
|
||||||
.isFollowed.value
|
|
||||||
? '已${bangumiIntroController.type}'
|
|
||||||
: '${bangumiIntroController.type}',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
StatView(
|
|
||||||
context: context,
|
|
||||||
theme: 'gray',
|
|
||||||
value: Utils.numFormat(!widget.isLoading
|
|
||||||
? widget.bangumiDetail!.stat!['views']
|
|
||||||
: bangumiItem!.stat!['views']),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
StatDanMu(
|
|
||||||
context: context,
|
|
||||||
theme: 'gray',
|
|
||||||
value: Utils.numFormat(!widget.isLoading
|
|
||||||
? widget
|
|
||||||
.bangumiDetail!.stat!['danmakus']
|
|
||||||
: bangumiItem!.stat!['danmakus']),
|
|
||||||
),
|
|
||||||
if (isLandscape) ...[
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
AreasAndPubTime(
|
|
||||||
widget: widget,
|
|
||||||
bangumiItem: bangumiItem,
|
|
||||||
theme: theme,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
NewEpDesc(
|
|
||||||
widget: widget,
|
|
||||||
bangumiItem: bangumiItem,
|
|
||||||
theme: theme,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: isLandscape ? 2 : 6),
|
|
||||||
if (!isLandscape)
|
|
||||||
AreasAndPubTime(
|
|
||||||
widget: widget,
|
|
||||||
bangumiItem: bangumiItem,
|
|
||||||
theme: theme,
|
|
||||||
),
|
|
||||||
if (!isLandscape)
|
|
||||||
NewEpDesc(
|
|
||||||
widget: widget,
|
|
||||||
bangumiItem: bangumiItem,
|
|
||||||
theme: theme,
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Text(
|
|
||||||
'简介:${!widget.isLoading ? widget.bangumiDetail!.evaluate! : bangumiItem!.evaluate!}',
|
|
||||||
maxLines: isLandscape ? 2 : 3,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
color: theme.colorScheme.outline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
if (bangumiItem.rating != null)
|
||||||
const SizedBox(height: 6),
|
PBadge(
|
||||||
// 点赞收藏转发 布局样式2
|
text: '评分 ${bangumiItem.rating!['score']!}',
|
||||||
actionGrid(theme, bangumiIntroController),
|
top: null,
|
||||||
// 番剧分p
|
right: 6,
|
||||||
if ((!widget.isLoading &&
|
bottom: 6,
|
||||||
widget.bangumiDetail!.episodes!.isNotEmpty) ||
|
left: null,
|
||||||
bangumiItem != null &&
|
),
|
||||||
bangumiItem!.episodes!.isNotEmpty) ...[
|
|
||||||
BangumiPanel(
|
|
||||||
heroTag: widget.heroTag,
|
|
||||||
pages: bangumiItem != null
|
|
||||||
? bangumiItem!.episodes!
|
|
||||||
: widget.bangumiDetail!.episodes!,
|
|
||||||
cid: cid ??
|
|
||||||
(bangumiItem != null
|
|
||||||
? bangumiItem!.episodes!.first.cid
|
|
||||||
: widget.bangumiDetail!.episodes!.first.cid),
|
|
||||||
changeFuc: bangumiIntroController.changeSeasonOrbangu,
|
|
||||||
showEpisodes: widget.showEpisodes,
|
|
||||||
newEp: bangumiItem?.newEp,
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
],
|
|
||||||
)
|
|
||||||
: const SizedBox(
|
|
||||||
height: 100,
|
|
||||||
child: Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => widget.showIntroDetail(
|
||||||
|
bangumiItem, bangumiIntroController.videoTags),
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
child: SizedBox(
|
||||||
|
height: isLandscape ? 115 : 115 / 0.75,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
bangumiItem.title!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Obx(
|
||||||
|
() => FilledButton.tonal(
|
||||||
|
style: FilledButton.styleFrom(
|
||||||
|
tapTargetSize:
|
||||||
|
MaterialTapTargetSize.shrinkWrap,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
foregroundColor:
|
||||||
|
bangumiIntroController.isFollowed.value
|
||||||
|
? theme.colorScheme.outline
|
||||||
|
: null,
|
||||||
|
backgroundColor:
|
||||||
|
bangumiIntroController.isFollowed.value
|
||||||
|
? theme.colorScheme.onInverseSurface
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
onPressed: bangumiIntroController
|
||||||
|
.followStatus.value ==
|
||||||
|
-1
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (bangumiIntroController
|
||||||
|
.isFollowed.value) {
|
||||||
|
showPgcFollowDialog(
|
||||||
|
context: context,
|
||||||
|
type: bangumiIntroController.type,
|
||||||
|
followStatus:
|
||||||
|
bangumiIntroController
|
||||||
|
.followStatus.value,
|
||||||
|
onUpdateStatus: (followStatus) {
|
||||||
|
if (followStatus == -1) {
|
||||||
|
bangumiIntroController
|
||||||
|
.bangumiDel();
|
||||||
|
} else {
|
||||||
|
bangumiIntroController
|
||||||
|
.bangumiUpdate(
|
||||||
|
followStatus);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
bangumiIntroController.bangumiAdd();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
bangumiIntroController.isFollowed.value
|
||||||
|
? '已${bangumiIntroController.type}'
|
||||||
|
: '${bangumiIntroController.type}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
StatView(
|
||||||
|
context: context,
|
||||||
|
theme: 'gray',
|
||||||
|
value:
|
||||||
|
Utils.numFormat(bangumiItem.stat!['views']),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
StatDanMu(
|
||||||
|
context: context,
|
||||||
|
theme: 'gray',
|
||||||
|
value: Utils.numFormat(
|
||||||
|
bangumiItem.stat!['danmakus']),
|
||||||
|
),
|
||||||
|
if (isLandscape) ...[
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
areasAndPubTime(theme, bangumiItem),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
newEpDesc(theme, bangumiItem),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: isLandscape ? 2 : 6),
|
||||||
|
if (!isLandscape) ...[
|
||||||
|
areasAndPubTime(theme, bangumiItem),
|
||||||
|
newEpDesc(theme, bangumiItem),
|
||||||
|
],
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
'简介:${bangumiItem.evaluate!}',
|
||||||
|
maxLines: isLandscape ? 2 : 3,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: theme.colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
// 点赞收藏转发 布局样式2
|
||||||
|
actionGrid(theme, bangumiItem, bangumiIntroController),
|
||||||
|
// 番剧分p
|
||||||
|
if (bangumiItem.episodes!.isNotEmpty) ...[
|
||||||
|
BangumiPanel(
|
||||||
|
heroTag: widget.heroTag,
|
||||||
|
pages: bangumiItem.episodes!,
|
||||||
|
cid: videoDetailCtr.cid.value,
|
||||||
|
changeFuc: bangumiIntroController.changeSeasonOrbangu,
|
||||||
|
showEpisodes: widget.showEpisodes,
|
||||||
|
newEp: bangumiItem.newEp,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget actionGrid(
|
Widget actionGrid(ThemeData theme, BangumiInfoModel bangumiItem,
|
||||||
ThemeData theme, BangumiIntroController bangumiIntroController) {
|
BangumiIntroController bangumiIntroController) {
|
||||||
return Material(
|
return Material(
|
||||||
color: theme.colorScheme.surface,
|
color: theme.colorScheme.surface,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -445,13 +287,9 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
handleState(bangumiIntroController.actionLikeVideo),
|
handleState(bangumiIntroController.actionLikeVideo),
|
||||||
onLongPress: bangumiIntroController.actionOneThree,
|
onLongPress: bangumiIntroController.actionOneThree,
|
||||||
selectStatus: bangumiIntroController.hasLike.value,
|
selectStatus: bangumiIntroController.hasLike.value,
|
||||||
loadingStatus: false,
|
isLoading: false,
|
||||||
semanticsLabel: '点赞',
|
semanticsLabel: '点赞',
|
||||||
text: !widget.isLoading
|
text: Utils.numFormat(bangumiItem.stat!['likes']!),
|
||||||
? Utils.numFormat(widget.bangumiDetail!.stat!['likes']!)
|
|
||||||
: Utils.numFormat(
|
|
||||||
bangumiItem!.stat!['likes']!,
|
|
||||||
),
|
|
||||||
needAnim: true,
|
needAnim: true,
|
||||||
hasTriple: bangumiIntroController.hasLike.value &&
|
hasTriple: bangumiIntroController.hasLike.value &&
|
||||||
bangumiIntroController.hasCoin &&
|
bangumiIntroController.hasCoin &&
|
||||||
@@ -476,13 +314,9 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
onTap: () =>
|
onTap: () =>
|
||||||
handleState(bangumiIntroController.actionCoinVideo),
|
handleState(bangumiIntroController.actionCoinVideo),
|
||||||
selectStatus: bangumiIntroController.hasCoin,
|
selectStatus: bangumiIntroController.hasCoin,
|
||||||
loadingStatus: false,
|
isLoading: false,
|
||||||
semanticsLabel: '投币',
|
semanticsLabel: '投币',
|
||||||
text: !widget.isLoading
|
text: Utils.numFormat(bangumiItem.stat!['coins']!),
|
||||||
? Utils.numFormat(widget.bangumiDetail!.stat!['coins']!)
|
|
||||||
: Utils.numFormat(
|
|
||||||
bangumiItem!.stat!['coins']!,
|
|
||||||
),
|
|
||||||
needAnim: true,
|
needAnim: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -496,14 +330,9 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
onLongPress: () => bangumiIntroController
|
onLongPress: () => bangumiIntroController
|
||||||
.showFavBottomSheet(context, type: 'longPress'),
|
.showFavBottomSheet(context, type: 'longPress'),
|
||||||
selectStatus: bangumiIntroController.hasFav.value,
|
selectStatus: bangumiIntroController.hasFav.value,
|
||||||
loadingStatus: false,
|
isLoading: false,
|
||||||
semanticsLabel: '收藏',
|
semanticsLabel: '收藏',
|
||||||
text: !widget.isLoading
|
text: Utils.numFormat(bangumiItem.stat!['favorite']!),
|
||||||
? Utils.numFormat(
|
|
||||||
widget.bangumiDetail!.stat!['favorite']!)
|
|
||||||
: Utils.numFormat(
|
|
||||||
bangumiItem!.stat!['favorite']!,
|
|
||||||
),
|
|
||||||
needAnim: true,
|
needAnim: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -512,21 +341,18 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
selectIcon: const Icon(FontAwesomeIcons.reply),
|
selectIcon: const Icon(FontAwesomeIcons.reply),
|
||||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: false,
|
isLoading: false,
|
||||||
semanticsLabel: '评论',
|
semanticsLabel: '评论',
|
||||||
text: !widget.isLoading
|
text: Utils.numFormat(bangumiItem.stat!['reply']!),
|
||||||
? Utils.numFormat(widget.bangumiDetail!.stat!['reply']!)
|
|
||||||
: Utils.numFormat(bangumiItem!.stat!['reply']!),
|
|
||||||
),
|
),
|
||||||
ActionItem(
|
ActionItem(
|
||||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||||
onTap: () => bangumiIntroController.actionShareVideo(context),
|
onTap: () => bangumiIntroController.actionShareVideo(context),
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: false,
|
isLoading: false,
|
||||||
semanticsLabel: '转发',
|
semanticsLabel: '转发',
|
||||||
text: !widget.isLoading
|
text: Utils.numFormat(bangumiItem.stat!['share']!),
|
||||||
? Utils.numFormat(widget.bangumiDetail!.stat!['share']!)
|
),
|
||||||
: Utils.numFormat(bangumiItem!.stat!['share']!)),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -535,95 +361,72 @@ class _BangumiInfoState extends State<BangumiInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget actionRow(
|
Widget actionRow(
|
||||||
BuildContext context,
|
BangumiInfoModel bangumiItem,
|
||||||
BangumiIntroController bangumiIntroController,
|
BangumiIntroController bangumiIntroController,
|
||||||
VideoDetailController videoDetailCtr,
|
VideoDetailController videoDetailCtr,
|
||||||
) {
|
) {
|
||||||
return Row(children: [
|
return Row(
|
||||||
Obx(
|
children: [
|
||||||
() => ActionRowItem(
|
Obx(
|
||||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
() => ActionRowItem(
|
||||||
onTap: () => handleState(bangumiIntroController.actionLikeVideo),
|
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||||
selectStatus: bangumiIntroController.hasLike.value,
|
onTap: () => handleState(bangumiIntroController.actionLikeVideo),
|
||||||
loadingStatus: widget.isLoading,
|
selectStatus: bangumiIntroController.hasLike.value,
|
||||||
text: !widget.isLoading
|
isLoading: false,
|
||||||
? widget.bangumiDetail!.stat!['likes']!.toString()
|
text: bangumiItem.stat!['likes']!.toString(),
|
||||||
: '-',
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 8),
|
||||||
const SizedBox(width: 8),
|
Obx(
|
||||||
Obx(
|
() => ActionRowItem(
|
||||||
() => ActionRowItem(
|
icon: const Icon(FontAwesomeIcons.b),
|
||||||
icon: const Icon(FontAwesomeIcons.b),
|
onTap: () => handleState(bangumiIntroController.actionCoinVideo),
|
||||||
onTap: () => handleState(bangumiIntroController.actionCoinVideo),
|
selectStatus: bangumiIntroController.hasCoin,
|
||||||
selectStatus: bangumiIntroController.hasCoin,
|
isLoading: false,
|
||||||
loadingStatus: widget.isLoading,
|
text: bangumiItem.stat!['coins']!.toString(),
|
||||||
text: !widget.isLoading
|
),
|
||||||
? widget.bangumiDetail!.stat!['coins']!.toString()
|
|
||||||
: '-',
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 8),
|
||||||
const SizedBox(width: 8),
|
Obx(
|
||||||
Obx(
|
() => ActionRowItem(
|
||||||
() => ActionRowItem(
|
icon: const Icon(FontAwesomeIcons.heart),
|
||||||
icon: const Icon(FontAwesomeIcons.heart),
|
onTap: () => bangumiIntroController.showFavBottomSheet(context),
|
||||||
onTap: () => bangumiIntroController.showFavBottomSheet(context),
|
onLongPress: () => bangumiIntroController
|
||||||
onLongPress: () => bangumiIntroController.showFavBottomSheet(context,
|
.showFavBottomSheet(context, type: 'longPress'),
|
||||||
type: 'longPress'),
|
selectStatus: bangumiIntroController.hasFav.value,
|
||||||
selectStatus: bangumiIntroController.hasFav.value,
|
isLoading: false,
|
||||||
loadingStatus: widget.isLoading,
|
text: bangumiItem.stat!['favorite']!.toString(),
|
||||||
text: !widget.isLoading
|
),
|
||||||
? widget.bangumiDetail!.stat!['favorite']!.toString()
|
|
||||||
: '-',
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 8),
|
||||||
const SizedBox(width: 8),
|
ActionRowItem(
|
||||||
ActionRowItem(
|
icon: const Icon(FontAwesomeIcons.comment),
|
||||||
icon: const Icon(FontAwesomeIcons.comment),
|
onTap: () {
|
||||||
onTap: () {
|
videoDetailCtr.tabCtr.animateTo(1);
|
||||||
videoDetailCtr.tabCtr.animateTo(1);
|
},
|
||||||
},
|
selectStatus: false,
|
||||||
selectStatus: false,
|
isLoading: false,
|
||||||
loadingStatus: widget.isLoading,
|
text: bangumiItem.stat!['reply']!.toString(),
|
||||||
text: !widget.isLoading
|
),
|
||||||
? widget.bangumiDetail!.stat!['reply']!.toString()
|
const SizedBox(width: 8),
|
||||||
: '-',
|
ActionRowItem(
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
ActionRowItem(
|
|
||||||
icon: const Icon(FontAwesomeIcons.share),
|
icon: const Icon(FontAwesomeIcons.share),
|
||||||
onTap: () => bangumiIntroController.actionShareVideo(context),
|
onTap: () => bangumiIntroController.actionShareVideo(context),
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.isLoading,
|
isLoading: false,
|
||||||
text: '转发'),
|
text: '转发',
|
||||||
]);
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class AreasAndPubTime extends StatelessWidget {
|
Widget areasAndPubTime(ThemeData theme, BangumiInfoModel bangumiItem) {
|
||||||
const AreasAndPubTime({
|
|
||||||
super.key,
|
|
||||||
required this.widget,
|
|
||||||
required this.bangumiItem,
|
|
||||||
required this.theme,
|
|
||||||
});
|
|
||||||
|
|
||||||
final BangumiInfo widget;
|
|
||||||
final BangumiInfoModel? bangumiItem;
|
|
||||||
final ThemeData theme;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
!widget.isLoading
|
(bangumiItem.areas!.isNotEmpty
|
||||||
? (widget.bangumiDetail!.areas!.isNotEmpty
|
? bangumiItem.areas!.first['name']
|
||||||
? widget.bangumiDetail!.areas!.first['name']
|
: ''),
|
||||||
: '')
|
|
||||||
: (bangumiItem!.areas!.isNotEmpty
|
|
||||||
? bangumiItem!.areas!.first['name']
|
|
||||||
: ''),
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: theme.colorScheme.outline,
|
color: theme.colorScheme.outline,
|
||||||
@@ -631,9 +434,7 @@ class AreasAndPubTime extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
Text(
|
Text(
|
||||||
!widget.isLoading
|
bangumiItem.publish!['pub_time_show'],
|
||||||
? widget.bangumiDetail!.publish!['pub_time_show']
|
|
||||||
: bangumiItem!.publish!['pub_time_show'],
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: theme.colorScheme.outline,
|
color: theme.colorScheme.outline,
|
||||||
@@ -642,26 +443,10 @@ class AreasAndPubTime extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class NewEpDesc extends StatelessWidget {
|
Widget newEpDesc(ThemeData theme, BangumiInfoModel bangumiItem) {
|
||||||
const NewEpDesc({
|
|
||||||
super.key,
|
|
||||||
required this.widget,
|
|
||||||
required this.bangumiItem,
|
|
||||||
required this.theme,
|
|
||||||
});
|
|
||||||
|
|
||||||
final BangumiInfo widget;
|
|
||||||
final BangumiInfoModel? bangumiItem;
|
|
||||||
final ThemeData theme;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Text(
|
return Text(
|
||||||
!widget.isLoading
|
bangumiItem.newEp!['desc'],
|
||||||
? widget.bangumiDetail!.newEp!['desc']
|
|
||||||
: bangumiItem!.newEp!['desc'],
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: theme.colorScheme.outline,
|
color: theme.colorScheme.outline,
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
|||||||
return Obx(
|
return Obx(
|
||||||
() => videoIntroController.videoDetail.value.title == null
|
() => videoIntroController.videoDetail.value.title == null
|
||||||
? VideoInfo(
|
? VideoInfo(
|
||||||
loadingStatus: true,
|
isLoading: true,
|
||||||
videoIntroController: videoIntroController,
|
videoIntroController: videoIntroController,
|
||||||
heroTag: widget.heroTag,
|
heroTag: widget.heroTag,
|
||||||
showAiBottomSheet: widget.showAiBottomSheet,
|
showAiBottomSheet: widget.showAiBottomSheet,
|
||||||
@@ -80,7 +80,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
|||||||
)
|
)
|
||||||
: VideoInfo(
|
: VideoInfo(
|
||||||
key: ValueKey(widget.heroTag),
|
key: ValueKey(widget.heroTag),
|
||||||
loadingStatus: false,
|
isLoading: false,
|
||||||
videoIntroController: videoIntroController,
|
videoIntroController: videoIntroController,
|
||||||
heroTag: widget.heroTag,
|
heroTag: widget.heroTag,
|
||||||
showAiBottomSheet: widget.showAiBottomSheet,
|
showAiBottomSheet: widget.showAiBottomSheet,
|
||||||
@@ -92,7 +92,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
class VideoInfo extends StatefulWidget {
|
class VideoInfo extends StatefulWidget {
|
||||||
final bool loadingStatus;
|
final bool isLoading;
|
||||||
final String heroTag;
|
final String heroTag;
|
||||||
final Function showAiBottomSheet;
|
final Function showAiBottomSheet;
|
||||||
final Function showEpisodes;
|
final Function showEpisodes;
|
||||||
@@ -101,7 +101,7 @@ class VideoInfo extends StatefulWidget {
|
|||||||
|
|
||||||
const VideoInfo({
|
const VideoInfo({
|
||||||
super.key,
|
super.key,
|
||||||
this.loadingStatus = false,
|
this.isLoading = false,
|
||||||
required this.heroTag,
|
required this.heroTag,
|
||||||
required this.showAiBottomSheet,
|
required this.showAiBottomSheet,
|
||||||
required this.showEpisodes,
|
required this.showEpisodes,
|
||||||
@@ -236,7 +236,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
|
|
||||||
// 视频介绍
|
// 视频介绍
|
||||||
void showIntroDetail() {
|
void showIntroDetail() {
|
||||||
if (widget.loadingStatus) {
|
if (widget.isLoading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
feedBack();
|
feedBack();
|
||||||
@@ -246,9 +246,8 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
// 用户主页
|
// 用户主页
|
||||||
void onPushMember() {
|
void onPushMember() {
|
||||||
feedBack();
|
feedBack();
|
||||||
int? mid = !widget.loadingStatus
|
int? mid =
|
||||||
? videoDetail.owner?.mid
|
!widget.isLoading ? videoDetail.owner?.mid : videoItem['owner']?.mid;
|
||||||
: videoItem['owner']?.mid;
|
|
||||||
if (mid != null) {
|
if (mid != null) {
|
||||||
if (context.orientation == Orientation.landscape &&
|
if (context.orientation == Orientation.landscape &&
|
||||||
_horizontalMemberPage) {
|
_horizontalMemberPage) {
|
||||||
@@ -369,7 +368,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
childBuilder: (index) => GestureDetector(
|
childBuilder: (index) => GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
int? ownerMid = !widget.loadingStatus
|
int? ownerMid = !widget.isLoading
|
||||||
? videoDetail.owner?.mid
|
? videoDetail.owner?.mid
|
||||||
: videoItem['owner']?.mid;
|
: videoItem['owner']?.mid;
|
||||||
if (videoItem['staff'][index].mid ==
|
if (videoItem['staff'][index].mid ==
|
||||||
@@ -557,7 +556,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
StatView(
|
StatView(
|
||||||
context: context,
|
context: context,
|
||||||
theme: 'gray',
|
theme: 'gray',
|
||||||
value: Utils.numFormat(!widget.loadingStatus
|
value: Utils.numFormat(!widget.isLoading
|
||||||
? videoDetail.stat?.view ?? '-'
|
? videoDetail.stat?.view ?? '-'
|
||||||
: videoItem['stat']?.view ?? '-'),
|
: videoItem['stat']?.view ?? '-'),
|
||||||
textColor: theme.colorScheme.outline,
|
textColor: theme.colorScheme.outline,
|
||||||
@@ -566,7 +565,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
StatDanMu(
|
StatDanMu(
|
||||||
context: context,
|
context: context,
|
||||||
theme: 'gray',
|
theme: 'gray',
|
||||||
value: Utils.numFormat(!widget.loadingStatus
|
value: Utils.numFormat(!widget.isLoading
|
||||||
? videoDetail.stat?.danmaku ?? '-'
|
? videoDetail.stat?.danmaku ?? '-'
|
||||||
: videoItem['stat']?.danmu ?? '-'),
|
: videoItem['stat']?.danmu ?? '-'),
|
||||||
textColor: theme.colorScheme.outline,
|
textColor: theme.colorScheme.outline,
|
||||||
@@ -574,7 +573,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Text(
|
Text(
|
||||||
Utils.dateFormat(
|
Utils.dateFormat(
|
||||||
!widget.loadingStatus
|
!widget.isLoading
|
||||||
? videoDetail.pubdate
|
? videoDetail.pubdate
|
||||||
: videoItem['pubdate'],
|
: videoItem['pubdate'],
|
||||||
formatType: 'detail'),
|
formatType: 'detail'),
|
||||||
@@ -769,7 +768,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
actionGrid(context, videoIntroController),
|
actionGrid(context, videoIntroController),
|
||||||
],
|
],
|
||||||
// 合集
|
// 合集
|
||||||
if (!widget.loadingStatus &&
|
if (!widget.isLoading &&
|
||||||
videoDetail.ugcSeason != null &&
|
videoDetail.ugcSeason != null &&
|
||||||
(context.orientation != Orientation.landscape ||
|
(context.orientation != Orientation.landscape ||
|
||||||
(context.orientation == Orientation.landscape &&
|
(context.orientation == Orientation.landscape &&
|
||||||
@@ -784,7 +783,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
videoIntroController: videoIntroController,
|
videoIntroController: videoIntroController,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!widget.loadingStatus &&
|
if (!widget.isLoading &&
|
||||||
videoDetail.pages != null &&
|
videoDetail.pages != null &&
|
||||||
videoDetail.pages!.length > 1 &&
|
videoDetail.pages!.length > 1 &&
|
||||||
(context.orientation != Orientation.landscape ||
|
(context.orientation != Orientation.landscape ||
|
||||||
@@ -857,9 +856,9 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
onLongPress: () =>
|
onLongPress: () =>
|
||||||
handleState(videoIntroController.actionOneThree),
|
handleState(videoIntroController.actionOneThree),
|
||||||
selectStatus: videoIntroController.hasLike.value,
|
selectStatus: videoIntroController.hasLike.value,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
semanticsLabel: '点赞',
|
semanticsLabel: '点赞',
|
||||||
text: !widget.loadingStatus
|
text: !widget.isLoading
|
||||||
? Utils.numFormat(videoDetail.stat!.like!)
|
? Utils.numFormat(videoDetail.stat!.like!)
|
||||||
: '-',
|
: '-',
|
||||||
needAnim: true,
|
needAnim: true,
|
||||||
@@ -884,7 +883,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
selectIcon: const Icon(FontAwesomeIcons.solidThumbsDown),
|
selectIcon: const Icon(FontAwesomeIcons.solidThumbsDown),
|
||||||
onTap: () => handleState(videoIntroController.actionDislikeVideo),
|
onTap: () => handleState(videoIntroController.actionDislikeVideo),
|
||||||
selectStatus: videoIntroController.hasDislike.value,
|
selectStatus: videoIntroController.hasDislike.value,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
semanticsLabel: '点踩',
|
semanticsLabel: '点踩',
|
||||||
text: "点踩",
|
text: "点踩",
|
||||||
),
|
),
|
||||||
@@ -896,9 +895,9 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
selectIcon: const Icon(FontAwesomeIcons.b),
|
selectIcon: const Icon(FontAwesomeIcons.b),
|
||||||
onTap: () => handleState(videoIntroController.actionCoinVideo),
|
onTap: () => handleState(videoIntroController.actionCoinVideo),
|
||||||
selectStatus: videoIntroController.hasCoin,
|
selectStatus: videoIntroController.hasCoin,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
semanticsLabel: '投币',
|
semanticsLabel: '投币',
|
||||||
text: !widget.loadingStatus
|
text: !widget.isLoading
|
||||||
? Utils.numFormat(videoDetail.stat!.coin!)
|
? Utils.numFormat(videoDetail.stat!.coin!)
|
||||||
: '-',
|
: '-',
|
||||||
needAnim: true,
|
needAnim: true,
|
||||||
@@ -913,9 +912,9 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
onLongPress: () => videoIntroController
|
onLongPress: () => videoIntroController
|
||||||
.showFavBottomSheet(context, type: 'longPress'),
|
.showFavBottomSheet(context, type: 'longPress'),
|
||||||
selectStatus: videoIntroController.hasFav.value,
|
selectStatus: videoIntroController.hasFav.value,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
semanticsLabel: '收藏',
|
semanticsLabel: '收藏',
|
||||||
text: !widget.loadingStatus
|
text: !widget.isLoading
|
||||||
? Utils.numFormat(videoDetail.stat!.favorite!)
|
? Utils.numFormat(videoDetail.stat!.favorite!)
|
||||||
: '-',
|
: '-',
|
||||||
needAnim: true,
|
needAnim: true,
|
||||||
@@ -927,7 +926,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
selectIcon: const Icon(FontAwesomeIcons.solidClock),
|
selectIcon: const Icon(FontAwesomeIcons.solidClock),
|
||||||
onTap: () => handleState(videoIntroController.viewLater),
|
onTap: () => handleState(videoIntroController.viewLater),
|
||||||
selectStatus: videoIntroController.hasLater.value,
|
selectStatus: videoIntroController.hasLater.value,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
semanticsLabel: '再看',
|
semanticsLabel: '再看',
|
||||||
text: '再看',
|
text: '再看',
|
||||||
),
|
),
|
||||||
@@ -936,9 +935,9 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||||
onTap: () => videoIntroController.actionShareVideo(context),
|
onTap: () => videoIntroController.actionShareVideo(context),
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
semanticsLabel: '分享',
|
semanticsLabel: '分享',
|
||||||
text: !widget.loadingStatus
|
text: !widget.isLoading
|
||||||
? Utils.numFormat(videoDetail.stat!.share!)
|
? Utils.numFormat(videoDetail.stat!.share!)
|
||||||
: '分享',
|
: '分享',
|
||||||
),
|
),
|
||||||
@@ -958,9 +957,8 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||||
onTap: () => handleState(videoIntroController.actionLikeVideo),
|
onTap: () => handleState(videoIntroController.actionLikeVideo),
|
||||||
selectStatus: videoIntroController.hasLike.value,
|
selectStatus: videoIntroController.hasLike.value,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
text:
|
text: !widget.isLoading ? videoDetail.stat!.like!.toString() : '-',
|
||||||
!widget.loadingStatus ? videoDetail.stat!.like!.toString() : '-',
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@@ -969,9 +967,8 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
icon: const Icon(FontAwesomeIcons.b),
|
icon: const Icon(FontAwesomeIcons.b),
|
||||||
onTap: () => handleState(videoIntroController.actionCoinVideo),
|
onTap: () => handleState(videoIntroController.actionCoinVideo),
|
||||||
selectStatus: videoIntroController.hasCoin,
|
selectStatus: videoIntroController.hasCoin,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
text:
|
text: !widget.isLoading ? videoDetail.stat!.coin!.toString() : '-',
|
||||||
!widget.loadingStatus ? videoDetail.stat!.coin!.toString() : '-',
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@@ -982,10 +979,9 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
onLongPress: () => videoIntroController.showFavBottomSheet(context,
|
onLongPress: () => videoIntroController.showFavBottomSheet(context,
|
||||||
type: 'longPress'),
|
type: 'longPress'),
|
||||||
selectStatus: videoIntroController.hasFav.value,
|
selectStatus: videoIntroController.hasFav.value,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
text: !widget.loadingStatus
|
text:
|
||||||
? videoDetail.stat!.favorite!.toString()
|
!widget.isLoading ? videoDetail.stat!.favorite!.toString() : '-',
|
||||||
: '-',
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@@ -995,15 +991,15 @@ class _VideoInfoState extends State<VideoInfo> {
|
|||||||
videoDetailCtr.tabCtr.animateTo(1);
|
videoDetailCtr.tabCtr.animateTo(1);
|
||||||
},
|
},
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
text: !widget.loadingStatus ? videoDetail.stat!.reply!.toString() : '-',
|
text: !widget.isLoading ? videoDetail.stat!.reply!.toString() : '-',
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
ActionRowItem(
|
ActionRowItem(
|
||||||
icon: const Icon(FontAwesomeIcons.share),
|
icon: const Icon(FontAwesomeIcons.share),
|
||||||
onTap: () => videoIntroController.actionShareVideo(context),
|
onTap: () => videoIntroController.actionShareVideo(context),
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.loadingStatus,
|
isLoading: widget.isLoading,
|
||||||
text: '转发',
|
text: '转发',
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class ActionItem extends StatefulWidget {
|
|||||||
final Icon? selectIcon;
|
final Icon? selectIcon;
|
||||||
final Function? onTap;
|
final Function? onTap;
|
||||||
final Function? onLongPress;
|
final Function? onLongPress;
|
||||||
final bool? loadingStatus;
|
final bool? isLoading;
|
||||||
final String? text;
|
final String? text;
|
||||||
final bool selectStatus;
|
final bool selectStatus;
|
||||||
final String semanticsLabel;
|
final String semanticsLabel;
|
||||||
@@ -27,7 +27,7 @@ class ActionItem extends StatefulWidget {
|
|||||||
this.selectIcon,
|
this.selectIcon,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.onLongPress,
|
this.onLongPress,
|
||||||
this.loadingStatus,
|
this.isLoading,
|
||||||
this.text,
|
this.text,
|
||||||
this.selectStatus = false,
|
this.selectStatus = false,
|
||||||
this.needAnim = false,
|
this.needAnim = false,
|
||||||
@@ -183,7 +183,7 @@ class ActionItemState extends State<ActionItem>
|
|||||||
),
|
),
|
||||||
if (widget.text != null)
|
if (widget.text != null)
|
||||||
AnimatedOpacity(
|
AnimatedOpacity(
|
||||||
opacity: widget.loadingStatus! ? 0 : 1,
|
opacity: widget.isLoading! ? 0 : 1,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
child: AnimatedSwitcher(
|
child: AnimatedSwitcher(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class ActionRowItem extends StatelessWidget {
|
|||||||
final Icon? icon;
|
final Icon? icon;
|
||||||
final Icon? selectIcon;
|
final Icon? selectIcon;
|
||||||
final Function? onTap;
|
final Function? onTap;
|
||||||
final bool? loadingStatus;
|
final bool? isLoading;
|
||||||
final String? text;
|
final String? text;
|
||||||
final bool selectStatus;
|
final bool selectStatus;
|
||||||
final Function? onLongPress;
|
final Function? onLongPress;
|
||||||
@@ -15,7 +15,7 @@ class ActionRowItem extends StatelessWidget {
|
|||||||
this.icon,
|
this.icon,
|
||||||
this.selectIcon,
|
this.selectIcon,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.loadingStatus,
|
this.isLoading,
|
||||||
this.text,
|
this.text,
|
||||||
this.selectStatus = false,
|
this.selectStatus = false,
|
||||||
this.onLongPress,
|
this.onLongPress,
|
||||||
@@ -53,7 +53,7 @@ class ActionRowItem extends StatelessWidget {
|
|||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
],
|
],
|
||||||
AnimatedOpacity(
|
AnimatedOpacity(
|
||||||
opacity: loadingStatus! ? 0 : 1,
|
opacity: isLoading! ? 0 : 1,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
child: AnimatedSwitcher(
|
child: AnimatedSwitcher(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import 'package:flutter/material.dart';
|
|||||||
class MenuRow extends StatelessWidget {
|
class MenuRow extends StatelessWidget {
|
||||||
const MenuRow({
|
const MenuRow({
|
||||||
super.key,
|
super.key,
|
||||||
this.loadingStatus,
|
this.isLoading,
|
||||||
});
|
});
|
||||||
final bool? loadingStatus;
|
final bool? isLoading;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -20,28 +20,28 @@ class MenuRow extends StatelessWidget {
|
|||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
ActionRowLineItem(
|
ActionRowLineItem(
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
loadingStatus: loadingStatus,
|
isLoading: isLoading,
|
||||||
text: '推荐',
|
text: '推荐',
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
ActionRowLineItem(
|
ActionRowLineItem(
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
loadingStatus: loadingStatus,
|
isLoading: isLoading,
|
||||||
text: '弹幕',
|
text: '弹幕',
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
ActionRowLineItem(
|
ActionRowLineItem(
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
loadingStatus: loadingStatus,
|
isLoading: isLoading,
|
||||||
text: '评论列表',
|
text: '评论列表',
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
ActionRowLineItem(
|
ActionRowLineItem(
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
loadingStatus: loadingStatus,
|
isLoading: isLoading,
|
||||||
text: '播放列表',
|
text: '播放列表',
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
),
|
),
|
||||||
@@ -51,7 +51,7 @@ class MenuRow extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget actionRowLineItem(
|
Widget actionRowLineItem(
|
||||||
ThemeData theme, Function? onTap, bool? loadingStatus, String? text,
|
ThemeData theme, Function? onTap, bool? isLoading, String? text,
|
||||||
{bool selectStatus = false}) {
|
{bool selectStatus = false}) {
|
||||||
return Material(
|
return Material(
|
||||||
color: selectStatus
|
color: selectStatus
|
||||||
@@ -78,7 +78,7 @@ class MenuRow extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
AnimatedOpacity(
|
AnimatedOpacity(
|
||||||
opacity: loadingStatus! ? 0 : 1,
|
opacity: isLoading! ? 0 : 1,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
child: Text(
|
child: Text(
|
||||||
text!,
|
text!,
|
||||||
@@ -103,13 +103,13 @@ class ActionRowLineItem extends StatelessWidget {
|
|||||||
required this.selectStatus,
|
required this.selectStatus,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.text,
|
this.text,
|
||||||
this.loadingStatus = false,
|
this.isLoading = false,
|
||||||
this.iconData,
|
this.iconData,
|
||||||
this.icon,
|
this.icon,
|
||||||
});
|
});
|
||||||
final bool selectStatus;
|
final bool selectStatus;
|
||||||
final Function? onTap;
|
final Function? onTap;
|
||||||
final bool? loadingStatus;
|
final bool? isLoading;
|
||||||
final String? text;
|
final String? text;
|
||||||
final IconData? iconData;
|
final IconData? iconData;
|
||||||
final Widget? icon;
|
final Widget? icon;
|
||||||
@@ -152,7 +152,7 @@ class ActionRowLineItem extends StatelessWidget {
|
|||||||
else if (icon != null)
|
else if (icon != null)
|
||||||
icon!,
|
icon!,
|
||||||
AnimatedOpacity(
|
AnimatedOpacity(
|
||||||
opacity: loadingStatus! ? 0 : 1,
|
opacity: isLoading! ? 0 : 1,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
child: Text(
|
child: Text(
|
||||||
text!,
|
text!,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
|
|||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/main.dart';
|
import 'package:PiliPlus/main.dart';
|
||||||
import 'package:PiliPlus/models/bangumi/info.dart' as bangumi;
|
import 'package:PiliPlus/models/bangumi/info.dart' as bangumi;
|
||||||
import 'package:PiliPlus/models/bangumi/info.dart';
|
|
||||||
import 'package:PiliPlus/models/common/episode_panel_type.dart';
|
import 'package:PiliPlus/models/common/episode_panel_type.dart';
|
||||||
import 'package:PiliPlus/models/common/reply/reply_type.dart';
|
import 'package:PiliPlus/models/common/reply/reply_type.dart';
|
||||||
import 'package:PiliPlus/models/common/search_type.dart';
|
import 'package:PiliPlus/models/common/search_type.dart';
|
||||||
@@ -103,8 +102,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
videoDetailController.plPlayerController.horizontalPreview;
|
videoDetailController.plPlayerController.horizontalPreview;
|
||||||
|
|
||||||
StreamSubscription? _listenerDetail;
|
StreamSubscription? _listenerDetail;
|
||||||
StreamSubscription? _listenerLoadingState;
|
|
||||||
StreamSubscription? _listenerCid;
|
|
||||||
StreamSubscription? _listenerFS;
|
StreamSubscription? _listenerFS;
|
||||||
|
|
||||||
Box get setting => GStorage.setting;
|
Box get setting => GStorage.setting;
|
||||||
@@ -137,23 +134,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
});
|
});
|
||||||
if (videoDetailController.videoType == SearchType.media_bangumi) {
|
if (videoDetailController.videoType == SearchType.media_bangumi) {
|
||||||
bangumiIntroController = Get.put(BangumiIntroController(), tag: heroTag);
|
bangumiIntroController = Get.put(BangumiIntroController(), tag: heroTag);
|
||||||
_listenerLoadingState =
|
|
||||||
bangumiIntroController.loadingState.listen((value) {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
if (value is Success<BangumiInfoModel>) {
|
|
||||||
videoPlayerServiceHandler.onVideoDetailChange(
|
|
||||||
value.response, videoDetailController.cid.value, heroTag);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
_listenerCid = videoDetailController.cid.listen((p0) {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
if (bangumiIntroController.loadingState.value is Success) {
|
|
||||||
videoPlayerServiceHandler.onVideoDetailChange(
|
|
||||||
(bangumiIntroController.loadingState.value as Success).response,
|
|
||||||
p0,
|
|
||||||
heroTag);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
autoExitFullscreen =
|
autoExitFullscreen =
|
||||||
setting.get(SettingBoxKey.enableAutoExit, defaultValue: true);
|
setting.get(SettingBoxKey.enableAutoExit, defaultValue: true);
|
||||||
@@ -337,8 +317,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_listenerDetail?.cancel();
|
_listenerDetail?.cancel();
|
||||||
_listenerLoadingState?.cancel();
|
|
||||||
_listenerCid?.cancel();
|
|
||||||
_listenerFS?.cancel();
|
_listenerFS?.cancel();
|
||||||
|
|
||||||
videoDetailController.skipTimer?.cancel();
|
videoDetailController.skipTimer?.cancel();
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import 'dart:math';
|
|||||||
import 'package:PiliPlus/common/constants.dart';
|
import 'package:PiliPlus/common/constants.dart';
|
||||||
import 'package:PiliPlus/common/widgets/progress_bar/audio_video_progress_bar.dart';
|
import 'package:PiliPlus/common/widgets/progress_bar/audio_video_progress_bar.dart';
|
||||||
import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart';
|
import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
|
||||||
import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
||||||
import 'package:PiliPlus/models/video_detail_res.dart';
|
import 'package:PiliPlus/models/video_detail_res.dart';
|
||||||
import 'package:PiliPlus/pages/video/controller.dart';
|
import 'package:PiliPlus/pages/video/controller.dart';
|
||||||
@@ -266,7 +265,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
bool isSeason = videoIntroController?.videoDetail.value.ugcSeason != null;
|
bool isSeason = videoIntroController?.videoDetail.value.ugcSeason != null;
|
||||||
bool isPage = videoIntroController?.videoDetail.value.pages != null &&
|
bool isPage = videoIntroController?.videoDetail.value.pages != null &&
|
||||||
videoIntroController!.videoDetail.value.pages!.length > 1;
|
videoIntroController!.videoDetail.value.pages!.length > 1;
|
||||||
bool isBangumi = bangumiIntroController?.loadingState.value is Success;
|
bool isBangumi = bangumiIntroController != null;
|
||||||
bool anySeason = isSeason || isPage || isBangumi;
|
bool anySeason = isSeason || isPage || isBangumi;
|
||||||
double widgetWidth =
|
double widgetWidth =
|
||||||
isFullScreen && context.orientation == Orientation.landscape ? 42 : 35;
|
isFullScreen && context.orientation == Orientation.landscape ? 42 : 35;
|
||||||
@@ -508,9 +507,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
videoIntroController!.videoDetail.value.pages!;
|
videoIntroController!.videoDetail.value.pages!;
|
||||||
episodes = pages;
|
episodes = pages;
|
||||||
} else if (isBangumi) {
|
} else if (isBangumi) {
|
||||||
episodes = (bangumiIntroController!.loadingState.value as Success)
|
episodes = bangumiIntroController!.bangumiItem.episodes!;
|
||||||
.response
|
|
||||||
.episodes!;
|
|
||||||
}
|
}
|
||||||
widget.showEpisodes?.call(
|
widget.showEpisodes?.call(
|
||||||
index,
|
index,
|
||||||
|
|||||||
Reference in New Issue
Block a user