opt: pages

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-01-02 20:34:05 +08:00
parent f1a10a786d
commit 621239551f
22 changed files with 227 additions and 191 deletions

View File

@@ -45,6 +45,17 @@ class VideoCardVSkeleton extends StatelessWidget {
margin: const EdgeInsets.only(bottom: 12), margin: const EdgeInsets.only(bottom: 12),
color: Theme.of(context).colorScheme.onInverseSurface, color: Theme.of(context).colorScheme.onInverseSurface,
), ),
Container(
width: 110,
height: 13,
margin: const EdgeInsets.only(bottom: 5),
color: Theme.of(context).colorScheme.onInverseSurface,
),
Container(
width: 75,
height: 13,
color: Theme.of(context).colorScheme.onInverseSurface,
),
], ],
), ),
), ),

View File

@@ -145,7 +145,7 @@ class VideoCardH extends StatelessWidget {
if (source == 'normal') if (source == 'normal')
Positioned( Positioned(
bottom: 0, bottom: 0,
right: 0, right: 12,
child: VideoPopupMenu( child: VideoPopupMenu(
size: 29, size: 29,
iconSize: 17, iconSize: 17,

View File

@@ -106,7 +106,7 @@ class VideoCardHMemberVideo extends StatelessWidget {
), ),
Positioned( Positioned(
bottom: 0, bottom: 0,
right: 0, right: 12,
child: VideoPopupMenu( child: VideoPopupMenu(
size: 29, size: 29,
iconSize: 17, iconSize: 17,

View File

@@ -220,64 +220,64 @@ Widget videoContent(BuildContext context, Item videoItem) {
), ),
], ],
), ),
const Spacer(), // const Spacer(),
// const SizedBox(height: 2), // const SizedBox(height: 2),
// VideoStat( // VideoStat(
// videoItem: videoItem, // videoItem: videoItem,
// ), // ),
Row( // Row(
children: [ // children: [
// if (videoItem.goto == 'bangumi') ...[ // if (videoItem.goto == 'bangumi') ...[
// PBadge( // PBadge(
// text: videoItem.bangumiBadge, // text: videoItem.bangumiBadge,
// stack: 'normal', // stack: 'normal',
// size: 'small', // size: 'small',
// type: 'line', // type: 'line',
// fs: 9, // fs: 9,
// ) // )
// ], // ],
// if (videoItem.rcmdReason != null) ...[ // if (videoItem.rcmdReason != null) ...[
// PBadge( // PBadge(
// text: videoItem.rcmdReason, // text: videoItem.rcmdReason,
// stack: 'normal', // stack: 'normal',
// size: 'small', // size: 'small',
// type: 'color', // type: 'color',
// ) // )
// ], // ],
if (videoItem.goto == 'picture') ...[ // if (videoItem.goto == 'picture') ...[
const PBadge( // const PBadge(
text: '动态', // text: '动态',
stack: 'normal', // stack: 'normal',
size: 'small', // size: 'small',
type: 'line', // type: 'line',
fs: 9, // fs: 9,
) // )
], // ],
// if (videoItem.isFollowed == 1) ...[ // if (videoItem.isFollowed == 1) ...[
// const PBadge( // const PBadge(
// text: '已关注', // text: '已关注',
// stack: 'normal', // stack: 'normal',
// size: 'small', // size: 'small',
// type: 'color', // type: 'color',
// ) // )
// ], // ],
Expanded( // Expanded(
flex: 1, // flex: 1,
child: Text( // child: Text(
videoItem.author ?? '', // videoItem.author ?? '',
// semanticsLabel: "Up主${videoItem.owner.name}", // // semanticsLabel: "Up主${videoItem.owner.name}",
maxLines: 1, // maxLines: 1,
overflow: TextOverflow.clip, // overflow: TextOverflow.clip,
style: TextStyle( // style: TextStyle(
height: 1.5, // height: 1.5,
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, // fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
color: Theme.of(context).colorScheme.outline, // color: Theme.of(context).colorScheme.outline,
), // ),
), // ),
), // ),
if (videoItem.goto == 'av') const SizedBox(width: 10) // if (videoItem.goto == 'av') const SizedBox(width: 10)
], // ],
), // ),
], ],
), ),
), ),

View File

