From caf63f0cbea6306912c39cb6d0787a864e316ab0 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Fri, 21 Mar 2025 23:59:42 +0800 Subject: [PATCH] :sparkles: Notification preferences --- assets/translations/en-US.json | 15 ++- assets/translations/zh-CN.json | 13 ++- lib/router.dart | 8 ++ lib/screens/account/account_settings.dart | 10 ++ lib/screens/account/prefs/notify.dart | 115 +++++++++++++++++++++- 5 files changed, 156 insertions(+), 5 deletions(-) diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index b3a25fa..1c6a2a0 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -130,7 +130,7 @@ "accountPublishersSubtitle": "Manage your publish identities.", "accountSettings": "Account Settings", "accountSettingsSubtitle": "Manage your account and make it yours.", - "accountProfileEdit": "Edit your profile", + "accountProfileEdit": "Edit Profile", "accountProfileEditSubtitle": "Make your Solarpass account more looks like you.", "accountWallet": "Wallet", "accountWalletSubtitle": "View your balance and transactions.", @@ -848,5 +848,16 @@ "translated": "Translated", "settingsAutoTranslate": "Auto Translate", "settingsAutoTranslateDescription": "Automatically translate text when viewing posts and messages.", - "trayMenuHide": "Hide" + "trayMenuHide": "Hide", + "accountSettingsNotify": "Notify Settings", + "accountSettingsNotifyDescription": "Adjust the types of notifications you receive.", + "accountSettingsSecurity": "Security Settings", + "accountSettingsSecurityDescription": "Adjust your account security settings.", + "save": "Save", + "notificationTopicPostFeedback": "Post Feedback", + "notificationTopicPostReply": "Post Replies", + "notificationTopicPostSubscription": "Post Subscriptions", + "notificationTopicMessaging": "New Messages", + "notificationTopicMessagingCall": "Incoming Calls", + "notificationTopicGeneral": "General" } diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index 3c3079c..8833be9 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -846,5 +846,16 @@ "translated": "已翻译", "settingsAutoTranslate": "自动翻译", "settingsAutoTranslateDescription": "在查看帖子、消息时自动翻译文本。", - "trayMenuHide": "隐藏" + "trayMenuHide": "隐藏", + "accountSettingsNotify": "通知设置", + "accountSettingsNotifyDescription": "调整你所收到的通知种类。", + "accountSettingsSecurity": "安全设置", + "accountSettingsSecurityDescription": "调整你的帐户安全设置。", + "save": "保存", + "notificationTopicPostFeedback": "帖子数据反馈", + "notificationTopicPostReply": "帖子回复", + "notificationTopicPostSubscription": "帖子订阅", + "notificationTopicMessaging": "消息", + "notificationTopicMessagingCall": "通话", + "notificationTopicGeneral": "杂项" } diff --git a/lib/router.dart b/lib/router.dart index 5b04c8a..f42f916 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -9,6 +9,7 @@ import 'package:surface/screens/account/badges.dart'; import 'package:surface/screens/account/contact_methods.dart'; import 'package:surface/screens/account/factor_settings.dart'; import 'package:surface/screens/account/keypairs.dart'; +import 'package:surface/screens/account/prefs/notify.dart'; import 'package:surface/screens/account/profile_page.dart'; import 'package:surface/screens/account/profile_edit.dart'; import 'package:surface/screens/account/publishers/publisher_edit.dart'; @@ -161,6 +162,13 @@ final _appRoutes = [ path: '/settings', name: 'accountSettings', builder: (context, state) => AccountSettingsScreen(), + routes: [ + GoRoute( + path: '/notify', + name: 'accountSettingsNotify', + builder: (context, state) => const AccountNotifyPrefsScreen(), + ), + ], ), GoRoute( path: '/settings/factors', diff --git a/lib/screens/account/account_settings.dart b/lib/screens/account/account_settings.dart index 6454e1a..2460b90 100644 --- a/lib/screens/account/account_settings.dart +++ b/lib/screens/account/account_settings.dart @@ -97,6 +97,16 @@ class AccountSettingsScreen extends StatelessWidget { GoRouter.of(context).pushNamed('accountContactMethods'); }, ), + ListTile( + title: Text('accountSettingsNotify').tr(), + subtitle: Text('accountSettingsNotifyDescription').tr(), + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + leading: const Icon(Symbols.notifications), + trailing: const Icon(Symbols.chevron_right), + onTap: () { + GoRouter.of(context).pushNamed('accountSettingsNotify'); + }, + ), ListTile( title: Text('accountProfileEdit').tr(), subtitle: Text('accountProfileEditSubtitle').tr(), diff --git a/lib/screens/account/prefs/notify.dart b/lib/screens/account/prefs/notify.dart index 189ffd0..b3da351 100644 --- a/lib/screens/account/prefs/notify.dart +++ b/lib/screens/account/prefs/notify.dart @@ -1,11 +1,122 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; +import 'package:surface/providers/sn_network.dart'; +import 'package:surface/widgets/dialog.dart'; +import 'package:surface/widgets/loading_indicator.dart'; import 'package:surface/widgets/navigation/app_scaffold.dart'; -class AccountNotifyPrefsScreen extends StatelessWidget { +final Map kNotifyTopicMap = { + 'interactive.reply': 'notificationTopicPostReply'.tr(), + 'interactive.feedback': 'notificationTopicPostFeedback'.tr(), + 'interactive.subscription': 'notificationTopicPostSubscription'.tr(), + 'messaging.message': 'notificationTopicMessaging'.tr(), + 'messaging.call': 'notificationTopicMessagingCall'.tr(), + 'general': 'notificationTopicGeneral'.tr(), +}; + +class AccountNotifyPrefsScreen extends StatefulWidget { const AccountNotifyPrefsScreen({super.key}); + @override + State createState() => + _AccountNotifyPrefsScreenState(); +} + +class _AccountNotifyPrefsScreenState extends State { + bool _isBusy = true; + + Map _config = {}; + + Future _getPreferences() async { + setState(() => _isBusy = true); + + final sn = context.read(); + + try { + final resp = await sn.client.get('/cgi/id/preferences/notifications'); + _config = resp.data['config'] + .map((k, v) => MapEntry(k, v as bool)) + .cast(); + } finally { + setState(() => _isBusy = false); + } + } + + Future _savePreferences() async { + setState(() => _isBusy = true); + + final sn = context.read(); + + try { + await sn.client.put( + '/cgi/id/preferences/notifications', + data: { + 'config': _config, + }, + ); + if (!mounted) return; + context.showSnackbar('accountSettingsApplied'.tr()); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err); + } finally { + setState(() => _isBusy = false); + } + } + + @override + void initState() { + super.initState(); + _getPreferences(); + } + @override Widget build(BuildContext context) { - return AppScaffold(); + return AppScaffold( + appBar: AppBar( + leading: const PageBackButton(), + title: Text('accountSettingsNotify').tr(), + ), + body: Column( + children: [ + LoadingIndicator(isActive: _isBusy), + ListTile( + tileColor: Theme.of(context).colorScheme.surfaceContainer, + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + leading: const Icon(Icons.save), + title: Text('save').tr(), + enabled: !_isBusy, + onTap: () { + _savePreferences(); + }, + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.zero, + itemCount: kNotifyTopicMap.length, + itemBuilder: (context, index) { + final element = kNotifyTopicMap.entries.elementAt(index); + return CheckboxListTile( + title: Text(element.value), + subtitle: Text( + element.key, + style: GoogleFonts.robotoMono(fontSize: 12), + ), + value: _config[element.key] ?? true, + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + onChanged: (value) { + setState(() { + _config[element.key] = value ?? false; + }); + }, + ); + }, + ), + ), + ], + ), + ); } }