diff --git a/lib/models/common/video/live_quality.dart b/lib/models/common/video/live_quality.dart index f1ee04ccb..62c861d68 100644 --- a/lib/models/common/video/live_quality.dart +++ b/lib/models/common/video/live_quality.dart @@ -1,40 +1,23 @@ enum LiveQuality { - dolby, - super4K, - origin, - bluRay, - superHD, - smooth, - flunt, -} + dolby(30000, '杜比'), + origin4K(25000, '4K 原画'), + super4K(20000, '4K'), + origin(10000, '原画'), + bluRay(400, '蓝光'), + superHD(250, '超清'), + smooth(150, '高清'), + flunt(80, '流畅'); -extension LiveQualityExt on LiveQuality { - static const List _codeList = [ - 30000, - 20000, - 10000, - 400, - 250, - 150, - 80, - ]; - int get code => _codeList[index]; + final int code; + final String desc; + const LiveQuality(this.code, this.desc); - static LiveQuality? fromCode(int code) { - final index = _codeList.indexOf(code); - if (index != -1) { - return LiveQuality.values[index]; + static LiveQuality? fromCode(int? code) { + for (var e in LiveQuality.values) { + if (e.code == code) { + return e; + } } return null; } - - String get description => const [ - '杜比', - '4K', - '原画', - '蓝光', - '超清', - '高清', - '流畅', - ][index]; } diff --git a/lib/pages/about/view.dart b/lib/pages/about/view.dart index 65159c90b..5af069d8d 100644 --- a/lib/pages/about/view.dart +++ b/lib/pages/about/view.dart @@ -97,12 +97,11 @@ class _AboutPageState extends State { ); } }, - child: ConstrainedBox( - constraints: const BoxConstraints(maxHeight: 150), - child: ExcludeSemantics( - child: Image.asset( - 'assets/images/logo/logo.png', - ), + child: ExcludeSemantics( + child: Image.asset( + width: 150, + height: 150, + 'assets/images/logo/logo.png', ), ), ), diff --git a/lib/pages/common/reply_controller.dart b/lib/pages/common/reply_controller.dart index e14ddd004..a0acea088 100644 --- a/lib/pages/common/reply_controller.dart +++ b/lib/pages/common/reply_controller.dart @@ -106,20 +106,21 @@ abstract class ReplyController extends CommonListController { } (bool inputDisable, String? hint) get replyHint { + bool inputDisable = false; + String? hint; try { if (subjectControl != null && subjectControl!.hasRootText()) { - if (subjectControl!.inputDisable) { - SmartDialog.showToast(subjectControl!.rootText); - return (true, null); + final rootText = subjectControl!.rootText; + inputDisable = subjectControl!.inputDisable; + if (inputDisable) { + SmartDialog.showToast(rootText); } - if ((subjectControl!.hasSwitcherType() && - subjectControl!.switcherType != 1) || - subjectControl!.rootText.contains('可发评论')) { - return (false, subjectControl!.rootText); + if (rootText.contains('可发') || rootText.contains('可见')) { + hint = rootText; } } } catch (_) {} - return (false, null); + return (inputDisable, hint); } void onReply( diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index 681654f95..60dc2c860 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -144,18 +144,11 @@ class LiveRoomController extends GetxController { acceptQnList = item.acceptQn!.map((e) { return ( code: e, - desc: - LiveQuality.values - .firstWhereOrNull((element) => element.code == e) - ?.description ?? - e.toString(), + desc: LiveQuality.fromCode(e)?.desc ?? e.toString(), ); }).toList(); currentQnDesc.value = - LiveQuality.values - .firstWhereOrNull((element) => element.code == currentQn) - ?.description ?? - currentQn.toString(); + LiveQuality.fromCode(currentQn)?.desc ?? currentQn.toString(); videoUrl = VideoUtils.getCdnUrl(item); await playerInit(); isLoaded.value = true; @@ -286,10 +279,7 @@ class LiveRoomController extends GetxController { } currentQn = qn; currentQnDesc.value = - LiveQuality.values - .firstWhereOrNull((element) => element.code == currentQn) - ?.description ?? - currentQn.toString(); + LiveQuality.fromCode(currentQn)?.desc ?? currentQn.toString(); return queryLiveUrl(); } diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index f10907098..3f71c2fdf 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -13,6 +13,7 @@ import 'package:PiliPlus/plugin/pl_player/controller.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_status.dart'; import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart'; import 'package:PiliPlus/plugin/pl_player/view.dart'; +import 'package:PiliPlus/plugin/pl_player/widgets/common_btn.dart'; import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/utils/duration_util.dart'; import 'package:PiliPlus/utils/extension.dart'; @@ -46,8 +47,6 @@ class _LiveRoomPageState extends State final GlobalKey chatKey = GlobalKey(); final GlobalKey playerKey = GlobalKey(); - final Color _color = const Color(0xFFEEEEEE); - @override void initState() { super.initState(); @@ -630,13 +629,14 @@ class _LiveRoomPageState extends State child: Padding( padding: const EdgeInsets.only(top: 5, bottom: 10), child: Row( + spacing: 6, children: [ Obx( () { final enableShowDanmaku = plPlayerController.enableShowDanmaku.value; - return IconButton( - onPressed: () { + return ComBtn( + onTap: () { final newVal = !enableShowDanmaku; plPlayerController.enableShowDanmaku.value = newVal; if (!plPlayerController.tempPlayerConf) { @@ -646,19 +646,24 @@ class _LiveRoomPageState extends State ); } }, - icon: Icon( - enableShowDanmaku - ? Icons.subtitles_outlined - : Icons.subtitles_off_outlined, - color: _color, - ), + icon: enableShowDanmaku + ? const Icon( + size: 22, + Icons.subtitles_outlined, + color: Color(0xFFEEEEEE), + ) + : const Icon( + size: 22, + Icons.subtitles_off_outlined, + color: Color(0xFFEEEEEE), + ), ); }, ), - Expanded( + const Expanded( child: Text( '发送弹幕', - style: TextStyle(color: _color), + style: TextStyle(color: Color(0xFFEEEEEE)), ), ), Builder( @@ -675,9 +680,13 @@ class _LiveRoomPageState extends State onTapDown: _liveRoomController.onLikeTapDown, onTapUp: _liveRoomController.onLikeTapUp, onTapCancel: _liveRoomController.onLikeTapUp, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Icon(Icons.thumb_up_off_alt, color: _color), + child: const SizedBox.square( + dimension: 34, + child: Icon( + size: 22, + color: Color(0xFFEEEEEE), + Icons.thumb_up_off_alt, + ), ), ), Positioned( @@ -715,9 +724,13 @@ class _LiveRoomPageState extends State ); }, ), - IconButton( - onPressed: () => onSendDanmaku(true), - icon: Icon(Icons.emoji_emotions_outlined, color: _color), + ComBtn( + onTap: () => onSendDanmaku(true), + icon: const Icon( + size: 22, + color: Color(0xFFEEEEEE), + Icons.emoji_emotions_outlined, + ), ), ], ), diff --git a/lib/pages/live_room/widgets/bottom_control.dart b/lib/pages/live_room/widgets/bottom_control.dart index 85ce98568..60bdf0736 100644 --- a/lib/pages/live_room/widgets/bottom_control.dart +++ b/lib/pages/live_room/widgets/bottom_control.dart @@ -37,6 +37,7 @@ class BottomControl extends StatelessWidget { children: [ PlayOrPauseButton(plPlayerController: plPlayerController), ComBtn( + height: 30, icon: const Icon( Icons.refresh, size: 18, @@ -45,92 +46,81 @@ class BottomControl extends StatelessWidget { onTap: onRefresh, ), const Spacer(), - SizedBox( - width: 35, - height: 35, - child: IconButton( - tooltip: '弹幕屏蔽', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () { - if (liveRoomCtr.isLogin) { - Get.toNamed( - '/liveDmBlockPage', - parameters: { - 'roomId': liveRoomCtr.roomId.toString(), - }, - ); - } else { - SmartDialog.showToast('账号未登录'); - } - }, - icon: const Icon( - size: 18, - Icons.block, - color: Colors.white, - ), + ComBtn( + height: 30, + icon: const Icon( + size: 18, + Icons.block, + color: Colors.white, ), + onTap: () { + if (liveRoomCtr.isLogin) { + Get.toNamed( + '/liveDmBlockPage', + parameters: { + 'roomId': liveRoomCtr.roomId.toString(), + }, + ); + } else { + SmartDialog.showToast('账号未登录'); + } + }, ), - const SizedBox(width: 10), + const SizedBox(width: 3), Obx( () { final enableShowDanmaku = plPlayerController.enableShowDanmaku.value; - return SizedBox( - width: 35, - height: 35, - child: IconButton( - tooltip: '弹幕开关', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () { - final newVal = !enableShowDanmaku; - plPlayerController.enableShowDanmaku.value = newVal; - if (!plPlayerController.tempPlayerConf) { - GStorage.setting.put( - SettingBoxKey.enableShowDanmaku, - newVal, - ); - } - }, - icon: Icon( - size: 18, - enableShowDanmaku - ? Icons.subtitles_outlined - : Icons.subtitles_off_outlined, - color: Colors.white, - ), - ), + return ComBtn( + icon: enableShowDanmaku + ? const Icon( + size: 18, + Icons.subtitles_outlined, + color: Colors.white, + ) + : const Icon( + size: 18, + Icons.subtitles_off_outlined, + color: Colors.white, + ), + onTap: () { + final newVal = !enableShowDanmaku; + plPlayerController.enableShowDanmaku.value = newVal; + if (!plPlayerController.tempPlayerConf) { + GStorage.setting.put( + SettingBoxKey.enableShowDanmaku, + newVal, + ); + } + }, ); }, ), Obx( - () => Container( - height: 30, - margin: const EdgeInsets.symmetric(horizontal: 10), - alignment: Alignment.center, - child: PopupMenuButton( - initialValue: plPlayerController.videoFit.value, - color: Colors.black.withValues(alpha: 0.8), - itemBuilder: (BuildContext context) { - return BoxFit.values.map((BoxFit boxFit) { - return PopupMenuItem( - height: 35, - padding: const EdgeInsets.only(left: 30), - value: boxFit, - onTap: () => plPlayerController.toggleVideoFit(boxFit), - child: Text( - boxFit.desc, - style: const TextStyle( - color: Colors.white, - fontSize: 13, + () => PopupMenuButton( + initialValue: plPlayerController.videoFit.value, + color: Colors.black.withValues(alpha: 0.8), + itemBuilder: (context) { + return BoxFit.values + .map( + (BoxFit boxFit) => PopupMenuItem( + height: 35, + padding: const EdgeInsets.only(left: 30), + value: boxFit, + onTap: () => plPlayerController.toggleVideoFit(boxFit), + child: Text( + boxFit.desc, + style: const TextStyle( + color: Colors.white, + fontSize: 13, + ), ), ), - ); - }).toList(); - }, + ) + .toList(); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), child: Text( plPlayerController.videoFit.value.desc, style: const TextStyle(color: Colors.white, fontSize: 13), @@ -138,46 +128,54 @@ class BottomControl extends StatelessWidget { ), ), ), - const SizedBox(width: 10), Obx( - () => SizedBox( - width: 30, - child: PopupMenuButton( - padding: EdgeInsets.zero, - initialValue: liveRoomCtr.currentQn, - color: Colors.black.withValues(alpha: 0.8), + () => PopupMenuButton( + padding: EdgeInsets.zero, + initialValue: liveRoomCtr.currentQn, + color: Colors.black.withValues(alpha: 0.8), + itemBuilder: (context) { + return liveRoomCtr.acceptQnList + .map( + (e) => PopupMenuItem( + height: 35, + padding: const EdgeInsets.only(left: 30), + value: e.code, + onTap: () => liveRoomCtr.changeQn(e.code), + child: Text( + e.desc, + style: const TextStyle( + color: Colors.white, + fontSize: 13, + ), + ), + ), + ) + .toList(); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), child: Text( liveRoomCtr.currentQnDesc.value, style: const TextStyle(color: Colors.white, fontSize: 13), ), - itemBuilder: (BuildContext context) { - return liveRoomCtr.acceptQnList.map((e) { - return PopupMenuItem( - height: 35, - padding: const EdgeInsets.only(left: 30), - value: e.code, - onTap: () => liveRoomCtr.changeQn(e.code), - child: Text( - e.desc, - style: const TextStyle( - color: Colors.white, - fontSize: 13, - ), - ), - ); - }).toList(); - }, ), ), ), - const SizedBox(width: 10), ComBtn( - icon: const Icon( - Icons.fullscreen, - semanticLabel: '全屏切换', - size: 20, - color: Colors.white, - ), + height: 30, + icon: plPlayerController.isFullScreen.value + ? const Icon( + Icons.fullscreen_exit, + semanticLabel: '退出全屏', + size: 24, + color: Colors.white, + ) + : const Icon( + Icons.fullscreen, + semanticLabel: '全屏', + size: 24, + color: Colors.white, + ), onTap: () => plPlayerController.triggerFullScreen( status: !plPlayerController.isFullScreen.value, ), diff --git a/lib/pages/live_room/widgets/header_control.dart b/lib/pages/live_room/widgets/header_control.dart index bda0b5dde..cadd4f115 100644 --- a/lib/pages/live_room/widgets/header_control.dart +++ b/lib/pages/live_room/widgets/header_control.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; +import 'package:PiliPlus/plugin/pl_player/widgets/common_btn.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:floating/floating.dart'; import 'package:flutter/material.dart'; @@ -27,6 +28,39 @@ class LiveHeaderControl extends StatelessWidget { @override Widget build(BuildContext context) { final isFullScreen = plPlayerController.isFullScreen.value; + Widget child; + if (title != null) { + child = Text( + title!, + maxLines: 1, + style: const TextStyle( + fontSize: 15, + height: 1, + color: Colors.white, + ), + ); + if (isFullScreen && upName != null) { + child = Column( + spacing: 5, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + child, + Text( + upName!, + maxLines: 1, + style: const TextStyle( + fontSize: 12, + height: 1, + color: Colors.white, + ), + ), + ], + ); + } + child = Expanded(child: child); + } else { + child = const Spacer(); + } return AppBar( backgroundColor: Colors.transparent, foregroundColor: Colors.white, @@ -37,147 +71,75 @@ class LiveHeaderControl extends StatelessWidget { spacing: 10, children: [ if (isFullScreen) - SizedBox( - width: 35, - height: 35, - child: IconButton( - tooltip: '返回', - icon: const Icon( - FontAwesomeIcons.arrowLeft, - size: 15, - ), - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () => - plPlayerController.triggerFullScreen(status: false), - ), + ComBtn( + icon: const Icon(FontAwesomeIcons.arrowLeft, size: 15), + onTap: () => plPlayerController.triggerFullScreen(status: false), ), - if (title != null) - Expanded( - child: Column( - spacing: 5, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title!, - maxLines: 1, - style: const TextStyle( - fontSize: 15, - height: 1, - color: Colors.white, - ), - ), - if (isFullScreen && upName != null) - Text( - upName!, - maxLines: 1, - style: const TextStyle( - fontSize: 12, - height: 1, - color: Colors.white, - ), - ), - ], - ), - ) - else - const Spacer(), - SizedBox( - width: 35, - height: 35, - child: IconButton( - tooltip: '发弹幕', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: onSendDanmaku, - icon: const Icon( - Icons.comment_outlined, - size: 18, - color: Colors.white, - ), + child, + ComBtn( + icon: const Icon( + size: 18, + Icons.comment_outlined, + color: Colors.white, ), + onTap: onSendDanmaku, ), Obx( () { final onlyPlayAudio = plPlayerController.onlyPlayAudio.value; - return SizedBox( - width: 35, - height: 35, - child: IconButton( - onPressed: () { - plPlayerController.onlyPlayAudio.value = !onlyPlayAudio; - onPlayAudio(); - }, - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - icon: onlyPlayAudio - ? const Icon( - size: 18, - MdiIcons.musicCircle, - color: Colors.white, - ) - : const Icon( - size: 18, - MdiIcons.musicCircleOutline, - color: Colors.white, - ), - ), + return ComBtn( + onTap: () { + plPlayerController.onlyPlayAudio.value = !onlyPlayAudio; + onPlayAudio(); + }, + icon: onlyPlayAudio + ? const Icon( + size: 18, + MdiIcons.musicCircle, + color: Colors.white, + ) + : const Icon( + size: 18, + MdiIcons.musicCircleOutline, + color: Colors.white, + ), ); }, ), if (Platform.isAndroid) - SizedBox( - width: 35, - height: 35, - child: IconButton( - tooltip: '画中画', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () async { - try { - var floating = Floating(); - if ((await floating.isPipAvailable) == true) { - plPlayerController.hiddenControls(false); - floating.enable( - plPlayerController.isVertical - ? const EnableManual( - aspectRatio: Rational.vertical(), - ) - : const EnableManual(), - ); - } - } catch (_) {} - }, - icon: const Icon( - Icons.picture_in_picture_outlined, - size: 18, - color: Colors.white, - ), - ), - ), - SizedBox( - width: 35, - height: 35, - child: IconButton( - tooltip: '定时关闭', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () => PageUtils.scheduleExit( - context, - plPlayerController.isFullScreen.value, - true, - ), + ComBtn( + onTap: () async { + try { + var floating = Floating(); + if ((await floating.isPipAvailable) == true) { + plPlayerController.hiddenControls(false); + floating.enable( + plPlayerController.isVertical + ? const EnableManual( + aspectRatio: Rational.vertical(), + ) + : const EnableManual(), + ); + } + } catch (_) {} + }, icon: const Icon( size: 18, - Icons.schedule, + Icons.picture_in_picture_outlined, color: Colors.white, ), ), + ComBtn( + onTap: () => PageUtils.scheduleExit( + context, + plPlayerController.isFullScreen.value, + true, + ), + icon: const Icon( + size: 18, + Icons.schedule, + color: Colors.white, + ), ), ], ), diff --git a/lib/pages/member/controller.dart b/lib/pages/member/controller.dart index 443ad2cd7..7ba8d4dba 100644 --- a/lib/pages/member/controller.dart +++ b/lib/pages/member/controller.dart @@ -25,7 +25,6 @@ class MemberController extends CommonDataController MemberController({required this.mid}); int mid; String? username; - RxBool showUname = false.obs; AccountService accountService = Get.find(); @@ -131,7 +130,6 @@ class MemberController extends CommonDataController vsync: this, length: tabs.length, ); - showUname.value = true; username = errMsg; loadingState.value = const Success(null); return true; diff --git a/lib/pages/member/widget/user_info_card.dart b/lib/pages/member/widget/user_info_card.dart index 8e21592a1..0b3e13e07 100644 --- a/lib/pages/member/widget/user_info_card.dart +++ b/lib/pages/member/widget/user_info_card.dart @@ -110,7 +110,7 @@ class UserInfoCard extends StatelessWidget { List _buildLeft(BuildContext context, ThemeData theme) => [ Padding( - padding: const EdgeInsets.only(left: 20, right: 20, top: 5), + padding: const EdgeInsets.only(left: 20, right: 20), child: Wrap( spacing: 8, runSpacing: 8, @@ -461,6 +461,7 @@ class UserInfoCard extends StatelessWidget { ), ], ), + const SizedBox(height: 5), ..._buildLeft(context, theme), if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo(theme), const SizedBox(height: 5), diff --git a/lib/pages/member_video/view.dart b/lib/pages/member_video/view.dart index f361cf13d..f5a8708a4 100644 --- a/lib/pages/member_video/view.dart +++ b/lib/pages/member_video/view.dart @@ -61,27 +61,28 @@ class _MemberVideoState extends State Widget build(BuildContext context) { super.build(context); final theme = Theme.of(context); - return Stack( - clipBehavior: Clip.none, - children: [ - refreshIndicator( - onRefresh: _controller.onRefresh, - child: CustomScrollView( - physics: ReloadScrollPhysics(controller: _controller), - slivers: [ - SliverPadding( - padding: EdgeInsets.only( - bottom: MediaQuery.paddingOf(context).bottom + 80, - ), - sliver: Obx( - () => _buildBody(theme, _controller.loadingState.value), - ), - ), - ], + Widget child = refreshIndicator( + onRefresh: _controller.onRefresh, + child: CustomScrollView( + physics: ReloadScrollPhysics(controller: _controller), + slivers: [ + SliverPadding( + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 80, + ), + sliver: Obx( + () => _buildBody(theme, _controller.loadingState.value), + ), ), - ), - if (widget.type == ContributeType.video && - _controller.fromViewAid?.isNotEmpty == true) + ], + ), + ); + if (widget.type == ContributeType.video && + _controller.fromViewAid?.isNotEmpty == true) { + return Stack( + clipBehavior: Clip.none, + children: [ + child, Obx( () => _controller.isLocating.value != true ? Positioned( @@ -103,6 +104,7 @@ class _MemberVideoState extends State ?.indexWhere((i) => i.param == fromViewAid); if (locatedIndex == null || locatedIndex == -1) { _controller + ..reload = true ..page = 0 ..loadingState.value = LoadingState.loading() ..queryData(); @@ -120,8 +122,10 @@ class _MemberVideoState extends State ) : const SizedBox.shrink(), ), - ], - ); + ], + ); + } + return child; } Widget _buildBody( diff --git a/lib/pages/setting/models/extra_settings.dart b/lib/pages/setting/models/extra_settings.dart index 25d2200b9..9d2b5c6c4 100644 --- a/lib/pages/setting/models/extra_settings.dart +++ b/lib/pages/setting/models/extra_settings.dart @@ -527,14 +527,14 @@ List get extraSettings => [ title: '超分辨率', leading: const Icon(Icons.stay_current_landscape_outlined), getSubtitle: () => - '当前:「${SuperResolutionType.values[Pref.superResolutionType].title}」\n默认设置对番剧生效, 其他视频默认关闭\n超分辨率需要启用硬件解码, 若启用硬件解码后仍然不生效, 尝试切换硬件解码器为 auto-copy', + '当前:「${Pref.superResolutionType.title}」\n默认设置对番剧生效, 其他视频默认关闭\n超分辨率需要启用硬件解码, 若启用硬件解码后仍然不生效, 尝试切换硬件解码器为 auto-copy', onTap: (setState) async { SuperResolutionType? result = await showDialog( context: Get.context!, builder: (context) { return SelectDialog( title: '超分辨率', - value: SuperResolutionType.values[Pref.superResolutionType], + value: Pref.superResolutionType, values: SuperResolutionType.values .map((e) => (e, e.title)) .toList(), diff --git a/lib/pages/setting/models/video_settings.dart b/lib/pages/setting/models/video_settings.dart index c9c687950..f772ded1d 100644 --- a/lib/pages/setting/models/video_settings.dart +++ b/lib/pages/setting/models/video_settings.dart @@ -204,8 +204,7 @@ List get videoSettings => [ settingsType: SettingsType.normal, title: '直播默认画质', leading: const Icon(Icons.video_settings_outlined), - getSubtitle: () => - '当前画质:${LiveQualityExt.fromCode(Pref.liveQuality)!.description}', + getSubtitle: () => '当前画质:${LiveQuality.fromCode(Pref.liveQuality)?.desc}', onTap: (setState) async { int? result = await showDialog( context: Get.context!, @@ -213,9 +212,7 @@ List get videoSettings => [ return SelectDialog( title: '直播默认画质', value: Pref.liveQuality, - values: LiveQuality.values - .map((e) => (e.code, e.description)) - .toList(), + values: LiveQuality.values.map((e) => (e.code, e.desc)).toList(), ); }, ); @@ -230,17 +227,15 @@ List get videoSettings => [ title: '蜂窝网络直播默认画质', leading: const Icon(Icons.video_settings_outlined), getSubtitle: () => - '当前画质:${LiveQualityExt.fromCode(Pref.liveQualityCellular)!.description}', + '当前画质:${LiveQuality.fromCode(Pref.liveQualityCellular)?.desc}', onTap: (setState) async { int? result = await showDialog( context: Get.context!, builder: (context) { return SelectDialog( - title: '直播默认画质', + title: '蜂窝网络直播默认画质', value: Pref.liveQualityCellular, - values: LiveQuality.values - .map((e) => (e.code, e.description)) - .toList(), + values: LiveQuality.values.map((e) => (e.code, e.desc)).toList(), ); }, ); diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index 4e143fce1..b20867434 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -201,18 +201,18 @@ class HeaderControlState extends TripleState { const SizedBox(width: 10), Builder( builder: (context) => PopupMenuButton( - initialValue: SuperResolutionType - .values[widget.controller.superResolutionType], + initialValue: + widget.controller.superResolutionType.value, child: Padding( padding: const EdgeInsets.all(4), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( - SuperResolutionType - .values[widget - .controller - .superResolutionType] + widget + .controller + .superResolutionType + .value .title, strutStyle: const StrutStyle( leading: 0, @@ -235,7 +235,7 @@ class HeaderControlState extends TripleState { ), ), onSelected: (value) { - widget.controller.setShader(value.index); + widget.controller.setShader(value); if (context.mounted) { (context as Element).markNeedsBuild(); } diff --git a/lib/pages/webdav/view.dart b/lib/pages/webdav/view.dart index 8d13effd8..d1b62965e 100644 --- a/lib/pages/webdav/view.dart +++ b/lib/pages/webdav/view.dart @@ -121,15 +121,15 @@ class _WebDavSettingPageState extends State { floatingActionButton: FloatingActionButton( child: const Icon(Icons.save), onPressed: () async { + await GStorage.setting.putAll({ + SettingBoxKey.webdavUri: _uriCtr.text, + SettingBoxKey.webdavUsername: _usernameCtr.text, + SettingBoxKey.webdavPassword: _passwordCtr.text, + SettingBoxKey.webdavDirectory: _directoryCtr.text, + }); if (_uriCtr.text.isEmpty) { - SmartDialog.showToast('地址不能为空'); return; } - final setting = GStorage.setting; - await setting.put(SettingBoxKey.webdavUri, _uriCtr.text); - await setting.put(SettingBoxKey.webdavUsername, _usernameCtr.text); - await setting.put(SettingBoxKey.webdavPassword, _passwordCtr.text); - await setting.put(SettingBoxKey.webdavDirectory, _directoryCtr.text); try { final res = await WebDav().init(); if (res.first) { diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index f66ca0d89..eb9de4401 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -9,6 +9,7 @@ import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/models/common/account_type.dart'; import 'package:PiliPlus/models/common/audio_normalization.dart'; import 'package:PiliPlus/models/common/sponsor_block/skip_type.dart'; +import 'package:PiliPlus/models/common/super_resolution_type.dart'; import 'package:PiliPlus/models/common/video/video_type.dart'; import 'package:PiliPlus/models/user/danmaku_rule.dart'; import 'package:PiliPlus/models_new/video/video_shot/data.dart'; @@ -646,41 +647,43 @@ class PlPlayerController { } late final isAnim = _pgcType == 1 || _pgcType == 4; - late int superResolutionType = isAnim ? Pref.superResolutionType : 0; - Future setShader([int? type, NativePlayer? pp]) async { + late final Rx superResolutionType = + (isAnim ? Pref.superResolutionType : SuperResolutionType.disable).obs; + Future setShader([SuperResolutionType? type, NativePlayer? pp]) async { if (type == null) { - type ??= superResolutionType; + type = superResolutionType.value; } else { - superResolutionType = type; + superResolutionType.value = type; if (isAnim && !tempPlayerConf) { - GStorage.setting.put(SettingBoxKey.superResolutionType, type); + setting.put(SettingBoxKey.superResolutionType, type.index); } } pp ??= _videoPlayerController?.platform as NativePlayer; await pp.waitForPlayerInitialization; await pp.waitForVideoControllerInitializationIfAttached; - if (type == 1) { - await pp.command([ - 'change-list', - 'glsl-shaders', - 'set', - Utils.buildShadersAbsolutePath( - (await copyShadersToExternalDirectory())?.path ?? '', - Constants.mpvAnime4KShadersLite, - ), - ]); - } else if (type == 2) { - await pp.command([ - 'change-list', - 'glsl-shaders', - 'set', - Utils.buildShadersAbsolutePath( - (await copyShadersToExternalDirectory())?.path ?? '', - Constants.mpvAnime4KShaders, - ), - ]); - } else { - await pp.command(['change-list', 'glsl-shaders', 'clr', '']); + switch (type) { + case SuperResolutionType.disable: + return pp.command(['change-list', 'glsl-shaders', 'clr', '']); + case SuperResolutionType.efficiency: + return pp.command([ + 'change-list', + 'glsl-shaders', + 'set', + Utils.buildShadersAbsolutePath( + (await copyShadersToExternalDirectory())?.path ?? '', + Constants.mpvAnime4KShadersLite, + ), + ]); + case SuperResolutionType.quality: + return pp.command([ + 'change-list', + 'glsl-shaders', + 'set', + Utils.buildShadersAbsolutePath( + (await copyShadersToExternalDirectory())?.path ?? '', + Constants.mpvAnime4KShaders, + ), + ]); } } @@ -711,7 +714,7 @@ class PlPlayerController { var pp = player.platform as NativePlayer; if (_videoPlayerController == null) { if (isAnim) { - setShader(superResolutionType, pp); + setShader(superResolutionType.value, pp); } String audioNormalization = Pref.audioNormalization; audioNormalization = switch (audioNormalization) { @@ -1500,29 +1503,31 @@ class PlPlayerController { } void putDanmakuSettings() { - setting - ..put(SettingBoxKey.danmakuWeight, danmakuWeight) - ..put(SettingBoxKey.danmakuBlockType, blockTypes.toList()) - ..put(SettingBoxKey.danmakuShowArea, showArea) - ..put(SettingBoxKey.danmakuOpacity, danmakuOpacity) - ..put(SettingBoxKey.danmakuFontScale, danmakuFontScale) - ..put(SettingBoxKey.danmakuFontScaleFS, danmakuFontScaleFS) - ..put(SettingBoxKey.danmakuDuration, danmakuDuration) - ..put(SettingBoxKey.danmakuStaticDuration, danmakuStaticDuration) - ..put(SettingBoxKey.strokeWidth, strokeWidth) - ..put(SettingBoxKey.fontWeight, fontWeight) - ..put(SettingBoxKey.danmakuLineHeight, danmakuLineHeight); + setting.putAll({ + SettingBoxKey.danmakuWeight: danmakuWeight, + SettingBoxKey.danmakuBlockType: blockTypes.toList(), + SettingBoxKey.danmakuShowArea: showArea, + SettingBoxKey.danmakuOpacity: danmakuOpacity, + SettingBoxKey.danmakuFontScale: danmakuFontScale, + SettingBoxKey.danmakuFontScaleFS: danmakuFontScaleFS, + SettingBoxKey.danmakuDuration: danmakuDuration, + SettingBoxKey.danmakuStaticDuration: danmakuStaticDuration, + SettingBoxKey.strokeWidth: strokeWidth, + SettingBoxKey.fontWeight: fontWeight, + SettingBoxKey.danmakuLineHeight: danmakuLineHeight, + }); } void putSubtitleSettings() { - setting - ..put(SettingBoxKey.subtitleFontScale, subtitleFontScale) - ..put(SettingBoxKey.subtitleFontScaleFS, subtitleFontScaleFS) - ..put(SettingBoxKey.subtitlePaddingH, subtitlePaddingH) - ..put(SettingBoxKey.subtitlePaddingB, subtitlePaddingB) - ..put(SettingBoxKey.subtitleBgOpaticy, subtitleBgOpaticy) - ..put(SettingBoxKey.subtitleStrokeWidth, subtitleStrokeWidth) - ..put(SettingBoxKey.subtitleFontWeight, subtitleFontWeight); + setting.putAll({ + SettingBoxKey.subtitleFontScale: subtitleFontScale, + SettingBoxKey.subtitleFontScaleFS: subtitleFontScaleFS, + SettingBoxKey.subtitlePaddingH: subtitlePaddingH, + SettingBoxKey.subtitlePaddingB: subtitlePaddingB, + SettingBoxKey.subtitleBgOpaticy: subtitleBgOpaticy, + SettingBoxKey.subtitleStrokeWidth: subtitleStrokeWidth, + SettingBoxKey.subtitleFontWeight: subtitleFontWeight, + }); } Future dispose() async { diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 169d04770..35956e2a9 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -266,49 +266,43 @@ class _PLVideoPlayerState extends State Widget progressWidget( BottomControlType bottomControl, ) => switch (bottomControl) { - /// 上一集 - BottomControlType.pre => Container( - width: widgetWidth, - height: 30, - alignment: Alignment.center, - child: ComBtn( - icon: const Icon( - Icons.skip_previous, - semanticLabel: '上一集', - size: 22, - color: Colors.white, - ), - onTap: () { - if (!introController.prevPlay()) { - SmartDialog.showToast('已经是第一集了'); - } - }, - ), - ), - /// 播放暂停 BottomControlType.playOrPause => PlayOrPauseButton( plPlayerController: plPlayerController, ), - /// 下一集 - BottomControlType.next => Container( + /// 上一集 + BottomControlType.pre => ComBtn( width: widgetWidth, height: 30, - alignment: Alignment.center, - child: ComBtn( - icon: const Icon( - Icons.skip_next, - semanticLabel: '下一集', - size: 22, - color: Colors.white, - ), - onTap: () { - if (!introController.nextPlay()) { - SmartDialog.showToast('已经是最后一集了'); - } - }, + icon: const Icon( + Icons.skip_previous, + semanticLabel: '上一集', + size: 22, + color: Colors.white, ), + onTap: () { + if (!introController.prevPlay()) { + SmartDialog.showToast('已经是第一集了'); + } + }, + ), + + /// 下一集 + BottomControlType.next => ComBtn( + width: widgetWidth, + height: 30, + icon: const Icon( + Icons.skip_next, + semanticLabel: '下一集', + size: 22, + color: Colors.white, + ), + onTap: () { + if (!introController.nextPlay()) { + SmartDialog.showToast('已经是最后一集了'); + } + }, ), /// 时间进度 @@ -317,8 +311,8 @@ class _PLVideoPlayerState extends State crossAxisAlignment: CrossAxisAlignment.end, children: [ // 播放时间 - Obx(() { - return Text( + Obx( + () => Text( DurationUtil.formatDuration( plPlayerController.positionSeconds.value, ), @@ -328,8 +322,8 @@ class _PLVideoPlayerState extends State height: 1.4, fontFeatures: [FontFeature.tabularFigures()], ), - ); - }), + ), + ), Obx( () => Text( DurationUtil.formatDuration( @@ -350,72 +344,63 @@ class _PLVideoPlayerState extends State BottomControlType.dmChart => Obx( () => plPlayerController.dmTrend.isEmpty ? const SizedBox.shrink() - : Container( + : ComBtn( width: widgetWidth, height: 30, - alignment: Alignment.center, - child: ComBtn( - icon: plPlayerController.showDmTreandChart.value - ? const Icon( - Icons.show_chart, - size: 22, - color: Colors.white, - ) - : const Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - Icon( - Icons.show_chart, - size: 22, - color: Colors.white, - ), - Icon( - Icons.hide_source, - size: 22, - color: Colors.white, - ), - ], - ), - onTap: () => plPlayerController.showDmTreandChart.value = - !plPlayerController.showDmTreandChart.value, - ), + icon: plPlayerController.showDmTreandChart.value + ? const Icon( + Icons.show_chart, + size: 22, + color: Colors.white, + ) + : const Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + Icon( + Icons.show_chart, + size: 22, + color: Colors.white, + ), + Icon( + Icons.hide_source, + size: 22, + color: Colors.white, + ), + ], + ), + onTap: () => plPlayerController.showDmTreandChart.value = + !plPlayerController.showDmTreandChart.value, ), ), /// 超分辨率 - BottomControlType.superResolution => Container( - height: 30, - margin: const EdgeInsets.symmetric(horizontal: 10), - alignment: Alignment.center, - child: PopupMenuButton( - initialValue: SuperResolutionType - .values[plPlayerController.superResolutionType], + BottomControlType.superResolution => Obx( + () => PopupMenuButton( + initialValue: plPlayerController.superResolutionType.value, color: Colors.black.withValues(alpha: 0.8), - itemBuilder: (BuildContext context) { - return SuperResolutionType.values.map(( - SuperResolutionType type, - ) { - return PopupMenuItem( - height: 35, - padding: const EdgeInsets.only(left: 30), - value: type, - onTap: () => plPlayerController.setShader(type.index), - child: Text( - type.title, - style: const TextStyle( - color: Colors.white, - fontSize: 13, + itemBuilder: (context) { + return SuperResolutionType.values + .map( + (type) => PopupMenuItem( + height: 35, + padding: const EdgeInsets.only(left: 30), + value: type, + onTap: () => plPlayerController.setShader(type), + child: Text( + type.title, + style: const TextStyle(color: Colors.white, fontSize: 13), + ), ), - ), - ); - }).toList(); + ) + .toList(); }, - child: Text( - SuperResolutionType - .values[plPlayerController.superResolutionType] - .title, - style: const TextStyle(color: Colors.white, fontSize: 13), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + plPlayerController.superResolutionType.value.title, + style: const TextStyle(color: Colors.white, fontSize: 13), + ), ), ), ), @@ -424,110 +409,105 @@ class _PLVideoPlayerState extends State BottomControlType.viewPoints => Obx( () => plPlayerController.viewPointList.isEmpty ? const SizedBox.shrink() - : Container( + : ComBtn( width: widgetWidth, height: 30, - alignment: Alignment.center, - child: ComBtn( - icon: Transform.rotate( - angle: pi / 2, - child: const Icon( - MdiIcons.viewHeadline, - semanticLabel: '分段信息', - size: 22, - color: Colors.white, - ), + icon: Transform.rotate( + angle: pi / 2, + child: const Icon( + MdiIcons.viewHeadline, + semanticLabel: '分段信息', + size: 22, + color: Colors.white, ), - onTap: widget.showViewPoints, - onLongPress: () { - Feedback.forLongPress(context); - plPlayerController.showVP.value = - !plPlayerController.showVP.value; - }, ), + onTap: widget.showViewPoints, + onLongPress: () { + Feedback.forLongPress(context); + plPlayerController.showVP.value = + !plPlayerController.showVP.value; + }, ), ), /// 选集 - BottomControlType.episode => Container( + BottomControlType.episode => ComBtn( width: widgetWidth, height: 30, - alignment: Alignment.center, - child: ComBtn( - icon: const Icon( - Icons.list, - semanticLabel: '选集', - size: 22, - color: Colors.white, - ), - onTap: () { - // part -> playAll -> season(pgc) - if (isPlayAll && !isPart) { - widget.showEpisodes?.call(); - return; - } - int? index; - int currentCid = plPlayerController.cid; - String bvid = plPlayerController.bvid; - List episodes = []; - if (isSeason) { - final List sections = - videoDetail.ugcSeason!.sections!; - for (int i = 0; i < sections.length; i++) { - final List episodesList = sections[i].episodes!; - for (int j = 0; j < episodesList.length; j++) { - if (episodesList[j].cid == plPlayerController.cid) { - index = i; - episodes = episodesList; - break; - } + icon: const Icon( + Icons.list, + semanticLabel: '选集', + size: 22, + color: Colors.white, + ), + onTap: () { + // part -> playAll -> season(pgc) + if (isPlayAll && !isPart) { + widget.showEpisodes?.call(); + return; + } + int? index; + int currentCid = plPlayerController.cid; + String bvid = plPlayerController.bvid; + List episodes = []; + if (isSeason) { + final List sections = videoDetail.ugcSeason!.sections!; + for (int i = 0; i < sections.length; i++) { + final List episodesList = sections[i].episodes!; + for (int j = 0; j < episodesList.length; j++) { + if (episodesList[j].cid == plPlayerController.cid) { + index = i; + episodes = episodesList; + break; } } - } else if (isPart) { - episodes = videoDetail.pages!; - } else if (isPgc) { - episodes = - (introController as PgcIntroController).pgcItem.episodes!; } - widget.showEpisodes?.call( - index, - isSeason ? videoDetail.ugcSeason! : null, - isSeason ? null : episodes, - bvid, - IdUtils.bv2av(bvid), - isSeason && isPart - ? widget.videoDetailController?.seasonCid ?? currentCid - : currentCid, - ); - }, - ), + } else if (isPart) { + episodes = videoDetail.pages!; + } else if (isPgc) { + episodes = + (introController as PgcIntroController).pgcItem.episodes!; + } + widget.showEpisodes?.call( + index, + isSeason ? videoDetail.ugcSeason! : null, + isSeason ? null : episodes, + bvid, + IdUtils.bv2av(bvid), + isSeason && isPart + ? widget.videoDetailController?.seasonCid ?? currentCid + : currentCid, + ); + }, ), /// 画面比例 - BottomControlType.fit => Container( - height: 30, - margin: const EdgeInsets.symmetric(horizontal: 10), - alignment: Alignment.center, - child: PopupMenuButton( + BottomControlType.fit => Obx( + () => PopupMenuButton( initialValue: plPlayerController.videoFit.value, color: Colors.black.withValues(alpha: 0.8), - itemBuilder: (BuildContext context) { - return BoxFit.values.map((BoxFit boxFit) { - return PopupMenuItem( - height: 35, - padding: const EdgeInsets.only(left: 30), - value: boxFit, - onTap: () => plPlayerController.toggleVideoFit(boxFit), - child: Text( - boxFit.desc, - style: const TextStyle(color: Colors.white, fontSize: 13), - ), - ); - }).toList(); + itemBuilder: (context) { + return BoxFit.values + .map( + (BoxFit boxFit) => PopupMenuItem( + height: 35, + padding: const EdgeInsets.only(left: 30), + value: boxFit, + onTap: () => plPlayerController.toggleVideoFit(boxFit), + child: Text( + boxFit.desc, + style: const TextStyle(color: Colors.white, fontSize: 13), + ), + ), + ) + .toList(); }, - child: Text( - plPlayerController.videoFit.value.desc, - style: const TextStyle(color: Colors.white, fontSize: 13), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + plPlayerController.videoFit.value.desc, + style: const TextStyle(color: Colors.white, fontSize: 13), + ), ), ), ), @@ -536,83 +516,79 @@ class _PLVideoPlayerState extends State BottomControlType.subtitle => Obx( () => widget.videoDetailController?.subtitles.isEmpty == true ? const SizedBox.shrink() - : SizedBox( - width: widgetWidth, - height: 30, - child: PopupMenuButton( - initialValue: widget - .videoDetailController! - .vttSubtitlesIndex - .value - .clamp(0, widget.videoDetailController!.subtitles.length), - color: Colors.black.withValues(alpha: 0.8), - itemBuilder: (BuildContext context) { - return [ - PopupMenuItem( - value: 0, - onTap: () => - widget.videoDetailController!.setSubtitle(0), - child: const Text( - "关闭字幕", - style: TextStyle(color: Colors.white), - ), + : PopupMenuButton( + initialValue: widget + .videoDetailController! + .vttSubtitlesIndex + .value + .clamp(0, widget.videoDetailController!.subtitles.length), + color: Colors.black.withValues(alpha: 0.8), + itemBuilder: (context) { + return [ + PopupMenuItem( + value: 0, + onTap: () => widget.videoDetailController!.setSubtitle(0), + child: const Text( + "关闭字幕", + style: TextStyle(color: Colors.white), ), - ...widget.videoDetailController!.subtitles.indexed.map(( - e, - ) { - return PopupMenuItem( - value: e.$1 + 1, - onTap: () => widget.videoDetailController! - .setSubtitle(e.$1 + 1), - child: Text( - "${e.$2.lanDoc}", - style: const TextStyle(color: Colors.white), - ), - ); - }), - ]; - }, - child: Container( - width: 35, - height: 30, - alignment: Alignment.center, - child: Icon( - widget.videoDetailController!.vttSubtitlesIndex.value == 0 - ? Icons.closed_caption_off_outlined - : Icons.closed_caption_off_rounded, - size: 22, - color: Colors.white, - semanticLabel: '字幕', ), - ), + ...widget.videoDetailController!.subtitles.indexed.map((e) { + return PopupMenuItem( + value: e.$1 + 1, + onTap: () => + widget.videoDetailController!.setSubtitle(e.$1 + 1), + child: Text( + "${e.$2.lanDoc}", + style: const TextStyle(color: Colors.white), + ), + ); + }), + ]; + }, + child: SizedBox( + width: widgetWidth, + height: 30, + child: + widget.videoDetailController!.vttSubtitlesIndex.value == 0 + ? const Icon( + Icons.closed_caption_off_outlined, + size: 22, + color: Colors.white, + ) + : const Icon( + Icons.closed_caption_off_rounded, + size: 22, + color: Colors.white, + ), ), ), ), /// 播放速度 BottomControlType.speed => Obx( - () => Container( - height: 30, - margin: const EdgeInsets.symmetric(horizontal: 10), - alignment: Alignment.center, - child: PopupMenuButton( - initialValue: plPlayerController.playbackSpeed, - color: Colors.black.withValues(alpha: 0.8), - itemBuilder: (BuildContext context) { - return plPlayerController.speedList.map((double speed) { - return PopupMenuItem( - height: 35, - padding: const EdgeInsets.only(left: 30), - value: speed, - onTap: () => plPlayerController.setPlaybackSpeed(speed), - child: Text( - "${speed}X", - style: const TextStyle(color: Colors.white, fontSize: 13), - semanticsLabel: "$speed倍速", + () => PopupMenuButton( + initialValue: plPlayerController.playbackSpeed, + color: Colors.black.withValues(alpha: 0.8), + itemBuilder: (context) { + return plPlayerController.speedList + .map( + (double speed) => PopupMenuItem( + height: 35, + padding: const EdgeInsets.only(left: 30), + value: speed, + onTap: () => plPlayerController.setPlaybackSpeed(speed), + child: Text( + "${speed}X", + style: const TextStyle(color: Colors.white, fontSize: 13), + semanticsLabel: "$speed倍速", + ), ), - ); - }).toList(); - }, + ) + .toList(); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), child: Text( "${plPlayerController.playbackSpeed}X", style: const TextStyle(color: Colors.white, fontSize: 13), @@ -623,20 +599,25 @@ class _PLVideoPlayerState extends State ), /// 全屏 - BottomControlType.fullscreen => SizedBox( - width: widgetWidth, - height: 30, - child: Obx( - () => ComBtn( - icon: Icon( - isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, - semanticLabel: isFullScreen ? '退出全屏' : '全屏', - size: 24, - color: Colors.white, - ), - onTap: () => - plPlayerController.triggerFullScreen(status: !isFullScreen), - ), + BottomControlType.fullscreen => Obx( + () => ComBtn( + width: widgetWidth, + height: 30, + icon: isFullScreen + ? const Icon( + Icons.fullscreen_exit, + semanticLabel: '退出全屏', + size: 24, + color: Colors.white, + ) + : const Icon( + Icons.fullscreen, + semanticLabel: '全屏', + size: 24, + color: Colors.white, + ), + onTap: () => + plPlayerController.triggerFullScreen(status: !isFullScreen), ), ), }; diff --git a/lib/plugin/pl_player/widgets/common_btn.dart b/lib/plugin/pl_player/widgets/common_btn.dart index 484367bfc..f40bf6a3a 100644 --- a/lib/plugin/pl_player/widgets/common_btn.dart +++ b/lib/plugin/pl_player/widgets/common_btn.dart @@ -4,19 +4,23 @@ class ComBtn extends StatelessWidget { final Widget icon; final VoidCallback? onTap; final VoidCallback? onLongPress; + final double width; + final double height; const ComBtn({ + super.key, required this.icon, this.onTap, this.onLongPress, - super.key, + this.width = 34, + this.height = 34, }); @override Widget build(BuildContext context) { return SizedBox( - width: 34, - height: 34, + width: width, + height: height, child: GestureDetector( onTap: onTap, onLongPress: onLongPress, diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index 199c7bec1..bd41817fd 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -9,6 +9,7 @@ import 'package:PiliPlus/models/common/member/tab_type.dart'; import 'package:PiliPlus/models/common/msg/msg_unread_type.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/super_resolution_type.dart'; import 'package:PiliPlus/models/common/theme/theme_type.dart'; import 'package:PiliPlus/models/common/video/audio_quality.dart'; import 'package:PiliPlus/models/common/video/cdn_type.dart'; @@ -22,6 +23,7 @@ import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart'; import 'package:PiliPlus/plugin/pl_player/models/fullscreen_mode.dart'; import 'package:PiliPlus/plugin/pl_player/models/play_repeat.dart'; import 'package:PiliPlus/utils/context_ext.dart'; +import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/global_data.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; @@ -406,8 +408,15 @@ class Pref { static String get audioNormalization => _setting.get(SettingBoxKey.audioNormalization, defaultValue: '0'); - static int get superResolutionType => - _setting.get(SettingBoxKey.superResolutionType, defaultValue: 0); + static SuperResolutionType get superResolutionType { + SuperResolutionType? superResolutionType; + final index = _setting.get(SettingBoxKey.superResolutionType); + if (index != null) { + superResolutionType = SuperResolutionType.values.getOrNull(index); + } + superResolutionType ??= SuperResolutionType.disable; + return superResolutionType; + } static bool get preInitPlayer => _setting.get(SettingBoxKey.preInitPlayer, defaultValue: false);