mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-22 07:09:10 +00:00
refactor "new ms config import" to step 1b
This commit is contained in:
parent
56b18a6c93
commit
999df80e60
6 changed files with 451 additions and 469 deletions
|
@ -1,433 +0,0 @@
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:barcode_scan2/barcode_scan2.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/frost_scaffold.dart';
|
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart';
|
|
||||||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
|
||||||
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
|
||||||
import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart';
|
|
||||||
import 'package:stackwallet/services/frost.dart';
|
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
|
||||||
import 'package:stackwallet/utilities/logger.dart';
|
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
|
||||||
import 'package:stackwallet/wallets/crypto_currency/intermediate/frost_currency.dart';
|
|
||||||
import 'package:stackwallet/widgets/background.dart';
|
|
||||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
|
||||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
|
||||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
|
||||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
|
||||||
import 'package:stackwallet/widgets/frost_mascot.dart';
|
|
||||||
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
|
|
||||||
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
|
|
||||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
|
||||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
|
||||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
|
||||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
|
||||||
|
|
||||||
class ImportNewFrostMsWalletView extends ConsumerStatefulWidget {
|
|
||||||
const ImportNewFrostMsWalletView({
|
|
||||||
super.key,
|
|
||||||
required this.walletName,
|
|
||||||
required this.frostCurrency,
|
|
||||||
});
|
|
||||||
|
|
||||||
static const String routeName = "/importNewFrostMsWalletView";
|
|
||||||
|
|
||||||
final String walletName;
|
|
||||||
final FrostCurrency frostCurrency;
|
|
||||||
|
|
||||||
@override
|
|
||||||
ConsumerState<ImportNewFrostMsWalletView> createState() =>
|
|
||||||
_ImportNewFrostMsWalletViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ImportNewFrostMsWalletViewState
|
|
||||||
extends ConsumerState<ImportNewFrostMsWalletView> {
|
|
||||||
late final TextEditingController myNameFieldController, configFieldController;
|
|
||||||
late final FocusNode myNameFocusNode, configFocusNode;
|
|
||||||
|
|
||||||
bool _nameEmpty = true, _configEmpty = true;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
myNameFieldController = TextEditingController();
|
|
||||||
configFieldController = TextEditingController();
|
|
||||||
myNameFocusNode = FocusNode();
|
|
||||||
configFocusNode = FocusNode();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
myNameFieldController.dispose();
|
|
||||||
configFieldController.dispose();
|
|
||||||
myNameFocusNode.dispose();
|
|
||||||
configFocusNode.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ConditionalParent(
|
|
||||||
condition: Util.isDesktop,
|
|
||||||
builder: (child) => DesktopScaffold(
|
|
||||||
background: Theme.of(context).extension<StackColors>()!.background,
|
|
||||||
appBar: const DesktopAppBar(
|
|
||||||
isCompactHeight: false,
|
|
||||||
leading: AppBarBackButton(),
|
|
||||||
// TODO: [prio=high] get rid of placeholder text??
|
|
||||||
trailing: FrostMascot(
|
|
||||||
title: 'Lorem ipsum',
|
|
||||||
body:
|
|
||||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam est justo, ',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: SizedBox(
|
|
||||||
width: 480,
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: ConditionalParent(
|
|
||||||
condition: !Util.isDesktop,
|
|
||||||
builder: (child) => Background(
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).extension<StackColors>()!.background,
|
|
||||||
appBar: AppBar(
|
|
||||||
leading: AppBarBackButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
"Import FROST multisig config",
|
|
||||||
style: STextStyles.navBarTitle(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
|
||||||
child: LayoutBuilder(
|
|
||||||
builder: (context, constraints) {
|
|
||||||
return SingleChildScrollView(
|
|
||||||
child: ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
minHeight: constraints.maxHeight,
|
|
||||||
),
|
|
||||||
child: IntrinsicHeight(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
child: TextField(
|
|
||||||
key: const Key("frMyNameTextFieldKey"),
|
|
||||||
controller: myNameFieldController,
|
|
||||||
onChanged: (_) {
|
|
||||||
setState(() {
|
|
||||||
_nameEmpty = myNameFieldController.text.isEmpty;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
focusNode: myNameFocusNode,
|
|
||||||
readOnly: false,
|
|
||||||
autocorrect: false,
|
|
||||||
enableSuggestions: false,
|
|
||||||
style: STextStyles.field(context),
|
|
||||||
decoration: standardInputDecoration(
|
|
||||||
"My name",
|
|
||||||
myNameFocusNode,
|
|
||||||
context,
|
|
||||||
).copyWith(
|
|
||||||
contentPadding: const EdgeInsets.only(
|
|
||||||
left: 16,
|
|
||||||
top: 6,
|
|
||||||
bottom: 8,
|
|
||||||
right: 5,
|
|
||||||
),
|
|
||||||
suffixIcon: Padding(
|
|
||||||
padding: _nameEmpty
|
|
||||||
? const EdgeInsets.only(right: 8)
|
|
||||||
: const EdgeInsets.only(right: 0),
|
|
||||||
child: UnconstrainedBox(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
!_nameEmpty
|
|
||||||
? TextFieldIconButton(
|
|
||||||
semanticsLabel:
|
|
||||||
"Clear Button. Clears The Config Field.",
|
|
||||||
key: const Key("frMyNameClearButtonKey"),
|
|
||||||
onTap: () {
|
|
||||||
myNameFieldController.text = "";
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_nameEmpty = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: const XIcon(),
|
|
||||||
)
|
|
||||||
: TextFieldIconButton(
|
|
||||||
semanticsLabel:
|
|
||||||
"Paste Button. Pastes From Clipboard To Name Field.",
|
|
||||||
key: const Key("frMyNamePasteButtonKey"),
|
|
||||||
onTap: () async {
|
|
||||||
final ClipboardData? data =
|
|
||||||
await Clipboard.getData(
|
|
||||||
Clipboard.kTextPlain);
|
|
||||||
if (data?.text != null &&
|
|
||||||
data!.text!.isNotEmpty) {
|
|
||||||
myNameFieldController.text =
|
|
||||||
data.text!.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_nameEmpty =
|
|
||||||
myNameFieldController.text.isEmpty;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: _nameEmpty
|
|
||||||
? const ClipboardIcon()
|
|
||||||
: const XIcon(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
child: TextField(
|
|
||||||
key: const Key("frConfigTextFieldKey"),
|
|
||||||
controller: configFieldController,
|
|
||||||
onChanged: (_) {
|
|
||||||
setState(() {
|
|
||||||
_configEmpty = configFieldController.text.isEmpty;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
focusNode: configFocusNode,
|
|
||||||
readOnly: false,
|
|
||||||
autocorrect: false,
|
|
||||||
enableSuggestions: false,
|
|
||||||
style: STextStyles.field(context),
|
|
||||||
decoration: standardInputDecoration(
|
|
||||||
"Enter config",
|
|
||||||
configFocusNode,
|
|
||||||
context,
|
|
||||||
).copyWith(
|
|
||||||
contentPadding: const EdgeInsets.only(
|
|
||||||
left: 16,
|
|
||||||
top: 6,
|
|
||||||
bottom: 8,
|
|
||||||
right: 5,
|
|
||||||
),
|
|
||||||
suffixIcon: Padding(
|
|
||||||
padding: _configEmpty
|
|
||||||
? const EdgeInsets.only(right: 8)
|
|
||||||
: const EdgeInsets.only(right: 0),
|
|
||||||
child: UnconstrainedBox(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
!_configEmpty
|
|
||||||
? TextFieldIconButton(
|
|
||||||
semanticsLabel:
|
|
||||||
"Clear Button. Clears The Config Field.",
|
|
||||||
key: const Key("frConfigClearButtonKey"),
|
|
||||||
onTap: () {
|
|
||||||
configFieldController.text = "";
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_configEmpty = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: const XIcon(),
|
|
||||||
)
|
|
||||||
: TextFieldIconButton(
|
|
||||||
semanticsLabel:
|
|
||||||
"Paste Button. Pastes From Clipboard To Config Field Input.",
|
|
||||||
key: const Key("frConfigPasteButtonKey"),
|
|
||||||
onTap: () async {
|
|
||||||
final ClipboardData? data =
|
|
||||||
await Clipboard.getData(
|
|
||||||
Clipboard.kTextPlain);
|
|
||||||
if (data?.text != null &&
|
|
||||||
data!.text!.isNotEmpty) {
|
|
||||||
configFieldController.text =
|
|
||||||
data.text!.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_configEmpty =
|
|
||||||
configFieldController.text.isEmpty;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: _configEmpty
|
|
||||||
? const ClipboardIcon()
|
|
||||||
: const XIcon(),
|
|
||||||
),
|
|
||||||
if (_configEmpty)
|
|
||||||
TextFieldIconButton(
|
|
||||||
semanticsLabel:
|
|
||||||
"Scan QR Button. Opens Camera For Scanning QR Code.",
|
|
||||||
key: const Key("frConfigScanQrButtonKey"),
|
|
||||||
onTap: () async {
|
|
||||||
try {
|
|
||||||
if (FocusScope.of(context).hasFocus) {
|
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
await Future<void>.delayed(
|
|
||||||
const Duration(milliseconds: 75));
|
|
||||||
}
|
|
||||||
|
|
||||||
final qrResult = await BarcodeScanner.scan();
|
|
||||||
|
|
||||||
configFieldController.text =
|
|
||||||
qrResult.rawContent;
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_configEmpty =
|
|
||||||
configFieldController.text.isEmpty;
|
|
||||||
});
|
|
||||||
} on PlatformException catch (e, s) {
|
|
||||||
Logging.instance.log(
|
|
||||||
"Failed to get camera permissions while trying to scan qr code: $e\n$s",
|
|
||||||
level: LogLevel.Warning,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: const QrCodeIcon(),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
if (!Util.isDesktop) const Spacer(),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
PrimaryButton(
|
|
||||||
label: "Start key generation",
|
|
||||||
enabled: !_nameEmpty && !_configEmpty,
|
|
||||||
onPressed: () async {
|
|
||||||
if (FocusScope.of(context).hasFocus) {
|
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
final config = configFieldController.text;
|
|
||||||
|
|
||||||
if (!Frost.validateEncodedMultisigConfig(
|
|
||||||
encodedConfig: config)) {
|
|
||||||
return await showDialog<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (_) => StackOkDialog(
|
|
||||||
title: "Invalid config",
|
|
||||||
desktopPopRootNavigator: Util.isDesktop,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Frost.getParticipants(multisigConfig: config)
|
|
||||||
.contains(myNameFieldController.text)) {
|
|
||||||
return await showDialog<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (_) => StackOkDialog(
|
|
||||||
title: "My name not found in config participants",
|
|
||||||
desktopPopRootNavigator: Util.isDesktop,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ref.read(pFrostMyName.state).state = myNameFieldController.text;
|
|
||||||
ref.read(pFrostMultisigConfig.notifier).state = config;
|
|
||||||
|
|
||||||
ref.read(pFrostStartKeyGenData.state).state =
|
|
||||||
Frost.startKeyGeneration(
|
|
||||||
multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
|
|
||||||
myName: ref.read(pFrostMyName.state).state!,
|
|
||||||
);
|
|
||||||
|
|
||||||
ref.read(pFrostCreateNewArgs.state).state = (
|
|
||||||
(
|
|
||||||
walletName: widget.walletName,
|
|
||||||
frostCurrency: widget.frostCurrency,
|
|
||||||
),
|
|
||||||
FrostRouteGenerator.createNewConfigStepRoutes,
|
|
||||||
() {
|
|
||||||
// successful completion of steps
|
|
||||||
if (Util.isDesktop) {
|
|
||||||
Navigator.of(context).popUntil(
|
|
||||||
ModalRoute.withName(
|
|
||||||
DesktopHomeView.routeName,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
unawaited(
|
|
||||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
|
||||||
HomeView.routeName,
|
|
||||||
(route) => false,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ref.read(pFrostMultisigConfig.state).state = null;
|
|
||||||
ref.read(pFrostStartKeyGenData.state).state = null;
|
|
||||||
ref.read(pFrostSecretSharesData.state).state = null;
|
|
||||||
ref.read(pFrostCreateNewArgs.state).state = null;
|
|
||||||
|
|
||||||
unawaited(
|
|
||||||
showFloatingFlushBar(
|
|
||||||
type: FlushBarType.success,
|
|
||||||
message: "Your wallet is set up.",
|
|
||||||
iconAsset: Assets.svg.check,
|
|
||||||
context: context,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await Navigator.of(context).pushNamed(
|
|
||||||
FrostStepScaffold.routeName,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,16 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/import_new_frost_ms_wallet_view.dart';
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/frost_scaffold.dart';
|
||||||
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart';
|
||||||
|
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/wallet_settings_view/frost_ms/resharing/new/new_import_resharer_config_view.dart';
|
import 'package:stackwallet/pages/settings_views/wallet_settings_view/frost_ms/resharing/new/new_import_resharer_config_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
||||||
|
import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart';
|
||||||
import 'package:stackwallet/themes/stack_colors.dart';
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
@ -17,7 +25,7 @@ import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
import 'package:stackwallet/widgets/dialogs/simple_mobile_dialog.dart';
|
import 'package:stackwallet/widgets/dialogs/simple_mobile_dialog.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
class SelectNewFrostImportTypeView extends StatefulWidget {
|
class SelectNewFrostImportTypeView extends ConsumerStatefulWidget {
|
||||||
const SelectNewFrostImportTypeView({
|
const SelectNewFrostImportTypeView({
|
||||||
super.key,
|
super.key,
|
||||||
required this.walletName,
|
required this.walletName,
|
||||||
|
@ -30,12 +38,12 @@ class SelectNewFrostImportTypeView extends StatefulWidget {
|
||||||
final FrostCurrency frostCurrency;
|
final FrostCurrency frostCurrency;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SelectNewFrostImportTypeView> createState() =>
|
ConsumerState<SelectNewFrostImportTypeView> createState() =>
|
||||||
_SelectNewFrostImportTypeViewState();
|
_SelectNewFrostImportTypeViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SelectNewFrostImportTypeViewState
|
class _SelectNewFrostImportTypeViewState
|
||||||
extends State<SelectNewFrostImportTypeView> {
|
extends ConsumerState<SelectNewFrostImportTypeView> {
|
||||||
_ImportOption _selectedOption = _ImportOption.multisigNew;
|
_ImportOption _selectedOption = _ImportOption.multisigNew;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -133,18 +141,60 @@ class _SelectNewFrostImportTypeViewState
|
||||||
final String route;
|
final String route;
|
||||||
switch (_selectedOption) {
|
switch (_selectedOption) {
|
||||||
case _ImportOption.multisigNew:
|
case _ImportOption.multisigNew:
|
||||||
route = ImportNewFrostMsWalletView.routeName;
|
ref.read(pFrostCreateNewArgs.state).state = (
|
||||||
case _ImportOption.resharerExisting:
|
(
|
||||||
route = NewImportResharerConfigView.routeName;
|
walletName: widget.walletName,
|
||||||
}
|
frostCurrency: widget.frostCurrency,
|
||||||
|
),
|
||||||
|
FrostRouteGenerator.importNewConfigStepRoutes,
|
||||||
|
() {
|
||||||
|
// successful completion of steps
|
||||||
|
if (Util.isDesktop) {
|
||||||
|
Navigator.of(context).popUntil(
|
||||||
|
ModalRoute.withName(
|
||||||
|
DesktopHomeView.routeName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unawaited(
|
||||||
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||||
|
HomeView.routeName,
|
||||||
|
(route) => false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await Navigator.of(context).pushNamed(
|
ref.read(pFrostMultisigConfig.state).state = null;
|
||||||
route,
|
ref.read(pFrostStartKeyGenData.state).state = null;
|
||||||
arguments: (
|
ref.read(pFrostSecretSharesData.state).state = null;
|
||||||
walletName: widget.walletName,
|
ref.read(pFrostCreateNewArgs.state).state = null;
|
||||||
frostCurrency: widget.frostCurrency,
|
|
||||||
),
|
unawaited(
|
||||||
);
|
showFloatingFlushBar(
|
||||||
|
type: FlushBarType.success,
|
||||||
|
message: "Your wallet is set up.",
|
||||||
|
iconAsset: Assets.svg.check,
|
||||||
|
context: context,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await Navigator.of(context).pushNamed(
|
||||||
|
FrostStepScaffold.routeName,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _ImportOption.resharerExisting:
|
||||||
|
await Navigator.of(context).pushNamed(
|
||||||
|
NewImportResharerConfigView.routeName,
|
||||||
|
arguments: (
|
||||||
|
walletName: widget.walletName,
|
||||||
|
frostCurrency: widget.frostCurrency,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
|
@ -21,7 +21,7 @@ import 'package:stackwallet/widgets/frost_step_user_steps.dart';
|
||||||
class FrostCreateStep1a extends ConsumerStatefulWidget {
|
class FrostCreateStep1a extends ConsumerStatefulWidget {
|
||||||
const FrostCreateStep1a({super.key});
|
const FrostCreateStep1a({super.key});
|
||||||
|
|
||||||
static const String routeName = "/frostCreateStep1";
|
static const String routeName = "/frostCreateStep1a";
|
||||||
static const String title = "Multisig group info";
|
static const String title = "Multisig group info";
|
||||||
|
|
||||||
@override
|
@override
|
|
@ -0,0 +1,368 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:barcode_scan2/barcode_scan2.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart';
|
||||||
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_route_generator.dart';
|
||||||
|
import 'package:stackwallet/providers/frost_wallet/frost_wallet_providers.dart';
|
||||||
|
import 'package:stackwallet/services/frost.dart';
|
||||||
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/frost_step_user_steps.dart';
|
||||||
|
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
|
||||||
|
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
|
||||||
|
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||||
|
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
|
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||||
|
|
||||||
|
class FrostCreateStep1b extends ConsumerStatefulWidget {
|
||||||
|
const FrostCreateStep1b({super.key});
|
||||||
|
|
||||||
|
static const String routeName = "/frostCreateStep1b";
|
||||||
|
static const String title = "Import group info";
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<FrostCreateStep1b> createState() => _FrostCreateStep1bState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
|
||||||
|
static const info = [
|
||||||
|
"Scan the config QR code or paste the code provided by the group creator.",
|
||||||
|
"Enter your name EXACTLY as the group creator entered it. When in doubt, "
|
||||||
|
"double check with them. The names are case-sensitive.",
|
||||||
|
"Wait for other participants to finish entering their information.",
|
||||||
|
"Verify that everyone has filled out their forms before continuing. If you "
|
||||||
|
"try to continue before everyone is ready, the process will be canceled.",
|
||||||
|
"Check the box and press “Generate keys”.",
|
||||||
|
];
|
||||||
|
|
||||||
|
late final TextEditingController myNameFieldController, configFieldController;
|
||||||
|
late final FocusNode myNameFocusNode, configFocusNode;
|
||||||
|
|
||||||
|
bool _nameEmpty = true, _configEmpty = true, _userVerifyContinue = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
myNameFieldController = TextEditingController();
|
||||||
|
configFieldController = TextEditingController();
|
||||||
|
myNameFocusNode = FocusNode();
|
||||||
|
configFocusNode = FocusNode();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
myNameFieldController.dispose();
|
||||||
|
configFieldController.dispose();
|
||||||
|
myNameFocusNode.dispose();
|
||||||
|
configFocusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const FrostStepUserSteps(
|
||||||
|
userSteps: info,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
key: const Key("frMyNameTextFieldKey"),
|
||||||
|
controller: myNameFieldController,
|
||||||
|
onChanged: (_) {
|
||||||
|
setState(() {
|
||||||
|
_nameEmpty = myNameFieldController.text.isEmpty;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
focusNode: myNameFocusNode,
|
||||||
|
readOnly: false,
|
||||||
|
autocorrect: false,
|
||||||
|
enableSuggestions: false,
|
||||||
|
style: STextStyles.field(context),
|
||||||
|
decoration: standardInputDecoration(
|
||||||
|
"My name",
|
||||||
|
myNameFocusNode,
|
||||||
|
context,
|
||||||
|
).copyWith(
|
||||||
|
contentPadding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
top: 6,
|
||||||
|
bottom: 8,
|
||||||
|
right: 5,
|
||||||
|
),
|
||||||
|
suffixIcon: Padding(
|
||||||
|
padding: _nameEmpty
|
||||||
|
? const EdgeInsets.only(right: 8)
|
||||||
|
: const EdgeInsets.only(right: 0),
|
||||||
|
child: UnconstrainedBox(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
!_nameEmpty
|
||||||
|
? TextFieldIconButton(
|
||||||
|
semanticsLabel:
|
||||||
|
"Clear Button. Clears The Config Field.",
|
||||||
|
key: const Key("frMyNameClearButtonKey"),
|
||||||
|
onTap: () {
|
||||||
|
myNameFieldController.text = "";
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_nameEmpty = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: const XIcon(),
|
||||||
|
)
|
||||||
|
: TextFieldIconButton(
|
||||||
|
semanticsLabel:
|
||||||
|
"Paste Button. Pastes From Clipboard To Name Field.",
|
||||||
|
key: const Key("frMyNamePasteButtonKey"),
|
||||||
|
onTap: () async {
|
||||||
|
final ClipboardData? data =
|
||||||
|
await Clipboard.getData(
|
||||||
|
Clipboard.kTextPlain);
|
||||||
|
if (data?.text != null &&
|
||||||
|
data!.text!.isNotEmpty) {
|
||||||
|
myNameFieldController.text =
|
||||||
|
data.text!.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_nameEmpty =
|
||||||
|
myNameFieldController.text.isEmpty;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: _nameEmpty
|
||||||
|
? const ClipboardIcon()
|
||||||
|
: const XIcon(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
key: const Key("frConfigTextFieldKey"),
|
||||||
|
controller: configFieldController,
|
||||||
|
onChanged: (_) {
|
||||||
|
setState(() {
|
||||||
|
_configEmpty = configFieldController.text.isEmpty;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
focusNode: configFocusNode,
|
||||||
|
readOnly: false,
|
||||||
|
autocorrect: false,
|
||||||
|
enableSuggestions: false,
|
||||||
|
style: STextStyles.field(context),
|
||||||
|
decoration: standardInputDecoration(
|
||||||
|
"Enter config",
|
||||||
|
configFocusNode,
|
||||||
|
context,
|
||||||
|
).copyWith(
|
||||||
|
contentPadding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
top: 6,
|
||||||
|
bottom: 8,
|
||||||
|
right: 5,
|
||||||
|
),
|
||||||
|
suffixIcon: Padding(
|
||||||
|
padding: _configEmpty
|
||||||
|
? const EdgeInsets.only(right: 8)
|
||||||
|
: const EdgeInsets.only(right: 0),
|
||||||
|
child: UnconstrainedBox(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
!_configEmpty
|
||||||
|
? TextFieldIconButton(
|
||||||
|
semanticsLabel:
|
||||||
|
"Clear Button. Clears The Config Field.",
|
||||||
|
key: const Key("frConfigClearButtonKey"),
|
||||||
|
onTap: () {
|
||||||
|
configFieldController.text = "";
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_configEmpty = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: const XIcon(),
|
||||||
|
)
|
||||||
|
: TextFieldIconButton(
|
||||||
|
semanticsLabel:
|
||||||
|
"Paste Button. Pastes From Clipboard To Config Field Input.",
|
||||||
|
key: const Key("frConfigPasteButtonKey"),
|
||||||
|
onTap: () async {
|
||||||
|
final ClipboardData? data =
|
||||||
|
await Clipboard.getData(
|
||||||
|
Clipboard.kTextPlain);
|
||||||
|
if (data?.text != null &&
|
||||||
|
data!.text!.isNotEmpty) {
|
||||||
|
configFieldController.text =
|
||||||
|
data.text!.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_configEmpty =
|
||||||
|
configFieldController.text.isEmpty;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: _configEmpty
|
||||||
|
? const ClipboardIcon()
|
||||||
|
: const XIcon(),
|
||||||
|
),
|
||||||
|
if (_configEmpty)
|
||||||
|
TextFieldIconButton(
|
||||||
|
semanticsLabel:
|
||||||
|
"Scan QR Button. Opens Camera For Scanning QR Code.",
|
||||||
|
key: const Key("frConfigScanQrButtonKey"),
|
||||||
|
onTap: () async {
|
||||||
|
try {
|
||||||
|
if (FocusScope.of(context).hasFocus) {
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
await Future<void>.delayed(
|
||||||
|
const Duration(milliseconds: 75));
|
||||||
|
}
|
||||||
|
|
||||||
|
final qrResult = await BarcodeScanner.scan();
|
||||||
|
|
||||||
|
configFieldController.text =
|
||||||
|
qrResult.rawContent;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_configEmpty =
|
||||||
|
configFieldController.text.isEmpty;
|
||||||
|
});
|
||||||
|
} on PlatformException catch (e, s) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"Failed to get camera permissions while trying to scan qr code: $e\n$s",
|
||||||
|
level: LogLevel.Warning,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const QrCodeIcon(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
if (!Util.isDesktop) const Spacer(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_userVerifyContinue = !_userVerifyContinue;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 26,
|
||||||
|
child: Checkbox(
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
value: _userVerifyContinue,
|
||||||
|
onChanged: (value) => setState(
|
||||||
|
() => _userVerifyContinue = value == true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"I have verified that everyone has joined the group",
|
||||||
|
style: STextStyles.w500_14(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
PrimaryButton(
|
||||||
|
label: "Start key generation",
|
||||||
|
enabled: _userVerifyContinue && !_nameEmpty && !_configEmpty,
|
||||||
|
onPressed: () async {
|
||||||
|
if (FocusScope.of(context).hasFocus) {
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
final config = configFieldController.text;
|
||||||
|
|
||||||
|
if (!Frost.validateEncodedMultisigConfig(encodedConfig: config)) {
|
||||||
|
return await showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => StackOkDialog(
|
||||||
|
title: "Invalid config",
|
||||||
|
desktopPopRootNavigator: Util.isDesktop,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Frost.getParticipants(multisigConfig: config)
|
||||||
|
.contains(myNameFieldController.text)) {
|
||||||
|
return await showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => StackOkDialog(
|
||||||
|
title: "My name not found in config participants",
|
||||||
|
desktopPopRootNavigator: Util.isDesktop,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.read(pFrostMyName.state).state = myNameFieldController.text;
|
||||||
|
ref.read(pFrostMultisigConfig.notifier).state = config;
|
||||||
|
|
||||||
|
ref.read(pFrostStartKeyGenData.state).state =
|
||||||
|
Frost.startKeyGeneration(
|
||||||
|
multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
|
||||||
|
myName: ref.read(pFrostMyName.state).state!,
|
||||||
|
);
|
||||||
|
ref.read(pFrostCreateCurrentStep.state).state = 2;
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
FrostCreateStep2.routeName,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1.dart';
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1a.dart';
|
||||||
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart';
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart';
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_4.dart';
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_4.dart';
|
||||||
|
@ -30,6 +31,14 @@ abstract class FrostRouteGenerator {
|
||||||
(routeName: FrostCreateStep5.routeName, title: FrostCreateStep5.title),
|
(routeName: FrostCreateStep5.routeName, title: FrostCreateStep5.title),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static const List<FrostStepRoute> importNewConfigStepRoutes = [
|
||||||
|
(routeName: FrostCreateStep1b.routeName, title: FrostCreateStep1b.title),
|
||||||
|
(routeName: FrostCreateStep2.routeName, title: FrostCreateStep2.title),
|
||||||
|
(routeName: FrostCreateStep3.routeName, title: FrostCreateStep3.title),
|
||||||
|
(routeName: FrostCreateStep4.routeName, title: FrostCreateStep4.title),
|
||||||
|
(routeName: FrostCreateStep5.routeName, title: FrostCreateStep5.title),
|
||||||
|
];
|
||||||
|
|
||||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||||
final args = settings.arguments;
|
final args = settings.arguments;
|
||||||
|
|
||||||
|
@ -41,6 +50,13 @@ abstract class FrostRouteGenerator {
|
||||||
settings: settings,
|
settings: settings,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case FrostCreateStep1b.routeName:
|
||||||
|
return RouteGenerator.getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => const FrostCreateStep1b(),
|
||||||
|
settings: settings,
|
||||||
|
);
|
||||||
|
|
||||||
case FrostCreateStep2.routeName:
|
case FrostCreateStep2.routeName:
|
||||||
return RouteGenerator.getRoute(
|
return RouteGenerator.getRoute(
|
||||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
|
|
@ -28,7 +28,6 @@ import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_vi
|
||||||
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/frost_scaffold.dart';
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/frost_scaffold.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/create_new_frost_ms_wallet_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/create_new_frost_ms_wallet_view.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/import_new_frost_ms_wallet_view.dart';
|
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart';
|
||||||
|
@ -500,24 +499,6 @@ class RouteGenerator {
|
||||||
}
|
}
|
||||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
case ImportNewFrostMsWalletView.routeName:
|
|
||||||
if (args is ({
|
|
||||||
String walletName,
|
|
||||||
FrostCurrency frostCurrency,
|
|
||||||
})) {
|
|
||||||
return getRoute(
|
|
||||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
|
||||||
builder: (_) => ImportNewFrostMsWalletView(
|
|
||||||
walletName: args.walletName,
|
|
||||||
frostCurrency: args.frostCurrency,
|
|
||||||
),
|
|
||||||
settings: RouteSettings(
|
|
||||||
name: settings.name,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
|
||||||
|
|
||||||
case NewImportResharerConfigView.routeName:
|
case NewImportResharerConfigView.routeName:
|
||||||
if (args is ({
|
if (args is ({
|
||||||
String walletName,
|
String walletName,
|
||||||
|
|
Loading…
Reference in a new issue