@@ -230,9 +230,9 @@ class VideoHttp {
}); });
try { try {
var res = epid != null var res = await Request().get(
? await Request().get(Api.bangumiVideoUrl, queryParameters: params) epid != null ? Api.bangumiVideoUrl : Api.videoUrl,
: await Request().get(Api.videoUrl, queryParameters: params); queryParameters: params);
if (res.data['code'] == 0) { if (res.data['code'] == 0) {
late PlayUrlModel data; late PlayUrlModel data;
if (epid != null) { if (epid != null) {

View File

@@ -82,7 +82,7 @@ class _BangumiIntroPanelState extends State<BangumiIntroPanel>
return switch (loadingState) { return switch (loadingState) {
Loading() => BangumiInfo( Loading() => BangumiInfo(
heroTag: widget.heroTag, heroTag: widget.heroTag,
loadingStatus: true, isLoading: true,
bangumiDetail: null, bangumiDetail: null,
cid: cid, cid: cid,
showEpisodes: widget.showEpisodes, showEpisodes: widget.showEpisodes,
@@ -90,7 +90,7 @@ class _BangumiIntroPanelState extends State<BangumiIntroPanel>
), ),
Success() => BangumiInfo( Success() => BangumiInfo(
heroTag: widget.heroTag, heroTag: widget.heroTag,
loadingStatus: false, isLoading: false,
bangumiDetail: loadingState.response, bangumiDetail: loadingState.response,
cid: cid, cid: cid,
showEpisodes: widget.showEpisodes, showEpisodes: widget.showEpisodes,
@@ -111,7 +111,7 @@ class _BangumiIntroPanelState extends State<BangumiIntroPanel>
class BangumiInfo extends StatefulWidget { class BangumiInfo extends StatefulWidget {
const BangumiInfo({ const BangumiInfo({
super.key, super.key,
this.loadingStatus = false, this.isLoading = false,
this.bangumiDetail, this.bangumiDetail,
this.cid, this.cid,
required this.showEpisodes, required this.showEpisodes,
@@ -119,7 +119,7 @@ class BangumiInfo extends StatefulWidget {
required this.heroTag, required this.heroTag,
}); });
final bool loadingStatus; final bool isLoading;
final BangumiInfoModel? bangumiDetail; final BangumiInfoModel? bangumiDetail;
final int? cid; final int? cid;
final Function showEpisodes; final Function showEpisodes;
@@ -219,11 +219,13 @@ class _BangumiInfoState extends State<BangumiInfo>
MediaQuery.of(context).orientation == Orientation.landscape; MediaQuery.of(context).orientation == Orientation.landscape;
return SliverPadding( return SliverPadding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
left: StyleString.safeSpace, left: StyleString.safeSpace,
right: StyleString.safeSpace, right: StyleString.safeSpace,
top: isLandscape ? 10 : 20), top: StyleString.safeSpace,
bottom: StyleString.safeSpace + MediaQuery.paddingOf(context).bottom,
),
sliver: SliverToBoxAdapter( sliver: SliverToBoxAdapter(
child: !widget.loadingStatus || bangumiItem != null child: !widget.isLoading || bangumiItem != null
? Column( ? Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -232,19 +234,33 @@ class _BangumiInfoState extends State<BangumiInfo>
children: [ children: [
Stack( Stack(
children: [ children: [
NetworkImgLayer( GestureDetector(
width: isLandscape ? 160 : 105, onTap: () => context.imageView(
height: isLandscape ? 105 : 160, imgList: [
src: !widget.loadingStatus !widget.isLoading
? widget.bangumiDetail!.cover! ? widget.bangumiDetail!.cover!
: bangumiItem!.cover!, : bangumiItem!.cover!
semanticsLabel: '封面', ],
),
child: Hero(
tag: !widget.isLoading
? widget.bangumiDetail!.cover!
: bangumiItem!.cover!,
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 && if (bangumiItem != null &&
bangumiItem!.rating != null) bangumiItem!.rating != null)
PBadge( PBadge(
text: text:
'评分 ${!widget.loadingStatus ? widget.bangumiDetail!.rating!['score']! : bangumiItem!.rating!['score']!}', '评分 ${!widget.isLoading ? widget.bangumiDetail!.rating!['score']! : bangumiItem!.rating!['score']!}',
top: null, top: null,
right: 6, right: 6,
bottom: 6, bottom: 6,
@@ -254,19 +270,20 @@ class _BangumiInfoState extends State<BangumiInfo>
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
child: InkWell( child: GestureDetector(
onTap: showIntroDetail, onTap: showIntroDetail,
child: SizedBox( child: SizedBox(
height: isLandscape ? 103 : 158, height: isLandscape ? 115 : 115 / 0.75,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
!widget.loadingStatus !widget.isLoading
? widget.bangumiDetail!.title! ? widget.bangumiDetail!.title!
: bangumiItem!.title!, : bangumiItem!.title!,
style: const TextStyle( style: const TextStyle(
@@ -280,8 +297,12 @@ class _BangumiInfoState extends State<BangumiInfo>
Obx( Obx(
() => FilledButton.tonal( () => FilledButton.tonal(
style: FilledButton.styleFrom( style: FilledButton.styleFrom(
tapTargetSize:
MaterialTapTargetSize.shrinkWrap,
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 10), horizontal: 20,
vertical: 10,
),
visualDensity: const VisualDensity( visualDensity: const VisualDensity(
horizontal: -2, horizontal: -2,
vertical: -2, vertical: -2,
@@ -330,7 +351,7 @@ class _BangumiInfoState extends State<BangumiInfo>
statView( statView(
context: context, context: context,
theme: 'gray', theme: 'gray',
view: !widget.loadingStatus view: !widget.isLoading
? widget.bangumiDetail!.stat!['views'] ? widget.bangumiDetail!.stat!['views']
: bangumiItem!.stat!['views'], : bangumiItem!.stat!['views'],
size: 'medium', size: 'medium',
@@ -339,7 +360,7 @@ class _BangumiInfoState extends State<BangumiInfo>
statDanMu( statDanMu(
context: context, context: context,
theme: 'gray', theme: 'gray',
danmu: !widget.loadingStatus danmu: !widget.isLoading
? widget ? widget
.bangumiDetail!.stat!['danmakus'] .bangumiDetail!.stat!['danmakus']
: bangumiItem!.stat!['danmakus'], : bangumiItem!.stat!['danmakus'],
@@ -372,7 +393,7 @@ class _BangumiInfoState extends State<BangumiInfo>
t: t), t: t),
const Spacer(), const Spacer(),
Text( Text(
'简介:${!widget.loadingStatus ? widget.bangumiDetail!.evaluate! : bangumiItem!.evaluate!}', '简介:${!widget.isLoading ? widget.bangumiDetail!.evaluate! : bangumiItem!.evaluate!}',
maxLines: isLandscape ? 2 : 3, maxLines: isLandscape ? 2 : 3,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
@@ -401,7 +422,7 @@ class _BangumiInfoState extends State<BangumiInfo>
// 点赞收藏转发 布局样式2 // 点赞收藏转发 布局样式2
actionGrid(context, bangumiIntroController), actionGrid(context, bangumiIntroController),
// 番剧分p // 番剧分p
if ((!widget.loadingStatus && if ((!widget.isLoading &&
widget.bangumiDetail!.episodes!.isNotEmpty) || widget.bangumiDetail!.episodes!.isNotEmpty) ||
bangumiItem != null && bangumiItem != null &&
bangumiItem!.episodes!.isNotEmpty) ...[ bangumiItem!.episodes!.isNotEmpty) ...[
@@ -452,7 +473,7 @@ class _BangumiInfoState extends State<BangumiInfo>
selectStatus: bangumiIntroController.hasLike.value, selectStatus: bangumiIntroController.hasLike.value,
loadingStatus: false, loadingStatus: false,
semanticsLabel: '点赞', semanticsLabel: '点赞',
text: !widget.loadingStatus text: !widget.isLoading
? Utils.numFormat(widget.bangumiDetail!.stat!['likes']!) ? Utils.numFormat(widget.bangumiDetail!.stat!['likes']!)
: Utils.numFormat( : Utils.numFormat(
bangumiItem!.stat!['likes']!, bangumiItem!.stat!['likes']!,
@@ -482,7 +503,7 @@ class _BangumiInfoState extends State<BangumiInfo>
selectStatus: bangumiIntroController.hasCoin.value, selectStatus: bangumiIntroController.hasCoin.value,
loadingStatus: false, loadingStatus: false,
semanticsLabel: '投币', semanticsLabel: '投币',
text: !widget.loadingStatus text: !widget.isLoading
? Utils.numFormat(widget.bangumiDetail!.stat!['coins']!) ? Utils.numFormat(widget.bangumiDetail!.stat!['coins']!)
: Utils.numFormat( : Utils.numFormat(
bangumiItem!.stat!['coins']!, bangumiItem!.stat!['coins']!,
@@ -499,7 +520,7 @@ class _BangumiInfoState extends State<BangumiInfo>
selectStatus: bangumiIntroController.hasFav.value, selectStatus: bangumiIntroController.hasFav.value,
loadingStatus: false, loadingStatus: false,
semanticsLabel: '收藏', semanticsLabel: '收藏',
text: !widget.loadingStatus text: !widget.isLoading
? Utils.numFormat( ? Utils.numFormat(
widget.bangumiDetail!.stat!['favorite']!) widget.bangumiDetail!.stat!['favorite']!)
: Utils.numFormat( : Utils.numFormat(
@@ -515,7 +536,7 @@ class _BangumiInfoState extends State<BangumiInfo>
selectStatus: false, selectStatus: false,
loadingStatus: false, loadingStatus: false,
semanticsLabel: '评论', semanticsLabel: '评论',
text: !widget.loadingStatus text: !widget.isLoading
? Utils.numFormat(widget.bangumiDetail!.stat!['reply']!) ? Utils.numFormat(widget.bangumiDetail!.stat!['reply']!)
: Utils.numFormat(bangumiItem!.stat!['reply']!), : Utils.numFormat(bangumiItem!.stat!['reply']!),
), ),
@@ -525,7 +546,7 @@ class _BangumiInfoState extends State<BangumiInfo>
selectStatus: false, selectStatus: false,
loadingStatus: false, loadingStatus: false,
semanticsLabel: '转发', semanticsLabel: '转发',
text: !widget.loadingStatus text: !widget.isLoading
? Utils.numFormat(widget.bangumiDetail!.stat!['share']!) ? Utils.numFormat(widget.bangumiDetail!.stat!['share']!)
: Utils.numFormat(bangumiItem!.stat!['share']!)), : Utils.numFormat(bangumiItem!.stat!['share']!)),
], ],
@@ -543,8 +564,8 @@ class _BangumiInfoState extends State<BangumiInfo>
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, loadingStatus: widget.isLoading,
text: !widget.loadingStatus text: !widget.isLoading
? widget.bangumiDetail!.stat!['likes']!.toString() ? widget.bangumiDetail!.stat!['likes']!.toString()
: '-', : '-',
), ),
@@ -555,8 +576,8 @@ class _BangumiInfoState extends State<BangumiInfo>
icon: const Icon(FontAwesomeIcons.b), icon: const Icon(FontAwesomeIcons.b),
onTap: () => handleState(videoIntroController.actionCoinVideo), onTap: () => handleState(videoIntroController.actionCoinVideo),
selectStatus: videoIntroController.hasCoin.value, selectStatus: videoIntroController.hasCoin.value,
loadingStatus: widget.loadingStatus, loadingStatus: widget.isLoading,
text: !widget.loadingStatus text: !widget.isLoading
? widget.bangumiDetail!.stat!['coins']!.toString() ? widget.bangumiDetail!.stat!['coins']!.toString()
: '-', : '-',
), ),
@@ -567,8 +588,8 @@ class _BangumiInfoState extends State<BangumiInfo>
icon: const Icon(FontAwesomeIcons.heart), icon: const Icon(FontAwesomeIcons.heart),
onTap: () => showFavBottomSheet(), onTap: () => showFavBottomSheet(),
selectStatus: videoIntroController.hasFav.value, selectStatus: videoIntroController.hasFav.value,
loadingStatus: widget.loadingStatus, loadingStatus: widget.isLoading,
text: !widget.loadingStatus text: !widget.isLoading
? widget.bangumiDetail!.stat!['favorite']!.toString() ? widget.bangumiDetail!.stat!['favorite']!.toString()
: '-', : '-',
), ),
@@ -580,8 +601,8 @@ class _BangumiInfoState extends State<BangumiInfo>
videoDetailCtr.tabCtr.animateTo(1); videoDetailCtr.tabCtr.animateTo(1);
}, },
selectStatus: false, selectStatus: false,
loadingStatus: widget.loadingStatus, loadingStatus: widget.isLoading,
text: !widget.loadingStatus text: !widget.isLoading
? widget.bangumiDetail!.stat!['reply']!.toString() ? widget.bangumiDetail!.stat!['reply']!.toString()
: '-', : '-',
), ),
@@ -590,7 +611,7 @@ class _BangumiInfoState extends State<BangumiInfo>
icon: const Icon(FontAwesomeIcons.share), icon: const Icon(FontAwesomeIcons.share),
onTap: () => videoIntroController.actionShareVideo(), onTap: () => videoIntroController.actionShareVideo(),
selectStatus: false, selectStatus: false,
loadingStatus: widget.loadingStatus, loadingStatus: widget.isLoading,
text: '转发'), text: '转发'),
]); ]);
} }
@@ -666,7 +687,7 @@ class AreasAndPubTime extends StatelessWidget {
return Row( return Row(
children: [ children: [
Text( Text(
!widget.loadingStatus !widget.isLoading
? (widget.bangumiDetail!.areas!.isNotEmpty ? (widget.bangumiDetail!.areas!.isNotEmpty
? widget.bangumiDetail!.areas!.first['name'] ? widget.bangumiDetail!.areas!.first['name']
: '') : '')
@@ -680,7 +701,7 @@ class AreasAndPubTime extends StatelessWidget {
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Text( Text(
!widget.loadingStatus !widget.isLoading
? widget.bangumiDetail!.publish!['pub_time_show'] ? widget.bangumiDetail!.publish!['pub_time_show']
: bangumiItem!.publish!['pub_time_show'], : bangumiItem!.publish!['pub_time_show'],
style: TextStyle( style: TextStyle(
@@ -708,7 +729,7 @@ class NewEpDesc extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Text( return Text(
!widget.loadingStatus !widget.isLoading
? widget.bangumiDetail!.newEp!['desc'] ? widget.bangumiDetail!.newEp!['desc']
: bangumiItem!.newEp!['desc'], : bangumiItem!.newEp!['desc'],
style: TextStyle( style: TextStyle(

View File

@@ -62,8 +62,10 @@ class _BangumiPageState extends State<BangumiPage>
super.build(context); super.build(context);
return refreshIndicator( return refreshIndicator(
onRefresh: () async { onRefresh: () async {
await _bangumiController.onRefresh(); await Future.wait([
await _bangumiController.queryBangumiFollow(); _bangumiController.onRefresh(),
_bangumiController.queryBangumiFollow(),
]);
}, },
child: CustomScrollView( child: CustomScrollView(
controller: _bangumiController.scrollController, controller: _bangumiController.scrollController,
@@ -76,8 +78,7 @@ class _BangumiPageState extends State<BangumiPage>
child: Column( child: Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(left: 16),
top: StyleString.safeSpace, bottom: 10, left: 16),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@@ -99,7 +100,8 @@ class _BangumiPageState extends State<BangumiPage>
), ),
), ),
SizedBox( SizedBox(
height: Grid.maxRowWidth * 1, height: Grid.maxRowWidth / 2 / 0.75 +
MediaQuery.textScalerOf(context).scale(50),
child: Obx( child: Obx(
() => _buildFollowBody( () => _buildFollowBody(
_bangumiController.followState.value), _bangumiController.followState.value),
@@ -143,13 +145,13 @@ class _BangumiPageState extends State<BangumiPage>
? SliverGrid( ? SliverGrid(
gridDelegate: SliverGridDelegateWithExtentAndRatio( gridDelegate: SliverGridDelegateWithExtentAndRatio(
// 行间距 // 行间距
mainAxisSpacing: StyleString.cardSpace - 2, mainAxisSpacing: StyleString.cardSpace,
// 列间距 // 列间距
crossAxisSpacing: StyleString.cardSpace, crossAxisSpacing: StyleString.cardSpace,
// 最大宽度 // 最大宽度
maxCrossAxisExtent: Grid.maxRowWidth / 3 * 2, maxCrossAxisExtent: Grid.maxRowWidth / 3 * 2,
childAspectRatio: 0.65, childAspectRatio: 0.75,
mainAxisExtent: MediaQuery.textScalerOf(context).scale(60), mainAxisExtent: MediaQuery.textScalerOf(context).scale(50),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) { (BuildContext context, int index) {
@@ -180,7 +182,6 @@ class _BangumiPageState extends State<BangumiPage>
itemBuilder: (context, index) { itemBuilder: (context, index) {
return Container( return Container(
width: Grid.maxRowWidth / 2, width: Grid.maxRowWidth / 2,
height: Grid.maxRowWidth * 1,
margin: EdgeInsets.only( margin: EdgeInsets.only(
left: StyleString.safeSpace, left: StyleString.safeSpace,
right: index == loadingState.response.length - 1 right: index == loadingState.response.length - 1

View File

@@ -83,14 +83,9 @@ class BangumiCardV extends StatelessWidget {
child: Column( child: Column(
children: [ children: [
ClipRRect( ClipRRect(
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.all(StyleString.imgRadius),
topLeft: StyleString.imgRadius,
topRight: StyleString.imgRadius,
bottomLeft: StyleString.imgRadius,
bottomRight: StyleString.imgRadius,
),
child: AspectRatio( child: AspectRatio(
aspectRatio: 0.65, aspectRatio: 0.75,
child: LayoutBuilder(builder: (context, boxConstraints) { child: LayoutBuilder(builder: (context, boxConstraints) {
final double maxWidth = boxConstraints.maxWidth; final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight; final double maxHeight = boxConstraints.maxHeight;
@@ -106,11 +101,12 @@ class BangumiCardV extends StatelessWidget {
), ),
if (bangumiItem.badge != null) if (bangumiItem.badge != null)
PBadge( PBadge(
text: bangumiItem.badge, text: bangumiItem.badge,
top: 6, top: 6,
right: 6, right: 6,
bottom: null, bottom: null,
left: null), left: null,
),
if (bangumiItem.order != null) if (bangumiItem.order != null)
PBadge( PBadge(
text: bangumiItem.order, text: bangumiItem.order,

View File

@@ -79,7 +79,7 @@ class BangumiCardVMemberHome extends StatelessWidget {
bottomRight: StyleString.imgRadius, bottomRight: StyleString.imgRadius,
), ),
child: AspectRatio( child: AspectRatio(
aspectRatio: 0.65, aspectRatio: 0.75,
child: LayoutBuilder(builder: (context, boxConstraints) { child: LayoutBuilder(builder: (context, boxConstraints) {
final double maxWidth = boxConstraints.maxWidth; final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight; final double maxHeight = boxConstraints.maxHeight;

View File

@@ -257,7 +257,7 @@ class _BangumiPanelState extends State<BangumiPanel> {
); );
}, },
), ),
) ),
], ],
); );
} }

View File

@@ -90,8 +90,10 @@ class _DynamicsTabPageState extends State<DynamicsTabPage>
onRefresh: () async { onRefresh: () async {
dynamicsWaterfallFlow = GStorage.setting dynamicsWaterfallFlow = GStorage.setting
.get(SettingBoxKey.dynamicsWaterfallFlow, defaultValue: true); .get(SettingBoxKey.dynamicsWaterfallFlow, defaultValue: true);
await _dynamicsTabController.onRefresh(); await Future.wait([
await dynamicsController.queryFollowUp(); _dynamicsTabController.onRefresh(),
dynamicsController.queryFollowUp(),
]);
}, },
child: CustomScrollView( child: CustomScrollView(
physics: const AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),

View File

@@ -1,3 +1,4 @@
import 'package:PiliPalaX/common/widgets/icon_button.dart';
import 'package:PiliPalaX/common/widgets/image_save.dart'; import 'package:PiliPalaX/common/widgets/image_save.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -215,12 +216,13 @@ class FavVideoCardH extends StatelessWidget {
if (searchType != 1 && isOwner) if (searchType != 1 && isOwner)
Positioned( Positioned(
right: 0, right: 0,
bottom: -4, bottom: 0,
child: IconButton( child: iconButton(
context: context,
icon: Icons.clear,
tooltip: '取消收藏', tooltip: '取消收藏',
style: ButtonStyle( iconColor: Theme.of(context).colorScheme.onSurfaceVariant,
padding: WidgetStateProperty.all(EdgeInsets.zero), bgColor: Colors.transparent,
),
onPressed: () { onPressed: () {
showDialog( showDialog(
context: Get.context!, context: Get.context!,
@@ -250,11 +252,6 @@ class FavVideoCardH extends StatelessWidget {
}, },
); );
}, },
icon: Icon(
Icons.clear_outlined,
color: Theme.of(context).colorScheme.outline,
size: 18,
),
), ),
), ),
], ],

View File

@@ -372,7 +372,7 @@ class HistoryItem extends StatelessWidget {
icon: Icon( icon: Icon(
Icons.more_vert_outlined, Icons.more_vert_outlined,
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
size: 14, size: 18,
), ),
position: PopupMenuPosition.under, position: PopupMenuPosition.under,
// constraints: const BoxConstraints(maxHeight: 35), // constraints: const BoxConstraints(maxHeight: 35),

View File

@@ -221,10 +221,9 @@ class _LaterPageState extends State<LaterPage> {
), ),
), ),
Positioned( Positioned(
right: 0, right: 12,
bottom: 0, bottom: 0,
child: iconButton( child: iconButton(
size: 30,
tooltip: '移除', tooltip: '移除',
context: context, context: context,
onPressed: () { onPressed: () {

View File

@@ -64,9 +64,9 @@ class _MemberBangumiState extends State<MemberBangumi>
mainAxisSpacing: StyleString.cardSpace, mainAxisSpacing: StyleString.cardSpace,
crossAxisSpacing: StyleString.cardSpace, crossAxisSpacing: StyleString.cardSpace,
maxCrossAxisExtent: Grid.maxRowWidth / 3 * 2, maxCrossAxisExtent: Grid.maxRowWidth / 3 * 2,
childAspectRatio: 0.65, childAspectRatio: 0.75,
mainAxisExtent: mainAxisExtent:
MediaQuery.textScalerOf(context).scale(60), MediaQuery.textScalerOf(context).scale(30),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(context, index) { (context, index) {

View File

@@ -64,7 +64,7 @@ class _MemberHomeState extends State<MemberHome>
maxCrossAxisExtent: Grid.maxRowWidth, maxCrossAxisExtent: Grid.maxRowWidth,
childAspectRatio: StyleString.aspectRatio, childAspectRatio: StyleString.aspectRatio,
mainAxisExtent: mainAxisExtent:
MediaQuery.textScalerOf(context).scale(90), MediaQuery.textScalerOf(context).scale(55),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(context, index) { (context, index) {
@@ -186,12 +186,12 @@ class _MemberHomeState extends State<MemberHome>
), ),
sliver: SliverGrid( sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithExtentAndRatio( gridDelegate: SliverGridDelegateWithExtentAndRatio(
mainAxisSpacing: StyleString.cardSpace - 2, mainAxisSpacing: StyleString.cardSpace,
crossAxisSpacing: StyleString.cardSpace, crossAxisSpacing: StyleString.cardSpace,
maxCrossAxisExtent: Grid.maxRowWidth / 3 * 2, maxCrossAxisExtent: Grid.maxRowWidth / 3 * 2,
childAspectRatio: 0.65, childAspectRatio: 0.75,
mainAxisExtent: mainAxisExtent:
MediaQuery.textScalerOf(context).scale(60), MediaQuery.textScalerOf(context).scale(30),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(context, index) { (context, index) {

View File

@@ -8,6 +8,7 @@ import 'package:PiliPalaX/common/widgets/pair.dart';
import 'package:PiliPalaX/common/widgets/segment_progress_bar.dart'; import 'package:PiliPalaX/common/widgets/segment_progress_bar.dart';
import 'package:PiliPalaX/http/danmaku.dart'; import 'package:PiliPalaX/http/danmaku.dart';
import 'package:PiliPalaX/http/init.dart'; import 'package:PiliPalaX/http/init.dart';
import 'package:PiliPalaX/http/loading_state.dart';
import 'package:PiliPalaX/http/user.dart'; import 'package:PiliPalaX/http/user.dart';
import 'package:PiliPalaX/models/video/later.dart'; import 'package:PiliPalaX/models/video/later.dart';
import 'package:PiliPalaX/models/video/play/subtitle.dart'; import 'package:PiliPalaX/models/video/play/subtitle.dart';
@@ -162,12 +163,10 @@ class VideoDetailController extends GetxController
/// tabs相关配置 /// tabs相关配置
int tabInitialIndex = 0; int tabInitialIndex = 0;
late TabController tabCtr; late TabController tabCtr;
RxList<String> tabs = <String>['简介', '评论'].obs;
// 请求返回的视频信息 // 请求返回的视频信息
late PlayUrlModel data; late PlayUrlModel data;
// 请求状态 Rx<LoadingState> videoState = LoadingState.loading().obs;
RxBool isLoading = false.obs;
/// 播放器配置 画质 音质 解码格式 /// 播放器配置 画质 音质 解码格式
late VideoQuality currentVideoQa; late VideoQuality currentVideoQa;
@@ -175,8 +174,6 @@ class VideoDetailController extends GetxController
late VideoDecodeFormats currentDecodeFormats; late VideoDecodeFormats currentDecodeFormats;
// 是否开始自动播放 存在多p的情况下第二p需要为true // 是否开始自动播放 存在多p的情况下第二p需要为true
RxBool autoPlay = true.obs; RxBool autoPlay = true.obs;
// 视频资源是否有效
RxBool isEffective = true.obs;
// 封面图的展示 // 封面图的展示
RxBool isShowCover = true.obs; RxBool isShowCover = true.obs;
// 硬解 // 硬解
@@ -1061,8 +1058,13 @@ class VideoDetailController extends GetxController
plPlayerController.headerControl = headerControl; plPlayerController.headerControl = headerControl;
} }
bool isQuerying = false;
// 视频链接 // 视频链接
Future queryVideoUrl() async { Future queryVideoUrl() async {
if (isQuerying) {
return;
}
isQuerying = true;
if (cacheVideoQa == null) { if (cacheVideoQa == null) {
await Connectivity().checkConnectivity().then((res) { await Connectivity().checkConnectivity().then((res) {
cacheVideoQa = res.contains(ConnectivityResult.wifi) cacheVideoQa = res.contains(ConnectivityResult.wifi)
@@ -1226,7 +1228,8 @@ class VideoDetailController extends GetxController
SmartDialog.showToast("错误(${result['code']}${result['msg']}"); SmartDialog.showToast("错误(${result['code']}${result['msg']}");
} }
} }
return result; isQuerying = false;
videoState.value = LoadingState.success(null);
} }
List<PostSegmentModel>? list; List<PostSegmentModel>? list;

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/http/loading_state.dart';
import 'package:PiliPalaX/utils/extension.dart';
import 'package:PiliPalaX/utils/utils.dart'; import 'package:PiliPalaX/utils/utils.dart';
import 'package:expandable/expandable.dart'; import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -146,7 +147,8 @@ class VideoIntroController extends GetxController
final videoDetailController = final videoDetailController =
Get.find<VideoDetailController>(tag: heroTag); Get.find<VideoDetailController>(tag: heroTag);
if (videoDetailController.videoItem['pic'] == null || if (videoDetailController.videoItem['pic'] == null ||
videoDetailController.videoItem['pic'] == '') { videoDetailController.videoItem['pic'] == '' ||
videoDetailController.videoUrl.isNullOrEmpty) {
videoDetailController.videoItem['pic'] = result['data'].pic; videoDetailController.videoItem['pic'] = result['data'].pic;
} }
} catch (_) {} } catch (_) {}

View File

@@ -653,6 +653,10 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
videoIntroController videoIntroController
.queryVideoIntroData.value["status"] = true; .queryVideoIntroData.value["status"] = true;
videoIntroController.queryVideoIntro(); videoIntroController.queryVideoIntro();
if (videoDetailCtr.videoUrl.isNullOrEmpty &&
videoDetailCtr.isQuerying.not) {
videoDetailCtr.queryVideoUrl();
}
}, },
label: const Text("点此重新加载"), label: const Text("点此重新加载"),
), ),

View File

@@ -73,7 +73,6 @@ class _VideoDetailPageState extends State<VideoDetailPage>
double doubleOffset = 0; double doubleOffset = 0;
late Future _futureBuilderFuture;
// 自动退出全屏 // 自动退出全屏
late bool autoExitFullscreen; late bool autoExitFullscreen;
late bool autoPlayEnable; late bool autoPlayEnable;
@@ -194,7 +193,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
// 获取视频资源,初始化播放器 // 获取视频资源,初始化播放器
Future<void> videoSourceInit() async { Future<void> videoSourceInit() async {
_futureBuilderFuture = videoDetailController.queryVideoUrl(); videoDetailController.queryVideoUrl();
if (videoDetailController.showReply) { if (videoDetailController.showReply) {
_videoReplyController.queryData(); _videoReplyController.queryData();
} }
@@ -289,6 +288,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
videoDetailController.audioUrl == null) { videoDetailController.audioUrl == null) {
// SmartDialog.showToast('not initialized'); // SmartDialog.showToast('not initialized');
debugPrint('not initialized'); debugPrint('not initialized');
if (videoDetailController.isQuerying.not) {
videoDetailController.queryVideoUrl();
}
return; return;
} }
plPlayerController = videoDetailController.plPlayerController; plPlayerController = videoDetailController.plPlayerController;
@@ -985,8 +987,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
Widget get manualPlayerWidget => Obx( Widget get manualPlayerWidget => Obx(
() => Visibility( () => Visibility(
visible: videoDetailController.isShowCover.value && visible: videoDetailController.isShowCover.value,
videoDetailController.isEffective.value,
child: Stack( child: Stack(
children: [ children: [
Positioned( Positioned(
@@ -1084,42 +1085,35 @@ class _VideoDetailPageState extends State<VideoDetailPage>
), ),
); );
Widget get plPlayer => FutureBuilder( Widget get plPlayer => Obx(
future: _futureBuilderFuture, () => videoDetailController.videoState.value is! Success
builder: (BuildContext context, AsyncSnapshot snapshot) { ? nil
if (snapshot.hasData && snapshot.data['status']) { : !videoDetailController.autoPlay.value ||
return Obx( plPlayerController == null ||
() => !videoDetailController.autoPlay.value || plPlayerController!.videoController == null
plPlayerController == null || ? nil
plPlayerController!.videoController == null : PLVideoPlayer(
? nil plPlayerController: plPlayerController!,
: PLVideoPlayer( videoIntroController:
plPlayerController: plPlayerController!, videoDetailController.videoType == SearchType.video
videoIntroController: ? videoIntroController
videoDetailController.videoType == SearchType.video : null,
? videoIntroController bangumiIntroController: videoDetailController.videoType ==
: null, SearchType.media_bangumi
bangumiIntroController: videoDetailController.videoType == ? bangumiIntroController
SearchType.media_bangumi : null,
? bangumiIntroController headerControl: videoDetailController.headerControl,
: null, danmuWidget: Obx(
headerControl: videoDetailController.headerControl, () => PlDanmaku(
danmuWidget: Obx( key: Key(
() => PlDanmaku( videoDetailController.danmakuCid.value.toString()),
key: Key(videoDetailController.danmakuCid.value cid: videoDetailController.danmakuCid.value,
.toString()), playerController: plPlayerController!,
cid: videoDetailController.danmakuCid.value,
playerController: plPlayerController!,
),
), ),
showEpisodes: showEpisodes,
showViewPoints: showViewPoints,
), ),
); showEpisodes: showEpisodes,
} else { showViewPoints: showViewPoints,
return const SizedBox(); ),
}
},
); );
Widget autoChoose(Widget childWhenDisabled) { Widget autoChoose(Widget childWhenDisabled) {

View File

@@ -71,8 +71,10 @@ class _WhisperPageState extends State<WhisperPage> {
), ),
body: refreshIndicator( body: refreshIndicator(
onRefresh: () async { onRefresh: () async {
await _whisperController.queryMsgFeedUnread(); await Future.wait([
await _whisperController.onRefresh(); _whisperController.queryMsgFeedUnread(),
_whisperController.onRefresh(),
]);
}, },
child: SingleChildScrollView( child: SingleChildScrollView(
controller: _scrollController, controller: _scrollController,

View File

@@ -53,6 +53,10 @@ extension StringExt on String {
String get http2https => replaceFirst(RegExp("^http://"), "https://"); String get http2https => replaceFirst(RegExp("^http://"), "https://");
} }
extension StringNullExt on String? {
bool get isNullOrEmpty => this == null || this!.isEmpty;
}
extension BoolExt on bool { extension BoolExt on bool {
bool get not => !this; bool get not => !this;
} }