diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb
index 413773ab5..47597b395 100644
--- a/lib/l10n/arb/app_en.arb
+++ b/lib/l10n/arb/app_en.arb
@@ -1,4 +1,3 @@
-
{
"account": "Account",
"recoveryKey": "Recovery key",
@@ -14,10 +13,10 @@
"importAccountPageTitle": "Enter account details",
"secretCanNotBeEmpty": "Secret can not be empty",
"bothIssuerAndAccountCanNotBeEmpty": "Both issuer and account can not be empty",
- "incorrectDetails" :"Incorrect details",
+ "incorrectDetails": "Incorrect details",
"pleaseVerifyDetails": "Please verify the details and try again",
"codeIssuerHint": "Issuer",
- "codeSecretKeyHint" : "Secret Key",
+ "codeSecretKeyHint": "Secret Key",
"codeAccountHint": "Account (you@domain.com)",
"accountKeyType": "Type of key",
"sessionExpired": "Session expired",
@@ -25,7 +24,7 @@
"description": "Title of the dialog when the users current session is invalid/expired"
},
"pleaseLoginAgain": "Please login again",
- "loggingOut" : "Logging out...",
+ "loggingOut": "Logging out...",
"timeBasedKeyType": "Time based (TOTP)",
"counterBasedKeyType": "Counter based (HOTP)",
"saveAction": "Save",
@@ -67,15 +66,15 @@
"incorrectPasswordTitle": "Incorrect password",
"welcomeBack": "Welcome back!",
"madeWithLoveAtPrefix": "made with ❤️ at ",
- "supportDevs" : "Subscribe to ente to support this project.",
- "supportDiscount" : "Use coupon code \"AUTH\" to get 10% off first year",
+ "supportDevs": "Subscribe to ente to support this project.",
+ "supportDiscount": "Use coupon code \"AUTH\" to get 10% off first year",
"changeEmail": "Change email",
"changePassword": "Change password",
- "data" : "Data",
+ "data": "Data",
"importCodes": "Import codes",
"importTypePlainText": "Plain text",
"importTypeEnteEncrypted": "ente Encrypted export",
- "passwordForDecryptingExport" : "Password to decrypt export",
+ "passwordForDecryptingExport": "Password to decrypt export",
"passwordEmptyError": "Password can not be empty",
"importFromApp": "Import codes from {appName}",
"importGoogleAuthGuide": "Export your accounts from Google Authenticator to a QR code using the \"Transfer Accounts\" option. Then using another device, scan the QR code.",
@@ -102,11 +101,22 @@
"copied": "Copied",
"pleaseTryAgain": "Please try again",
"existingUser": "Existing User",
- "newUser" : "New to ente",
+ "newUser": "New to ente",
"delete": "Delete",
"enterYourPasswordHint": "Enter your password",
"forgotPassword": "Forgot password",
"oops": "Oops",
+ "faq": "FAQ",
+ "faq_q_1": "How secure is ente Auth?",
+ "faq_a_1": "All codes you backup via ente is stored end-to-end encrypted. This means only you can access your codes. Our apps are open source and our cryptography has been externally audited.",
+ "faq_q_2": "Can I access my codes on desktop?",
+ "faq_a_2": "You can access your codes on the web @ auth.ente.io.",
+ "faq_q_3": "How can I delete codes?",
+ "faq_a_3": "You can delete a code by swiping left on that item.",
+ "faq_q_4": "How can I support this project?",
+ "faq_a_4": "You can support the development of this project by subscribing to our Photos app @ ente.io.",
+ "faq_q_5": "How can I enable FaceID lock in ente Auth",
+ "faq_a_5": "You can enable FaceID lock under Settings → Security → Lockscreen.",
"somethingWentWrongMessage": "Something went wrong, please try again",
"leaveFamily": "Leave family",
"leaveFamilyMessage": "Are you sure that you want to leave the family plan?",
@@ -122,7 +132,7 @@
"recoverAccount": "Recover account",
"enterRecoveryKeyHint": "Enter your recovery key",
"recover": "Recover",
- "contactSupportViaEmailMessage":"Please drop an email to {email} from your registered email address",
+ "contactSupportViaEmailMessage": "Please drop an email to {email} from your registered email address",
"@contactSupportViaEmailMessage": {
"placeholders": {
"email": {
@@ -187,7 +197,7 @@
"message": "Password Strength: {passwordStrengthText}"
},
"password": "Password",
- "signUpTerms" : "I agree to the terms of service and privacy policy",
+ "signUpTerms": "I agree to the terms of service and privacy policy",
"privacyPolicyTitle": "Privacy Policy",
"termsOfServicesTitle": "Terms",
"encryption": "Encryption",
@@ -240,14 +250,14 @@
"youAreOnTheLatestVersion": "You are on the latest version",
"warning": "Warning",
"exportWarningDesc": "The exported file contains sensitive information. Please store this safely.",
- "iUnderStand" : "I understand",
+ "iUnderStand": "I understand",
"@iUnderStand": {
"description": "Text for the button to confirm the user understands the warning"
},
"authToExportCodes": "Please authenticate to export your codes",
"importSuccessTitle": "Yay!",
"importSuccessDesc": "You have imported {count} codes!",
- "@importSuccessDesc" : {
+ "@importSuccessDesc": {
"placeholders": {
"count": {
"description": "The number of codes imported",
@@ -256,9 +266,9 @@
}
}
},
- "sorry" : "Sorry",
+ "sorry": "Sorry",
"importFailureDesc": "Could not parse the selected file.\nPlease write to support@ente.io if you need help!",
- "pendingSyncs" : "Warning",
+ "pendingSyncs": "Warning",
"pendingSyncsWarningBody": "Some of your codes have not been backed up.\n\nPlease ensure that you have a backup for these codes before you logout.",
"checkInboxAndSpamFolder": "Please check your inbox (and spam) to complete verification",
"tapToEnterCode": "Tap to enter code",
diff --git a/lib/ui/settings/faq.dart b/lib/ui/settings/faq.dart
new file mode 100644
index 000000000..3d5c78ab8
--- /dev/null
+++ b/lib/ui/settings/faq.dart
@@ -0,0 +1,124 @@
+import 'dart:convert';
+
+import 'package:ente_auth/ente_theme_data.dart';
+import 'package:ente_auth/l10n/l10n.dart';
+import 'package:ente_auth/ui/common/loading_widget.dart';
+import 'package:expansion_tile_card/expansion_tile_card.dart';
+import 'package:flutter/material.dart';
+
+class FAQQuestionsWidget extends StatelessWidget {
+ const FAQQuestionsWidget({
+ Key? key,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return FutureBuilder>(
+ future: Future.value(_getFAQs(context)),
+ builder: (BuildContext context, AsyncSnapshot snapshot) {
+ if (snapshot.hasData) {
+ final faqs = [];
+ faqs.add(
+ Padding(
+ padding: const EdgeInsets.all(24),
+ child: Text(
+ context.l10n.faq,
+ style: const TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ );
+ for (final faq in snapshot.data) {
+ faqs.add(FaqWidget(faq: faq));
+ }
+ faqs.add(
+ const Padding(
+ padding: EdgeInsets.all(16),
+ ),
+ );
+ return SingleChildScrollView(
+ child: Column(
+ children: faqs,
+ ),
+ );
+ } else {
+ return const EnteLoadingWidget();
+ }
+ },
+ );
+ }
+
+ List _getFAQs(BuildContext context) {
+ final l01n = context.l10n;
+ List faqs = [];
+ faqs.add(FaqItem(q: l01n.faq_q_1, a: l01n.faq_a_1));
+ faqs.add(FaqItem(q: l01n.faq_q_2, a: l01n.faq_a_2));
+ faqs.add(FaqItem(q: l01n.faq_q_3, a: l01n.faq_a_3));
+ faqs.add(FaqItem(q: l01n.faq_q_4, a: l01n.faq_a_4));
+ faqs.add(FaqItem(q: l01n.faq_q_5, a: l01n.faq_a_5));
+ return faqs;
+ }
+}
+
+class FaqWidget extends StatelessWidget {
+ const FaqWidget({
+ Key? key,
+ required this.faq,
+ }) : super(key: key);
+
+ final FaqItem? faq;
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.all(2),
+ child: ExpansionTileCard(
+ elevation: 0,
+ title: Text(faq!.q),
+ expandedTextColor: Theme.of(context).colorScheme.alternativeColor,
+ baseColor: Theme.of(context).cardColor,
+ children: [
+ Align(
+ alignment: Alignment.centerLeft,
+ child: Padding(
+ padding: const EdgeInsets.only(
+ left: 16,
+ right: 16,
+ bottom: 12,
+ ),
+ child: Text(
+ faq!.a,
+ style: const TextStyle(
+ height: 1.5,
+ ),
+ ),
+ ),
+ )
+ ],
+ ),
+ );
+ }
+}
+
+class FaqItem {
+ final String q;
+ final String a;
+
+ FaqItem({
+ required this.q,
+ required this.a,
+ });
+
+ factory FaqItem.fromMap(Map map) {
+ return FaqItem(
+ q: map['q'] ?? 'q',
+ a: map['a'] ?? 'a',
+ );
+ }
+
+ factory FaqItem.fromJson(String source) =>
+ FaqItem.fromMap(json.decode(source));
+
+}
diff --git a/lib/ui/settings/support_section_widget.dart b/lib/ui/settings/support_section_widget.dart
index 8695e0664..b06b28b05 100644
--- a/lib/ui/settings/support_section_widget.dart
+++ b/lib/ui/settings/support_section_widget.dart
@@ -7,6 +7,7 @@ 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/toggle_switch_widget.dart';
import 'package:ente_auth/ui/settings/common_settings.dart';
+import 'package:ente_auth/ui/settings/faq.dart';
import 'package:ente_auth/utils/email_util.dart';
import 'package:flutter/material.dart';
@@ -33,6 +34,27 @@ class _SupportSectionWidgetState extends State {
return Column(
children: [
sectionOptionSpacing,
+
+ MenuItemWidget(
+ captionedTextWidget: CaptionedTextWidget(
+ title: l10n.faq,
+ ),
+ pressedColor: getEnteColorScheme(context).fillFaint,
+ trailingIcon: Icons.chevron_right_outlined,
+ trailingIconIsMuted: true,
+ onTap: () async {
+ showModalBottomSheet(
+ backgroundColor: Theme.of(context).colorScheme.background,
+ barrierColor: Colors.black87,
+ context: context,
+ builder: (context) {
+ return const FAQQuestionsWidget();
+ },
+ );
+ },
+ ),
+ sectionOptionSpacing,
+
MenuItemWidget(
captionedTextWidget: CaptionedTextWidget(
title: l10n.email,
diff --git a/pubspec.yaml b/pubspec.yaml
index bd1fd9d38..ef3e11c23 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: ente_auth
description: ente two-factor authenticator
-version: 1.0.43+43
+version: 1.0.50+50
publish_to: none
environment: