Merge branch 'design'

This commit is contained in:
guozhigq
2024-03-02 11:46:20 +08:00
20 changed files with 169 additions and 29 deletions

View File

@ -0,0 +1,12 @@
enum FullScreenGestureMode {
/// 从上滑到下
fromToptoBottom,
/// 从下滑到上
fromBottomtoTop,
}
extension FullScreenGestureModeExtension on FullScreenGestureMode {
String get values => ['fromToptoBottom', 'fromBottomtoTop'][index];
String get labels => ['从上往下滑进入全屏', '从下往上滑进入全屏'][index];
}

View File

@ -0,0 +1,4 @@
library commonn_model;
export './business_type.dart';
export './gesture_mode.dart';

View File

@ -15,7 +15,7 @@ class FavFolderData {
? json['list'] ? json['list']
.map<FavFolderItemData>((e) => FavFolderItemData.fromJson(e)) .map<FavFolderItemData>((e) => FavFolderItemData.fromJson(e))
.toList() .toList()
: [FavFolderItemData()]; : <FavFolderItemData>[];
hasMore = json['has_more']; hasMore = json['has_more'];
} }
} }

View File

@ -7,8 +7,8 @@ import 'package:pilipala/utils/storage.dart';
class BangumiController extends GetxController { class BangumiController extends GetxController {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
RxList<BangumiListItemModel> bangumiList = [BangumiListItemModel()].obs; RxList<BangumiListItemModel> bangumiList = <BangumiListItemModel>[].obs;
RxList<BangumiListItemModel> bangumiFollowList = [BangumiListItemModel()].obs; RxList<BangumiListItemModel> bangumiFollowList = <BangumiListItemModel>[].obs;
int _currentPage = 1; int _currentPage = 1;
bool isLoadingMore = true; bool isLoadingMore = true;
Box userInfoCache = GStrorage.userInfo; Box userInfoCache = GStrorage.userInfo;

View File

@ -139,7 +139,7 @@ class BlackListController extends GetxController {
int currentPage = 1; int currentPage = 1;
int pageSize = 50; int pageSize = 50;
RxInt total = 0.obs; RxInt total = 0.obs;
RxList<BlackListItem> blackList = [BlackListItem()].obs; RxList<BlackListItem> blackList = <BlackListItem>[].obs;
Future queryBlacklist({type = 'init'}) async { Future queryBlacklist({type = 'init'}) async {
if (type == 'init') { if (type == 'init') {

View File

@ -20,7 +20,7 @@ import 'package:pilipala/utils/utils.dart';
class DynamicsController extends GetxController { class DynamicsController extends GetxController {
int page = 1; int page = 1;
String? offset = ''; String? offset = '';
RxList<DynamicItemModel> dynamicsList = [DynamicItemModel()].obs; RxList<DynamicItemModel> dynamicsList = <DynamicItemModel>[].obs;
Rx<DynamicsType> dynamicsType = DynamicsType.values[0].obs; Rx<DynamicsType> dynamicsType = DynamicsType.values[0].obs;
RxString dynamicsTypeLabel = '全部'.obs; RxString dynamicsTypeLabel = '全部'.obs;
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
@ -105,7 +105,7 @@ class DynamicsController extends GetxController {
onSelectType(value) async { onSelectType(value) async {
dynamicsType.value = filterTypeList[value]['value']; dynamicsType.value = filterTypeList[value]['value'];
dynamicsList.value = [DynamicItemModel()]; dynamicsList.value = <DynamicItemModel>[];
page = 1; page = 1;
initialValue.value = value; initialValue.value = value;
await queryFollowDynamic(); await queryFollowDynamic();
@ -264,7 +264,7 @@ class DynamicsController extends GetxController {
onSelectUp(mid) async { onSelectUp(mid) async {
dynamicsType.value = DynamicsType.values[0]; dynamicsType.value = DynamicsType.values[0];
dynamicsList.value = [DynamicItemModel()]; dynamicsList.value = <DynamicItemModel>[];
page = 1; page = 1;
queryFollowDynamic(); queryFollowDynamic();
} }
@ -293,7 +293,7 @@ class DynamicsController extends GetxController {
dynamicsType.value = DynamicsType.values[0]; dynamicsType.value = DynamicsType.values[0];
initialValue.value = 0; initialValue.value = 0;
SmartDialog.showToast('还原默认加载'); SmartDialog.showToast('还原默认加载');
dynamicsList.value = [DynamicItemModel()]; dynamicsList.value = <DynamicItemModel>[];
queryFollowDynamic(); queryFollowDynamic();
} }
} }

View File

@ -17,7 +17,7 @@ class DynamicDetailController extends GetxController {
int currentPage = 0; int currentPage = 0;
bool isLoadingMore = false; bool isLoadingMore = false;
RxString noMore = ''.obs; RxString noMore = ''.obs;
RxList<ReplyItemModel> replyList = [ReplyItemModel()].obs; RxList<ReplyItemModel> replyList = <ReplyItemModel>[].obs;
RxInt acount = 0.obs; RxInt acount = 0.obs;
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();

View File

@ -10,7 +10,7 @@ class FansController extends GetxController {
int pn = 1; int pn = 1;
int ps = 20; int ps = 20;
int total = 0; int total = 0;
RxList<FansItemModel> fansList = [FansItemModel()].obs; RxList<FansItemModel> fansList = <FansItemModel>[].obs;
late int mid; late int mid;
late String name; late String name;
var userInfo; var userInfo;

View File

@ -7,7 +7,7 @@ class HotController extends GetxController {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
final int _count = 20; final int _count = 20;
int _currentPage = 1; int _currentPage = 1;
RxList<HotVideoItemModel> videoList = [HotVideoItemModel()].obs; RxList<HotVideoItemModel> videoList = <HotVideoItemModel>[].obs;
bool isLoadingMore = false; bool isLoadingMore = false;
bool flag = false; bool flag = false;
OverlayEntry? popupDialog; OverlayEntry? popupDialog;

View File

@ -20,7 +20,7 @@ class MemberController extends GetxController {
Box userInfoCache = GStrorage.userInfo; Box userInfoCache = GStrorage.userInfo;
late int ownerMid; late int ownerMid;
// 投稿列表 // 投稿列表
RxList<VListItemModel>? archiveList = [VListItemModel()].obs; RxList<VListItemModel>? archiveList = <VListItemModel>[].obs;
dynamic userInfo; dynamic userInfo;
RxInt attribute = (-1).obs; RxInt attribute = (-1).obs;
RxString attributeText = '关注'.obs; RxString attributeText = '关注'.obs;

View File

@ -15,7 +15,7 @@ class SSearchController extends GetxController {
Box histiryWord = GStrorage.historyword; Box histiryWord = GStrorage.historyword;
List historyCacheList = []; List historyCacheList = [];
RxList historyList = [].obs; RxList historyList = [].obs;
RxList<SearchSuggestItem> searchSuggestList = [SearchSuggestItem()].obs; RxList<SearchSuggestItem> searchSuggestList = <SearchSuggestItem>[].obs;
final _debouncer = final _debouncer =
Debouncer(delay: const Duration(milliseconds: 200)); // 设置延迟时间 Debouncer(delay: const Duration(milliseconds: 200)); // 设置延迟时间
String hintText = '搜索'; String hintText = '搜索';

View File

@ -0,0 +1,88 @@
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/utils/global_data.dart';
import '../../../models/common/gesture_mode.dart';
import '../../../utils/storage.dart';
import '../widgets/select_dialog.dart';
import '../widgets/switch_item.dart';
class PlayGesturePage extends StatefulWidget {
const PlayGesturePage({super.key});
@override
State<PlayGesturePage> createState() => _PlayGesturePageState();
}
class _PlayGesturePageState extends State<PlayGesturePage> {
Box setting = GStrorage.setting;
late int fullScreenGestureMode;
@override
void initState() {
super.initState();
fullScreenGestureMode = setting.get(SettingBoxKey.fullScreenGestureMode,
defaultValue: FullScreenGestureMode.values.last.index);
}
@override
Widget build(BuildContext context) {
TextStyle titleStyle = Theme.of(context).textTheme.titleMedium!;
TextStyle subTitleStyle = Theme.of(context)
.textTheme
.labelMedium!
.copyWith(color: Theme.of(context).colorScheme.outline);
return Scaffold(
appBar: AppBar(
centerTitle: false,
titleSpacing: 0,
title: Text(
'手势设置',
style: Theme.of(context).textTheme.titleMedium,
),
),
body: ListView(
children: [
ListTile(
dense: false,
title: Text('全屏手势', style: titleStyle),
subtitle: Text(
'通过手势快速进入全屏',
style: subTitleStyle,
),
onTap: () async {
String? result = await showDialog(
context: context,
builder: (context) {
return SelectDialog<String>(
title: '全屏手势',
value: FullScreenGestureMode
.values[fullScreenGestureMode].values,
values: FullScreenGestureMode.values.map((e) {
return {'title': e.labels, 'value': e.values};
}).toList());
},
);
if (result != null) {
GlobalData().fullScreenGestureMode = FullScreenGestureMode
.values
.firstWhere((element) => element.values == result);
fullScreenGestureMode =
GlobalData().fullScreenGestureMode.index;
setting.put(
SettingBoxKey.fullScreenGestureMode, fullScreenGestureMode);
setState(() {});
}
},
),
const SetSwitchItem(
title: '双击快退/快进',
subTitle: '左侧双击快退,右侧双击快进',
setKey: SettingBoxKey.enableQuickDouble,
defaultVal: true,
),
],
),
);
}
}

View File

@ -7,6 +7,7 @@ import 'package:pilipala/models/video/play/quality.dart';
import 'package:pilipala/pages/setting/widgets/select_dialog.dart'; import 'package:pilipala/pages/setting/widgets/select_dialog.dart';
import 'package:pilipala/plugin/pl_player/index.dart'; import 'package:pilipala/plugin/pl_player/index.dart';
import 'package:pilipala/services/service_locator.dart'; import 'package:pilipala/services/service_locator.dart';
import 'package:pilipala/utils/global_data.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
import 'widgets/switch_item.dart'; import 'widgets/switch_item.dart';
@ -73,6 +74,12 @@ class _PlaySettingState extends State<PlaySetting> {
title: Text('倍速设置', style: titleStyle), title: Text('倍速设置', style: titleStyle),
subtitle: Text('设置视频播放速度', style: subTitleStyle), subtitle: Text('设置视频播放速度', style: subTitleStyle),
), ),
ListTile(
dense: false,
onTap: () => Get.toNamed('/playerGestureSet'),
title: Text('手势设置', style: titleStyle),
subtitle: Text('设置播放器手势', style: subTitleStyle),
),
const SetSwitchItem( const SetSwitchItem(
title: '开启1080P', title: '开启1080P',
subTitle: '免登录查看1080P视频', subTitle: '免登录查看1080P视频',
@ -134,18 +141,20 @@ class _PlaySettingState extends State<PlaySetting> {
setKey: SettingBoxKey.enableAutoBrightness, setKey: SettingBoxKey.enableAutoBrightness,
defaultVal: false, defaultVal: false,
), ),
const SetSwitchItem(
title: '双击快退/快进',
subTitle: '左侧双击快退,右侧双击快进',
setKey: SettingBoxKey.enableQuickDouble,
defaultVal: true,
),
const SetSwitchItem( const SetSwitchItem(
title: '弹幕开关', title: '弹幕开关',
subTitle: '展示弹幕', subTitle: '展示弹幕',
setKey: SettingBoxKey.enableShowDanmaku, setKey: SettingBoxKey.enableShowDanmaku,
defaultVal: false, defaultVal: false,
), ),
SetSwitchItem(
title: '控制栏动画',
subTitle: '播放器控制栏显示动画效果',
setKey: SettingBoxKey.enablePlayerControlAnimation,
defaultVal: true,
callFn: (bool val) {
GlobalData().enablePlayerControlAnimation = val;
}),
ListTile( ListTile(
dense: false, dense: false,
title: Text('默认画质', style: titleStyle), title: Text('默认画质', style: titleStyle),

View File

@ -22,7 +22,7 @@ class VideoReplyController extends GetxController {
String? replyLevel; String? replyLevel;
// rpid 请求楼中楼回复 // rpid 请求楼中楼回复
String? rpid; String? rpid;
RxList<ReplyItemModel> replyList = [ReplyItemModel()].obs; RxList<ReplyItemModel> replyList = <ReplyItemModel>[].obs;
// 当前页 // 当前页
int currentPage = 0; int currentPage = 0;
bool isLoadingMore = false; bool isLoadingMore = false;

View File

@ -12,7 +12,7 @@ class VideoReplyReplyController extends GetxController {
// rpid 请求楼中楼回复 // rpid 请求楼中楼回复
String? rpid; String? rpid;
ReplyType replyType = ReplyType.video; ReplyType replyType = ReplyType.video;
RxList<ReplyItemModel> replyList = [ReplyItemModel()].obs; RxList<ReplyItemModel> replyList = <ReplyItemModel>[].obs;
// 当前页 // 当前页
int currentPage = 0; int currentPage = 0;
bool isLoadingMore = false; bool isLoadingMore = false;

View File

@ -9,6 +9,7 @@ import 'package:hive/hive.dart';
import 'package:media_kit/media_kit.dart'; import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart'; import 'package:media_kit_video/media_kit_video.dart';
import 'package:nil/nil.dart'; import 'package:nil/nil.dart';
import 'package:pilipala/models/common/gesture_mode.dart';
import 'package:pilipala/plugin/pl_player/controller.dart'; import 'package:pilipala/plugin/pl_player/controller.dart';
import 'package:pilipala/plugin/pl_player/models/duration.dart'; import 'package:pilipala/plugin/pl_player/models/duration.dart';
import 'package:pilipala/plugin/pl_player/models/fullscreen_mode.dart'; import 'package:pilipala/plugin/pl_player/models/fullscreen_mode.dart';
@ -17,6 +18,7 @@ import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
import 'package:screen_brightness/screen_brightness.dart'; import 'package:screen_brightness/screen_brightness.dart';
import '../../utils/global_data.dart';
import 'models/bottom_progress_behavior.dart'; import 'models/bottom_progress_behavior.dart';
import 'widgets/app_bar_ani.dart'; import 'widgets/app_bar_ani.dart';
import 'widgets/backward_seek.dart'; import 'widgets/backward_seek.dart';
@ -73,6 +75,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
late bool enableQuickDouble; late bool enableQuickDouble;
late bool enableBackgroundPlay; late bool enableBackgroundPlay;
late double screenWidth; late double screenWidth;
final FullScreenGestureMode fullScreenGestureMode =
GlobalData().fullScreenGestureMode;
// 用于记录上一次全屏切换手势触发时间,避免误触 // 用于记录上一次全屏切换手势触发时间,避免误触
DateTime? lastFullScreenToggleTime; DateTime? lastFullScreenToggleTime;
@ -116,7 +120,11 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
super.initState(); super.initState();
screenWidth = Get.size.width; screenWidth = Get.size.width;
animationController = AnimationController( animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 300)); vsync: this,
duration: GlobalData().enablePlayerControlAnimation
? const Duration(milliseconds: 150)
: const Duration(milliseconds: 10),
);
videoController = widget.controller.videoController!; videoController = widget.controller.videoController!;
widget.controller.headerControl = widget.headerControl; widget.controller.headerControl = widget.headerControl;
widget.controller.bottomControl = widget.bottomControl; widget.controller.bottomControl = widget.bottomControl;
@ -520,18 +528,20 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
// 全屏 // 全屏
final double dy = details.delta.dy; final double dy = details.delta.dy;
const double threshold = 7.0; // 滑动阈值 const double threshold = 7.0; // 滑动阈值
final bool flag =
fullScreenGestureMode != FullScreenGestureMode.values.last;
if (dy > _distance && dy > threshold) { if (dy > _distance && dy > threshold) {
if (_.isFullScreen.value) { if (_.isFullScreen.value ^ flag) {
lastFullScreenToggleTime = DateTime.now(); lastFullScreenToggleTime = DateTime.now();
// 下滑退出全屏 // 下滑退出全屏
await widget.controller.triggerFullScreen(status: false); await widget.controller.triggerFullScreen(status: flag);
} }
_distance = 0.0; _distance = 0.0;
} else if (dy < _distance && dy < -threshold) { } else if (dy < _distance && dy < -threshold) {
if (!_.isFullScreen.value) { if (!_.isFullScreen.value ^ flag) {
lastFullScreenToggleTime = DateTime.now(); lastFullScreenToggleTime = DateTime.now();
// 上滑进入全屏 // 上滑进入全屏
await widget.controller.triggerFullScreen(); await widget.controller.triggerFullScreen(status: !flag);
} }
_distance = 0.0; _distance = 0.0;
} }

View File

@ -19,11 +19,11 @@ class AppBarAni extends StatelessWidget implements PreferredSizeWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
visible ? controller.reverse() : controller.forward(); visible ? controller.forward() : controller.reverse();
return SlideTransition( return SlideTransition(
position: Tween<Offset>( position: Tween<Offset>(
begin: Offset.zero, begin: Offset(0, position! == 'top' ? -1 : 1),
end: Offset(0, position! == 'top' ? -1 : 1), end: Offset.zero,
).animate(CurvedAnimation( ).animate(CurvedAnimation(
parent: controller, parent: controller,
curve: Curves.linear, curve: Curves.linear,

View File

@ -39,6 +39,7 @@ import '../pages/setting/pages/color_select.dart';
import '../pages/setting/pages/display_mode.dart'; import '../pages/setting/pages/display_mode.dart';
import '../pages/setting/pages/font_size_select.dart'; import '../pages/setting/pages/font_size_select.dart';
import '../pages/setting/pages/home_tabbar_set.dart'; import '../pages/setting/pages/home_tabbar_set.dart';
import '../pages/setting/pages/play_gesture_set.dart';
import '../pages/setting/pages/play_speed_set.dart'; import '../pages/setting/pages/play_speed_set.dart';
import '../pages/setting/recommend_setting.dart'; import '../pages/setting/recommend_setting.dart';
import '../pages/setting/play_setting.dart'; import '../pages/setting/play_setting.dart';
@ -166,6 +167,9 @@ class Routes {
CustomGetPage(name: '/subscription', page: () => const SubPage()), CustomGetPage(name: '/subscription', page: () => const SubPage()),
// 订阅详情 // 订阅详情
CustomGetPage(name: '/subDetail', page: () => const SubDetailPage()), CustomGetPage(name: '/subDetail', page: () => const SubDetailPage()),
// 播放器手势
CustomGetPage(
name: '/playerGestureSet', page: () => const PlayGesturePage()),
]; ];
} }

View File

@ -1,5 +1,10 @@
import '../models/common/index.dart';
class GlobalData { class GlobalData {
int imgQuality = 10; int imgQuality = 10;
FullScreenGestureMode fullScreenGestureMode =
FullScreenGestureMode.values.last;
bool enablePlayerControlAnimation = true;
// 私有构造函数 // 私有构造函数
GlobalData._(); GlobalData._();

View File

@ -4,6 +4,7 @@ import 'package:path_provider/path_provider.dart';
import 'package:pilipala/models/model_owner.dart'; import 'package:pilipala/models/model_owner.dart';
import 'package:pilipala/models/search/hot.dart'; import 'package:pilipala/models/search/hot.dart';
import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/models/user/info.dart';
import '../models/common/gesture_mode.dart';
import 'global_data.dart'; import 'global_data.dart';
class GStrorage { class GStrorage {
@ -45,6 +46,11 @@ class GStrorage {
video = await Hive.openBox('video'); video = await Hive.openBox('video');
GlobalData().imgQuality = GlobalData().imgQuality =
setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10); // 设置全局变量 setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10); // 设置全局变量
GlobalData().fullScreenGestureMode = FullScreenGestureMode.values[
setting.get(SettingBoxKey.fullScreenGestureMode,
defaultValue: FullScreenGestureMode.values.last.index) as int];
GlobalData().enablePlayerControlAnimation = setting
.get(SettingBoxKey.enablePlayerControlAnimation, defaultValue: true);
} }
static void regAdapter() { static void regAdapter() {
@ -94,11 +100,13 @@ class SettingBoxKey {
enableCDN = 'enableCDN', enableCDN = 'enableCDN',
autoPiP = 'autoPiP', autoPiP = 'autoPiP',
enableAutoLongPressSpeed = 'enableAutoLongPressSpeed', enableAutoLongPressSpeed = 'enableAutoLongPressSpeed',
enablePlayerControlAnimation = 'enablePlayerControlAnimation',
// youtube 双击快进快退 // youtube 双击快进快退
enableQuickDouble = 'enableQuickDouble', enableQuickDouble = 'enableQuickDouble',
enableShowDanmaku = 'enableShowDanmaku', enableShowDanmaku = 'enableShowDanmaku',
enableBackgroundPlay = 'enableBackgroundPlay', enableBackgroundPlay = 'enableBackgroundPlay',
fullScreenGestureMode = 'fullScreenGestureMode',
/// 隐私 /// 隐私
blackMidsList = 'blackMidsList', blackMidsList = 'blackMidsList',