From e8c82f69d4d8f2be6d9cb6c52605bc7d8d226ffa Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Thu, 9 Jan 2025 12:41:04 +0800 Subject: [PATCH] opt: unread msg Closes #122 Signed-off-by: bggRGjQaUbCoE --- lib/models/common/dynamic_badge_mode.dart | 4 +- lib/pages/main/controller.dart | 37 ++++---- lib/pages/setting/widgets/model.dart | 15 ++-- .../setting/widgets/multi_select_dialog.dart | 87 +++++++++++++++++++ lib/pages/setting/widgets/select_dialog.dart | 7 +- lib/utils/storage.dart | 12 +-- 6 files changed, 129 insertions(+), 33 deletions(-) create mode 100644 lib/pages/setting/widgets/multi_select_dialog.dart diff --git a/lib/models/common/dynamic_badge_mode.dart b/lib/models/common/dynamic_badge_mode.dart index a49e9086..01e4c7d1 100644 --- a/lib/models/common/dynamic_badge_mode.dart +++ b/lib/models/common/dynamic_badge_mode.dart @@ -4,8 +4,8 @@ extension DynamicBadgeModeDesc on DynamicBadgeMode { String get description => ['隐藏', '红点', '数字'][index]; } -enum MsgUnReadType { pm, reply, at, like, sysMsg, all } +enum MsgUnReadType { pm, reply, at, like, sysMsg } extension MsgUnReadTypeExt on MsgUnReadType { - String get title => ['私信', '回复我的', '@我', '收到的赞', '系统通知', '全部'][index]; + String get title => ['私信', '回复我的', '@我', '收到的赞', '系统通知'][index]; } diff --git a/lib/pages/main/controller.dart b/lib/pages/main/controller.dart index b0ab3549..7a46346d 100644 --- a/lib/pages/main/controller.dart +++ b/lib/pages/main/controller.dart @@ -35,7 +35,7 @@ class MainController extends GetxController { late int homeIndex = -1; late DynamicBadgeMode msgBadgeMode = GStorage.msgBadgeMode; - late MsgUnReadType msgUnReadType = GStorage.msgUnReadType; + late List msgUnReadTypes = GStorage.msgUnReadTypeV2; late final RxString msgUnReadCount = ''.obs; late int lastCheckUnreadAt = 0; @@ -77,11 +77,14 @@ class MainController extends GetxController { if (isLogin.value.not || homeIndex == -1) { return; } + if (msgUnReadTypes.isEmpty) { + msgUnReadCount.value = ''; + return; + } try { - bool shouldCheckPM = msgUnReadType == MsgUnReadType.pm || - msgUnReadType == MsgUnReadType.all; - bool shouldCheckFeed = msgUnReadType != MsgUnReadType.pm || - msgUnReadType == MsgUnReadType.all; + bool shouldCheckPM = msgUnReadTypes.contains(MsgUnReadType.pm); + bool shouldCheckFeed = + ([...msgUnReadTypes]..remove(MsgUnReadType.pm)).isNotEmpty; List res = await Future.wait([ if (shouldCheckPM) _queryPMUnread(), if (shouldCheckFeed) _queryMsgFeedUnread(), @@ -93,18 +96,18 @@ class MainController extends GetxController { if ((shouldCheckPM.not && res.firstOrNull?['status'] == true) || (shouldCheckPM && res.getOrNull(1)?['status'] == true)) { int index = shouldCheckPM.not ? 0 : 1; - count += (switch (msgUnReadType) { - MsgUnReadType.pm => 0, - MsgUnReadType.reply => res[index]['data']['reply'], - MsgUnReadType.at => res[index]['data']['at'], - MsgUnReadType.like => res[index]['data']['like'], - MsgUnReadType.sysMsg => res[index]['data']['sys_msg'], - MsgUnReadType.all => res[index]['data']['reply'] + - res[index]['data']['at'] + - res[index]['data']['like'] + - res[index]['data']['sys_msg'], - } as int?) ?? - 0; + if (msgUnReadTypes.contains(MsgUnReadType.reply)) { + count += (res[index]['data']['reply'] as int?) ?? 0; + } + if (msgUnReadTypes.contains(MsgUnReadType.at)) { + count += (res[index]['data']['at'] as int?) ?? 0; + } + if (msgUnReadTypes.contains(MsgUnReadType.like)) { + count += (res[index]['data']['like'] as int?) ?? 0; + } + if (msgUnReadTypes.contains(MsgUnReadType.sysMsg)) { + count += (res[index]['data']['sys_msg'] as int?) ?? 0; + } } count = count == 0 ? '' diff --git a/lib/pages/setting/widgets/model.dart b/lib/pages/setting/widgets/model.dart index ec5374a7..5262bc67 100644 --- a/lib/pages/setting/widgets/model.dart +++ b/lib/pages/setting/widgets/model.dart @@ -17,6 +17,7 @@ import 'package:PiliPlus/pages/main/controller.dart'; import 'package:PiliPlus/pages/member/new/controller.dart'; import 'package:PiliPlus/pages/mine/controller.dart'; import 'package:PiliPlus/pages/setting/pages/color_select.dart'; +import 'package:PiliPlus/pages/setting/widgets/multi_select_dialog.dart'; import 'package:PiliPlus/pages/setting/widgets/normal_item.dart'; import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart'; import 'package:PiliPlus/pages/setting/widgets/slide_dialog.dart'; @@ -286,12 +287,12 @@ List get styleSettings => [ SettingsModel( settingsType: SettingsType.normal, onTap: (setState) async { - MsgUnReadType? result = await showDialog( + List? result = await showDialog( context: Get.context!, builder: (context) { - return SelectDialog( + return MultiSelectDialog( title: '消息未读类型', - value: GStorage.msgUnReadType, + initValues: GStorage.msgUnReadTypeV2, values: MsgUnReadType.values.map((e) { return {'title': e.title, 'value': e}; }).toList(), @@ -299,9 +300,10 @@ List get styleSettings => [ }, ); if (result != null) { - GStorage.setting.put(SettingBoxKey.msgUnReadType, result.index); + GStorage.setting.put(SettingBoxKey.msgUnReadTypeV2, + result.map((item) => item.index).toList()..sort()); MainController mainController = Get.put(MainController()); - mainController.msgUnReadType = MsgUnReadType.values[result.index]; + mainController.msgUnReadTypes = result; if (mainController.msgBadgeMode != DynamicBadgeMode.hidden) { mainController.queryUnreadMsg(); } @@ -311,7 +313,8 @@ List get styleSettings => [ }, title: '消息未读类型', leading: const Icon(Icons.notifications_active_outlined), - getSubtitle: () => '当前消息类型:${GStorage.msgUnReadType.title}', + getSubtitle: () => + '当前消息类型:${GStorage.msgUnReadTypeV2.map((item) => item.title).join('、')}', ), SettingsModel( settingsType: SettingsType.sw1tch, diff --git a/lib/pages/setting/widgets/multi_select_dialog.dart b/lib/pages/setting/widgets/multi_select_dialog.dart new file mode 100644 index 00000000..210444e3 --- /dev/null +++ b/lib/pages/setting/widgets/multi_select_dialog.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class MultiSelectDialog extends StatefulWidget { + final List initValues; + final String title; + final List values; + + const MultiSelectDialog({ + super.key, + required this.initValues, + required this.values, + required this.title, + }); + + @override + State> createState() => _MultiSelectDialogState(); +} + +class _MultiSelectDialogState extends State> { + late Set _tempValues; + + @override + void initState() { + super.initState(); + _tempValues = widget.initValues.toSet(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + clipBehavior: Clip.hardEdge, + title: Text( + widget.title, + style: TextStyle(fontSize: 18), + ), + contentPadding: const EdgeInsets.only(top: 12), + content: StatefulBuilder(builder: (context, StateSetter setState) { + return SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: List.generate( + widget.values.length, + (index) { + bool isChecked = + _tempValues.contains(widget.values[index]['value']); + return CheckboxListTile( + dense: true, + value: isChecked, + controlAffinity: ListTileControlAffinity.leading, + title: Text( + widget.values[index]['title'], + style: Theme.of(context).textTheme.titleMedium!, + ), + onChanged: (value) { + if (isChecked) { + _tempValues.remove(widget.values[index]['value']); + } else { + _tempValues.add(widget.values[index]['value']); + } + setState(() {}); + }, + ); + }, + ), + ), + ); + }), + actionsPadding: EdgeInsets.only(left: 16, right: 16, bottom: 12), + actions: [ + TextButton( + onPressed: Get.back, + child: Text( + '取消', + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + ), + ), + ), + TextButton( + onPressed: () => Get.back(result: _tempValues.toList()), + child: const Text('确定'), + ), + ], + ); + } +} diff --git a/lib/pages/setting/widgets/select_dialog.dart b/lib/pages/setting/widgets/select_dialog.dart index da931634..ef137397 100644 --- a/lib/pages/setting/widgets/select_dialog.dart +++ b/lib/pages/setting/widgets/select_dialog.dart @@ -93,8 +93,6 @@ class _SelectDialogState extends State> { @override Widget build(BuildContext context) { - TextStyle titleStyle = Theme.of(context).textTheme.titleMedium!; - return AlertDialog( clipBehavior: Clip.hardEdge, title: Text( @@ -111,7 +109,10 @@ class _SelectDialogState extends State> { (index) => RadioListTile( dense: true, value: widget.values[index]['value'], - title: Text(widget.values[index]['title'], style: titleStyle), + title: Text( + widget.values[index]['title'], + style: Theme.of(context).textTheme.titleMedium!, + ), subtitle: widget.title == 'CDN 设置' && cdnSpeedTest ? Text( _cdnResList[index] is double diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 3716bc4a..a3afb364 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -99,10 +99,11 @@ class GStorage { defaultValue: DynamicBadgeMode.number.index, )]; - static MsgUnReadType get msgUnReadType => MsgUnReadType.values[setting.get( - SettingBoxKey.msgUnReadType, - defaultValue: MsgUnReadType.pm.index, - )]; + static List get msgUnReadTypeV2 => List.from(setting.get( + SettingBoxKey.msgUnReadTypeV2, + defaultValue: + List.generate(MsgUnReadType.values.length, (index) => index), + )).map((index) => MsgUnReadType.values[index]).toList(); static int get defaultHomePage => setting.get(SettingBoxKey.defaultHomePage, defaultValue: 0); @@ -574,7 +575,8 @@ class SettingBoxKey { tabbarSort = 'tabbarSort', // 首页tabbar dynamicBadgeMode = 'dynamicBadgeMode', msgBadgeMode = 'msgBadgeMode', - msgUnReadType = 'msgUnReadType', + // msgUnReadType = 'msgUnReadType', + msgUnReadTypeV2 = 'msgUnReadTypeV2', hiddenSettingUnlocked = 'hiddenSettingUnlocked', enableGradientBg = 'enableGradientBg', navBarSort = 'navBarSort';