diff --git a/lib/models/common/super_chat_type.dart b/lib/models/common/super_chat_type.dart new file mode 100644 index 000000000..53b930a0b --- /dev/null +++ b/lib/models/common/super_chat_type.dart @@ -0,0 +1,9 @@ +enum SuperChatType { + valid('有效时间内显示'), + persist('持久显示'), + disable('不显示'), + ; + + final String title; + const SuperChatType(this.title); +} diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index a6bc7295c..802a821ab 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/flutter/text_field/controller.dart'; import 'package:PiliPlus/http/constants.dart'; import 'package:PiliPlus/http/live.dart'; import 'package:PiliPlus/http/video.dart'; +import 'package:PiliPlus/models/common/super_chat_type.dart'; import 'package:PiliPlus/models/common/video/live_quality.dart'; import 'package:PiliPlus/models_new/live/live_danmaku/danmaku_msg.dart'; import 'package:PiliPlus/models_new/live/live_danmaku/live_emote.dart'; @@ -113,7 +114,8 @@ class LiveRoomController extends GetxController { bool? isPlaying; late bool isFullScreen = false; - final showSuperChat = Pref.showSuperChat; + final superChatType = Pref.superChatType; + late final showSuperChat = superChatType != SuperChatType.disable; final headerKey = GlobalKey(); diff --git a/lib/pages/live_room/superchat/superchat_card.dart b/lib/pages/live_room/superchat/superchat_card.dart index ee975f722..a6b6d34ca 100644 --- a/lib/pages/live_room/superchat/superchat_card.dart +++ b/lib/pages/live_room/superchat/superchat_card.dart @@ -13,10 +13,12 @@ class SuperChatCard extends StatefulWidget { super.key, required this.item, required this.onRemove, + this.persistentSC = false, }); final SuperChatItem item; final VoidCallback onRemove; + final bool persistentSC; @override State createState() => _SuperChatCardState(); @@ -29,17 +31,19 @@ class _SuperChatCardState extends State { @override void initState() { super.initState(); - if (widget.item.expired) { - _remove(); - return; - } - final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; - final offset = widget.item.endTime - now; - if (offset > 0) { - _remains = offset.obs; - _timer = Timer.periodic(const Duration(seconds: 1), _callback); - } else { - _remove(); + if (!widget.persistentSC) { + if (widget.item.expired) { + _remove(); + return; + } + final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final offset = widget.item.endTime - now; + if (offset > 0) { + _remains = offset.obs; + _timer = Timer.periodic(const Duration(seconds: 1), _callback); + } else { + _remove(); + } } } diff --git a/lib/pages/live_room/superchat/superchat_panel.dart b/lib/pages/live_room/superchat/superchat_panel.dart index d996cc684..ad6f33c9f 100644 --- a/lib/pages/live_room/superchat/superchat_panel.dart +++ b/lib/pages/live_room/superchat/superchat_panel.dart @@ -1,3 +1,4 @@ +import 'package:PiliPlus/models/common/super_chat_type.dart'; import 'package:PiliPlus/pages/live_room/controller.dart'; import 'package:PiliPlus/pages/live_room/superchat/superchat_card.dart'; import 'package:PiliPlus/pages/search/controller.dart'; @@ -21,6 +22,9 @@ class _SuperChatPanelState extends DebounceStreamState @override Duration get duration => const Duration(milliseconds: 300); + late final persistentSC = + widget.controller.superChatType == SuperChatType.persist; + @override Widget build(BuildContext context) { super.build(context); @@ -42,6 +46,7 @@ class _SuperChatPanelState extends DebounceStreamState key: ValueKey(item.id), item: item, onRemove: () => ctr?.add(true), + persistentSC: persistentSC, ); }, separatorBuilder: (_, _) => const SizedBox(height: 12), diff --git a/lib/pages/setting/models/extra_settings.dart b/lib/pages/setting/models/extra_settings.dart index 65832beda..d5cc8b865 100644 --- a/lib/pages/setting/models/extra_settings.dart +++ b/lib/pages/setting/models/extra_settings.dart @@ -874,7 +874,6 @@ List get extraSettings => [ onTap: (context, setState) async { final result = await showDialog( context: context, - builder: (context) { return SlideDialog( title: '连接重试次数', @@ -900,7 +899,6 @@ List get extraSettings => [ onTap: (context, setState) async { final result = await showDialog( context: context, - builder: (context) { return SlideDialog( title: '连接重试间隔', @@ -928,7 +926,6 @@ List get extraSettings => [ onTap: (context, setState) async { final result = await showDialog( context: context, - builder: (context) { return SelectDialog( title: '评论展示', @@ -953,7 +950,6 @@ List get extraSettings => [ onTap: (context, setState) async { final result = await showDialog( context: context, - builder: (context) { return SelectDialog( title: '动态展示', @@ -978,7 +974,6 @@ List get extraSettings => [ onTap: (context, setState) async { final result = await showDialog( context: context, - builder: (context) { return SelectDialog( title: '用户页默认展示TAB', @@ -1194,7 +1189,6 @@ Future audioNormalization( String param = ''; await showDialog( context: context, - builder: (context) { return AlertDialog( title: const Text('自定义参数'), diff --git a/lib/pages/setting/models/play_settings.dart b/lib/pages/setting/models/play_settings.dart index 52aa6da6a..57d427acc 100644 --- a/lib/pages/setting/models/play_settings.dart +++ b/lib/pages/setting/models/play_settings.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:PiliPlus/common/widgets/custom_icon.dart'; +import 'package:PiliPlus/models/common/super_chat_type.dart'; import 'package:PiliPlus/models/common/video/subtitle_pref_type.dart'; import 'package:PiliPlus/pages/main/controller.dart'; import 'package:PiliPlus/pages/setting/models/model.dart'; @@ -157,11 +158,26 @@ List get playSettings => [ setKey: SettingBoxKey.keyboardControl, defaultVal: true, ), - const SwitchModel( - title: '显示 SuperChat (醒目留言)', - leading: Icon(Icons.live_tv), - setKey: SettingBoxKey.showSuperChat, - defaultVal: true, + NormalModel( + title: 'SuperChat (醒目留言) 显示类型', + leading: const Icon(Icons.live_tv), + getSubtitle: () => '当前:「${Pref.superChatType.title}」', + onTap: (context, setState) async { + final result = await showDialog( + context: context, + builder: (context) { + return SelectDialog( + title: 'SuperChat (醒目留言) 显示类型', + value: Pref.superChatType, + values: SuperChatType.values.map((e) => (e, e.title)).toList(), + ); + }, + ); + if (result != null) { + await GStorage.setting.put(SettingBoxKey.superChatType, result.index); + setState(); + } + }, ), const SwitchModel( title: '竖屏扩大展示', diff --git a/lib/utils/storage_key.dart b/lib/utils/storage_key.dart index 4f5490449..030e34745 100644 --- a/lib/utils/storage_key.dart +++ b/lib/utils/storage_key.dart @@ -21,7 +21,7 @@ abstract class SettingBoxKey { enableAutoEnter = 'enableAutoEnter', enableAutoExit = 'enableAutoExit', enableOnlineTotal = 'enableOnlineTotal', - showSuperChat = 'showSuperChat', + superChatType = 'superChatType', keyboardControl = 'keyboardControl', pauseOnMinimize = 'pauseOnMinimize', pgcSkipType = 'pgcSkipType', diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index 56a4a0bc9..e2ebb0957 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -10,6 +10,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_chat_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'; @@ -823,8 +824,11 @@ abstract class Pref { static bool get showMemberShop => _setting.get(SettingBoxKey.showMemberShop, defaultValue: false); - static bool get showSuperChat => - _setting.get(SettingBoxKey.showSuperChat, defaultValue: true); + static SuperChatType get superChatType => + SuperChatType.values[_setting.get( + SettingBoxKey.superChatType, + defaultValue: SuperChatType.valid.index, + )]; static bool get minimizeOnExit => _setting.get(SettingBoxKey.minimizeOnExit, defaultValue: true);