mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-19 05:58:50 +02:00
CW-229 Improved restore options from QR code (#793)
* add restoring wallet from qr * add restore mode * add alert for exceptions * add restore from seed * add check for create wallet state * convert sweeping page into stateful * fix parsing url * restoration flow update * update restoring from key mode * update config * fix restor of BTC and LTC wallets * fix pin code issue * wallet Seed/keys uri or code fix * fix key restore credentials * update the restore workflow * update from main * PR coments fixes * update * update * PR fixes
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/utils/language_list.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
||||
import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
@@ -7,15 +15,16 @@ import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
class RestoreOptionsPage extends BasePage {
|
||||
RestoreOptionsPage();
|
||||
|
||||
static const _aspectRatioImage = 2.086;
|
||||
RestoreOptionsPage({required this.isNewInstall});
|
||||
|
||||
@override
|
||||
String get title => S.current.restore_restore_wallet;
|
||||
|
||||
|
||||
final bool isNewInstall;
|
||||
final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png');
|
||||
final imageBackup = Image.asset('assets/images/backup.png');
|
||||
final qrCode = Image.asset('assets/images/qr_code_icon.png');
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
@@ -28,24 +37,69 @@ class RestoreOptionsPage extends BasePage {
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
RestoreButton(
|
||||
onPressed: () =>
|
||||
Navigator.pushNamed(context, Routes.restoreWalletOptionsFromWelcome),
|
||||
onPressed: () => Navigator.pushNamed(
|
||||
context, Routes.restoreWalletOptionsFromWelcome,
|
||||
arguments: isNewInstall),
|
||||
image: imageSeedKeys,
|
||||
title: S.of(context).restore_title_from_seed_keys,
|
||||
description:
|
||||
S.of(context).restore_description_from_seed_keys),
|
||||
description: S.of(context).restore_description_from_seed_keys),
|
||||
if (isNewInstall)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: RestoreButton(
|
||||
onPressed: () => Navigator.pushNamed(context, Routes.restoreFromBackup),
|
||||
image: imageBackup,
|
||||
title: S.of(context).restore_title_from_backup,
|
||||
description: S.of(context).restore_description_from_backup),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: RestoreButton(
|
||||
onPressed: () =>
|
||||
Navigator.pushNamed(context, Routes.restoreFromBackup),
|
||||
image: imageBackup,
|
||||
title: S.of(context).restore_title_from_backup,
|
||||
description: S.of(context).restore_description_from_backup),
|
||||
onPressed: () async {
|
||||
bool isPinSet = false;
|
||||
if (isNewInstall) {
|
||||
await Navigator.pushNamed(context, Routes.setupPin,
|
||||
arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
|
||||
setupPinContext.close();
|
||||
isPinSet = true;
|
||||
});
|
||||
}
|
||||
if (!isNewInstall || isPinSet) {
|
||||
try {
|
||||
final restoreWallet =
|
||||
await WalletRestoreFromQRCode.scanQRCodeForRestoring(context);
|
||||
|
||||
final restoreFromQRViewModel = getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type);
|
||||
|
||||
await restoreFromQRViewModel.create(restoreWallet: restoreWallet);
|
||||
if (restoreFromQRViewModel.state is FailureState) {
|
||||
_onWalletCreateFailure(context,
|
||||
'Create wallet state: ${restoreFromQRViewModel.state.runtimeType.toString()}');
|
||||
}
|
||||
} catch (e) {
|
||||
_onWalletCreateFailure(context, e.toString());
|
||||
}
|
||||
}
|
||||
},
|
||||
image: qrCode,
|
||||
title: S.of(context).scan_qr_code,
|
||||
description: S.of(context).cold_or_recover_wallet),
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
void _onWalletCreateFailure(BuildContext context, String error) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.current.error,
|
||||
alertContent: error,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
||||
class SweepingWalletPage extends BasePage {
|
||||
SweepingWalletPage();
|
||||
|
||||
static const aspectRatioImage = 1.25;
|
||||
final welcomeImageLight = Image.asset('assets/images/welcome_light.png');
|
||||
final welcomeImageDark = Image.asset('assets/images/welcome.png');
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Theme.of(context).backgroundColor,
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: body(context));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final welcomeImage = currentTheme.type == ThemeType.dark ? welcomeImageDark : welcomeImageLight;
|
||||
|
||||
return SweepingWalletWidget(
|
||||
aspectRatioImage: aspectRatioImage,
|
||||
welcomeImage: welcomeImage,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SweepingWalletWidget extends StatefulWidget {
|
||||
const SweepingWalletWidget({
|
||||
required this.aspectRatioImage,
|
||||
required this.welcomeImage,
|
||||
});
|
||||
|
||||
final double aspectRatioImage;
|
||||
final Image welcomeImage;
|
||||
|
||||
@override
|
||||
State<SweepingWalletWidget> createState() => _SweepingWalletWidgetState();
|
||||
}
|
||||
|
||||
class _SweepingWalletWidgetState extends State<SweepingWalletWidget> {
|
||||
@override
|
||||
void initState() {
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) async {
|
||||
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 64, bottom: 24, left: 24, right: 24),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: AspectRatio(
|
||||
aspectRatio: widget.aspectRatioImage,
|
||||
child: FittedBox(child: widget.welcomeImage, fit: BoxFit.fill))),
|
||||
Flexible(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: Text(
|
||||
S.of(context).please_wait,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).accentTextTheme!.headline2!.color!,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Text(
|
||||
S.of(context).sweeping_wallet,
|
||||
style: TextStyle(
|
||||
fontSize: 36,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).primaryTextTheme!.headline6!.color!,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 5),
|
||||
child: Text(
|
||||
S.of(context).sweeping_wallet_alert,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).accentTextTheme!.headline2!.color!,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
))
|
||||
],
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/core/seed_validator.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
|
||||
class WalletRestorePage extends BasePage {
|
||||
WalletRestorePage(this.walletRestoreViewModel)
|
||||
|
||||
@@ -178,7 +178,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||
Navigator.of(context).pushNamed(Routes.restoreWallet,
|
||||
arguments: widget.walletListViewModel.currentWalletType);
|
||||
} else {
|
||||
Navigator.of(context).pushNamed(Routes.restoreWalletType);
|
||||
Navigator.of(context).pushNamed(Routes.restoreOptions, arguments: false);
|
||||
}
|
||||
},
|
||||
image: restoreWalletImage,
|
||||
|
||||
@@ -148,7 +148,8 @@ class WelcomePage extends BasePage {
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: PrimaryImageButton(
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, Routes.restoreOptions);
|
||||
Navigator.pushNamed(context, Routes.restoreOptions,
|
||||
arguments: true);
|
||||
},
|
||||
image: restoreWalletImage,
|
||||
text: S.of(context).restore_wallet,
|
||||
|
||||
Reference in New Issue
Block a user