Merge branch 'main' into opt-videoPlayerControl
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.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';
|
||||||
import 'package:pilipala/common/constants.dart';
|
import 'package:pilipala/common/constants.dart';
|
||||||
@ -98,7 +99,8 @@ class _PagesBottomSheetState extends State<PagesBottomSheet>
|
|||||||
with TickerProviderStateMixin {
|
with TickerProviderStateMixin {
|
||||||
final ScrollController _listScrollController = ScrollController();
|
final ScrollController _listScrollController = ScrollController();
|
||||||
late ListObserverController _listObserverController;
|
late ListObserverController _listObserverController;
|
||||||
final ScrollController _scrollController = ScrollController();
|
late GridObserverController _gridObserverController;
|
||||||
|
final ScrollController _gridScrollController = ScrollController();
|
||||||
late int currentIndex;
|
late int currentIndex;
|
||||||
TabController? tabController;
|
TabController? tabController;
|
||||||
List<ListObserverController>? _listObserverControllerList;
|
List<ListObserverController>? _listObserverControllerList;
|
||||||
@ -163,6 +165,9 @@ class _PagesBottomSheetState extends State<PagesBottomSheet>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
_gridObserverController =
|
||||||
|
GridObserverController(controller: _gridScrollController);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,18 +190,12 @@ class _PagesBottomSheetState extends State<PagesBottomSheet>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
_gridObserverController.initialIndexModel = ObserverIndexPositionModel(
|
||||||
|
index: currentIndex,
|
||||||
|
isFixedHeight: false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
if (widget.dataType != VideoEpidoesType.videoEpisode) {
|
|
||||||
double itemHeight = (widget.isFullScreen
|
|
||||||
? 400
|
|
||||||
: Get.size.width - 3 * StyleString.safeSpace) /
|
|
||||||
5.2;
|
|
||||||
double offset = ((currentIndex - 1) / 2).ceil() * itemHeight;
|
|
||||||
_scrollController.jumpTo(offset);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取订阅状态
|
// 获取订阅状态
|
||||||
@ -236,7 +235,9 @@ class _PagesBottomSheetState extends State<PagesBottomSheet>
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
try {
|
try {
|
||||||
_listObserverController.controller?.dispose();
|
_listObserverController.controller?.dispose();
|
||||||
|
_gridObserverController.controller?.dispose();
|
||||||
_listScrollController.dispose();
|
_listScrollController.dispose();
|
||||||
|
_gridScrollController.dispose();
|
||||||
for (var element in _listObserverControllerList!) {
|
for (var element in _listObserverControllerList!) {
|
||||||
element.controller?.dispose();
|
element.controller?.dispose();
|
||||||
}
|
}
|
||||||
@ -303,24 +304,27 @@ class _PagesBottomSheetState extends State<PagesBottomSheet>
|
|||||||
: Padding(
|
: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 12.0), // 设置左右间距为12
|
horizontal: 12.0), // 设置左右间距为12
|
||||||
child: GridView.count(
|
child: GridViewObserver(
|
||||||
controller: _scrollController,
|
controller: _gridObserverController,
|
||||||
crossAxisCount: 2,
|
child: GridView.count(
|
||||||
crossAxisSpacing: StyleString.safeSpace,
|
controller: _gridScrollController,
|
||||||
childAspectRatio: 2.6,
|
crossAxisCount: 2,
|
||||||
children: List.generate(
|
crossAxisSpacing: StyleString.safeSpace,
|
||||||
widget.episodes.length,
|
childAspectRatio: 2.6,
|
||||||
(index) {
|
children: List.generate(
|
||||||
bool isCurrentIndex = currentIndex == index;
|
widget.episodes.length,
|
||||||
return EpisodeGridItem(
|
(index) {
|
||||||
episode: widget.episodes[index],
|
bool isCurrentIndex = currentIndex == index;
|
||||||
index: index,
|
return EpisodeGridItem(
|
||||||
isCurrentIndex: isCurrentIndex,
|
episode: widget.episodes[index],
|
||||||
dataType: widget.dataType,
|
index: index,
|
||||||
changeFucCall: widget.changeFucCall,
|
isCurrentIndex: isCurrentIndex,
|
||||||
isFullScreen: widget.isFullScreen,
|
dataType: widget.dataType,
|
||||||
);
|
changeFucCall: widget.changeFucCall,
|
||||||
},
|
isFullScreen: widget.isFullScreen,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
25
lib/common/widgets/drag_handle.dart
Normal file
25
lib/common/widgets/drag_handle.dart
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DragHandle extends StatelessWidget {
|
||||||
|
const DragHandle({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: Navigator.of(context).pop,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 36,
|
||||||
|
child: Center(
|
||||||
|
child: Container(
|
||||||
|
width: 32,
|
||||||
|
height: 4,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ import '../../http/video.dart';
|
|||||||
import '../../utils/utils.dart';
|
import '../../utils/utils.dart';
|
||||||
import '../constants.dart';
|
import '../constants.dart';
|
||||||
import 'badge.dart';
|
import 'badge.dart';
|
||||||
|
import 'drag_handle.dart';
|
||||||
import 'network_img_layer.dart';
|
import 'network_img_layer.dart';
|
||||||
import 'stat/danmu.dart';
|
import 'stat/danmu.dart';
|
||||||
import 'stat/view.dart';
|
import 'stat/view.dart';
|
||||||
@ -373,27 +374,12 @@ class MorePanel extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
const DragHandle(),
|
||||||
onTap: () => Get.back(),
|
|
||||||
child: Container(
|
|
||||||
height: 35,
|
|
||||||
padding: const EdgeInsets.only(bottom: 2),
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 32,
|
|
||||||
height: 3,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(3))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () async => await menuActionHandler('block'),
|
onTap: () async => await menuActionHandler('block'),
|
||||||
minLeadingWidth: 0,
|
minLeadingWidth: 0,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:pilipala/utils/feed_back.dart';
|
|||||||
import 'package:pilipala/utils/image_save.dart';
|
import 'package:pilipala/utils/image_save.dart';
|
||||||
import 'package:pilipala/utils/route_push.dart';
|
import 'package:pilipala/utils/route_push.dart';
|
||||||
import '../../models/model_rec_video_item.dart';
|
import '../../models/model_rec_video_item.dart';
|
||||||
|
import 'drag_handle.dart';
|
||||||
import 'stat/danmu.dart';
|
import 'stat/danmu.dart';
|
||||||
import 'stat/view.dart';
|
import 'stat/view.dart';
|
||||||
import '../../http/dynamics.dart';
|
import '../../http/dynamics.dart';
|
||||||
@ -368,27 +369,12 @@ class MorePanel extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
const DragHandle(),
|
||||||
onTap: () => Get.back(),
|
|
||||||
child: Container(
|
|
||||||
height: 35,
|
|
||||||
padding: const EdgeInsets.only(bottom: 2),
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 32,
|
|
||||||
height: 3,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(3))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () async => await menuActionHandler('block'),
|
onTap: () async => await menuActionHandler('block'),
|
||||||
minLeadingWidth: 0,
|
minLeadingWidth: 0,
|
||||||
|
|||||||
@ -622,4 +622,8 @@ class Api {
|
|||||||
|
|
||||||
/// 视频标签
|
/// 视频标签
|
||||||
static const String videoTag = '/x/tag/archive/tags';
|
static const String videoTag = '/x/tag/archive/tags';
|
||||||
|
|
||||||
|
/// 修复标题和海报
|
||||||
|
// /api/view?id=${aid} /all/video/av${aid} /video/av${aid}/
|
||||||
|
static const String fixTitleAndPic = '${HttpString.biliplusBaseUrl}/api/view';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:pilipala/models/common/invalid_video.dart';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
@ -50,6 +51,32 @@ class CommonHttp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future fixVideoPicAndTitle({required int aid}) async {
|
||||||
|
var res = await Request().getWithoutCookie(Api.fixTitleAndPic, data: {
|
||||||
|
'id': aid,
|
||||||
|
});
|
||||||
|
if (res != null) {
|
||||||
|
if (res.data['code'] == -404) {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': null,
|
||||||
|
'msg': '没有相关信息',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': true,
|
||||||
|
'data': InvalidVideoModel.fromJson(res.data),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': null,
|
||||||
|
'msg': '没有相关信息',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Future buvidActivate() async {
|
static Future buvidActivate() async {
|
||||||
try {
|
try {
|
||||||
// 获取 HTML 数据
|
// 获取 HTML 数据
|
||||||
|
|||||||
@ -8,6 +8,8 @@ class HttpString {
|
|||||||
static const String messageBaseUrl = 'https://message.bilibili.com';
|
static const String messageBaseUrl = 'https://message.bilibili.com';
|
||||||
static const String bangumiBaseUrl = 'https://bili.meark.me';
|
static const String bangumiBaseUrl = 'https://bili.meark.me';
|
||||||
static const String sponsorBlockBaseUrl = 'https://www.bsbsb.top';
|
static const String sponsorBlockBaseUrl = 'https://www.bsbsb.top';
|
||||||
|
static const String biliplusBaseUrl = 'https://www.biliplus.com';
|
||||||
|
|
||||||
static const List<int> validateStatusCodes = [
|
static const List<int> validateStatusCodes = [
|
||||||
302,
|
302,
|
||||||
304,
|
304,
|
||||||
|
|||||||
@ -68,7 +68,7 @@ class Request {
|
|||||||
// 从cookie中获取 csrf token
|
// 从cookie中获取 csrf token
|
||||||
static Future<String> getCsrf() async {
|
static Future<String> getCsrf() async {
|
||||||
List<Cookie> cookies = await cookieManager.cookieJar
|
List<Cookie> cookies = await cookieManager.cookieJar
|
||||||
.loadForRequest(Uri.parse(HttpString.apiBaseUrl));
|
.loadForRequest(Uri.parse(HttpString.baseUrl));
|
||||||
String token = '';
|
String token = '';
|
||||||
if (cookies.where((e) => e.name == 'bili_jct').isNotEmpty) {
|
if (cookies.where((e) => e.name == 'bili_jct').isNotEmpty) {
|
||||||
token = cookies.firstWhere((e) => e.name == 'bili_jct').value;
|
token = cookies.firstWhere((e) => e.name == 'bili_jct').value;
|
||||||
@ -82,9 +82,12 @@ class Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<Cookie> cookies = await cookieManager.cookieJar
|
final List<Cookie> cookies = await cookieManager.cookieJar
|
||||||
.loadForRequest(Uri.parse(HttpString.baseUrl));
|
.loadForRequest(Uri.parse(HttpString.apiBaseUrl));
|
||||||
buvid = cookies.firstWhere((cookie) => cookie.name == 'buvid3').value;
|
buvid = cookies
|
||||||
if (buvid == null) {
|
.firstWhere((cookie) => cookie.name == 'buvid3',
|
||||||
|
orElse: () => Cookie('buvid3', ''))
|
||||||
|
.value;
|
||||||
|
if (buvid == null || buvid!.isEmpty) {
|
||||||
try {
|
try {
|
||||||
var result = await Request().get(
|
var result = await Request().get(
|
||||||
"${HttpString.apiBaseUrl}/x/frontend/finger/spi",
|
"${HttpString.apiBaseUrl}/x/frontend/finger/spi",
|
||||||
|
|||||||
18
lib/models/common/comment_range_type.dart
Normal file
18
lib/models/common/comment_range_type.dart
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
enum CommentRangeType {
|
||||||
|
video,
|
||||||
|
bangumi,
|
||||||
|
// dynamic,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ActionTypeExtension on CommentRangeType {
|
||||||
|
String get value => [
|
||||||
|
'video',
|
||||||
|
'bangumi',
|
||||||
|
// 'dynamic',
|
||||||
|
][index];
|
||||||
|
String get label => [
|
||||||
|
'视频',
|
||||||
|
'番剧',
|
||||||
|
// '动态',
|
||||||
|
][index];
|
||||||
|
}
|
||||||
73
lib/models/common/invalid_video.dart
Normal file
73
lib/models/common/invalid_video.dart
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
class InvalidVideoModel {
|
||||||
|
final int? id;
|
||||||
|
final int? ver;
|
||||||
|
final int? aid;
|
||||||
|
final String? lastupdate;
|
||||||
|
final int? lastupdatets;
|
||||||
|
final String? title;
|
||||||
|
final String? description;
|
||||||
|
final String? pic;
|
||||||
|
final int? tid;
|
||||||
|
final String? typename;
|
||||||
|
final int? created;
|
||||||
|
final String? createdAt;
|
||||||
|
final String? author;
|
||||||
|
final int? mid;
|
||||||
|
final String? play;
|
||||||
|
final String? coins;
|
||||||
|
final String? review;
|
||||||
|
final String? videoReview;
|
||||||
|
final String? favorites;
|
||||||
|
final String? tag;
|
||||||
|
final List<String>? tagList;
|
||||||
|
|
||||||
|
InvalidVideoModel({
|
||||||
|
this.id,
|
||||||
|
this.ver,
|
||||||
|
this.aid,
|
||||||
|
this.lastupdate,
|
||||||
|
this.lastupdatets,
|
||||||
|
this.title,
|
||||||
|
this.description,
|
||||||
|
this.pic,
|
||||||
|
this.tid,
|
||||||
|
this.typename,
|
||||||
|
this.created,
|
||||||
|
this.createdAt,
|
||||||
|
this.author,
|
||||||
|
this.mid,
|
||||||
|
this.play,
|
||||||
|
this.coins,
|
||||||
|
this.review,
|
||||||
|
this.videoReview,
|
||||||
|
this.favorites,
|
||||||
|
this.tag,
|
||||||
|
this.tagList,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory InvalidVideoModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return InvalidVideoModel(
|
||||||
|
id: json['id'],
|
||||||
|
ver: json['ver'],
|
||||||
|
aid: json['aid'],
|
||||||
|
lastupdate: json['lastupdate'],
|
||||||
|
lastupdatets: json['lastupdatets'],
|
||||||
|
title: json['title'],
|
||||||
|
description: json['description'],
|
||||||
|
pic: json['pic'],
|
||||||
|
tid: json['tid'],
|
||||||
|
typename: json['typename'],
|
||||||
|
created: json['created'],
|
||||||
|
createdAt: json['created_at'],
|
||||||
|
author: json['author'],
|
||||||
|
mid: json['mid'],
|
||||||
|
play: json['play'],
|
||||||
|
coins: json['coins'],
|
||||||
|
review: json['review'],
|
||||||
|
videoReview: json['video_review'],
|
||||||
|
favorites: json['favorites'],
|
||||||
|
tag: json['tag'],
|
||||||
|
tagList: json['tag'].toString().split(',').toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,6 +5,7 @@ import 'package:get/get.dart';
|
|||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:pilipala/common/constants.dart';
|
import 'package:pilipala/common/constants.dart';
|
||||||
import 'package:pilipala/common/widgets/badge.dart';
|
import 'package:pilipala/common/widgets/badge.dart';
|
||||||
|
import 'package:pilipala/common/widgets/drag_handle.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
import 'package:pilipala/common/widgets/stat/danmu.dart';
|
import 'package:pilipala/common/widgets/stat/danmu.dart';
|
||||||
import 'package:pilipala/common/widgets/stat/view.dart';
|
import 'package:pilipala/common/widgets/stat/view.dart';
|
||||||
@ -445,27 +446,12 @@ class BangumiStatusWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget morePanel(BuildContext context, BangumiIntroController ctr) {
|
Widget morePanel(BuildContext context, BangumiIntroController ctr) {
|
||||||
return Container(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
const DragHandle(),
|
||||||
onTap: () => Get.back(),
|
|
||||||
child: Container(
|
|
||||||
height: 35,
|
|
||||||
padding: const EdgeInsets.only(bottom: 2),
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 32,
|
|
||||||
height: 3,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(3))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
...ctr.followStatusList
|
...ctr.followStatusList
|
||||||
.map(
|
.map(
|
||||||
(e) => ListTile(
|
(e) => ListTile(
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:pilipala/common/widgets/drag_handle.dart';
|
||||||
import 'package:pilipala/common/widgets/stat/danmu.dart';
|
import 'package:pilipala/common/widgets/stat/danmu.dart';
|
||||||
import 'package:pilipala/common/widgets/stat/view.dart';
|
import 'package:pilipala/common/widgets/stat/view.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
@ -23,94 +24,81 @@ class IntroDetail extends StatelessWidget {
|
|||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
);
|
);
|
||||||
return Container(
|
return Container(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
padding: const EdgeInsets.only(left: 14, right: 14),
|
|
||||||
height: sheetHeight,
|
height: sheetHeight,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
const DragHandle(),
|
||||||
height: 35,
|
|
||||||
padding: const EdgeInsets.only(bottom: 2),
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 32,
|
|
||||||
height: 3,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.onSecondaryContainer
|
|
||||||
.withOpacity(0.5),
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(3))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: Padding(
|
||||||
child: Column(
|
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: SingleChildScrollView(
|
||||||
children: [
|
child: Column(
|
||||||
Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
bangumiDetail!.title,
|
children: [
|
||||||
style: const TextStyle(
|
Text(
|
||||||
fontSize: 16,
|
bangumiDetail!.title,
|
||||||
fontWeight: FontWeight.w500,
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 4),
|
||||||
const SizedBox(height: 4),
|
Row(
|
||||||
Row(
|
children: [
|
||||||
children: [
|
StatView(
|
||||||
StatView(
|
view: bangumiDetail!.stat!['views'],
|
||||||
view: bangumiDetail!.stat!['views'],
|
size: 'medium',
|
||||||
size: 'medium',
|
),
|
||||||
),
|
const SizedBox(width: 6),
|
||||||
const SizedBox(width: 6),
|
StatDanMu(
|
||||||
StatDanMu(
|
danmu: bangumiDetail!.stat!['danmakus'],
|
||||||
danmu: bangumiDetail!.stat!['danmakus'],
|
size: 'medium',
|
||||||
size: 'medium',
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
const SizedBox(height: 4),
|
||||||
const SizedBox(height: 4),
|
Row(
|
||||||
Row(
|
children: [
|
||||||
children: [
|
Text(
|
||||||
Text(
|
bangumiDetail!.areas!.first['name'],
|
||||||
bangumiDetail!.areas!.first['name'],
|
style: smallTitle,
|
||||||
style: smallTitle,
|
),
|
||||||
),
|
const SizedBox(width: 6),
|
||||||
const SizedBox(width: 6),
|
Text(
|
||||||
Text(
|
bangumiDetail!.publish!['pub_time_show'],
|
||||||
bangumiDetail!.publish!['pub_time_show'],
|
style: smallTitle,
|
||||||
style: smallTitle,
|
),
|
||||||
),
|
const SizedBox(width: 6),
|
||||||
const SizedBox(width: 6),
|
Text(
|
||||||
Text(
|
bangumiDetail!.newEp!['desc'],
|
||||||
bangumiDetail!.newEp!['desc'],
|
style: smallTitle,
|
||||||
style: smallTitle,
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
const SizedBox(height: 20),
|
||||||
const SizedBox(height: 20),
|
Text(
|
||||||
Text(
|
'简介:',
|
||||||
'简介:',
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
),
|
||||||
),
|
const SizedBox(height: 4),
|
||||||
const SizedBox(height: 4),
|
Text(
|
||||||
Text(
|
'${bangumiDetail!.evaluate!}',
|
||||||
'${bangumiDetail!.evaluate!}',
|
style: smallTitle.copyWith(fontSize: 13),
|
||||||
style: smallTitle.copyWith(fontSize: 13),
|
),
|
||||||
),
|
const SizedBox(height: 20),
|
||||||
const SizedBox(height: 20),
|
Text(
|
||||||
Text(
|
'声优:',
|
||||||
'声优:',
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
),
|
||||||
),
|
const SizedBox(height: 4),
|
||||||
const SizedBox(height: 4),
|
Text(
|
||||||
Text(
|
bangumiDetail.actors,
|
||||||
bangumiDetail.actors,
|
style: smallTitle.copyWith(fontSize: 13),
|
||||||
style: smallTitle.copyWith(fontSize: 13),
|
),
|
||||||
),
|
SizedBox(height: MediaQuery.of(context).padding.bottom + 20)
|
||||||
SizedBox(height: MediaQuery.of(context).padding.bottom + 20)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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';
|
||||||
|
import 'package:pilipala/common/widgets/drag_handle.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
import 'package:pilipala/http/user.dart';
|
import 'package:pilipala/http/user.dart';
|
||||||
import 'package:pilipala/utils/feed_back.dart';
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
@ -108,28 +109,12 @@ class MorePanel extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
// clipBehavior: Clip.hardEdge,
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
const DragHandle(),
|
||||||
onTap: () => Get.back(),
|
|
||||||
child: Container(
|
|
||||||
height: 35,
|
|
||||||
padding: const EdgeInsets.only(bottom: 2),
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 32,
|
|
||||||
height: 3,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(3))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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';
|
||||||
|
import 'package:pilipala/http/common.dart';
|
||||||
import 'package:pilipala/http/user.dart';
|
import 'package:pilipala/http/user.dart';
|
||||||
import 'package:pilipala/http/video.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/user/fav_detail.dart';
|
import 'package:pilipala/models/user/fav_detail.dart';
|
||||||
@ -8,6 +9,8 @@ import 'package:pilipala/models/user/fav_folder.dart';
|
|||||||
import 'package:pilipala/pages/fav/index.dart';
|
import 'package:pilipala/pages/fav/index.dart';
|
||||||
import 'package:pilipala/utils/utils.dart';
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
|
import 'widget/invalid_video_card.dart';
|
||||||
|
|
||||||
class FavDetailController extends GetxController {
|
class FavDetailController extends GetxController {
|
||||||
FavFolderItemData? item;
|
FavFolderItemData? item;
|
||||||
RxString title = ''.obs;
|
RxString title = ''.obs;
|
||||||
@ -131,8 +134,9 @@ class FavDetailController extends GetxController {
|
|||||||
'privacy': [22, 0].contains(item!.attr) ? 0 : 1,
|
'privacy': [22, 0].contains(item!.attr) ? 0 : 1,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
title.value = res['title'];
|
if (res != null) {
|
||||||
print(title);
|
title.value = res['title'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future toViewPlayAll() async {
|
Future toViewPlayAll() async {
|
||||||
@ -152,4 +156,22 @@ class FavDetailController extends GetxController {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查看无效视频信息
|
||||||
|
Future toViewInvalidVideo(FavDetailItemData item) async {
|
||||||
|
SmartDialog.showLoading(msg: '加载中...');
|
||||||
|
var res = await CommonHttp.fixVideoPicAndTitle(aid: item.id!);
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
if (res['status']) {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: Get.context!,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return InvalidVideoCard(videoInfo: res['data']);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
SmartDialog.showToast(res['msg']);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -226,6 +226,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
isOwner: _favDetailController.isOwner,
|
isOwner: _favDetailController.isOwner,
|
||||||
callFn: () => _favDetailController
|
callFn: () => _favDetailController
|
||||||
.onCancelFav(favList[index].id),
|
.onCancelFav(favList[index].id),
|
||||||
|
viewInvalidVideoCb: () => _favDetailController
|
||||||
|
.toViewInvalidVideo(favList[index]),
|
||||||
);
|
);
|
||||||
}, childCount: favList.length),
|
}, childCount: favList.length),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -19,6 +19,7 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
final Function? callFn;
|
final Function? callFn;
|
||||||
final int? searchType;
|
final int? searchType;
|
||||||
final String isOwner;
|
final String isOwner;
|
||||||
|
final Function? viewInvalidVideoCb;
|
||||||
|
|
||||||
const FavVideoCardH({
|
const FavVideoCardH({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -26,6 +27,7 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
this.callFn,
|
this.callFn,
|
||||||
this.searchType,
|
this.searchType,
|
||||||
required this.isOwner,
|
required this.isOwner,
|
||||||
|
this.viewInvalidVideoCb,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -36,6 +38,10 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// int? seasonId;
|
// int? seasonId;
|
||||||
|
if (videoItem.title == '已失效视频') {
|
||||||
|
viewInvalidVideoCb?.call();
|
||||||
|
return;
|
||||||
|
}
|
||||||
String? epId;
|
String? epId;
|
||||||
if (videoItem.ogv != null &&
|
if (videoItem.ogv != null &&
|
||||||
(videoItem.ogv['type_name'] == '番剧' ||
|
(videoItem.ogv['type_name'] == '番剧' ||
|
||||||
@ -65,11 +71,17 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
epId != null ? SearchType.media_bangumi : SearchType.video,
|
epId != null ? SearchType.media_bangumi : SearchType.video,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onLongPress: () => imageSaveDialog(
|
onLongPress: () {
|
||||||
context,
|
if (videoItem.title == '已失效视频') {
|
||||||
videoItem,
|
SmartDialog.showToast('视频已失效');
|
||||||
SmartDialog.dismiss,
|
return;
|
||||||
),
|
}
|
||||||
|
imageSaveDialog(
|
||||||
|
context,
|
||||||
|
videoItem,
|
||||||
|
SmartDialog.dismiss,
|
||||||
|
);
|
||||||
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
|
|||||||
97
lib/pages/fav_detail/widget/invalid_video_card.dart
Normal file
97
lib/pages/fav_detail/widget/invalid_video_card.dart
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/models/common/invalid_video.dart';
|
||||||
|
|
||||||
|
class InvalidVideoCard extends StatelessWidget {
|
||||||
|
const InvalidVideoCard({required this.videoInfo, Key? key}) : super(key: key);
|
||||||
|
final InvalidVideoModel videoInfo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const TextStyle textStyle = TextStyle(fontSize: 14.0);
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(
|
||||||
|
12,
|
||||||
|
14,
|
||||||
|
12,
|
||||||
|
MediaQuery.of(context).padding.bottom + 20,
|
||||||
|
),
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
double maxWidth = constraints.maxWidth;
|
||||||
|
double maxHeight = maxWidth * 9 / 16;
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
NetworkImgLayer(
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
src: videoInfo.pic,
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
SelectableText(
|
||||||
|
videoInfo.title!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
SelectableText(videoInfo.author!, style: textStyle),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
SelectableText('创建时间:${videoInfo.createdAt}', style: textStyle),
|
||||||
|
SelectableText('更新时间:${videoInfo.lastupdate}',
|
||||||
|
style: textStyle),
|
||||||
|
SelectableText('分类:${videoInfo.typename}', style: textStyle),
|
||||||
|
SelectableText(
|
||||||
|
'投币:${videoInfo.coins} 收藏:${videoInfo.favorites}',
|
||||||
|
style: textStyle),
|
||||||
|
if (videoInfo.tagList != null &&
|
||||||
|
videoInfo.tagList!.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
_buildTags(context, videoInfo.tagList),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTags(BuildContext context, List<String>? videoTags) {
|
||||||
|
final ColorScheme colorScheme = Theme.of(context).colorScheme;
|
||||||
|
return Wrap(
|
||||||
|
spacing: 6,
|
||||||
|
runSpacing: 6,
|
||||||
|
direction: Axis.horizontal,
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
children: videoTags!.map((tag) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed('/searchResult', parameters: {'keyword': tag});
|
||||||
|
},
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: colorScheme.surfaceVariant.withOpacity(0.5),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 10),
|
||||||
|
child: Text(
|
||||||
|
tag,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -53,6 +53,7 @@ class FavEditController extends GetxController {
|
|||||||
intro: intro,
|
intro: intro,
|
||||||
mediaId: mediaId!,
|
mediaId: mediaId!,
|
||||||
cover: cover,
|
cover: cover,
|
||||||
|
privacy: privacy.value,
|
||||||
);
|
);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
SmartDialog.showToast('编辑成功');
|
SmartDialog.showToast('编辑成功');
|
||||||
@ -74,4 +75,14 @@ class FavEditController extends GetxController {
|
|||||||
SmartDialog.showToast(res['msg']);
|
SmartDialog.showToast(res['msg']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void togglePrivacy() {
|
||||||
|
if (privacy.value == 0) {
|
||||||
|
privacy.value = 1;
|
||||||
|
SmartDialog.showToast('设置为私密后,只有自己可见');
|
||||||
|
} else {
|
||||||
|
privacy.value = 0;
|
||||||
|
SmartDialog.showToast('设置为公开后,所有人可见');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,31 +21,22 @@ class _FavEditPageState extends State<FavEditPage> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Obx(
|
title: Obx(
|
||||||
() => _favEditController.type.value == 'add'
|
() => _favEditController.type.value == 'add'
|
||||||
? Text(
|
? const Text('新建收藏夹')
|
||||||
'新建收藏夹',
|
: const Text('编辑收藏夹'),
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
)
|
|
||||||
: Text(
|
|
||||||
'编辑收藏夹',
|
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
Obx(
|
Obx(
|
||||||
() => _favEditController.privacy.value == 0
|
() => IconButton(
|
||||||
? IconButton(
|
onPressed: _favEditController.togglePrivacy,
|
||||||
onPressed: () {
|
icon: Icon(
|
||||||
_favEditController.privacy.value = 1;
|
_favEditController.privacy.value == 0
|
||||||
},
|
? Icons.lock_open_outlined
|
||||||
icon: const Icon(Icons.lock_open_outlined))
|
: Icons.lock_outlined,
|
||||||
: IconButton(
|
color: _favEditController.privacy.value == 0
|
||||||
onPressed: () {
|
? null
|
||||||
_favEditController.privacy.value = 0;
|
: Theme.of(context).colorScheme.error,
|
||||||
},
|
),
|
||||||
icon: Icon(
|
),
|
||||||
Icons.lock_outlined,
|
|
||||||
color: Theme.of(context).colorScheme.error,
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _favEditController.onSubmit, child: const Text('保存')),
|
onPressed: _favEditController.onSubmit, child: const Text('保存')),
|
||||||
|
|||||||
@ -69,7 +69,7 @@ class LiveRoomController extends GetxController {
|
|||||||
Request.getBuvid().then((value) => buvid = value);
|
Request.getBuvid().then((value) => buvid = value);
|
||||||
}
|
}
|
||||||
// CDN优化
|
// CDN优化
|
||||||
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: false);
|
||||||
final userInfo = userInfoCache.get('userInfoCache');
|
final userInfo = userInfoCache.get('userInfoCache');
|
||||||
if (userInfo != null && userInfo.mid != null) {
|
if (userInfo != null && userInfo.mid != null) {
|
||||||
userId = userInfo.mid;
|
userId = userInfo.mid;
|
||||||
|
|||||||
@ -312,25 +312,28 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
// 消息列表
|
// 消息列表
|
||||||
Obx(
|
Visibility(
|
||||||
() => Align(
|
visible: !isLandscape,
|
||||||
alignment: Alignment.bottomCenter,
|
child: Obx(
|
||||||
child: Container(
|
() => Align(
|
||||||
margin: EdgeInsets.only(
|
alignment: Alignment.bottomCenter,
|
||||||
bottom: 90 + padding.bottom,
|
child: Container(
|
||||||
),
|
margin: EdgeInsets.only(
|
||||||
height: Get.size.height -
|
bottom: 90 + padding.bottom,
|
||||||
(padding.top +
|
),
|
||||||
kToolbarHeight +
|
height: Get.size.height -
|
||||||
(_liveRoomController.isPortrait.value
|
(padding.top +
|
||||||
? Get.size.width
|
kToolbarHeight +
|
||||||
: Get.size.width * 9 / 16) +
|
(_liveRoomController.isPortrait.value
|
||||||
100 +
|
? Get.size.width
|
||||||
padding.bottom),
|
: Get.size.width * 9 / 16) +
|
||||||
child: buildMessageListUI(
|
100 +
|
||||||
context,
|
padding.bottom),
|
||||||
_liveRoomController,
|
child: buildMessageListUI(
|
||||||
_scrollController,
|
context,
|
||||||
|
_liveRoomController,
|
||||||
|
_scrollController,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import 'package:flutter/material.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';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:pilipala/models/common/comment_range_type.dart';
|
||||||
import 'package:pilipala/models/common/dynamics_type.dart';
|
import 'package:pilipala/models/common/dynamics_type.dart';
|
||||||
import 'package:pilipala/models/common/reply_sort_type.dart';
|
import 'package:pilipala/models/common/reply_sort_type.dart';
|
||||||
import 'package:pilipala/pages/setting/widgets/select_dialog.dart';
|
import 'package:pilipala/pages/setting/widgets/select_dialog.dart';
|
||||||
@ -27,6 +28,8 @@ class _ExtraSettingState extends State<ExtraSetting> {
|
|||||||
late String defaultSystemProxyHost;
|
late String defaultSystemProxyHost;
|
||||||
late String defaultSystemProxyPort;
|
late String defaultSystemProxyPort;
|
||||||
bool userLogin = false;
|
bool userLogin = false;
|
||||||
|
// 记录每个选项是否被选中的状态
|
||||||
|
late List<String> enableComment;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -47,6 +50,8 @@ class _ExtraSettingState extends State<ExtraSetting> {
|
|||||||
localCache.get(LocalCacheKey.systemProxyHost, defaultValue: '');
|
localCache.get(LocalCacheKey.systemProxyHost, defaultValue: '');
|
||||||
defaultSystemProxyPort =
|
defaultSystemProxyPort =
|
||||||
localCache.get(LocalCacheKey.systemProxyPort, defaultValue: '');
|
localCache.get(LocalCacheKey.systemProxyPort, defaultValue: '');
|
||||||
|
enableComment = setting
|
||||||
|
.get(SettingBoxKey.enableComment, defaultValue: ['video', 'bangumi']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置代理
|
// 设置代理
|
||||||
@ -199,9 +204,94 @@ class _ExtraSettingState extends State<ExtraSetting> {
|
|||||||
GlobalDataCache.enableDlna = val;
|
GlobalDataCache.enableDlna = val;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
SetSwitchItem(
|
||||||
|
title: 'Sponsor Block',
|
||||||
|
subTitle: '自动跳过视频中赞助片段',
|
||||||
|
setKey: SettingBoxKey.enableSponsorBlock,
|
||||||
|
defaultVal: false,
|
||||||
|
callFn: (bool val) {
|
||||||
|
GlobalDataCache.enableSponsorBlock = val;
|
||||||
|
},
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
dense: false,
|
dense: false,
|
||||||
title: Text('评论展示', style: titleStyle),
|
title: Text('评论展示', style: titleStyle),
|
||||||
|
onTap: () async {
|
||||||
|
List<String> tempEnableComment = List.from(enableComment);
|
||||||
|
int? result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
// 带多选框的list
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (BuildContext context, StateSetter setState) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('评论展示'),
|
||||||
|
contentPadding: const EdgeInsets.fromLTRB(0, 24, 0, 24),
|
||||||
|
content: SizedBox(
|
||||||
|
width: double.maxFinite,
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: CommentRangeType.values.length,
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return CheckboxListTile(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24, vertical: 0),
|
||||||
|
title: Text(
|
||||||
|
'${CommentRangeType.values[index].label}评论'),
|
||||||
|
value: tempEnableComment.contains(
|
||||||
|
CommentRangeType.values[index].value),
|
||||||
|
onChanged: (bool? value) {
|
||||||
|
setState(() {
|
||||||
|
if (value == true) {
|
||||||
|
tempEnableComment.add(
|
||||||
|
CommentRangeType.values[index].value);
|
||||||
|
} else {
|
||||||
|
tempEnableComment.remove(
|
||||||
|
CommentRangeType.values[index].value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: Navigator.of(context).pop,
|
||||||
|
child: Text(
|
||||||
|
'取消',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.outline),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
enableComment = tempEnableComment;
|
||||||
|
setting.put(
|
||||||
|
SettingBoxKey.enableComment, enableComment);
|
||||||
|
GlobalDataCache.enableComment = enableComment;
|
||||||
|
SmartDialog.showToast('操作成功');
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: const Text('确认'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
defaultReplySort = result;
|
||||||
|
setting.put(SettingBoxKey.replySortType, result);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: false,
|
||||||
|
title: Text('评论排序', style: titleStyle),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
'当前优先展示「${ReplySortType.values[defaultReplySort].titles}」',
|
'当前优先展示「${ReplySortType.values[defaultReplySort].titles}」',
|
||||||
style: subTitleStyle,
|
style: subTitleStyle,
|
||||||
@ -211,7 +301,7 @@ class _ExtraSettingState extends State<ExtraSetting> {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return SelectDialog<int>(
|
return SelectDialog<int>(
|
||||||
title: '评论展示',
|
title: '评论排序',
|
||||||
value: defaultReplySort,
|
value: defaultReplySort,
|
||||||
values: ReplySortType.values.map((e) {
|
values: ReplySortType.values.map((e) {
|
||||||
return {'title': e.titles, 'value': e.index};
|
return {'title': e.titles, 'value': e.index};
|
||||||
|
|||||||
@ -31,6 +31,7 @@ class _PlaySettingState extends State<PlaySetting> {
|
|||||||
late int defaultFullScreenMode;
|
late int defaultFullScreenMode;
|
||||||
late int defaultBtmProgressBehavior;
|
late int defaultBtmProgressBehavior;
|
||||||
late String defaultAoOutput;
|
late String defaultAoOutput;
|
||||||
|
late String hardwareDecodeFormat;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -49,6 +50,8 @@ class _PlaySettingState extends State<PlaySetting> {
|
|||||||
defaultValue: BtmProgresBehavior.values.first.code);
|
defaultValue: BtmProgresBehavior.values.first.code);
|
||||||
defaultAoOutput =
|
defaultAoOutput =
|
||||||
setting.get(SettingBoxKey.defaultAoOutput, defaultValue: '0');
|
setting.get(SettingBoxKey.defaultAoOutput, defaultValue: '0');
|
||||||
|
hardwareDecodeFormat = setting.get(SettingBoxKey.hardwareDecodeFormat,
|
||||||
|
defaultValue: Platform.isAndroid ? 'auto-safe' : 'auto');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -92,7 +95,7 @@ class _PlaySettingState extends State<PlaySetting> {
|
|||||||
title: 'CDN优化',
|
title: 'CDN优化',
|
||||||
subTitle: '使用优质CDN线路',
|
subTitle: '使用优质CDN线路',
|
||||||
setKey: SettingBoxKey.enableCDN,
|
setKey: SettingBoxKey.enableCDN,
|
||||||
defaultVal: true,
|
defaultVal: false,
|
||||||
),
|
),
|
||||||
const SetSwitchItem(
|
const SetSwitchItem(
|
||||||
title: '自动播放',
|
title: '自动播放',
|
||||||
@ -294,6 +297,34 @@ class _PlaySettingState extends State<PlaySetting> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: false,
|
||||||
|
title: Text('硬解方式', style: titleStyle),
|
||||||
|
subtitle: Text(
|
||||||
|
'当前硬解方式(--hwdec):$hardwareDecodeFormat',
|
||||||
|
style: subTitleStyle,
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
String? result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return SelectDialog<String>(
|
||||||
|
title: '硬解方式',
|
||||||
|
value: hardwareDecodeFormat,
|
||||||
|
values: ['no', 'auto-safe', 'auto', 'yes', 'auto-copy']
|
||||||
|
.map((e) {
|
||||||
|
return {'title': e, 'value': e};
|
||||||
|
}).toList());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
setting.put(SettingBoxKey.hardwareDecodeFormat, result);
|
||||||
|
hardwareDecodeFormat = result;
|
||||||
|
GlobalDataCache.hardwareDecodeFormat = result;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
dense: false,
|
dense: false,
|
||||||
title: Text('默认全屏方式', style: titleStyle),
|
title: Text('默认全屏方式', style: titleStyle),
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import 'package:pilipala/models/video/play/url.dart';
|
|||||||
import 'package:pilipala/models/video/reply/item.dart';
|
import 'package:pilipala/models/video/reply/item.dart';
|
||||||
import 'package:pilipala/pages/video/detail/reply_reply/index.dart';
|
import 'package:pilipala/pages/video/detail/reply_reply/index.dart';
|
||||||
import 'package:pilipala/plugin/pl_player/index.dart';
|
import 'package:pilipala/plugin/pl_player/index.dart';
|
||||||
|
import 'package:pilipala/utils/global_data_cache.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
import 'package:pilipala/utils/utils.dart';
|
import 'package:pilipala/utils/utils.dart';
|
||||||
import 'package:pilipala/utils/video_utils.dart';
|
import 'package:pilipala/utils/video_utils.dart';
|
||||||
@ -141,8 +142,16 @@ class VideoDetailController extends GetxController
|
|||||||
} else if (argMap.containsKey('pic')) {
|
} else if (argMap.containsKey('pic')) {
|
||||||
updateCover(argMap['pic']);
|
updateCover(argMap['pic']);
|
||||||
}
|
}
|
||||||
|
tabs.value = <String>[
|
||||||
tabCtr = TabController(length: 2, vsync: this);
|
'简介',
|
||||||
|
if (videoType == SearchType.video &&
|
||||||
|
GlobalDataCache.enableComment.contains('video'))
|
||||||
|
'评论',
|
||||||
|
if (videoType == SearchType.media_bangumi &&
|
||||||
|
GlobalDataCache.enableComment.contains('bangumi'))
|
||||||
|
'评论'
|
||||||
|
];
|
||||||
|
tabCtr = TabController(length: tabs.length, vsync: this);
|
||||||
autoPlay.value =
|
autoPlay.value =
|
||||||
setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true);
|
setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true);
|
||||||
enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: false);
|
enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: false);
|
||||||
@ -160,7 +169,7 @@ class VideoDetailController extends GetxController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CDN优化
|
// CDN优化
|
||||||
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: false);
|
||||||
// 预设的画质
|
// 预设的画质
|
||||||
cacheVideoQa = setting.get(SettingBoxKey.defaultVideoQa);
|
cacheVideoQa = setting.get(SettingBoxKey.defaultVideoQa);
|
||||||
// 预设的解码格式
|
// 预设的解码格式
|
||||||
@ -199,7 +208,7 @@ class VideoDetailController extends GetxController
|
|||||||
});
|
});
|
||||||
|
|
||||||
/// 仅投稿视频skip
|
/// 仅投稿视频skip
|
||||||
if (videoType == SearchType.video) {
|
if (videoType == SearchType.video && GlobalDataCache.enableSponsorBlock) {
|
||||||
querySkipSegments();
|
querySkipSegments();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import 'package:pilipala/pages/video/detail/controller.dart';
|
|||||||
import 'package:pilipala/pages/video/detail/reply/index.dart';
|
import 'package:pilipala/pages/video/detail/reply/index.dart';
|
||||||
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
||||||
import 'package:pilipala/utils/feed_back.dart';
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
|
import 'package:pilipala/utils/global_data_cache.dart';
|
||||||
import 'package:pilipala/utils/id_utils.dart';
|
import 'package:pilipala/utils/id_utils.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
@ -87,19 +88,22 @@ class VideoIntroController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取视频简介&分p
|
// 获取视频简介&分p
|
||||||
Future queryVideoIntro({cover}) async {
|
Future queryVideoIntro({String? cover, String? type, int? cid}) async {
|
||||||
var result = await VideoHttp.videoIntro(bvid: bvid);
|
var result = await VideoHttp.videoIntro(bvid: bvid);
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
videoDetail.value = result['data']!;
|
videoDetail.value = result['data']!;
|
||||||
ugcSeason = result['data']!.ugcSeason;
|
ugcSeason = result['data']!.ugcSeason;
|
||||||
pages.value = result['data']!.pages!;
|
pages.value = result['data']!.pages!;
|
||||||
lastPlayCid.value = videoDetail.value.cid!;
|
if (type == null) {
|
||||||
if (pages.isNotEmpty) {
|
lastPlayCid.value = cid ?? videoDetail.value.cid!;
|
||||||
lastPlayCid.value = pages.first.cid!;
|
|
||||||
}
|
}
|
||||||
final VideoDetailController videoDetailCtr =
|
final VideoDetailController videoDetailCtr =
|
||||||
Get.find<VideoDetailController>(tag: heroTag);
|
Get.find<VideoDetailController>(tag: heroTag);
|
||||||
videoDetailCtr.tabs.value = ['简介', '评论 ${result['data']?.stat?.reply}'];
|
videoDetailCtr.tabs.value = [
|
||||||
|
'简介',
|
||||||
|
if (GlobalDataCache.enableComment.contains('video'))
|
||||||
|
'评论 ${result['data']?.stat?.reply}'
|
||||||
|
];
|
||||||
videoDetailCtr.cover.value = cover ?? result['data'].pic ?? '';
|
videoDetailCtr.cover.value = cover ?? result['data'].pic ?? '';
|
||||||
// 获取到粉丝数再返回
|
// 获取到粉丝数再返回
|
||||||
await queryUserStat();
|
await queryUserStat();
|
||||||
@ -469,13 +473,16 @@ class VideoIntroController extends GetxController {
|
|||||||
// 重新请求评论
|
// 重新请求评论
|
||||||
try {
|
try {
|
||||||
/// 未渲染回复组件时可能异常
|
/// 未渲染回复组件时可能异常
|
||||||
final VideoReplyController videoReplyCtr =
|
if (GlobalDataCache.enableComment.contains('video')) {
|
||||||
Get.find<VideoReplyController>(tag: heroTag);
|
final VideoReplyController videoReplyCtr =
|
||||||
videoReplyCtr.aid = aid;
|
Get.find<VideoReplyController>(tag: heroTag);
|
||||||
videoReplyCtr.queryReplyList(type: 'init');
|
videoReplyCtr.aid = aid;
|
||||||
|
videoReplyCtr.queryReplyList(type: 'init');
|
||||||
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
this.bvid = bvid;
|
this.bvid = bvid;
|
||||||
await queryVideoIntro(cover: cover);
|
// 点击切换时,优先取当前cid
|
||||||
|
await queryVideoIntro(cover: cover, cid: cid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startTimer() {
|
void startTimer() {
|
||||||
|
|||||||
@ -57,7 +57,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
|||||||
heroTag = Get.arguments['heroTag'];
|
heroTag = Get.arguments['heroTag'];
|
||||||
videoIntroController =
|
videoIntroController =
|
||||||
Get.put(VideoIntroController(bvid: widget.bvid), tag: heroTag);
|
Get.put(VideoIntroController(bvid: widget.bvid), tag: heroTag);
|
||||||
_futureBuilderFuture = videoIntroController.queryVideoIntro();
|
_futureBuilderFuture = videoIntroController.queryVideoIntro(type: 'init');
|
||||||
videoIntroController.videoDetail.listen((value) {
|
videoIntroController.videoDetail.listen((value) {
|
||||||
videoDetail = value;
|
videoDetail = value;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class SeasonPanel extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SeasonPanelState extends State<SeasonPanel> {
|
class _SeasonPanelState extends State<SeasonPanel> {
|
||||||
late List<EpisodeItem> episodes;
|
List<EpisodeItem>? episodes;
|
||||||
late int cid;
|
late int cid;
|
||||||
late RxInt currentIndex = (-1).obs;
|
late RxInt currentIndex = (-1).obs;
|
||||||
final String heroTag = Get.arguments['heroTag'];
|
final String heroTag = Get.arguments['heroTag'];
|
||||||
@ -75,7 +75,10 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
|
|
||||||
// 获取currentIndex
|
// 获取currentIndex
|
||||||
void getCurrentIndex() {
|
void getCurrentIndex() {
|
||||||
currentIndex.value = episodes.indexWhere((EpisodeItem e) => e.cid == cid);
|
if (episodes != null) {
|
||||||
|
currentIndex.value =
|
||||||
|
episodes!.indexWhere((EpisodeItem e) => e.cid == cid);
|
||||||
|
}
|
||||||
final List<SectionItem> sections = widget.ugcSeason.sections!;
|
final List<SectionItem> sections = widget.ugcSeason.sections!;
|
||||||
if (sections.length == 1 && sections.first.type == 1) {
|
if (sections.length == 1 && sections.first.type == 1) {
|
||||||
final List<EpisodeItem> episodesList = sections.first.episodes!;
|
final List<EpisodeItem> episodesList = sections.first.episodes!;
|
||||||
@ -83,6 +86,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
for (int j = 0; j < episodesList[i].pages!.length; j++) {
|
for (int j = 0; j < episodesList[i].pages!.length; j++) {
|
||||||
if (episodesList[i].pages![j].cid == cid) {
|
if (episodesList[i].pages![j].cid == cid) {
|
||||||
currentIndex.value = i;
|
currentIndex.value = i;
|
||||||
|
episodes = episodesList;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,7 +141,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
widget.videoIntroCtr.bottomSheetController =
|
widget.videoIntroCtr.bottomSheetController =
|
||||||
_bottomSheetController = EpisodeBottomSheet(
|
_bottomSheetController = EpisodeBottomSheet(
|
||||||
currentCid: cid,
|
currentCid: cid,
|
||||||
episodes: episodes,
|
episodes: episodes!,
|
||||||
changeFucCall: changeFucCall,
|
changeFucCall: changeFucCall,
|
||||||
sheetHeight: widget.sheetHeight,
|
sheetHeight: widget.sheetHeight,
|
||||||
dataType: VideoEpidoesType.videoEpisode,
|
dataType: VideoEpidoesType.videoEpisode,
|
||||||
@ -165,7 +169,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Obx(() => Text(
|
Obx(() => Text(
|
||||||
'${currentIndex.value + 1}/${episodes.length}',
|
'${currentIndex.value + 1}/${episodes!.length}',
|
||||||
style: Theme.of(context).textTheme.labelMedium,
|
style: Theme.of(context).textTheme.labelMedium,
|
||||||
)),
|
)),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:pilipala/common/widgets/badge.dart';
|
import 'package:pilipala/common/widgets/badge.dart';
|
||||||
|
import 'package:pilipala/common/widgets/drag_handle.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
import 'package:pilipala/http/reply.dart';
|
import 'package:pilipala/http/reply.dart';
|
||||||
import 'package:pilipala/models/common/reply_type.dart';
|
import 'package:pilipala/models/common/reply_type.dart';
|
||||||
@ -1117,27 +1118,12 @@ class MorePanel extends StatelessWidget {
|
|||||||
ColorScheme colorScheme = Theme.of(context).colorScheme;
|
ColorScheme colorScheme = Theme.of(context).colorScheme;
|
||||||
TextTheme textTheme = Theme.of(context).textTheme;
|
TextTheme textTheme = Theme.of(context).textTheme;
|
||||||
Color errorColor = colorScheme.error;
|
Color errorColor = colorScheme.error;
|
||||||
return Container(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
const DragHandle(),
|
||||||
onTap: () => Get.back(),
|
|
||||||
child: Container(
|
|
||||||
height: 35,
|
|
||||||
padding: const EdgeInsets.only(bottom: 2),
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 32,
|
|
||||||
height: 3,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: colorScheme.outline,
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(3))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () async => await menuActionHandler('copyAll'),
|
onTap: () async => await menuActionHandler('copyAll'),
|
||||||
minLeadingWidth: 0,
|
minLeadingWidth: 0,
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import 'package:pilipala/pages/video/detail/related/index.dart';
|
|||||||
import 'package:pilipala/plugin/pl_player/index.dart';
|
import 'package:pilipala/plugin/pl_player/index.dart';
|
||||||
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
||||||
import 'package:pilipala/services/service_locator.dart';
|
import 'package:pilipala/services/service_locator.dart';
|
||||||
|
import 'package:pilipala/utils/global_data_cache.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
import 'package:status_bar_control/status_bar_control.dart';
|
import 'package:status_bar_control/status_bar_control.dart';
|
||||||
|
|
||||||
@ -679,8 +680,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
forceElevated: innerBoxIsScrolled,
|
forceElevated: innerBoxIsScrolled,
|
||||||
expandedHeight: expandedHeight,
|
expandedHeight: expandedHeight,
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
flexibleSpace: SizedBox.expand(
|
||||||
background: PopScope(
|
child: PopScope(
|
||||||
canPop:
|
canPop:
|
||||||
plPlayerController?.isFullScreen.value != true,
|
plPlayerController?.isFullScreen.value != true,
|
||||||
onPopInvoked: (bool didPop) {
|
onPopInvoked: (bool didPop) {
|
||||||
@ -779,13 +780,20 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Obx(
|
if ((vdCtr.videoType == SearchType.media_bangumi &&
|
||||||
() => VideoReplyPanel(
|
GlobalDataCache.enableComment
|
||||||
bvid: vdCtr.bvid,
|
.contains('bangumi')) ||
|
||||||
oid: vdCtr.oid.value,
|
(vdCtr.videoType == SearchType.video &&
|
||||||
onControllerCreated: vdCtr.onControllerCreated,
|
GlobalDataCache.enableComment
|
||||||
),
|
.contains('video'))) ...[
|
||||||
)
|
Obx(
|
||||||
|
() => VideoReplyPanel(
|
||||||
|
bvid: vdCtr.bvid,
|
||||||
|
oid: vdCtr.oid.value,
|
||||||
|
onControllerCreated: vdCtr.onControllerCreated,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:pilipala/common/widgets/drag_handle.dart';
|
||||||
import 'package:pilipala/models/video/ai.dart';
|
import 'package:pilipala/models/video/ai.dart';
|
||||||
import 'package:pilipala/pages/video/detail/index.dart';
|
import 'package:pilipala/pages/video/detail/index.dart';
|
||||||
import 'package:pilipala/utils/global_data_cache.dart';
|
import 'package:pilipala/utils/global_data_cache.dart';
|
||||||
@ -17,21 +18,24 @@ class AiDetail extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
height: GlobalDataCache.sheetHeight,
|
height: GlobalDataCache.sheetHeight,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
_buildHeader(context),
|
const DragHandle(),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||||
if (modelResult!.summary != '') ...[
|
child: Column(
|
||||||
_buildSummaryText(modelResult!.summary!),
|
children: [
|
||||||
const SizedBox(height: 20),
|
if (modelResult!.summary != '') ...[
|
||||||
|
_buildSummaryText(modelResult!.summary!),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
],
|
||||||
|
_buildOutlineList(context),
|
||||||
],
|
],
|
||||||
_buildOutlineList(context),
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -40,20 +44,6 @@ class AiDetail extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHeader(BuildContext context) {
|
|
||||||
return Center(
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).hintColor,
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
|
||||||
),
|
|
||||||
height: 4,
|
|
||||||
width: 40,
|
|
||||||
margin: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildSummaryText(String summary) {
|
Widget _buildSummaryText(String summary) {
|
||||||
return SelectableText(
|
return SelectableText(
|
||||||
summary,
|
summary,
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:ns_danmaku/ns_danmaku.dart';
|
import 'package:ns_danmaku/ns_danmaku.dart';
|
||||||
|
import 'package:pilipala/common/widgets/drag_handle.dart';
|
||||||
import 'package:pilipala/http/user.dart';
|
import 'package:pilipala/http/user.dart';
|
||||||
import 'package:pilipala/models/video/play/quality.dart';
|
import 'package:pilipala/models/video/play/quality.dart';
|
||||||
import 'package:pilipala/models/video/play/url.dart';
|
import 'package:pilipala/models/video/play/url.dart';
|
||||||
@ -102,22 +103,7 @@ class _HeaderControlState extends State<HeaderControl> {
|
|||||||
margin: const EdgeInsets.all(12),
|
margin: const EdgeInsets.all(12),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
SizedBox(
|
const DragHandle(),
|
||||||
height: 35,
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 32,
|
|
||||||
height: 3,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.onSecondaryContainer
|
|
||||||
.withOpacity(0.5),
|
|
||||||
borderRadius:
|
|
||||||
const BorderRadius.all(Radius.circular(3))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Material(
|
child: Material(
|
||||||
child: ListView(
|
child: ListView(
|
||||||
|
|||||||
@ -101,25 +101,11 @@ class _WhisperDetailPageState extends State<WhisperDetailPage>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
title: SizedBox(
|
title: SizedBox(
|
||||||
width: double.infinity,
|
width: double.maxFinite,
|
||||||
height: 50,
|
height: 50,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
|
||||||
width: 34,
|
|
||||||
height: 34,
|
|
||||||
child: IconButton(
|
|
||||||
onPressed: () => Get.back(),
|
|
||||||
icon: Icon(
|
|
||||||
Icons.arrow_back_ios,
|
|
||||||
size: 18,
|
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.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:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:pilipala/common/widgets/drag_handle.dart';
|
||||||
import 'package:pilipala/utils/download.dart';
|
import 'package:pilipala/utils/download.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:status_bar_control/status_bar_control.dart';
|
import 'package:status_bar_control/status_bar_control.dart';
|
||||||
@ -234,17 +234,17 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InteractiveViewerBoundary(
|
return Stack(children: [
|
||||||
controller: _transformationController,
|
InteractiveViewerBoundary(
|
||||||
boundaryWidth: MediaQuery.of(context).size.width,
|
controller: _transformationController,
|
||||||
onScaleChanged: _onScaleChanged,
|
boundaryWidth: MediaQuery.of(context).size.width,
|
||||||
onLeftBoundaryHit: _onLeftBoundaryHit,
|
onScaleChanged: _onScaleChanged,
|
||||||
onRightBoundaryHit: _onRightBoundaryHit,
|
onLeftBoundaryHit: _onLeftBoundaryHit,
|
||||||
onNoBoundaryHit: _onNoBoundaryHit,
|
onRightBoundaryHit: _onRightBoundaryHit,
|
||||||
maxScale: widget.maxScale,
|
onNoBoundaryHit: _onNoBoundaryHit,
|
||||||
minScale: widget.minScale,
|
maxScale: widget.maxScale,
|
||||||
child: Stack(children: [
|
minScale: widget.minScale,
|
||||||
CustomDismissible(
|
child: CustomDismissible(
|
||||||
onDismissed: () {
|
onDismissed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
widget.onDismissed?.call(_pageController!.page!.floor());
|
widget.onDismissed?.call(_pageController!.page!.floor());
|
||||||
@ -275,53 +275,50 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
),
|
||||||
bottom: 0,
|
Positioned(
|
||||||
left: 0,
|
bottom: 0,
|
||||||
right: 0,
|
left: 0,
|
||||||
child: Container(
|
right: 0,
|
||||||
padding: EdgeInsets.fromLTRB(
|
child: Container(
|
||||||
12, 8, 20, MediaQuery.of(context).padding.bottom + 8),
|
padding: EdgeInsets.fromLTRB(
|
||||||
decoration: _enablePageView
|
12, 8, 20, MediaQuery.of(context).padding.bottom + 8),
|
||||||
? BoxDecoration(
|
decoration: _enablePageView
|
||||||
gradient: LinearGradient(
|
? BoxDecoration(
|
||||||
begin: Alignment.topCenter,
|
gradient: LinearGradient(
|
||||||
end: Alignment.bottomCenter,
|
begin: Alignment.topCenter,
|
||||||
colors: [
|
end: Alignment.bottomCenter,
|
||||||
Colors.transparent,
|
colors: [Colors.transparent, Colors.black.withOpacity(0.3)],
|
||||||
Colors.black.withOpacity(0.3)
|
),
|
||||||
],
|
)
|
||||||
),
|
: null,
|
||||||
)
|
child: Row(
|
||||||
: null,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
child: Row(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
IconButton(
|
||||||
children: [
|
icon: const Icon(Icons.close, color: Colors.white),
|
||||||
IconButton(
|
onPressed: () {
|
||||||
icon: const Icon(Icons.close, color: Colors.white),
|
Navigator.of(context).pop();
|
||||||
onPressed: () {
|
widget.onDismissed?.call(_pageController!.page!.floor());
|
||||||
Navigator.of(context).pop();
|
},
|
||||||
widget.onDismissed?.call(_pageController!.page!.floor());
|
),
|
||||||
},
|
widget.sources.length > 1
|
||||||
),
|
? Text(
|
||||||
widget.sources.length > 1
|
"${currentIndex! + 1}/${widget.sources.length}",
|
||||||
? Text(
|
style: const TextStyle(color: Colors.white),
|
||||||
"${currentIndex! + 1}/${widget.sources.length}",
|
)
|
||||||
style: const TextStyle(color: Colors.white),
|
: const SizedBox(),
|
||||||
)
|
PopupMenuButton(
|
||||||
: const SizedBox(),
|
itemBuilder: (context) {
|
||||||
PopupMenuButton(
|
return _buildPopupMenuList();
|
||||||
itemBuilder: (context) {
|
},
|
||||||
return _buildPopupMenuList();
|
child: const Icon(Icons.more_horiz, color: Colors.white),
|
||||||
},
|
),
|
||||||
child: const Icon(Icons.more_horiz, color: Colors.white),
|
],
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
),
|
||||||
);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图片分享
|
// 图片分享
|
||||||
@ -426,29 +423,13 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
|||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return Container(
|
return Padding(
|
||||||
padding:
|
padding:
|
||||||
EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
const DragHandle(),
|
||||||
onTap: () => Get.back(),
|
|
||||||
child: Container(
|
|
||||||
height: 35,
|
|
||||||
padding: const EdgeInsets.only(bottom: 2),
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 32,
|
|
||||||
height: 3,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
borderRadius:
|
|
||||||
const BorderRadius.all(Radius.circular(3))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
..._buildListTitles(),
|
..._buildListTitles(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -472,6 +472,7 @@ class PlPlayerController {
|
|||||||
configuration: VideoControllerConfiguration(
|
configuration: VideoControllerConfiguration(
|
||||||
enableHardwareAcceleration: enableHA,
|
enableHardwareAcceleration: enableHA,
|
||||||
androidAttachSurfaceAfterVideoParameters: false,
|
androidAttachSurfaceAfterVideoParameters: false,
|
||||||
|
hwdec: enableHA ? GlobalDataCache.hardwareDecodeFormat : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -766,29 +766,37 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
// 头部、底部控制条
|
// 头部、底部控制条
|
||||||
Obx(
|
Obx(
|
||||||
() => Column(
|
() => Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
if (widget.headerControl != null || _.headerControl != null)
|
if (widget.headerControl != null || _.headerControl != null) ...[
|
||||||
ClipRect(
|
Flexible(
|
||||||
|
child: ClipRect(
|
||||||
|
child: AppBarAni(
|
||||||
|
controller: animationController,
|
||||||
|
visible: !_.controlsLock.value && _.showControls.value,
|
||||||
|
position: 'top',
|
||||||
|
child: widget.headerControl ?? _.headerControl!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
|
const SizedBox.shrink()
|
||||||
|
],
|
||||||
|
Flexible(
|
||||||
|
flex: _.videoType == 'live' ? 0 : 1,
|
||||||
|
child: ClipRect(
|
||||||
child: AppBarAni(
|
child: AppBarAni(
|
||||||
controller: animationController,
|
controller: animationController,
|
||||||
visible: !_.controlsLock.value && _.showControls.value,
|
visible: !_.controlsLock.value && _.showControls.value,
|
||||||
position: 'top',
|
position: 'bottom',
|
||||||
child: widget.headerControl ?? _.headerControl!,
|
child: widget.bottomControl ??
|
||||||
|
BottomControl(
|
||||||
|
controller: widget.controller,
|
||||||
|
triggerFullScreen: _.triggerFullScreen,
|
||||||
|
buildBottomControl: buildBottomControl(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
|
||||||
ClipRect(
|
|
||||||
child: AppBarAni(
|
|
||||||
controller: animationController,
|
|
||||||
visible: !_.controlsLock.value && _.showControls.value,
|
|
||||||
position: 'bottom',
|
|
||||||
child: widget.bottomControl ??
|
|
||||||
BottomControl(
|
|
||||||
controller: widget.controller,
|
|
||||||
triggerFullScreen: _.triggerFullScreen,
|
|
||||||
buildBottomControl: buildBottomControl(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:io';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:pilipala/models/user/info.dart';
|
import 'package:pilipala/models/user/info.dart';
|
||||||
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
|
||||||
@ -5,7 +6,7 @@ import 'package:pilipala/plugin/pl_player/models/play_speed.dart';
|
|||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
import '../models/common/index.dart';
|
import '../models/common/index.dart';
|
||||||
|
|
||||||
Box setting = GStorage.setting;
|
Box settingBox = GStorage.setting;
|
||||||
Box localCache = GStorage.localCache;
|
Box localCache = GStorage.localCache;
|
||||||
Box videoStorage = GStorage.video;
|
Box videoStorage = GStorage.video;
|
||||||
Box userInfoCache = GStorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
@ -55,6 +56,12 @@ class GlobalDataCache {
|
|||||||
static late bool enableDynamicSwitch;
|
static late bool enableDynamicSwitch;
|
||||||
// 投屏开关
|
// 投屏开关
|
||||||
static bool enableDlna = false;
|
static bool enableDlna = false;
|
||||||
|
// 硬件解码格式
|
||||||
|
static late String hardwareDecodeFormat;
|
||||||
|
// sponsorBlock开关
|
||||||
|
static bool enableSponsorBlock = false;
|
||||||
|
// 视频评论开关
|
||||||
|
static List<String> enableComment = ['video', 'bangumi'];
|
||||||
|
|
||||||
// 私有构造函数
|
// 私有构造函数
|
||||||
GlobalDataCache._();
|
GlobalDataCache._();
|
||||||
@ -67,18 +74,18 @@ class GlobalDataCache {
|
|||||||
|
|
||||||
// 异步初始化方法
|
// 异步初始化方法
|
||||||
static Future<void> initialize() async {
|
static Future<void> initialize() async {
|
||||||
imgQuality = await setting.get(SettingBoxKey.defaultPicQa,
|
imgQuality = await settingBox.get(SettingBoxKey.defaultPicQa,
|
||||||
defaultValue: 10); // 设置全局变量
|
defaultValue: 10); // 设置全局变量
|
||||||
fullScreenGestureMode = FullScreenGestureMode.values[setting.get(
|
fullScreenGestureMode = FullScreenGestureMode.values[settingBox.get(
|
||||||
SettingBoxKey.fullScreenGestureMode,
|
SettingBoxKey.fullScreenGestureMode,
|
||||||
defaultValue: FullScreenGestureMode.fromBottomtoTop.index)];
|
defaultValue: FullScreenGestureMode.fromBottomtoTop.index)];
|
||||||
enablePlayerControlAnimation = setting
|
enablePlayerControlAnimation = settingBox
|
||||||
.get(SettingBoxKey.enablePlayerControlAnimation, defaultValue: true);
|
.get(SettingBoxKey.enablePlayerControlAnimation, defaultValue: true);
|
||||||
actionTypeSort = await setting.get(SettingBoxKey.actionTypeSort,
|
actionTypeSort = await settingBox.get(SettingBoxKey.actionTypeSort,
|
||||||
defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']);
|
defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']);
|
||||||
|
|
||||||
isOpenDanmu =
|
isOpenDanmu = await settingBox.get(SettingBoxKey.enableShowDanmaku,
|
||||||
await setting.get(SettingBoxKey.enableShowDanmaku, defaultValue: false);
|
defaultValue: false);
|
||||||
blockTypes =
|
blockTypes =
|
||||||
await localCache.get(LocalCacheKey.danmakuBlockType, defaultValue: []);
|
await localCache.get(LocalCacheKey.danmakuBlockType, defaultValue: []);
|
||||||
showArea =
|
showArea =
|
||||||
@ -99,7 +106,7 @@ class GlobalDataCache {
|
|||||||
.firstWhere((e) => e.value == defaultPlayRepeat);
|
.firstWhere((e) => e.value == defaultPlayRepeat);
|
||||||
playbackSpeed =
|
playbackSpeed =
|
||||||
await videoStorage.get(VideoBoxKey.playSpeedDefault, defaultValue: 1.0);
|
await videoStorage.get(VideoBoxKey.playSpeedDefault, defaultValue: 1.0);
|
||||||
enableAutoLongPressSpeed = await setting
|
enableAutoLongPressSpeed = await settingBox
|
||||||
.get(SettingBoxKey.enableAutoLongPressSpeed, defaultValue: false);
|
.get(SettingBoxKey.enableAutoLongPressSpeed, defaultValue: false);
|
||||||
if (!enableAutoLongPressSpeed) {
|
if (!enableAutoLongPressSpeed) {
|
||||||
longPressSpeed = await videoStorage.get(VideoBoxKey.longPressSpeedDefault,
|
longPressSpeed = await videoStorage.get(VideoBoxKey.longPressSpeedDefault,
|
||||||
@ -117,11 +124,21 @@ class GlobalDataCache {
|
|||||||
sheetHeight = localCache.get('sheetHeight', defaultValue: 0.0);
|
sheetHeight = localCache.get('sheetHeight', defaultValue: 0.0);
|
||||||
historyCacheList = localCache.get('cacheList', defaultValue: []);
|
historyCacheList = localCache.get('cacheList', defaultValue: []);
|
||||||
enableSearchSuggest =
|
enableSearchSuggest =
|
||||||
setting.get(SettingBoxKey.enableSearchSuggest, defaultValue: true);
|
settingBox.get(SettingBoxKey.enableSearchSuggest, defaultValue: true);
|
||||||
enableAutoExpand =
|
enableAutoExpand =
|
||||||
setting.get(SettingBoxKey.enableAutoExpand, defaultValue: false);
|
settingBox.get(SettingBoxKey.enableAutoExpand, defaultValue: false);
|
||||||
enableDynamicSwitch =
|
enableDynamicSwitch =
|
||||||
setting.get(SettingBoxKey.enableDynamicSwitch, defaultValue: true);
|
settingBox.get(SettingBoxKey.enableDynamicSwitch, defaultValue: true);
|
||||||
enableDlna = setting.get(SettingBoxKey.enableDlna, defaultValue: false);
|
enableDlna = settingBox.get(SettingBoxKey.enableDlna, defaultValue: false);
|
||||||
|
hardwareDecodeFormat = settingBox.get(SettingBoxKey.hardwareDecodeFormat,
|
||||||
|
defaultValue: Platform.isAndroid ? 'auto-safe' : 'auto');
|
||||||
|
settingBox.get(SettingBoxKey.enableDynamicSwitch, defaultValue: true);
|
||||||
|
enableDlna = settingBox.get(SettingBoxKey.enableDlna, defaultValue: false);
|
||||||
|
enableSponsorBlock =
|
||||||
|
settingBox.get(SettingBoxKey.enableSponsorBlock, defaultValue: false);
|
||||||
|
settingBox.get(SettingBoxKey.enableDynamicSwitch, defaultValue: true);
|
||||||
|
enableDlna = settingBox.get(SettingBoxKey.enableDlna, defaultValue: false);
|
||||||
|
enableComment = settingBox
|
||||||
|
.get(SettingBoxKey.enableComment, defaultValue: ['video', 'bangumi']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -116,7 +116,10 @@ class SettingBoxKey {
|
|||||||
enableAutoExpand = 'enableAutoExpand',
|
enableAutoExpand = 'enableAutoExpand',
|
||||||
defaultHomePage = 'defaultHomePage',
|
defaultHomePage = 'defaultHomePage',
|
||||||
enableRelatedVideo = 'enableRelatedVideo',
|
enableRelatedVideo = 'enableRelatedVideo',
|
||||||
enableDlna = 'enableDlna';
|
enableDlna = 'enableDlna',
|
||||||
|
hardwareDecodeFormat = 'hardwareDecodeFormat',
|
||||||
|
enableSponsorBlock = 'enableSponsorBlock',
|
||||||
|
enableComment = 'enableComment';
|
||||||
|
|
||||||
/// 外观
|
/// 外观
|
||||||
static const String themeMode = 'themeMode',
|
static const String themeMode = 'themeMode',
|
||||||
|
|||||||
Reference in New Issue
Block a user