Compare commits
1 Commits
fix-issues
...
feature-se
| Author | SHA1 | Date | |
|---|---|---|---|
| bc26e79bf9 |
@ -1,9 +0,0 @@
|
|||||||
## 1.0.21
|
|
||||||
|
|
||||||
### 修复
|
|
||||||
+ 推荐视频全屏问题
|
|
||||||
+ 番剧全屏播放时灰屏问题
|
|
||||||
+ 评论回调导致页面卡死问题
|
|
||||||
|
|
||||||
更多更新日志可在Github上查看
|
|
||||||
问题反馈、功能建议请查看「关于」页面。
|
|
||||||
@ -490,6 +490,9 @@ class Api {
|
|||||||
/// 我的订阅详情
|
/// 我的订阅详情
|
||||||
static const userSubFolderDetail = '/x/space/fav/season/list';
|
static const userSubFolderDetail = '/x/space/fav/season/list';
|
||||||
|
|
||||||
|
/// 取消订阅
|
||||||
|
static const userSubCancel = '/x/v3/fav/season/unfav';
|
||||||
|
|
||||||
/// 表情
|
/// 表情
|
||||||
static const emojiList = '/x/emote/user/panel/web';
|
static const emojiList = '/x/emote/user/panel/web';
|
||||||
|
|
||||||
|
|||||||
@ -349,4 +349,21 @@ class UserHttp {
|
|||||||
return {'status': false, 'msg': res.data['message']};
|
return {'status': false, 'msg': res.data['message']};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 取消订阅
|
||||||
|
static Future userSubCancel({required int seasonId}) async {
|
||||||
|
var res = await Request().post(
|
||||||
|
Api.userSubCancel,
|
||||||
|
queryParameters: {
|
||||||
|
'season_id': seasonId,
|
||||||
|
'platform': 'web',
|
||||||
|
'csrf': await Request.getCsrf(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {'status': true, 'msg': '取消订阅成功'};
|
||||||
|
} else {
|
||||||
|
return {'status': false, 'msg': res.data['message']};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
List defaultNavigationBars = [
|
const defaultNavigationBars = [
|
||||||
{
|
{
|
||||||
'id': 0,
|
'id': 0,
|
||||||
'icon': const Icon(
|
'icon': Icon(
|
||||||
Icons.home_outlined,
|
Icons.home_outlined,
|
||||||
size: 21,
|
size: 21,
|
||||||
),
|
),
|
||||||
'selectIcon': const Icon(
|
'selectIcon': Icon(
|
||||||
Icons.home,
|
Icons.home,
|
||||||
size: 21,
|
size: 21,
|
||||||
),
|
),
|
||||||
@ -16,11 +16,11 @@ List defaultNavigationBars = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 1,
|
'id': 1,
|
||||||
'icon': const Icon(
|
'icon': Icon(
|
||||||
Icons.motion_photos_on_outlined,
|
Icons.motion_photos_on_outlined,
|
||||||
size: 21,
|
size: 21,
|
||||||
),
|
),
|
||||||
'selectIcon': const Icon(
|
'selectIcon': Icon(
|
||||||
Icons.motion_photos_on,
|
Icons.motion_photos_on,
|
||||||
size: 21,
|
size: 21,
|
||||||
),
|
),
|
||||||
@ -29,11 +29,11 @@ List defaultNavigationBars = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 2,
|
'id': 2,
|
||||||
'icon': const Icon(
|
'icon': Icon(
|
||||||
Icons.video_collection_outlined,
|
Icons.video_collection_outlined,
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
'selectIcon': const Icon(
|
'selectIcon': Icon(
|
||||||
Icons.video_collection,
|
Icons.video_collection,
|
||||||
size: 21,
|
size: 21,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -144,9 +144,9 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Material(
|
child: Material(
|
||||||
child: ScrollablePositionedList.builder(
|
child: ScrollablePositionedList.builder(
|
||||||
itemCount: widget.pages.length + 1,
|
itemCount: widget.pages.length,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
bool isLastItem = index == widget.pages.length;
|
bool isLastItem = index == widget.pages.length - 1;
|
||||||
bool isCurrentIndex = currentIndex == index;
|
bool isCurrentIndex = currentIndex == index;
|
||||||
return isLastItem
|
return isLastItem
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
|
|||||||
@ -34,6 +34,8 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
userInfo = userInfoCache.get('userInfoCache');
|
userInfo = userInfoCache.get('userInfoCache');
|
||||||
userLogin.value = userInfo != null;
|
userLogin.value = userInfo != null;
|
||||||
userFace.value = userInfo != null ? userInfo.face : '';
|
userFace.value = userInfo != null ? userInfo.face : '';
|
||||||
|
// 进行tabs配置
|
||||||
|
setTabConfig();
|
||||||
hideSearchBar =
|
hideSearchBar =
|
||||||
setting.get(SettingBoxKey.hideSearchBar, defaultValue: true);
|
setting.get(SettingBoxKey.hideSearchBar, defaultValue: true);
|
||||||
if (setting.get(SettingBoxKey.enableSearchWord, defaultValue: true)) {
|
if (setting.get(SettingBoxKey.enableSearchWord, defaultValue: true)) {
|
||||||
@ -41,8 +43,6 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
enableGradientBg =
|
enableGradientBg =
|
||||||
setting.get(SettingBoxKey.enableGradientBg, defaultValue: true);
|
setting.get(SettingBoxKey.enableGradientBg, defaultValue: true);
|
||||||
// 进行tabs配置
|
|
||||||
setTabConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRefresh() {
|
void onRefresh() {
|
||||||
@ -91,7 +91,6 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
vsync: this,
|
vsync: this,
|
||||||
);
|
);
|
||||||
// 监听 tabController 切换
|
// 监听 tabController 切换
|
||||||
if (enableGradientBg) {
|
|
||||||
tabController.animation!.addListener(() {
|
tabController.animation!.addListener(() {
|
||||||
if (tabController.indexIsChanging) {
|
if (tabController.indexIsChanging) {
|
||||||
if (initialIndex.value != tabController.index) {
|
if (initialIndex.value != tabController.index) {
|
||||||
@ -106,7 +105,6 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void searchDefault() async {
|
void searchDefault() async {
|
||||||
var res = await Request().get(Api.searchDefault);
|
var res = await Request().get(Api.searchDefault);
|
||||||
|
|||||||
@ -46,4 +46,41 @@ class SubController extends GetxController {
|
|||||||
Future onLoad() async {
|
Future onLoad() async {
|
||||||
querySubFolder(type: 'onload');
|
querySubFolder(type: 'onload');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 取消订阅
|
||||||
|
Future<dynamic> cancelSub({required int id}) async {
|
||||||
|
showDialog(
|
||||||
|
context: Get.context!,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('提示'),
|
||||||
|
content: const Text('确认要取消订阅吗?'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
child: Text(
|
||||||
|
'取消',
|
||||||
|
style:
|
||||||
|
TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||||
|
)),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Get.back();
|
||||||
|
var res = await UserHttp.userSubCancel(seasonId: id);
|
||||||
|
if (res['status']) {
|
||||||
|
SmartDialog.showToast('取消订阅成功');
|
||||||
|
subFolderData.value.list!
|
||||||
|
.removeWhere((element) => element.id == id);
|
||||||
|
subFolderData.update((val) {});
|
||||||
|
} else {
|
||||||
|
SmartDialog.showToast(res['msg']);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const Text('确认'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,14 @@ class _SubPageState extends State<SubPage> {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return SubItem(
|
return SubItem(
|
||||||
subFolderItem:
|
subFolderItem:
|
||||||
_subController.subFolderData.value.list![index]);
|
_subController.subFolderData.value.list![index],
|
||||||
|
fuc: () {
|
||||||
|
_subController.cancelSub(
|
||||||
|
id: _subController
|
||||||
|
.subFolderData.value.list![index].id!,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -8,7 +8,8 @@ import '../../../models/user/sub_folder.dart';
|
|||||||
|
|
||||||
class SubItem extends StatelessWidget {
|
class SubItem extends StatelessWidget {
|
||||||
final SubFolderItemData subFolderItem;
|
final SubFolderItemData subFolderItem;
|
||||||
const SubItem({super.key, required this.subFolderItem});
|
final Function fuc;
|
||||||
|
const SubItem({super.key, required this.subFolderItem, required this.fuc});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -51,7 +52,7 @@ class SubItem extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
VideoContent(subFolderItem: subFolderItem)
|
VideoContent(subFolderItem: subFolderItem, fuc: fuc)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -64,7 +65,9 @@ class SubItem extends StatelessWidget {
|
|||||||
|
|
||||||
class VideoContent extends StatelessWidget {
|
class VideoContent extends StatelessWidget {
|
||||||
final SubFolderItemData subFolderItem;
|
final SubFolderItemData subFolderItem;
|
||||||
const VideoContent({super.key, required this.subFolderItem});
|
final Function fuc;
|
||||||
|
const VideoContent(
|
||||||
|
{super.key, required this.subFolderItem, required this.fuc});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -100,6 +103,20 @@ class VideoContent extends StatelessWidget {
|
|||||||
color: Theme.of(context).colorScheme.outline,
|
color: Theme.of(context).colorScheme.outline,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const Spacer(),
|
||||||
|
SizedBox(
|
||||||
|
height: 34,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () => fuc(),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
|
||||||
|
foregroundColor: Theme.of(context).colorScheme.outline,
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.onInverseSurface, // 设置按钮背景色
|
||||||
|
),
|
||||||
|
child: const Text('取消订阅'),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -129,7 +129,6 @@ class VideoDetailController extends GetxController
|
|||||||
videoDetailCtr: this,
|
videoDetailCtr: this,
|
||||||
floating: floating,
|
floating: floating,
|
||||||
bvid: bvid,
|
bvid: bvid,
|
||||||
videoType: videoType,
|
|
||||||
);
|
);
|
||||||
// CDN优化
|
// CDN优化
|
||||||
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
||||||
|
|||||||
@ -23,10 +23,7 @@ class IntroDetail extends StatelessWidget {
|
|||||||
sheetHeight = localCache.get('sheetHeight');
|
sheetHeight = localCache.get('sheetHeight');
|
||||||
return Container(
|
return Container(
|
||||||
color: Theme.of(context).colorScheme.background,
|
color: Theme.of(context).colorScheme.background,
|
||||||
padding: EdgeInsets.only(
|
padding: const EdgeInsets.only(left: 14, right: 14),
|
||||||
left: 14,
|
|
||||||
right: 14,
|
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 20),
|
|
||||||
height: sheetHeight,
|
height: sheetHeight,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@ -161,9 +161,9 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Material(
|
child: Material(
|
||||||
child: ScrollablePositionedList.builder(
|
child: ScrollablePositionedList.builder(
|
||||||
itemCount: episodes.length + 1,
|
itemCount: episodes.length,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
bool isLastItem = index == episodes.length;
|
bool isLastItem = index == episodes.length - 1;
|
||||||
bool isCurrentIndex = currentIndex == index;
|
bool isCurrentIndex = currentIndex == index;
|
||||||
return isLastItem
|
return isLastItem
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
|
|||||||
@ -280,7 +280,7 @@ class ReplyItem extends StatelessWidget {
|
|||||||
// 完成评论,数据添加
|
// 完成评论,数据添加
|
||||||
if (value != null && value['data'] != null)
|
if (value != null && value['data'] != null)
|
||||||
{
|
{
|
||||||
addReply?.call(value['data'])
|
addReply!(value['data'])
|
||||||
// replyControl.replies.add(value['data']),
|
// replyControl.replies.add(value['data']),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -531,8 +531,8 @@ InlineSpan buildContent(
|
|||||||
spanChilds.add(TextSpan(
|
spanChilds.add(TextSpan(
|
||||||
text: str,
|
text: str,
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () =>
|
..onTap =
|
||||||
replyReply?.call(replyItem.root == 0 ? replyItem : fReplyItem)));
|
() => replyReply(replyItem.root == 0 ? replyItem : fReplyItem)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分割文本并处理每个部分
|
// 分割文本并处理每个部分
|
||||||
@ -642,11 +642,6 @@ InlineSpan buildContent(
|
|||||||
} else {
|
} else {
|
||||||
final String redirectUrl =
|
final String redirectUrl =
|
||||||
await UrlUtils.parseRedirectUrl(matchStr);
|
await UrlUtils.parseRedirectUrl(matchStr);
|
||||||
if (redirectUrl == matchStr) {
|
|
||||||
Clipboard.setData(ClipboardData(text: matchStr));
|
|
||||||
SmartDialog.showToast('地址可能有误');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final String pathSegment = Uri.parse(redirectUrl).path;
|
final String pathSegment = Uri.parse(redirectUrl).path;
|
||||||
final String lastPathSegment =
|
final String lastPathSegment =
|
||||||
pathSegment.split('/').last;
|
pathSegment.split('/').last;
|
||||||
|
|||||||
@ -30,9 +30,6 @@ class VideoReplyReplyController extends GetxController {
|
|||||||
if (type == 'init') {
|
if (type == 'init') {
|
||||||
currentPage = 0;
|
currentPage = 0;
|
||||||
}
|
}
|
||||||
if (isLoadingMore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isLoadingMore = true;
|
isLoadingMore = true;
|
||||||
final res = await ReplyHttp.replyReplyList(
|
final res = await ReplyHttp.replyReplyList(
|
||||||
oid: aid!,
|
oid: aid!,
|
||||||
@ -44,7 +41,7 @@ class VideoReplyReplyController extends GetxController {
|
|||||||
final List<ReplyItemModel> replies = res['data'].replies;
|
final List<ReplyItemModel> replies = res['data'].replies;
|
||||||
if (replies.isNotEmpty) {
|
if (replies.isNotEmpty) {
|
||||||
noMore.value = '加载中...';
|
noMore.value = '加载中...';
|
||||||
if (replies.length == res['data'].page.count) {
|
if (replyList.length == res['data'].page.count) {
|
||||||
noMore.value = '没有更多了';
|
noMore.value = '没有更多了';
|
||||||
}
|
}
|
||||||
currentPage++;
|
currentPage++;
|
||||||
@ -53,6 +50,21 @@ class VideoReplyReplyController extends GetxController {
|
|||||||
noMore.value = currentPage == 0 ? '还没有评论' : '没有更多了';
|
noMore.value = currentPage == 0 ? '还没有评论' : '没有更多了';
|
||||||
}
|
}
|
||||||
if (type == 'init') {
|
if (type == 'init') {
|
||||||
|
// List<ReplyItemModel> replies = res['data'].replies;
|
||||||
|
// 添加置顶回复
|
||||||
|
// if (res['data'].upper.top != null) {
|
||||||
|
// bool flag = false;
|
||||||
|
// for (var i = 0; i < res['data'].topReplies.length; i++) {
|
||||||
|
// if (res['data'].topReplies[i].rpid == res['data'].upper.top.rpid) {
|
||||||
|
// flag = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (!flag) {
|
||||||
|
// replies.insert(0, res['data'].upper.top);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// replies.insertAll(0, res['data'].topReplies);
|
||||||
|
// res['data'].replies = replies;
|
||||||
replyList.value = replies;
|
replyList.value = replies;
|
||||||
} else {
|
} else {
|
||||||
// 每次回复之后,翻页请求有且只有相同的一条回复数据
|
// 每次回复之后,翻页请求有且只有相同的一条回复数据
|
||||||
|
|||||||
@ -54,8 +54,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
|
|||||||
() {
|
() {
|
||||||
if (scrollController.position.pixels >=
|
if (scrollController.position.pixels >=
|
||||||
scrollController.position.maxScrollExtent - 300) {
|
scrollController.position.maxScrollExtent - 300) {
|
||||||
EasyThrottle.throttle('replylist', const Duration(milliseconds: 200),
|
EasyThrottle.throttle('replylist', const Duration(seconds: 2), () {
|
||||||
() {
|
|
||||||
_videoReplyReplyController.queryReplyList(type: 'onLoad');
|
_videoReplyReplyController.queryReplyList(type: 'onLoad');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -93,7 +92,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
|
|||||||
icon: const Icon(Icons.close, size: 20),
|
icon: const Icon(Icons.close, size: 20),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_videoReplyReplyController.currentPage = 0;
|
_videoReplyReplyController.currentPage = 0;
|
||||||
widget.closePanel?.call;
|
widget.closePanel!();
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -185,8 +184,6 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
|
|||||||
.add(replyItem);
|
.add(replyItem);
|
||||||
},
|
},
|
||||||
replyType: widget.replyType,
|
replyType: widget.replyType,
|
||||||
replyReply: (replyItem) =>
|
|
||||||
replyReply(replyItem),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -572,7 +572,6 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
controller: plPlayerController,
|
controller: plPlayerController,
|
||||||
videoDetailCtr: videoDetailController,
|
videoDetailCtr: videoDetailController,
|
||||||
bvid: videoDetailController.bvid,
|
bvid: videoDetailController.bvid,
|
||||||
videoType: videoDetailController.videoType,
|
|
||||||
),
|
),
|
||||||
danmuWidget: Obx(
|
danmuWidget: Obx(
|
||||||
() => PlDanmaku(
|
() => PlDanmaku(
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
|||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
import 'package:pilipala/http/danmaku.dart';
|
import 'package:pilipala/http/danmaku.dart';
|
||||||
import 'package:pilipala/services/shutdown_timer_service.dart';
|
import 'package:pilipala/services/shutdown_timer_service.dart';
|
||||||
import '../../../../models/common/search_type.dart';
|
|
||||||
import '../../../../models/video_detail_res.dart';
|
import '../../../../models/video_detail_res.dart';
|
||||||
import '../introduction/index.dart';
|
import '../introduction/index.dart';
|
||||||
|
|
||||||
@ -29,14 +28,12 @@ class HeaderControl extends StatefulWidget implements PreferredSizeWidget {
|
|||||||
this.videoDetailCtr,
|
this.videoDetailCtr,
|
||||||
this.floating,
|
this.floating,
|
||||||
this.bvid,
|
this.bvid,
|
||||||
this.videoType,
|
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
final PlPlayerController? controller;
|
final PlPlayerController? controller;
|
||||||
final VideoDetailController? videoDetailCtr;
|
final VideoDetailController? videoDetailCtr;
|
||||||
final Floating? floating;
|
final Floating? floating;
|
||||||
final String? bvid;
|
final String? bvid;
|
||||||
final SearchType? videoType;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<HeaderControl> createState() => _HeaderControlState();
|
State<HeaderControl> createState() => _HeaderControlState();
|
||||||
@ -79,11 +76,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
} else {
|
} else {
|
||||||
showTitle = false;
|
showTitle = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO setState() called after dispose()
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1114,16 +1107,14 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SizedBox(width: buttonSpace),
|
SizedBox(width: buttonSpace),
|
||||||
if (showTitle &&
|
if (showTitle && isLandscape) ...[
|
||||||
isLandscape &&
|
|
||||||
widget.videoType == SearchType.video) ...[
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxWidth: 200),
|
constraints: BoxConstraints(maxWidth: 200),
|
||||||
child: Text(
|
child: Text(
|
||||||
videoIntroController.videoDetail.value.title ?? '',
|
videoIntroController.videoDetail.value.title!,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
|||||||
@ -277,7 +277,8 @@ class PlPlayerController {
|
|||||||
danmakuDurationVal =
|
danmakuDurationVal =
|
||||||
localCache.get(LocalCacheKey.danmakuDuration, defaultValue: 4.0);
|
localCache.get(LocalCacheKey.danmakuDuration, defaultValue: 4.0);
|
||||||
// 描边粗细
|
// 描边粗细
|
||||||
strokeWidth = localCache.get(LocalCacheKey.strokeWidth, defaultValue: 1.5);
|
strokeWidth =
|
||||||
|
localCache.get(LocalCacheKey.strokeWidth, defaultValue: 1.5);
|
||||||
playRepeat = PlayRepeat.values.toList().firstWhere(
|
playRepeat = PlayRepeat.values.toList().firstWhere(
|
||||||
(e) =>
|
(e) =>
|
||||||
e.value ==
|
e.value ==
|
||||||
@ -534,10 +535,8 @@ class PlPlayerController {
|
|||||||
if (event) {
|
if (event) {
|
||||||
playerStatus.status.value = PlayerStatus.playing;
|
playerStatus.status.value = PlayerStatus.playing;
|
||||||
} else {
|
} else {
|
||||||
playerStatus.status.value = PlayerStatus.paused;
|
// playerStatus.status.value = PlayerStatus.paused;
|
||||||
}
|
}
|
||||||
videoPlayerServiceHandler.onStatusChange(
|
|
||||||
playerStatus.status.value, isBuffering.value);
|
|
||||||
|
|
||||||
/// 触发回调事件
|
/// 触发回调事件
|
||||||
for (var element in _statusListeners) {
|
for (var element in _statusListeners) {
|
||||||
|
|||||||
@ -26,7 +26,6 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
|||||||
static final List<MediaItem> _item = [];
|
static final List<MediaItem> _item = [];
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStrorage.setting;
|
||||||
bool enableBackgroundPlay = false;
|
bool enableBackgroundPlay = false;
|
||||||
PlPlayerController player = PlPlayerController.getInstance();
|
|
||||||
|
|
||||||
VideoPlayerServiceHandler() {
|
VideoPlayerServiceHandler() {
|
||||||
revalidateSetting();
|
revalidateSetting();
|
||||||
@ -39,12 +38,12 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> play() async {
|
Future<void> play() async {
|
||||||
player.play();
|
PlPlayerController.getInstance().play();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> pause() async {
|
Future<void> pause() async {
|
||||||
player.pause();
|
PlPlayerController.getInstance().pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -52,7 +51,7 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
|||||||
playbackState.add(playbackState.value.copyWith(
|
playbackState.add(playbackState.value.copyWith(
|
||||||
updatePosition: position,
|
updatePosition: position,
|
||||||
));
|
));
|
||||||
await player.seekTo(position);
|
await PlPlayerController.getInstance().seekTo(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setMediaItem(MediaItem newMediaItem) async {
|
Future<void> setMediaItem(MediaItem newMediaItem) async {
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class AudioSessionHandler {
|
|||||||
session.interruptionEventStream.listen((event) {
|
session.interruptionEventStream.listen((event) {
|
||||||
final player = PlPlayerController.getInstance();
|
final player = PlPlayerController.getInstance();
|
||||||
if (event.begin) {
|
if (event.begin) {
|
||||||
if (!player.playerStatus.playing) return;
|
if (player.playerStatus != PlayerStatus.playing) return;
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case AudioInterruptionType.duck:
|
case AudioInterruptionType.duck:
|
||||||
player.setVolume(player.volume.value * 0.5);
|
player.setVolume(player.volume.value * 0.5);
|
||||||
@ -52,7 +52,7 @@ class AudioSessionHandler {
|
|||||||
// 耳机拔出暂停
|
// 耳机拔出暂停
|
||||||
session.becomingNoisyEventStream.listen((_) {
|
session.becomingNoisyEventStream.listen((_) {
|
||||||
final player = PlPlayerController.getInstance();
|
final player = PlPlayerController.getInstance();
|
||||||
if (player.playerStatus.playing) {
|
if (player.playerStatus == PlayerStatus.playing) {
|
||||||
player.pause();
|
player.pause();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -14,7 +14,6 @@ class UrlUtils {
|
|||||||
dio.options.validateStatus = (status) {
|
dio.options.validateStatus = (status) {
|
||||||
return status == 200 || status == 301 || status == 302;
|
return status == 200 || status == 301 || status == 302;
|
||||||
};
|
};
|
||||||
try {
|
|
||||||
final response = await dio.get(url);
|
final response = await dio.get(url);
|
||||||
if (response.statusCode == 302) {
|
if (response.statusCode == 302) {
|
||||||
redirectUrl = response.headers['location']?.first as String;
|
redirectUrl = response.headers['location']?.first as String;
|
||||||
@ -28,9 +27,6 @@ class UrlUtils {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
return redirectUrl;
|
return redirectUrl;
|
||||||
} catch (err) {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 匹配url路由跳转
|
// 匹配url路由跳转
|
||||||
|
|||||||
@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.21+1021
|
version: 1.0.20+1020
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.19.6 <3.0.0"
|
sdk: ">=2.19.6 <3.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user