opt: video page

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2024-11-30 15:28:47 +08:00
parent 0dd90ef075
commit 0e783588ba
8 changed files with 47 additions and 40 deletions

View File

@@ -1,3 +1,4 @@
import 'package:PiliPalaX/http/search.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -78,7 +79,11 @@ class VideoCardV extends StatelessWidget {
break; break;
case 'av': case 'av':
String bvid = videoItem.bvid ?? IdUtils.av2bv(videoItem.aid); String bvid = videoItem.bvid ?? IdUtils.av2bv(videoItem.aid);
Get.toNamed('/video?bvid=$bvid&cid=${videoItem.cid}', arguments: { int cid = videoItem.cid;
if (cid == -1) {
cid = await SearchHttp.ab2c(aid: videoItem.aid, bvid: bvid);
}
Get.toNamed('/video?bvid=$bvid&cid=$cid', arguments: {
// 'videoItem': videoItem, // 'videoItem': videoItem,
'pic': videoItem.pic, 'pic': videoItem.pic,
'heroTag': heroTag, 'heroTag': heroTag,

View File

@@ -55,7 +55,7 @@ class RecVideoItemAppModel {
id = json['player_args'] != null id = json['player_args'] != null
? json['player_args']['aid'] ? json['player_args']['aid']
: int.parse(json['param'] ?? '-1'); : int.parse(json['param'] ?? '-1');
aid = json['player_args'] != null ? json['player_args']['aid'] : -1; aid = id;
bvid = json['bvid'] ?? bvid = json['bvid'] ??
(json['player_args'] != null (json['player_args'] != null
? IdUtils.av2bv(json['player_args']['aid']) ? IdUtils.av2bv(json['player_args']['aid'])

View File

@@ -92,12 +92,16 @@ abstract class ReplyController extends CommonController {
if (response.response.upper.top != null) { if (response.response.upper.top != null) {
final bool flag = response.response.topReplies.any( final bool flag = response.response.topReplies.any(
(ReplyItemModel reply) => (ReplyItemModel reply) =>
reply.rpid == response.response.upper.top.rpid) as bool; reply.rpid != response.response.upper.top.rpid) as bool;
if (!flag) { if (flag) {
replies.insert(0, response.response.upper.top); replies.insert(0, response.response.upper.top);
hasUpTop = true;
} }
} }
replies.insertAll(0, response.response.topReplies); if (response.response.topReplies != null) {
replies.insertAll(0, response.response.topReplies);
hasUpTop = true;
}
} else if (loadingState.value is Success) { } else if (loadingState.value is Success) {
replies.insertAll(0, (loadingState.value as Success).response.replies); replies.insertAll(0, (loadingState.value as Success).response.replies);
} }

View File

@@ -25,7 +25,7 @@ class PlDanmaku extends StatefulWidget {
State<PlDanmaku> createState() => _PlDanmakuState(); State<PlDanmaku> createState() => _PlDanmakuState();
} }
class _PlDanmakuState extends State<PlDanmaku> with WidgetsBindingObserver { class _PlDanmakuState extends State<PlDanmaku> {
late PlPlayerController playerController; late PlPlayerController playerController;
late PlDanmakuController _plDanmakuController; late PlDanmakuController _plDanmakuController;
DanmakuController? _controller; DanmakuController? _controller;
@@ -41,23 +41,11 @@ class _PlDanmakuState extends State<PlDanmaku> with WidgetsBindingObserver {
// late double strokeWidth; // late double strokeWidth;
// late int fontWeight; // late int fontWeight;
int latestAddedPosition = -1; int latestAddedPosition = -1;
bool showDanmaku = true;
bool? _isFullScreen; bool? _isFullScreen;
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
showDanmaku = true;
} else if (state == AppLifecycleState.paused) {
showDanmaku = false;
_controller?.clear();
}
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance.addObserver(this);
enableShowDanmaku = enableShowDanmaku =
setting.get(SettingBoxKey.enableShowDanmaku, defaultValue: true); setting.get(SettingBoxKey.enableShowDanmaku, defaultValue: true);
_plDanmakuController = PlDanmakuController( _plDanmakuController = PlDanmakuController(
@@ -129,7 +117,7 @@ class _PlDanmakuState extends State<PlDanmaku> with WidgetsBindingObserver {
List<DanmakuElem>? currentDanmakuList = List<DanmakuElem>? currentDanmakuList =
_plDanmakuController.getCurrentDanmaku(currentPosition); _plDanmakuController.getCurrentDanmaku(currentPosition);
if (showDanmaku && if (playerController.showDanmaku &&
playerController.playerStatus.status.value == PlayerStatus.playing && playerController.playerStatus.status.value == PlayerStatus.playing &&
currentDanmakuList != null && currentDanmakuList != null &&
_controller != null) { _controller != null) {
@@ -150,7 +138,6 @@ class _PlDanmakuState extends State<PlDanmaku> with WidgetsBindingObserver {
@override @override
void dispose() { void dispose() {
WidgetsBinding.instance.removeObserver(this);
playerController.removePositionListener(videoPositionListen); playerController.removePositionListener(videoPositionListen);
playerController.removeStatusLister(playerListener); playerController.removeStatusLister(playerListener);
_plDanmakuController.dispose(); _plDanmakuController.dispose();

View File

@@ -22,7 +22,7 @@ class SponsorBlockPage extends StatefulWidget {
} }
class _SponsorBlockPageState extends State<SponsorBlockPage> { class _SponsorBlockPageState extends State<SponsorBlockPage> {
final _url = 'https://github.com/hanydd/BilibiliSponsorBlock'; static const _url = 'https://github.com/hanydd/BilibiliSponsorBlock';
final _textController = TextEditingController(); final _textController = TextEditingController();
late double _blockLimit; late double _blockLimit;
late List<Pair<SegmentType, SkipType>> _blockSettings; late List<Pair<SegmentType, SkipType>> _blockSettings;
@@ -78,7 +78,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
setState(() { setState(() {
_serverStatus = res.statusCode == 200 && _serverStatus = res.statusCode == 200 &&
res.data is String && res.data is String &&
(double.tryParse(res.data) ?? int.tryParse(res.data)) != null; Utils.isStringNumeric(res.data);
}); });
}); });
} }

View File

@@ -74,7 +74,6 @@ class VideoIntroController extends GetxController
bool isShowOnlineTotal = false; bool isShowOnlineTotal = false;
RxString total = '1'.obs; RxString total = '1'.obs;
Timer? timer; Timer? timer;
bool isPaused = false;
String heroTag = ''; String heroTag = '';
late ModelResult modelResult; late ModelResult modelResult;
Rx<Map<String, dynamic>> queryVideoIntroData = Rx<Map<String, dynamic>> queryVideoIntroData =
@@ -574,11 +573,8 @@ class VideoIntroController extends GetxController
void startTimer() { void startTimer() {
if (isShowOnlineTotal) { if (isShowOnlineTotal) {
queryOnlineTotal(); queryOnlineTotal();
const duration = Duration(seconds: 10); // 设置定时器间隔为10秒 timer ??= Timer.periodic(const Duration(seconds: 10), (Timer timer) {
timer ??= Timer.periodic(duration, (Timer timer) { queryOnlineTotal();
if (!isPaused) {
queryOnlineTotal(); // 定时器回调函数,发起请求
}
}); });
} }
} }
@@ -606,9 +602,7 @@ class VideoIntroController extends GetxController
@override @override
void onClose() { void onClose() {
if (timer != null) { canelTimer();
timer!.cancel(); // 销毁页面时取消定时器
}
super.onClose(); super.onClose();
} }

View File

@@ -54,7 +54,7 @@ class VideoDetailPage extends StatefulWidget {
} }
class _VideoDetailPageState extends State<VideoDetailPage> class _VideoDetailPageState extends State<VideoDetailPage>
with TickerProviderStateMixin, RouteAware { with TickerProviderStateMixin, RouteAware, WidgetsBindingObserver {
late VideoDetailController videoDetailController; late VideoDetailController videoDetailController;
late VideoReplyController _videoReplyController; late VideoReplyController _videoReplyController;
PlPlayerController? plPlayerController; PlPlayerController? plPlayerController;
@@ -170,6 +170,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
// : context.width * 9 / 16), // : context.width * 9 / 16),
// end: 0, // end: 0,
// ).animate(_animationController); // ).animate(_animationController);
WidgetsBinding.instance.addObserver(this);
} }
// 获取视频资源,初始化播放器 // 获取视频资源,初始化播放器
@@ -183,6 +184,17 @@ class _VideoDetailPageState extends State<VideoDetailPage>
} }
} }
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
videoIntroController.startTimer();
videoDetailController.plPlayerController.showDanmaku = true;
} else if (state == AppLifecycleState.paused) {
videoIntroController.canelTimer();
videoDetailController.plPlayerController.showDanmaku = false;
}
}
void playCallBack() { void playCallBack() {
plPlayerController?.play(); plPlayerController?.play();
} }
@@ -241,7 +253,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
Future<void> handlePlay() async { Future<void> handlePlay() async {
if (videoDetailController.videoUrl == null || if (videoDetailController.videoUrl == null ||
videoDetailController.audioUrl == null) { videoDetailController.audioUrl == null) {
SmartDialog.showToast('not initialized'); // SmartDialog.showToast('not initialized');
debugPrint('not initialized');
return; return;
} }
plPlayerController = videoDetailController.plPlayerController; plPlayerController = videoDetailController.plPlayerController;
@@ -275,6 +288,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
@override @override
void dispose() { void dispose() {
WidgetsBinding.instance.removeObserver(this);
if (!Get.previousRoute.startsWith('/video')) { if (!Get.previousRoute.startsWith('/video')) {
ScreenBrightness().resetApplicationScreenBrightness(); ScreenBrightness().resetApplicationScreenBrightness();
PlPlayerController.setPlayCallBack(null); PlPlayerController.setPlayCallBack(null);
@@ -325,7 +339,6 @@ class _VideoDetailPageState extends State<VideoDetailPage>
} }
if (plPlayerController != null) { if (plPlayerController != null) {
videoDetailController.defaultST = plPlayerController!.position.value; videoDetailController.defaultST = plPlayerController!.position.value;
videoIntroController.isPaused = true;
plPlayerController!.removeStatusLister(playerListener); plPlayerController!.removeStatusLister(playerListener);
plPlayerController!.pause(); plPlayerController!.pause();
} }
@@ -369,7 +382,6 @@ class _VideoDetailPageState extends State<VideoDetailPage>
// } // }
/// 未开启自动播放时,未播放跳转下一页返回/播放后跳转下一页返回 /// 未开启自动播放时,未播放跳转下一页返回/播放后跳转下一页返回
videoIntroController.isPaused = false;
// if (autoplay) { // if (autoplay) {
// // await Future.delayed(const Duration(milliseconds: 300)); // // await Future.delayed(const Duration(milliseconds: 300));
// debugPrint(plPlayerController); // debugPrint(plPlayerController);

View File

@@ -243,6 +243,7 @@ class PlPlayerController {
ValueNotifier([]); ValueNotifier([]);
// 关联弹幕控制器 // 关联弹幕控制器
DanmakuController? danmakuController; DanmakuController? danmakuController;
bool showDanmaku = true;
// 弹幕相关配置 // 弹幕相关配置
late List blockTypes; late List blockTypes;
late double showArea; late double showArea;
@@ -1243,7 +1244,10 @@ class PlPlayerController {
// 记录播放记录 // 记录播放记录
Future makeHeartBeat(int progress, {type = 'playing'}) async { Future makeHeartBeat(int progress, {type = 'playing'}) async {
if (!_enableHeart || MineController.anonymity) { if (!_enableHeart ||
MineController.anonymity ||
progress == 0 ||
playerStatus.status.value == PlayerStatus.paused) {
return false; return false;
} }
if (videoType.value == 'live') { if (videoType.value == 'live') {
@@ -1252,6 +1256,7 @@ class PlPlayerController {
bool isComplete = playerStatus.status.value == PlayerStatus.completed || bool isComplete = playerStatus.status.value == PlayerStatus.completed ||
type == 'completed'; type == 'completed';
// 播放状态变化时,更新 // 播放状态变化时,更新
if (type == 'status' || type == 'completed') { if (type == 'status' || type == 'completed') {
await VideoHttp.heartBeat( await VideoHttp.heartBeat(
bvid: _bvid, bvid: _bvid,
@@ -1261,7 +1266,7 @@ class PlPlayerController {
return; return;
} }
// 正常播放时间隔5秒更新一次 // 正常播放时间隔5秒更新一次
if (progress - _heartDuration >= 5) { else if (progress - _heartDuration >= 5) {
_heartDuration = progress; _heartDuration = progress;
await VideoHttp.heartBeat( await VideoHttp.heartBeat(
bvid: _bvid, bvid: _bvid,
@@ -1335,9 +1340,9 @@ class PlPlayerController {
Future refreshSubtitles() async { Future refreshSubtitles() async {
_vttSubtitles.clear(); _vttSubtitles.clear();
Map res = await VideoHttp.subtitlesJson(bvid: _bvid, cid: _cid); Map res = await VideoHttp.subtitlesJson(bvid: _bvid, cid: _cid);
if (!res["status"]) { // if (!res["status"]) {
SmartDialog.showToast('查询字幕错误,${res["msg"]}'); // SmartDialog.showToast('查询字幕错误,${res["msg"]}');
} // }
if (res["data"].length == 0) { if (res["data"].length == 0) {
return; return;
} }