From 4cbeafd447c2c935d62f8329073e7a5a4750c1b5 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 21 Sep 2024 22:44:08 +0800 Subject: [PATCH] :sparkles: Account deletion --- assets/locales/en_us.json | 9 +++++- assets/locales/zh_cn.json | 9 +++++- lib/bootstrapper.dart | 4 +++ lib/exts.dart | 43 +++++++++++++++++++++++++ lib/screens/settings.dart | 51 ++++++++++++++++++++++++++++++ lib/widgets/posts/post_action.dart | 2 +- pubspec.lock | 24 +++++++++----- pubspec.yaml | 3 +- 8 files changed, 133 insertions(+), 12 deletions(-) diff --git a/assets/locales/en_us.json b/assets/locales/en_us.json index 84973e0..4fb827a 100644 --- a/assets/locales/en_us.json +++ b/assets/locales/en_us.json @@ -443,7 +443,14 @@ "iAmNotRobot": "I'm not a Robot", "report": "Report", "reportAbuse": "Report abuse", + "reportAbuseDesc": "Report any violation of service terms", "reportAbuseResource": "Resource identifier", "reportAbuseReason": "Report reason", - "reportSubmitted": "Report submitted, thank you for your contribution. We will send a notification about the result of the report within 24 hours for you." + "reportSubmitted": "Report submitted, thank you for your contribution. We will send a notification about the result of the report within 24 hours for you.", + "accountDeletion": "Request account deletion", + "accountDeletionDesc": "Delete the current account and all its data. Note that this action is irreversible!", + "accountDeletionConfirm": "Confirm request account deletion", + "accountDeletionConfirmDesc": "Are you sure to delete account @account? You will receive a confirmation email with a link to confirm the deletion of the account within 24 hours. Note that this action is irreversible, and all data associated with the account will be deleted, and you should be careful about it.", + "accountDeletionRequested": "Account deletion requested, check your inbox to confirm the request.", + "slideToConfirm": "Slide to confirm" } diff --git a/assets/locales/zh_cn.json b/assets/locales/zh_cn.json index 7655aba..d3efb92 100644 --- a/assets/locales/zh_cn.json +++ b/assets/locales/zh_cn.json @@ -439,7 +439,14 @@ "iAmNotRobot": "我不是机器人", "report": "举报", "reportAbuse": "举报滥用", + "reportAbuseDesc": "举报任何违反服务条款的行为", "reportAbuseResource": "举报的资源", "reportAbuseReason": "举报的原因", - "reportSubmitted": "举报已提交,感谢你的贡献。我们将通过通知在 24 小时内通知该举报的处理结果。" + "reportSubmitted": "举报已提交,感谢你的贡献。我们将通过通知在 24 小时内通知该举报的处理结果。", + "accountDeletion": "请求删除账号", + "accountDeletionDesc": "删除目前登陆的账号,及其所有的数据。注意,该操作不可撤销!", + "accountDeletionConfirm": "确认账号删除请求", + "accountDeletionConfirmDesc": "你确定要删除账号 @account 吗?你将会在其绑定的主要邮件地址收到一封包含着确认删除账号连接的邮件,在二十四小时内使用该连接即可完成删除账号。注意,本操作不可撤销,并且账号创建或关联的所有数据都将被删除,请三思而后行。", + "accountDeletionRequested": "已请求删除账号,检查你的收件箱来确认请求。", + "slideToConfirm": "滑动来确认" } diff --git a/lib/bootstrapper.dart b/lib/bootstrapper.dart index d01dd00..eb93bdc 100644 --- a/lib/bootstrapper.dart +++ b/lib/bootstrapper.dart @@ -6,6 +6,7 @@ import 'package:get/get.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:solian/exceptions/request.dart'; import 'package:solian/exts.dart'; import 'package:solian/platform.dart'; import 'package:solian/providers/auth.dart'; @@ -52,6 +53,9 @@ class _BootstrapperShellState extends State { ).get( 'https://git.solsynth.dev/api/v1/repos/hydrogen/solian/tags?page=1&limit=1', ); + if (resp.statusCode != 200) { + throw RequestException(resp); + } final remoteVersionString = (resp.body as List).firstOrNull?['name'] ?? '0.0.0+0'; final remoteVersion = Version.parse(remoteVersionString.split('+').first); diff --git a/lib/exts.dart b/lib/exts.dart index f171333..917da1a 100644 --- a/lib/exts.dart +++ b/lib/exts.dart @@ -1,6 +1,8 @@ import 'dart:math' as math; +import 'package:action_slider/action_slider.dart'; import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; import 'package:get/get.dart'; import 'package:solian/exceptions/request.dart'; import 'package:solian/exceptions/unauthorized.dart'; @@ -73,6 +75,47 @@ extension AppExtensions on BuildContext { false; } + Future showSlideToConfirmDialog(String title, body) async { + return await showDialog( + useRootNavigator: true, + context: this, + builder: (ctx) => AlertDialog( + title: Text(title, textAlign: TextAlign.center), + content: SizedBox( + width: double.maxFinite, + child: ListView( + shrinkWrap: true, + children: [ + Text(body, textAlign: TextAlign.center), + const Gap(28), + ActionSlider.standard( + icon: const Icon(Icons.send), + iconAlignment: Alignment.center, + sliderBehavior: SliderBehavior.move, + actionThresholdType: ThresholdType.release, + toggleColor: Colors.red, + action: (controller) async { + controller.success(); + await Future.delayed(const Duration(milliseconds: 500)); + Navigator.pop(ctx, true); + }, + child: Text('slideToConfirm'.tr), + ), + ], + ), + ), + actionsAlignment: MainAxisAlignment.center, + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx, false), + child: Text('cancel'.tr), + ) + ], + ), + ) ?? + false; + } + Future showErrorDialog(dynamic exception) { Widget content = Text(exception.toString().capitalize!); if (exception is UnauthorizedException) { diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index b83f924..36bd7c4 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -2,12 +2,15 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:solian/exceptions/request.dart'; import 'package:solian/exts.dart'; import 'package:solian/platform.dart'; +import 'package:solian/providers/auth.dart'; import 'package:solian/providers/database/database.dart'; import 'package:solian/providers/theme_switcher.dart'; import 'package:solian/router.dart'; import 'package:solian/theme.dart'; +import 'package:solian/widgets/reports/abuse_report.dart'; class SettingScreen extends StatefulWidget { const SettingScreen({super.key}); @@ -129,6 +132,54 @@ class _SettingScreenState extends State { }); }, ), + Obx(() { + final AuthProvider auth = Get.find(); + if (!auth.isAuthorized.value) return const SizedBox.shrink(); + return Column( + children: [ + _buildCaptionHeader('account'.tr), + ListTile( + leading: const Icon(Icons.flag), + trailing: const Icon(Icons.chevron_right), + contentPadding: const EdgeInsets.symmetric(horizontal: 22), + title: Text('reportAbuse'.tr), + subtitle: Text('reportAbuseDesc'.tr), + onTap: () { + showDialog( + context: context, + builder: (context) => const AbuseReportDialog(), + ); + }, + ), + ListTile( + leading: const Icon(Icons.person_remove), + trailing: const Icon(Icons.chevron_right), + contentPadding: const EdgeInsets.symmetric(horizontal: 22), + title: Text('accountDeletion'.tr), + subtitle: Text('accountDeletionDesc'.tr), + onTap: () { + context + .showSlideToConfirmDialog( + 'accountDeletionConfirm'.tr, + 'accountDeletionConfirmDesc'.trParams({ + 'account': '@${auth.userProfile.value!['name']}', + }), + ) + .then((value) async { + if (value != true) return; + final client = await auth.configureClient('id'); + final resp = await client.post('/users/me/deletion', {}); + if (resp.statusCode != 200) { + context.showErrorDialog(RequestException(resp)); + } else { + context.showSnackbar('accountDeletionRequested'.tr); + } + }); + }, + ), + ], + ); + }), _buildCaptionHeader('more'.tr), ListTile( leading: const Icon(Icons.delete_sweep), diff --git a/lib/widgets/posts/post_action.dart b/lib/widgets/posts/post_action.dart index c71013a..83db4de 100644 --- a/lib/widgets/posts/post_action.dart +++ b/lib/widgets/posts/post_action.dart @@ -152,7 +152,7 @@ class _PostActionState extends State { ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Icons.report), + leading: const Icon(Icons.flag), title: Text('report'.tr), onTap: () { showDialog( diff --git a/pubspec.lock b/pubspec.lock index eae0d8e..a5e8d59 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,6 +22,14 @@ packages: description: dart source: sdk version: "0.3.2" + action_slider: + dependency: "direct main" + description: + name: action_slider + sha256: fad0720cde9bf06c12594c15da17dba087556a3285875a91aee3d3a64a3072e2 + url: "https://pub.dev" + source: hosted + version: "0.7.0" analyzer: dependency: transitive description: @@ -330,10 +338,10 @@ packages: dependency: "direct main" description: name: desktop_drop - sha256: d55a010fe46c8e8fcff4ea4b451a9ff84a162217bdb3b2a0aa1479776205e15d + sha256: "03abf1c0443afdd1d65cf8fa589a2f01c67a11da56bbb06f6ea1de79d5628e94" url: "https://pub.dev" source: hosted - version: "0.4.4" + version: "0.5.0" device_info_plus: dependency: "direct main" description: @@ -639,10 +647,10 @@ packages: dependency: "direct main" description: name: flutter_app_update - sha256: "2b83278d5cc807f543e623d5b466216316104335a4918d9cc4556f39985fe84a" + sha256: "3650f57571e9f05d51f008f3fc9d556351910348f8011de7734b56fa74ccfee6" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" flutter_background_service: dependency: "direct main" description: @@ -759,10 +767,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: c500d5d9e7e553f06b61877ca6b9c8b92c570a4c8db371038702e8ce57f8a50f + sha256: "49eeef364fddb71515bc78d5a8c51435a68bccd6e4d68e25a942c5e47761ae71" url: "https://pub.dev" source: hosted - version: "17.2.2" + version: "17.2.3" flutter_local_notifications_linux: dependency: transitive description: @@ -1201,10 +1209,10 @@ packages: dependency: "direct main" description: name: livekit_client - sha256: "5df9b6f153b5f2c59fbf116b41e54597dfe8b2340b6630f7d8869887a9e58f44" + sha256: "449f1f4f7688cc0d27a466d5b78c8973ec4bf2bbe93f79441f4fd118ecea61d7" url: "https://pub.dev" source: hosted - version: "2.2.5" + version: "2.2.6" logging: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e5bef8c..f41009f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -43,7 +43,7 @@ dependencies: protocol_handler: ^0.2.0 markdown: ^7.2.2 pasteboard: ^0.3.0 - desktop_drop: ^0.4.4 + desktop_drop: ^0.5.0 badges: ^3.1.2 flutter_card_swiper: ^7.0.1 dismissible_page: ^1.0.2 @@ -82,6 +82,7 @@ dependencies: flutter_local_notifications: ^17.2.2 flutter_app_update: ^3.1.0 version: ^3.0.2 + action_slider: ^0.7.0 dev_dependencies: flutter_test: