Skip to content

Commit

Permalink
Show passcode on signing request (#1907)
Browse files Browse the repository at this point in the history
  • Loading branch information
RaulUrtecho authored Jun 26, 2022
1 parent 2ff5b73 commit 116c53e
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 35 deletions.
5 changes: 1 addition & 4 deletions lib/domain-shared/page_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ class NavigateToRouteWithArguments<T> extends PageCommand {
final String route;
final T arguments;

NavigateToRouteWithArguments({
required this.route,
required this.arguments,
});
NavigateToRouteWithArguments({required this.route, required this.arguments});
}

class NavigateToSendConfirmation extends NavigateToRouteWithArguments {
Expand Down
10 changes: 6 additions & 4 deletions lib/navigation/navigation_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class Routes {
static const importKey = 'importKey';
static const importWords = 'importWords';
static const verification = 'verification';
static const verificationUnpoppable = 'verificationUnpoppable';
static const signup = 'signup';
static const recoverAccountSearch = 'recoverAccountSearch';
static const recoveryPhrase = 'recoveryPhrase';
Expand Down Expand Up @@ -125,6 +126,8 @@ class NavigationService {
Routes.login: (_) => const LoginScreen(),
Routes.importKey: (_) => const ImportKeyScreen(),
Routes.importWords: (_) => const ImportWordsScreen(),
Routes.verification: (_) => const VerificationScreen(),
Routes.verificationUnpoppable: (_) => const VerificationScreen.unpoppable(),
Routes.recoverAccountSearch: (_) => const RecoverAccountSearchScreen(),
Routes.recoverAccountFound: (_) => const RecoverAccountFoundScreen(),
Routes.signup: (_) => const SignupScreen(),
Expand Down Expand Up @@ -165,7 +168,6 @@ class NavigationService {
Routes.citizenship: (_) => const CitizenshipScreen(),
Routes.contribution: (_) => const ContributionScreen(),
Routes.contributionDetail: (_) => const ContributionDetailScreen(),
Routes.verification: (_) => const VerificationScreen(),
Routes.recoveryPhrase: (_) => const RecoveryPhraseScreen(),
Routes.region: (_) => const RegionScreen(),
Routes.editRegionDescription: (_) => const EditRegionDescription(),
Expand All @@ -181,7 +183,7 @@ class NavigationService {
// On iOS that's a standard full screen dialog
// Has no effect on Android.
final _fullScreenRoutes = {
Routes.verification,
Routes.verificationUnpoppable,
};

// iOS transition: Pages that slides in from the right and exits in reverse.
Expand Down Expand Up @@ -231,8 +233,8 @@ class NavigationService {
///
/// If there is a route in stack and is verification, pop any other on top.
Future<dynamic> pushApp() async {
if (currentRouteName() != null && currentRouteName() == Routes.verification) {
return appNavigatorKey.currentState?.popUntil((route) => route.settings.name != Routes.verification);
if (currentRouteName() != null && currentRouteName() == Routes.verificationUnpoppable) {
return appNavigatorKey.currentState?.popUntil((route) => route.settings.name != Routes.verificationUnpoppable);
}
return pushAndRemoveAll(Routes.app);
}
Expand Down
10 changes: 8 additions & 2 deletions lib/screens/app/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
child: Scaffold(
body: BlocConsumer<AppBloc, AppState>(
listenWhen: (_, current) => current.pageCommand != null,
listener: (context, state) {
listener: (context, state) async {
final pageCommand = state.pageCommand;
_appBloc.add(ClearAppPageCommand());
if (pageCommand is BottomBarNavigateToIndex) {
Expand All @@ -107,7 +107,13 @@ class _AppState extends State<App> with WidgetsBindingObserver {
} else if (pageCommand is ShowMessage) {
eventBus.fire(ShowSnackBar(pageCommand.message));
} else if (pageCommand is NavigateToRouteWithArguments) {
NavigationService.of(context).navigateTo(pageCommand.route, pageCommand.arguments);
if (pageCommand is NavigateToSendConfirmation) {
await NavigationService.of(context)
.navigateTo(Routes.verificationUnpoppable)
.then((_) => NavigationService.of(context).navigateTo(pageCommand.route, pageCommand.arguments));
} else {
await NavigationService.of(context).navigateTo(pageCommand.route, pageCommand.arguments);
}
}
},
builder: (context, state) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import 'package:seeds/utils/build_context_extension.dart';
class PasscodeCreatedDialog extends StatelessWidget {
const PasscodeCreatedDialog({super.key});

Future<void> show(BuildContext context) async {
return showDialog<void>(context: context, barrierDismissible: false, builder: (_) => this);
}

@override
Widget build(BuildContext context) {
return CustomDialog(
Expand Down
39 changes: 16 additions & 23 deletions lib/screens/authentication/verification/verification_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@ import 'package:seeds/screens/authentication/verification/components/passcode_cr
import 'package:seeds/screens/authentication/verification/components/passcode_screen.dart';
import 'package:seeds/screens/authentication/verification/interactor/viewmodels/page_commands.dart';
import 'package:seeds/screens/authentication/verification/interactor/viewmodels/verification_bloc.dart';
import 'package:seeds/screens/profile_screens/security/interactor/viewmodels/security_bloc.dart';
import 'package:seeds/utils/build_context_extension.dart';

class VerificationScreen extends StatelessWidget {
const VerificationScreen({super.key});
final bool _isUnpoppable;

const VerificationScreen({super.key}) : _isUnpoppable = false;

/// This contructor creates a unpoppable screen and use the main builder to unlock the app.
const VerificationScreen.unpoppable({super.key}) : _isUnpoppable = true;

@override
Widget build(BuildContext context) {
final SecurityBloc? _securityBloc = ModalRoute.of(context)!.settings.arguments as SecurityBloc?;
return BlocProvider(
create: (_) => VerificationBloc()..add(const InitBiometricAuth()),
child: WillPopScope(
// User can only pop without auth if it is on security screen
onWillPop: () async => _securityBloc != null,
onWillPop: () async => !_isUnpoppable,
child: Scaffold(
body: SafeArea(
child: BlocConsumer<VerificationBloc, VerificationState>(
Expand All @@ -33,38 +36,28 @@ class VerificationScreen extends StatelessWidget {
if (pageCommand is PasscodeNotMatch) {
eventBus.fire(ShowSnackBar.success(context.loc.verificationScreenSnackBarError));
} else if (pageCommand is BiometricAuthorized) {
final authenticationBloc = BlocProvider.of<AuthenticationBloc>(context);
if (_securityBloc == null) {
if (_isUnpoppable) {
// Onboarding or timeout authentication: just unlock
authenticationBloc.add(const UnlockWallet());
} else {
// Security flow: update screen and then fires navigator pop
_securityBloc.add(const OnValidVerification());
Navigator.of(context).pop();
BlocProvider.of<AuthenticationBloc>(context).add(const UnlockWallet());
}
Navigator.of(context).pop(true);
} else if (pageCommand is PasscodeValid) {
final authenticationBloc = BlocProvider.of<AuthenticationBloc>(context);
_securityBloc?.add(const OnValidVerification());
if (state.isCreateMode) {
// Enable and save new passcode
authenticationBloc.add(EnablePasscode(newPasscode: state.newPasscode!));
Navigator.of(context).pop();
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (_) => const PasscodeCreatedDialog(),
);
if (_securityBloc == null) {
if (_isUnpoppable) {
authenticationBloc.add(const UnlockWallet());
}
Navigator.of(context).pop(true);
const PasscodeCreatedDialog().show(context);
} else {
if (_securityBloc == null) {
if (_isUnpoppable) {
// Onboarding or timeout authentication: just unlock
authenticationBloc.add(const UnlockWallet());
} else {
// pop from disable on security
Navigator.of(context).pop();
}
// pop from disable on security
Navigator.of(context).pop(true);
}
}
},
Expand Down
6 changes: 5 additions & 1 deletion lib/screens/profile_screens/security/security_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ class SecurityScreen extends StatelessWidget {
listenWhen: (_, current) => current.navigateToVerification != null,
listener: (context, _) {
BlocProvider.of<SecurityBloc>(context).add(const ResetNavigateToVerification());
NavigationService.of(context).navigateTo(Routes.verification, BlocProvider.of<SecurityBloc>(context));
NavigationService.of(context).navigateTo(Routes.verification).then((isValid) {
if (isValid ?? false) {
BlocProvider.of<SecurityBloc>(context).add(const OnValidVerification());
}
});
},
),
BlocListener<SecurityBloc, SecurityState>(
Expand Down
2 changes: 1 addition & 1 deletion lib/seeds_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class SeedsApp extends StatelessWidget {
navigator.currentRouteName() == Routes.importWords) {
navigator.pushAndRemoveAll(Routes.app);
}
navigator.navigateTo(Routes.verification);
navigator.navigateTo(Routes.verificationUnpoppable);
break;
case AuthStatus.unlocked:
navigator.pushApp();
Expand Down

0 comments on commit 116c53e

Please sign in to comment.