* mod: ui

* fix: -400

* tweaks

* update

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* tweak [skip ci]

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

* tweak [skip ci]

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>

---------

Co-authored-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
My-Responsitories
2025-10-12 12:12:44 +08:00
committed by GitHub
parent 16f577f3fd
commit e44419e088
7 changed files with 194 additions and 191 deletions

View File

@@ -10,7 +10,6 @@ import 'package:PiliPlus/grpc/bilibili/app/listener/v1.pb.dart'
PlaylistSource,
PlayInfo,
ThumbUpReq_ThumbType;
import 'package:PiliPlus/grpc/bilibili/pagination.pb.dart';
import 'package:PiliPlus/http/constants.dart';
import 'package:PiliPlus/http/ua_type.dart';
import 'package:PiliPlus/pages/common/common_intro_controller.dart'
@@ -28,6 +27,7 @@ import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:PiliPlus/utils/video_utils.dart';
import 'package:fixnum/fixnum.dart' show Int64;
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -41,6 +41,7 @@ class AudioController extends GetxController
late List<Int64> subId;
late int itemType;
late final PlaylistSource from;
late final isVideo = itemType == 1;
final Rx<DetailItem?> audioItem = Rx<DetailItem?>(null);
@@ -120,10 +121,10 @@ class AudioController extends GetxController
subId: isInit ? subId : null,
itemType: isInit ? itemType : null,
from: isInit ? from : null,
pagination: isLoadPrev
? Pagination(next: _prev)
next: isLoadPrev
? _prev
: isLoadNext
? Pagination(next: _next)
? _next
: null,
);
if (res.isSuccess) {
@@ -174,7 +175,7 @@ class AudioController extends GetxController
}
}
Future<void> _onPlay(PlayURLResp data) async {
void _onPlay(PlayURLResp data) {
final PlayInfo? playInfo = data.playerInfo.values.firstOrNull;
if (playInfo != null) {
if (playInfo.hasPlayDash()) {
@@ -188,7 +189,7 @@ class AudioController extends GetxController
(e) => e.id <= cacheAudioQa,
(a, b) => a.id > b.id ? a : b,
);
_onOpenMedia(audio.baseUrl);
_onOpenMedia(VideoUtils.getCdnUrl(audio.baseUrl));
} else if (playInfo.hasPlayUrl()) {
final playUrl = playInfo.playUrl;
final durls = playUrl.durl;
@@ -197,7 +198,7 @@ class AudioController extends GetxController
}
final durl = durls.first;
position.value = Duration.zero;
_onOpenMedia(durl.url);
_onOpenMedia(VideoUtils.getDurlCdnUrl(durl));
}
}
}
@@ -380,7 +381,7 @@ class AudioController extends GetxController
void showReply() {
MainReplyPage.toMainReplyPage(
oid: oid.toInt(),
replyType: itemType == 1 ? 1 : 14,
replyType: isVideo ? 1 : 14,
);
}
@@ -388,7 +389,7 @@ class AudioController extends GetxController
showDialog(
context: context,
builder: (_) {
final audioUrl = itemType == 1
final audioUrl = isVideo
? '${HttpString.baseUrl}/video/${IdUtils.av2bv(oid.toInt())}'
: '${HttpString.baseUrl}/audio/au$oid';
return AlertDialog(
@@ -452,7 +453,7 @@ class AudioController extends GetxController
useSafeArea: true,
builder: (context) => RepostPanel(
rid: oid.toInt(),
dynType: itemType == 1 ? 8 : 256,
dynType: isVideo ? 8 : 256,
pic: audioItem.arc.cover,
title: audioItem.arc.title,
uname: audioItem.owner.name,
@@ -461,7 +462,7 @@ class AudioController extends GetxController
}
},
),
if (itemType == 1)
if (isVideo)
ListTile(
dense: true,
title: const Text(
@@ -563,7 +564,7 @@ class AudioController extends GetxController
// }
@override
(Object, int) get getFavRidType => (oid, itemType == 1 ? 2 : 12);
(Object, int) get getFavRidType => (oid, isVideo ? 2 : 12);
@override
void updateFavCount(int count) {

View File

@@ -19,6 +19,7 @@ import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_key.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/gestures.dart' show TapGestureRecognizer;
import 'package:flutter/material.dart' hide DraggableScrollableSheet;
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
@@ -59,6 +60,12 @@ class _AudioPageState extends State<AudioPage> {
tag: Utils.generateRandomString(8),
);
@override
void didChangeDependencies() {
super.didChangeDependencies();
_controller.didChangeDependencies(context);
}
@override
Widget build(BuildContext context) {
final colorScheme = ColorScheme.of(context);
@@ -66,17 +73,18 @@ class _AudioPageState extends State<AudioPage> {
final padding = MediaQuery.viewPaddingOf(context);
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
onPressed: _showMore,
icon: const Icon(Icons.more_vert),
),
const SizedBox(width: 5),
],
actions: _controller.isVideo
? [
IconButton(
onPressed: _showMore,
icon: const Icon(Icons.more_vert),
),
const SizedBox(width: 5),
]
: null,
),
body: Padding(
padding: EdgeInsets.only(
top: 20,
left: 20 + padding.left,
right: 20 + padding.right,
bottom: 30 + padding.bottom,
@@ -96,11 +104,7 @@ class _AudioPageState extends State<AudioPage> {
spacing: 12,
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [_buildInfo(colorScheme, isPortrait)],
),
child: _buildInfo(colorScheme, isPortrait),
),
Expanded(
child: Column(
@@ -175,6 +179,9 @@ class _AudioPageState extends State<AudioPage> {
onRefresh: () => _controller.loadPrev(context),
child: CustomScrollView(
controller: scrollController,
physics: const AlwaysScrollableScrollPhysics(
parent: ClampingScrollPhysics(),
),
slivers: [
SliverPadding(
padding: EdgeInsets.only(
@@ -475,18 +482,17 @@ class _AudioPageState extends State<AudioPage> {
// _controller.showTimerDialog();
// },
// ),
if (_controller.itemType == 1)
ListTile(
dense: true,
title: const Text(
'举报',
style: TextStyle(fontSize: 14),
),
onTap: () {
Get.back();
PageUtils.reportVideo(_controller.oid.toInt());
},
ListTile(
dense: true,
title: const Text(
'举报',
style: TextStyle(fontSize: 14),
),
onTap: () {
Get.back();
PageUtils.reportVideo(_controller.oid.toInt());
},
),
],
),
);
@@ -565,6 +571,21 @@ class _AudioPageState extends State<AudioPage> {
audioItem.stat.share,
),
),
if (audioItem.associatedItem.hasOid() &&
audioItem.associatedItem.subId.isNotEmpty)
ActionItem(
icon: const Icon(FontAwesomeIcons.circlePlay),
onTap: () {
_controller.player?.pause();
PageUtils.toVideoPage(
cid: audioItem.associatedItem.subId.first.toInt(),
aid: audioItem.associatedItem.oid.toInt(),
);
},
selectStatus: false,
semanticsLabel: '看MV',
text: '看MV',
),
],
),
);
@@ -694,159 +715,114 @@ class _AudioPageState extends State<AudioPage> {
if (audioItem != null) {
final cover = audioItem.arc.cover.http2https;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: GestureDetector(
onTap: () => PageUtils.imageView(
imgList: [SourceModel(url: cover)],
),
child: Hero(
tag: cover,
child: NetworkImgLayer(
src: cover,
width: 150,
height: 150,
),
Expanded(
child: Center(
child: ListView(
key: const PageStorageKey(_AudioPageState),
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
children: [
Center(
child: GestureDetector(
onTap: () => PageUtils.imageView(
imgList: [SourceModel(url: cover)],
),
child: Hero(
tag: cover,
child: NetworkImgLayer(
src: cover,
width: 170,
height: 170,
),
),
),
),
const SizedBox(height: 12),
SelectableText(
audioItem.arc.title,
style: const TextStyle(
height: 1.7,
fontSize: 16,
),
),
const SizedBox(height: 12),
if (audioItem.owner.hasName()) ...[
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
_controller.player?.pause();
Get.toNamed('/member?mid=${audioItem.owner.mid}');
},
child: Row(
spacing: 6,
mainAxisSize: MainAxisSize.min,
children: [
if (audioItem.owner.hasAvatar())
NetworkImgLayer(
src: audioItem.owner.avatar,
width: 22,
height: 22,
type: ImageType.avatar,
),
Text(
audioItem.owner.name,
),
],
),
),
const SizedBox(height: 10),
],
Row(
children: [
Icon(
size: 14,
Icons.headphones_outlined,
color: colorScheme.outline,
),
Text.rich(
TextSpan(
children: [
TextSpan(
text:
' ${NumUtils.numFormat(audioItem.stat.view)} '
'${DateFormatUtils.dateFormat(audioItem.arc.publish.toInt(), long: DateFormatUtils.longFormatD)} ',
),
TextSpan(
text: audioItem.arc.displayedOid,
style: TextStyle(color: colorScheme.secondary),
recognizer: TapGestureRecognizer()
..onTap = () => Utils.copyText(
audioItem.arc.displayedOid,
),
),
],
),
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
if (audioItem.arc.hasDesc()) ...[
const SizedBox(height: 10),
SelectableText(audioItem.arc.desc),
],
],
),
),
),
const SizedBox(height: 12),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: SelectableText(
audioItem.arc.title,
style: const TextStyle(
height: 1.7,
fontSize: 15,
),
),
),
iconButton(
context: context,
icon: Icons.keyboard_arrow_down,
onPressed: () => _showIntro(audioItem),
bgColor: Colors.transparent,
iconColor: colorScheme.outline,
size: 26,
iconSize: 18,
),
],
),
const SizedBox(height: 10),
if (audioItem.owner.hasName())
Row(
spacing: 6,
mainAxisSize: MainAxisSize.min,
children: [
if (audioItem.owner.hasAvatar())
NetworkImgLayer(
src: audioItem.owner.avatar,
width: 22,
height: 22,
type: ImageType.avatar,
),
Text(
audioItem.owner.name,
),
],
),
if (isPortrait)
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: _buildActions(audioItem),
),
),
if (isPortrait) ...[
const SizedBox(height: 10),
_buildActions(audioItem),
],
],
);
}
return const SizedBox.shrink();
});
}
void _showIntro(DetailItem audioItem) {
final arc = audioItem.arc;
showModalBottomSheet(
context: context,
useSafeArea: true,
constraints: BoxConstraints(
maxWidth: min(640, context.mediaQueryShortestSide),
),
builder: (context) {
final colorScheme = ColorScheme.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InkWell(
onTap: Get.back,
borderRadius: StyleString.bottomSheetRadius,
child: SizedBox(
height: 35,
child: Center(
child: Container(
width: 32,
height: 3,
decoration: BoxDecoration(
color: colorScheme.outline,
borderRadius: const BorderRadius.all(
Radius.circular(3),
),
),
),
),
),
),
Padding(
padding: EdgeInsets.only(
top: 12,
left: 20,
right: 20,
bottom: MediaQuery.viewPaddingOf(context).bottom + 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('简介', style: TextStyle(fontSize: 15)),
const SizedBox(height: 20),
Text(
arc.title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Row(
children: [
Icon(
size: 14,
Icons.headphones_outlined,
color: colorScheme.outline,
),
Text(
' ${NumUtils.numFormat(audioItem.stat.view)} '
'${DateFormatUtils.dateFormat(arc.publish.toInt(), long: DateFormatUtils.longFormatD)} '
'${arc.displayedOid}',
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
const SizedBox(height: 20),
SelectableText(arc.desc),
],
),
),
],
);
},
);
}
}
extension _PlayReatExt on PlayRepeat {