Browse Source

Add faq for auth (#178)

Neeraj Gupta 1 year ago
parent
commit
5d682989cd
4 changed files with 172 additions and 16 deletions
  1. 25 15
      lib/l10n/arb/app_en.arb
  2. 124 0
      lib/ui/settings/faq.dart
  3. 22 0
      lib/ui/settings/support_section_widget.dart
  4. 1 1
      pubspec.yaml

+ 25 - 15
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 <bold-green>ente</bold-green> to support this project.",
-  "supportDiscount" : "Use coupon code \"AUTH\" to get 10% off first year",
+  "supportDevs": "Subscribe to <bold-green>ente</bold-green> 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 <u-terms>terms of service</u-terms> and <u-policy>privacy policy</u-policy>",
+  "signUpTerms": "I agree to the <u-terms>terms of service</u-terms> and <u-policy>privacy policy</u-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",

+ 124 - 0
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<List<FaqItem>>(
+      future: Future.value(_getFAQs(context)),
+      builder: (BuildContext context, AsyncSnapshot snapshot) {
+        if (snapshot.hasData) {
+          final faqs = <Widget>[];
+          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<FaqItem> _getFAQs(BuildContext context) {
+    final l01n = context.l10n;
+    List<FaqItem> 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<String, dynamic> map) {
+    return FaqItem(
+      q: map['q'] ?? 'q',
+      a: map['a'] ?? 'a',
+    );
+  }
+
+  factory FaqItem.fromJson(String source) =>
+      FaqItem.fromMap(json.decode(source));
+
+}

+ 22 - 0
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<SupportSectionWidget> {
     return Column(
       children: [
         sectionOptionSpacing,
+
+        MenuItemWidget(
+          captionedTextWidget: CaptionedTextWidget(
+            title: l10n.faq,
+          ),
+          pressedColor: getEnteColorScheme(context).fillFaint,
+          trailingIcon: Icons.chevron_right_outlined,
+          trailingIconIsMuted: true,
+          onTap: () async {
+            showModalBottomSheet<void>(
+              backgroundColor: Theme.of(context).colorScheme.background,
+              barrierColor: Colors.black87,
+              context: context,
+              builder: (context) {
+                return const FAQQuestionsWidget();
+              },
+            );
+          },
+        ),
+        sectionOptionSpacing,
+
         MenuItemWidget(
           captionedTextWidget: CaptionedTextWidget(
             title: l10n.email,

+ 1 - 1
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: