From a8a70f5bb9490684f570c6ead3cd685f0cb4915b Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Tue, 2 Jun 2026 13:45:44 +0000 Subject: [PATCH] Node UI Fixes (#3275) * UI fixes, updated icons, and temporarily revert Rescan button * readd ping test button to node list, readd rescan to connections, fixup ui * increase gap for node edit button * remove rescan from connections for sp * remove rescan from connections for mweb --------- Co-authored-by: Robert Malikowski --- cw_monero/pubspec.lock | 2 +- cw_wownero/pubspec.lock | 2 +- cw_zano/pubspec.lock | 2 +- lib/new-ui/widgets/modal_header.dart | 74 ++++++----- .../screens/nodes/widgets/node_list_row.dart | 72 ++++++----- .../settings/connection_sync_page.dart | 6 + .../screens/settings/manage_nodes_page.dart | 115 +++++++++--------- .../node_list/node_list_view_model.dart | 11 +- .../settings/connection_sync_view_model.dart | 2 + .../node_speed_badges/disconnected-dark.svg | 6 + .../node_speed_badges/disconnected.svg | 6 +- res/pictures/node_speed_badges/fast.svg | 2 +- res/pictures/node_speed_badges/medium.svg | 4 +- res/pictures/node_speed_badges/slow-dark.svg | 7 ++ res/pictures/node_speed_badges/slow.svg | 10 +- 15 files changed, 187 insertions(+), 134 deletions(-) create mode 100644 res/pictures/node_speed_badges/disconnected-dark.svg create mode 100644 res/pictures/node_speed_badges/slow-dark.svg diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index d00f2149e..fc33c6fe8 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -592,7 +592,7 @@ packages: path: "impls/monero.dart" ref: "3bfb3856a838f2bf6b729501837bb0295dedf25d" resolved-ref: "3bfb3856a838f2bf6b729501837bb0295dedf25d" - url: "http://github.com/mrcyjanek/monero_c.git" + url: "https://github.com/mrcyjanek/monero_c.git" source: git version: "0.0.0" mutex: diff --git a/cw_wownero/pubspec.lock b/cw_wownero/pubspec.lock index 55cfb8fdf..3c12da261 100644 --- a/cw_wownero/pubspec.lock +++ b/cw_wownero/pubspec.lock @@ -504,7 +504,7 @@ packages: path: "impls/monero.dart" ref: "3bfb3856a838f2bf6b729501837bb0295dedf25d" resolved-ref: "3bfb3856a838f2bf6b729501837bb0295dedf25d" - url: "http://github.com/mrcyjanek/monero_c.git" + url: "https://github.com/mrcyjanek/monero_c.git" source: git version: "0.0.0" mutex: diff --git a/cw_zano/pubspec.lock b/cw_zano/pubspec.lock index 6e2916d71..080704b93 100644 --- a/cw_zano/pubspec.lock +++ b/cw_zano/pubspec.lock @@ -509,7 +509,7 @@ packages: path: "impls/monero.dart" ref: "3bfb3856a838f2bf6b729501837bb0295dedf25d" resolved-ref: "3bfb3856a838f2bf6b729501837bb0295dedf25d" - url: "http://github.com/mrcyjanek/monero_c.git" + url: "https://github.com/mrcyjanek/monero_c.git" source: git version: "0.0.0" nested: diff --git a/lib/new-ui/widgets/modal_header.dart b/lib/new-ui/widgets/modal_header.dart index 6bef2bba5..b43b07d03 100644 --- a/lib/new-ui/widgets/modal_header.dart +++ b/lib/new-ui/widgets/modal_header.dart @@ -1,6 +1,5 @@ import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; class ModalHeader extends StatelessWidget { const ModalHeader( @@ -17,38 +16,49 @@ class ModalHeader extends StatelessWidget { decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceContainer, borderRadius: BorderRadius.circular(16)), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - spacing: 10, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CakeImageWidget( - imageUrl: iconPath, width: 36, height: 36), - Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface), - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 32), - child: Text( - message, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + spacing: 10, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + CakeImageWidget( + imageUrl: iconPath, width: 36, height: 36), + Text( + title, style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurfaceVariant), - textAlign: TextAlign.center, - )), - if(bottomWidget != null) ...[ - Padding(padding: EdgeInsets.symmetric(horizontal: 18), child: Container(height:1, color: Theme.of(context).colorScheme.surfaceContainerHigh),), - bottomWidget! - ] - ], - ), + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 32), + child: Text( + message, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + color: Theme.of(context).colorScheme.onSurfaceVariant), + textAlign: TextAlign.center, + )), + + ], + ), + ), + if (bottomWidget != null) ...[ + Padding( + padding: EdgeInsets.symmetric(horizontal: 18), + child: + Container(height: 1, color: Theme.of(context).colorScheme.surfaceContainerHigh), + ), + ClipRRect( + borderRadius: BorderRadius.vertical(bottom: Radius.circular(16)), + child: bottomWidget!) + ] + ], ), ); } diff --git a/lib/src/screens/nodes/widgets/node_list_row.dart b/lib/src/screens/nodes/widgets/node_list_row.dart index 5be027481..7020e3bd8 100644 --- a/lib/src/screens/nodes/widgets/node_list_row.dart +++ b/lib/src/screens/nodes/widgets/node_list_row.dart @@ -10,7 +10,10 @@ class NodeListRow extends StatelessWidget { required this.onTap, required this.onEditComplete, required this.isSelected, - required this.isPow, this.speed}); + required this.isPow, + this.speed, + this.vertical = 10.0, + this.horizontal = 12.0}); final Node node; final bool isPow; @@ -18,6 +21,8 @@ class NodeListRow extends StatelessWidget { final Future Function(Object?) onEditComplete; final bool isSelected; final NodeSpeed? speed; + final double vertical; + final double horizontal; @override Widget build(BuildContext context) { @@ -26,32 +31,34 @@ class NodeListRow extends StatelessWidget { final hasLabel = node.label != null && node.label!.isNotEmpty; final uriText = "${node.uri.host}:${node.uri.port}"; - return GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: onTap, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 12), - child: Row( - spacing: 12, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - leading, - Expanded( - child: Column(crossAxisAlignment:CrossAxisAlignment.start,spacing:4,children: [ - Row( - spacing: 4, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text(hasLabel ? node.label! : uriText, style: TextStyle(fontSize: 12),), - if(badgePath != null) - CakeImageWidget(imageUrl: badgePath, colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary,BlendMode.srcIn),) - ], - ), - if(hasLabel) Text(uriText, style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),), - ],), - ), - trailing, - ], + return Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + child: Padding( + padding: EdgeInsets.symmetric(vertical: vertical, horizontal: horizontal), + child: Row( + spacing: 12, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + leading, + Expanded( + child: Column(crossAxisAlignment:CrossAxisAlignment.start,spacing:4,children: [ + Row( + spacing: 4, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text(hasLabel ? node.label! : uriText, style: TextStyle(fontSize: 12),), + if(badgePath != null) + CakeImageWidget(imageUrl: badgePath, colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary,BlendMode.srcIn),) + ], + ), + if(hasLabel) Text(uriText, style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),), + ],), + ), + trailing, + ], + ), ), ), ); @@ -71,7 +78,14 @@ class NodeListRow extends StatelessWidget { Widget buildTrailing(BuildContext context) { return Row( children: [ - if (speed != null) CakeImageWidget(imageUrl: speed!.iconPath, width: 24, height: 24), + if (speed != null) + CakeImageWidget( + imageUrl: Theme.of(context).brightness == Brightness.dark + ? speed!.darkIconPath + : speed!.iconPath, + width: 24, + height: 24, + ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () async { @@ -80,7 +94,7 @@ class NodeListRow extends StatelessWidget { await onEditComplete(res); }, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), + padding: const EdgeInsets.only(right: 8.0, left: 12.0), child: CakeImageWidget( imageUrl: "assets/new-ui/3dots_vertical.svg", colorFilter: diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 75d4d066e..123e81d0b 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -208,6 +208,12 @@ class ConnectionSyncPage extends BasePage { label: S.of(context).domain_looks_up, onTap: () => Navigator.of(context).pushNamed(Routes.domainLookupsPage) ), + if(_connectionSyncViewModel.hasRescan) + ListItemRegularRow( + keyValue: "rescan", + label: S.of(context).rescan, + onTap: ()=>Navigator.of(context).pushNamed(Routes.rescan) + ) ], } ) diff --git a/lib/src/screens/settings/manage_nodes_page.dart b/lib/src/screens/settings/manage_nodes_page.dart index 9f69c6587..75c384374 100644 --- a/lib/src/screens/settings/manage_nodes_page.dart +++ b/lib/src/screens/settings/manage_nodes_page.dart @@ -71,6 +71,8 @@ class _ManageNodesPageState extends State { title: S.of(context).nodes, bottomWidget: Observer( builder: (_) => NodeListRow( + // vertical: 0, + // horizontal: 0, node: widget.nodeListViewModel.currentNode, speed: widget.nodeListViewModel.nodeSpeedFor(widget.nodeListViewModel.currentNode), onEditComplete: (res)async{ @@ -90,63 +92,66 @@ class _ManageNodesPageState extends State { decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceContainer, borderRadius: BorderRadius.circular(18)), - child: Observer( - builder: (BuildContext context) { - int itemsCount = widget.nodeListViewModel.nonCurrentNodes.length; - return ListView.separated( - controller: ModalScrollController.of(context), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemCount: itemsCount, - separatorBuilder: (context, index) => Padding( - padding: EdgeInsets.symmetric(horizontal: 12), - child: Container( - height: 1, - color: Theme.of(context).colorScheme.surfaceContainerHigh, + child: ClipRRect( + borderRadius: BorderRadius.circular(18), + child: Observer( + builder: (BuildContext context) { + int itemsCount = widget.nodeListViewModel.nonCurrentNodes.length; + return ListView.separated( + controller: ModalScrollController.of(context), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemCount: itemsCount, + separatorBuilder: (context, index) => Padding( + padding: EdgeInsets.symmetric(horizontal: 12), + child: Container( + height: 1, + color: Theme.of(context).colorScheme.surfaceContainerHigh, + ), ), - ), - itemBuilder: (_, index) { - return Observer( - builder: (context) { - final node = widget.nodeListViewModel.nonCurrentNodes[index]; - final nodeListRow = NodeListRow( - node: node, - isSelected: false, - isPow: widget.isPow, - speed: widget.nodeListViewModel.nodeSpeedFor(node), - onEditComplete: (res) async { - if(res != null && res is Node) { - widget.nodeListViewModel.nodes.removeWhere((item)=>item.id == res.id); - widget.nodeListViewModel.nodes.add(res); - } + itemBuilder: (_, index) { + return Observer( + builder: (context) { + final node = widget.nodeListViewModel.nonCurrentNodes[index]; + final nodeListRow = NodeListRow( + node: node, + isSelected: false, + isPow: widget.isPow, + speed: widget.nodeListViewModel.nodeSpeedFor(node), + onEditComplete: (res) async { + if(res != null && res is Node) { + widget.nodeListViewModel.nodes.removeWhere((item)=>item.id == res.id); + widget.nodeListViewModel.nodes.add(res); + } - }, - onTap: () async { - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).change_current_node_title, - alertContent: - widget.nodeListViewModel.getAlertContent(node.uriRaw), - leftButtonText: S.of(context).cancel, - rightButtonText: S.of(context).change, - actionLeftButton: () => Navigator.of(context).pop(), - actionRightButton: () async { - await widget.nodeListViewModel.setAsCurrent(node); - Navigator.of(context).pop(); - }, - ); - }, - ); - }, - ); - return nodeListRow; - }, - ); - }, - ); - }, + }, + onTap: () async { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).change_current_node_title, + alertContent: + widget.nodeListViewModel.getAlertContent(node.uriRaw), + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).change, + actionLeftButton: () => Navigator.of(context).pop(), + actionRightButton: () async { + await widget.nodeListViewModel.setAsCurrent(node); + Navigator.of(context).pop(); + }, + ); + }, + ); + }, + ); + return nodeListRow; + }, + ); + }, + ); + }, + ), ), ), ], diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index cc91577af..3350f57e8 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -19,20 +19,21 @@ part 'node_list_view_model.g.dart'; class NodeSpeed { final String iconPath; + final String darkIconPath; // fraction of best node ping needed to be classified as this speed. final double treshold; - const NodeSpeed._(this.iconPath, this.treshold); + const NodeSpeed._(this.iconPath, this.darkIconPath, this.treshold); static const disconnected = NodeSpeed._( - "assets/new-ui/node_speed_badges/disconnected.svg", 0); + "assets/new-ui/node_speed_badges/disconnected.svg", "assets/new-ui/node_speed_badges/disconnected-dark.svg", 0); static const slow = NodeSpeed._( - "assets/new-ui/node_speed_badges/slow.svg", 0); + "assets/new-ui/node_speed_badges/slow.svg", "assets/new-ui/node_speed_badges/slow-dark.svg", 0); static const medium = NodeSpeed._( - "assets/new-ui/node_speed_badges/medium.svg", 0.5); + "assets/new-ui/node_speed_badges/medium.svg", "assets/new-ui/node_speed_badges/medium.svg", 0.5); static const fast = NodeSpeed._( - "assets/new-ui/node_speed_badges/fast.svg", 0.8); + "assets/new-ui/node_speed_badges/fast.svg", "assets/new-ui/node_speed_badges/fast.svg", 0.8); static const all = [fast, medium, slow, disconnected]; } diff --git a/lib/view_model/settings/connection_sync_view_model.dart b/lib/view_model/settings/connection_sync_view_model.dart index 47f4be7f4..1d1fb30f1 100644 --- a/lib/view_model/settings/connection_sync_view_model.dart +++ b/lib/view_model/settings/connection_sync_view_model.dart @@ -162,6 +162,8 @@ abstract class ConnectionSyncViewModelBase with Store { @action void setUseBlinkProtection(bool value) => _settingsStore.useBlinkProtection = value; + bool get hasRescan => _wallet.hasRescan && _wallet.type != WalletType.bitcoin && _wallet.type != WalletType.litecoin; + @action void setUseEtherscan(bool value) { _settingsStore.useEtherscan = value; diff --git a/res/pictures/node_speed_badges/disconnected-dark.svg b/res/pictures/node_speed_badges/disconnected-dark.svg new file mode 100644 index 000000000..e1f20e94e --- /dev/null +++ b/res/pictures/node_speed_badges/disconnected-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/res/pictures/node_speed_badges/disconnected.svg b/res/pictures/node_speed_badges/disconnected.svg index 33b7d28ba..03f001b5d 100644 --- a/res/pictures/node_speed_badges/disconnected.svg +++ b/res/pictures/node_speed_badges/disconnected.svg @@ -1,4 +1,6 @@ - - + + + + diff --git a/res/pictures/node_speed_badges/fast.svg b/res/pictures/node_speed_badges/fast.svg index 4205def6f..d7d1e8277 100644 --- a/res/pictures/node_speed_badges/fast.svg +++ b/res/pictures/node_speed_badges/fast.svg @@ -1,3 +1,3 @@ - + diff --git a/res/pictures/node_speed_badges/medium.svg b/res/pictures/node_speed_badges/medium.svg index 398280251..9de715bf5 100644 --- a/res/pictures/node_speed_badges/medium.svg +++ b/res/pictures/node_speed_badges/medium.svg @@ -1,4 +1,4 @@ - - + + diff --git a/res/pictures/node_speed_badges/slow-dark.svg b/res/pictures/node_speed_badges/slow-dark.svg new file mode 100644 index 000000000..5f8505073 --- /dev/null +++ b/res/pictures/node_speed_badges/slow-dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/res/pictures/node_speed_badges/slow.svg b/res/pictures/node_speed_badges/slow.svg index fc4d0b200..b51c980a6 100644 --- a/res/pictures/node_speed_badges/slow.svg +++ b/res/pictures/node_speed_badges/slow.svg @@ -1,7 +1,7 @@ - - - - - + + + + +