diff --git a/lib/http/init.dart b/lib/http/init.dart index 45dada55..2c266072 100644 --- a/lib/http/init.dart +++ b/lib/http/init.dart @@ -290,15 +290,6 @@ class Request { token.cancel("cancelled"); } - static String headerUa({String type = 'mob'}) { - return switch (type) { - 'mob' => - 'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36', - _ => - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15', - }; - } - static String responseDecoder( List responseBytes, RequestOptions options, diff --git a/lib/http/live.dart b/lib/http/live.dart index 86602dd5..8e42c7e6 100644 --- a/lib/http/live.dart +++ b/lib/http/live.dart @@ -2,6 +2,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/http/api.dart'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/http/ua_type.dart'; import 'package:PiliPlus/models/common/live_search_type.dart'; import 'package:PiliPlus/models_new/live/live_area_list/area_item.dart'; import 'package:PiliPlus/models_new/live/live_area_list/area_list.dart'; @@ -114,7 +115,7 @@ class LiveHttp { options: Options( headers: { 'referer': 'https://live.bilibili.com/$roomId', - 'user-agent': Request.headerUa(type: 'pc'), + 'user-agent': UaType.pc.ua, }, ), ); diff --git a/lib/http/member.dart b/lib/http/member.dart index 43bbfd0f..fa4f0759 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/http/api.dart'; import 'package:PiliPlus/http/constants.dart'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/http/ua_type.dart'; import 'package:PiliPlus/models/common/member/contribute_type.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/models/member/info.dart'; @@ -280,7 +281,7 @@ class MemberHttp { headers: { 'origin': 'https://space.bilibili.com', 'referer': 'https://space.bilibili.com/$mid/dynamic', - 'user-agent': Request.headerUa(type: 'pc'), + 'user-agent': UaType.pc.ua, }, ), ); @@ -352,7 +353,7 @@ class MemberHttp { queryParameters: params, options: Options( headers: { - HttpHeaders.userAgentHeader: Request.headerUa(type: 'pc'), + HttpHeaders.userAgentHeader: UaType.pc.ua, HttpHeaders.refererHeader: '${HttpString.spaceBaseUrl}/$mid', 'origin': HttpString.spaceBaseUrl, }, diff --git a/lib/http/ua_type.dart b/lib/http/ua_type.dart new file mode 100644 index 00000000..bf0ba9ba --- /dev/null +++ b/lib/http/ua_type.dart @@ -0,0 +1,11 @@ +enum UaType { + mob( + 'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36', + ), + pc( + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15', + ); + + final String ua; + const UaType(this.ua); +} diff --git a/lib/http/video.dart b/lib/http/video.dart index 3f8208ef..232af082 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/http/api.dart'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/login.dart'; +import 'package:PiliPlus/http/ua_type.dart'; import 'package:PiliPlus/models/common/account_type.dart'; import 'package:PiliPlus/models/home/rcmd/result.dart'; import 'package:PiliPlus/models/model_hot_video_item.dart'; @@ -367,7 +368,7 @@ class VideoHttp { headers: { 'origin': 'https://www.bilibili.com', 'referer': 'https://www.bilibili.com/bangumi/play/ss$seasonId', - 'user-agent': Request.headerUa(type: 'pc'), + 'user-agent': UaType.pc.ua, }, ), ); @@ -395,7 +396,7 @@ class VideoHttp { headers: { 'origin': 'https://www.bilibili.com', 'referer': 'https://www.bilibili.com/video/$bvid', - 'user-agent': Request.headerUa(type: 'pc'), + 'user-agent': UaType.pc.ua, }, ), ); @@ -593,7 +594,7 @@ class VideoHttp { 'extend_content': jsonEncode({ "entity": "user", "entity_id": mid, - 'fp': Request.headerUa(type: 'pc'), + 'fp': UaType.pc.ua, }), 'csrf': Accounts.main.csrf, }, @@ -602,7 +603,7 @@ class VideoHttp { headers: { 'origin': 'https://space.bilibili.com', 'referer': 'https://space.bilibili.com/$mid/dynamic', - 'user-agent': Request.headerUa(type: 'pc'), + 'user-agent': UaType.pc.ua, }, ), ); diff --git a/lib/models/common/setting_type.dart b/lib/models/common/setting_type.dart new file mode 100644 index 00000000..864f25c6 --- /dev/null +++ b/lib/models/common/setting_type.dart @@ -0,0 +1,13 @@ +enum SettingType { + privacySetting('隐私设置'), + recommendSetting('推荐流设置'), + videoSetting('音视频设置'), + playSetting('播放器设置'), + styleSetting('外观设置'), + extraSetting('其它设置'), + webdavSetting('WebDAV 设置'), + about('关于'); + + final String title; + const SettingType(this.title); +} diff --git a/lib/models/common/video/subtitle_pref_type.dart b/lib/models/common/video/subtitle_pref_type.dart index 8be5aebd..9eae7cca 100644 --- a/lib/models/common/video/subtitle_pref_type.dart +++ b/lib/models/common/video/subtitle_pref_type.dart @@ -1,21 +1,9 @@ -enum SubtitlePrefType { off, on, withoutAi, auto } +enum SubtitlePrefType { + off('默认不显示字幕'), + on('优先选择非自动生成(ai)字幕'), + withoutAi('跳过自动生成(ai)字幕,选择第一个可用字幕'), + auto('静音时等同第二项,非静音时等同第三项'); -extension SubtitlePrefTypeExt on SubtitlePrefType { - String get description => const [ - '默认不显示字幕', - '优先选择非自动生成(ai)字幕', - '跳过自动生成(ai)字幕,选择第一个可用字幕', - '静音时等同第二项,非静音时等同第三项', - ][index]; - - static const List _codeList = ['off', 'on', 'withoutAi', 'auto']; - String get code => _codeList[index]; - - static SubtitlePrefType? fromCode(String code) { - final index = _codeList.indexOf(code); - if (index != -1) { - return SubtitlePrefType.values[index]; - } - return null; - } + final String desc; + const SubtitlePrefType(this.desc); } diff --git a/lib/pages/common/common_intro_controller.dart b/lib/pages/common/common_intro_controller.dart index 01d6e047..bb005406 100644 --- a/lib/pages/common/common_intro_controller.dart +++ b/lib/pages/common/common_intro_controller.dart @@ -31,7 +31,7 @@ abstract class CommonIntroController extends GetxController { Future queryVideoInFolder(); - Future actionFavVideo({String type = 'choose'}); + Future actionFavVideo({bool isQuick = false}); late final enableQuickFav = Pref.enableQuickFav; int? quickFavId; @@ -54,7 +54,7 @@ abstract class CommonIntroController extends GetxController { } // 收藏 - void showFavBottomSheet(BuildContext context, {type = 'tap'}) { + void showFavBottomSheet(BuildContext context, {bool isLongPress = false}) { if (!accountService.isLogin.value) { SmartDialog.showToast('账号未登录'); return; @@ -63,12 +63,12 @@ abstract class CommonIntroController extends GetxController { // 点按 收藏至默认文件夹 // 长按选择文件夹 if (enableQuickFav) { - if (type == 'tap') { - actionFavVideo(type: 'default'); + if (!isLongPress) { + actionFavVideo(isQuick: true); } else { PageUtils.showFavBottomSheet(context: context, ctr: this); } - } else if (type != 'longPress') { + } else if (!isLongPress) { PageUtils.showFavBottomSheet(context: context, ctr: this); } } diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart index ee13df05..0dc2bae2 100644 --- a/lib/pages/dynamics/controller.dart +++ b/lib/pages/dynamics/controller.dart @@ -93,7 +93,7 @@ class DynamicsController extends GetxController } late bool isQuerying = false; - Future queryFollowUp({String type = 'init'}) async { + Future queryFollowUp() async { if (isQuerying) return; isQuerying = true; if (!accountService.isLogin.value) { diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index 50643a29..e46dcf0e 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -36,7 +36,7 @@ class LiveRoomController extends GetxController { // 静音状态 RxBool volumeOff = false.obs; PlPlayerController plPlayerController = PlPlayerController.getInstance( - videoType: 'live', + isLive: true, ); Rx roomInfoH5 = Rx(null); @@ -80,7 +80,7 @@ class LiveRoomController extends GetxController { }, ), autoplay: true, - direction: isPortrait.value ? 'vertical' : 'horizontal', + isVertical: isPortrait.value, ); } diff --git a/lib/pages/live_room/widgets/header_control.dart b/lib/pages/live_room/widgets/header_control.dart index 000aa1ec..bda0b5dd 100644 --- a/lib/pages/live_room/widgets/header_control.dart +++ b/lib/pages/live_room/widgets/header_control.dart @@ -143,7 +143,7 @@ class LiveHeaderControl extends StatelessWidget { if ((await floating.isPipAvailable) == true) { plPlayerController.hiddenControls(false); floating.enable( - plPlayerController.direction.value == 'vertical' + plPlayerController.isVertical ? const EnableManual( aspectRatio: Rational.vertical(), ) diff --git a/lib/pages/setting/models/play_settings.dart b/lib/pages/setting/models/play_settings.dart index 73845b1f..ad1810bc 100644 --- a/lib/pages/setting/models/play_settings.dart +++ b/lib/pages/setting/models/play_settings.dart @@ -95,22 +95,22 @@ List get playSettings => [ title: '自动启用字幕', leading: const Icon(Icons.closed_caption_outlined), getSubtitle: () => - '当前选择偏好:${SubtitlePrefTypeExt.fromCode(Pref.subtitlePreference)!.description}', + '当前选择偏好:${SubtitlePrefType.values[Pref.subtitlePreferenceV2].desc}', onTap: (setState) async { - String? result = await showDialog( + int? result = await showDialog( context: Get.context!, builder: (context) { - return SelectDialog( + return SelectDialog( title: '字幕选择偏好', - value: Pref.subtitlePreference, + value: Pref.subtitlePreferenceV2, values: SubtitlePrefType.values - .map((e) => (e.code, e.description)) + .map((e) => (e.index, e.desc)) .toList(), ); }, ); if (result != null) { - await GStorage.setting.put(SettingBoxKey.subtitlePreference, result); + await GStorage.setting.put(SettingBoxKey.subtitlePreferenceV2, result); setState(); } }, diff --git a/lib/pages/setting/view.dart b/lib/pages/setting/view.dart index ecac7fe6..ff86635e 100644 --- a/lib/pages/setting/view.dart +++ b/lib/pages/setting/view.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/http/login.dart'; +import 'package:PiliPlus/models/common/setting_type.dart'; import 'package:PiliPlus/pages/about/view.dart'; import 'package:PiliPlus/pages/login/controller.dart'; import 'package:PiliPlus/pages/setting/extra_setting.dart'; @@ -18,14 +19,12 @@ import 'package:get/get.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; class _SettingsModel { - final String name; - final String title; + final SettingType type; final String? subtitle; final IconData icon; const _SettingsModel({ - required this.name, - required this.title, + required this.type, this.subtitle, required this.icon, }); @@ -39,55 +38,47 @@ class SettingPage extends StatefulWidget { } class _SettingPageState extends State { - late String _type = 'privacySetting'; + late SettingType _type = SettingType.privacySetting; final RxBool _noAccount = Accounts.accountMode.isEmpty.obs; - bool get _isPortrait => context.orientation == Orientation.portrait; + late bool _isPortrait; final List<_SettingsModel> _items = [ const _SettingsModel( - name: 'privacySetting', - title: '隐私设置', + type: SettingType.privacySetting, subtitle: '黑名单、无痕模式', icon: Icons.privacy_tip_outlined, ), const _SettingsModel( - name: 'recommendSetting', - title: '推荐流设置', + type: SettingType.recommendSetting, subtitle: '推荐来源(web/app)、刷新保留内容、过滤器', icon: Icons.explore_outlined, ), const _SettingsModel( - name: 'videoSetting', - title: '音视频设置', + type: SettingType.videoSetting, subtitle: '画质、音质、解码、缓冲、音频输出等', icon: Icons.video_settings_outlined, ), const _SettingsModel( - name: 'playSetting', - title: '播放器设置', + type: SettingType.playSetting, subtitle: '双击/长按、全屏、后台播放、弹幕、字幕、底部进度条等', icon: Icons.touch_app_outlined, ), const _SettingsModel( - name: 'styleSetting', - title: '外观设置', + type: SettingType.styleSetting, subtitle: '横屏适配(平板)、侧栏、列宽、首页、动态红点、主题、字号、图片、帧率等', icon: Icons.style_outlined, ), const _SettingsModel( - name: 'extraSetting', - title: '其它设置', + type: SettingType.extraSetting, subtitle: '震动、搜索、收藏、ai、评论、动态、代理、更新检查等', icon: Icons.extension_outlined, ), const _SettingsModel( - name: 'webdavSetting', - title: 'WebDAV 设置', + type: SettingType.webdavSetting, icon: MdiIcons.databaseCogOutline, ), const _SettingsModel( - name: 'about', - title: '关于', + type: SettingType.about, icon: Icons.info_outline, ), ]; @@ -95,21 +86,10 @@ class _SettingPageState extends State { @override Widget build(BuildContext context) { final theme = Theme.of(context); + _isPortrait = context.orientation == Orientation.portrait; return Scaffold( appBar: AppBar( - title: _isPortrait - ? const Text('设置') - : Text(switch (_type) { - 'privacySetting' => '隐私设置', - 'recommendSetting' => '推荐流设置', - 'videoSetting' => '音视频设置', - 'playSetting' => '播放器设置', - 'styleSetting' => '外观设置', - 'extraSetting' => '其它设置', - 'webdavSetting' => 'WebDAV 设置', - 'about' => '关于', - _ => '设置', - }), + title: _isPortrait ? const Text('设置') : Text(_type.title), ), body: _isPortrait ? _buildList(theme) @@ -136,21 +116,28 @@ class _SettingPageState extends State { removeLeft: true, removeTop: true, child: switch (_type) { - 'privacySetting' => const PrivacySetting( + SettingType.privacySetting => const PrivacySetting( showAppBar: false, ), - 'recommendSetting' => const RecommendSetting( + SettingType.recommendSetting => const RecommendSetting( showAppBar: false, ), - 'videoSetting' => const VideoSetting(showAppBar: false), - 'playSetting' => const PlaySetting(showAppBar: false), - 'styleSetting' => const StyleSetting(showAppBar: false), - 'extraSetting' => const ExtraSetting(showAppBar: false), - 'webdavSetting' => const WebDavSettingPage( + SettingType.videoSetting => const VideoSetting( showAppBar: false, ), - 'about' => const AboutPage(showAppBar: false), - _ => const SizedBox.shrink(), + SettingType.playSetting => const PlaySetting( + showAppBar: false, + ), + SettingType.styleSetting => const StyleSetting( + showAppBar: false, + ), + SettingType.extraSetting => const ExtraSetting( + showAppBar: false, + ), + SettingType.webdavSetting => const WebDavSettingPage( + showAppBar: false, + ), + SettingType.about => const AboutPage(showAppBar: false), }, ), ), @@ -159,20 +146,20 @@ class _SettingPageState extends State { ); } - void _toPage(String name) { + void _toPage(SettingType type) { if (_isPortrait) { - Get.toNamed('/$name'); + Get.toNamed('/${type.name}'); } else { - _type = name; + _type = type; setState(() {}); } } - Color? _getTileColor(ThemeData theme, String name) { + Color? _getTileColor(ThemeData theme, SettingType type) { if (_isPortrait) { return null; } else { - return name == _type ? theme.colorScheme.onInverseSurface : null; + return type == _type ? theme.colorScheme.onInverseSurface : null; } } @@ -188,10 +175,10 @@ class _SettingPageState extends State { .sublist(0, _items.length - 1) .map( (item) => ListTile( - tileColor: _getTileColor(theme, item.name), - onTap: () => _toPage(item.name), + tileColor: _getTileColor(theme, item.type), + onTap: () => _toPage(item.type), leading: Icon(item.icon), - title: Text(item.title, style: titleStyle), + title: Text(item.type.title, style: titleStyle), subtitle: item.subtitle == null ? null : Text(item.subtitle!, style: subTitleStyle), @@ -212,10 +199,10 @@ class _SettingPageState extends State { ), ), ListTile( - tileColor: _getTileColor(theme, _items.last.name), - onTap: () => _toPage(_items.last.name), + tileColor: _getTileColor(theme, _items.last.type), + onTap: () => _toPage(_items.last.type), leading: Icon(_items.last.icon), - title: Text(_items.last.title, style: titleStyle), + title: Text(_items.last.type.title, style: titleStyle), ), SizedBox(height: MediaQuery.paddingOf(context).bottom + 80), ], diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index 2b31af15..55899821 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -18,6 +18,7 @@ import 'package:PiliPlus/models/common/sponsor_block/segment_model.dart'; import 'package:PiliPlus/models/common/sponsor_block/segment_type.dart'; import 'package:PiliPlus/models/common/sponsor_block/skip_type.dart'; import 'package:PiliPlus/models/common/video/audio_quality.dart'; +import 'package:PiliPlus/models/common/video/subtitle_pref_type.dart'; import 'package:PiliPlus/models/common/video/video_decode_type.dart'; import 'package:PiliPlus/models/common/video/video_quality.dart'; import 'package:PiliPlus/models/video/play/url.dart'; @@ -69,7 +70,7 @@ class VideoDetailController extends GetxController final heroTag = Get.arguments['heroTag']; final RxString cover = ''.obs; // 视频类型 默认投稿视频 - final videoType = Get.arguments['videoType'] ?? SearchType.video; + final SearchType videoType = Get.arguments['videoType'] ?? SearchType.video; /// tabs相关配置 late TabController tabCtr; @@ -122,7 +123,7 @@ class VideoDetailController extends GetxController StreamSubscription? positionSubscription; late final scrollKey = GlobalKey(); - late final RxString direction = 'horizontal'.obs; + late final RxBool isVertical = false.obs; late final RxDouble scrollRatio = 0.0.obs; late final ScrollController scrollCtr = ScrollController() ..addListener(scrollListener); @@ -150,21 +151,17 @@ class VideoDetailController extends GetxController } void setVideoHeight() { - String direction = firstVideo.width != null && firstVideo.height != null - ? firstVideo.width! > firstVideo.height! - ? 'horizontal' - : 'vertical' - : 'horizontal'; + final isVertical = firstVideo.width != null && firstVideo.height != null + ? firstVideo.width! < firstVideo.height! + : false; if (!scrollCtr.hasClients) { - videoHeight = direction == 'vertical' ? maxVideoHeight : minVideoHeight; - this.direction.value = direction; + videoHeight = isVertical ? maxVideoHeight : minVideoHeight; + this.isVertical.value = isVertical; return; } - if (this.direction.value != direction) { - this.direction.value = direction; - double videoHeight = direction == 'vertical' - ? maxVideoHeight - : minVideoHeight; + if (this.isVertical.value != isVertical) { + this.isVertical.value = isVertical; + double videoHeight = isVertical ? maxVideoHeight : minVideoHeight; if (this.videoHeight != videoHeight) { if (videoHeight > this.videoHeight) { // current minVideoHeight @@ -1140,7 +1137,7 @@ class VideoDetailController extends GetxController ? null : Duration(milliseconds: data.timeLength!)), // 宽>高 水平 否则 垂直 - direction: direction.value, + isVertical: isVertical.value, bvid: bvid, cid: cid.value, autoplay: autoplay ?? autoPlay.value, @@ -1562,12 +1559,13 @@ class VideoDetailController extends GetxController int idx = 0; subtitles.value = playInfo.subtitle!.subtitles!; - String preference = Pref.subtitlePreference; - if (preference != 'off') { + SubtitlePrefType preference = + SubtitlePrefType.values[Pref.subtitlePreferenceV2]; + if (preference != SubtitlePrefType.off) { idx = subtitles.indexWhere((i) => !i.lan!.startsWith('ai')) + 1; if (idx == 0) { - if (preference == 'on' || - (preference == 'auto' && + if (preference == SubtitlePrefType.on || + (preference == SubtitlePrefType.auto && (await FlutterVolumeController.getVolume() ?? 0) <= 0)) { idx = 1; } diff --git a/lib/pages/video/introduction/pgc/controller.dart b/lib/pages/video/introduction/pgc/controller.dart index 6d797455..d3d8cda9 100644 --- a/lib/pages/video/introduction/pgc/controller.dart +++ b/lib/pages/video/introduction/pgc/controller.dart @@ -34,7 +34,7 @@ class PgcIntroController extends CommonIntroController { ? int.tryParse(Get.parameters['epId']!) : null; - late dynamic type = + late final String pgcType = Get.parameters['type'] == '1' || Get.parameters['type'] == '4' ? '追番' : '追剧'; @@ -139,9 +139,9 @@ class PgcIntroController extends CommonIntroController { // (取消)收藏 pgc @override - Future actionFavVideo({String type = 'choose'}) async { + Future actionFavVideo({bool isQuick = false}) async { // 收藏至默认文件夹 - if (type == 'default') { + if (isQuick) { SmartDialog.showLoading(msg: '请求中'); queryVideoInFolder().then((res) async { if (res['status']) { diff --git a/lib/pages/video/introduction/pgc/view.dart b/lib/pages/video/introduction/pgc/view.dart index 98e7f7b8..77f40dd0 100644 --- a/lib/pages/video/introduction/pgc/view.dart +++ b/lib/pages/video/introduction/pgc/view.dart @@ -176,7 +176,8 @@ class _PgcIntroPageState extends State if (isFollowed) { showPgcFollowDialog( context: context, - type: pgcIntroController.type, + type: + pgcIntroController.pgcType, followStatus: followStatus, onUpdateStatus: (followStatus) { if (followStatus == -1) { @@ -195,8 +196,8 @@ class _PgcIntroPageState extends State }, child: Text( isFollowed - ? '已${pgcIntroController.type}' - : '${pgcIntroController.type}', + ? '已${pgcIntroController.pgcType}' + : pgcIntroController.pgcType, ), ); }, @@ -317,7 +318,7 @@ class _PgcIntroPageState extends State onTap: () => pgcIntroController.showFavBottomSheet(context), onLongPress: () => pgcIntroController.showFavBottomSheet( context, - type: 'longPress', + isLongPress: true, ), selectStatus: pgcIntroController.hasFav.value, semanticsLabel: '收藏', diff --git a/lib/pages/video/introduction/ugc/controller.dart b/lib/pages/video/introduction/ugc/controller.dart index 1d1d2f66..e5f0aeca 100644 --- a/lib/pages/video/introduction/ugc/controller.dart +++ b/lib/pages/video/introduction/ugc/controller.dart @@ -358,9 +358,9 @@ class VideoIntroController extends CommonIntroController with ReloadMixin { // (取消)收藏 @override - Future actionFavVideo({String type = 'choose'}) async { + Future actionFavVideo({bool isQuick = false}) async { // 收藏至默认文件夹 - if (type == 'default') { + if (isQuick) { SmartDialog.showLoading(msg: '请求中'); queryVideoInFolder().then((res) async { if (res['status']) { diff --git a/lib/pages/video/introduction/ugc/view.dart b/lib/pages/video/introduction/ugc/view.dart index f9e3f370..f1646d8f 100644 --- a/lib/pages/video/introduction/ugc/view.dart +++ b/lib/pages/video/introduction/ugc/view.dart @@ -579,7 +579,7 @@ class _VideoIntroPanelState extends State onTap: () => videoIntroController.showFavBottomSheet(context), onLongPress: () => videoIntroController.showFavBottomSheet( context, - type: 'longPress', + isLongPress: true, ), selectStatus: videoIntroController.hasFav.value, semanticsLabel: '收藏', diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index 25e5e1ca..126d9fed 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -940,8 +940,7 @@ class _VideoDetailPageVState extends State final double width = size.width; final double height = size.height; final padding = MediaQuery.paddingOf(context); - if (enableVerticalExpand && - videoDetailController.direction.value == 'vertical') { + if (enableVerticalExpand && videoDetailController.isVertical.value) { final double videoHeight = height - (removeSafeArea ? 0 : padding.vertical); final double videoWidth = videoHeight * 9 / 16; @@ -1026,8 +1025,7 @@ class _VideoDetailPageVState extends State final double width = size.width; final double height = size.height; final padding = MediaQuery.paddingOf(context); - if (enableVerticalExpand && - videoDetailController.direction.value == 'vertical') { + if (enableVerticalExpand && videoDetailController.isVertical.value) { final double videoHeight = height - (removeSafeArea ? 0 : padding.top); final double videoWidth = videoHeight * 9 / 16; return Row( diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index 874364ae..c581e203 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -2342,7 +2342,7 @@ class HeaderControlState extends State { onTap: () => videoIntroController .showFavBottomSheet(context), onLongPress: () => videoIntroController - .showFavBottomSheet(context, type: 'longPress'), + .showFavBottomSheet(context, isLongPress: true), selectStatus: videoIntroController.hasFav.value, semanticsLabel: '收藏', needAnim: true, @@ -2442,7 +2442,7 @@ class HeaderControlState extends State { onTap: () => pgcIntroController.showFavBottomSheet(context), onLongPress: () => pgcIntroController - .showFavBottomSheet(context, type: 'longPress'), + .showFavBottomSheet(context, isLongPress: true), selectStatus: pgcIntroController.hasFav.value, semanticsLabel: '收藏', needAnim: true, diff --git a/lib/pages/webview/view.dart b/lib/pages/webview/view.dart index c24fc918..032e3c9e 100644 --- a/lib/pages/webview/view.dart +++ b/lib/pages/webview/view.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:PiliPlus/http/init.dart'; +import 'package:PiliPlus/http/ua_type.dart'; import 'package:PiliPlus/models/common/webview_menu_type.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts/account.dart'; @@ -22,7 +22,7 @@ class WebviewPage extends StatefulWidget { // note final int? oid; final String? title; - final String? uaType; + final UaType? uaType; @override State createState() => _WebviewPageState(); @@ -30,7 +30,8 @@ class WebviewPage extends StatefulWidget { class _WebviewPageState extends State { late final String _url = widget.url ?? Get.parameters['url'] ?? ''; - late final uaType = widget.uaType ?? Get.parameters['uaType'] ?? 'mob'; + late final UaType uaType = + widget.uaType ?? UaType.values.byName(Get.parameters['uaType'] ?? 'mob'); final RxString title = ''.obs; final RxDouble progress = 1.0.obs; bool? _inApp; @@ -158,7 +159,7 @@ class _WebviewPageState extends State { useHybridComposition: false, algorithmicDarkeningAllowed: true, useShouldOverrideUrlLoading: true, - userAgent: Request.headerUa(type: uaType), + userAgent: uaType.ua, mixedContentMode: MixedContentMode.MIXED_CONTENT_ALWAYS_ALLOW, ), initialUrlRequest: URLRequest( diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 186712df..774581b0 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -93,9 +93,9 @@ class PlPlayerController { final RxBool _controlsLock = false.obs; final RxBool _isFullScreen = false.obs; // 默认投稿视频格式 - static final RxString _videoType = 'archive'.obs; + bool _isLive = false; - final RxString _direction = 'horizontal'.obs; + bool _isVertical = false; final Rx _videoFit = Rx(BoxFit.contain); late StreamSubscription _dataListenerForVideoFit; @@ -241,12 +241,12 @@ class PlPlayerController { RxBool get isFullScreen => _isFullScreen; /// 全屏方向 - RxString get direction => _direction; + bool get isVertical => _isVertical; RxInt get playerCount => _playerCount; /// - RxString get videoType => _videoType; + bool get isLive => _isLive; /// 弹幕开关 RxBool enableShowDanmaku = Pref.enableShowDanmaku.obs; @@ -467,7 +467,8 @@ class PlPlayerController { Box video = GStorage.video; // 添加一个私有构造函数 - PlPlayerController._() { + PlPlayerController._({bool isLive = false}) { + _isLive = isLive; if (!Accounts.get(AccountType.heartbeat).isLogin || Pref.historyPause) { enableHeart = false; } @@ -492,13 +493,10 @@ class PlPlayerController { } // 获取实例 传参 - static PlPlayerController getInstance({ - String videoType = 'archive', - }) { + static PlPlayerController getInstance({bool isLive = false}) { // 如果实例尚未创建,则创建一个新实例 - _instance ??= PlPlayerController._(); + _instance ??= PlPlayerController._(isLive: isLive); _instance!._playerCount.value += 1; - _videoType.value = videoType; return _instance!; } @@ -520,7 +518,7 @@ class PlPlayerController { int? height, Duration? duration, // 方向 - String? direction, + bool? isVertical, // 记录历史记录 String bvid = '', int cid = 0, @@ -544,7 +542,7 @@ class PlPlayerController { // 初始化数据加载状态 dataStatus.status.value = DataStatus.loading; // 初始化全屏方向 - _direction.value = direction ?? 'horizontal'; + _isVertical = isVertical ?? false; _bvid = bvid; _cid = cid; _epid = epid; @@ -697,12 +695,8 @@ class PlPlayerController { configuration: PlayerConfiguration( // 默认缓冲 4M 大小 bufferSize: Pref.expandBuffer - ? (videoType.value == 'live' - ? 64 * 1024 * 1024 - : 32 * 1024 * 1024) - : (videoType.value == 'live' - ? 16 * 1024 * 1024 - : 4 * 1024 * 1024), + ? (isLive ? 64 * 1024 * 1024 : 32 * 1024 * 1024) + : (isLive ? 16 * 1024 * 1024 : 4 * 1024 * 1024), ), ); var pp = player.platform as NativePlayer; @@ -833,7 +827,7 @@ class PlPlayerController { Future _initializePlayer() async { if (_instance == null) return; // 设置倍速 - if (videoType.value == 'live') { + if (isLive) { await setPlaybackSpeed(1.0); } else { if (_videoPlayerController?.state.rate != _playbackSpeed.value) { @@ -891,7 +885,7 @@ class PlPlayerController { videoPlayerServiceHandler.onStatusChange( playerStatus.status.value, isBuffering.value, - videoType.value == 'live', + isLive, ); /// 触发回调事件 @@ -941,12 +935,12 @@ class PlPlayerController { videoPlayerServiceHandler.onStatusChange( playerStatus.status.value, event, - videoType.value == 'live', + isLive, ); }), videoPlayerController!.stream.error.listen((String event) { // 直播的错误提示没有参考价值,均不予显示 - if (videoType.value == 'live') return; + if (isLive) return; if (event.startsWith("Failed to open https://") || event.startsWith("Can not open external file https://") || //tcp: ffurl_read returned 0xdfb9b0bb @@ -957,11 +951,12 @@ class PlPlayerController { const Duration(milliseconds: 10000), () { Future.delayed(const Duration(milliseconds: 3000), () async { - if (kDebugMode) { - debugPrint("isBuffering.value: ${isBuffering.value}"); - } - if (kDebugMode) - debugPrint("_buffered.value: ${_buffered.value}"); + // if (kDebugMode) { + // debugPrint("isBuffering.value: ${isBuffering.value}"); + // } + // if (kDebugMode) { + // debugPrint("_buffered.value: ${_buffered.value}"); + // } if (isBuffering.value && _buffered.value == Duration.zero) { SmartDialog.showToast( '视频链接打开失败,重试中', @@ -998,7 +993,7 @@ class PlPlayerController { videoPlayerServiceHandler.onStatusChange( event, isBuffering.value, - videoType.value == 'live', + isLive, ); }), onPositionChanged.listen((Duration event) { @@ -1286,7 +1281,7 @@ class PlPlayerController { }); } // fill不应该在竖屏视频生效 - } else if (attr == BoxFit.fill && direction.value == 'vertical') { + } else if (attr == BoxFit.fill && isVertical) { attr = BoxFit.contain; } _videoFit.value = attr; @@ -1312,7 +1307,7 @@ class PlPlayerController { /// 设置长按倍速状态 live模式下禁用 Future setLongPressStatus(bool val) async { - if (videoType.value == 'live') { + if (isLive) { return; } if (controlsLock.value) { @@ -1376,10 +1371,9 @@ class PlPlayerController { return; } if (mode == FullScreenMode.vertical || - (mode == FullScreenMode.auto && direction.value == 'vertical') || + (mode == FullScreenMode.auto && isVertical) || (mode == FullScreenMode.ratio && - (Get.height / Get.width < 1.25 || - direction.value == 'vertical'))) { + (Get.height / Get.width < 1.25 || isVertical))) { await verticalScreenForTwoSeconds(); } else { await landScape(); @@ -1445,7 +1439,7 @@ class PlPlayerController { return; } } - if (videoType.value == 'live') { + if (isLive) { return; } bool isComplete = @@ -1512,9 +1506,9 @@ class PlPlayerController { ..put(SettingBoxKey.subtitleFontWeight, subtitleFontWeight); } - Future dispose({String type = 'single'}) async { + Future dispose() async { // 每次减1,最后销毁 - if (type == 'single' && playerCount.value > 1) { + if (playerCount.value > 1) { _playerCount.value -= 1; _heartDuration = 0; if (!Get.previousRoute.startsWith('/video')) { diff --git a/lib/plugin/pl_player/models/double_tap_type.dart b/lib/plugin/pl_player/models/double_tap_type.dart new file mode 100644 index 00000000..3ee31af3 --- /dev/null +++ b/lib/plugin/pl_player/models/double_tap_type.dart @@ -0,0 +1 @@ +enum DoubleTapType { left, center, right } diff --git a/lib/plugin/pl_player/models/gesture_type.dart b/lib/plugin/pl_player/models/gesture_type.dart new file mode 100644 index 00000000..f89eec8f --- /dev/null +++ b/lib/plugin/pl_player/models/gesture_type.dart @@ -0,0 +1,10 @@ +// ignore_for_file: constant_identifier_names + +enum GestureType { + left, + center, + right, + horizontal, + center_up, + center_down, +} diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 4cb362ef..6362d570 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -16,8 +16,10 @@ import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; import 'package:PiliPlus/plugin/pl_player/models/bottom_control_type.dart'; import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart'; +import 'package:PiliPlus/plugin/pl_player/models/double_tap_type.dart'; import 'package:PiliPlus/plugin/pl_player/models/duration.dart'; import 'package:PiliPlus/plugin/pl_player/models/fullscreen_mode.dart'; +import 'package:PiliPlus/plugin/pl_player/models/gesture_type.dart'; import 'package:PiliPlus/plugin/pl_player/utils.dart'; import 'package:PiliPlus/plugin/pl_player/widgets/app_bar_ani.dart'; import 'package:PiliPlus/plugin/pl_player/widgets/backward_seek.dart'; @@ -110,7 +112,7 @@ class _PLVideoPlayerState extends State late final RxBool showRestoreScaleBtn = false.obs; Offset _initialFocalPoint = Offset.zero; - String? _gestureType; + GestureType? _gestureType; //播放器放缩 bool interacting = false; @@ -138,20 +140,20 @@ class _PLVideoPlayerState extends State } } - void doubleTapFuc(String type) { + void doubleTapFuc(DoubleTapType type) { if (!plPlayerController.enableQuickDouble) { onDoubleTapCenter(); return; } switch (type) { - case 'left': + case DoubleTapType.left: // 双击左边区域 👈 onDoubleTapSeekBackward(); break; - case 'center': + case DoubleTapType.center: onDoubleTapCenter(); break; - case 'right': + case DoubleTapType.right: // 双击右边区域 👈 onDoubleTapSeekForward(); break; @@ -770,7 +772,7 @@ class _PLVideoPlayerState extends State if (cumulativeDelta.distance < 1) return; if (cumulativeDelta.dx.abs() > 3 * cumulativeDelta.dy.abs()) { - _gestureType = 'horizontal'; + _gestureType = GestureType.horizontal; } else if (cumulativeDelta.dy.abs() > 3 * cumulativeDelta.dx.abs()) { if (!plPlayerController.enableSlideVolumeBrightness && @@ -787,19 +789,19 @@ class _PLVideoPlayerState extends State return; } // 左边区域 - _gestureType = 'left'; + _gestureType = GestureType.left; } else if (tapPosition < sectionWidth * 2) { if (!plPlayerController.enableSlideFS) { return; } // 全屏 - _gestureType = 'center'; + _gestureType = GestureType.center; } else { if (!plPlayerController.enableSlideVolumeBrightness) { return; } // 右边区域 - _gestureType = 'right'; + _gestureType = GestureType.right; } } else { return; @@ -808,9 +810,9 @@ class _PLVideoPlayerState extends State Offset delta = details.focalPointDelta; - if (_gestureType == 'horizontal') { + if (_gestureType == GestureType.horizontal) { // live模式下禁用 - if (plPlayerController.videoType.value == 'live') return; + if (plPlayerController.isLive) return; final int curSliderPosition = plPlayerController.sliderPosition.value.inMilliseconds; @@ -884,14 +886,14 @@ class _PLVideoPlayerState extends State } } catch (_) {} } - } else if (_gestureType == 'left') { + } else if (_gestureType == GestureType.left) { // 左边区域 👈 final double level = maxHeight * 3; final double brightness = _brightnessValue.value - delta.dy / level; final double result = brightness.clamp(0.0, 1.0); setBrightness(result); - } else if (_gestureType == 'center') { + } else if (_gestureType == GestureType.center) { // 全屏 const double threshold = 2.5; // 滑动阈值 double cumulativeDy = @@ -902,7 +904,7 @@ class _PLVideoPlayerState extends State } if (cumulativeDy > threshold) { - _gestureType = 'center_down'; + _gestureType = GestureType.center_down; if (isFullScreen ^ plPlayerController.fullScreenGestureReverse) { fullScreenTrigger( @@ -911,7 +913,7 @@ class _PLVideoPlayerState extends State } // if (kDebugMode) debugPrint('center_down:$cumulativeDy'); } else if (cumulativeDy < -threshold) { - _gestureType = 'center_up'; + _gestureType = GestureType.center_up; if (!isFullScreen ^ plPlayerController.fullScreenGestureReverse) { fullScreenTrigger( @@ -920,7 +922,7 @@ class _PLVideoPlayerState extends State } // if (kDebugMode) debugPrint('center_up:$cumulativeDy'); } - } else if (_gestureType == 'right') { + } else if (_gestureType == GestureType.right) { // 右边区域 final double level = maxHeight * 0.5; EasyThrottle.throttle( @@ -975,25 +977,25 @@ class _PLVideoPlayerState extends State } final double tapPosition = details.localPosition.dx; final double sectionWidth = maxWidth / 3; - late String gestureType; + late GestureType gestureType; if (tapPosition < sectionWidth) { if (!plPlayerController.enableSlideVolumeBrightness) { return; } // 左边区域 - gestureType = 'left'; + gestureType = GestureType.left; } else if (tapPosition < sectionWidth * 2) { if (!plPlayerController.enableSlideFS) { return; } // 全屏 - gestureType = 'center'; + gestureType = GestureType.center; } else { if (!plPlayerController.enableSlideVolumeBrightness) { return; } // 右边区域 - gestureType = 'right'; + gestureType = GestureType.right; } if (_gestureType != null && _gestureType != gestureType) { @@ -1001,14 +1003,14 @@ class _PLVideoPlayerState extends State } _gestureType = gestureType; - if (_gestureType == 'left') { + if (_gestureType == GestureType.left) { // 左边区域 👈 final double level = maxHeight * 3; final double brightness = _brightnessValue.value - details.delta.dy / level; final double result = brightness.clamp(0.0, 1.0); setBrightness(result); - } else if (_gestureType == 'center') { + } else if (_gestureType == GestureType.center) { // 全屏 const double threshold = 2.5; // 滑动阈值 double cumulativeDy = @@ -1019,7 +1021,7 @@ class _PLVideoPlayerState extends State } if (cumulativeDy > threshold) { - _gestureType = 'center_down'; + _gestureType = GestureType.center_down; if (isFullScreen ^ plPlayerController.fullScreenGestureReverse) { fullScreenTrigger( @@ -1028,7 +1030,7 @@ class _PLVideoPlayerState extends State } // if (kDebugMode) debugPrint('center_down:$cumulativeDy'); } else if (cumulativeDy < -threshold) { - _gestureType = 'center_up'; + _gestureType = GestureType.center_up; if (!isFullScreen ^ plPlayerController.fullScreenGestureReverse) { fullScreenTrigger( @@ -1037,7 +1039,7 @@ class _PLVideoPlayerState extends State } // if (kDebugMode) debugPrint('center_up:$cumulativeDy'); } - } else if (_gestureType == 'right') { + } else if (_gestureType == GestureType.right) { // 右边区域 final double level = maxHeight * 0.5; EasyThrottle.throttle( @@ -1065,19 +1067,19 @@ class _PLVideoPlayerState extends State if (plPlayerController.controlsLock.value) { return; } - if (plPlayerController.videoType.value == 'live') { - doubleTapFuc('center'); + if (plPlayerController.isLive) { + doubleTapFuc(DoubleTapType.center); return; } final double tapPosition = details.localPosition.dx; final double sectionWidth = maxWidth / 4; - String type = 'left'; + DoubleTapType type; if (tapPosition < sectionWidth) { - type = 'left'; + type = DoubleTapType.left; } else if (tapPosition < sectionWidth * 3) { - type = 'center'; + type = DoubleTapType.center; } else { - type = 'right'; + type = DoubleTapType.right; } doubleTapFuc(type); }, @@ -1426,7 +1428,7 @@ class _PLVideoPlayerState extends State } } - if (plPlayerController.videoType.value == 'live') { + if (plPlayerController.isLive) { return const SizedBox.shrink(); } @@ -1551,9 +1553,7 @@ class _PLVideoPlayerState extends State SafeArea( child: Obx( () => Visibility( - visible: - plPlayerController.videoType.value != 'live' && - isFullScreen, + visible: !plPlayerController.isLive && isFullScreen, child: Align( alignment: Alignment.centerLeft, child: FractionalTranslation( @@ -1895,7 +1895,7 @@ Widget buildSeekPreviewWidget(PlPlayerController plPlayerController) { try { double scale = plPlayerController.isFullScreen.value && - plPlayerController.direction.value == 'horizontal' + !plPlayerController.isVertical ? 4 : 2.5; // offset diff --git a/lib/utils/storage_key.dart b/lib/utils/storage_key.dart index 4efff628..0e935c16 100644 --- a/lib/utils/storage_key.dart +++ b/lib/utils/storage_key.dart @@ -134,7 +134,7 @@ class SettingBoxKey { directExitOnBack = 'directExitOnBack', quickFavId = 'quickFavId'; - static const String subtitlePreference = 'subtitlePreference', + static const String subtitlePreferenceV2 = 'subtitlePreferenceV2', enableDragSubtitle = 'enableDragSubtitle', subtitlePaddingH = 'subtitlePaddingH', subtitlePaddingB = 'subtitlePaddingB', diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index 3d65a6ee..87cc7f3e 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -186,9 +186,9 @@ class Pref { defaultValue: BtmProgressBehavior.alwaysShow.index, ); - static String get subtitlePreference => _setting.get( - SettingBoxKey.subtitlePreference, - defaultValue: SubtitlePrefType.off.code, + static int get subtitlePreferenceV2 => _setting.get( + SettingBoxKey.subtitlePreferenceV2, + defaultValue: SubtitlePrefType.off.index, ); static bool get useRelativeSlide => diff --git a/lib/utils/update.dart b/lib/utils/update.dart index 5750d60b..d73071d1 100644 --- a/lib/utils/update.dart +++ b/lib/utils/update.dart @@ -3,6 +3,7 @@ import 'dart:io' show Platform; import 'package:PiliPlus/build_config.dart'; import 'package:PiliPlus/http/api.dart'; import 'package:PiliPlus/http/init.dart'; +import 'package:PiliPlus/http/ua_type.dart'; import 'package:PiliPlus/utils/accounts/account.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; @@ -22,7 +23,7 @@ class Update { final res = await Request().get( Api.latestApp, options: Options( - headers: {'user-agent': Request.headerUa()}, + headers: {'user-agent': UaType.mob.ua}, extra: {'account': NoAccount()}, ), );