✨ Notification preferences
This commit is contained in:
		| @@ -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" | ||||
| } | ||||
|   | ||||
| @@ -846,5 +846,16 @@ | ||||
|   "translated": "已翻译", | ||||
|   "settingsAutoTranslate": "自动翻译", | ||||
|   "settingsAutoTranslateDescription": "在查看帖子、消息时自动翻译文本。", | ||||
|   "trayMenuHide": "隐藏" | ||||
|   "trayMenuHide": "隐藏", | ||||
|   "accountSettingsNotify": "通知设置", | ||||
|   "accountSettingsNotifyDescription": "调整你所收到的通知种类。", | ||||
|   "accountSettingsSecurity": "安全设置", | ||||
|   "accountSettingsSecurityDescription": "调整你的帐户安全设置。", | ||||
|   "save": "保存", | ||||
|   "notificationTopicPostFeedback": "帖子数据反馈", | ||||
|   "notificationTopicPostReply": "帖子回复", | ||||
|   "notificationTopicPostSubscription": "帖子订阅", | ||||
|   "notificationTopicMessaging": "消息", | ||||
|   "notificationTopicMessagingCall": "通话", | ||||
|   "notificationTopicGeneral": "杂项" | ||||
| } | ||||
|   | ||||
| @@ -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', | ||||
|   | ||||
| @@ -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(), | ||||
|   | ||||
| @@ -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<String, String> 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<AccountNotifyPrefsScreen> createState() => | ||||
|       _AccountNotifyPrefsScreenState(); | ||||
| } | ||||
|  | ||||
| class _AccountNotifyPrefsScreenState extends State<AccountNotifyPrefsScreen> { | ||||
|   bool _isBusy = true; | ||||
|  | ||||
|   Map<String, bool> _config = {}; | ||||
|  | ||||
|   Future<void> _getPreferences() async { | ||||
|     setState(() => _isBusy = true); | ||||
|  | ||||
|     final sn = context.read<SnNetworkProvider>(); | ||||
|  | ||||
|     try { | ||||
|       final resp = await sn.client.get('/cgi/id/preferences/notifications'); | ||||
|       _config = resp.data['config'] | ||||
|           .map((k, v) => MapEntry(k, v as bool)) | ||||
|           .cast<String, bool>(); | ||||
|     } finally { | ||||
|       setState(() => _isBusy = false); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future<void> _savePreferences() async { | ||||
|     setState(() => _isBusy = true); | ||||
|  | ||||
|     final sn = context.read<SnNetworkProvider>(); | ||||
|  | ||||
|     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; | ||||
|                     }); | ||||
|                   }, | ||||
|                 ); | ||||
|               }, | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user