diff --git a/auth/lib/l10n/arb/app_en.arb b/auth/lib/l10n/arb/app_en.arb index 78f111d6a9..5a82718034 100644 --- a/auth/lib/l10n/arb/app_en.arb +++ b/auth/lib/l10n/arb/app_en.arb @@ -141,16 +141,6 @@ "oops": "Oops", "suggestFeatures": "Suggest features", "faq": "FAQ", - "faq_q_1": "How secure is Auth?", - "faq_a_1": "All codes you backup via Auth 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 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?", diff --git a/auth/lib/onboarding/view/onboarding_page.dart b/auth/lib/onboarding/view/onboarding_page.dart index dff1fbc179..af8793d9ab 100644 --- a/auth/lib/onboarding/view/onboarding_page.dart +++ b/auth/lib/onboarding/view/onboarding_page.dart @@ -8,6 +8,7 @@ import 'package:ente_auth/ente_theme_data.dart'; import 'package:ente_auth/events/trigger_logout_event.dart'; import "package:ente_auth/l10n/l10n.dart"; import 'package:ente_auth/locale.dart'; +import 'package:ente_auth/services/preference_service.dart'; import 'package:ente_auth/theme/text_style.dart'; import 'package:ente_auth/ui/account/email_entry_page.dart'; import 'package:ente_auth/ui/account/login_page.dart'; @@ -49,6 +50,7 @@ class _OnboardingPageState extends State { await autoLogoutAlert(context); }); super.initState(); + PreferenceService.instance.configureDefaults().ignore(); } @override diff --git a/auth/lib/services/preference_service.dart b/auth/lib/services/preference_service.dart index ba43e69be3..73dc00fad9 100644 --- a/auth/lib/services/preference_service.dart +++ b/auth/lib/services/preference_service.dart @@ -57,6 +57,12 @@ class PreferenceService { await _prefs.setBool(kCompactMode, value); } + Future configureDefaults() async { + if (!_prefs.containsKey(kCompactMode)) { + await _prefs.setBool(kCompactMode, true); + } + } + Future setHideCodes(bool value) async { await _prefs.setBool(kShouldHideCodesKey, value); Bus.instance.fire(IconsChangedEvent()); diff --git a/auth/lib/ui/home/home_empty_state.dart b/auth/lib/ui/home/home_empty_state.dart index 0632364ea4..68d9044aa6 100644 --- a/auth/lib/ui/home/home_empty_state.dart +++ b/auth/lib/ui/home/home_empty_state.dart @@ -1,10 +1,10 @@ import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/theme/ente_theme.dart'; import 'package:ente_auth/ui/settings/data/import_page.dart'; -import 'package:ente_auth/ui/settings/faq.dart'; import 'package:ente_auth/utils/navigation_util.dart'; import 'package:ente_auth/utils/platform_util.dart'; import 'package:flutter/material.dart'; +import 'package:logging/logging.dart'; class HomeEmptyStateWidget extends StatelessWidget { final VoidCallback? onScanTap; @@ -73,15 +73,16 @@ class HomeEmptyStateWidget extends StatelessWidget { const SizedBox(height: 18), InkWell( onTap: () { - showModalBottomSheet( - backgroundColor: - Theme.of(context).colorScheme.surface, - barrierColor: Colors.black87, - context: context, - builder: (context) { - return const FAQQuestionsWidget(); - }, - ); + try { + PlatformUtil.openWebView( + context, + context.l10n.faq, + "https://help.ente.io/auth/faq", + ); + } catch (e) { + Logger("HomeEmptyStateWidget") + .severe("Failed to open FAQ", e); + } }, child: Text( l10n.faq, diff --git a/auth/lib/ui/settings/faq.dart b/auth/lib/ui/settings/faq.dart deleted file mode 100644 index 5f441912eb..0000000000 --- a/auth/lib/ui/settings/faq.dart +++ /dev/null @@ -1,124 +0,0 @@ -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({ - super.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({ - super.key, - required this.faq, - }); - - 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/auth/lib/ui/settings/support_section_widget.dart b/auth/lib/ui/settings/support_section_widget.dart index 057c5dd389..720096dda2 100644 --- a/auth/lib/ui/settings/support_section_widget.dart +++ b/auth/lib/ui/settings/support_section_widget.dart @@ -5,8 +5,8 @@ import 'package:ente_auth/ui/components/captioned_text_widget.dart'; import 'package:ente_auth/ui/components/expandable_menu_item_widget.dart'; import 'package:ente_auth/ui/components/menu_item_widget.dart'; import 'package:ente_auth/ui/settings/common_settings.dart'; -import 'package:ente_auth/ui/settings/faq.dart'; import 'package:ente_auth/utils/email_util.dart'; +import 'package:ente_auth/utils/platform_util.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -42,15 +42,15 @@ class _SupportSectionWidgetState extends State { trailingIcon: Icons.chevron_right_outlined, trailingIconIsMuted: true, onTap: () async { - // ignore: unawaited_futures - showModalBottomSheet( - backgroundColor: Theme.of(context).colorScheme.surface, - barrierColor: Colors.black87, - context: context, - builder: (context) { - return const FAQQuestionsWidget(); - }, - ); + try { + PlatformUtil.openWebView( + context, + context.l10n.faq, + "https://help.ente.io/auth/faq", + ); + } catch (e) { + Logger("SupportSection").severe("Failed to open FAQ", e); + } }, ), sectionOptionSpacing, diff --git a/auth/lib/utils/dialog_util.dart b/auth/lib/utils/dialog_util.dart index 6c58e1f861..fd2111abfd 100644 --- a/auth/lib/utils/dialog_util.dart +++ b/auth/lib/utils/dialog_util.dart @@ -1,3 +1,4 @@ +import 'dart:io'; import 'dart:math'; import 'package:confetti/confetti.dart'; @@ -14,6 +15,7 @@ import 'package:ente_auth/ui/components/dialog_widget.dart'; import 'package:ente_auth/ui/components/models/button_result.dart'; import 'package:ente_auth/ui/components/models/button_type.dart'; import 'package:ente_auth/utils/email_util.dart'; +import 'package:ente_auth/utils/platform_util.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -140,11 +142,19 @@ Future showGenericErrorDialog({ bool isDismissible = true, required Object? error, }) async { - final errorBody = parseErrorForUI( + String errorBody = parseErrorForUI( context, context.l10n.itLooksLikeSomethingWentWrongPleaseRetryAfterSome, error: error, ); + bool isWindowCertError = false; + if (Platform.isWindows && + error != null && + error.toString().contains("CERTIFICATE_VERIFY_FAILED")) { + isWindowCertError = true; + errorBody = + "Certificate verification failed. Please update your system certificates, & restart the app. If the issue persists, please contact support."; + } return showDialogWidget( context: context, @@ -159,6 +169,20 @@ Future showGenericErrorDialog({ buttonAction: ButtonAction.first, isInAlert: true, ), + if (isWindowCertError) + ButtonWidget( + buttonType: ButtonType.neutral, + labelText: 'Update Certificates', + buttonAction: ButtonAction.third, + isInAlert: true, + onTap: () async { + PlatformUtil.openWebView( + context, + context.l10n.faq, + "https://help.ente.io/auth/troubleshooting/windows-login", + ); + }, + ), ButtonWidget( buttonType: ButtonType.secondary, labelText: context.l10n.contactSupport,