diff --git a/change_log/1.0.16.0102.md b/change_log/1.0.16.0102.md new file mode 100644 index 000000000..b0a85a0f2 --- /dev/null +++ b/change_log/1.0.16.0102.md @@ -0,0 +1,15 @@ +## 1.0.16 + + +### 功能 ++ toast 背景支持透明度调节 + +### 修复 ++ web端推荐未展示【已关注】 ++ up主动态页异常 ++ 未打开自动播放时,视频详情页异常 ++ 视频暂停状态取消自动ip + + +更多更新日志可在Github上查看 +问题反馈、功能建议请查看「关于」页面。 diff --git a/lib/common/widgets/custom_toast.dart b/lib/common/widgets/custom_toast.dart index 9cd3461dc..64cf0da27 100644 --- a/lib/common/widgets/custom_toast.dart +++ b/lib/common/widgets/custom_toast.dart @@ -1,4 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:hive/hive.dart'; +import 'package:pilipala/utils/storage.dart'; + +Box setting = GStrorage.setting; class CustomToast extends StatelessWidget { final String msg; @@ -6,12 +10,17 @@ class CustomToast extends StatelessWidget { @override Widget build(BuildContext context) { + double toastOpacity = + setting.get(SettingBoxKey.defaultToastOp, defaultValue: 1.0); return Container( margin: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom + 30), padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 10), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primaryContainer, + color: Theme.of(context) + .colorScheme + .primaryContainer + .withOpacity(toastOpacity), borderRadius: BorderRadius.circular(20), ), child: Text( diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index fa15a75cc..5c827f848 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -266,6 +266,14 @@ class VideoContent extends StatelessWidget { fs: 9, ) ], + if (videoItem.isFollowed == 1) ...[ + const PBadge( + text: '已关注', + stack: 'normal', + size: 'small', + type: 'color', + ) + ], Expanded( flex: crossAxisCount == 1 ? 0 : 1, child: Text( diff --git a/lib/pages/dynamics/widgets/author_panel.dart b/lib/pages/dynamics/widgets/author_panel.dart index c21516e50..5276d390a 100644 --- a/lib/pages/dynamics/widgets/author_panel.dart +++ b/lib/pages/dynamics/widgets/author_panel.dart @@ -57,14 +57,6 @@ class AuthorPanel extends StatelessWidget { fontSize: Theme.of(context).textTheme.titleSmall!.fontSize, ), ), - if (item.modules.moduleTag != null) ...[ - const SizedBox(width: 6), - PBadge( - bottom: 10, - right: 10, - text: item.modules.moduleTag['text'], - ) - ] ], ), DefaultTextStyle.merge( diff --git a/lib/pages/setting/controller.dart b/lib/pages/setting/controller.dart index 0e1505a5a..afd141561 100644 --- a/lib/pages/setting/controller.dart +++ b/lib/pages/setting/controller.dart @@ -15,6 +15,7 @@ class SettingController extends GetxController { RxBool userLogin = false.obs; RxBool feedBackEnable = false.obs; + RxDouble toastOpacity = (1.0).obs; RxInt picQuality = 10.obs; Rx themeType = ThemeType.system.obs; var userInfo; @@ -26,6 +27,8 @@ class SettingController extends GetxController { userLogin.value = userInfo != null; feedBackEnable.value = setting.get(SettingBoxKey.feedBackEnable, defaultValue: false); + toastOpacity.value = + setting.get(SettingBoxKey.defaultToastOp, defaultValue: 1.0); picQuality.value = setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10); themeType.value = ThemeType.values[setting.get(SettingBoxKey.themeMode, diff --git a/lib/pages/setting/play_setting.dart b/lib/pages/setting/play_setting.dart index 4dd76a7a3..bfd5db5fc 100644 --- a/lib/pages/setting/play_setting.dart +++ b/lib/pages/setting/play_setting.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; @@ -95,12 +97,13 @@ class _PlaySettingState extends State { setKey: SettingBoxKey.enableBackgroundPlay, defaultVal: false, ), - const SetSwitchItem( - title: '自动PiP播放', - subTitle: '进入后台时画中画播放', - setKey: SettingBoxKey.autoPiP, - defaultVal: false, - ), + if (Platform.isAndroid) + const SetSwitchItem( + title: '自动PiP播放', + subTitle: '进入后台时画中画播放', + setKey: SettingBoxKey.autoPiP, + defaultVal: false, + ), const SetSwitchItem( title: '自动全屏', subTitle: '视频开始播放时进入全屏', @@ -154,9 +157,12 @@ class _PlaySettingState extends State { int? result = await showDialog( context: context, builder: (context) { - return SelectDialog(title: '默认画质', value: defaultVideoQa, values: VideoQuality.values.reversed.map((e) { - return {'title': e.description, 'value': e.code}; - }).toList()); + return SelectDialog( + title: '默认画质', + value: defaultVideoQa, + values: VideoQuality.values.reversed.map((e) { + return {'title': e.description, 'value': e.code}; + }).toList()); }, ); if (result != null) { @@ -177,9 +183,12 @@ class _PlaySettingState extends State { int? result = await showDialog( context: context, builder: (context) { - return SelectDialog(title: '默认音质', value: defaultAudioQa, values: AudioQuality.values.reversed.map((e) { - return {'title': e.description, 'value': e.code}; - }).toList()); + return SelectDialog( + title: '默认音质', + value: defaultAudioQa, + values: AudioQuality.values.reversed.map((e) { + return {'title': e.description, 'value': e.code}; + }).toList()); }, ); if (result != null) { @@ -200,9 +209,12 @@ class _PlaySettingState extends State { String? result = await showDialog( context: context, builder: (context) { - return SelectDialog(title: '默认解码格式', value: defaultDecode, values: VideoDecodeFormats.values.map((e) { - return {'title': e.description, 'value': e.code}; - }).toList()); + return SelectDialog( + title: '默认解码格式', + value: defaultDecode, + values: VideoDecodeFormats.values.map((e) { + return {'title': e.description, 'value': e.code}; + }).toList()); }, ); if (result != null) { @@ -223,9 +235,12 @@ class _PlaySettingState extends State { int? result = await showDialog( context: context, builder: (context) { - return SelectDialog(title: '默认全屏方式', value: defaultFullScreenMode, values: FullScreenMode.values.map((e) { - return {'title': e.description, 'value': e.code}; - }).toList()); + return SelectDialog( + title: '默认全屏方式', + value: defaultFullScreenMode, + values: FullScreenMode.values.map((e) { + return {'title': e.description, 'value': e.code}; + }).toList()); }, ); if (result != null) { @@ -246,9 +261,12 @@ class _PlaySettingState extends State { int? result = await showDialog( context: context, builder: (context) { - return SelectDialog(title: '底部进度条展示', value: defaultBtmProgressBehavior, values: BtmProgresBehavior.values.map((e) { - return {'title': e.description, 'value': e.code}; - }).toList()); + return SelectDialog( + title: '底部进度条展示', + value: defaultBtmProgressBehavior, + values: BtmProgresBehavior.values.map((e) { + return {'title': e.description, 'value': e.code}; + }).toList()); }, ); if (result != null) { diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index ed35193e3..a4e39aa09 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -1,11 +1,13 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/models/common/theme_type.dart'; import 'package:pilipala/pages/setting/pages/color_select.dart'; import 'package:pilipala/pages/setting/widgets/select_dialog.dart'; +import 'package:pilipala/pages/setting/widgets/slide_dialog.dart'; import 'package:pilipala/utils/storage.dart'; import 'controller.dart'; @@ -25,6 +27,7 @@ class _StyleSettingState extends State { Box setting = GStrorage.setting; late int picQuality; + late double toastOpacity; late ThemeType _tempThemeValue; late dynamic defaultCustomRows; @@ -32,6 +35,7 @@ class _StyleSettingState extends State { void initState() { super.initState(); picQuality = setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10); + toastOpacity = setting.get(SettingBoxKey.defaultToastOp, defaultValue: 1.0); _tempThemeValue = settingController.themeType.value; defaultCustomRows = setting.get(SettingBoxKey.customRows, defaultValue: 2); } @@ -187,6 +191,30 @@ class _StyleSettingState extends State { ), ), ), + ListTile( + dense: false, + onTap: () async { + double? result = await showDialog( + context: context, + builder: (context) { + return SlideDialog( + title: 'Toast不透明度', + value: settingController.toastOpacity.value, + min: 0.0, + max: 1.0, + divisions: 10, + ); + }, + ); + if (result != null) { + settingController.toastOpacity.value = result; + SmartDialog.showToast('设置成功'); + setting.put(SettingBoxKey.defaultToastOp, result); + } + }, + title: Text('Toast不透明度', style: titleStyle), + subtitle: Text('自定义Toast不透明度', style: subTitleStyle), + ), ListTile( dense: false, onTap: () async { diff --git a/lib/pages/setting/widgets/slide_dialog.dart b/lib/pages/setting/widgets/slide_dialog.dart new file mode 100644 index 000000000..7fa6eeab8 --- /dev/null +++ b/lib/pages/setting/widgets/slide_dialog.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; +// import 'package:pilipala/models/common/theme_type.dart'; + +class SlideDialog extends StatefulWidget { + final T value; + final String title; + final double min; + final double max; + final int? divisions; + final String? suffix; + + const SlideDialog({ + super.key, + required this.value, + required this.title, + required this.min, + required this.max, + this.divisions, + this.suffix, + }); + + @override + _SlideDialogState createState() => _SlideDialogState(); +} + +class _SlideDialogState extends State> { + late double _tempValue; + + @override + void initState() { + super.initState(); + _tempValue = widget.value.toDouble(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(widget.title), + contentPadding: + const EdgeInsets.only(top: 20, left: 8, right: 8, bottom: 8), + content: SizedBox( + height: 40, + child: Slider( + value: _tempValue, + min: widget.min, + max: widget.max, + divisions: widget.divisions ?? 10, + label: '$_tempValue${widget.suffix ?? ''}', + onChanged: (double value) { + setState(() { + _tempValue = value; + }); + }, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + '取消', + style: TextStyle(color: Theme.of(context).colorScheme.outline), + ), + ), + TextButton( + onPressed: () => Navigator.pop(context, _tempValue as T), + child: const Text('确定'), + ) + ], + ); + } +} diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 29566e7be..18dd4ccf7 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -244,7 +244,10 @@ class _VideoDetailPageState extends State void _handleTransition(String name) { switch (name) { case 'inactive': - autoEnterPip(); + if (plPlayerController != null && + playerStatus == PlayerStatus.playing) { + autoEnterPip(); + } break; } } @@ -302,7 +305,10 @@ class _VideoDetailPageState extends State return [ Obx(() => SliverAppBar( automaticallyImplyLeading: false, - pinned: false, + // 假装使用一个非空变量,避免Obx检测不到而罢工 + pinned: videoDetailController + .autoPlay.value ^ false ^ videoDetailController + .autoPlay.value, elevation: 0, scrolledUnderElevation: 0, forceElevated: innerBoxIsScrolled, diff --git a/lib/plugin/pl_player/models/bottom_progress_behavior.dart b/lib/plugin/pl_player/models/bottom_progress_behavior.dart index c632669c2..c7f1453dd 100644 --- a/lib/plugin/pl_player/models/bottom_progress_behavior.dart +++ b/lib/plugin/pl_player/models/bottom_progress_behavior.dart @@ -3,14 +3,15 @@ enum BtmProgresBehavior { alwaysShow, alwaysHide, onlyShowFullScreen, + onlyHideFullScreen, } extension BtmProgresBehaviorDesc on BtmProgresBehavior { - String get description => ['始终展示', '始终隐藏', '仅全屏时展示'][index]; + String get description => ['始终展示', '始终隐藏', '仅全屏时展示', '仅全屏时隐藏'][index]; } extension BtmProgresBehaviorCode on BtmProgresBehavior { - static final List _codeList = [0, 1, 2]; + static final List _codeList = [0, 1, 2, 3]; int get code => _codeList[index]; static BtmProgresBehavior? fromCode(int code) { diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 89b85607b..781fa6140 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -610,6 +610,10 @@ class _PLVideoPlayerState extends State BtmProgresBehavior.onlyShowFullScreen.code && !_.isFullScreen.value) { return Container(); + } else if (defaultBtmProgressBehavior == + BtmProgresBehavior.onlyHideFullScreen.code && + _.isFullScreen.value) { + return Container(); } if (_.videoType.value == 'live') { diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 7aec10d5d..e3a508819 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -98,6 +98,7 @@ class SettingBoxKey { fullScreenMode = 'fullScreenMode', defaultDecode = 'defaultDecode', danmakuEnable = 'danmakuEnable', + defaultToastOp = 'defaultToastOp', defaultPicQa = 'defaultPicQa', enableHA = 'enableHA', enableOnlineTotal = 'enableOnlineTotal', diff --git a/pubspec.yaml b/pubspec.yaml index 0b1a3cf98..ab64473c9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.15+1015 +version: 1.0.16+1016 environment: sdk: ">=2.19.6 <3.0.0"