mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: video page
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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'])
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user