account_section_widget.dart 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import 'package:expandable/expandable.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_sodium/flutter_sodium.dart';
  4. import 'package:local_auth/local_auth.dart';
  5. import 'package:photos/core/configuration.dart';
  6. import 'package:photos/services/user_service.dart';
  7. import 'package:photos/ui/account/change_email_dialog.dart';
  8. import 'package:photos/ui/account/password_entry_page.dart';
  9. import 'package:photos/ui/account/recovery_key_page.dart';
  10. import 'package:photos/ui/settings/common_settings.dart';
  11. import 'package:photos/ui/settings/settings_section_title.dart';
  12. import 'package:photos/ui/settings/settings_text_item.dart';
  13. import 'package:photos/ui/tools/app_lock.dart';
  14. import 'package:photos/utils/auth_util.dart';
  15. import 'package:photos/utils/dialog_util.dart';
  16. import 'package:photos/utils/navigation_util.dart';
  17. import 'package:photos/utils/toast_util.dart';
  18. class AccountSectionWidget extends StatefulWidget {
  19. const AccountSectionWidget({Key key}) : super(key: key);
  20. @override
  21. AccountSectionWidgetState createState() => AccountSectionWidgetState();
  22. }
  23. class AccountSectionWidgetState extends State<AccountSectionWidget> {
  24. @override
  25. Widget build(BuildContext context) {
  26. return ExpandablePanel(
  27. header: const SettingsSectionTitle("Account"),
  28. collapsed: Container(),
  29. expanded: _getSectionOptions(context),
  30. theme: getExpandableTheme(context),
  31. );
  32. }
  33. Column _getSectionOptions(BuildContext context) {
  34. return Column(
  35. children: [
  36. GestureDetector(
  37. behavior: HitTestBehavior.translucent,
  38. onTap: () async {
  39. if (await LocalAuthentication().isDeviceSupported()) {
  40. AppLock.of(context).setEnabled(false);
  41. String reason = "Please authenticate to view your recovery key";
  42. final result = await requestAuthentication(reason);
  43. AppLock.of(context)
  44. .setEnabled(Configuration.instance.shouldShowLockScreen());
  45. if (!result) {
  46. showToast(context, reason);
  47. return;
  48. }
  49. }
  50. String recoveryKey;
  51. try {
  52. recoveryKey = await _getOrCreateRecoveryKey();
  53. } catch (e) {
  54. showGenericErrorDialog(context);
  55. return;
  56. }
  57. routeToPage(
  58. context,
  59. RecoveryKeyPage(
  60. recoveryKey,
  61. "OK",
  62. showAppBar: true,
  63. onDone: () {},
  64. ),
  65. );
  66. },
  67. child: const SettingsTextItem(
  68. text: "Recovery key",
  69. icon: Icons.navigate_next,
  70. ),
  71. ),
  72. sectionOptionDivider,
  73. GestureDetector(
  74. behavior: HitTestBehavior.translucent,
  75. onTap: () async {
  76. if (await LocalAuthentication().isDeviceSupported()) {
  77. AppLock.of(context).setEnabled(false);
  78. String reason = "Please authenticate to change your email";
  79. final result = await requestAuthentication(reason);
  80. AppLock.of(context)
  81. .setEnabled(Configuration.instance.shouldShowLockScreen());
  82. if (!result) {
  83. showToast(context, reason);
  84. return;
  85. }
  86. }
  87. showDialog(
  88. context: context,
  89. builder: (BuildContext context) {
  90. return const ChangeEmailDialog();
  91. },
  92. barrierColor: Colors.black.withOpacity(0.85),
  93. barrierDismissible: false,
  94. );
  95. },
  96. child: const SettingsTextItem(
  97. text: "Change email",
  98. icon: Icons.navigate_next,
  99. ),
  100. ),
  101. sectionOptionDivider,
  102. GestureDetector(
  103. behavior: HitTestBehavior.translucent,
  104. onTap: () async {
  105. if (await LocalAuthentication().isDeviceSupported()) {
  106. AppLock.of(context).setEnabled(false);
  107. String reason = "Please authenticate to change your password";
  108. final result = await requestAuthentication(reason);
  109. AppLock.of(context)
  110. .setEnabled(Configuration.instance.shouldShowLockScreen());
  111. if (!result) {
  112. showToast(context, reason);
  113. return;
  114. }
  115. }
  116. Navigator.of(context).push(
  117. MaterialPageRoute(
  118. builder: (BuildContext context) {
  119. return const PasswordEntryPage(
  120. mode: PasswordEntryMode.update,
  121. );
  122. },
  123. ),
  124. );
  125. },
  126. child: const SettingsTextItem(
  127. text: "Change password",
  128. icon: Icons.navigate_next,
  129. ),
  130. ),
  131. ],
  132. );
  133. }
  134. Future<String> _getOrCreateRecoveryKey() async {
  135. return Sodium.bin2hex(
  136. await UserService.instance.getOrCreateRecoveryKey(context),
  137. );
  138. }
  139. }