From 3bce3092e3a09b6405f4f152d393c29ea7ad343d Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sat, 6 May 2023 00:00:07 +0530 Subject: [PATCH 1/5] Remove redundant lint ignore rule --- lib/core/configuration.dart | 1 - lib/onboarding/view/onboarding_page.dart | 2 -- lib/onboarding/view/setup_enter_secret_key_page.dart | 1 - lib/ui/components/expandable_menu_item_widget.dart | 1 - lib/ui/home_page.dart | 2 -- 5 files changed, 7 deletions(-) diff --git a/lib/core/configuration.dart b/lib/core/configuration.dart index ed4cf2107f..edf63d10b5 100644 --- a/lib/core/configuration.dart +++ b/lib/core/configuration.dart @@ -6,7 +6,6 @@ import 'package:bip39/bip39.dart' as bip39; import 'package:ente_auth/core/constants.dart'; import 'package:ente_auth/core/errors.dart'; import 'package:ente_auth/core/event_bus.dart'; -// ignore: import_of_legacy_library_into_null_safe import 'package:ente_auth/events/signed_in_event.dart'; import 'package:ente_auth/events/signed_out_event.dart'; import 'package:ente_auth/models/key_attributes.dart'; diff --git a/lib/onboarding/view/onboarding_page.dart b/lib/onboarding/view/onboarding_page.dart index ef27660359..b49a8d1415 100644 --- a/lib/onboarding/view/onboarding_page.dart +++ b/lib/onboarding/view/onboarding_page.dart @@ -1,5 +1,3 @@ -// ignore_for_file: import_of_legacy_library_into_null_safe - import 'dart:async'; import 'package:ente_auth/app/view/app.dart'; diff --git a/lib/onboarding/view/setup_enter_secret_key_page.dart b/lib/onboarding/view/setup_enter_secret_key_page.dart index a6a1d507ba..aa0bc2e611 100644 --- a/lib/onboarding/view/setup_enter_secret_key_page.dart +++ b/lib/onboarding/view/setup_enter_secret_key_page.dart @@ -1,6 +1,5 @@ import "package:ente_auth/l10n/l10n.dart"; import 'package:ente_auth/models/code.dart'; -// ignore: import_of_legacy_library_into_null_safe import 'package:ente_auth/utils/dialog_util.dart'; import 'package:ente_auth/utils/totp_util.dart'; import "package:flutter/material.dart"; diff --git a/lib/ui/components/expandable_menu_item_widget.dart b/lib/ui/components/expandable_menu_item_widget.dart index 5953d135ce..9628078be4 100644 --- a/lib/ui/components/expandable_menu_item_widget.dart +++ b/lib/ui/components/expandable_menu_item_widget.dart @@ -1,7 +1,6 @@ import 'package:ente_auth/ente_theme_data.dart'; import 'package:ente_auth/ui/components/captioned_text_widget.dart'; import 'package:ente_auth/ui/components/menu_item_widget.dart'; -// ignore: import_of_legacy_library_into_null_safe import 'package:ente_auth/ui/settings/common_settings.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/material.dart'; diff --git a/lib/ui/home_page.dart b/lib/ui/home_page.dart index daaad36c2a..7e628dbc74 100644 --- a/lib/ui/home_page.dart +++ b/lib/ui/home_page.dart @@ -1,5 +1,3 @@ -// ignore_for_file: import_of_legacy_library_into_null_safe - import 'dart:async'; import 'dart:io'; import 'dart:ui'; From 4d88503c2b0bf5a908fcbd5cd80122a0507fca36 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sat, 6 May 2023 00:16:07 +0530 Subject: [PATCH 2/5] Extract widget in separate file --- lib/ui/common/report_bug.dart | 1 - lib/ui/home/speed_dial_label_widget.dart | 29 ++++++++++++++++++++++++ lib/ui/home_page.dart | 28 +---------------------- 3 files changed, 30 insertions(+), 28 deletions(-) create mode 100644 lib/ui/home/speed_dial_label_widget.dart diff --git a/lib/ui/common/report_bug.dart b/lib/ui/common/report_bug.dart index f4eca12743..48f0691b04 100644 --- a/lib/ui/common/report_bug.dart +++ b/lib/ui/common/report_bug.dart @@ -1,6 +1,5 @@ import 'package:ente_auth/utils/email_util.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; PopupMenuButton reportBugPopupMenu(BuildContext context) { return PopupMenuButton( diff --git a/lib/ui/home/speed_dial_label_widget.dart b/lib/ui/home/speed_dial_label_widget.dart new file mode 100644 index 0000000000..40c945893e --- /dev/null +++ b/lib/ui/home/speed_dial_label_widget.dart @@ -0,0 +1,29 @@ +import 'package:ente_auth/ente_theme_data.dart'; +import 'package:flutter/material.dart'; + +class SpeedDialLabelWidget extends StatelessWidget { + final String label; + + const SpeedDialLabelWidget( + this.label, { + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(4), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: Theme.of(context).colorScheme.fabBackgroundColor, + ), + child: Text( + label, + style: TextStyle( + color: Theme.of(context).colorScheme.fabForegroundColor, + ), + ), + ); + } +} diff --git a/lib/ui/home_page.dart b/lib/ui/home_page.dart index 7e628dbc74..6a626ec7a8 100644 --- a/lib/ui/home_page.dart +++ b/lib/ui/home_page.dart @@ -15,6 +15,7 @@ import 'package:ente_auth/store/code_store.dart'; import 'package:ente_auth/ui/account/logout_dialog.dart'; import 'package:ente_auth/ui/code_widget.dart'; import 'package:ente_auth/ui/common/loading_widget.dart'; +import 'package:ente_auth/ui/home/speed_dial_label_widget.dart'; import 'package:ente_auth/ui/scanner_page.dart'; import 'package:ente_auth/ui/settings_page.dart'; import 'package:flutter/material.dart'; @@ -397,30 +398,3 @@ class _HomePageState extends State { ); } } - -class SpeedDialLabelWidget extends StatelessWidget { - final String label; - - const SpeedDialLabelWidget( - this.label, { - Key? key, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.all(4), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: Theme.of(context).colorScheme.fabBackgroundColor, - ), - child: Text( - label, - style: TextStyle( - color: Theme.of(context).colorScheme.fabForegroundColor, - ), - ), - ); - } -} From 73c130ce7e08281fb465d1d2630383f586891dca Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sat, 6 May 2023 00:45:34 +0530 Subject: [PATCH 3/5] Add widget for empty state and coach mark --- lib/services/preference_service.dart | 2 +- lib/ui/home/coach_mark_widget.dart | 71 ++++++++++++++++ lib/ui/home/home_empty_state.dart | 61 ++++++++++++++ lib/ui/home_page.dart | 116 ++------------------------- 4 files changed, 140 insertions(+), 110 deletions(-) create mode 100644 lib/ui/home/coach_mark_widget.dart create mode 100644 lib/ui/home/home_empty_state.dart diff --git a/lib/services/preference_service.dart b/lib/services/preference_service.dart index 06ab103094..04e182f82e 100644 --- a/lib/services/preference_service.dart +++ b/lib/services/preference_service.dart @@ -7,7 +7,7 @@ class PreferenceService { late final SharedPreferences _prefs; - static const kHasShownCoachMarkKey = "has_shown_coach_mark"; + static const kHasShownCoachMarkKey = "has_shown_coach_markx"; Future init() async { _prefs = await SharedPreferences.getInstance(); diff --git a/lib/ui/home/coach_mark_widget.dart b/lib/ui/home/coach_mark_widget.dart new file mode 100644 index 0000000000..912758a3a7 --- /dev/null +++ b/lib/ui/home/coach_mark_widget.dart @@ -0,0 +1,71 @@ +import 'dart:ui'; + +import 'package:ente_auth/core/event_bus.dart'; +import 'package:ente_auth/events/codes_updated_event.dart'; +import 'package:ente_auth/l10n/l10n.dart'; +import 'package:ente_auth/services/preference_service.dart'; +import 'package:flutter/material.dart'; + +class CoachMarkWidget extends StatelessWidget { + const CoachMarkWidget({super.key}); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + return GestureDetector( + onTap: () async { + await PreferenceService.instance.setHasShownCoachMark(true); + Bus.instance.fire(CodesUpdatedEvent()); + }, + child: Row( + children: [ + Expanded( + child: Container( + width: double.infinity, + color: Theme.of(context).colorScheme.background.withOpacity(0.1), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.swipe_left, + size: 42, + ), + const SizedBox( + height: 24, + ), + Text( + l10n.swipeHint, + style: Theme.of(context).textTheme.headline6, + ), + const SizedBox( + height: 36, + ), + SizedBox( + width: 160, + child: OutlinedButton( + onPressed: () async { + await PreferenceService.instance + .setHasShownCoachMark(true); + Bus.instance.fire(CodesUpdatedEvent()); + }, + child: Text(l10n.ok), + ), + ) + ], + ), + ], + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/ui/home/home_empty_state.dart b/lib/ui/home/home_empty_state.dart new file mode 100644 index 0000000000..10f45324ff --- /dev/null +++ b/lib/ui/home/home_empty_state.dart @@ -0,0 +1,61 @@ +import 'package:ente_auth/l10n/l10n.dart'; +import 'package:flutter/material.dart'; + +class HomeEmptyStateWidget extends StatelessWidget { + final VoidCallback? onScanTap; + final VoidCallback? onManuallySetupTap; + + const HomeEmptyStateWidget({ + Key? key, + required this.onScanTap, + required this.onManuallySetupTap, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + return Center( + child: ConstrainedBox( + constraints: const BoxConstraints.tightFor(height: 800, width: 450), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 40.0, horizontal: 40), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Image.asset( + "assets/wallet-front-gradient.png", + width: 200, + height: 200, + ), + Text( + l10n.setupFirstAccount, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.headline4, + ), + const SizedBox(height: 64), + SizedBox( + width: 400, + child: OutlinedButton( + onPressed: onScanTap, + child: Text(l10n.importScanQrCode), + ), + ), + const SizedBox(height: 18), + SizedBox( + width: 400, + child: OutlinedButton( + onPressed: onManuallySetupTap, + child: Text(l10n.importEnterSetupKey), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/ui/home_page.dart b/lib/ui/home_page.dart index 6a626ec7a8..10aaa71ac7 100644 --- a/lib/ui/home_page.dart +++ b/lib/ui/home_page.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:io'; -import 'dart:ui'; import 'package:ente_auth/core/event_bus.dart'; import 'package:ente_auth/ente_theme_data.dart'; @@ -15,6 +14,8 @@ import 'package:ente_auth/store/code_store.dart'; import 'package:ente_auth/ui/account/logout_dialog.dart'; import 'package:ente_auth/ui/code_widget.dart'; import 'package:ente_auth/ui/common/loading_widget.dart'; +import 'package:ente_auth/ui/home/coach_mark_widget.dart'; +import 'package:ente_auth/ui/home/home_empty_state.dart'; import 'package:ente_auth/ui/home/speed_dial_label_widget.dart'; import 'package:ente_auth/ui/scanner_page.dart'; import 'package:ente_auth/ui/settings_page.dart'; @@ -206,7 +207,10 @@ class _HomePageState extends State { final l10n = context.l10n; if (_hasLoaded) { if (_filteredCodes.isEmpty && _searchText.isEmpty) { - return _getEmptyState(); + return HomeEmptyStateWidget( + onScanTap: _redirectToManualEntryPage, + onManuallySetupTap: _redirectToManualEntryPage, + ); } else { final list = ListView.builder( itemBuilder: ((context, index) { @@ -218,7 +222,7 @@ class _HomePageState extends State { return Stack( children: [ list, - _getCoachMarkWidget(), + const CoachMarkWidget(), ], ); } else if (_showSearchBox) { @@ -291,110 +295,4 @@ class _HomePageState extends State { ], ); } - - Widget _getEmptyState() { - final l10n = context.l10n; - return Center( - child: ConstrainedBox( - constraints: const BoxConstraints.tightFor(height: 800, width: 450), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 40.0, horizontal: 40), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - children: [ - Image.asset( - "assets/wallet-front-gradient.png", - width: 200, - height: 200, - ), - Text( - l10n.setupFirstAccount, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.headline4, - ), - const SizedBox(height: 64), - SizedBox( - width: 400, - child: OutlinedButton( - onPressed: _redirectToScannerPage, - child: Text(l10n.importScanQrCode), - ), - ), - const SizedBox(height: 18), - SizedBox( - width: 400, - child: OutlinedButton( - onPressed: _redirectToManualEntryPage, - child: Text(l10n.importEnterSetupKey), - ), - ), - ], - ), - ], - ), - ), - ), - ); - } - - Widget _getCoachMarkWidget() { - final l10n = context.l10n; - return GestureDetector( - onTap: () async { - await PreferenceService.instance.setHasShownCoachMark(true); - setState(() {}); - }, - child: Row( - children: [ - Expanded( - child: Container( - width: double.infinity, - color: Theme.of(context).colorScheme.background.withOpacity(0.1), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.swipe_left, - size: 42, - ), - const SizedBox( - height: 24, - ), - Text( - l10n.swipeHint, - style: Theme.of(context).textTheme.headline6, - ), - const SizedBox( - height: 36, - ), - SizedBox( - width: 160, - child: OutlinedButton( - onPressed: () async { - await PreferenceService.instance - .setHasShownCoachMark(true); - setState(() {}); - }, - child: Text(l10n.ok), - ), - ) - ], - ), - ], - ), - ), - ), - ), - ], - ), - ); - } } From ba49d0002d3d59db7801d628583464adb594ec3e Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sat, 6 May 2023 01:39:44 +0530 Subject: [PATCH 4/5] Add dependency on uni_link --- ios/Podfile.lock | 6 ++++++ lib/services/preference_service.dart | 2 +- pubspec.lock | 24 ++++++++++++++++++++++++ pubspec.yaml | 1 + 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 18fcb61877..e76020ba57 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -99,6 +99,8 @@ PODS: - FMDB (>= 2.7.5) - SwiftyGif (5.4.4) - Toast (4.0.0) + - uni_links (0.0.1): + - Flutter - url_launcher_ios (0.0.1): - Flutter @@ -125,6 +127,7 @@ DEPENDENCIES: - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`) + - uni_links (from `.symlinks/plugins/uni_links/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) SPEC REPOS: @@ -185,6 +188,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/shared_preferences_foundation/ios" sqflite: :path: ".symlinks/plugins/sqflite/ios" + uni_links: + :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" @@ -221,6 +226,7 @@ SPEC CHECKSUMS: sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 + uni_links: d97da20c7701486ba192624d99bffaaffcfc298a url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2 PODFILE CHECKSUM: b4e3a7eabb03395b66e81fc061789f61526ee6bb diff --git a/lib/services/preference_service.dart b/lib/services/preference_service.dart index 04e182f82e..06ab103094 100644 --- a/lib/services/preference_service.dart +++ b/lib/services/preference_service.dart @@ -7,7 +7,7 @@ class PreferenceService { late final SharedPreferences _prefs; - static const kHasShownCoachMarkKey = "has_shown_coach_markx"; + static const kHasShownCoachMarkKey = "has_shown_coach_mark"; Future init() async { _prefs = await SharedPreferences.getInstance(); diff --git a/pubspec.lock b/pubspec.lock index 654c1f8db3..e682113b56 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1387,6 +1387,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + uni_links: + dependency: "direct main" + description: + name: uni_links + sha256: "051098acfc9e26a9fde03b487bef5d3d228ca8f67693480c6f33fd4fbb8e2b6e" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + uni_links_platform_interface: + dependency: transitive + description: + name: uni_links_platform_interface + sha256: "929cf1a71b59e3b7c2d8a2605a9cf7e0b125b13bc858e55083d88c62722d4507" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + uni_links_web: + dependency: transitive + description: + name: uni_links_web + sha256: "7539db908e25f67de2438e33cc1020b30ab94e66720b5677ba6763b25f6394df" + url: "https://pub.dev" + source: hosted + version: "0.1.0" universal_io: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4decfbdccb..13752e4172 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: sqflite: ^2.1.0 step_progress_indicator: ^1.0.2 styled_text: ^7.0.0 + uni_links: ^0.5.1 url_launcher: ^6.1.5 uuid: ^3.0.4 From ea3cd1844b1d68201144d186740b70daffc3e380 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sat, 6 May 2023 01:47:04 +0530 Subject: [PATCH 5/5] Add support for handling otpauth:// scheme --- android/app/src/main/AndroidManifest.xml | 7 + ios/Runner/Info.plist | 137 +++++++++++--------- lib/ui/home_page.dart | 61 ++++++++- lib/ui/settings/support_section_widget.dart | 2 - 4 files changed, 140 insertions(+), 67 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 2a533c629d..f2f1146ec2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -28,6 +28,13 @@ + + + + + + +