mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-16 17:27:39 +00:00
fix delete frost wallet on mobile
This commit is contained in:
parent
33c78a4b42
commit
738cb55a40
4 changed files with 338 additions and 115 deletions
|
@ -17,6 +17,7 @@ import 'package:flutter_svg/svg.dart';
|
|||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart';
|
||||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
|
@ -24,23 +25,35 @@ import 'package:stackwallet/utilities/assets.dart';
|
|||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/simple_copy_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/detail_item.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
|
||||
class DeleteWalletRecoveryPhraseView extends ConsumerStatefulWidget {
|
||||
const DeleteWalletRecoveryPhraseView({
|
||||
Key? key,
|
||||
super.key,
|
||||
required this.walletId,
|
||||
required this.mnemonic,
|
||||
this.frostWalletData,
|
||||
this.clipboardInterface = const ClipboardWrapper(),
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
static const routeName = "/deleteWalletRecoveryPhrase";
|
||||
|
||||
final String walletId;
|
||||
final List<String> mnemonic;
|
||||
final ({
|
||||
String myName,
|
||||
String config,
|
||||
String keys,
|
||||
({String config, String keys})? prevGen,
|
||||
})? frostWalletData;
|
||||
|
||||
final ClipboardInterface clipboardInterface;
|
||||
|
||||
|
@ -54,6 +67,62 @@ class _DeleteWalletRecoveryPhraseViewState
|
|||
late List<String> _mnemonic;
|
||||
late ClipboardInterface _clipboardInterface;
|
||||
|
||||
bool _lock = false;
|
||||
|
||||
void _continuePressed() {
|
||||
if (_lock) {
|
||||
return;
|
||||
}
|
||||
_lock = true;
|
||||
try {
|
||||
showDialog<dynamic>(
|
||||
barrierDismissible: true,
|
||||
context: context,
|
||||
builder: (_) => StackDialog(
|
||||
title: "Thanks! Your wallet will be deleted.",
|
||||
leftButton: TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getSecondaryEnabledButtonStyle(context),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: STextStyles.button(context).copyWith(
|
||||
color:
|
||||
Theme.of(context).extension<StackColors>()!.accentColorDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
rightButton: TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: () async {
|
||||
await ref.read(pWallets).deleteWallet(
|
||||
ref.read(pWalletInfo(widget.walletId)),
|
||||
ref.read(secureStoreProvider),
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).popUntil(
|
||||
ModalRoute.withName(HomeView.routeName),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
"Ok",
|
||||
style: STextStyles.button(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
_lock = false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_mnemonic = widget.mnemonic;
|
||||
|
@ -65,6 +134,9 @@ class _DeleteWalletRecoveryPhraseViewState
|
|||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
|
||||
final bool frost = widget.frostWalletData != null;
|
||||
final prevGen = widget.frostWalletData?.prevGen != null;
|
||||
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
||||
|
@ -93,7 +165,7 @@ class _DeleteWalletRecoveryPhraseViewState
|
|||
onPressed: () async {
|
||||
await _clipboardInterface
|
||||
.setData(ClipboardData(text: _mnemonic.join(" ")));
|
||||
if (mounted) {
|
||||
if (context.mounted) {
|
||||
unawaited(
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.info,
|
||||
|
@ -111,116 +183,207 @@ class _DeleteWalletRecoveryPhraseViewState
|
|||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
ref.watch(pWalletName(widget.walletId)),
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.label(context).copyWith(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Recovery Phrase",
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.pageTitleH1(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Text(
|
||||
"Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.",
|
||||
style: STextStyles.label(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: MnemonicTable(
|
||||
words: _mnemonic,
|
||||
isDesktop: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: () {
|
||||
showDialog<dynamic>(
|
||||
barrierDismissible: true,
|
||||
context: context,
|
||||
builder: (_) => StackDialog(
|
||||
title: "Thanks! Your wallet will be deleted.",
|
||||
leftButton: TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getSecondaryEnabledButtonStyle(context),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: STextStyles.button(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark),
|
||||
child: frost
|
||||
? LayoutBuilder(
|
||||
builder: (builderContext, constraints) {
|
||||
return SingleChildScrollView(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: constraints.maxHeight,
|
||||
),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
RoundedWhiteContainer(
|
||||
child: Text(
|
||||
"Please write down your backup data. Keep it safe and "
|
||||
"never share it with anyone. "
|
||||
"Your backup data is the only way you can access your "
|
||||
"funds if you forget your PIN, lose your phone, etc."
|
||||
"\n\n"
|
||||
"Stack Wallet does not keep nor is able to restore "
|
||||
"your backup data. "
|
||||
"Only you have access to your wallet.",
|
||||
style: STextStyles.label(context),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
// DetailItem(
|
||||
// title: "My name",
|
||||
// detail: frostWalletData!.myName,
|
||||
// button: Util.isDesktop
|
||||
// ? IconCopyButton(
|
||||
// data: frostWalletData!.myName,
|
||||
// )
|
||||
// : SimpleCopyButton(
|
||||
// data: frostWalletData!.myName,
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 16,
|
||||
// ),
|
||||
DetailItem(
|
||||
title: "Multisig config",
|
||||
detail: widget.frostWalletData!.config,
|
||||
button: Util.isDesktop
|
||||
? IconCopyButton(
|
||||
data: widget.frostWalletData!.config,
|
||||
)
|
||||
: SimpleCopyButton(
|
||||
data: widget.frostWalletData!.config,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
DetailItem(
|
||||
title: "Keys",
|
||||
detail: widget.frostWalletData!.keys,
|
||||
button: Util.isDesktop
|
||||
? IconCopyButton(
|
||||
data: widget.frostWalletData!.keys,
|
||||
)
|
||||
: SimpleCopyButton(
|
||||
data: widget.frostWalletData!.keys,
|
||||
),
|
||||
),
|
||||
if (prevGen)
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
if (prevGen)
|
||||
RoundedWhiteContainer(
|
||||
child: Text(
|
||||
"Previous generation info",
|
||||
style: STextStyles.label(context),
|
||||
),
|
||||
),
|
||||
if (prevGen)
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (prevGen)
|
||||
DetailItem(
|
||||
title: "Previous multisig config",
|
||||
detail:
|
||||
widget.frostWalletData!.prevGen!.config,
|
||||
button: Util.isDesktop
|
||||
? IconCopyButton(
|
||||
data: widget
|
||||
.frostWalletData!.prevGen!.config,
|
||||
)
|
||||
: SimpleCopyButton(
|
||||
data: widget
|
||||
.frostWalletData!.prevGen!.config,
|
||||
),
|
||||
),
|
||||
if (prevGen)
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
if (prevGen)
|
||||
DetailItem(
|
||||
title: "Previous keys",
|
||||
detail: widget.frostWalletData!.prevGen!.keys,
|
||||
button: Util.isDesktop
|
||||
? IconCopyButton(
|
||||
data: widget
|
||||
.frostWalletData!.prevGen!.keys,
|
||||
)
|
||||
: SimpleCopyButton(
|
||||
data: widget
|
||||
.frostWalletData!.prevGen!.keys,
|
||||
),
|
||||
),
|
||||
|
||||
const Spacer(),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
PrimaryButton(
|
||||
label: "Continue",
|
||||
onPressed: _continuePressed,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
rightButton: TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: () async {
|
||||
await ref.read(pWallets).deleteWallet(
|
||||
ref.read(pWalletInfo(widget.walletId)),
|
||||
ref.read(secureStoreProvider),
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).popUntil(
|
||||
ModalRoute.withName(HomeView.routeName));
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
ref.watch(pWalletName(widget.walletId)),
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.label(context).copyWith(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Recovery Phrase",
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.pageTitleH1(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Text(
|
||||
"Ok",
|
||||
style: STextStyles.button(context),
|
||||
"Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.",
|
||||
style: STextStyles.label(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"Continue",
|
||||
style: STextStyles.button(context),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: MnemonicTable(
|
||||
words: _mnemonic,
|
||||
isDesktop: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: _continuePressed,
|
||||
child: Text(
|
||||
"Continue",
|
||||
style: STextStyles.button(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -14,6 +14,7 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_set
|
|||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/bitcoin_frost_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
|
@ -21,9 +22,9 @@ import 'package:stackwallet/widgets/rounded_container.dart';
|
|||
|
||||
class DeleteWalletWarningView extends ConsumerWidget {
|
||||
const DeleteWalletWarningView({
|
||||
Key? key,
|
||||
super.key,
|
||||
required this.walletId,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
static const String routeName = "/deleteWalletWarning";
|
||||
|
||||
|
@ -100,14 +101,50 @@ class DeleteWalletWarningView extends ConsumerWidget {
|
|||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: () async {
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
final mnemonic =
|
||||
await (wallet as MnemonicInterface).getMnemonicAsWords();
|
||||
|
||||
// TODO: [prio=med] take wallets that don't have a mnemonic into account
|
||||
|
||||
List<String>? mnemonic;
|
||||
({
|
||||
String myName,
|
||||
String config,
|
||||
String keys,
|
||||
({String config, String keys})? prevGen,
|
||||
})? frostWalletData;
|
||||
|
||||
if (wallet is BitcoinFrostWallet) {
|
||||
final futures = [
|
||||
wallet.getSerializedKeys(),
|
||||
wallet.getMultisigConfig(),
|
||||
wallet.getSerializedKeysPrevGen(),
|
||||
wallet.getMultisigConfigPrevGen(),
|
||||
];
|
||||
|
||||
final results = await Future.wait(futures);
|
||||
|
||||
if (results.length == 4) {
|
||||
frostWalletData = (
|
||||
myName: wallet.frostInfo.myName,
|
||||
config: results[1]!,
|
||||
keys: results[0]!,
|
||||
prevGen: results[2] == null || results[3] == null
|
||||
? null
|
||||
: (
|
||||
config: results[3]!,
|
||||
keys: results[2]!,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else if (wallet is MnemonicInterface) {
|
||||
mnemonic = await wallet.getMnemonicAsWords();
|
||||
}
|
||||
if (context.mounted) {
|
||||
await Navigator.of(context).pushNamed(
|
||||
DeleteWalletRecoveryPhraseView.routeName,
|
||||
arguments: (
|
||||
walletId: walletId,
|
||||
mnemonicWords: mnemonic,
|
||||
mnemonicWords: mnemonic ?? [],
|
||||
frostWalletData: frostWalletData,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -122,9 +122,10 @@ class WalletSettingsWalletSettingsView extends ConsumerWidget {
|
|||
child: Text(
|
||||
"Cancel",
|
||||
style: STextStyles.button(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark),
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
rightButton: TextButton(
|
||||
|
@ -150,7 +151,8 @@ class WalletSettingsWalletSettingsView extends ConsumerWidget {
|
|||
"Delete wallet",
|
||||
),
|
||||
settings: const RouteSettings(
|
||||
name: "/deleteWalletLockscreen"),
|
||||
name: "/deleteWalletLockscreen",
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1745,6 +1745,27 @@ class RouteGenerator {
|
|||
name: settings.name,
|
||||
),
|
||||
);
|
||||
} else if (args is ({
|
||||
String walletId,
|
||||
List<String> mnemonicWords,
|
||||
({
|
||||
String myName,
|
||||
String config,
|
||||
String keys,
|
||||
({String config, String keys})? prevGen,
|
||||
})? frostWalletData,
|
||||
})) {
|
||||
return getRoute(
|
||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||
builder: (_) => DeleteWalletRecoveryPhraseView(
|
||||
mnemonic: args.mnemonicWords,
|
||||
walletId: args.walletId,
|
||||
frostWalletData: args.frostWalletData,
|
||||
),
|
||||
settings: RouteSettings(
|
||||
name: settings.name,
|
||||
),
|
||||
);
|
||||
}
|
||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||
|
||||
|
|
Loading…
Reference in a new issue