l10n: Extract strings [Part-1] (#955)
This commit is contained in:
commit
f3e2c2d962
|
@ -20,18 +20,260 @@ typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
|
|||
class MessageLookup extends MessageLookupByLibrary {
|
||||
String get localeName => 'en';
|
||||
|
||||
static String m0(user) =>
|
||||
"${user} will not be able to add more photos to this album\n\nThey will still be able to remove existing photos added by them";
|
||||
|
||||
static String m1(supportEmail) =>
|
||||
"Please drop an email to ${supportEmail} from your registered email address";
|
||||
|
||||
static String m2(passwordStrengthValue) =>
|
||||
"Password strength: ${passwordStrengthValue}";
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||
"accountWelcomeBack":
|
||||
MessageLookupByLibrary.simpleMessage("Welcome back!"),
|
||||
"ackPasswordLostWarningPart1": MessageLookupByLibrary.simpleMessage(
|
||||
"I understand that if I lose my password, I may lose my data since my data is "),
|
||||
"ackPasswordLostWarningPart2":
|
||||
MessageLookupByLibrary.simpleMessage(" with ente"),
|
||||
"activeSessions":
|
||||
MessageLookupByLibrary.simpleMessage("Active sessions"),
|
||||
"addANewEmail": MessageLookupByLibrary.simpleMessage("Add a new email"),
|
||||
"addCollaborator":
|
||||
MessageLookupByLibrary.simpleMessage("Add collaborator"),
|
||||
"addMore": MessageLookupByLibrary.simpleMessage("Add more"),
|
||||
"addViewer": MessageLookupByLibrary.simpleMessage("Add viewer"),
|
||||
"addedAs": MessageLookupByLibrary.simpleMessage("Added as"),
|
||||
"albumOwner": MessageLookupByLibrary.simpleMessage("Owner"),
|
||||
"and": MessageLookupByLibrary.simpleMessage("and"),
|
||||
"askDeleteReason": MessageLookupByLibrary.simpleMessage(
|
||||
"What is the main reason you are deleting your account?"),
|
||||
"byClickingLogInIAgreeToThe": MessageLookupByLibrary.simpleMessage(
|
||||
"By clicking log in, I agree to the"),
|
||||
"cancel": MessageLookupByLibrary.simpleMessage("Cancel"),
|
||||
"cannotAddMorePhotosAfterBecomingViewer": m0,
|
||||
"changeEmail": MessageLookupByLibrary.simpleMessage("Change email"),
|
||||
"changePasswordTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Change password"),
|
||||
"changePermissions":
|
||||
MessageLookupByLibrary.simpleMessage("Change permissions?"),
|
||||
"checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage(
|
||||
"Please check your inbox (and spam) to complete verification"),
|
||||
"codeCopiedToClipboard":
|
||||
MessageLookupByLibrary.simpleMessage("Code copied to clipboard"),
|
||||
"collaborator": MessageLookupByLibrary.simpleMessage("Collaborator"),
|
||||
"collaboratorsCanAddPhotosAndVideosToTheSharedAlbum":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Collaborators can add photos and videos to the shared album."),
|
||||
"confirm": MessageLookupByLibrary.simpleMessage("Confirm"),
|
||||
"confirmAccountDeletion":
|
||||
MessageLookupByLibrary.simpleMessage("Confirm Account Deletion"),
|
||||
"confirmDeletePrompt": MessageLookupByLibrary.simpleMessage(
|
||||
"Yes, I want to permanently delete this account and all its data."),
|
||||
"confirmPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Confirm password"),
|
||||
"confirmRecoveryKey":
|
||||
MessageLookupByLibrary.simpleMessage("Confirm recovery key"),
|
||||
"confirmYourRecoveryKey":
|
||||
MessageLookupByLibrary.simpleMessage("Confirm your recovery key"),
|
||||
"contactSupport":
|
||||
MessageLookupByLibrary.simpleMessage("Contact support"),
|
||||
"continueLabel": MessageLookupByLibrary.simpleMessage("Continue"),
|
||||
"copypasteThisCodentoYourAuthenticatorApp":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Copy-paste this code\nto your authenticator app"),
|
||||
"createAccount": MessageLookupByLibrary.simpleMessage("Create account"),
|
||||
"createNewAccount":
|
||||
MessageLookupByLibrary.simpleMessage("Create new account"),
|
||||
"decrypting": MessageLookupByLibrary.simpleMessage("Decrypting..."),
|
||||
"deleteAccount": MessageLookupByLibrary.simpleMessage("Delete account"),
|
||||
"deleteAccountFeedbackPrompt": MessageLookupByLibrary.simpleMessage(
|
||||
"We are sorry to see you go. Please share your feedback to help us improve."),
|
||||
"deleteAccountPermanentlyButton":
|
||||
MessageLookupByLibrary.simpleMessage("Delete Account Permanently"),
|
||||
"deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage(
|
||||
"You are about to permanently delete your account and all its data.\nThis action is irreversible."),
|
||||
"deleteReason1": MessageLookupByLibrary.simpleMessage(
|
||||
"It’s missing a key feature that I need"),
|
||||
"deleteReason2": MessageLookupByLibrary.simpleMessage(
|
||||
"The app or a certain feature does not \nbehave as I think it should"),
|
||||
"deleteReason3": MessageLookupByLibrary.simpleMessage(
|
||||
"I found another service that I like better"),
|
||||
"deleteReason4":
|
||||
MessageLookupByLibrary.simpleMessage("My reason isn’t listed"),
|
||||
"deleteRequestSLAText": MessageLookupByLibrary.simpleMessage(
|
||||
"Your request will be processed within 72 hours."),
|
||||
"doThisLater": MessageLookupByLibrary.simpleMessage("Do this later"),
|
||||
"dropSupportEmail": m1,
|
||||
"email": MessageLookupByLibrary.simpleMessage("Email"),
|
||||
"encryption": MessageLookupByLibrary.simpleMessage("Encryption"),
|
||||
"encryptionKeys":
|
||||
MessageLookupByLibrary.simpleMessage("Encryption keys"),
|
||||
"endToEndEncrypted":
|
||||
MessageLookupByLibrary.simpleMessage("end-to-end encrypted"),
|
||||
"enterCode": MessageLookupByLibrary.simpleMessage("Enter code"),
|
||||
"enterEmail": MessageLookupByLibrary.simpleMessage("Enter email"),
|
||||
"enterNewPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Enter a new password we can use to encrypt your data"),
|
||||
"enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage(
|
||||
"Enter a password we can use to encrypt your data"),
|
||||
"enterThe6digitCodeFromnyourAuthenticatorApp":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Enter the 6-digit code from\nyour authenticator app"),
|
||||
"enterValidEmail": MessageLookupByLibrary.simpleMessage(
|
||||
"Please enter a valid email address."),
|
||||
"enterYourEmailAddress":
|
||||
MessageLookupByLibrary.simpleMessage("Enter your email address"),
|
||||
"enterYourPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Enter your password"),
|
||||
"enterYourRecoveryKey":
|
||||
MessageLookupByLibrary.simpleMessage("Enter your recovery key"),
|
||||
"feedback": MessageLookupByLibrary.simpleMessage("Feedback"),
|
||||
"forgotPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Forgot password"),
|
||||
"fromYourRegisteredEmailAddress": MessageLookupByLibrary.simpleMessage(
|
||||
"from your registered email address."),
|
||||
"generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage(
|
||||
"Generating encryption keys..."),
|
||||
"howItWorks": MessageLookupByLibrary.simpleMessage("How it works"),
|
||||
"incorrectPasswordTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Incorrect password"),
|
||||
"incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage(
|
||||
"The recovery key you entered is incorrect"),
|
||||
"incorrectRecoveryKeyTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Incorrect recovery key"),
|
||||
"insecureDevice":
|
||||
MessageLookupByLibrary.simpleMessage("Insecure device"),
|
||||
"invalidEmailAddress":
|
||||
MessageLookupByLibrary.simpleMessage("Invalid email address"),
|
||||
"verify": MessageLookupByLibrary.simpleMessage("Verify")
|
||||
"invalidKey": MessageLookupByLibrary.simpleMessage("Invalid key"),
|
||||
"invalidRecoveryKey": MessageLookupByLibrary.simpleMessage(
|
||||
"The recovery key you entered is not valid. Please make sure it "),
|
||||
"kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage(
|
||||
"Kindly help us with this information"),
|
||||
"logInLabel": MessageLookupByLibrary.simpleMessage("Log in"),
|
||||
"lostDevice": MessageLookupByLibrary.simpleMessage("Lost device?"),
|
||||
"manage": MessageLookupByLibrary.simpleMessage("Manage"),
|
||||
"moderateStrength": MessageLookupByLibrary.simpleMessage("Moderate"),
|
||||
"noPasswordWarningPart1": MessageLookupByLibrary.simpleMessage(
|
||||
"We don\'t store this password, so if you forget,"),
|
||||
"noPasswordWarningPart2":
|
||||
MessageLookupByLibrary.simpleMessage("we cannot decrypt your data"),
|
||||
"noRecoveryKey":
|
||||
MessageLookupByLibrary.simpleMessage("No recovery key?"),
|
||||
"noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage(
|
||||
"Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key"),
|
||||
"ok": MessageLookupByLibrary.simpleMessage("Ok"),
|
||||
"oops": MessageLookupByLibrary.simpleMessage("Oops"),
|
||||
"orPickAnExistingOne":
|
||||
MessageLookupByLibrary.simpleMessage("Or pick an existing one"),
|
||||
"password": MessageLookupByLibrary.simpleMessage("Password"),
|
||||
"passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage(
|
||||
"Password changed successfully"),
|
||||
"passwordStrength": m2,
|
||||
"pleaseSendAnEmailTo":
|
||||
MessageLookupByLibrary.simpleMessage("Please send an email to"),
|
||||
"pleaseTryAgain":
|
||||
MessageLookupByLibrary.simpleMessage("Please try again"),
|
||||
"pleaseWait": MessageLookupByLibrary.simpleMessage("Please wait..."),
|
||||
"privacyPolicy": MessageLookupByLibrary.simpleMessage("privacy policy"),
|
||||
"privacyPolicyTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Privacy Policy"),
|
||||
"recover": MessageLookupByLibrary.simpleMessage("Recover"),
|
||||
"recoverAccount":
|
||||
MessageLookupByLibrary.simpleMessage("Recover account"),
|
||||
"recoverButton": MessageLookupByLibrary.simpleMessage("Recover"),
|
||||
"recoveryKey": MessageLookupByLibrary.simpleMessage("Recovery key"),
|
||||
"recoveryKeyCopiedToClipboard": MessageLookupByLibrary.simpleMessage(
|
||||
"Recovery key copied to clipboard"),
|
||||
"recoveryKeyOnForgotPassword": MessageLookupByLibrary.simpleMessage(
|
||||
"If you forget your password, the only way you can recover your data is with this key."),
|
||||
"recoveryKeySaveDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"We don\'t store this key, please save this 24 word key in a safe place."),
|
||||
"recoveryKeySuccessBody": MessageLookupByLibrary.simpleMessage(
|
||||
"Great! Your recovery key is valid. Thank you for verifying.\n\nPlease remember to keep your recovery key safely backed up."),
|
||||
"recoveryKeyVerified":
|
||||
MessageLookupByLibrary.simpleMessage("Recovery key verified"),
|
||||
"recoveryKeyVerifyReason": MessageLookupByLibrary.simpleMessage(
|
||||
"Your recovery key is the only way to recover your photos if you forget your password. You can find your recovery key in Settings > Account.\n\nPlease enter your recovery key here to verify that you have saved it correctly."),
|
||||
"recoverySuccessful":
|
||||
MessageLookupByLibrary.simpleMessage("Recovery successful!"),
|
||||
"recreatePasswordBody": MessageLookupByLibrary.simpleMessage(
|
||||
"The current device is not powerful enough to verify your "),
|
||||
"recreatePasswordTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Recreate password"),
|
||||
"remove": MessageLookupByLibrary.simpleMessage("Remove"),
|
||||
"removeParticipant":
|
||||
MessageLookupByLibrary.simpleMessage("Remove participant"),
|
||||
"resendEmail": MessageLookupByLibrary.simpleMessage("Resend email"),
|
||||
"resetPasswordTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Reset password"),
|
||||
"saveKey": MessageLookupByLibrary.simpleMessage("Save key"),
|
||||
"saveYourRecoveryKeyIfYouHaventAlready":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Save your recovery key if you haven\'t already"),
|
||||
"scanCode": MessageLookupByLibrary.simpleMessage("Scan code"),
|
||||
"scanThisBarcodeWithnyourAuthenticatorApp":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Scan this barcode with\nyour authenticator app"),
|
||||
"selectReason": MessageLookupByLibrary.simpleMessage("Select reason"),
|
||||
"sendEmail": MessageLookupByLibrary.simpleMessage("Send email"),
|
||||
"setPasswordTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Set password"),
|
||||
"setupComplete": MessageLookupByLibrary.simpleMessage("Setup complete"),
|
||||
"somethingWentWrongPleaseTryAgain":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Something went wrong, please try again"),
|
||||
"sorry": MessageLookupByLibrary.simpleMessage("Sorry"),
|
||||
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Sorry, we could not generate secure keys on this device.\n\nplease sign up from a different device."),
|
||||
"strongStrength": MessageLookupByLibrary.simpleMessage("Strong"),
|
||||
"tapToCopy": MessageLookupByLibrary.simpleMessage("tap to copy"),
|
||||
"tapToEnterCode":
|
||||
MessageLookupByLibrary.simpleMessage("Tap to enter code"),
|
||||
"terminate": MessageLookupByLibrary.simpleMessage("Terminate"),
|
||||
"terminateSession":
|
||||
MessageLookupByLibrary.simpleMessage("Terminate session?"),
|
||||
"termsAgreePart1":
|
||||
MessageLookupByLibrary.simpleMessage("I agree to the "),
|
||||
"termsOfService":
|
||||
MessageLookupByLibrary.simpleMessage("terms of service"),
|
||||
"termsOfServicesTitle": MessageLookupByLibrary.simpleMessage("Terms"),
|
||||
"thisCanBeUsedToRecoverYourAccountIfYou":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"This can be used to recover your account if you lose your second factor"),
|
||||
"thisDevice": MessageLookupByLibrary.simpleMessage("This device"),
|
||||
"thisWillLogYouOutOfTheFollowingDevice":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"This will log you out of the following device:"),
|
||||
"thisWillLogYouOutOfThisDevice": MessageLookupByLibrary.simpleMessage(
|
||||
"This will log you out of this device!"),
|
||||
"tryAgain": MessageLookupByLibrary.simpleMessage("Try again"),
|
||||
"twofactorAuthenticationPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Two-factor authentication"),
|
||||
"twofactorSetup":
|
||||
MessageLookupByLibrary.simpleMessage("Two-factor setup"),
|
||||
"useRecoveryKey":
|
||||
MessageLookupByLibrary.simpleMessage("Use recovery key"),
|
||||
"verify": MessageLookupByLibrary.simpleMessage("Verify"),
|
||||
"verifyEmail": MessageLookupByLibrary.simpleMessage("Verify email"),
|
||||
"verifyPassword":
|
||||
MessageLookupByLibrary.simpleMessage("Verify password"),
|
||||
"verifyingRecoveryKey":
|
||||
MessageLookupByLibrary.simpleMessage("Verifying recovery key..."),
|
||||
"viewRecoveryKey":
|
||||
MessageLookupByLibrary.simpleMessage("View recovery key"),
|
||||
"viewer": MessageLookupByLibrary.simpleMessage("Viewer"),
|
||||
"weakStrength": MessageLookupByLibrary.simpleMessage("Weak"),
|
||||
"welcomeBack": MessageLookupByLibrary.simpleMessage("Welcome back!"),
|
||||
"weveSentAMailTo":
|
||||
MessageLookupByLibrary.simpleMessage("We\'ve sent a mail to"),
|
||||
"yesConvertToViewer":
|
||||
MessageLookupByLibrary.simpleMessage("Yes, convert to viewer"),
|
||||
"you": MessageLookupByLibrary.simpleMessage("You"),
|
||||
"yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage(
|
||||
"Your account has been deleted")
|
||||
};
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,5 +5,197 @@
|
|||
"cancel": "Cancel",
|
||||
"verify": "Verify",
|
||||
"invalidEmailAddress": "Invalid email address",
|
||||
"enterValidEmail": "Please enter a valid email address."
|
||||
"enterValidEmail": "Please enter a valid email address.",
|
||||
"deleteAccount": "Delete account",
|
||||
"askDeleteReason": "What is the main reason you are deleting your account?",
|
||||
"deleteAccountFeedbackPrompt": "We are sorry to see you go. Please share your feedback to help us improve.",
|
||||
"feedback": "Feedback",
|
||||
"kindlyHelpUsWithThisInformation": "Kindly help us with this information",
|
||||
"confirmDeletePrompt": "Yes, I want to permanently delete this account and all its data.",
|
||||
"confirmAccountDeletion": "Confirm Account Deletion",
|
||||
"deleteConfirmDialogBody": "You are about to permanently delete your account and all its data.\nThis action is irreversible.",
|
||||
"deleteAccountPermanentlyButton": "Delete Account Permanently",
|
||||
"yourAccountHasBeenDeleted": "Your account has been deleted",
|
||||
"selectReason": "Select reason",
|
||||
"deleteReason1": "It’s missing a key feature that I need",
|
||||
"deleteReason2": "The app or a certain feature does not \nbehave as I think it should",
|
||||
"deleteReason3": "I found another service that I like better",
|
||||
"deleteReason4": "My reason isn’t listed",
|
||||
"sendEmail": "Send email",
|
||||
"deleteRequestSLAText": "Your request will be processed within 72 hours.",
|
||||
"pleaseSendAnEmailTo": "Please send an email to",
|
||||
"@pleaseSendAnEmailTo": {
|
||||
"description": "This text is part of the sentence 'Please send an email to email@ente.io from your registered email address.'"
|
||||
},
|
||||
"fromYourRegisteredEmailAddress": "from your registered email address.",
|
||||
"@fromYourRegisteredEmailAddress": {
|
||||
"description": "This text is part of the sentence 'Please send an email to email@ente.io from your registered email address.'"
|
||||
},
|
||||
"ok": "Ok",
|
||||
"createAccount": "Create account",
|
||||
"createNewAccount": "Create new account",
|
||||
"password": "Password",
|
||||
"confirmPassword": "Confirm password",
|
||||
"activeSessions": "Active sessions",
|
||||
"oops": "Oops",
|
||||
"somethingWentWrongPleaseTryAgain": "Something went wrong, please try again",
|
||||
"thisWillLogYouOutOfThisDevice": "This will log you out of this device!",
|
||||
"thisWillLogYouOutOfTheFollowingDevice": "This will log you out of the following device:",
|
||||
"terminateSession": "Terminate session?",
|
||||
"terminate": "Terminate",
|
||||
"thisDevice": "This device",
|
||||
"recoverButton": "Recover",
|
||||
"recoverySuccessful": "Recovery successful!",
|
||||
"decrypting": "Decrypting...",
|
||||
"incorrectRecoveryKeyTitle": "Incorrect recovery key",
|
||||
"incorrectRecoveryKeyBody": "The recovery key you entered is incorrect",
|
||||
"forgotPassword": "Forgot password",
|
||||
"enterYourRecoveryKey": "Enter your recovery key",
|
||||
"noRecoveryKey": "No recovery key?",
|
||||
"sorry": "Sorry",
|
||||
"noRecoveryKeyNoDecryption": "Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key",
|
||||
"verifyEmail": "Verify email",
|
||||
"checkInboxAndSpamFolder": "Please check your inbox (and spam) to complete verification",
|
||||
"tapToEnterCode": "Tap to enter code",
|
||||
"resendEmail": "Resend email",
|
||||
"weveSentAMailTo": "We've sent a mail to",
|
||||
"setPasswordTitle": "Set password",
|
||||
"changePasswordTitle": "Change password",
|
||||
"resetPasswordTitle": "Reset password",
|
||||
"encryptionKeys": "Encryption keys",
|
||||
"noPasswordWarningPart1": "We don't store this password, so if you forget,",
|
||||
"@noPasswordWarningPart1": {
|
||||
"description": "This text is part1 the sentence 'We don't store this password, so if you forget, we cannot decrypt your data.'"
|
||||
},
|
||||
"noPasswordWarningPart2": "we cannot decrypt your data",
|
||||
"@noPasswordWarningPart2": {
|
||||
"description": "This text is part2 the sentence 'We don't store this password, so if you forget, we cannot decrypt your data.'"
|
||||
},
|
||||
"enterPasswordToEncrypt": "Enter a password we can use to encrypt your data",
|
||||
"enterNewPasswordToEncrypt": "Enter a new password we can use to encrypt your data",
|
||||
"weakStrength": "Weak",
|
||||
"strongStrength": "Strong",
|
||||
"moderateStrength": "Moderate",
|
||||
"passwordStrength": "Password strength: {passwordStrengthValue}",
|
||||
"@passwordStrength": {
|
||||
"description": "Text to indicate the password strength",
|
||||
"placeholders": {
|
||||
"passwordStrengthValue": {
|
||||
"description": "The strength of the password as a string",
|
||||
"type": "String",
|
||||
"example": "Weak or Moderate or Strong"
|
||||
}
|
||||
},
|
||||
"message": "Password Strength: {passwordStrengthText}"
|
||||
},
|
||||
"passwordChangedSuccessfully": "Password changed successfully",
|
||||
"generatingEncryptionKeys": "Generating encryption keys...",
|
||||
"pleaseWait": "Please wait...",
|
||||
"continueLabel": "Continue",
|
||||
"insecureDevice": "Insecure device",
|
||||
"sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Sorry, we could not generate secure keys on this device.\n\nplease sign up from a different device.",
|
||||
"howItWorks": "How it works",
|
||||
"encryption": "Encryption",
|
||||
"ackPasswordLostWarningPart1": "I understand that if I lose my password, I may lose my data since my data is ",
|
||||
"endToEndEncrypted": "end-to-end encrypted",
|
||||
"ackPasswordLostWarningPart2": " with ente",
|
||||
"@ackPasswordLostWarningPart2": {
|
||||
"description": "This text is part2 the sentence 'I understand that if I lose my password, I may lose my data since my data is end-to-end encrypted with ente.'"
|
||||
},
|
||||
"privacyPolicyTitle": "Privacy Policy",
|
||||
"termsOfServicesTitle": "Terms",
|
||||
"termsAgreePart1": "I agree to the ",
|
||||
"@termsAgreePart1": {
|
||||
"description": "Note: there's a trailing space. This text is part the sentence 'I agree to the terms of service and privacy policy.'"
|
||||
},
|
||||
"privacyPolicy": "privacy policy",
|
||||
"and": "and",
|
||||
"@and": {
|
||||
"description": "Separator used in sentences like 'I agree to the terms of service and privacy policy.'"
|
||||
},
|
||||
"termsOfService": "terms of service",
|
||||
"logInLabel": "Log in",
|
||||
"byClickingLogInIAgreeToThe": "By clicking log in, I agree to the",
|
||||
"@byClickingLogInIAgreeToThe": {
|
||||
"description": "This text is part the sentence 'By clicking log in, I agree to the terms of service and privacy policy'"
|
||||
},
|
||||
"changeEmail": "Change email",
|
||||
"enterYourPassword": "Enter your password",
|
||||
"welcomeBack": "Welcome back!",
|
||||
"contactSupport": "Contact support",
|
||||
"incorrectPasswordTitle": "Incorrect password",
|
||||
"pleaseTryAgain": "Please try again",
|
||||
"recreatePasswordTitle": "Recreate password",
|
||||
"useRecoveryKey": "Use recovery key",
|
||||
"recreatePasswordBody": "The current device is not powerful enough to verify your ",
|
||||
"verifyPassword": "Verify password",
|
||||
"recoveryKey": "Recovery key",
|
||||
"recoveryKeyOnForgotPassword": "If you forget your password, the only way you can recover your data is with this key.",
|
||||
"recoveryKeySaveDescription": "We don't store this key, please save this 24 word key in a safe place.",
|
||||
"doThisLater": "Do this later",
|
||||
"saveKey": "Save key",
|
||||
"recoveryKeyCopiedToClipboard": "Recovery key copied to clipboard",
|
||||
"recoverAccount": "Recover account",
|
||||
"recover": "Recover",
|
||||
"dropSupportEmail": "Please drop an email to {supportEmail} from your registered email address",
|
||||
"@dropSupportEmail": {
|
||||
"placeholders": {
|
||||
"supportEmail": {
|
||||
"description": "The support email address",
|
||||
"type": "String",
|
||||
"example": "support@ente.io"
|
||||
}
|
||||
}
|
||||
},
|
||||
"twofactorSetup": "Two-factor setup",
|
||||
"enterCode": "Enter code",
|
||||
"scanCode": "Scan code",
|
||||
"codeCopiedToClipboard": "Code copied to clipboard",
|
||||
"copypasteThisCodentoYourAuthenticatorApp": "Copy-paste this code\nto your authenticator app",
|
||||
"tapToCopy": "tap to copy",
|
||||
"scanThisBarcodeWithnyourAuthenticatorApp": "Scan this barcode with\nyour authenticator app",
|
||||
"enterThe6digitCodeFromnyourAuthenticatorApp": "Enter the 6-digit code from\nyour authenticator app",
|
||||
"confirm": "Confirm",
|
||||
"setupComplete": "Setup complete",
|
||||
"saveYourRecoveryKeyIfYouHaventAlready": "Save your recovery key if you haven't already",
|
||||
"thisCanBeUsedToRecoverYourAccountIfYou": "This can be used to recover your account if you lose your second factor",
|
||||
"twofactorAuthenticationPageTitle": "Two-factor authentication",
|
||||
"lostDevice": "Lost device?",
|
||||
"verifyingRecoveryKey": "Verifying recovery key...",
|
||||
"recoveryKeyVerified": "Recovery key verified",
|
||||
"recoveryKeySuccessBody": "Great! Your recovery key is valid. Thank you for verifying.\n\nPlease remember to keep your recovery key safely backed up.",
|
||||
"invalidRecoveryKey": "The recovery key you entered is not valid. Please make sure it ",
|
||||
"invalidKey": "Invalid key",
|
||||
"tryAgain": "Try again",
|
||||
"viewRecoveryKey": "View recovery key",
|
||||
"confirmRecoveryKey": "Confirm recovery key",
|
||||
"recoveryKeyVerifyReason": "Your recovery key is the only way to recover your photos if you forget your password. You can find your recovery key in Settings > Account.\n\nPlease enter your recovery key here to verify that you have saved it correctly.",
|
||||
"confirmYourRecoveryKey": "Confirm your recovery key",
|
||||
"addViewer": "Add viewer",
|
||||
"addCollaborator": "Add collaborator",
|
||||
"addANewEmail": "Add a new email",
|
||||
"orPickAnExistingOne": "Or pick an existing one",
|
||||
"collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": "Collaborators can add photos and videos to the shared album.",
|
||||
"enterEmail": "Enter email",
|
||||
"albumOwner": "Owner",
|
||||
"@albumOwner": {
|
||||
"description": "Role of the album owner"
|
||||
},
|
||||
"you": "You",
|
||||
"collaborator": "Collaborator",
|
||||
"addMore": "Add more",
|
||||
"@addMore": {
|
||||
"description": "Button text to add more collaborators/viewers"
|
||||
},
|
||||
"viewer": "Viewer",
|
||||
"remove": "Remove",
|
||||
"removeParticipant": "Remove participant",
|
||||
"@removeParticipant": {
|
||||
"description": "menuSectionTitle for removing a participant"
|
||||
},
|
||||
"manage": "Manage",
|
||||
"addedAs": "Added as",
|
||||
"changePermissions": "Change permissions?",
|
||||
"yesConvertToViewer": "Yes, convert to viewer",
|
||||
"cannotAddMorePhotosAfterBecomingViewer": "{user} will not be able to add more photos to this album\n\nThey will still be able to remove existing photos added by them"
|
||||
}
|
|
@ -4,6 +4,7 @@ import "package:dropdown_button2/dropdown_button2.dart";
|
|||
import 'package:flutter/material.dart';
|
||||
import "package:logging/logging.dart";
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/models/delete_account.dart';
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/theme/ente_theme.dart';
|
||||
|
@ -26,23 +27,26 @@ class DeleteAccountPage extends StatefulWidget {
|
|||
class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
||||
bool _hasConfirmedDeletion = false;
|
||||
final _feedbackTextCtrl = TextEditingController();
|
||||
final String _defaultSelection = 'Select reason';
|
||||
late String _dropdownValue = _defaultSelection;
|
||||
late String _defaultSelection = S.of(context).selectReason;
|
||||
String? _dropdownValue;
|
||||
late final List<String> _deletionReason = [
|
||||
_defaultSelection,
|
||||
'It’s missing a key feature that I need',
|
||||
'The app or a certain feature does not \nbehave as I think it should',
|
||||
'I found another service that I like better',
|
||||
'My reason isn’t listed',
|
||||
S.of(context).deleteReason1,
|
||||
S.of(context).deleteReason2,
|
||||
S.of(context).deleteReason3,
|
||||
S.of(context).deleteReason4,
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_defaultSelection = S.of(context).selectReason;
|
||||
_dropdownValue ??= _defaultSelection;
|
||||
|
||||
final colorScheme = getEnteColorScheme(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
title: const Text("Delete account"),
|
||||
title: Text(S.of(context).deleteAccount),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
|
@ -59,7 +63,7 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text(
|
||||
"What is the main reason you are deleting your account?",
|
||||
S.of(context).askDeleteReason,
|
||||
style: getEnteTextTheme(context).body,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
|
@ -97,8 +101,7 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
"We are sorry to see you go. Please share your feedback to "
|
||||
"help us improve.",
|
||||
S.of(context).deleteAccountFeedbackPrompt,
|
||||
style: getEnteTextTheme(context).body,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
|
@ -116,7 +119,7 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
),
|
||||
filled: true,
|
||||
fillColor: Colors.transparent,
|
||||
hintText: "Feedback",
|
||||
hintText: S.of(context).feedback,
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
),
|
||||
controller: _feedbackTextCtrl,
|
||||
|
@ -135,7 +138,7 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: Text(
|
||||
"Kindly help us with this information",
|
||||
S.of(context).kindlyHelpUsWithThisInformation,
|
||||
style: getEnteTextTheme(context)
|
||||
.smallBold
|
||||
.copyWith(color: colorScheme.warning700),
|
||||
|
@ -162,8 +165,7 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Yes, I want to permanently delete this account and "
|
||||
"all its data.",
|
||||
S.of(context).confirmDeletePrompt,
|
||||
style: getEnteTextTheme(context).bodyMuted,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
|
@ -177,7 +179,7 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
children: [
|
||||
ButtonWidget(
|
||||
buttonType: ButtonType.critical,
|
||||
labelText: "Confirm Account Deletion",
|
||||
labelText: S.of(context).confirmAccountDeletion,
|
||||
isDisabled: _shouldBlockDeletion(),
|
||||
onTap: () async {
|
||||
await _initiateDelete(context);
|
||||
|
@ -187,7 +189,7 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
const SizedBox(height: 8),
|
||||
ButtonWidget(
|
||||
buttonType: ButtonType.secondary,
|
||||
labelText: "Cancel",
|
||||
labelText: S.of(context).cancel,
|
||||
onTap: () async {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -220,10 +222,9 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
Future<void> _initiateDelete(BuildContext context) async {
|
||||
final choice = await showChoiceDialog(
|
||||
context,
|
||||
title: "Confirm Account Deletion",
|
||||
body: "You are about to permanently delete your account and all its data."
|
||||
"\nThis action is irreversible.",
|
||||
firstButtonLabel: "Delete Account Permanently",
|
||||
title: S.of(context).confirmAccountDeletion,
|
||||
body: S.of(context).deleteConfirmDialogBody,
|
||||
firstButtonLabel: S.of(context).deleteAccountPermanentlyButton,
|
||||
firstButtonType: ButtonType.critical,
|
||||
firstButtonOnTap: () async {
|
||||
final deleteChallengeResponse =
|
||||
|
@ -260,11 +261,11 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
await UserService.instance.deleteAccount(
|
||||
context,
|
||||
challengeResponseStr,
|
||||
reasonCategory: _dropdownValue,
|
||||
reasonCategory: _dropdownValue!,
|
||||
feedback: _feedbackTextCtrl.text.trim(),
|
||||
);
|
||||
Navigator.of(context).popUntil((route) => route.isFirst);
|
||||
showShortToast(context, "Your account has been deleted");
|
||||
showShortToast(context, S.of(context).yourAccountHasBeenDeleted);
|
||||
} catch (e, s) {
|
||||
Logger("DeleteAccount").severe("failed to delete", e, s);
|
||||
showGenericErrorDialog(context: context);
|
||||
|
@ -273,17 +274,17 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
|
||||
Future<void> _requestEmailForDeletion(BuildContext context) async {
|
||||
final AlertDialog alert = AlertDialog(
|
||||
title: const Text(
|
||||
"Delete account",
|
||||
style: TextStyle(
|
||||
title: Text(
|
||||
S.of(context).deleteAccount,
|
||||
style: const TextStyle(
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
content: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: "Please send an email to ",
|
||||
TextSpan(
|
||||
text: S.of(context).pleaseSendAnEmailTo,
|
||||
),
|
||||
TextSpan(
|
||||
text: "account-deletion@ente.io",
|
||||
|
@ -291,9 +292,9 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
color: Colors.orange[300],
|
||||
),
|
||||
),
|
||||
const TextSpan(
|
||||
TextSpan(
|
||||
text:
|
||||
" from your registered email address.\n\nYour request will be processed within 72 hours.",
|
||||
" ${S.of(context).fromYourRegisteredEmailAddress}\n\n${S.of(context).deleteRequestSLAText}",
|
||||
),
|
||||
],
|
||||
style: TextStyle(
|
||||
|
@ -305,9 +306,9 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text(
|
||||
"Send email",
|
||||
style: TextStyle(
|
||||
child: Text(
|
||||
S.of(context).sendEmail,
|
||||
style: const TextStyle(
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
|
@ -316,13 +317,13 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
await sendEmail(
|
||||
context,
|
||||
to: 'account-deletion@ente.io',
|
||||
subject: '[Delete account]',
|
||||
subject: '[${S.of(context).deleteAccount}]',
|
||||
);
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
"Ok",
|
||||
S.of(context).ok,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
|
|||
import 'package:password_strength/password_strength.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/ente_theme_data.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/common/dynamic_fab.dart';
|
||||
import 'package:photos/ui/common/web_page.dart';
|
||||
|
@ -99,7 +100,7 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
floatingActionButton: DynamicFAB(
|
||||
isKeypadOpen: isKeypadOpen,
|
||||
isFormValid: _isFormValid(),
|
||||
buttonText: 'Create account',
|
||||
buttonText: S.of(context).createAccount,
|
||||
onPressedFunction: () {
|
||||
_config.setVolatilePassword(_passwordController1.text);
|
||||
UserService.instance.setEmail(_email!);
|
||||
|
@ -114,13 +115,13 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
}
|
||||
|
||||
Widget _getBody() {
|
||||
var passwordStrengthText = 'Weak';
|
||||
var passwordStrengthText = S.of(context).weakStrength;
|
||||
var passwordStrengthColor = Colors.redAccent;
|
||||
if (_passwordStrength > kStrongPasswordStrengthThreshold) {
|
||||
passwordStrengthText = 'Strong';
|
||||
passwordStrengthText = S.of(context).strongStrength;
|
||||
passwordStrengthColor = Colors.greenAccent;
|
||||
} else if (_passwordStrength > kMildPasswordStrengthThreshold) {
|
||||
passwordStrengthText = 'Moderate';
|
||||
passwordStrengthText = S.of(context).moderateStrength;
|
||||
passwordStrengthColor = Colors.orangeAccent;
|
||||
}
|
||||
return Column(
|
||||
|
@ -133,7 +134,7 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
|
||||
child: Text(
|
||||
'Create new account',
|
||||
S.of(context).createNewAccount,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
),
|
||||
|
@ -145,7 +146,7 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
decoration: InputDecoration(
|
||||
fillColor: _emailIsValid ? _validFieldValueColor : null,
|
||||
filled: true,
|
||||
hintText: 'Email',
|
||||
hintText: S.of(context).email,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 14,
|
||||
|
@ -193,7 +194,7 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
fillColor:
|
||||
_passwordIsValid ? _validFieldValueColor : null,
|
||||
filled: true,
|
||||
hintText: "Password",
|
||||
hintText: S.of(context).password,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 14,
|
||||
|
@ -262,7 +263,7 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
? _validFieldValueColor
|
||||
: null,
|
||||
filled: true,
|
||||
hintText: "Confirm password",
|
||||
hintText: S.of(context).confirmPassword,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 14,
|
||||
|
@ -314,7 +315,7 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
|
||||
child: Text(
|
||||
'Password strength: $passwordStrengthText',
|
||||
S.of(context).passwordStrength(passwordStrengthText),
|
||||
style: TextStyle(
|
||||
color: passwordStrengthColor,
|
||||
fontWeight: FontWeight.w500,
|
||||
|
@ -371,11 +372,11 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: "I agree to the ",
|
||||
TextSpan(
|
||||
text: S.of(context).termsAgreePart1,
|
||||
),
|
||||
TextSpan(
|
||||
text: "terms of service",
|
||||
text: S.of(context).termsOfService,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
|
@ -384,8 +385,8 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const WebPage(
|
||||
"Terms",
|
||||
return WebPage(
|
||||
S.of(context).termsOfServicesTitle,
|
||||
"https://ente.io/terms",
|
||||
);
|
||||
},
|
||||
|
@ -393,9 +394,9 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
);
|
||||
},
|
||||
),
|
||||
const TextSpan(text: " and "),
|
||||
TextSpan(text: ' ${S.of(context).and} '),
|
||||
TextSpan(
|
||||
text: "privacy policy",
|
||||
text: S.of(context).privacyPolicy,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
|
@ -404,8 +405,8 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const WebPage(
|
||||
"Privacy",
|
||||
return WebPage(
|
||||
S.of(context).privacyPolicyTitle,
|
||||
"https://ente.io/privacy",
|
||||
);
|
||||
},
|
||||
|
@ -450,12 +451,11 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
const TextSpan(
|
||||
text:
|
||||
"I understand that if I lose my password, I may lose my data since my data is ",
|
||||
TextSpan(
|
||||
text: S.of(context).ackPasswordLostWarningPart1,
|
||||
),
|
||||
TextSpan(
|
||||
text: "end-to-end encrypted",
|
||||
text: S.of(context).endToEndEncrypted,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
|
@ -464,8 +464,8 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const WebPage(
|
||||
"Encryption",
|
||||
return WebPage(
|
||||
S.of(context).encryption,
|
||||
"https://ente.io/architecture",
|
||||
);
|
||||
},
|
||||
|
@ -473,7 +473,9 @@ class _EmailEntryPageState extends State<EmailEntryPage> {
|
|||
);
|
||||
},
|
||||
),
|
||||
const TextSpan(text: " with ente"),
|
||||
TextSpan(
|
||||
text: " ${S.of(context).ackPasswordLostWarningPart2}",
|
||||
),
|
||||
],
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:email_validator/email_validator.dart';
|
|||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import "package:photos/l10n/l10n.dart";
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/common/dynamic_fab.dart';
|
||||
|
@ -54,7 +55,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||
floatingActionButton: DynamicFAB(
|
||||
isKeypadOpen: isKeypadOpen,
|
||||
isFormValid: _emailIsValid,
|
||||
buttonText: 'Log in',
|
||||
buttonText: S.of(context).logInLabel,
|
||||
onPressedFunction: () {
|
||||
UserService.instance.setEmail(_email!);
|
||||
UserService.instance
|
||||
|
@ -148,11 +149,12 @@ class _LoginPageState extends State<LoginPage> {
|
|||
.subtitle1!
|
||||
.copyWith(fontSize: 12),
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: "By clicking log in, I agree to the ",
|
||||
TextSpan(
|
||||
text: S.of(context).byClickingLogInIAgreeToThe +
|
||||
" ",
|
||||
),
|
||||
TextSpan(
|
||||
text: "terms of service",
|
||||
text: S.of(context).termsOfService,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
|
@ -161,8 +163,8 @@ class _LoginPageState extends State<LoginPage> {
|
|||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const WebPage(
|
||||
"terms",
|
||||
return WebPage(
|
||||
S.of(context).termsOfServicesTitle,
|
||||
"https://ente.io/terms",
|
||||
);
|
||||
},
|
||||
|
@ -170,9 +172,9 @@ class _LoginPageState extends State<LoginPage> {
|
|||
);
|
||||
},
|
||||
),
|
||||
const TextSpan(text: " and "),
|
||||
TextSpan(text: " ${S.of(context).and} "),
|
||||
TextSpan(
|
||||
text: "privacy policy",
|
||||
text: S.of(context).privacyPolicy,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
|
@ -181,8 +183,8 @@ class _LoginPageState extends State<LoginPage> {
|
|||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const WebPage(
|
||||
"privacy",
|
||||
return WebPage(
|
||||
S.of(context).privacyPolicyTitle,
|
||||
"https://ente.io/privacy",
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/ente_theme_data.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/common/dynamic_fab.dart';
|
||||
import 'package:step_progress_indicator/step_progress_indicator.dart';
|
||||
|
@ -64,7 +65,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
floatingActionButton: DynamicFAB(
|
||||
isKeypadOpen: isKeypadOpen,
|
||||
isFormValid: _verificationCodeController.text.isNotEmpty,
|
||||
buttonText: 'Verify',
|
||||
buttonText: S.of(context).verify,
|
||||
onPressedFunction: () {
|
||||
if (widget.isChangeEmail) {
|
||||
UserService.instance.changeEmail(
|
||||
|
@ -93,7 +94,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 30, 20, 15),
|
||||
child: Text(
|
||||
'Verify email',
|
||||
S.of(context).verifyEmail,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
),
|
||||
|
@ -114,7 +115,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
.subtitle1!
|
||||
.copyWith(fontSize: 14),
|
||||
children: [
|
||||
const TextSpan(text: "We've sent a mail to "),
|
||||
TextSpan(text: S.of(context).weveSentAMailTo),
|
||||
TextSpan(
|
||||
text: widget.email,
|
||||
style: TextStyle(
|
||||
|
@ -128,7 +129,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
),
|
||||
),
|
||||
Text(
|
||||
'Please check your inbox (and spam) to complete verification',
|
||||
S.of(context).checkInboxAndSpamFolder,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.subtitle1!
|
||||
|
@ -150,7 +151,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
style: Theme.of(context).textTheme.subtitle1,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
hintText: 'Tap to enter code',
|
||||
hintText: S.of(context).tapToEnterCode,
|
||||
contentPadding: const EdgeInsets.all(15),
|
||||
border: UnderlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
|
@ -183,7 +184,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
|||
);
|
||||
},
|
||||
child: Text(
|
||||
"Resend email",
|
||||
S.of(context).resendEmail,
|
||||
style: Theme.of(context).textTheme.subtitle1!.copyWith(
|
||||
fontSize: 14,
|
||||
decoration: TextDecoration.underline,
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:photos/core/configuration.dart';
|
|||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/account_configured_event.dart';
|
||||
import 'package:photos/events/subscription_purchased_event.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/account/recovery_key_page.dart';
|
||||
import 'package:photos/ui/common/dynamic_fab.dart';
|
||||
|
@ -87,13 +88,13 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
}
|
||||
}
|
||||
|
||||
String title = "Set password";
|
||||
String title = S.of(context).setPasswordTitle;
|
||||
if (widget.mode == PasswordEntryMode.update) {
|
||||
title = "Change password";
|
||||
title = S.of(context).changePasswordTitle;
|
||||
} else if (widget.mode == PasswordEntryMode.reset) {
|
||||
title = "Reset password";
|
||||
title = S.of(context).resetPasswordTitle;
|
||||
} else if (_volatilePassword != null) {
|
||||
title = "Encryption keys";
|
||||
title = S.of(context).encryptionKeys;
|
||||
}
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: isKeypadOpen,
|
||||
|
@ -130,13 +131,13 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
|
||||
Widget _getBody(String buttonTextAndHeading) {
|
||||
final email = Configuration.instance.getEmail();
|
||||
var passwordStrengthText = 'Weak';
|
||||
var passwordStrengthText = S.of(context).weakStrength;
|
||||
var passwordStrengthColor = Colors.redAccent;
|
||||
if (_passwordStrength > kStrongPasswordStrengthThreshold) {
|
||||
passwordStrengthText = 'Strong';
|
||||
passwordStrengthText = S.of(context).strongStrength;
|
||||
passwordStrengthColor = Colors.greenAccent;
|
||||
} else if (_passwordStrength > kMildPasswordStrengthThreshold) {
|
||||
passwordStrengthText = 'Moderate';
|
||||
passwordStrengthText = S.of(context).moderateStrength;
|
||||
passwordStrengthColor = Colors.orangeAccent;
|
||||
}
|
||||
if (_volatilePassword != null) {
|
||||
|
@ -159,9 +160,9 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Text(
|
||||
"Enter a" +
|
||||
(widget.mode != PasswordEntryMode.set ? " new " : " ") +
|
||||
"password we can use to encrypt your data",
|
||||
widget.mode == PasswordEntryMode.set
|
||||
? S.of(context).enterPasswordToEncrypt
|
||||
: S.of(context).enterNewPasswordToEncrypt,
|
||||
textAlign: TextAlign.start,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
|
@ -179,12 +180,11 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
.subtitle1!
|
||||
.copyWith(fontSize: 14),
|
||||
children: [
|
||||
const TextSpan(
|
||||
text:
|
||||
"We don't store this password, so if you forget, ",
|
||||
TextSpan(
|
||||
text: '${S.of(context).noPasswordWarningPart1} ',
|
||||
),
|
||||
TextSpan(
|
||||
text: "we cannot decrypt your data",
|
||||
text: S.of(context).noPasswordWarningPart2,
|
||||
style:
|
||||
Theme.of(context).textTheme.subtitle1!.copyWith(
|
||||
fontSize: 14,
|
||||
|
@ -218,7 +218,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
fillColor:
|
||||
_isPasswordValid ? _validFieldValueColor : null,
|
||||
filled: true,
|
||||
hintText: "Password",
|
||||
hintText: S.of(context).password,
|
||||
contentPadding: const EdgeInsets.all(20),
|
||||
border: UnderlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
|
@ -281,7 +281,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
decoration: InputDecoration(
|
||||
fillColor: _passwordsMatch ? _validFieldValueColor : null,
|
||||
filled: true,
|
||||
hintText: "Confirm password",
|
||||
hintText: S.of(context).confirmPassword,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 20,
|
||||
|
@ -335,7 +335,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
|
||||
child: Text(
|
||||
'Password Strength: $passwordStrengthText',
|
||||
S.of(context).passwordStrength(passwordStrengthText),
|
||||
style: TextStyle(
|
||||
color: passwordStrengthColor,
|
||||
),
|
||||
|
@ -349,8 +349,8 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const WebPage(
|
||||
"How it works",
|
||||
return WebPage(
|
||||
S.of(context).howItWorks,
|
||||
"https://ente.io/architecture",
|
||||
);
|
||||
},
|
||||
|
@ -361,7 +361,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
text: "How it works",
|
||||
text: S.of(context).howItWorks,
|
||||
style: Theme.of(context).textTheme.subtitle1!.copyWith(
|
||||
fontSize: 14,
|
||||
decoration: TextDecoration.underline,
|
||||
|
@ -381,14 +381,14 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
|
||||
void _updatePassword() async {
|
||||
final dialog =
|
||||
createProgressDialog(context, "Generating encryption keys...");
|
||||
createProgressDialog(context, S.of(context).generatingEncryptionKeys);
|
||||
await dialog.show();
|
||||
try {
|
||||
final keyAttributes = await Configuration.instance
|
||||
.updatePassword(_passwordController1.text);
|
||||
await UserService.instance.updateKeyAttributes(keyAttributes);
|
||||
await dialog.hide();
|
||||
showShortToast(context, "Password changed successfully");
|
||||
showShortToast(context, S.of(context).passwordChangedSuccessfully);
|
||||
Navigator.of(context).pop();
|
||||
if (widget.mode == PasswordEntryMode.reset) {
|
||||
Bus.instance.fire(SubscriptionPurchasedEvent());
|
||||
|
@ -403,14 +403,14 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
|
||||
Future<void> _showRecoveryCodeDialog(String password) async {
|
||||
final dialog =
|
||||
createProgressDialog(context, "Generating encryption keys...");
|
||||
createProgressDialog(context, S.of(context).generatingEncryptionKeys);
|
||||
await dialog.show();
|
||||
try {
|
||||
final result = await Configuration.instance.generateKey(password);
|
||||
Configuration.instance.setVolatilePassword(null);
|
||||
await dialog.hide();
|
||||
onDone() async {
|
||||
final dialog = createProgressDialog(context, "Please wait...");
|
||||
final dialog = createProgressDialog(context, S.of(context).pleaseWait);
|
||||
await dialog.show();
|
||||
try {
|
||||
await UserService.instance.setAttributes(result);
|
||||
|
@ -435,7 +435,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
context,
|
||||
RecoveryKeyPage(
|
||||
result.privateKeyAttributes.recoveryKey,
|
||||
"Continue",
|
||||
S.of(context).continueLabel,
|
||||
showAppBar: false,
|
||||
isDismissible: false,
|
||||
onDone: onDone,
|
||||
|
@ -448,8 +448,8 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
if (e is UnsupportedError) {
|
||||
showErrorDialog(
|
||||
context,
|
||||
"Insecure device",
|
||||
"Sorry, we could not generate secure keys on this device.\n\nplease sign up from a different device.",
|
||||
S.of(context).insecureDevice,
|
||||
S.of(context).sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease,
|
||||
);
|
||||
} else {
|
||||
showGenericErrorDialog(context: context);
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:photos/core/configuration.dart';
|
|||
import 'package:photos/core/errors.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/subscription_purchased_event.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/ui/account/recovery_page.dart';
|
||||
import 'package:photos/ui/common/dynamic_fab.dart';
|
||||
import 'package:photos/ui/components/buttons/button_widget.dart';
|
||||
|
@ -67,10 +68,11 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
floatingActionButton: DynamicFAB(
|
||||
isKeypadOpen: isKeypadOpen,
|
||||
isFormValid: _passwordController.text.isNotEmpty,
|
||||
buttonText: 'Verify password',
|
||||
buttonText: S.of(context).verifyPassword,
|
||||
onPressedFunction: () async {
|
||||
FocusScope.of(context).unfocus();
|
||||
final dialog = createProgressDialog(context, "Please wait...");
|
||||
final dialog =
|
||||
createProgressDialog(context, S.of(context).pleaseWait);
|
||||
await dialog.show();
|
||||
try {
|
||||
await Configuration.instance.decryptAndSaveSecrets(
|
||||
|
@ -82,12 +84,9 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
await dialog.hide();
|
||||
final dialogChoice = await showChoiceDialog(
|
||||
context,
|
||||
title: "Recreate password",
|
||||
body: "The current device is not powerful enough to verify your "
|
||||
"password, so we need to regenerate it once in a way that "
|
||||
"works with all devices. \n\nPlease login using your "
|
||||
"recovery key and regenerate your password (you can use the same one again if you wish).",
|
||||
firstButtonLabel: "Use recovery key",
|
||||
title: S.of(context).recreatePasswordTitle,
|
||||
body: S.of(context).recreatePasswordBody,
|
||||
firstButtonLabel: S.of(context).useRecoveryKey,
|
||||
);
|
||||
if (dialogChoice!.action == ButtonAction.first) {
|
||||
Navigator.of(context).push(
|
||||
|
@ -104,15 +103,15 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
await dialog.hide();
|
||||
final dialogChoice = await showChoiceDialog(
|
||||
context,
|
||||
title: "Incorrect password",
|
||||
body: "Please try again",
|
||||
firstButtonLabel: "Contact Support",
|
||||
secondButtonLabel: "OK",
|
||||
title: S.of(context).incorrectPasswordTitle,
|
||||
body: S.of(context).pleaseTryAgain,
|
||||
firstButtonLabel: S.of(context).contactSupport,
|
||||
secondButtonLabel: S.of(context).ok,
|
||||
);
|
||||
if (dialogChoice!.action == ButtonAction.first) {
|
||||
await sendLogs(
|
||||
context,
|
||||
"Contact support",
|
||||
S.of(context).contactSupport,
|
||||
"support@ente.io",
|
||||
postShare: () {},
|
||||
);
|
||||
|
@ -149,7 +148,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
|
||||
child: Text(
|
||||
'Welcome back!',
|
||||
S.of(context).welcomeBack,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
),
|
||||
|
@ -172,7 +171,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
child: TextFormField(
|
||||
autofillHints: const [AutofillHints.password],
|
||||
decoration: InputDecoration(
|
||||
hintText: "Enter your password",
|
||||
hintText: S.of(context).enterYourPassword,
|
||||
filled: true,
|
||||
contentPadding: const EdgeInsets.all(20),
|
||||
border: UnderlineInputBorder(
|
||||
|
@ -234,7 +233,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
},
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Forgot password",
|
||||
S.of(context).forgotPassword,
|
||||
style:
|
||||
Theme.of(context).textTheme.subtitle1!.copyWith(
|
||||
fontSize: 14,
|
||||
|
@ -246,8 +245,8 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () async {
|
||||
final dialog =
|
||||
createProgressDialog(context, "Please wait...");
|
||||
final dialog = createProgressDialog(
|
||||
context, S.of(context).pleaseWait);
|
||||
await dialog.show();
|
||||
await Configuration.instance.logout();
|
||||
await dialog.hide();
|
||||
|
@ -256,7 +255,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
|||
},
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Change email",
|
||||
S.of(context).changeEmail,
|
||||
style:
|
||||
Theme.of(context).textTheme.subtitle1!.copyWith(
|
||||
fontSize: 14,
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:flutter/services.dart';
|
|||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/core/constants.dart';
|
||||
import 'package:photos/ente_theme_data.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/ui/common/gradient_button.dart';
|
||||
import 'package:photos/utils/toast_util.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
@ -80,7 +81,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
: widget.showAppBar!
|
||||
? AppBar(
|
||||
elevation: 0,
|
||||
title: Text(widget.title ?? "Recovery key"),
|
||||
title: Text(widget.title ?? S.of(context).recoveryKey),
|
||||
)
|
||||
: null,
|
||||
body: Padding(
|
||||
|
@ -101,7 +102,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
widget.showAppBar!
|
||||
? const SizedBox.shrink()
|
||||
: Text(
|
||||
widget.title ?? "Recovery key",
|
||||
widget.title ?? S.of(context).recoveryKey,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
Padding(
|
||||
|
@ -109,7 +110,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
),
|
||||
Text(
|
||||
widget.text ??
|
||||
"If you forget your password, the only way you can recover your data is with this key.",
|
||||
S.of(context).recoveryKeyOnForgotPassword,
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
const Padding(padding: EdgeInsets.only(top: 24)),
|
||||
|
@ -136,7 +137,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
);
|
||||
showShortToast(
|
||||
context,
|
||||
"Recovery key copied to clipboard",
|
||||
S.of(context).recoveryKeyCopiedToClipboard,
|
||||
);
|
||||
setState(() {
|
||||
_hasTriedToSave = true;
|
||||
|
@ -176,7 +177,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||
child: Text(
|
||||
widget.subText ??
|
||||
"We don't store this key, please save this 24 word key in a safe place.",
|
||||
S.of(context).recoveryKeySaveDescription,
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
),
|
||||
),
|
||||
|
@ -212,7 +213,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
onPressed: () async {
|
||||
await _saveKeys();
|
||||
},
|
||||
child: const Text('Do this later'),
|
||||
child: Text(S.of(context).doThisLater),
|
||||
),
|
||||
);
|
||||
childrens.add(const SizedBox(height: 10));
|
||||
|
@ -223,7 +224,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
onTap: () async {
|
||||
await _shareRecoveryKey(recoveryKey);
|
||||
},
|
||||
text: 'Save key',
|
||||
text: S.of(context).saveKey,
|
||||
),
|
||||
);
|
||||
if (_hasTriedToSave) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:ui';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/ui/account/password_entry_page.dart';
|
||||
import 'package:photos/ui/common/dynamic_fab.dart';
|
||||
import 'package:photos/utils/dialog_util.dart';
|
||||
|
@ -43,15 +44,16 @@ class _RecoveryPageState extends State<RecoveryPage> {
|
|||
floatingActionButton: DynamicFAB(
|
||||
isKeypadOpen: isKeypadOpen,
|
||||
isFormValid: _recoveryKey.text.isNotEmpty,
|
||||
buttonText: 'Recover',
|
||||
buttonText: S.of(context).recoverButton,
|
||||
onPressedFunction: () async {
|
||||
FocusScope.of(context).unfocus();
|
||||
final dialog = createProgressDialog(context, "Decrypting...");
|
||||
final dialog =
|
||||
createProgressDialog(context, S.of(context).decrypting);
|
||||
await dialog.show();
|
||||
try {
|
||||
await Configuration.instance.recover(_recoveryKey.text.trim());
|
||||
await dialog.hide();
|
||||
showShortToast(context, "Recovery successful!");
|
||||
showShortToast(context, S.of(context).recoverySuccessful);
|
||||
Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
|
@ -66,11 +68,15 @@ class _RecoveryPageState extends State<RecoveryPage> {
|
|||
);
|
||||
} catch (e) {
|
||||
await dialog.hide();
|
||||
String errMessage = "The recovery key you entered is incorrect";
|
||||
String errMessage = S.of(context).incorrectRecoveryKeyBody;
|
||||
if (e is AssertionError) {
|
||||
errMessage = '$errMessage : ${e.message}';
|
||||
}
|
||||
showErrorDialog(context, "Incorrect recovery key", errMessage);
|
||||
showErrorDialog(
|
||||
context,
|
||||
S.of(context).incorrectRecoveryKeyTitle,
|
||||
errMessage,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
@ -85,7 +91,7 @@ class _RecoveryPageState extends State<RecoveryPage> {
|
|||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
|
||||
child: Text(
|
||||
'Forgot password',
|
||||
S.of(context).forgotPassword,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
),
|
||||
|
@ -94,7 +100,7 @@ class _RecoveryPageState extends State<RecoveryPage> {
|
|||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
hintText: "Enter your recovery key",
|
||||
hintText: S.of(context).enterYourRecoveryKey,
|
||||
contentPadding: const EdgeInsets.all(20),
|
||||
border: UnderlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
|
@ -128,15 +134,15 @@ class _RecoveryPageState extends State<RecoveryPage> {
|
|||
onTap: () {
|
||||
showErrorDialog(
|
||||
context,
|
||||
"Sorry",
|
||||
"Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key",
|
||||
S.of(context).sorry,
|
||||
S.of(context).noRecoveryKeyNoDecryption,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"No recovery key?",
|
||||
S.of(context).noRecoveryKey,
|
||||
style:
|
||||
Theme.of(context).textTheme.subtitle1!.copyWith(
|
||||
fontSize: 14,
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/ente_theme_data.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/models/sessions.dart';
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/common/loading_widget.dart';
|
||||
|
@ -33,7 +34,7 @@ class _SessionsPageState extends State<SessionsPage> {
|
|||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
title: const Text("Active sessions"),
|
||||
title: Text(S.of(context).activeSessions),
|
||||
),
|
||||
body: _getBody(),
|
||||
);
|
||||
|
@ -111,7 +112,7 @@ class _SessionsPageState extends State<SessionsPage> {
|
|||
}
|
||||
|
||||
Future<void> _terminateSession(Session session) async {
|
||||
final dialog = createProgressDialog(context, "Please wait...");
|
||||
final dialog = createProgressDialog(context, S.of(context).pleaseWait);
|
||||
await dialog.show();
|
||||
try {
|
||||
await UserService.instance.terminateSession(session.token);
|
||||
|
@ -122,8 +123,8 @@ class _SessionsPageState extends State<SessionsPage> {
|
|||
_logger.severe('failed to terminate');
|
||||
showErrorDialog(
|
||||
context,
|
||||
'Oops',
|
||||
"Something went wrong, please try again",
|
||||
S.of(context).oops,
|
||||
S.of(context).somethingWentWrongPleaseTryAgain,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -148,15 +149,15 @@ class _SessionsPageState extends State<SessionsPage> {
|
|||
session.token == Configuration.instance.getToken();
|
||||
Widget text;
|
||||
if (isLoggingOutFromThisDevice) {
|
||||
text = const Text(
|
||||
"This will log you out of this device!",
|
||||
text = Text(
|
||||
S.of(context).thisWillLogYouOutOfThisDevice,
|
||||
);
|
||||
} else {
|
||||
text = SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
"This will log you out of the following device:",
|
||||
Text(
|
||||
S.of(context).thisWillLogYouOutOfTheFollowingDevice,
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8)),
|
||||
Text(
|
||||
|
@ -168,13 +169,13 @@ class _SessionsPageState extends State<SessionsPage> {
|
|||
);
|
||||
}
|
||||
final AlertDialog alert = AlertDialog(
|
||||
title: const Text("Terminate session?"),
|
||||
title: Text(S.of(context).terminateSession),
|
||||
content: text,
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text(
|
||||
"Terminate",
|
||||
style: TextStyle(
|
||||
child: Text(
|
||||
S.of(context).terminate,
|
||||
style: const TextStyle(
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
|
@ -189,7 +190,7 @@ class _SessionsPageState extends State<SessionsPage> {
|
|||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
"Cancel",
|
||||
S.of(context).cancel,
|
||||
style: TextStyle(
|
||||
color: isLoggingOutFromThisDevice
|
||||
? Theme.of(context).colorScheme.greenAlternative
|
||||
|
@ -214,7 +215,7 @@ class _SessionsPageState extends State<SessionsPage> {
|
|||
Widget _getUAWidget(Session session) {
|
||||
if (session.token == Configuration.instance.getToken()) {
|
||||
return Text(
|
||||
"This device",
|
||||
S.of(context).thisDevice,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).colorScheme.greenAlternative,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/lifecycle_event_handler.dart';
|
||||
import 'package:pinput/pin_put/pin_put.dart';
|
||||
|
@ -51,8 +52,8 @@ class _TwoFactorAuthenticationPageState
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
"Two-factor authentication",
|
||||
title: Text(
|
||||
S.of(context).twofactorAuthenticationPageTitle,
|
||||
),
|
||||
),
|
||||
body: _getBody(),
|
||||
|
@ -65,9 +66,9 @@ class _TwoFactorAuthenticationPageState
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const Text(
|
||||
"Enter the 6-digit code from\nyour authenticator app",
|
||||
style: TextStyle(
|
||||
Text(
|
||||
S.of(context).enterThe6digitCodeFromnyourAuthenticatorApp,
|
||||
style: const TextStyle(
|
||||
height: 1.4,
|
||||
fontSize: 16,
|
||||
),
|
||||
|
@ -116,7 +117,7 @@ class _TwoFactorAuthenticationPageState
|
|||
_verifyTwoFactorCode(_code);
|
||||
}
|
||||
: null,
|
||||
child: const Text("Verify"),
|
||||
child: Text(S.of(context).verify),
|
||||
),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(30)),
|
||||
|
@ -127,10 +128,10 @@ class _TwoFactorAuthenticationPageState
|
|||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: const Center(
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Lost device?",
|
||||
style: TextStyle(
|
||||
S.of(context).lostDevice,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 12,
|
||||
),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/utils/dialog_util.dart';
|
||||
|
||||
|
@ -27,9 +28,9 @@ class _TwoFactorRecoveryPageState extends State<TwoFactorRecoveryPage> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
"Recover account",
|
||||
style: TextStyle(
|
||||
title: Text(
|
||||
S.of(context).recoverAccount,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
|
@ -42,9 +43,9 @@ class _TwoFactorRecoveryPageState extends State<TwoFactorRecoveryPage> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(60, 0, 60, 0),
|
||||
child: TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
hintText: "Enter your recovery key",
|
||||
contentPadding: EdgeInsets.all(20),
|
||||
decoration: InputDecoration(
|
||||
hintText: S.of(context).enterYourRecoveryKey,
|
||||
contentPadding: const EdgeInsets.all(20),
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
|
@ -77,7 +78,7 @@ class _TwoFactorRecoveryPageState extends State<TwoFactorRecoveryPage> {
|
|||
);
|
||||
}
|
||||
: null,
|
||||
child: const Text("Recover"),
|
||||
child: Text(S.of(context).recover),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
|
@ -85,15 +86,15 @@ class _TwoFactorRecoveryPageState extends State<TwoFactorRecoveryPage> {
|
|||
onTap: () {
|
||||
showErrorDialog(
|
||||
context,
|
||||
"Contact support",
|
||||
"Please drop an email to support@ente.io from your registered email address",
|
||||
S.of(context).contactSupport,
|
||||
S.of(context).dropSupportEmail("support@ente.io"),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(40),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"No recovery key?",
|
||||
S.of(context).noRecoveryKey,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 12,
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/ente_theme_data.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/services/user_service.dart';
|
||||
import 'package:photos/ui/account/recovery_key_page.dart';
|
||||
import 'package:photos/ui/lifecycle_event_handler.dart';
|
||||
|
@ -75,8 +76,8 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
|||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
title: const Text(
|
||||
"Two-factor setup",
|
||||
title: Text(
|
||||
S.of(context).twofactorSetup,
|
||||
),
|
||||
),
|
||||
body: _getBody(),
|
||||
|
@ -97,12 +98,12 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
|||
TabBar(
|
||||
labelColor: Theme.of(context).colorScheme.greenAlternative,
|
||||
unselectedLabelColor: Colors.grey,
|
||||
tabs: const [
|
||||
tabs: [
|
||||
Tab(
|
||||
text: "Enter code",
|
||||
text: S.of(context).enterCode,
|
||||
),
|
||||
Tab(
|
||||
text: "Scan code",
|
||||
text: S.of(context).scanCode,
|
||||
)
|
||||
],
|
||||
controller: _tabController,
|
||||
|
@ -137,15 +138,15 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
|||
return GestureDetector(
|
||||
onTap: () async {
|
||||
await Clipboard.setData(ClipboardData(text: widget.secretCode));
|
||||
showShortToast(context, "Code copied to clipboard");
|
||||
showShortToast(context, S.of(context).codeCopiedToClipboard);
|
||||
},
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Padding(padding: EdgeInsets.all(12)),
|
||||
const Text(
|
||||
"Copy-paste this code\nto your authenticator app",
|
||||
style: TextStyle(
|
||||
Text(
|
||||
S.of(context).copypasteThisCodentoYourAuthenticatorApp,
|
||||
style: const TextStyle(
|
||||
height: 1.4,
|
||||
fontSize: 16,
|
||||
),
|
||||
|
@ -171,7 +172,7 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
|||
),
|
||||
const Padding(padding: EdgeInsets.all(6)),
|
||||
Text(
|
||||
"tap to copy",
|
||||
S.of(context).tapToCopy,
|
||||
style: TextStyle(color: textColor.withOpacity(0.5)),
|
||||
)
|
||||
],
|
||||
|
@ -184,9 +185,9 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
|||
child: Column(
|
||||
children: [
|
||||
const Padding(padding: EdgeInsets.all(12)),
|
||||
const Text(
|
||||
"Scan this barcode with\nyour authenticator app",
|
||||
style: TextStyle(
|
||||
Text(
|
||||
S.of(context).scanThisBarcodeWithnyourAuthenticatorApp,
|
||||
style: const TextStyle(
|
||||
height: 1.4,
|
||||
fontSize: 16,
|
||||
),
|
||||
|
@ -207,9 +208,9 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
|||
return Column(
|
||||
children: [
|
||||
const Padding(padding: EdgeInsets.all(12)),
|
||||
const Text(
|
||||
"Enter the 6-digit code from\nyour authenticator app",
|
||||
style: TextStyle(
|
||||
Text(
|
||||
S.of(context).enterThe6digitCodeFromnyourAuthenticatorApp,
|
||||
style: const TextStyle(
|
||||
height: 1.4,
|
||||
fontSize: 16,
|
||||
),
|
||||
|
@ -253,7 +254,7 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
|||
_enableTwoFactor(_code);
|
||||
}
|
||||
: null,
|
||||
child: const Text("Confirm"),
|
||||
child: Text(S.of(context).confirm),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.only(bottom: 24)),
|
||||
],
|
||||
|
@ -275,13 +276,12 @@ class _TwoFactorSetupPageState extends State<TwoFactorSetupPage>
|
|||
context,
|
||||
RecoveryKeyPage(
|
||||
recoveryKey,
|
||||
"OK",
|
||||
S.of(context).ok,
|
||||
showAppBar: true,
|
||||
onDone: () {},
|
||||
title: "Setup complete",
|
||||
text: "Save your recovery key if you haven't already",
|
||||
subText:
|
||||
"This can be used to recover your account if you lose your second factor",
|
||||
title: S.of(context).setupComplete,
|
||||
text: S.of(context).saveYourRecoveryKeyIfYouHaventAlready,
|
||||
subText: S.of(context).thisCanBeUsedToRecoverYourAccountIfYou,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:logging/logging.dart';
|
|||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/ente_theme_data.dart';
|
||||
import 'package:photos/events/notification_event.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/services/local_authentication_service.dart';
|
||||
import 'package:photos/services/user_remote_flag_service.dart';
|
||||
import 'package:photos/services/user_service.dart';
|
||||
|
@ -29,7 +30,8 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
final Logger _logger = Logger((_VerifyRecoveryPageState).toString());
|
||||
|
||||
void _verifyRecoveryKey() async {
|
||||
final dialog = createProgressDialog(context, "Verifying recovery key...");
|
||||
final dialog =
|
||||
createProgressDialog(context, S.of(context).verifyingRecoveryKey);
|
||||
await dialog.show();
|
||||
try {
|
||||
final String inputKey = _recoveryKey.text.trim();
|
||||
|
@ -58,10 +60,8 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
// todo: change this as per figma once the component is ready
|
||||
await showErrorDialog(
|
||||
context,
|
||||
"Recovery key verified",
|
||||
"Great! Your recovery key is valid. Thank you for verifying.\n"
|
||||
"\nPlease"
|
||||
" remember to keep your recovery key safely backed up.",
|
||||
S.of(context).recoveryKeyVerified,
|
||||
S.of(context).recoveryKeySuccessBody,
|
||||
);
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
|
@ -70,16 +70,13 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
} catch (e, s) {
|
||||
_logger.severe("failed to verify recovery key", e, s);
|
||||
await dialog.hide();
|
||||
const String errMessage =
|
||||
"The recovery key you entered is not valid. Please make sure it "
|
||||
"contains 24 words, and check the spelling of each.\n\nIf you "
|
||||
"entered an older recovery code, make sure it is 64 characters long, and check each of them.";
|
||||
final String errMessage = S.of(context).invalidRecoveryKey;
|
||||
final result = await showChoiceDialog(
|
||||
context,
|
||||
title: "Invalid key",
|
||||
title: S.of(context).invalidKey,
|
||||
body: errMessage,
|
||||
firstButtonLabel: "Try again",
|
||||
secondButtonLabel: "View recovery key",
|
||||
firstButtonLabel: S.of(context).tryAgain,
|
||||
secondButtonLabel: S.of(context).viewRecoveryKey,
|
||||
secondButtonAction: ButtonAction.second,
|
||||
);
|
||||
if (result!.action == ButtonAction.second) {
|
||||
|
@ -104,7 +101,7 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
context,
|
||||
RecoveryKeyPage(
|
||||
recoveryKey,
|
||||
"OK",
|
||||
S.of(context).ok,
|
||||
showAppBar: true,
|
||||
onDone: () {
|
||||
Navigator.of(context).pop();
|
||||
|
@ -149,14 +146,14 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: Text(
|
||||
'Confirm recovery key',
|
||||
S.of(context).confirmRecoveryKey,
|
||||
style: enteTheme.textTheme.h3Bold,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
Text(
|
||||
"Your recovery key is the only way to recover your photos if you forget your password. You can find your recovery key in Settings > Account.\n\nPlease enter your recovery key here to verify that you have saved it correctly.",
|
||||
S.of(context).recoveryKeyVerifyReason,
|
||||
style: enteTheme.textTheme.small
|
||||
.copyWith(color: enteTheme.colorScheme.textMuted),
|
||||
),
|
||||
|
@ -164,7 +161,7 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
TextFormField(
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
hintText: "Enter your recovery key",
|
||||
hintText: S.of(context).enterYourRecoveryKey,
|
||||
contentPadding: const EdgeInsets.all(20),
|
||||
border: UnderlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
|
@ -197,7 +194,7 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
children: [
|
||||
GradientButton(
|
||||
onTap: _verifyRecoveryKey,
|
||||
text: "Confirm",
|
||||
text: S.of(context).confirm,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:photos/core/event_bus.dart';
|
|||
import 'package:photos/ente_theme_data.dart';
|
||||
import 'package:photos/events/notification_event.dart';
|
||||
import 'package:photos/events/sync_status_update_event.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/services/sync_service.dart';
|
||||
import 'package:photos/services/user_remote_flag_service.dart';
|
||||
import 'package:photos/theme/text_style.dart';
|
||||
|
@ -100,14 +101,14 @@ class _StatusBarWidgetState extends State<StatusBarWidget> {
|
|||
_showErrorBanner
|
||||
? HeaderErrorWidget(error: _syncError)
|
||||
: const SizedBox.shrink(),
|
||||
UserRemoteFlagService.instance.shouldShowRecoveryVerification()
|
||||
!UserRemoteFlagService.instance.shouldShowRecoveryVerification()
|
||||
? Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12),
|
||||
child: NotificationWidget(
|
||||
startIcon: Icons.error_outline,
|
||||
actionIcon: Icons.arrow_forward,
|
||||
text: "Confirm your recovery key",
|
||||
text: S.of(context).confirmYourRecoveryKey,
|
||||
onTap: () async => {
|
||||
await routeToPage(
|
||||
context,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:email_validator/email_validator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/models/collection.dart';
|
||||
import 'package:photos/services/collections_service.dart';
|
||||
import 'package:photos/theme/ente_theme.dart';
|
||||
|
@ -60,7 +61,9 @@ class _AddParticipantPage extends State<AddParticipantPage> {
|
|||
return Scaffold(
|
||||
resizeToAvoidBottomInset: isKeypadOpen,
|
||||
appBar: AppBar(
|
||||
title: Text(widget.isAddingViewer ? "Add viewer" : "Add collaborator"),
|
||||
title: Text(widget.isAddingViewer
|
||||
? S.of(context).addViewer
|
||||
: S.of(context).addCollaborator),
|
||||
),
|
||||
body: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
|
@ -70,7 +73,7 @@ class _AddParticipantPage extends State<AddParticipantPage> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text(
|
||||
"Add a new email",
|
||||
S.of(context).addANewEmail,
|
||||
style: enteTextTheme.small
|
||||
.copyWith(color: enteColorScheme.textMuted),
|
||||
),
|
||||
|
@ -88,21 +91,22 @@ class _AddParticipantPage extends State<AddParticipantPage> {
|
|||
child: Column(
|
||||
children: [
|
||||
!isEmailListEmpty
|
||||
? const MenuSectionTitle(
|
||||
title: "Or pick an existing one",
|
||||
? MenuSectionTitle(
|
||||
title: S.of(context).orPickAnExistingOne,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= suggestedUsers.length) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: MenuSectionDescriptionWidget(
|
||||
content:
|
||||
"Collaborators can add photos and videos to the shared album.",
|
||||
content: S
|
||||
.of(context)
|
||||
.collaboratorsCanAddPhotosAndVideosToTheSharedAlbum,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -176,8 +180,8 @@ class _AddParticipantPage extends State<AddParticipantPage> {
|
|||
buttonType: ButtonType.primary,
|
||||
buttonSize: ButtonSize.large,
|
||||
labelText: widget.isAddingViewer
|
||||
? "Add viewer"
|
||||
: "Add collaborator",
|
||||
? S.of(context).addViewer
|
||||
: S.of(context).addCollaborator,
|
||||
isDisabled: (selectedEmail == '' && !_emailIsValid),
|
||||
onTap: (selectedEmail == '' && !_emailIsValid)
|
||||
? null
|
||||
|
@ -204,8 +208,8 @@ class _AddParticipantPage extends State<AddParticipantPage> {
|
|||
if ((selectedEmail == '' && !_emailIsValid)) {
|
||||
await showErrorDialog(
|
||||
context,
|
||||
"Invalid email address",
|
||||
"Please enter a valid email address.",
|
||||
S.of(context).invalidEmailAddress,
|
||||
S.of(context).enterValidEmail,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -261,7 +265,7 @@ class _AddParticipantPage extends State<AddParticipantPage> {
|
|||
),
|
||||
fillColor: getEnteColorScheme(context).fillFaint,
|
||||
filled: true,
|
||||
hintText: 'Enter email',
|
||||
hintText: S.of(context).enterEmail,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 14,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/extensions/list.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/models/collection.dart';
|
||||
import 'package:photos/theme/ente_theme.dart';
|
||||
import 'package:photos/ui/components/captioned_text_widget.dart';
|
||||
|
@ -95,14 +96,14 @@ class _AlbumParticipantsPageState extends State<AlbumParticipantsPage> {
|
|||
children: [
|
||||
Column(
|
||||
children: [
|
||||
const MenuSectionTitle(
|
||||
title: "Owner",
|
||||
MenuSectionTitle(
|
||||
title: S.of(context).albumOwner,
|
||||
iconData: Icons.admin_panel_settings_outlined,
|
||||
),
|
||||
MenuItemWidget(
|
||||
captionedTextWidget: CaptionedTextWidget(
|
||||
title: isOwner
|
||||
? "You"
|
||||
? S.of(context).you
|
||||
: widget.collection.owner?.email ?? '',
|
||||
makeTextBold: isOwner,
|
||||
),
|
||||
|
@ -130,8 +131,8 @@ class _AlbumParticipantsPageState extends State<AlbumParticipantsPage> {
|
|||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index == 0 && (isOwner || collaborators.isNotEmpty)) {
|
||||
return const MenuSectionTitle(
|
||||
title: "Collaborator",
|
||||
return MenuSectionTitle(
|
||||
title: S.of(context).collaborator,
|
||||
iconData: Icons.edit_outlined,
|
||||
);
|
||||
} else if (index > 0 && index <= collaborators.length) {
|
||||
|
@ -146,7 +147,7 @@ class _AlbumParticipantsPageState extends State<AlbumParticipantsPage> {
|
|||
MenuItemWidget(
|
||||
captionedTextWidget: CaptionedTextWidget(
|
||||
title: isSameAsLoggedInUser
|
||||
? "You"
|
||||
? S.of(context).you
|
||||
: currentUser.email,
|
||||
makeTextBold: isSameAsLoggedInUser,
|
||||
),
|
||||
|
@ -182,8 +183,8 @@ class _AlbumParticipantsPageState extends State<AlbumParticipantsPage> {
|
|||
return MenuItemWidget(
|
||||
captionedTextWidget: CaptionedTextWidget(
|
||||
title: collaborators.isNotEmpty
|
||||
? "Add more"
|
||||
: "Add collaborator",
|
||||
? S.of(context).addMore
|
||||
: S.of(context).addCollaborator,
|
||||
makeTextBold: true,
|
||||
),
|
||||
leadingIcon: Icons.add_outlined,
|
||||
|
@ -207,8 +208,8 @@ class _AlbumParticipantsPageState extends State<AlbumParticipantsPage> {
|
|||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index == 0 && (isOwner || viewers.isNotEmpty)) {
|
||||
return const MenuSectionTitle(
|
||||
title: "Viewer",
|
||||
return MenuSectionTitle(
|
||||
title: S.of(context).viewer,
|
||||
iconData: Icons.photo_outlined,
|
||||
);
|
||||
} else if (index > 0 && index <= viewers.length) {
|
||||
|
@ -222,7 +223,7 @@ class _AlbumParticipantsPageState extends State<AlbumParticipantsPage> {
|
|||
MenuItemWidget(
|
||||
captionedTextWidget: CaptionedTextWidget(
|
||||
title: isSameAsLoggedInUser
|
||||
? "You"
|
||||
? S.of(context).you
|
||||
: currentUser.email,
|
||||
makeTextBold: isSameAsLoggedInUser,
|
||||
),
|
||||
|
@ -257,7 +258,9 @@ class _AlbumParticipantsPageState extends State<AlbumParticipantsPage> {
|
|||
} else if (index == (1 + viewers.length) && isOwner) {
|
||||
return MenuItemWidget(
|
||||
captionedTextWidget: CaptionedTextWidget(
|
||||
title: viewers.isNotEmpty ? "Add more" : "Add viewer",
|
||||
title: viewers.isNotEmpty
|
||||
? S.of(context).addMore
|
||||
: S.of(context).addViewer,
|
||||
makeTextBold: true,
|
||||
),
|
||||
leadingIcon: Icons.add_outlined,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import 'package:photos/models/collection.dart';
|
||||
import 'package:photos/services/collections_service.dart';
|
||||
import 'package:photos/theme/colors.dart';
|
||||
|
@ -52,8 +53,8 @@ class _ManageIndividualParticipantState
|
|||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
const TitleBarTitleWidget(
|
||||
title: "Manage",
|
||||
TitleBarTitleWidget(
|
||||
title: S.of(context).manage,
|
||||
),
|
||||
Text(
|
||||
widget.user.email.toString().trim(),
|
||||
|
@ -65,10 +66,10 @@ class _ManageIndividualParticipantState
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const MenuSectionTitle(title: "Added as"),
|
||||
MenuSectionTitle(title: S.of(context).addedAs),
|
||||
MenuItemWidget(
|
||||
captionedTextWidget: const CaptionedTextWidget(
|
||||
title: "Collaborator",
|
||||
captionedTextWidget: CaptionedTextWidget(
|
||||
title: S.of(context).collaborator,
|
||||
),
|
||||
leadingIcon: Icons.edit_outlined,
|
||||
menuItemColor: getEnteColorScheme(context).fillFaint,
|
||||
|
@ -97,8 +98,8 @@ class _ManageIndividualParticipantState
|
|||
bgColor: getEnteColorScheme(context).fillFaint,
|
||||
),
|
||||
MenuItemWidget(
|
||||
captionedTextWidget: const CaptionedTextWidget(
|
||||
title: "Viewer",
|
||||
captionedTextWidget: CaptionedTextWidget(
|
||||
title: S.of(context).viewer,
|
||||
),
|
||||
leadingIcon: Icons.photo_outlined,
|
||||
leadingIconColor: getEnteColorScheme(context).strokeBase,
|
||||
|
@ -110,10 +111,12 @@ class _ManageIndividualParticipantState
|
|||
: () async {
|
||||
final actionResult = await showChoiceActionSheet(
|
||||
context,
|
||||
title: "Change permissions?",
|
||||
firstButtonLabel: "Yes, convert to viewer",
|
||||
body:
|
||||
'${widget.user.email} will not be able to add more photos to this album\n\nThey will still be able to remove existing photos added by them',
|
||||
title: S.of(context).changePermissions,
|
||||
firstButtonLabel: S.of(context).yesConvertToViewer,
|
||||
body: S
|
||||
.of(context)
|
||||
.cannotAddMorePhotosAfterBecomingViewer(
|
||||
widget.user.email),
|
||||
isCritical: true,
|
||||
);
|
||||
if (actionResult?.action != null) {
|
||||
|
@ -141,15 +144,16 @@ class _ManageIndividualParticipantState
|
|||
},
|
||||
isTopBorderRadiusRemoved: true,
|
||||
),
|
||||
const MenuSectionDescriptionWidget(
|
||||
content:
|
||||
"Collaborators can add photos and videos to the shared album.",
|
||||
MenuSectionDescriptionWidget(
|
||||
content: S
|
||||
.of(context)
|
||||
.collaboratorsCanAddPhotosAndVideosToTheSharedAlbum,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const MenuSectionTitle(title: "Remove participant"),
|
||||
MenuSectionTitle(title: S.of(context).removeParticipant),
|
||||
MenuItemWidget(
|
||||
captionedTextWidget: const CaptionedTextWidget(
|
||||
title: "Remove",
|
||||
captionedTextWidget: CaptionedTextWidget(
|
||||
title: S.of(context).remove,
|
||||
textColor: warning500,
|
||||
makeTextBold: true,
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue