From 9a6fd46e041a969b4805ff91f9c1d47b235d1e4f Mon Sep 17 00:00:00 2001 From: malik1004x Date: Fri, 13 Mar 2026 23:20:25 +0100 Subject: [PATCH] fix pow node edits (#3078) --- lib/router.dart | 5 +- .../nodes/pow_node_create_or_edit_page.dart | 230 ++++++++---------- .../screens/settings/manage_nodes_page.dart | 7 +- 3 files changed, 113 insertions(+), 129 deletions(-) diff --git a/lib/router.dart b/lib/router.dart index 60ca5d05c..6adfd313d 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -629,9 +629,10 @@ Route createRoute(RouteSettings settings) { case Routes.newPowNode: final args = settings.arguments as Map?; + final page = getIt.get( + param1: args?['editingNode'] as Node?, param2: args?['isSelected'] as bool?); return CupertinoPageRoute( - builder: (_) => getIt.get( - param1: args?['editingNode'] as Node?, param2: args?['isSelected'] as bool?)); + builder: (_) => page); case Routes.accountCreation: return CupertinoPageRoute( diff --git a/lib/src/screens/nodes/pow_node_create_or_edit_page.dart b/lib/src/screens/nodes/pow_node_create_or_edit_page.dart index 96f77858e..44968836b 100644 --- a/lib/src/screens/nodes/pow_node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/pow_node_create_or_edit_page.dart @@ -1,7 +1,10 @@ import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/new-ui/widgets/keyboard_hide_overlay.dart'; +import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart'; import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cw_core/node.dart'; @@ -13,76 +16,30 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/scrollable_with_bottom_section.dart'; -class PowNodeCreateOrEditPage extends BasePage { +class PowNodeCreateOrEditPage extends StatefulWidget { PowNodeCreateOrEditPage( {required this.nodeCreateOrEditViewModel, this.editingNode, this.isSelected}) - : _addressController = TextEditingController(), - _portController = TextEditingController(), - _loginController = TextEditingController(), - _passwordController = TextEditingController() { - reaction((_) => nodeCreateOrEditViewModel.address, (String address) { - if (address != _addressController.text) { - _addressController.text = address; - } - }); + ; - reaction((_) => nodeCreateOrEditViewModel.port, (String port) { - if (port != _portController.text) { - _portController.text = port; - } - }); - if (nodeCreateOrEditViewModel.hasAuthCredentials) { - reaction((_) => nodeCreateOrEditViewModel.login, (String login) { - if (login != _loginController.text) { - _loginController.text = login; - } - }); - reaction((_) => nodeCreateOrEditViewModel.password, (String password) { - if (password != _passwordController.text) { - _passwordController.text = password; - } - }); - } - - _addressController - .addListener(() => nodeCreateOrEditViewModel.address = _addressController.text); - _portController.addListener(() => nodeCreateOrEditViewModel.port = _portController.text); - _loginController.addListener(() => nodeCreateOrEditViewModel.login = _loginController.text); - _passwordController - .addListener(() => nodeCreateOrEditViewModel.password = _passwordController.text); - } - - final TextEditingController _addressController; - final TextEditingController _portController; - final TextEditingController _loginController; - final TextEditingController _passwordController; - - @override - String get title => editingNode != null ? S.current.edit_node : S.current.node_new; - - @override - Widget trailing(BuildContext context) => IconButton( - onPressed: () async { - await nodeCreateOrEditViewModel.scanQRCodeForNewNode(context); - }, - splashColor: Colors.transparent, - highlightColor: Colors.transparent, - hoverColor: Colors.transparent, - icon: Image.asset( - 'assets/images/qr_code_icon.png', - ), - ); final NodeCreateOrEditViewModel nodeCreateOrEditViewModel; final Node? editingNode; final bool? isSelected; - final _formKey = GlobalKey(); @override - Widget body(BuildContext context) { - reaction((_) => nodeCreateOrEditViewModel.connectionState, (ExecutionState state) { + State createState() => _PowNodeCreateOrEditPageState(); +} + +class _PowNodeCreateOrEditPageState extends State { + final _formKey = GlobalKey(); + + + @override + void initState() { + super.initState(); + reaction((_) => widget.nodeCreateOrEditViewModel.connectionState, (ExecutionState state) { if (state is ExecutedSuccessfullyState) { WidgetsBinding.instance.addPostFrameCallback((_) { showPopUp( @@ -111,73 +68,98 @@ class PowNodeCreateOrEditPage extends BasePage { }); } }); + } + + @override + Widget build(BuildContext context) { return Container( - padding: EdgeInsets.only(left: 24, right: 24), - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24.0, top: 8), - content: NodeForm( - key: _formKey, - nodeViewModel: nodeCreateOrEditViewModel, - ), - bottomSectionPadding: EdgeInsets.only(bottom: 24), - bottomSection: Observer( - builder: (_) => Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Container( - padding: EdgeInsets.only(right: 8.0), - child: LoadingPrimaryButton( - onPressed: () async { - final confirmed = await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).remove_node, - alertContent: S.of(context).remove_node_message, - rightButtonText: S.of(context).remove, - leftButtonText: S.of(context).cancel, - actionRightButton: () => Navigator.pop(context, true), - actionLeftButton: () => Navigator.pop(context, false)); - }) ?? - false; - - if (confirmed) { - await editingNode!.delete(); - Navigator.of(context).pop(); - } - }, - text: S.of(context).delete, - isDisabled: !nodeCreateOrEditViewModel.isReady || (isSelected ?? false), - color: Theme.of(context).colorScheme.errorContainer, - textColor: Theme.of(context).colorScheme.onPrimary, - ), - ), - ), - Flexible( - child: Container( - padding: EdgeInsets.only(left: 8.0), - child: PrimaryButton( - onPressed: () async { - if (_formKey.currentState != null && - !_formKey.currentState!.validate()) { - return; - } - - await nodeCreateOrEditViewModel.save( - editingNode: editingNode, saveAsCurrent: isSelected ?? false); - Navigator.of(context).pop(); - }, - text: S.of(context).save, - color: Theme.of(context).colorScheme.primary, - textColor: Theme.of(context).colorScheme.onPrimary, - isDisabled: (!nodeCreateOrEditViewModel.isReady) || - (nodeCreateOrEditViewModel.connectionState is IsExecutingState), - ), - )), - ], + color: Theme.of(context).colorScheme.surface, + child: KeyboardHideOverlay( + child: Column( + children: [ + ModalTopBar( + title: widget.editingNode != null ? S.current.edit_node : S.current.node_new, + leadingIcon: Icon(Icons.arrow_back_ios_new), + onLeadingPressed: Navigator.of(context).pop, + trailingIcon: CakeImageWidget(imageUrl: + "assets/new-ui/scan.svg",width:24,height:24, + colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn), + ), + onTrailingPressed: () => widget.nodeCreateOrEditViewModel.scanQRCodeForNewNode(context), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 24, right: 24), + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24.0, top: 8), + content: NodeForm( + key: _formKey, + nodeViewModel: widget.nodeCreateOrEditViewModel, + ), + bottomSectionPadding: EdgeInsets.only(bottom: 24), + bottomSection: Observer( + builder: (_) => Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Container( + padding: EdgeInsets.only(right: 8.0), + child: LoadingPrimaryButton( + onPressed: () async { + final confirmed = await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).remove_node, + alertContent: S.of(context).remove_node_message, + rightButtonText: S.of(context).remove, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.pop(context, true), + actionLeftButton: () => Navigator.pop(context, false)); + }) ?? + false; + + if (confirmed) { + await widget.editingNode!.delete(); + Navigator.of(context).pop(); + } + }, + text: S.of(context).delete, + isDisabled: !widget.nodeCreateOrEditViewModel.isReady || (widget.isSelected ?? false), + color: Theme.of(context).colorScheme.errorContainer, + textColor: Theme.of(context).colorScheme.onPrimary, + ), + ), + ), + Flexible( + child: Container( + padding: EdgeInsets.only(left: 8.0), + child: PrimaryButton( + onPressed: () async { + if (_formKey.currentState != null && + !_formKey.currentState!.validate()) { + return; + } + + await widget.nodeCreateOrEditViewModel.save( + editingNode: widget.editingNode, saveAsCurrent: widget.isSelected ?? false); + Navigator.of(context).pop(); + }, + text: S.of(context).save, + color: Theme.of(context).colorScheme.primary, + textColor: Theme.of(context).colorScheme.onPrimary, + isDisabled: (!widget.nodeCreateOrEditViewModel.isReady) || + (widget.nodeCreateOrEditViewModel.connectionState is IsExecutingState), + ), + )), + ], + )), )), - )); + ), + ], + ), + ), + ); } } diff --git a/lib/src/screens/settings/manage_nodes_page.dart b/lib/src/screens/settings/manage_nodes_page.dart index a0d2f0844..b96ea8756 100644 --- a/lib/src/screens/settings/manage_nodes_page.dart +++ b/lib/src/screens/settings/manage_nodes_page.dart @@ -15,7 +15,8 @@ import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; class ManageNodesPage extends BasePage { ManageNodesPage(this.isPow, {this.nodeListViewModel, this.powNodeListViewModel}) - : assert((isPow && powNodeListViewModel != null) || (!isPow && nodeListViewModel != null)); + : assert((isPow && powNodeListViewModel != null) || (!isPow && nodeListViewModel != null)), + assert(powNodeListViewModel == null || nodeListViewModel == null); final NodeListViewModel? nodeListViewModel; final PowNodeListViewModel? powNodeListViewModel; @@ -34,7 +35,7 @@ class ManageNodesPage extends BasePage { button: true, child: NodeHeaderListRow( title: S.of(context).add_new_node, - onTap: (_) async => await Navigator.of(context).pushNamed(Routes.newNode), + onTap: (_) async => await Navigator.of(context).pushNamed(isPow ? Routes.newPowNode : Routes.newNode), ), ), if (FeatureFlag.isAutomaticNodeSwitchingEnabled) @@ -80,7 +81,7 @@ class ManageNodesPage extends BasePage { title: node.uriRaw, node: node, isSelected: isSelected, - isPow: false, + isPow: isPow, onTap: (_) async { if (isSelected) { return;