diff --git a/mobile/apps/auth/lib/models/account/two_factor.dart b/mobile/apps/auth/lib/models/account/two_factor.dart deleted file mode 100644 index 45f7c8fde8..0000000000 --- a/mobile/apps/auth/lib/models/account/two_factor.dart +++ /dev/null @@ -1,11 +0,0 @@ -enum TwoFactorType { totp, passkey } - -// ToString for TwoFactorType -String twoFactorTypeToString(TwoFactorType type) { - switch (type) { - case TwoFactorType.totp: - return "totp"; - case TwoFactorType.passkey: - return "passkey"; - } -} diff --git a/mobile/apps/auth/lib/models/delete_account.dart b/mobile/apps/auth/lib/models/delete_account.dart deleted file mode 100644 index 71ca04e9c3..0000000000 --- a/mobile/apps/auth/lib/models/delete_account.dart +++ /dev/null @@ -1,9 +0,0 @@ -class DeleteChallengeResponse { - final bool allowDelete; - final String encryptedChallenge; - - DeleteChallengeResponse({ - required this.allowDelete, - required this.encryptedChallenge, - }); -} diff --git a/mobile/apps/auth/lib/models/sessions.dart b/mobile/apps/auth/lib/models/sessions.dart deleted file mode 100644 index 56ba8a31a1..0000000000 --- a/mobile/apps/auth/lib/models/sessions.dart +++ /dev/null @@ -1,45 +0,0 @@ -class Sessions { - final List sessions; - - Sessions( - this.sessions, - ); - - factory Sessions.fromMap(Map map) { - if (map["sessions"] == null) { - throw Exception('\'map["sessions"]\' must not be null'); - } - return Sessions( - List.from(map['sessions']?.map((x) => Session.fromMap(x))), - ); - } -} - -class Session { - final String token; - final int creationTime; - final String ip; - final String ua; - final String prettyUA; - final int lastUsedTime; - - Session( - this.token, - this.creationTime, - this.ip, - this.ua, - this.prettyUA, - this.lastUsedTime, - ); - - factory Session.fromMap(Map map) { - return Session( - map['token'], - map['creationTime'], - map['ip'], - map['ua'], - map['prettyUA'], - map['lastUsedTime'], - ); - } -} diff --git a/mobile/apps/auth/lib/models/set_keys_request.dart b/mobile/apps/auth/lib/models/set_keys_request.dart deleted file mode 100644 index e782319f50..0000000000 --- a/mobile/apps/auth/lib/models/set_keys_request.dart +++ /dev/null @@ -1,25 +0,0 @@ -class SetKeysRequest { - final String kekSalt; - final String encryptedKey; - final String keyDecryptionNonce; - final int memLimit; - final int opsLimit; - - SetKeysRequest({ - required this.kekSalt, - required this.encryptedKey, - required this.keyDecryptionNonce, - required this.memLimit, - required this.opsLimit, - }); - - Map toMap() { - return { - 'kekSalt': kekSalt, - 'encryptedKey': encryptedKey, - 'keyDecryptionNonce': keyDecryptionNonce, - 'memLimit': memLimit, - 'opsLimit': opsLimit, - }; - } -} diff --git a/mobile/apps/auth/lib/models/set_recovery_key_request.dart b/mobile/apps/auth/lib/models/set_recovery_key_request.dart deleted file mode 100644 index 1a03e4e36c..0000000000 --- a/mobile/apps/auth/lib/models/set_recovery_key_request.dart +++ /dev/null @@ -1,22 +0,0 @@ -class SetRecoveryKeyRequest { - final String masterKeyEncryptedWithRecoveryKey; - final String masterKeyDecryptionNonce; - final String recoveryKeyEncryptedWithMasterKey; - final String recoveryKeyDecryptionNonce; - - SetRecoveryKeyRequest( - this.masterKeyEncryptedWithRecoveryKey, - this.masterKeyDecryptionNonce, - this.recoveryKeyEncryptedWithMasterKey, - this.recoveryKeyDecryptionNonce, - ); - - Map toMap() { - return { - 'masterKeyEncryptedWithRecoveryKey': masterKeyEncryptedWithRecoveryKey, - 'masterKeyDecryptionNonce': masterKeyDecryptionNonce, - 'recoveryKeyEncryptedWithMasterKey': recoveryKeyEncryptedWithMasterKey, - 'recoveryKeyDecryptionNonce': recoveryKeyDecryptionNonce, - }; - } -} diff --git a/mobile/apps/auth/lib/models/subscription.dart b/mobile/apps/auth/lib/models/subscription.dart deleted file mode 100644 index 3804f9a2e8..0000000000 --- a/mobile/apps/auth/lib/models/subscription.dart +++ /dev/null @@ -1,65 +0,0 @@ -const freeProductID = "free"; -const stripe = "stripe"; -const appStore = "appstore"; -const playStore = "playstore"; - -class Subscription { - final String productID; - final int storage; - final String originalTransactionID; - final String paymentProvider; - final int expiryTime; - final String price; - final String period; - final Attributes? attributes; - - Subscription({ - required this.productID, - required this.storage, - required this.originalTransactionID, - required this.paymentProvider, - required this.expiryTime, - required this.price, - required this.period, - this.attributes, - }); - - bool isValid() { - return expiryTime > DateTime.now().microsecondsSinceEpoch; - } - - bool isYearlyPlan() { - return 'year' == period; - } - - static fromMap(Map? map) { - if (map == null) return null; - return Subscription( - productID: map['productID'], - storage: map['storage'], - originalTransactionID: map['originalTransactionID'], - paymentProvider: map['paymentProvider'], - expiryTime: map['expiryTime'], - price: map['price'], - period: map['period'], - attributes: map["attributes"] != null - ? Attributes.fromJson(map["attributes"]) - : null, - ); - } -} - -class Attributes { - bool? isCancelled; - String? customerID; - - Attributes({ - this.isCancelled, - this.customerID, - }); - - Attributes.fromJson(dynamic json) { - isCancelled = json["isCancelled"]; - customerID = json["customerID"]; - } -} diff --git a/mobile/apps/auth/lib/models/typedefs.dart b/mobile/apps/auth/lib/models/typedefs.dart deleted file mode 100644 index 7a42a1fe5e..0000000000 --- a/mobile/apps/auth/lib/models/typedefs.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'dart:async'; - -typedef FutureVoidCallback = Future Function(); -typedef BoolCallBack = bool Function(); -typedef FutureVoidCallbackParamStr = Future Function(String); -typedef VoidCallbackParamStr = void Function(String); -typedef FutureOrVoidCallback = FutureOr Function(); diff --git a/mobile/apps/auth/lib/models/user_details.dart b/mobile/apps/auth/lib/models/user_details.dart deleted file mode 100644 index e50d3ee295..0000000000 --- a/mobile/apps/auth/lib/models/user_details.dart +++ /dev/null @@ -1,146 +0,0 @@ -import 'dart:convert'; -import 'dart:math'; - -import 'package:collection/collection.dart'; -import 'package:ente_auth/models/subscription.dart'; - -class UserDetails { - final String email; - final int usage; - final int fileCount; - final int sharedCollectionsCount; - final Subscription subscription; - final FamilyData? familyData; - final ProfileData? profileData; - - UserDetails( - this.email, - this.usage, - this.fileCount, - this.sharedCollectionsCount, - this.subscription, - this.familyData, - this.profileData, - ); - - bool isPartOfFamily() { - return familyData?.members?.isNotEmpty ?? false; - } - - bool isFamilyAdmin() { - assert(isPartOfFamily(), "verify user is part of family before calling"); - final FamilyMember currentUserMember = familyData!.members! - .firstWhere((element) => element.email.trim() == email.trim()); - return currentUserMember.isAdmin; - } - - // getFamilyOrPersonalUsage will return total usage for family if user - // belong to family group. Otherwise, it will return storage consumed by - // current user - int getFamilyOrPersonalUsage() { - return isPartOfFamily() ? familyData!.getTotalUsage() : usage; - } - - int getFreeStorage() { - return max( - isPartOfFamily() - ? (familyData!.storage - familyData!.getTotalUsage()) - : (subscription.storage - (usage)), - 0, - ); - } - - int getTotalStorage() { - return isPartOfFamily() ? familyData!.storage : subscription.storage; - } - - factory UserDetails.fromMap(Map map) { - return UserDetails( - map['email'] as String, - map['usage'] as int, - (map['fileCount'] ?? 0) as int, - (map['sharedCollectionsCount'] ?? 0) as int, - Subscription.fromMap(map['subscription']), - FamilyData.fromMap(map['familyData']), - ProfileData.fromJson(map['profileData']), - ); - } - -} - -class FamilyMember { - final String email; - final int usage; - final String id; - final bool isAdmin; - - FamilyMember(this.email, this.usage, this.id, this.isAdmin); - - factory FamilyMember.fromMap(Map map) { - return FamilyMember( - (map['email'] ?? '') as String, - map['usage'] as int, - map['id'] as String, - map['isAdmin'] as bool, - ); - } -} -class ProfileData { - bool canDisableEmailMFA; - bool isEmailMFAEnabled; - bool isTwoFactorEnabled; - - // Constructor with default values - ProfileData({ - this.canDisableEmailMFA = false, - this.isEmailMFAEnabled = false, - this.isTwoFactorEnabled = false, - }); - - // Factory method to create ProfileData instance from JSON - factory ProfileData.fromJson(Map? json) { - if (json == null) null; - - return ProfileData( - canDisableEmailMFA: json!['canDisableEmailMFA'] ?? false, - isEmailMFAEnabled: json['isEmailMFAEnabled'] ?? false, - isTwoFactorEnabled: json['isTwoFactorEnabled'] ?? false, - ); - } - - // Method to convert ProfileData instance to JSON - Map toJson() { - return { - 'canDisableEmailMFA': canDisableEmailMFA, - 'isEmailMFAEnabled': isEmailMFAEnabled, - 'isTwoFactorEnabled': isTwoFactorEnabled, - }; - } - String toJsonString() => json.encode(toJson()); -} -class FamilyData { - final List? members; - - // Storage available based on the family plan - final int storage; - final int expiryTime; - - FamilyData(this.members, this.storage, this.expiryTime); - - int getTotalUsage() { - return members!.map((e) => e.usage).toList().sum; - } - - static fromMap(Map? map) { - if (map == null) return null; - assert(map['members'] != null && map['members'].length >= 0); - final members = List.from( - map['members'].map((x) => FamilyMember.fromMap(x)), - ); - return FamilyData( - members, - map['storage'] as int, - map['expiryTime'] as int, - ); - } -} diff --git a/mobile/apps/auth/lib/onboarding/view/onboarding_page.dart b/mobile/apps/auth/lib/onboarding/view/onboarding_page.dart index 0ce09dd45c..9037cf2652 100644 --- a/mobile/apps/auth/lib/onboarding/view/onboarding_page.dart +++ b/mobile/apps/auth/lib/onboarding/view/onboarding_page.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:ente_accounts/pages/email_entry_page.dart'; import 'package:ente_auth/app/view/app.dart'; import 'package:ente_auth/core/configuration.dart'; import 'package:ente_auth/ente_theme_data.dart'; @@ -8,7 +9,6 @@ import 'package:ente_auth/events/trigger_logout_event.dart'; import "package:ente_auth/l10n/l10n.dart"; import 'package:ente_auth/locale.dart'; import 'package:ente_auth/theme/text_style.dart'; -import 'package:ente_auth/ui/account/email_entry_page.dart'; import 'package:ente_auth/ui/account/login_page.dart'; import 'package:ente_auth/ui/account/logout_dialog.dart'; import 'package:ente_auth/ui/account/password_entry_page.dart'; @@ -260,7 +260,7 @@ class _OnboardingPageState extends State { void _navigateToSignUpPage() { Widget page; if (Configuration.instance.getEncryptedToken() == null) { - page = const EmailEntryPage(); + page = EmailEntryPage(Configuration.instance); } else { // No key if (Configuration.instance.getKeyAttributes() == null) { diff --git a/mobile/apps/auth/lib/services/billing_service.dart b/mobile/apps/auth/lib/services/billing_service.dart index 39929dc5aa..8aad05e5c7 100644 --- a/mobile/apps/auth/lib/services/billing_service.dart +++ b/mobile/apps/auth/lib/services/billing_service.dart @@ -1,10 +1,10 @@ import 'dart:io'; import 'package:dio/dio.dart'; +import 'package:ente_accounts/ente_accounts.dart'; import 'package:ente_auth/core/configuration.dart'; import 'package:ente_auth/core/errors.dart'; -import 'package:ente_auth/models/billing_plan.dart'; -import 'package:ente_auth/models/subscription.dart'; +import 'package:ente_auth/models/billing_plan.dart'; import 'package:ente_network/network.dart'; import 'package:logging/logging.dart'; diff --git a/mobile/apps/auth/lib/services/user_service.dart b/mobile/apps/auth/lib/services/user_service.dart index 2becb8e590..c79016b3d4 100644 --- a/mobile/apps/auth/lib/services/user_service.dart +++ b/mobile/apps/auth/lib/services/user_service.dart @@ -4,17 +4,19 @@ import "dart:math"; import 'package:bip39/bip39.dart' as bip39; import 'package:dio/dio.dart'; +import 'package:ente_accounts/models/delete_account.dart'; +import 'package:ente_accounts/models/sessions.dart'; +import 'package:ente_accounts/models/set_keys_request.dart'; +import 'package:ente_accounts/models/set_recovery_key_request.dart'; +import 'package:ente_accounts/models/two_factor.dart'; +import 'package:ente_accounts/models/user_details.dart'; +import 'package:ente_accounts/pages/two_factor_authentication_page.dart'; +import 'package:ente_accounts/pages/two_factor_recovery_page.dart'; import 'package:ente_auth/core/configuration.dart'; import 'package:ente_auth/core/constants.dart'; import 'package:ente_auth/core/errors.dart'; import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/account/two_factor.dart'; -import 'package:ente_auth/models/api/user/srp.dart'; -import 'package:ente_auth/models/delete_account.dart'; -import 'package:ente_auth/models/sessions.dart'; -import 'package:ente_auth/models/set_keys_request.dart'; -import 'package:ente_auth/models/set_recovery_key_request.dart'; -import 'package:ente_auth/models/user_details.dart'; +import 'package:ente_auth/models/api/user/srp.dart'; import 'package:ente_auth/ui/account/login_page.dart'; import 'package:ente_auth/ui/account/ott_verification_page.dart'; import 'package:ente_auth/ui/account/password_entry_page.dart'; @@ -23,8 +25,6 @@ import 'package:ente_auth/ui/account/recovery_page.dart'; import 'package:ente_auth/ui/common/progress_dialog.dart'; import 'package:ente_auth/ui/home_page.dart'; import 'package:ente_auth/ui/passkey_page.dart'; -import 'package:ente_auth/ui/two_factor_authentication_page.dart'; -import 'package:ente_auth/ui/two_factor_recovery_page.dart'; import 'package:ente_auth/utils/dialog_util.dart'; import 'package:ente_auth/utils/toast_util.dart'; import 'package:ente_base/models/key_attributes.dart'; diff --git a/mobile/apps/auth/lib/ui/account/change_email_dialog.dart b/mobile/apps/auth/lib/ui/account/change_email_dialog.dart deleted file mode 100644 index 5277e0fcb6..0000000000 --- a/mobile/apps/auth/lib/ui/account/change_email_dialog.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/services/user_service.dart'; -import 'package:ente_auth/utils/dialog_util.dart'; -import 'package:ente_auth/utils/email_util.dart'; -import 'package:flutter/material.dart'; - -class ChangeEmailDialog extends StatefulWidget { - const ChangeEmailDialog({super.key}); - - @override - State createState() => _ChangeEmailDialogState(); -} - -class _ChangeEmailDialogState extends State { - String _email = ""; - - @override - Widget build(BuildContext context) { - final l10n = context.l10n; - return AlertDialog( - title: Text(l10n.enterNewEmailHint), - content: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextFormField( - decoration: InputDecoration( - hintText: l10n.email, - hintStyle: const TextStyle( - color: Colors.white30, - ), - contentPadding: const EdgeInsets.all(12), - ), - onChanged: (value) { - setState(() { - _email = value; - }); - }, - autocorrect: false, - keyboardType: TextInputType.emailAddress, - initialValue: _email, - autofocus: true, - ), - ], - ), - ), - actions: [ - TextButton( - child: Text( - l10n.cancel, - style: const TextStyle( - color: Colors.redAccent, - ), - ), - onPressed: () { - Navigator.pop(context); - }, - ), - TextButton( - child: Text( - l10n.verify, - style: const TextStyle( - color: Colors.purple, - ), - ), - onPressed: () { - if (!isValidEmail(_email)) { - showErrorDialog( - context, - l10n.invalidEmailTitle, - l10n.invalidEmailMessage, - ); - return; - } - UserService.instance.sendOtt(context, _email, isChangeEmail: true); - }, - ), - ], - ); - } -} diff --git a/mobile/apps/auth/lib/ui/account/delete_account_page.dart b/mobile/apps/auth/lib/ui/account/delete_account_page.dart deleted file mode 100644 index d11b0ccaad..0000000000 --- a/mobile/apps/auth/lib/ui/account/delete_account_page.dart +++ /dev/null @@ -1,251 +0,0 @@ -import 'dart:convert'; - -import 'package:ente_auth/core/configuration.dart'; -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/delete_account.dart'; - import 'package:ente_auth/services/user_service.dart'; -import 'package:ente_auth/ui/common/dialogs.dart'; -import 'package:ente_auth/ui/common/gradient_button.dart'; -import 'package:ente_auth/utils/email_util.dart'; -import 'package:ente_auth/utils/platform_util.dart'; -import 'package:ente_crypto_dart/ente_crypto_dart.dart'; -import 'package:ente_lock_screen/local_authentication_service.dart'; -import 'package:flutter/material.dart'; - -class DeleteAccountPage extends StatelessWidget { - const DeleteAccountPage({ - super.key, - }); - - @override - Widget build(BuildContext context) { - final l10n = context.l10n; - return Scaffold( - appBar: AppBar( - elevation: 0, - title: Text(l10n.deleteAccount), - leading: IconButton( - icon: const Icon(Icons.arrow_back), - color: Theme.of(context).iconTheme.color, - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ), - body: Padding( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24), - child: Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Image.asset( - 'assets/broken_heart.png', - width: 200, - ), - const SizedBox( - height: 24, - ), - Center( - child: Text( - l10n.deleteAccountQuery, - style: Theme.of(context).textTheme.titleMedium, - ), - ), - const SizedBox( - height: 12, - ), - RichText( - // textAlign: TextAlign.center, - text: TextSpan( - children: const [ - TextSpan(text: "Please write to us at "), - TextSpan( - text: "feedback@ente.io", - style: TextStyle(color: Color.fromRGBO(29, 185, 84, 1)), - ), - TextSpan( - text: ", maybe there is a way we can help.", - ), - ], - style: Theme.of(context).textTheme.titleMedium, - ), - ), - const SizedBox( - height: 24, - ), - GradientButton( - text: l10n.yesSendFeedbackAction, - iconData: Icons.check, - onTap: () async { - await sendEmail( - context, - to: 'feedback@ente.io', - subject: '[Feedback]', - ); - }, - ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 8), - ), - InkWell( - child: SizedBox( - width: double.infinity, - child: OutlinedButton.icon( - style: OutlinedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - side: const BorderSide( - color: Colors.redAccent, - ), - padding: const EdgeInsets.symmetric( - vertical: 18, - horizontal: 10, - ), - backgroundColor: Colors.white, - ), - label: Text( - l10n.noDeleteAccountAction, - style: const TextStyle( - color: Colors.redAccent, // same for both themes - ), - textAlign: TextAlign.center, - ), - onPressed: () async => {await _initiateDelete(context)}, - icon: const Icon( - Icons.no_accounts, - color: Colors.redAccent, - ), - ), - ), - ), - ], - ), - ), - ), - ); - } - - Future _initiateDelete(BuildContext context) async { - final deleteChallengeResponse = - await UserService.instance.getDeleteChallenge(context); - if (deleteChallengeResponse == null) { - return; - } - if (deleteChallengeResponse.allowDelete) { - await _confirmAndDelete(context, deleteChallengeResponse); - } else { - await _requestEmailForDeletion(context); - } - } - - Future _confirmAndDelete( - BuildContext context, - DeleteChallengeResponse response, - ) async { - final l10n = context.l10n; - final hasAuthenticated = - await LocalAuthenticationService.instance.requestLocalAuthentication( - context, - l10n.initiateAccountDeleteTitle, - ); - - await PlatformUtil.refocusWindows(); - - if (hasAuthenticated) { - final choice = await showChoiceDialogOld( - context, - l10n.confirmAccountDeleteTitle, - l10n.confirmAccountDeleteMessage, - firstAction: l10n.cancel, - secondAction: l10n.delete, - firstActionColor: Theme.of(context).colorScheme.onSurface, - secondActionColor: Colors.red, - ); - if (choice != DialogUserChoice.secondChoice) { - return; - } - final decryptChallenge = CryptoUtil.openSealSync( - CryptoUtil.base642bin(response.encryptedChallenge), - CryptoUtil.base642bin( - Configuration.instance.getKeyAttributes()!.publicKey, - ), - Configuration.instance.getSecretKey()!, - ); - final challengeResponseStr = utf8.decode(decryptChallenge); - await UserService.instance.deleteAccount(context, challengeResponseStr); - } - } - - Future _requestEmailForDeletion(BuildContext context) async { - final l10n = context.l10n; - final AlertDialog alert = AlertDialog( - title: Text( - l10n.deleteAccount, - style: const TextStyle( - color: Colors.red, - ), - ), - content: RichText( - text: TextSpan( - children: [ - const TextSpan( - text: "Please send an email to ", - ), - TextSpan( - text: "account-deletion@ente.io", - style: TextStyle( - color: Colors.orange[300], - ), - ), - const TextSpan( - text: - " from your registered email address.\n\nYour request will be processed within 72 hours.", - ), - ], - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - height: 1.5, - fontSize: 16, - ), - ), - ), - actions: [ - TextButton( - child: Text( - l10n.sendEmail, - style: const TextStyle( - color: Colors.red, - ), - ), - onPressed: () async { - Navigator.of(context, rootNavigator: true).pop('dialog'); - await sendEmail( - context, - to: 'account-deletion@ente.io', - subject: '[Delete account]', - ); - }, - ), - TextButton( - child: Text( - l10n.ok, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - }, - ), - ], - ); - // ignore: unawaited_futures - showDialog( - context: context, - builder: (BuildContext context) { - return alert; - }, - ); - } -} diff --git a/mobile/apps/auth/lib/ui/account/email_entry_page.dart b/mobile/apps/auth/lib/ui/account/email_entry_page.dart index 2283f4ba09..24cc77cbce 100644 --- a/mobile/apps/auth/lib/ui/account/email_entry_page.dart +++ b/mobile/apps/auth/lib/ui/account/email_entry_page.dart @@ -1,516 +1,516 @@ -import 'package:email_validator/email_validator.dart'; -import 'package:ente_auth/core/configuration.dart'; -import 'package:ente_auth/ente_theme_data.dart'; -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/services/user_service.dart'; -import 'package:ente_auth/theme/ente_theme.dart'; -import 'package:ente_auth/ui/common/dynamic_fab.dart'; -import 'package:ente_auth/utils/platform_util.dart'; -import 'package:ente_auth/utils/toast_util.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:password_strength/password_strength.dart'; -import 'package:step_progress_indicator/step_progress_indicator.dart'; -import "package:styled_text/styled_text.dart"; +// import 'package:email_validator/email_validator.dart'; +// import 'package:ente_auth/core/configuration.dart'; +// import 'package:ente_auth/ente_theme_data.dart'; +// import 'package:ente_auth/l10n/l10n.dart'; +// import 'package:ente_auth/services/user_service.dart'; +// import 'package:ente_auth/theme/ente_theme.dart'; +// import 'package:ente_auth/ui/common/dynamic_fab.dart'; +// import 'package:ente_auth/utils/platform_util.dart'; +// import 'package:ente_auth/utils/toast_util.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter/services.dart'; +// import 'package:password_strength/password_strength.dart'; +// import 'package:step_progress_indicator/step_progress_indicator.dart'; +// import "package:styled_text/styled_text.dart"; -class EmailEntryPage extends StatefulWidget { - const EmailEntryPage({super.key}); +// class EmailEntryPage extends StatefulWidget { +// const EmailEntryPage({super.key}); - @override - State createState() => _EmailEntryPageState(); -} +// @override +// State createState() => _EmailEntryPageState(); +// } -class _EmailEntryPageState extends State { - static const kMildPasswordStrengthThreshold = 0.4; - static const kStrongPasswordStrengthThreshold = 0.7; +// class _EmailEntryPageState extends State { +// static const kMildPasswordStrengthThreshold = 0.4; +// static const kStrongPasswordStrengthThreshold = 0.7; - final _config = Configuration.instance; - final _passwordController1 = TextEditingController(); - final _passwordController2 = TextEditingController(); - final Color _validFieldValueColor = const Color.fromARGB(51, 157, 45, 194); +// final _config = Configuration.instance; +// final _passwordController1 = TextEditingController(); +// final _passwordController2 = TextEditingController(); +// final Color _validFieldValueColor = const Color.fromARGB(51, 157, 45, 194); - String? _email; - String? _password; - String _cnfPassword = ''; - String _referralSource = ''; - double _passwordStrength = 0.0; - bool _emailIsValid = false; - bool _hasAgreedToTOS = true; - bool _hasAgreedToE2E = false; - bool _password1Visible = false; - bool _password2Visible = false; - bool _passwordsMatch = false; +// String? _email; +// String? _password; +// String _cnfPassword = ''; +// String _referralSource = ''; +// double _passwordStrength = 0.0; +// bool _emailIsValid = false; +// bool _hasAgreedToTOS = true; +// bool _hasAgreedToE2E = false; +// bool _password1Visible = false; +// bool _password2Visible = false; +// bool _passwordsMatch = false; - final _password1FocusNode = FocusNode(); - final _password2FocusNode = FocusNode(); - bool _password1InFocus = false; - bool _password2InFocus = false; - bool _passwordIsValid = false; +// final _password1FocusNode = FocusNode(); +// final _password2FocusNode = FocusNode(); +// bool _password1InFocus = false; +// bool _password2InFocus = false; +// bool _passwordIsValid = false; - @override - void initState() { - _email = _config.getEmail(); - _password1FocusNode.addListener(() { - setState(() { - _password1InFocus = _password1FocusNode.hasFocus; - }); - }); - _password2FocusNode.addListener(() { - setState(() { - _password2InFocus = _password2FocusNode.hasFocus; - }); - }); - super.initState(); - } +// @override +// void initState() { +// _email = _config.getEmail(); +// _password1FocusNode.addListener(() { +// setState(() { +// _password1InFocus = _password1FocusNode.hasFocus; +// }); +// }); +// _password2FocusNode.addListener(() { +// setState(() { +// _password2InFocus = _password2FocusNode.hasFocus; +// }); +// }); +// super.initState(); +// } - @override - Widget build(BuildContext context) { - final isKeypadOpen = MediaQuery.of(context).viewInsets.bottom > 100; +// @override +// Widget build(BuildContext context) { +// final isKeypadOpen = MediaQuery.of(context).viewInsets.bottom > 100; - FloatingActionButtonLocation? fabLocation() { - if (isKeypadOpen) { - return null; - } else { - return FloatingActionButtonLocation.centerFloat; - } - } +// FloatingActionButtonLocation? fabLocation() { +// if (isKeypadOpen) { +// return null; +// } else { +// return FloatingActionButtonLocation.centerFloat; +// } +// } - final appBar = AppBar( - elevation: 0, - leading: IconButton( - icon: const Icon(Icons.arrow_back), - color: Theme.of(context).iconTheme.color, - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Material( - type: MaterialType.transparency, - child: StepProgressIndicator( - totalSteps: 4, - currentStep: 1, - selectedColor: Theme.of(context).colorScheme.alternativeColor, - roundedEdges: const Radius.circular(10), - unselectedColor: - Theme.of(context).colorScheme.stepProgressUnselectedColor, - ), - ), - ); - return Scaffold( - resizeToAvoidBottomInset: isKeypadOpen, - appBar: appBar, - body: _getBody(), - floatingActionButton: DynamicFAB( - isKeypadOpen: isKeypadOpen, - isFormValid: _isFormValid(), - buttonText: context.l10n.createAccount, - onPressedFunction: () { - UserService.instance.setEmail(_email!); - _config.setVolatilePassword(_passwordController1.text); - UserService.instance.setRefSource(_referralSource); - UserService.instance.sendOtt( - context, - _email!, - isCreateAccountScreen: true, - purpose: "signup", - ); - FocusScope.of(context).unfocus(); - }, - ), - floatingActionButtonLocation: fabLocation(), - floatingActionButtonAnimator: NoScalingAnimation(), - ); - } +// final appBar = AppBar( +// elevation: 0, +// leading: IconButton( +// icon: const Icon(Icons.arrow_back), +// color: Theme.of(context).iconTheme.color, +// onPressed: () { +// Navigator.of(context).pop(); +// }, +// ), +// title: Material( +// type: MaterialType.transparency, +// child: StepProgressIndicator( +// totalSteps: 4, +// currentStep: 1, +// selectedColor: Theme.of(context).colorScheme.alternativeColor, +// roundedEdges: const Radius.circular(10), +// unselectedColor: +// Theme.of(context).colorScheme.stepProgressUnselectedColor, +// ), +// ), +// ); +// return Scaffold( +// resizeToAvoidBottomInset: isKeypadOpen, +// appBar: appBar, +// body: _getBody(), +// floatingActionButton: DynamicFAB( +// isKeypadOpen: isKeypadOpen, +// isFormValid: _isFormValid(), +// buttonText: context.l10n.createAccount, +// onPressedFunction: () { +// UserService.instance.setEmail(_email!); +// _config.setVolatilePassword(_passwordController1.text); +// UserService.instance.setRefSource(_referralSource); +// UserService.instance.sendOtt( +// context, +// _email!, +// isCreateAccountScreen: true, +// purpose: "signup", +// ); +// FocusScope.of(context).unfocus(); +// }, +// ), +// floatingActionButtonLocation: fabLocation(), +// floatingActionButtonAnimator: NoScalingAnimation(), +// ); +// } - Widget _getBody() { - var passwordStrengthText = context.l10n.weakStrength; - var passwordStrengthColor = Colors.redAccent; - if (_passwordStrength > kStrongPasswordStrengthThreshold) { - passwordStrengthText = context.l10n.strongStrength; - passwordStrengthColor = Colors.greenAccent; - } else if (_passwordStrength > kMildPasswordStrengthThreshold) { - passwordStrengthText = context.l10n.moderateStrength; - passwordStrengthColor = Colors.orangeAccent; - } - return Column( - children: [ - Expanded( - child: AutofillGroup( - child: ListView( - children: [ - Padding( - padding: - const EdgeInsets.symmetric(vertical: 30, horizontal: 20), - child: Text( - context.l10n.createNewAccount, - style: Theme.of(context).textTheme.headlineMedium, - ), - ), - Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), - child: TextFormField( - style: Theme.of(context).textTheme.titleMedium, - autofillHints: const [AutofillHints.email], - decoration: InputDecoration( - fillColor: _emailIsValid ? _validFieldValueColor : null, - filled: true, - hintText: context.l10n.email, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 14, - ), - border: UnderlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(6), - ), - suffixIcon: _emailIsValid - ? Icon( - Icons.check, - size: 20, - color: Theme.of(context) - .inputDecorationTheme - .focusedBorder! - .borderSide - .color, - ) - : null, - ), - onChanged: (value) { - _email = value.trim(); - if (_emailIsValid != EmailValidator.validate(_email!)) { - setState(() { - _emailIsValid = EmailValidator.validate(_email!); - }); - } - }, - autocorrect: false, - keyboardType: TextInputType.emailAddress, - //initialValue: _email, - textInputAction: TextInputAction.next, - ), - ), - const Padding(padding: EdgeInsets.all(4)), - Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), - child: TextFormField( - keyboardType: TextInputType.text, - textInputAction: TextInputAction.next, - controller: _passwordController1, - obscureText: !_password1Visible, - enableSuggestions: true, - autofillHints: const [AutofillHints.newPassword], - decoration: InputDecoration( - fillColor: - _passwordIsValid ? _validFieldValueColor : null, - filled: true, - hintText: context.l10n.password, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 14, - ), - suffixIcon: _password1InFocus - ? IconButton( - icon: Icon( - _password1Visible - ? Icons.visibility - : Icons.visibility_off, - color: Theme.of(context).iconTheme.color, - size: 20, - ), - onPressed: () { - setState(() { - _password1Visible = !_password1Visible; - }); - }, - ) - : _passwordIsValid - ? Icon( - Icons.check, - color: Theme.of(context) - .inputDecorationTheme - .focusedBorder! - .borderSide - .color, - ) - : null, - border: UnderlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(6), - ), - ), - focusNode: _password1FocusNode, - onChanged: (password) { - if (password != _password) { - setState(() { - _password = password; - _passwordStrength = - estimatePasswordStrength(password); - _passwordIsValid = _passwordStrength >= - kMildPasswordStrengthThreshold; - _passwordsMatch = _password == _cnfPassword; - }); - } - }, - onEditingComplete: () { - _password1FocusNode.unfocus(); - _password2FocusNode.requestFocus(); - TextInput.finishAutofillContext(); - }, - ), - ), - const SizedBox(height: 8), - Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), - child: TextFormField( - keyboardType: TextInputType.visiblePassword, - controller: _passwordController2, - obscureText: !_password2Visible, - autofillHints: const [AutofillHints.newPassword], - onEditingComplete: () => TextInput.finishAutofillContext(), - decoration: InputDecoration( - fillColor: _passwordsMatch && _passwordIsValid - ? _validFieldValueColor - : null, - filled: true, - hintText: context.l10n.confirmPassword, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 14, - ), - suffixIcon: _password2InFocus - ? IconButton( - icon: Icon( - _password2Visible - ? Icons.visibility - : Icons.visibility_off, - color: Theme.of(context).iconTheme.color, - size: 20, - ), - onPressed: () { - setState(() { - _password2Visible = !_password2Visible; - }); - }, - ) - : _passwordsMatch - ? Icon( - Icons.check, - color: Theme.of(context) - .inputDecorationTheme - .focusedBorder! - .borderSide - .color, - ) - : null, - border: UnderlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(6), - ), - ), - focusNode: _password2FocusNode, - onChanged: (cnfPassword) { - setState(() { - _cnfPassword = cnfPassword; - if (_password != null || _password != '') { - _passwordsMatch = _password == _cnfPassword; - } - }); - }, - ), - ), - Opacity( - opacity: (_password != '') && _password1InFocus ? 1 : 0, - child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 24, vertical: 8), - child: Text( - context.l10n.passwordStrength(passwordStrengthText), - style: TextStyle( - color: passwordStrengthColor, - fontWeight: FontWeight.w500, - fontSize: 12, - ), - ), - ), - ), - const SizedBox(height: 4), - Padding( - padding: - const EdgeInsets.symmetric(vertical: 0, horizontal: 20), - child: Text( - context.l10n.hearUsWhereTitle, - style: getEnteTextTheme(context).smallFaint, - ), - ), - const SizedBox(height: 4), - Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), - child: TextFormField( - style: Theme.of(context).textTheme.titleMedium, - decoration: InputDecoration( - fillColor: null, - filled: true, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 14, - ), - border: UnderlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(6), - ), - suffixIcon: InkWell( - onTap: () { - showToast( - context, - context.l10n.hearUsExplanation, - ); - }, - child: Icon( - Icons.info_outline_rounded, - color: getEnteColorScheme(context).strokeMuted, - ), - ), - ), - onChanged: (value) { - _referralSource = value.trim(); - }, - autocorrect: false, - keyboardType: TextInputType.text, - textInputAction: TextInputAction.next, - ), - ), - const Divider(thickness: 1), - const SizedBox(height: 12), - _getAgreement(), - const SizedBox(height: 40), - ], - ), - ), - ), - ], - ); - } +// Widget _getBody() { +// var passwordStrengthText = context.l10n.weakStrength; +// var passwordStrengthColor = Colors.redAccent; +// if (_passwordStrength > kStrongPasswordStrengthThreshold) { +// passwordStrengthText = context.l10n.strongStrength; +// passwordStrengthColor = Colors.greenAccent; +// } else if (_passwordStrength > kMildPasswordStrengthThreshold) { +// passwordStrengthText = context.l10n.moderateStrength; +// passwordStrengthColor = Colors.orangeAccent; +// } +// return Column( +// children: [ +// Expanded( +// child: AutofillGroup( +// child: ListView( +// children: [ +// Padding( +// padding: +// const EdgeInsets.symmetric(vertical: 30, horizontal: 20), +// child: Text( +// context.l10n.createNewAccount, +// style: Theme.of(context).textTheme.headlineMedium, +// ), +// ), +// Padding( +// padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), +// child: TextFormField( +// style: Theme.of(context).textTheme.titleMedium, +// autofillHints: const [AutofillHints.email], +// decoration: InputDecoration( +// fillColor: _emailIsValid ? _validFieldValueColor : null, +// filled: true, +// hintText: context.l10n.email, +// contentPadding: const EdgeInsets.symmetric( +// horizontal: 16, +// vertical: 14, +// ), +// border: UnderlineInputBorder( +// borderSide: BorderSide.none, +// borderRadius: BorderRadius.circular(6), +// ), +// suffixIcon: _emailIsValid +// ? Icon( +// Icons.check, +// size: 20, +// color: Theme.of(context) +// .inputDecorationTheme +// .focusedBorder! +// .borderSide +// .color, +// ) +// : null, +// ), +// onChanged: (value) { +// _email = value.trim(); +// if (_emailIsValid != EmailValidator.validate(_email!)) { +// setState(() { +// _emailIsValid = EmailValidator.validate(_email!); +// }); +// } +// }, +// autocorrect: false, +// keyboardType: TextInputType.emailAddress, +// //initialValue: _email, +// textInputAction: TextInputAction.next, +// ), +// ), +// const Padding(padding: EdgeInsets.all(4)), +// Padding( +// padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), +// child: TextFormField( +// keyboardType: TextInputType.text, +// textInputAction: TextInputAction.next, +// controller: _passwordController1, +// obscureText: !_password1Visible, +// enableSuggestions: true, +// autofillHints: const [AutofillHints.newPassword], +// decoration: InputDecoration( +// fillColor: +// _passwordIsValid ? _validFieldValueColor : null, +// filled: true, +// hintText: context.l10n.password, +// contentPadding: const EdgeInsets.symmetric( +// horizontal: 16, +// vertical: 14, +// ), +// suffixIcon: _password1InFocus +// ? IconButton( +// icon: Icon( +// _password1Visible +// ? Icons.visibility +// : Icons.visibility_off, +// color: Theme.of(context).iconTheme.color, +// size: 20, +// ), +// onPressed: () { +// setState(() { +// _password1Visible = !_password1Visible; +// }); +// }, +// ) +// : _passwordIsValid +// ? Icon( +// Icons.check, +// color: Theme.of(context) +// .inputDecorationTheme +// .focusedBorder! +// .borderSide +// .color, +// ) +// : null, +// border: UnderlineInputBorder( +// borderSide: BorderSide.none, +// borderRadius: BorderRadius.circular(6), +// ), +// ), +// focusNode: _password1FocusNode, +// onChanged: (password) { +// if (password != _password) { +// setState(() { +// _password = password; +// _passwordStrength = +// estimatePasswordStrength(password); +// _passwordIsValid = _passwordStrength >= +// kMildPasswordStrengthThreshold; +// _passwordsMatch = _password == _cnfPassword; +// }); +// } +// }, +// onEditingComplete: () { +// _password1FocusNode.unfocus(); +// _password2FocusNode.requestFocus(); +// TextInput.finishAutofillContext(); +// }, +// ), +// ), +// const SizedBox(height: 8), +// Padding( +// padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), +// child: TextFormField( +// keyboardType: TextInputType.visiblePassword, +// controller: _passwordController2, +// obscureText: !_password2Visible, +// autofillHints: const [AutofillHints.newPassword], +// onEditingComplete: () => TextInput.finishAutofillContext(), +// decoration: InputDecoration( +// fillColor: _passwordsMatch && _passwordIsValid +// ? _validFieldValueColor +// : null, +// filled: true, +// hintText: context.l10n.confirmPassword, +// contentPadding: const EdgeInsets.symmetric( +// horizontal: 16, +// vertical: 14, +// ), +// suffixIcon: _password2InFocus +// ? IconButton( +// icon: Icon( +// _password2Visible +// ? Icons.visibility +// : Icons.visibility_off, +// color: Theme.of(context).iconTheme.color, +// size: 20, +// ), +// onPressed: () { +// setState(() { +// _password2Visible = !_password2Visible; +// }); +// }, +// ) +// : _passwordsMatch +// ? Icon( +// Icons.check, +// color: Theme.of(context) +// .inputDecorationTheme +// .focusedBorder! +// .borderSide +// .color, +// ) +// : null, +// border: UnderlineInputBorder( +// borderSide: BorderSide.none, +// borderRadius: BorderRadius.circular(6), +// ), +// ), +// focusNode: _password2FocusNode, +// onChanged: (cnfPassword) { +// setState(() { +// _cnfPassword = cnfPassword; +// if (_password != null || _password != '') { +// _passwordsMatch = _password == _cnfPassword; +// } +// }); +// }, +// ), +// ), +// Opacity( +// opacity: (_password != '') && _password1InFocus ? 1 : 0, +// child: Padding( +// padding: +// const EdgeInsets.symmetric(horizontal: 24, vertical: 8), +// child: Text( +// context.l10n.passwordStrength(passwordStrengthText), +// style: TextStyle( +// color: passwordStrengthColor, +// fontWeight: FontWeight.w500, +// fontSize: 12, +// ), +// ), +// ), +// ), +// const SizedBox(height: 4), +// Padding( +// padding: +// const EdgeInsets.symmetric(vertical: 0, horizontal: 20), +// child: Text( +// context.l10n.hearUsWhereTitle, +// style: getEnteTextTheme(context).smallFaint, +// ), +// ), +// const SizedBox(height: 4), +// Padding( +// padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), +// child: TextFormField( +// style: Theme.of(context).textTheme.titleMedium, +// decoration: InputDecoration( +// fillColor: null, +// filled: true, +// contentPadding: const EdgeInsets.symmetric( +// horizontal: 16, +// vertical: 14, +// ), +// border: UnderlineInputBorder( +// borderSide: BorderSide.none, +// borderRadius: BorderRadius.circular(6), +// ), +// suffixIcon: InkWell( +// onTap: () { +// showToast( +// context, +// context.l10n.hearUsExplanation, +// ); +// }, +// child: Icon( +// Icons.info_outline_rounded, +// color: getEnteColorScheme(context).strokeMuted, +// ), +// ), +// ), +// onChanged: (value) { +// _referralSource = value.trim(); +// }, +// autocorrect: false, +// keyboardType: TextInputType.text, +// textInputAction: TextInputAction.next, +// ), +// ), +// const Divider(thickness: 1), +// const SizedBox(height: 12), +// _getAgreement(), +// const SizedBox(height: 40), +// ], +// ), +// ), +// ), +// ], +// ); +// } - Container _getAgreement() { - return Container( - padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20), - child: Column( - children: [ - _getTOSAgreement(), - _getPasswordAgreement(), - ], - ), - ); - } +// Container _getAgreement() { +// return Container( +// padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20), +// child: Column( +// children: [ +// _getTOSAgreement(), +// _getPasswordAgreement(), +// ], +// ), +// ); +// } - Widget _getTOSAgreement() { - return GestureDetector( - onTap: () { - setState(() { - _hasAgreedToTOS = !_hasAgreedToTOS; - }); - }, - behavior: HitTestBehavior.translucent, - child: Row( - children: [ - Checkbox( - value: _hasAgreedToTOS, - side: CheckboxTheme.of(context).side, - onChanged: (value) { - setState(() { - _hasAgreedToTOS = value!; - }); - }, - ), - Expanded( - child: StyledText( - text: context.l10n.signUpTerms, - style: Theme.of(context) - .textTheme - .titleMedium! - .copyWith(fontSize: 12), - tags: { - 'u-terms': StyledTextActionTag( - (String? text, Map attrs) => - PlatformUtil.openWebView( - context, - context.l10n.termsOfServicesTitle, - "https://ente.io/terms", - ), - style: const TextStyle( - decoration: TextDecoration.underline, - ), - ), - 'u-policy': StyledTextActionTag( - (String? text, Map attrs) => - PlatformUtil.openWebView( - context, - context.l10n.privacyPolicyTitle, - "https://ente.io/privacy", - ), - style: const TextStyle( - decoration: TextDecoration.underline, - ), - ), - }, - ), - ), - ], - ), - ); - } +// Widget _getTOSAgreement() { +// return GestureDetector( +// onTap: () { +// setState(() { +// _hasAgreedToTOS = !_hasAgreedToTOS; +// }); +// }, +// behavior: HitTestBehavior.translucent, +// child: Row( +// children: [ +// Checkbox( +// value: _hasAgreedToTOS, +// side: CheckboxTheme.of(context).side, +// onChanged: (value) { +// setState(() { +// _hasAgreedToTOS = value!; +// }); +// }, +// ), +// Expanded( +// child: StyledText( +// text: context.l10n.signUpTerms, +// style: Theme.of(context) +// .textTheme +// .titleMedium! +// .copyWith(fontSize: 12), +// tags: { +// 'u-terms': StyledTextActionTag( +// (String? text, Map attrs) => +// PlatformUtil.openWebView( +// context, +// context.l10n.termsOfServicesTitle, +// "https://ente.io/terms", +// ), +// style: const TextStyle( +// decoration: TextDecoration.underline, +// ), +// ), +// 'u-policy': StyledTextActionTag( +// (String? text, Map attrs) => +// PlatformUtil.openWebView( +// context, +// context.l10n.privacyPolicyTitle, +// "https://ente.io/privacy", +// ), +// style: const TextStyle( +// decoration: TextDecoration.underline, +// ), +// ), +// }, +// ), +// ), +// ], +// ), +// ); +// } - Widget _getPasswordAgreement() { - return GestureDetector( - onTap: () { - setState(() { - _hasAgreedToE2E = !_hasAgreedToE2E; - }); - }, - behavior: HitTestBehavior.translucent, - child: Row( - children: [ - Checkbox( - value: _hasAgreedToE2E, - side: CheckboxTheme.of(context).side, - onChanged: (value) { - setState(() { - _hasAgreedToE2E = value!; - }); - }, - ), - Expanded( - child: StyledText( - text: context.l10n.ackPasswordLostWarning, - style: Theme.of(context) - .textTheme - .titleMedium! - .copyWith(fontSize: 12), - tags: { - 'underline': StyledTextActionTag( - (String? text, Map attrs) => - PlatformUtil.openWebView( - context, - context.l10n.encryption, - "https://ente.io/architecture", - ), - style: const TextStyle( - decoration: TextDecoration.underline, - ), - ), - }, - ), - ), - ], - ), - ); - } +// Widget _getPasswordAgreement() { +// return GestureDetector( +// onTap: () { +// setState(() { +// _hasAgreedToE2E = !_hasAgreedToE2E; +// }); +// }, +// behavior: HitTestBehavior.translucent, +// child: Row( +// children: [ +// Checkbox( +// value: _hasAgreedToE2E, +// side: CheckboxTheme.of(context).side, +// onChanged: (value) { +// setState(() { +// _hasAgreedToE2E = value!; +// }); +// }, +// ), +// Expanded( +// child: StyledText( +// text: context.l10n.ackPasswordLostWarning, +// style: Theme.of(context) +// .textTheme +// .titleMedium! +// .copyWith(fontSize: 12), +// tags: { +// 'underline': StyledTextActionTag( +// (String? text, Map attrs) => +// PlatformUtil.openWebView( +// context, +// context.l10n.encryption, +// "https://ente.io/architecture", +// ), +// style: const TextStyle( +// decoration: TextDecoration.underline, +// ), +// ), +// }, +// ), +// ), +// ], +// ), +// ); +// } - bool _isFormValid() { - return _emailIsValid && - _passwordsMatch && - _hasAgreedToTOS && - _hasAgreedToE2E && - _passwordIsValid; - } -} +// bool _isFormValid() { +// return _emailIsValid && +// _passwordsMatch && +// _hasAgreedToTOS && +// _hasAgreedToE2E && +// _passwordIsValid; +// } +// } diff --git a/mobile/apps/auth/lib/ui/account/sessions_page.dart b/mobile/apps/auth/lib/ui/account/sessions_page.dart deleted file mode 100644 index 1aae822af4..0000000000 --- a/mobile/apps/auth/lib/ui/account/sessions_page.dart +++ /dev/null @@ -1,228 +0,0 @@ -import 'package:ente_auth/core/configuration.dart'; -import 'package:ente_auth/ente_theme_data.dart'; -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/sessions.dart'; -import 'package:ente_auth/services/user_service.dart'; -import 'package:ente_auth/ui/common/loading_widget.dart'; -import 'package:ente_auth/utils/date_time_util.dart'; -import 'package:ente_auth/utils/dialog_util.dart'; -import 'package:ente_auth/utils/toast_util.dart'; -import 'package:flutter/material.dart'; -import 'package:logging/logging.dart'; - -class SessionsPage extends StatefulWidget { - const SessionsPage({super.key}); - - @override - State createState() => _SessionsPageState(); -} - -class _SessionsPageState extends State { - Sessions? _sessions; - final Logger _logger = Logger("SessionsPageState"); - - @override - void initState() { - _fetchActiveSessions().onError((error, stackTrace) { - showToast(context, "Failed to fetch active sessions"); - }); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - elevation: 0, - title: Text(context.l10n.activeSessions), - ), - body: _getBody(), - ); - } - - Widget _getBody() { - if (_sessions == null) { - return const Center(child: EnteLoadingWidget()); - } - final List rows = []; - rows.add(const Padding(padding: EdgeInsets.all(4))); - for (final session in _sessions!.sessions) { - rows.add(_getSessionWidget(session)); - } - return SingleChildScrollView( - child: Column( - children: rows, - ), - ); - } - - Widget _getSessionWidget(Session session) { - final lastUsedTime = - DateTime.fromMicrosecondsSinceEpoch(session.lastUsedTime); - return Column( - children: [ - InkWell( - onTap: () async { - _showSessionTerminationDialog(session); - }, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _getUAWidget(session), - const Padding(padding: EdgeInsets.all(4)), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Text( - session.ip, - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface - .withValues(alpha: 0.8), - fontSize: 14, - ), - ), - ), - const Padding(padding: EdgeInsets.all(8)), - Flexible( - child: Text( - getFormattedTime(lastUsedTime), - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface - .withValues(alpha: 0.8), - fontSize: 12, - ), - ), - ), - ], - ), - ], - ), - ), - ), - const Divider(), - ], - ); - } - - Future _terminateSession(Session session) async { - final dialog = createProgressDialog(context, context.l10n.pleaseWait); - await dialog.show(); - try { - await UserService.instance.terminateSession(session.token); - await _fetchActiveSessions(); - await dialog.hide(); - } catch (e) { - await dialog.hide(); - _logger.severe('failed to terminate'); - // ignore: unawaited_futures - showErrorDialog( - context, - context.l10n.oops, - context.l10n.somethingWentWrongPleaseTryAgain, - ); - } - } - - Future _fetchActiveSessions() async { - _sessions = await UserService.instance.getActiveSessions().onError((e, s) { - _logger.severe("failed to fetch active sessions", e, s); - throw e!; - }); - if (_sessions != null) { - _sessions!.sessions.sort((first, second) { - return second.lastUsedTime.compareTo(first.lastUsedTime); - }); - if (mounted) { - setState(() {}); - } - } - } - - void _showSessionTerminationDialog(Session session) { - final isLoggingOutFromThisDevice = - session.token == Configuration.instance.getToken(); - Widget text; - if (isLoggingOutFromThisDevice) { - text = Text( - context.l10n.thisWillLogYouOutOfThisDevice, - ); - } else { - text = SingleChildScrollView( - child: Column( - children: [ - Text( - context.l10n.thisWillLogYouOutOfTheFollowingDevice, - ), - const Padding(padding: EdgeInsets.all(8)), - Text( - session.ua, - style: Theme.of(context).textTheme.bodySmall, - ), - ], - ), - ); - } - final AlertDialog alert = AlertDialog( - title: Text(context.l10n.terminateSession), - content: text, - actions: [ - TextButton( - child: Text( - context.l10n.terminate, - style: const TextStyle( - color: Colors.red, - ), - ), - onPressed: () async { - Navigator.of(context, rootNavigator: true).pop('dialog'); - if (isLoggingOutFromThisDevice) { - await UserService.instance.logout(context); - } else { - await _terminateSession(session); - } - }, - ), - TextButton( - child: Text( - context.l10n.cancel, - style: TextStyle( - color: isLoggingOutFromThisDevice - ? Theme.of(context).colorScheme.alternativeColor - : Theme.of(context).colorScheme.defaultTextColor, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - }, - ), - ], - ); - - showDialog( - context: context, - builder: (BuildContext context) { - return alert; - }, - ); - } - - Widget _getUAWidget(Session session) { - if (session.token == Configuration.instance.getToken()) { - return Text( - context.l10n.thisDevice, - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.alternativeColor, - ), - ); - } - return Text(session.prettyUA); - } -} diff --git a/mobile/apps/auth/lib/ui/common/dialogs.dart b/mobile/apps/auth/lib/ui/common/dialogs.dart index 60879335e5..4f76bcf7c1 100644 --- a/mobile/apps/auth/lib/ui/common/dialogs.dart +++ b/mobile/apps/auth/lib/ui/common/dialogs.dart @@ -1,9 +1,9 @@ -import 'package:ente_auth/ente_theme_data.dart'; -import 'package:ente_auth/models/typedefs.dart'; +import 'package:ente_auth/ente_theme_data.dart'; import 'package:ente_auth/ui/components/buttons/button_widget.dart'; import 'package:ente_auth/ui/components/dialog_widget.dart'; import 'package:ente_auth/ui/components/models/button_result.dart'; import 'package:ente_auth/ui/components/models/button_type.dart'; +import 'package:ente_base/typedefs.dart'; import 'package:flutter/material.dart'; enum DialogUserChoice { firstChoice, secondChoice } diff --git a/mobile/apps/auth/lib/ui/components/buttons/button_widget.dart b/mobile/apps/auth/lib/ui/components/buttons/button_widget.dart index 9e589cd7a0..10abb5c39f 100644 --- a/mobile/apps/auth/lib/ui/components/buttons/button_widget.dart +++ b/mobile/apps/auth/lib/ui/components/buttons/button_widget.dart @@ -1,5 +1,4 @@ -import 'package:ente_auth/models/execution_states.dart'; -import 'package:ente_auth/models/typedefs.dart'; +import 'package:ente_auth/models/execution_states.dart'; import 'package:ente_auth/theme/colors.dart'; import 'package:ente_auth/theme/ente_theme.dart'; import 'package:ente_auth/theme/text_style.dart'; @@ -9,6 +8,7 @@ import 'package:ente_auth/ui/components/models/button_type.dart'; import 'package:ente_auth/ui/components/models/custom_button_style.dart'; import 'package:ente_auth/utils/debouncer.dart'; import "package:ente_auth/utils/dialog_util.dart"; +import 'package:ente_base/typedefs.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; diff --git a/mobile/apps/auth/lib/ui/components/dialog_widget.dart b/mobile/apps/auth/lib/ui/components/dialog_widget.dart index bebd5c9f42..8b8b417074 100644 --- a/mobile/apps/auth/lib/ui/components/dialog_widget.dart +++ b/mobile/apps/auth/lib/ui/components/dialog_widget.dart @@ -1,7 +1,6 @@ import 'dart:math'; -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/typedefs.dart'; +import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/theme/colors.dart'; import 'package:ente_auth/theme/effects.dart'; import 'package:ente_auth/theme/ente_theme.dart'; @@ -11,6 +10,7 @@ import 'package:ente_auth/ui/components/models/button_result.dart'; import 'package:ente_auth/ui/components/models/button_type.dart'; import 'package:ente_auth/ui/components/separators.dart'; import 'package:ente_auth/ui/components/text_input_widget.dart'; +import 'package:ente_base/typedefs.dart'; import 'package:flutter/material.dart'; ///Will return null if dismissed by tapping outside diff --git a/mobile/apps/auth/lib/ui/components/menu_item_widget.dart b/mobile/apps/auth/lib/ui/components/menu_item_widget.dart index f5d6e9dff7..ced35b51e1 100644 --- a/mobile/apps/auth/lib/ui/components/menu_item_widget.dart +++ b/mobile/apps/auth/lib/ui/components/menu_item_widget.dart @@ -1,8 +1,8 @@ -import 'package:ente_auth/models/execution_states.dart'; -import 'package:ente_auth/models/typedefs.dart'; +import 'package:ente_auth/models/execution_states.dart'; import 'package:ente_auth/theme/ente_theme.dart'; import 'package:ente_auth/ui/components/menu_item_child_widgets.dart'; import 'package:ente_auth/utils/debouncer.dart'; +import 'package:ente_base/typedefs.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/material.dart'; diff --git a/mobile/apps/auth/lib/ui/components/text_input_widget.dart b/mobile/apps/auth/lib/ui/components/text_input_widget.dart index 2a06d3b71a..65c8b7fd11 100644 --- a/mobile/apps/auth/lib/ui/components/text_input_widget.dart +++ b/mobile/apps/auth/lib/ui/components/text_input_widget.dart @@ -1,9 +1,9 @@ -import 'package:ente_auth/models/execution_states.dart'; -import 'package:ente_auth/models/typedefs.dart'; +import 'package:ente_auth/models/execution_states.dart'; import 'package:ente_auth/theme/ente_theme.dart'; import 'package:ente_auth/ui/common/loading_widget.dart'; import 'package:ente_auth/ui/components/separators.dart'; import 'package:ente_auth/utils/debouncer.dart'; +import 'package:ente_base/typedefs.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:logging/logging.dart'; diff --git a/mobile/apps/auth/lib/ui/components/toggle_switch_widget.dart b/mobile/apps/auth/lib/ui/components/toggle_switch_widget.dart index dc1ca06c92..d9378d7f8a 100644 --- a/mobile/apps/auth/lib/ui/components/toggle_switch_widget.dart +++ b/mobile/apps/auth/lib/ui/components/toggle_switch_widget.dart @@ -1,9 +1,9 @@ import 'package:ente_auth/ente_theme_data.dart'; -import 'package:ente_auth/models/execution_states.dart'; -import 'package:ente_auth/models/typedefs.dart'; +import 'package:ente_auth/models/execution_states.dart'; import 'package:ente_auth/theme/colors.dart'; import 'package:ente_auth/ui/common/loading_widget.dart'; import 'package:ente_auth/utils/debouncer.dart'; +import 'package:ente_base/typedefs.dart'; import 'package:flutter/material.dart'; typedef OnChangedCallBack = void Function(bool); diff --git a/mobile/apps/auth/lib/ui/passkey_page.dart b/mobile/apps/auth/lib/ui/passkey_page.dart index 906d2122df..d4b37c615b 100644 --- a/mobile/apps/auth/lib/ui/passkey_page.dart +++ b/mobile/apps/auth/lib/ui/passkey_page.dart @@ -1,14 +1,14 @@ import 'dart:convert'; import 'package:app_links/app_links.dart'; +import 'package:ente_accounts/models/two_factor.dart'; +import 'package:ente_accounts/pages/two_factor_authentication_page.dart'; import 'package:ente_auth/core/configuration.dart'; import 'package:ente_auth/core/errors.dart'; import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/account/two_factor.dart'; import 'package:ente_auth/services/user_service.dart'; import 'package:ente_auth/ui/components/buttons/button_widget.dart'; import 'package:ente_auth/ui/components/models/button_type.dart'; -import 'package:ente_auth/ui/two_factor_authentication_page.dart'; import 'package:ente_auth/utils/dialog_util.dart'; import 'package:ente_auth/utils/navigation_util.dart'; import 'package:ente_auth/utils/toast_util.dart'; diff --git a/mobile/apps/auth/lib/ui/settings/account_section_widget.dart b/mobile/apps/auth/lib/ui/settings/account_section_widget.dart index 450f400290..8c64197fba 100644 --- a/mobile/apps/auth/lib/ui/settings/account_section_widget.dart +++ b/mobile/apps/auth/lib/ui/settings/account_section_widget.dart @@ -1,9 +1,9 @@ +import 'package:ente_accounts/pages/change_email_dialog.dart'; +import 'package:ente_accounts/pages/delete_account_page.dart'; import 'package:ente_auth/core/configuration.dart'; -import 'package:ente_auth/l10n/l10n.dart'; +import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/services/user_service.dart'; import 'package:ente_auth/theme/ente_theme.dart'; -import 'package:ente_auth/ui/account/change_email_dialog.dart'; -import 'package:ente_auth/ui/account/delete_account_page.dart'; import 'package:ente_auth/ui/account/password_entry_page.dart'; import 'package:ente_auth/ui/account/recovery_key_page.dart'; import 'package:ente_auth/ui/components/captioned_text_widget.dart'; @@ -151,8 +151,9 @@ class AccountSectionWidget extends StatelessWidget { trailingIcon: Icons.chevron_right_outlined, trailingIconIsMuted: true, onTap: () async { + final config = Configuration.instance; // ignore: unawaited_futures - routeToPage(context, const DeleteAccountPage()); + routeToPage(context, DeleteAccountPage(config)); }, ), sectionOptionSpacing, diff --git a/mobile/apps/auth/lib/ui/settings/notification_banner_widget.dart b/mobile/apps/auth/lib/ui/settings/notification_banner_widget.dart index 1c30dd2bbc..6c5bcd168d 100644 --- a/mobile/apps/auth/lib/ui/settings/notification_banner_widget.dart +++ b/mobile/apps/auth/lib/ui/settings/notification_banner_widget.dart @@ -1,8 +1,8 @@ import 'dart:io'; +import 'package:ente_accounts/models/user_details.dart'; import 'package:ente_auth/core/configuration.dart'; -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/user_details.dart'; +import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/services/preference_service.dart'; import 'package:ente_auth/services/user_service.dart'; import 'package:ente_auth/ui/components/banner_widget.dart'; diff --git a/mobile/apps/auth/lib/ui/settings/security_section_widget.dart b/mobile/apps/auth/lib/ui/settings/security_section_widget.dart index 1053e68b41..9fa7d06b54 100644 --- a/mobile/apps/auth/lib/ui/settings/security_section_widget.dart +++ b/mobile/apps/auth/lib/ui/settings/security_section_widget.dart @@ -1,22 +1,22 @@ import 'dart:async'; import 'dart:typed_data'; +import 'package:ente_accounts/models/user_details.dart'; +import 'package:ente_accounts/pages/sessions_page.dart'; import 'package:ente_auth/core/configuration.dart'; import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/user_details.dart'; import 'package:ente_auth/services/passkey_service.dart'; import 'package:ente_auth/services/user_service.dart'; import 'package:ente_auth/theme/ente_theme.dart'; import 'package:ente_auth/ui/account/request_pwd_verification_page.dart'; -import 'package:ente_auth/ui/account/sessions_page.dart'; import 'package:ente_auth/ui/components/buttons/button_widget.dart'; import 'package:ente_auth/ui/components/captioned_text_widget.dart'; import 'package:ente_auth/ui/components/expandable_menu_item_widget.dart'; import 'package:ente_auth/ui/components/menu_item_widget.dart'; import 'package:ente_auth/ui/components/models/button_result.dart'; import 'package:ente_auth/ui/components/toggle_switch_widget.dart'; -import 'package:ente_auth/ui/settings/common_settings.dart'; -import 'package:ente_auth/utils/dialog_util.dart'; +import 'package:ente_auth/ui/settings/common_settings.dart'; +import 'package:ente_auth/utils/dialog_util.dart'; import 'package:ente_auth/utils/navigation_util.dart'; import 'package:ente_auth/utils/platform_util.dart'; import 'package:ente_auth/utils/toast_util.dart'; @@ -128,7 +128,7 @@ class _SecuritySectionWidgetState extends State { Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) { - return const SessionsPage(); + return SessionsPage(Configuration.instance); }, ), ); diff --git a/mobile/apps/auth/lib/ui/two_factor_authentication_page.dart b/mobile/apps/auth/lib/ui/two_factor_authentication_page.dart deleted file mode 100644 index 86dfa503e9..0000000000 --- a/mobile/apps/auth/lib/ui/two_factor_authentication_page.dart +++ /dev/null @@ -1,161 +0,0 @@ -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/account/two_factor.dart'; -import 'package:ente_auth/services/user_service.dart'; -import 'package:ente_auth/ui/lifecycle_event_handler.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:pinput/pinput.dart'; - -class TwoFactorAuthenticationPage extends StatefulWidget { - final String sessionID; - - const TwoFactorAuthenticationPage(this.sessionID, {super.key}); - - @override - State createState() => - _TwoFactorAuthenticationPageState(); -} - -class _TwoFactorAuthenticationPageState - extends State { - final _pinController = TextEditingController(); - final _pinPutDecoration = PinTheme( - height: 45, - width: 45, - decoration: BoxDecoration( - border: Border.all(color: const Color.fromRGBO(45, 194, 98, 1.0)), - borderRadius: BorderRadius.circular(15.0), - ), - ); - String _code = ""; - late LifecycleEventHandler _lifecycleEventHandler; - - @override - void initState() { - _lifecycleEventHandler = LifecycleEventHandler( - resumeCallBack: () async { - if (mounted) { - final data = await Clipboard.getData(Clipboard.kTextPlain); - if (data != null && data.text != null && data.text!.length == 6) { - _pinController.text = data.text!; - } - } - }, - ); - WidgetsBinding.instance.addObserver(_lifecycleEventHandler); - super.initState(); - } - - @override - void dispose() { - WidgetsBinding.instance.removeObserver(_lifecycleEventHandler); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final l10n = context.l10n; - return Scaffold( - appBar: AppBar( - title: Text( - l10n.twoFactorAuthTitle, - ), - ), - body: _getBody(), - ); - } - - Widget _getBody() { - final l10n = context.l10n; - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - Text( - l10n.enterCodeHint, - style: const TextStyle( - height: 1.4, - fontSize: 16, - ), - textAlign: TextAlign.center, - ), - const Padding(padding: EdgeInsets.all(32)), - Padding( - padding: const EdgeInsets.fromLTRB(40, 0, 40, 0), - child: Pinput( - length: 6, - onCompleted: (String code) { - _verifyTwoFactorCode(code); - }, - onChanged: (String pin) { - setState(() { - _code = pin; - }); - }, - controller: _pinController, - submittedPinTheme: _pinPutDecoration.copyWith( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20.0), - border: Border.all( - color: const Color.fromRGBO(45, 194, 98, 0.5), - ), - ), - ), - defaultPinTheme: _pinPutDecoration, - followingPinTheme: _pinPutDecoration.copyWith( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10.0), - border: Border.all( - color: const Color.fromRGBO(45, 194, 98, 0.5), - ), - ), - ), - autofocus: true, - ), - ), - const Padding(padding: EdgeInsets.all(24)), - Container( - padding: const EdgeInsets.fromLTRB(80, 0, 80, 0), - width: double.infinity, - height: 64, - child: OutlinedButton( - onPressed: _code.length == 6 - ? () async { - await _verifyTwoFactorCode(_code); - } - : null, - child: Text(l10n.verify), - ), - ), - const Padding(padding: EdgeInsets.all(30)), - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () { - UserService.instance.recoverTwoFactor( - context, - widget.sessionID, - TwoFactorType.totp, - ); - }, - child: Container( - padding: const EdgeInsets.all(10), - child: Center( - child: Text( - l10n.lostDeviceTitle, - style: const TextStyle( - decoration: TextDecoration.underline, - fontSize: 12, - ), - ), - ), - ), - ), - ], - ); - } - - Future _verifyTwoFactorCode(String code) async { - await UserService.instance.verifyTwoFactor(context, widget.sessionID, code); - } -} diff --git a/mobile/apps/auth/lib/ui/two_factor_recovery_page.dart b/mobile/apps/auth/lib/ui/two_factor_recovery_page.dart deleted file mode 100644 index a00245471f..0000000000 --- a/mobile/apps/auth/lib/ui/two_factor_recovery_page.dart +++ /dev/null @@ -1,113 +0,0 @@ -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/account/two_factor.dart'; -import 'package:ente_auth/services/user_service.dart'; -import 'package:ente_auth/theme/ente_theme.dart'; -import 'package:ente_auth/utils/email_util.dart'; -import 'package:flutter/material.dart'; - -class TwoFactorRecoveryPage extends StatefulWidget { - final String sessionID; - final String encryptedSecret; - final String secretDecryptionNonce; - final TwoFactorType type; - - const TwoFactorRecoveryPage( - this.type, - this.sessionID, - this.encryptedSecret, - this.secretDecryptionNonce, { - super.key, - }); - - @override - State createState() => _TwoFactorRecoveryPageState(); -} - -class _TwoFactorRecoveryPageState extends State { - final _recoveryKey = TextEditingController(); - - @override - Widget build(BuildContext context) { - final l10n = context.l10n; - return Scaffold( - appBar: AppBar( - title: Text( - l10n.recoverAccount, - style: const TextStyle( - fontSize: 18, - ), - ), - ), - body: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(60, 0, 60, 0), - child: TextFormField( - decoration: InputDecoration( - hintText: l10n.enterRecoveryKeyHint, - contentPadding: const EdgeInsets.all(20), - ), - style: const TextStyle( - fontSize: 14, - fontFeatures: [FontFeature.tabularFigures()], - ), - controller: _recoveryKey, - autofocus: false, - autocorrect: false, - keyboardType: TextInputType.multiline, - maxLines: null, - onChanged: (_) { - setState(() {}); - }, - ), - ), - const Padding(padding: EdgeInsets.all(24)), - Container( - padding: const EdgeInsets.fromLTRB(80, 0, 80, 0), - width: double.infinity, - height: 64, - child: OutlinedButton( - onPressed: _recoveryKey.text.isNotEmpty - ? () async { - await UserService.instance.removeTwoFactor( - context, - widget.type, - widget.sessionID, - _recoveryKey.text, - widget.encryptedSecret, - widget.secretDecryptionNonce, - ); - } - : null, - child: Text(l10n.recover), - ), - ), - GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () async { - await openSupportPage(null, null); - }, - child: Container( - padding: const EdgeInsets.all(40), - child: Center( - child: Text( - l10n.noRecoveryKeyTitle, - style: TextStyle( - decoration: TextDecoration.underline, - fontSize: 12, - color: getEnteColorScheme(context) - .textBase - .withValues(alpha: 0.9), - ), - ), - ), - ), - ), - ], - ), - ); - } -} diff --git a/mobile/apps/auth/lib/utils/dialog_util.dart b/mobile/apps/auth/lib/utils/dialog_util.dart index dca3b9d1f9..538c0835cd 100644 --- a/mobile/apps/auth/lib/utils/dialog_util.dart +++ b/mobile/apps/auth/lib/utils/dialog_util.dart @@ -3,8 +3,7 @@ import 'dart:math'; import 'package:confetti/confetti.dart'; import "package:dio/dio.dart"; -import 'package:ente_auth/l10n/l10n.dart'; -import 'package:ente_auth/models/typedefs.dart'; +import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/theme/colors.dart'; import 'package:ente_auth/ui/common/loading_widget.dart'; import 'package:ente_auth/ui/common/progress_dialog.dart'; @@ -16,6 +15,7 @@ import 'package:ente_auth/ui/components/models/button_result.dart'; import 'package:ente_auth/ui/components/models/button_type.dart'; import 'package:ente_auth/utils/email_util.dart'; import 'package:ente_auth/utils/platform_util.dart'; +import 'package:ente_base/typedefs.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/mobile/packages/accounts/pubspec.lock b/mobile/packages/accounts/pubspec.lock index 1dd9150ce5..bca81b2cd0 100644 --- a/mobile/packages/accounts/pubspec.lock +++ b/mobile/packages/accounts/pubspec.lock @@ -337,19 +337,21 @@ packages: flutter_inappwebview: dependency: transitive description: - name: flutter_inappwebview - sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5" - url: "https://pub.dev" - source: hosted - version: "6.1.5" + path: flutter_inappwebview + ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + url: "https://github.com/pichillilorenzo/flutter_inappwebview.git" + source: git + version: "6.2.0-beta.3" flutter_inappwebview_android: dependency: transitive description: - name: flutter_inappwebview_android - sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba" - url: "https://pub.dev" - source: hosted - version: "1.1.3" + path: flutter_inappwebview_android + ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + url: "https://github.com/pichillilorenzo/flutter_inappwebview.git" + source: git + version: "1.2.0-beta.3" flutter_inappwebview_internal_annotations: dependency: transitive description: @@ -361,43 +363,48 @@ packages: flutter_inappwebview_ios: dependency: transitive description: - name: flutter_inappwebview_ios - sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d" - url: "https://pub.dev" - source: hosted - version: "1.1.2" + path: flutter_inappwebview_ios + ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + url: "https://github.com/pichillilorenzo/flutter_inappwebview.git" + source: git + version: "1.2.0-beta.3" flutter_inappwebview_macos: dependency: transitive description: - name: flutter_inappwebview_macos - sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1 - url: "https://pub.dev" - source: hosted - version: "1.1.2" + path: flutter_inappwebview_macos + ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + url: "https://github.com/pichillilorenzo/flutter_inappwebview.git" + source: git + version: "1.2.0-beta.3" flutter_inappwebview_platform_interface: dependency: transitive description: - name: flutter_inappwebview_platform_interface - sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500 - url: "https://pub.dev" - source: hosted - version: "1.3.0+1" + path: flutter_inappwebview_platform_interface + ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + url: "https://github.com/pichillilorenzo/flutter_inappwebview.git" + source: git + version: "1.4.0-beta.3" flutter_inappwebview_web: dependency: transitive description: - name: flutter_inappwebview_web - sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598" - url: "https://pub.dev" - source: hosted - version: "1.1.2" + path: flutter_inappwebview_web + ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + url: "https://github.com/pichillilorenzo/flutter_inappwebview.git" + source: git + version: "1.2.0-beta.3" flutter_inappwebview_windows: dependency: transitive description: - name: flutter_inappwebview_windows - sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055" - url: "https://pub.dev" - source: hosted - version: "0.6.0" + path: flutter_inappwebview_windows + ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + resolved-ref: "3e6c4c4a25340cd363af9d38891d88498b90be26" + url: "https://github.com/pichillilorenzo/flutter_inappwebview.git" + source: git + version: "0.7.0-beta.3" flutter_lints: dependency: "direct dev" description: