From 018424d5bdba6344450dd62de157d696c2f4fe9c Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Sun, 1 Dec 2024 10:22:31 +0800 Subject: [PATCH] feat: custom subtitle fontscale Closes #28 Signed-off-by: bggRGjQaUbCoE --- .../video/detail/widgets/header_control.dart | 81 ++++++++++++++++++- lib/plugin/pl_player/controller.dart | 6 ++ lib/plugin/pl_player/view.dart | 48 ++++++++--- lib/utils/storage.dart | 8 ++ 4 files changed, 130 insertions(+), 13 deletions(-) diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index dfcd482d..c10ac9ff 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -894,6 +894,8 @@ class _HeaderControlState extends State { double fontSizeVal = widget.controller!.fontSizeVal; // 全屏字体大小 double fontSizeFSVal = widget.controller!.fontSizeFSVal; + double subtitleFontScale = widget.controller!.subtitleFontScale.value; + double subtitleFontScaleFS = widget.controller!.subtitleFontScaleFS.value; // 弹幕速度 double danmakuDurationVal = widget.controller!.danmakuDurationVal; // 弹幕描边 @@ -912,13 +914,18 @@ class _HeaderControlState extends State { builder: (BuildContext context, StateSetter setState) { return Container( width: double.infinity, - height: 580, + height: 600, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), - margin: const EdgeInsets.all(12), + margin: EdgeInsets.only( + left: 12, + top: 12, + right: 12, + bottom: widget.controller?.isFullScreen.value == true ? 70 : 12, + ), padding: const EdgeInsets.only(left: 14, right: 14), child: SingleChildScrollView( child: Column( @@ -1258,6 +1265,76 @@ class _HeaderControlState extends State { ), ), ), + Text( + '字幕字体大小 ${(subtitleFontScale * 100).toStringAsFixed(1)}%'), + Padding( + padding: const EdgeInsets.only( + top: 0, + bottom: 6, + left: 10, + right: 10, + ), + child: SliderTheme( + data: SliderThemeData( + trackShape: MSliderTrackShape(), + thumbColor: Theme.of(context).colorScheme.primary, + activeTrackColor: Theme.of(context).colorScheme.primary, + trackHeight: 10, + thumbShape: const RoundSliderThumbShape( + enabledThumbRadius: 6.0), + ), + child: Slider( + min: 0.5, + max: 2.5, + value: subtitleFontScale, + divisions: 20, + label: + '${(subtitleFontScale * 100).toStringAsFixed(1)}%', + onChanged: (double val) { + subtitleFontScale = val; + widget.controller!.subtitleFontScale.value = + subtitleFontScale; + widget.controller?.putDanmakuSettings(); + setState(() {}); + }, + ), + ), + ), + Text( + '全屏字幕字体大小 ${(subtitleFontScaleFS * 100).toStringAsFixed(1)}%'), + Padding( + padding: const EdgeInsets.only( + top: 0, + bottom: 6, + left: 10, + right: 10, + ), + child: SliderTheme( + data: SliderThemeData( + trackShape: MSliderTrackShape(), + thumbColor: Theme.of(context).colorScheme.primary, + activeTrackColor: Theme.of(context).colorScheme.primary, + trackHeight: 10, + thumbShape: const RoundSliderThumbShape( + enabledThumbRadius: 6.0), + ), + child: Slider( + min: 0.5, + max: 2.5, + value: subtitleFontScaleFS, + divisions: 20, + label: + '${(subtitleFontScaleFS * 100).toStringAsFixed(1)}%', + onChanged: (double val) { + subtitleFontScaleFS = val; + widget.controller!.subtitleFontScaleFS.value = + subtitleFontScaleFS; + widget.controller?.putDanmakuSettings(); + setState(() {}); + }, + ), + ), + ), Text('弹幕时长 $danmakuDurationVal 秒'), Padding( padding: const EdgeInsets.only( diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 7c4b91af..a0fcad75 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -258,6 +258,8 @@ class PlPlayerController { double? defaultDuration; late bool enableAutoLongPressSpeed = false; late bool enableLongShowControl; + RxDouble subtitleFontScale = (1.0).obs; + RxDouble subtitleFontScaleFS = (1.5).obs; // 播放顺序相关 PlayRepeat playRepeat = PlayRepeat.pause; @@ -351,6 +353,8 @@ class PlPlayerController { setting.get(SettingBoxKey.danmakuFontScale, defaultValue: 1.0); // 全屏字体大小 fontSizeFSVal = GStorage.danmakuFontScaleFS; + subtitleFontScale.value = GStorage.subtitleFontScale; + subtitleFontScaleFS.value = GStorage.subtitleFontScaleFS; // 弹幕时间 danmakuDurationVal = setting.get(SettingBoxKey.danmakuDuration, defaultValue: 7.29); @@ -1296,6 +1300,8 @@ class PlPlayerController { setting.put(SettingBoxKey.danmakuOpacity, opacityVal); setting.put(SettingBoxKey.danmakuFontScale, fontSizeVal); setting.put(SettingBoxKey.danmakuFontScaleFS, fontSizeFSVal); + setting.put(SettingBoxKey.subtitleFontScale, subtitleFontScale.value); + setting.put(SettingBoxKey.subtitleFontScaleFS, subtitleFontScaleFS.value); setting.put(SettingBoxKey.danmakuDuration, danmakuDurationVal); setting.put(SettingBoxKey.strokeWidth, strokeWidth); setting.put(SettingBoxKey.fontWeight, fontWeight); diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 5ca0c827..fb06ba4a 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -75,6 +75,8 @@ class _PLVideoPlayerState extends State late BangumiIntroController? bangumiIntroController; final GlobalKey _playerKey = GlobalKey(); + final GlobalKey _key = GlobalKey(); + final RxBool _mountSeekBackwardButton = false.obs; final RxBool _mountSeekForwardButton = false.obs; final RxBool _hideSeekBackwardButton = false.obs; @@ -529,19 +531,43 @@ class _PLVideoPlayerState extends State return list; } + PlPlayerController get plPlayerController => widget.controller; + + TextStyle get subTitleStyle => TextStyle( + height: 1.5, + fontSize: 16 * + (plPlayerController.isFullScreen.value + ? plPlayerController.subtitleFontScaleFS.value + : plPlayerController.subtitleFontScale.value), + letterSpacing: 0.1, + wordSpacing: 0.1, + color: Color(0xffffffff), + fontWeight: FontWeight.normal, + backgroundColor: Color(0xaa000000), + ); + + void _updateSubtitle(double value) { + _key.currentState?.update( + subtitleViewConfiguration: SubtitleViewConfiguration( + style: subTitleStyle.copyWith(fontSize: 16 * value), + padding: const EdgeInsets.all(24.0), + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), + ), + ); + } + @override Widget build(BuildContext context) { - final PlPlayerController plPlayerController = widget.controller; + if (plPlayerController.isFullScreen.value) { + plPlayerController.subtitleFontScaleFS.listen((value) { + _updateSubtitle(value); + }); + } else { + plPlayerController.subtitleFontScale.listen((value) { + _updateSubtitle(value); + }); + } final Color colorTheme = Theme.of(context).colorScheme.primary; - const TextStyle subTitleStyle = TextStyle( - height: 1.5, - fontSize: 20.0, - letterSpacing: 0.1, - wordSpacing: 0.1, - color: Color(0xffffffff), - fontWeight: FontWeight.normal, - backgroundColor: Color(0xaa000000), - ); const TextStyle textStyle = TextStyle( color: Colors.white, fontSize: 12, @@ -684,7 +710,7 @@ class _PLVideoPlayerState extends State _gestureType = null; }, child: Video( - key: ValueKey('${plPlayerController.videoFit.value}'), + key: _key, controller: videoController, controls: NoVideoControls, pauseUponEnteringBackgroundMode: diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index c9117de9..9d8b16be 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -99,6 +99,12 @@ class GStorage { static double get danmakuFontScaleFS => setting.get(SettingBoxKey.danmakuFontScaleFS, defaultValue: 1.2); + static double get subtitleFontScale => + setting.get(SettingBoxKey.subtitleFontScale, defaultValue: 1.0); + + static double get subtitleFontScaleFS => + setting.get(SettingBoxKey.subtitleFontScaleFS, defaultValue: 1.5); + static bool get grpcReply => setting.get(SettingBoxKey.grpcReply, defaultValue: true); @@ -302,6 +308,8 @@ class SettingBoxKey { strokeWidth = 'strokeWidth', fontWeight = 'fontWeight', memberTab = 'memberTab', + subtitleFontScale = 'subtitleFontScale', + subtitleFontScaleFS = 'subtitleFontScaleFS', // 代理host port systemProxyHost = 'systemProxyHost',