diff --git a/lib/pages/settings_views/global_settings_view/currency_view.dart b/lib/pages/settings_views/global_settings_view/currency_view.dart index e884393bd..4f2c3258c 100644 --- a/lib/pages/settings_views/global_settings_view/currency_view.dart +++ b/lib/pages/settings_views/global_settings_view/currency_view.dart @@ -7,13 +7,17 @@ import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; -import 'package:stackwallet/utilities/util.dart'; +import '../../../widgets/rounded_white_container.dart'; class BaseCurrencySettingsView extends ConsumerStatefulWidget { const BaseCurrencySettingsView({Key? key}) : super(key: key); @@ -102,31 +106,90 @@ class _CurrencyViewState extends ConsumerState { currenciesWithoutSelected.insert(0, current); } currenciesWithoutSelected = _filtered(); - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Currency", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), + final isDesktop = Util.isDesktop; + + return ConditionalParent( + condition: !isDesktop, + builder: (child) { + return Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed(const Duration(milliseconds: 75)); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Currency", + style: STextStyles.navBarTitle(context), + ), + ), + body: Padding( + padding: const EdgeInsets.only( + top: 12, + left: 16, + right: 16, + ), + child: child, + ), + ); + }, + child: ConditionalParent( + condition: isDesktop, + builder: (child) { + return Padding( + padding: const EdgeInsets.only( + top: 16, + bottom: 32, + left: 32, + right: 32, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(20), + borderColor: + Theme.of(context).extension()!.background, + child: child, + ), + ), + const SizedBox( + height: 16, + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + desktopMed: true, + onPressed: Navigator.of(context).pop, + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + label: "Save changes", + desktopMed: true, + onPressed: Navigator.of(context).pop, + ), + ), + ], + ), + ], + ), + ); + }, child: NestedScrollView( floatHeaderSlivers: true, headerSliverBuilder: (context, innerBoxIsScrolled) { diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 77349f399..87aee413e 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -8,7 +8,6 @@ import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; -import 'package:stackwallet/providers/global/node_service_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; @@ -20,15 +19,18 @@ import 'package:stackwallet/utilities/test_epic_box_connection.dart'; import 'package:stackwallet/utilities/test_monero_node_connection.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.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_dialog.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.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'; import 'package:uuid/uuid.dart'; -import 'package:stackwallet/utilities/util.dart'; - enum AddEditNodeViewType { add, edit } class AddEditNodeView extends ConsumerStatefulWidget { @@ -59,6 +61,7 @@ class _AddEditNodeViewState extends ConsumerState { late final AddEditNodeViewType viewType; late final Coin coin; late final String? nodeId; + late final bool isDesktop; late bool saveEnabled; late bool testConnectionEnabled; @@ -162,8 +165,198 @@ class _AddEditNodeViewState extends ConsumerState { return testPassed; } + Future attemptSave() async { + final canConnect = await _testConnection(showFlushBar: false); + + bool? shouldSave; + + if (!canConnect) { + await showDialog( + context: context, + useSafeArea: true, + barrierDismissible: true, + builder: (_) => isDesktop + ? DesktopDialog( + maxWidth: 440, + maxHeight: 300, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only( + top: 32, + ), + child: Row( + children: [ + const SizedBox( + width: 32, + ), + Text( + "Server currently unreachable", + style: STextStyles.desktopH3(context), + ), + ], + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + top: 16, + bottom: 32, + ), + child: Column( + children: [ + const Spacer(), + Text( + "Would you like to save this node anyways?", + style: STextStyles.desktopTextMedium(context), + ), + const Spacer( + flex: 2, + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + desktopMed: true, + onPressed: () => Navigator.of( + context, + rootNavigator: true, + ).pop(false), + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + label: "Save", + desktopMed: true, + onPressed: () => Navigator.of( + context, + rootNavigator: true, + ).pop(true), + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ) + : StackDialog( + title: "Server currently unreachable", + message: "Would you like to save this node anyways?", + leftButton: TextButton( + onPressed: () async { + Navigator.of(context).pop(false); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + ), + rightButton: TextButton( + onPressed: () async { + Navigator.of(context).pop(true); + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + child: Text( + "Save", + style: STextStyles.button(context), + ), + ), + ), + ).then((value) { + if (value is bool && value) { + shouldSave = true; + } else { + shouldSave = false; + } + }); + } + + if (!canConnect && !shouldSave!) { + // return without saving + return; + } + + final formData = ref.read(nodeFormDataProvider); + + // strip unused path + String address = formData.host!; + if (coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash) { + if (address.startsWith("http")) { + final uri = Uri.parse(address); + address = "${uri.scheme}://${uri.host}"; + } + } + + switch (viewType) { + case AddEditNodeViewType.add: + NodeModel node = NodeModel( + host: address, + port: formData.port!, + name: formData.name!, + id: const Uuid().v1(), + useSSL: formData.useSSL!, + loginName: formData.login, + enabled: true, + coinName: coin.name, + isFailover: formData.isFailover!, + isDown: false, + ); + + await ref.read(nodeServiceChangeNotifierProvider).add( + node, + formData.password, + true, + ); + if (mounted) { + Navigator.of(context) + .popUntil(ModalRoute.withName(widget.routeOnSuccessOrDelete)); + } + break; + case AddEditNodeViewType.edit: + NodeModel node = NodeModel( + host: address, + port: formData.port!, + name: formData.name!, + id: nodeId!, + useSSL: formData.useSSL!, + loginName: formData.login, + enabled: true, + coinName: coin.name, + isFailover: formData.isFailover!, + isDown: false, + ); + + await ref.read(nodeServiceChangeNotifierProvider).add( + node, + formData.password, + true, + ); + if (mounted) { + Navigator.of(context) + .popUntil(ModalRoute.withName(widget.routeOnSuccessOrDelete)); + } + break; + } + } + @override void initState() { + isDesktop = Util.isDesktop; ref.refresh(nodeFormDataProvider); viewType = widget.viewType; @@ -196,279 +389,203 @@ class _AddEditNodeViewState extends ConsumerState { .select((value) => value.getNodeById(id: nodeId!))) : null; - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - viewType == AddEditNodeViewType.edit ? "Edit node" : "Add node", - style: STextStyles.navBarTitle(context), - ), - actions: [ - if (viewType == AddEditNodeViewType.edit) - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("deleteNodeAppBarButtonKey"), - size: 36, - shadows: const [], - color: Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.trash, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, - ), - onPressed: () async { - Navigator.popUntil(context, - ModalRoute.withName(widget.routeOnSuccessOrDelete)); + return ConditionalParent( + condition: !isDesktop, + builder: (child) => Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed(const Duration(milliseconds: 75)); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + viewType == AddEditNodeViewType.edit ? "Edit node" : "Add node", + style: STextStyles.navBarTitle(context), + ), + actions: [ + if (viewType == AddEditNodeViewType.edit) + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("deleteNodeAppBarButtonKey"), + size: 36, + shadows: const [], + color: + Theme.of(context).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.trash, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 20, + height: 20, + ), + onPressed: () async { + Navigator.popUntil(context, + ModalRoute.withName(widget.routeOnSuccessOrDelete)); - await ref.read(nodeServiceChangeNotifierProvider).delete( - nodeId!, - true, - ); - }, + await ref.read(nodeServiceChangeNotifierProvider).delete( + nodeId!, + true, + ); + }, + ), ), ), - ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, - bottom: 12, + ], ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight - 8), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - NodeForm( - node: node, - secureStore: widget.secureStore, - readOnly: false, - coin: widget.coin, - onChanged: (canSave, canTest) { - if (canSave != saveEnabled && - canTest != testConnectionEnabled) { - setState(() { - saveEnabled = canSave; - testConnectionEnabled = canTest; - }); - } else if (canSave != saveEnabled) { - setState(() { - saveEnabled = canSave; - }); - } else if (canTest != testConnectionEnabled) { - setState(() { - testConnectionEnabled = canTest; - }); - } - }, - ), - const Spacer(), - TextButton( - onPressed: testConnectionEnabled - ? () async { - await _testConnection(); - } - : null, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonColor(context), - child: Text( - "Test connection", - style: STextStyles.button(context).copyWith( - color: testConnectionEnabled - ? Theme.of(context) - .extension()! - .textDark - : Theme.of(context) - .extension()! - .textWhite, - ), - ), - ), - const SizedBox(height: 16), - TextButton( - style: saveEnabled - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonColor(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonColor(context), - onPressed: saveEnabled - ? () async { - final canConnect = await _testConnection( - showFlushBar: false); - - bool? shouldSave; - - if (!canConnect) { - await showDialog( - context: context, - useSafeArea: true, - barrierDismissible: true, - builder: (_) => StackDialog( - title: "Server currently unreachable", - message: - "Would you like to save this node anyways?", - leftButton: TextButton( - onPressed: () async { - Navigator.of(context).pop(false); - }, - child: Text( - "Cancel", - style: STextStyles.button(context) - .copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .accentColorDark), - ), - ), - rightButton: TextButton( - onPressed: () async { - Navigator.of(context).pop(true); - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonColor( - context), - child: Text( - "Save", - style: STextStyles.button(context), - ), - ), - ), - ).then((value) { - if (value is bool && value) { - shouldSave = true; - } else { - shouldSave = false; - } - }); - } - - if (!canConnect && !shouldSave!) { - // return without saving - return; - } - - final formData = - ref.read(nodeFormDataProvider); - - // strip unused path - String address = formData.host!; - if (coin == Coin.monero || - coin == Coin.wownero || - coin == Coin.epicCash) { - if (address.startsWith("http")) { - final uri = Uri.parse(address); - address = "${uri.scheme}://${uri.host}"; - } - } - - switch (viewType) { - case AddEditNodeViewType.add: - NodeModel node = NodeModel( - host: address, - port: formData.port!, - name: formData.name!, - id: const Uuid().v1(), - useSSL: formData.useSSL!, - loginName: formData.login, - enabled: true, - coinName: coin.name, - isFailover: formData.isFailover!, - isDown: false, - ); - - await ref - .read( - nodeServiceChangeNotifierProvider) - .add( - node, - formData.password, - true, - ); - if (mounted) { - Navigator.of(context).popUntil( - ModalRoute.withName( - widget.routeOnSuccessOrDelete)); - } - break; - case AddEditNodeViewType.edit: - NodeModel node = NodeModel( - host: address, - port: formData.port!, - name: formData.name!, - id: nodeId!, - useSSL: formData.useSSL!, - loginName: formData.login, - enabled: true, - coinName: coin.name, - isFailover: formData.isFailover!, - isDown: false, - ); - - await ref - .read( - nodeServiceChangeNotifierProvider) - .add( - node, - formData.password, - true, - ); - if (mounted) { - Navigator.of(context).popUntil( - ModalRoute.withName( - widget.routeOnSuccessOrDelete)); - } - break; - } - } - : null, - child: Text( - "Save", - style: STextStyles.button(context), - ), - ), - ], + body: Padding( + padding: const EdgeInsets.only( + top: 12, + left: 12, + right: 12, + bottom: 12, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: ConstrainedBox( + constraints: + BoxConstraints(minHeight: constraints.maxHeight - 8), + child: IntrinsicHeight( + child: child, ), ), ), + ); + }, + ), + ), + ), + child: ConditionalParent( + condition: isDesktop, + builder: (child) => DesktopDialog( + maxWidth: 580, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + const SizedBox( + width: 8, + ), + const AppBarBackButton( + iconSize: 24, + size: 40, + ), + Text( + "Add new node", + style: STextStyles.desktopH3(context), + ) + ], ), - ); - }, + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + top: 16, + bottom: 32, + ), + child: child, + ), + ], + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + NodeForm( + node: node, + secureStore: widget.secureStore, + readOnly: false, + coin: widget.coin, + onChanged: (canSave, canTest) { + if (canSave != saveEnabled && + canTest != testConnectionEnabled) { + setState(() { + saveEnabled = canSave; + testConnectionEnabled = canTest; + }); + } else if (canSave != saveEnabled) { + setState(() { + saveEnabled = canSave; + }); + } else if (canTest != testConnectionEnabled) { + setState(() { + testConnectionEnabled = canTest; + }); + } + }, + ), + if (!isDesktop) const Spacer(), + if (isDesktop) + const SizedBox( + height: 78, + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Test connection", + enabled: testConnectionEnabled, + desktopMed: true, + onPressed: testConnectionEnabled + ? () async { + await _testConnection(); + } + : null, + ), + ), + if (isDesktop) + const SizedBox( + width: 16, + ), + if (isDesktop) + Expanded( + child: PrimaryButton( + label: "Save", + enabled: saveEnabled, + desktopMed: true, + onPressed: saveEnabled ? attemptSave : null, + ), + ), + ], + ), + if (!isDesktop) + const SizedBox( + height: 16, + ), + if (!isDesktop) + TextButton( + style: saveEnabled + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonColor(context), + onPressed: saveEnabled ? attemptSave : null, + child: Text( + "Save", + style: STextStyles.button(context), + ), + ), + ], ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart index e3743d54e..a93b64be3 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart @@ -9,6 +9,7 @@ import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:tuple/tuple.dart'; @@ -17,11 +18,13 @@ class CoinNodesView extends ConsumerStatefulWidget { const CoinNodesView({ Key? key, required this.coin, + this.rootNavigator = false, }) : super(key: key); static const String routeName = "/coinNodes"; final Coin coin; + final bool rootNavigator; @override ConsumerState createState() => _CoinNodesViewState(); @@ -63,12 +66,17 @@ class _CoinNodesViewState extends ConsumerState { textAlign: TextAlign.center, ), Expanded( - child: const DesktopDialogCloseButton(), + child: DesktopDialogCloseButton( + onPressedOverride: Navigator.of( + context, + rootNavigator: widget.rootNavigator, + ).pop, + ), ), ], ), Padding( - padding: EdgeInsets.only( + padding: const EdgeInsets.only( left: 32, right: 32, ), @@ -83,14 +91,19 @@ class _CoinNodesViewState extends ConsumerState { ), textAlign: TextAlign.left, ), - RichText( - text: TextSpan( - text: 'Add new nodes', - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Colors.blueAccent, - ), - ), + BlueTextButton( + text: "Add new node", + onTap: () { + Navigator.of(context).pushNamed( + AddEditNodeView.routeName, + arguments: Tuple4( + AddEditNodeViewType.add, + widget.coin, + null, + CoinNodesView.routeName, + ), + ); + }, ), ], ), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index c5f797e37..c5e666ce2 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -17,7 +17,13 @@ import 'package:stackwallet/utilities/test_epic_box_connection.dart'; import 'package:stackwallet/utilities/test_monero_node_connection.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/delete_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:tuple/tuple.dart'; class NodeDetailsView extends ConsumerStatefulWidget { @@ -48,6 +54,8 @@ class _NodeDetailsViewState extends ConsumerState { late final String nodeId; late final String popRouteName; + bool _desktopReadOnly = true; + @override initState() { secureStore = widget.secureStore; @@ -126,130 +134,239 @@ class _NodeDetailsViewState extends ConsumerState { } if (testPassed) { - showFloatingFlushBar( - type: FlushBarType.success, - message: "Server ping success", - context: context, + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: "Server ping success", + context: context, + ), ); } else { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Server unreachable", - context: context, + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Server unreachable", + context: context, + ), ); } } @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Node details", - style: STextStyles.navBarTitle(context), - ), - actions: [ - if (!nodeId.startsWith("default")) - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("nodeDetailsEditNodeAppBarButtonKey"), - size: 36, - shadows: const [], - color: Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.pencil, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, + final isDesktop = Util.isDesktop; + + final node = ref.watch(nodeServiceChangeNotifierProvider + .select((value) => value.getNodeById(id: nodeId))); + + return ConditionalParent( + condition: !isDesktop, + builder: (child) => Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed(const Duration(milliseconds: 75)); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Node details", + style: STextStyles.navBarTitle(context), + ), + actions: [ + if (!nodeId.startsWith("default")) + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("nodeDetailsEditNodeAppBarButtonKey"), + size: 36, + shadows: const [], + color: + Theme.of(context).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.pencil, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context).pushNamed( + AddEditNodeView.routeName, + arguments: Tuple4( + AddEditNodeViewType.edit, + coin, + nodeId, + popRouteName, + ), + ); + }, ), - onPressed: () { - Navigator.of(context).pushNamed( - AddEditNodeView.routeName, - arguments: Tuple4( - AddEditNodeViewType.edit, - coin, - nodeId, - popRouteName, - ), - ); - }, ), ), - ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, + ], ), - child: LayoutBuilder( - builder: (context, constraints) { - final node = ref.watch(nodeServiceChangeNotifierProvider - .select((value) => value.getNodeById(id: nodeId))); - - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight - 8), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - NodeForm( - node: node, - secureStore: secureStore, - readOnly: true, - coin: coin, - ), - const Spacer(), - TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonColor(context), - onPressed: () async { - await _testConnection(ref, context); - }, - child: Text( - "Test connection", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark), - ), - ), - const SizedBox(height: 16), - ], + body: Padding( + padding: const EdgeInsets.only( + top: 12, + left: 12, + right: 12, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: ConstrainedBox( + constraints: + BoxConstraints(minHeight: constraints.maxHeight - 8), + child: IntrinsicHeight( + child: child, ), ), ), + ); + }, + ), + ), + ), + child: ConditionalParent( + condition: isDesktop, + builder: (child) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + const SizedBox( + width: 8, + ), + const AppBarBackButton( + iconSize: 24, + size: 40, + ), + Text( + "Node details", + style: STextStyles.desktopH3(context), + ) + ], ), - ); - }, + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + top: 16, + bottom: 32, + ), + child: child, + ), + ], + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + NodeForm( + node: node, + secureStore: secureStore, + readOnly: isDesktop ? _desktopReadOnly : true, + coin: coin, + ), + if (!isDesktop) const Spacer(), + if (isDesktop) + const SizedBox( + height: 22, + ), + if (isDesktop) + SizedBox( + height: 56, + child: _desktopReadOnly + ? null + : Row( + children: [ + Expanded( + child: DeleteButton( + label: "Delete node", + desktopMed: true, + onPressed: () async { + Navigator.of(context).pop(); + + await ref + .read(nodeServiceChangeNotifierProvider) + .delete( + node!.id, + true, + ); + }, + ), + ), + const SizedBox( + width: 16, + ), + const Spacer(), + ], + ), + ), + if (isDesktop && !_desktopReadOnly) + const SizedBox( + height: 45, + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Test connection", + desktopMed: true, + onPressed: () async { + await _testConnection(ref, context); + }, + ), + ), + if (isDesktop) + const SizedBox( + width: 16, + ), + if (isDesktop) + Expanded( + child: !nodeId.startsWith("default") + ? PrimaryButton( + label: _desktopReadOnly ? "Edit" : "Save", + desktopMed: true, + onPressed: () async { + final shouldSave = _desktopReadOnly == false; + setState(() { + _desktopReadOnly = !_desktopReadOnly; + }); + + if (shouldSave) { + // todo save node + } + }, + ) + : Container(), + ), + ], + ), + if (!isDesktop) + const SizedBox( + height: 16, + ), + ], ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart index bada67353..3681009a9 100644 --- a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart +++ b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart @@ -6,7 +6,11 @@ import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/sync_type_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.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_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; class SyncingOptionsView extends ConsumerWidget { @@ -16,384 +20,390 @@ class SyncingOptionsView extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Syncing", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, + final isDesktop = Util.isDesktop; + return ConditionalParent( + condition: !isDesktop, + builder: (child) { + return Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Syncing", + style: STextStyles.navBarTitle(context), + ), + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: child, + ), + ), + ); + }, + ), + ), + ); + }, + child: Column( + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(4), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + final state = + ref.read(prefsChangeNotifierProvider).syncType; + if (state != SyncingType.currentWalletOnly) { + ref.read(prefsChangeNotifierProvider).syncType = + SyncingType.currentWalletOnly; + + // disable auto sync on all wallets that aren't active/current + ref + .read(walletsChangeNotifierProvider) + .managers + .forEach((e) { + if (!e.isActiveWallet) { + e.shouldAutoSync = false; + } + }); + } + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding( - padding: const EdgeInsets.all(4), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: SyncingType.currentWalletOnly, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select((value) => value.syncType), ), - onPressed: () { - final state = ref - .read(prefsChangeNotifierProvider) - .syncType; - if (state != SyncingType.currentWalletOnly) { + onChanged: (value) { + if (value is SyncingType) { ref - .read(prefsChangeNotifierProvider) - .syncType = - SyncingType.currentWalletOnly; - - // disable auto sync on all wallets that aren't active/current - ref - .read(walletsChangeNotifierProvider) - .managers - .forEach((e) { - if (!e.isActiveWallet) { - e.shouldAutoSync = false; - } - }); - } - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: - SyncingType.currentWalletOnly, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => - value.syncType), - ), - onChanged: (value) { - if (value is SyncingType) { - ref - .read( - prefsChangeNotifierProvider) - .syncType = value; - } - }, - ), - ), - const SizedBox( - width: 12, - ), - Flexible( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Sync only currently open wallet", - style: STextStyles.titleBold12( - context), - textAlign: TextAlign.left, - ), - Text( - "Sync only the wallet that you are using", - style: STextStyles.itemSubtitle( - context), - textAlign: TextAlign.left, - ), - ], - ), - ), - ], - ), - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.all(4.0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - final state = ref - .read(prefsChangeNotifierProvider) - .syncType; - if (state != - SyncingType.allWalletsOnStartup) { - ref - .read(prefsChangeNotifierProvider) - .syncType = - SyncingType.allWalletsOnStartup; - - // enable auto sync on all wallets - ref - .read(walletsChangeNotifierProvider) - .managers - .forEach( - (e) => e.shouldAutoSync = true); - } - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: - SyncingType.allWalletsOnStartup, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => - value.syncType), - ), - onChanged: (value) { - if (value is SyncingType) { - ref - .read( - prefsChangeNotifierProvider) - .syncType = value; - } - }, - ), - ), - const SizedBox( - width: 12, - ), - Flexible( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Sync all wallets at startup", - style: STextStyles.titleBold12( - context), - textAlign: TextAlign.left, - ), - Text( - "All of your wallets will start syncing when you open the app", - style: STextStyles.itemSubtitle( - context), - textAlign: TextAlign.left, - ), - ], - ), - ), - ], - ), - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.all(4), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - final state = ref - .read(prefsChangeNotifierProvider) - .syncType; - if (state != - SyncingType.selectedWalletsAtStartup) { - ref - .read(prefsChangeNotifierProvider) - .syncType = - SyncingType.selectedWalletsAtStartup; - - final ids = ref .read(prefsChangeNotifierProvider) - .walletIdsSyncOnStartup; - - // enable auto sync on selected wallets only - ref - .read(walletsChangeNotifierProvider) - .managers - .forEach((e) => e.shouldAutoSync = - ids.contains(e.walletId)); + .syncType = value; } }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(8), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: SyncingType - .selectedWalletsAtStartup, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => - value.syncType), - ), - onChanged: (value) { - if (value is SyncingType) { - ref - .read( - prefsChangeNotifierProvider) - .syncType = value; - } - }, - ), - ), - const SizedBox( - width: 12, - ), - Flexible( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Sync only selected wallets at startup", - style: STextStyles.titleBold12( - context), - textAlign: TextAlign.left, - ), - Text( - "Only the wallets you select will start syncing when you open the app", - style: STextStyles.itemSubtitle( - context), - textAlign: TextAlign.left, - ), - ], - ), - ), - ], - ), - ), - ), ), ), - if (ref.watch(prefsChangeNotifierProvider - .select((value) => value.syncType)) != - SyncingType.selectedWalletsAtStartup) - const SizedBox( - height: 12, - ), - if (ref.watch(prefsChangeNotifierProvider - .select((value) => value.syncType)) == - SyncingType.selectedWalletsAtStartup) - Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - right: 12, - bottom: 12, + const SizedBox( + width: 12, + ), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Sync only currently open wallet", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, ), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - const SizedBox( - width: 12 + 20, - height: 12, - ), - Flexible( - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants - .size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context).pushNamed( - WalletSyncingOptionsView - .routeName); - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Select wallets...", - style: - STextStyles.link2(context), - textAlign: TextAlign.left, - ), - ], - ), - ), - ), - ], + Text( + "Sync only the wallet that you are using", + style: STextStyles.itemSubtitle(context), + textAlign: TextAlign.left, ), - ), + ], ), + ), ], ), ), - ], + ), ), ), - ), - ); - }, - ), + Padding( + padding: const EdgeInsets.all(4.0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + final state = + ref.read(prefsChangeNotifierProvider).syncType; + if (state != SyncingType.allWalletsOnStartup) { + ref.read(prefsChangeNotifierProvider).syncType = + SyncingType.allWalletsOnStartup; + + // enable auto sync on all wallets + ref + .read(walletsChangeNotifierProvider) + .managers + .forEach((e) => e.shouldAutoSync = true); + } + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: SyncingType.allWalletsOnStartup, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select((value) => value.syncType), + ), + onChanged: (value) { + if (value is SyncingType) { + ref + .read(prefsChangeNotifierProvider) + .syncType = value; + } + }, + ), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Sync all wallets at startup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + Text( + "All of your wallets will start syncing when you open the app", + style: STextStyles.itemSubtitle(context), + textAlign: TextAlign.left, + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(4), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + final state = + ref.read(prefsChangeNotifierProvider).syncType; + if (state != SyncingType.selectedWalletsAtStartup) { + ref.read(prefsChangeNotifierProvider).syncType = + SyncingType.selectedWalletsAtStartup; + + final ids = ref + .read(prefsChangeNotifierProvider) + .walletIdsSyncOnStartup; + + // enable auto sync on selected wallets only + ref + .read(walletsChangeNotifierProvider) + .managers + .forEach((e) => + e.shouldAutoSync = ids.contains(e.walletId)); + } + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: SyncingType.selectedWalletsAtStartup, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select((value) => value.syncType), + ), + onChanged: (value) { + if (value is SyncingType) { + ref + .read(prefsChangeNotifierProvider) + .syncType = value; + } + }, + ), + ), + const SizedBox( + width: 12, + ), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Sync only selected wallets at startup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + Text( + "Only the wallets you select will start syncing when you open the app", + style: STextStyles.itemSubtitle(context), + textAlign: TextAlign.left, + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + if (ref.watch(prefsChangeNotifierProvider + .select((value) => value.syncType)) != + SyncingType.selectedWalletsAtStartup) + const SizedBox( + height: 12, + ), + if (ref.watch(prefsChangeNotifierProvider + .select((value) => value.syncType)) == + SyncingType.selectedWalletsAtStartup) + Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, + right: 12, + bottom: 12, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + width: 12 + 20, + height: 12, + ), + Flexible( + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + !isDesktop + ? Navigator.of(context).pushNamed( + WalletSyncingOptionsView.routeName) + : showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxWidth: 600, + maxHeight: 800, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Padding( + padding: + const EdgeInsets.all( + 32), + child: Text( + "Select wallets to sync", + style: STextStyles + .desktopH3(context), + textAlign: + TextAlign.center, + ), + ), + const DesktopDialogCloseButton(), + ], + ), + const Expanded( + child: + WalletSyncingOptionsView(), + ), + ], + ), + ); + }); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Select wallets...", + style: STextStyles.link2(context), + textAlign: TextAlign.left, + ), + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ], ), ); } diff --git a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart index 1e302cf12..9724356a1 100644 --- a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart +++ b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart @@ -10,7 +10,9 @@ import 'package:stackwallet/utilities/enums/sync_type_enum.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/animated_text.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; @@ -25,30 +27,47 @@ class WalletSyncingOptionsView extends ConsumerWidget { final managers = ref .watch(walletsChangeNotifierProvider.select((value) => value.managers)); - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - "Sync only selected wallets at startup", - style: STextStyles.navBarTitle(context), + final isDesktop = Util.isDesktop; + return ConditionalParent( + condition: !isDesktop, + builder: (child) { + return Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + "Sync only selected wallets at startup", + style: STextStyles.navBarTitle(context), + ), + ), ), - ), - ), - body: LayoutBuilder(builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + body: Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, + ), + child: child, ), - child: SingleChildScrollView( + ); + }, + child: ConditionalParent( + condition: isDesktop, + builder: (child) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 32), + child: child, + ); + }, + child: LayoutBuilder(builder: (context, constraints) { + return SingleChildScrollView( child: ConstrainedBox( constraints: BoxConstraints( minHeight: constraints.maxHeight - 24, @@ -71,6 +90,11 @@ class WalletSyncingOptionsView extends ConsumerWidget { ), RoundedWhiteContainer( padding: const EdgeInsets.all(0), + borderColor: !isDesktop + ? Colors.transparent + : Theme.of(context) + .extension()! + .background, child: Column( children: [ ...managers.map( @@ -208,9 +232,9 @@ class WalletSyncingOptionsView extends ConsumerWidget { ), ), ), - ), - ); - }), + ); + }), + ), ); } } diff --git a/lib/pages/stack_privacy_calls.dart b/lib/pages/stack_privacy_calls.dart index fd6f60def..3f819492e 100644 --- a/lib/pages/stack_privacy_calls.dart +++ b/lib/pages/stack_privacy_calls.dart @@ -14,6 +14,7 @@ import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.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'; @@ -70,180 +71,195 @@ class _StackPrivacyCalls extends ConsumerState { ), ), body: SafeArea( - child: Padding( - padding: EdgeInsets.fromLTRB(0, isDesktop ? 0 : 40, 0, 0), - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: isDesktop ? 480 : double.infinity, + child: ConditionalParent( + condition: !isDesktop, + builder: (child) => LayoutBuilder( + builder: (context, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: child, + ), + ), ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Choose your Stack experience", - style: isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.pageTitleH1(context), - ), - SizedBox( - height: isDesktop ? 16 : 8, - ), - Text( - !widget.isSettings - ? "You can change it later in Settings" - : "", - style: isDesktop - ? STextStyles.desktopSubtitleH2(context) - : STextStyles.subtitle(context), - ), - SizedBox( - height: isDesktop ? 32 : 36, - ), - Padding( - padding: EdgeInsets.symmetric( - horizontal: isDesktop ? 0 : 16, + ), + child: Padding( + padding: EdgeInsets.fromLTRB(0, isDesktop ? 0 : 40, 0, 0), + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: isDesktop ? 480 : double.infinity, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Choose your Stack experience", + style: isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), ), - child: PrivacyToggle( - externalCallsEnabled: isEasy, - onChanged: (externalCalls) { - isEasy = externalCalls; - setState(() { - infoToggle = isEasy; - }); - }, + SizedBox( + height: isDesktop ? 16 : 8, ), - ), - SizedBox( - height: isDesktop ? 16 : 36, - ), - Padding( - padding: isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(16.0), - child: RoundedWhiteContainer( - child: Center( - child: RichText( - textAlign: TextAlign.left, - text: TextSpan( - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.label(context).copyWith( - fontSize: 12.0, - ), - children: infoToggle - ? [ - const TextSpan( - text: - "Exchange data preloaded for a seamless experience."), - const TextSpan( - text: - "\n\nCoinGecko enabled: (24 hour price change shown in-app, total wallet value shown in USD or other currency)."), - TextSpan( - text: - "\n\nRecommended for most crypto users.", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall600( - context) - : TextStyle( - color: Theme.of(context) - .extension()! - .textDark, - fontWeight: FontWeight.w600, - ), + Text( + !widget.isSettings + ? "You can change it later in Settings" + : "", + style: isDesktop + ? STextStyles.desktopSubtitleH2(context) + : STextStyles.subtitle(context), + ), + SizedBox( + height: isDesktop ? 32 : 36, + ), + Padding( + padding: EdgeInsets.symmetric( + horizontal: isDesktop ? 0 : 16, + ), + child: PrivacyToggle( + externalCallsEnabled: isEasy, + onChanged: (externalCalls) { + isEasy = externalCalls; + setState(() { + infoToggle = isEasy; + }); + }, + ), + ), + SizedBox( + height: isDesktop ? 16 : 36, + ), + Padding( + padding: isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(16.0), + child: RoundedWhiteContainer( + child: Center( + child: RichText( + textAlign: TextAlign.left, + text: TextSpan( + style: isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.label(context).copyWith( + fontSize: 12.0, ), - ] - : [ - const TextSpan( + children: infoToggle + ? [ + const TextSpan( + text: + "Exchange data preloaded for a seamless experience."), + const TextSpan( + text: + "\n\nCoinGecko enabled: (24 hour price change shown in-app, total wallet value shown in USD or other currency)."), + TextSpan( text: - "Exchange data not preloaded (slower experience)."), - const TextSpan( + "\n\nRecommended for most crypto users.", + style: isDesktop + ? STextStyles + .desktopTextExtraExtraSmall600( + context) + : TextStyle( + color: Theme.of(context) + .extension()! + .textDark, + fontWeight: FontWeight.w600, + ), + ), + ] + : [ + const TextSpan( + text: + "Exchange data not preloaded (slower experience)."), + const TextSpan( + text: + "\n\nCoinGecko disabled (price changes not shown, no wallet value shown in other currencies)."), + TextSpan( text: - "\n\nCoinGecko disabled (price changes not shown, no wallet value shown in other currencies)."), - TextSpan( - text: - "\n\nRecommended for the privacy conscious.", - style: isDesktop - ? STextStyles - .desktopTextExtraExtraSmall600( - context) - : TextStyle( - color: Theme.of(context) - .extension()! - .textDark, - fontWeight: FontWeight.w600, - ), - ), - ], + "\n\nRecommended for the privacy conscious.", + style: isDesktop + ? STextStyles + .desktopTextExtraExtraSmall600( + context) + : TextStyle( + color: Theme.of(context) + .extension()! + .textDark, + fontWeight: FontWeight.w600, + ), + ), + ], + ), ), ), ), ), - ), - if (!isDesktop) - const Spacer( - flex: 4, - ), - if (isDesktop) - const SizedBox( - height: 32, - ), - Padding( - padding: isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - child: Row( - children: [ - Expanded( - child: PrimaryButton( - label: - !widget.isSettings ? "Continue" : "Save changes", - onPressed: () { - ref - .read(prefsChangeNotifierProvider) - .externalCalls = isEasy; + if (!isDesktop) + const Spacer( + flex: 4, + ), + if (isDesktop) + const SizedBox( + height: 32, + ), + Padding( + padding: isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + child: Row( + children: [ + Expanded( + child: PrimaryButton( + label: + !widget.isSettings ? "Continue" : "Save changes", + onPressed: () { + ref + .read(prefsChangeNotifierProvider) + .externalCalls = isEasy; - DB.instance - .put( - boxName: DB.boxNamePrefs, - key: "externalCalls", - value: isEasy) - .then((_) { - if (isEasy) { - unawaited( - ExchangeDataLoadingService().loadAll(ref)); - ref - .read(priceAnd24hChangeNotifierProvider) - .start(true); - } - }); - if (!widget.isSettings) { - if (isDesktop) { - Navigator.of(context).pushNamed( - CreatePasswordView.routeName, - ); + DB.instance + .put( + boxName: DB.boxNamePrefs, + key: "externalCalls", + value: isEasy) + .then((_) { + if (isEasy) { + unawaited( + ExchangeDataLoadingService().loadAll(ref)); + ref + .read(priceAnd24hChangeNotifierProvider) + .start(true); + } + }); + if (!widget.isSettings) { + if (isDesktop) { + Navigator.of(context).pushNamed( + CreatePasswordView.routeName, + ); + } else { + Navigator.of(context).pushNamed( + CreatePinView.routeName, + ); + } } else { - Navigator.of(context).pushNamed( - CreatePinView.routeName, - ); + Navigator.pop(context); } - } else { - Navigator.pop(context); - } - }, + }, + ), ), - ), - ], + ], + ), ), - ), - if (isDesktop) - const SizedBox( - height: kDesktopAppBarHeight, - ), - ], + if (isDesktop) + const SizedBox( + height: kDesktopAppBarHeight, + ), + ], + ), ), ), ), @@ -494,158 +510,3 @@ class _PrivacyToggleState extends State { ); } } - -// class ContinueButton extends ConsumerWidget { -// const ContinueButton({ -// Key? key, -// required this.isDesktop, -// required this.onPressed, -// required this.label, -// }) : super(key: key); -// -// final String label; -// final bool isDesktop; -// final VoidCallback onPressed; -// -// @override -// Widget build(BuildContext context, WidgetRef ref) { -// if (isDesktop) { -// return SizedBox( -// width: 328, -// height: 70, -// child: TextButton( -// style: Theme.of(context) -// .extension()! -// .getPrimaryEnabledButtonColor(context), -// onPressed: onPressed, -// child: Text( -// label, -// style: STextStyles.button(context).copyWith(fontSize: 20), -// ), -// ), -// ); -// } else { -// return TextButton( -// style: Theme.of(context) -// .extension()! -// .getPrimaryEnabledButtonColor(context), -// onPressed: onPressed, -// child: Text( -// label, -// style: STextStyles.button(context), -// ), -// ); -// } -// } -// } - -// class CustomRadio extends StatefulWidget { -// CustomRadio(this.upperCall, {Key? key}) : super(key: key); -// -// Function upperCall; -// -// @override -// createState() { -// return CustomRadioState(); -// } -// } -// -// class CustomRadioState extends State { -// List sampleData = []; -// -// @override -// void initState() { -// super.initState(); -// sampleData.add( -// RadioModel(true, Assets.svg.personaEasy, 'Easy Crypto', 'Recommended')); -// sampleData.add(RadioModel( -// false, Assets.svg.personaIncognito, 'Incognito', 'Privacy conscious')); -// } -// -// @override -// Widget build(BuildContext context) { -// return Row( -// mainAxisAlignment: MainAxisAlignment.center, -// children: [ -// InkWell( -// onTap: () { -// setState(() { -// // if (!sampleData[0].isSelected) { -// widget.upperCall.call(true); -// // } -// for (var element in sampleData) { -// element.isSelected = false; -// } -// sampleData[0].isSelected = true; -// }); -// }, -// child: RadioItem(sampleData[0]), -// ), -// InkWell( -// onTap: () { -// setState(() { -// // if (!sampleData[1].isSelected) { -// widget.upperCall.call(false); -// // } -// for (var element in sampleData) { -// element.isSelected = false; -// } -// sampleData[1].isSelected = true; -// }); -// }, -// child: RadioItem(sampleData[1]), -// ) -// ], -// ); -// } -// } -// -// class RadioItem extends StatelessWidget { -// final RadioModel _item; -// const RadioItem(this._item, {Key? key}) : super(key: key); -// @override -// Widget build(BuildContext context) { -// return Container( -// margin: const EdgeInsets.all(15.0), -// child: RoundedWhiteContainer( -// borderColor: _item.isSelected ? const Color(0xFF0056D2) : null, -// child: Center( -// child: Column( -// children: [ -// SvgPicture.asset( -// _item.svg, -// // color: Theme.of(context).extension()!.textWhite, -// width: 140, -// height: 140, -// ), -// RichText( -// textAlign: TextAlign.center, -// text: TextSpan( -// style: STextStyles.label(context).copyWith(fontSize: 12.0), -// children: [ -// TextSpan( -// text: _item.topText, -// style: TextStyle( -// color: Theme.of(context) -// .extension()! -// .textDark, -// fontWeight: FontWeight.bold)), -// TextSpan(text: "\n${_item.bottomText}"), -// ], -// ), -// ), -// ], -// )), -// ), -// ); -// } -// } -// -// class RadioModel { -// bool isSelected; -// final String svg; -// final String topText; -// final String bottomText; -// -// RadioModel(this.isSelected, this.svg, this.topText, this.bottomText); -// } diff --git a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart index 8604ae721..d41877a9a 100644 --- a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart +++ b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart @@ -21,6 +21,7 @@ import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.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_dialog.dart'; @@ -302,68 +303,78 @@ class _TransactionDetailsViewState extends ConsumerState { padding: const EdgeInsets.all(4), child: Row( children: [ - SizedBox( - width: isDesktop ? 570 : null, - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + ConditionalParent( + condition: isDesktop, + builder: (child) => SizedBox( + width: 570, + child: child, + ), + child: ConditionalParent( + condition: !isDesktop, + builder: (child) => Expanded( + child: child, ), - child: TextField( - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - controller: _searchController, - focusNode: searchFieldFocusNode, - onChanged: (value) { - setState(() { - _searchString = value; - }); - }, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), - decoration: standardInputDecoration( - "Search...", - searchFieldFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - prefixIcon: Padding( - padding: EdgeInsets.symmetric( - horizontal: isDesktop ? 12 : 10, - vertical: isDesktop ? 18 : 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: isDesktop ? 20 : 16, - height: isDesktop ? 20 : 16, - ), - ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], - ), - ), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + controller: _searchController, + focusNode: searchFieldFocusNode, + onChanged: (value) { + setState(() { + _searchString = value; + }); + }, + style: isDesktop + ? STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, ) - : null, + : STextStyles.field(context), + decoration: standardInputDecoration( + "Search...", + searchFieldFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + prefixIcon: Padding( + padding: EdgeInsets.symmetric( + horizontal: isDesktop ? 12 : 10, + vertical: isDesktop ? 18 : 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: isDesktop ? 20 : 16, + height: isDesktop ? 20 : 16, + ), + ), + suffixIcon: _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), + ), + ) + : null, + ), ), ), ), diff --git a/lib/pages_desktop_specific/home/settings_menu/advanced_settings/advanced_settings.dart b/lib/pages_desktop_specific/home/settings_menu/advanced_settings/advanced_settings.dart index 1632576fd..8e89e3f67 100644 --- a/lib/pages_desktop_specific/home/settings_menu/advanced_settings/advanced_settings.dart +++ b/lib/pages_desktop_specific/home/settings_menu/advanced_settings/advanced_settings.dart @@ -10,6 +10,8 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; +import 'debug_info_dialog.dart'; + class AdvancedSettings extends ConsumerStatefulWidget { const AdvancedSettings({Key? key}) : super(key: key); @@ -226,16 +228,16 @@ class ShowLogsButton extends ConsumerWidget { }) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { - // Future viewDebugLogs() async { - // await showDialog( - // context: context, - // useSafeArea: false, - // barrierDismissible: true, - // builder: (context) { - // return const DebugInfoDialog(); - // }, - // ); - // } + Future viewDebugLogs() async { + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return const DebugInfoDialog(); + }, + ); + } return SizedBox( width: 101, @@ -245,8 +247,7 @@ class ShowLogsButton extends ConsumerWidget { .extension()! .getPrimaryEnabledButtonColor(context), onPressed: () { - // - // viewDebugLogs(); + viewDebugLogs(); }, child: Text( "Show logs", diff --git a/lib/pages_desktop_specific/home/settings_menu/advanced_settings/debug_info_dialog.dart b/lib/pages_desktop_specific/home/settings_menu/advanced_settings/debug_info_dialog.dart index 342d9180a..0406a059f 100644 --- a/lib/pages_desktop_specific/home/settings_menu/advanced_settings/debug_info_dialog.dart +++ b/lib/pages_desktop_specific/home/settings_menu/advanced_settings/debug_info_dialog.dart @@ -1,29 +1,33 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/models/isar/models/log.dart'; +import 'package:stackwallet/providers/global/debug_service_provider.dart'; +import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/log_level_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; +import 'package:stackwallet/widgets/rounded_container.dart'; +import 'package:stackwallet/widgets/stack_text_field.dart'; +import 'package:stackwallet/widgets/textfield_icon_button.dart'; -// import '../../../utilities/assets.dart'; -// import '../../../utilities/util.dart'; -// import '../../../widgets/icon_widgets/x_icon.dart'; -// import '../../../widgets/stack_text_field.dart'; -// import '../../../widgets/textfield_icon_button.dart'; - -class DebugInfoDialog extends StatefulWidget { +class DebugInfoDialog extends ConsumerStatefulWidget { const DebugInfoDialog({Key? key}) : super(key: key); @override - State createState() => _DebugInfoDialog(); + ConsumerState createState() => _DebugInfoDialog(); } -class _DebugInfoDialog extends State { - final _searchController = TextEditingController(); - final _searchFocusNode = FocusNode(); +class _DebugInfoDialog extends ConsumerState { + late final TextEditingController searchDebugController; + late final FocusNode searchDebugFocusNode; final scrollController = ScrollController(); @@ -62,15 +66,19 @@ class _DebugInfoDialog extends State { @override void initState() { - // ref.read(debugServiceProvider).updateRecentLogs(); + searchDebugController = TextEditingController(); + searchDebugFocusNode = FocusNode(); + + ref.read(debugServiceProvider).updateRecentLogs(); super.initState(); } @override void dispose() { - _searchController.dispose(); + searchDebugFocusNode.dispose(); + searchDebugController.dispose(); + scrollController.dispose(); - _searchFocusNode.dispose(); super.dispose(); } @@ -78,7 +86,7 @@ class _DebugInfoDialog extends State { @override Widget build(BuildContext context) { return DesktopDialog( - maxHeight: 800, + maxHeight: 850, maxWidth: 600, child: Column( children: [ @@ -96,68 +104,216 @@ class _DebugInfoDialog extends State { const DesktopDialogCloseButton(), ], ), - Row( - children: [ - // ClipRRect( - // borderRadius: BorderRadius.circular( - // Constants.size.circularBorderRadius, - // ), - // child: TextField( - // key: const Key("desktopSettingDebugInfo"), - // autocorrect: Util.isDesktop ? false : true, - // enableSuggestions: Util.isDesktop ? false : true, - // controller: _searchController, - // focusNode: _searchFocusNode, - // // onChanged: (newString) { - // // setState(() => _searchTerm = newString); - // // }, - // style: STextStyles.field(context), - // decoration: standardInputDecoration( - // "Search", - // _searchFocusNode, - // context, - // ).copyWith( - // prefixIcon: Padding( - // padding: const EdgeInsets.symmetric( - // horizontal: 10, - // vertical: 16, - // ), - // child: SvgPicture.asset( - // Assets.svg.search, - // width: 16, - // height: 16, - // ), - // ), - // suffixIcon: _searchController.text.isNotEmpty - // ? Padding( - // padding: const EdgeInsets.only(right: 0), - // child: UnconstrainedBox( - // child: Row( - // children: [ - // TextFieldIconButton( - // child: const XIcon(), - // onTap: () async { - // setState(() { - // _searchController.text = ""; - // _searchTerm = ""; - // }); - // }, - // ), - // ], - // ), - // ), - // ) - // : null, - // ), - // ), - // ), - ], + Expanded( + flex: 24, + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: (context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context), + sliver: SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 16, horizontal: 32), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: searchDebugController, + focusNode: searchDebugFocusNode, + onChanged: (newString) { + setState(() => _searchTerm = newString); + }, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + searchDebugFocusNode, + context, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), + ), + suffixIcon: searchDebugController + .text.isNotEmpty + ? Padding( + padding: + const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + searchDebugController + .text = ""; + _searchTerm = ""; + }); + }, + ), + ], + ), + ), + ) + : null, + ), + ), + ), + ), + const SizedBox( + height: 12, + ), + ], + ), + ), + ), + ), + ]; + }, + body: Builder( + builder: (context) { + final logs = filtered( + ref.watch(debugServiceProvider + .select((value) => value.recentLogs)), + _searchTerm) + .reversed + .toList(growable: false); + return CustomScrollView( + reverse: true, + // shrinkWrap: true, + controller: scrollController, + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context, + ), + ), + SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + final log = logs[index]; + + return Container( + key: Key( + "log_${log.id}_${log.timestampInMillisUTC}"), + decoration: BoxDecoration( + color: Theme.of(context) + .extension()! + .popupBG, + borderRadius: _borderRadius(index, logs.length), + ), + child: Padding( + padding: const EdgeInsets.all(4), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 32), + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: Theme.of(context) + .extension()! + .popupBG, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + " [${log.logLevel.name}]", + style: STextStyles.baseXS(context) + .copyWith( + fontSize: 8, + color: (log.logLevel == + LogLevel.Info + ? Theme.of(context) + .extension< + StackColors>()! + .topNavIconGreen + : (log.logLevel == + LogLevel.Warning + ? Theme.of(context) + .extension< + StackColors>()! + .topNavIconYellow + : (log.logLevel == + LogLevel.Error + ? Colors.orange + : Theme.of(context) + .extension< + StackColors>()! + .topNavIconRed))), + ), + ), + Text( + "[${DateTime.fromMillisecondsSinceEpoch(log.timestampInMillisUTC, isUtc: true)}]: ", + style: STextStyles.baseXS(context) + .copyWith( + fontSize: 12, + color: Theme.of(context) + .extension()! + .textDark3, + ), + ), + ], + ), + Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const SizedBox( + width: 20, + ), + Flexible( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SelectableText( + log.message, + style: STextStyles.baseXS( + context) + .copyWith( + fontSize: 11.5), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + ); + }, + childCount: logs.length, + ), + ), + ], + ); + }, + ), + ), ), - // Column( - // children: [ - // - // ], - // ), const Spacer(), Padding( padding: const EdgeInsets.all(32), diff --git a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_dialog.dart b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_dialog.dart deleted file mode 100644 index bbe98c1af..000000000 --- a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_dialog.dart +++ /dev/null @@ -1,371 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:stackwallet/providers/global/base_currencies_provider.dart'; -import 'package:stackwallet/providers/global/prefs_provider.dart'; -import 'package:stackwallet/utilities/assets.dart'; -import 'package:stackwallet/utilities/constants.dart'; -import 'package:stackwallet/utilities/text_styles.dart'; -import 'package:stackwallet/utilities/theme/stack_colors.dart'; -import 'package:stackwallet/utilities/util.dart'; -import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; -import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; -import 'package:stackwallet/widgets/desktop/primary_button.dart'; -import 'package:stackwallet/widgets/desktop/secondary_button.dart'; -import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; -import 'package:stackwallet/widgets/rounded_container.dart'; -import 'package:stackwallet/widgets/stack_text_field.dart'; -import 'package:stackwallet/widgets/textfield_icon_button.dart'; - -class CurrencyDialog extends ConsumerStatefulWidget { - const CurrencyDialog({Key? key}) : super(key: key); - - @override - ConsumerState createState() => _CurrencyDialog(); -} - -class _CurrencyDialog extends ConsumerState { - late String current; - late List currenciesWithoutSelected; - - late final TextEditingController searchCurrencyController; - - late final FocusNode searchCurrencyFocusNode; - - void onTap(int index) { - if (currenciesWithoutSelected[index] == current || current.isEmpty) { - // ignore if already selected currency - return; - } - current = currenciesWithoutSelected[index]; - currenciesWithoutSelected.remove(current); - currenciesWithoutSelected.insert(0, current); - ref.read(prefsChangeNotifierProvider).currency = current; - } - - BorderRadius? _borderRadius(int index) { - if (index == 0 && currenciesWithoutSelected.length == 1) { - return BorderRadius.circular( - Constants.size.circularBorderRadius, - ); - } else if (index == 0) { - return BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, - ), - ); - } else if (index == currenciesWithoutSelected.length - 1) { - return BorderRadius.vertical( - bottom: Radius.circular( - Constants.size.circularBorderRadius, - ), - ); - } - return null; - } - - String filter = ""; - - List _filtered() { - final currencyMap = ref.read(baseCurrenciesProvider).map; - return currenciesWithoutSelected.where((element) { - return element.toLowerCase().contains(filter.toLowerCase()) || - (currencyMap[element]?.toLowerCase().contains(filter.toLowerCase()) ?? - false); - }).toList(); - } - - @override - void initState() { - searchCurrencyController = TextEditingController(); - - searchCurrencyFocusNode = FocusNode(); - - super.initState(); - } - - @override - void dispose() { - searchCurrencyController.dispose(); - - searchCurrencyFocusNode.dispose(); - - super.dispose(); - } - - @override - Widget build(BuildContext context) { - current = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); - - currenciesWithoutSelected = ref - .watch(baseCurrenciesProvider.select((value) => value.map)) - .keys - .toList(); - if (current.isNotEmpty) { - currenciesWithoutSelected.remove(current); - currenciesWithoutSelected.insert(0, current); - } - currenciesWithoutSelected = _filtered(); - - return DesktopDialog( - maxHeight: 800, - maxWidth: 600, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.all(32), - child: Text( - "Select currency", - style: STextStyles.desktopH3(context), - textAlign: TextAlign.center, - ), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - flex: 24, - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: (context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor( - context), - sliver: SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, horizontal: 32), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - controller: searchCurrencyController, - focusNode: searchCurrencyFocusNode, - onChanged: (newString) { - setState(() => filter = newString); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - searchCurrencyFocusNode, - context, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, - ), - ), - suffixIcon: searchCurrencyController - .text.isNotEmpty - ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - searchCurrencyController - .text = ""; - filter = ""; - }); - }, - ), - ], - ), - ), - ) - : null, - ), - ), - ), - ), - ], - ), - ), - ), - ), - ]; - }, - body: Builder( - builder: (context) { - return CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor( - context, - ), - ), - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - return Container( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, - borderRadius: _borderRadius(index), - ), - child: Padding( - padding: const EdgeInsets.all(4), - key: Key( - "desktopSettingsCurrencySelect_${currenciesWithoutSelected[index]}"), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32), - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: currenciesWithoutSelected[index] == - current - ? Theme.of(context) - .extension()! - .currencyListItemBG - : Theme.of(context) - .extension()! - .popupBG, - child: RawMaterialButton( - onPressed: () async { - onTap(index); - }, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - materialTapTargetSize: - MaterialTapTargetSize - .shrinkWrap, - value: true, - groupValue: - currenciesWithoutSelected[ - index] == - current, - onChanged: (_) { - onTap(index); - }, - ), - ), - const SizedBox( - width: 12, - ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - currenciesWithoutSelected[ - index], - key: (currenciesWithoutSelected[ - index] == - current) - ? const Key( - "desktopSettingsSelectedCurrencyText") - : null, - style: - STextStyles.largeMedium14( - context), - ), - const SizedBox( - height: 2, - ), - Text( - ref.watch(baseCurrenciesProvider - .select((value) => - value.map))[ - currenciesWithoutSelected[ - index]] ?? - "", - key: (currenciesWithoutSelected[ - index] == - current) - ? const Key( - "desktopSelectedCurrencyTextDescription") - : null, - style: - STextStyles.itemSubtitle( - context), - ), - ], - ), - ], - ), - ), - ), - ), - ), - ), - ); - }, - childCount: currenciesWithoutSelected.length, - ), - ), - ], - ); - }, - ), - ), - ), - const Spacer(), - Padding( - padding: const EdgeInsets.all(32), - child: Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Cancel", - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Save Changes", - onPressed: () {}, - ), - ) - ], - ), - ), - ], - ), - ); - } -} diff --git a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart index b8ce76d25..dab613f63 100644 --- a/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart +++ b/lib/pages_desktop_specific/home/settings_menu/currency_settings/currency_settings.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:flutter/src/widgets/framework.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/currency_view.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -import 'currency_dialog.dart'; - class CurrencySettings extends ConsumerStatefulWidget { const CurrencySettings({Key? key}) : super(key: key); @@ -84,19 +84,51 @@ class NewPasswordButton extends ConsumerWidget { const NewPasswordButton({ Key? key, }) : super(key: key); + Future chooseCurrency(BuildContext context) async { + // await showDialog( + // context: context, + // useSafeArea: false, + // barrierDismissible: true, + // builder: (context) { + // return CurrencyDialog(); + // }, + // ); + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxHeight: 800, + maxWidth: 600, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(32), + child: Text( + "Select currency", + style: STextStyles.desktopH3(context), + textAlign: TextAlign.center, + ), + ), + const DesktopDialogCloseButton(), + ], + ), + const Expanded( + child: BaseCurrencySettingsView(), + ), + ], + ), + ); + }, + ); + } + @override Widget build(BuildContext context, WidgetRef ref) { - Future chooseCurrency() async { - await showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return CurrencyDialog(); - }, - ); - } - return SizedBox( width: 200, height: 48, @@ -105,7 +137,7 @@ class NewPasswordButton extends ConsumerWidget { .extension()! .getPrimaryEnabledButtonColor(context), onPressed: () { - chooseCurrency(); + chooseCurrency(context); }, child: Text( "Change currency", diff --git a/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart b/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart index 97b807b3b..0f66d7dd5 100644 --- a/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart +++ b/lib/pages_desktop_specific/home/settings_menu/language_settings/language_settings.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/src/widgets/framework.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages_desktop_specific/home/settings_menu/language_settings/language_dialog.dart'; @@ -86,19 +85,20 @@ class ChangeLanguageButton extends ConsumerWidget { const ChangeLanguageButton({ Key? key, }) : super(key: key); + + Future chooseLanguage(BuildContext context) async { + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return const LanguageDialog(); + }, + ); + } + @override Widget build(BuildContext context, WidgetRef ref) { - Future chooseLanguage() async { - await showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return LanguageDialog(); - }, - ); - } - return SizedBox( width: 200, height: 48, @@ -107,7 +107,7 @@ class ChangeLanguageButton extends ConsumerWidget { .extension()! .getPrimaryEnabledButtonColor(context), onPressed: () { - chooseLanguage(); + chooseLanguage(context); }, child: Text( "Change language", diff --git a/lib/pages_desktop_specific/home/settings_menu/nodes_settings.dart b/lib/pages_desktop_specific/home/settings_menu/nodes_settings.dart index bb60061d8..1d0317037 100644 --- a/lib/pages_desktop_specific/home/settings_menu/nodes_settings.dart +++ b/lib/pages_desktop_specific/home/settings_menu/nodes_settings.dart @@ -1,15 +1,18 @@ import 'package:flutter/material.dart'; -import 'package:flutter/src/widgets/framework.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart'; import 'package:stackwallet/providers/global/node_service_provider.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; +import 'package:stackwallet/widgets/stack_text_field.dart'; class NodesSettings extends ConsumerStatefulWidget { const NodesSettings({Key? key}) : super(key: key); @@ -23,15 +26,27 @@ class NodesSettings extends ConsumerStatefulWidget { class _NodesSettings extends ConsumerState { List _coins = [...Coin.values]; + late final TextEditingController searchNodeController; + late final FocusNode searchNodeFocusNode; + + String filter = ""; + @override void initState() { _coins = _coins.toList(); _coins.remove(Coin.firoTestNet); + + searchNodeController = TextEditingController(); + searchNodeFocusNode = FocusNode(); + super.initState(); } @override void dispose() { + searchNodeController.dispose(); + searchNodeFocusNode.dispose(); + super.dispose(); } @@ -47,6 +62,7 @@ class _NodesSettings extends ConsumerState { debugPrint("BUILD: $runtimeType"); return Column( + mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.only( @@ -55,6 +71,7 @@ class _NodesSettings extends ConsumerState { child: RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ SvgPicture.asset( Assets.svg.circleNode, @@ -63,6 +80,7 @@ class _NodesSettings extends ConsumerState { ), Column( crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(10), @@ -85,88 +103,145 @@ class _NodesSettings extends ConsumerState { ), ], ), - //TODO: add search bar - SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ...coins.map( - (coin) { - final count = ref - .watch(nodeServiceChangeNotifierProvider - .select((value) => value.getNodesFor(coin))) - .length; + Padding( + padding: const EdgeInsets.all(10.0), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: searchNodeController, + focusNode: searchNodeFocusNode, + onChanged: (newString) { + setState(() => filter = newString); + }, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + searchNodeFocusNode, + context, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + borderColor: + Theme.of(context).extension()!.background, + child: ListView.separated( + primary: false, + shrinkWrap: true, + itemBuilder: (context, index) { + final coin = coins[index]; + final count = ref + .watch(nodeServiceChangeNotifierProvider + .select((value) => value.getNodesFor(coin))) + .length; - return Padding( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - // side: BorderSide( - // color: Theme.of(context) - // .extension()! - // .shadow), - ), - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pushNamed( - CoinNodesView.routeName, - arguments: coin, - ); - }, - child: Padding( - padding: const EdgeInsets.all( - 12.0, - ), - child: Row( - children: [ - Row( - children: [ - SvgPicture.asset( - Assets.svg.iconFor(coin: coin), - width: 24, - height: 24, - ), - const SizedBox( - width: 12, - ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "${coin.prettyName} nodes", - style: STextStyles.titleBold12( - context), - ), - Text( - count > 1 - ? "$count nodes" - : "Default", - style: STextStyles.label(context), - ), - ], - ), - ], - ), - Expanded( - child: SvgPicture.asset( - Assets.svg.chevronRight, - alignment: Alignment.centerRight, - ), - ), - ], - ), + return Padding( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), ), - ); - }, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + onPressed: () { + showDialog( + context: context, + builder: (context) => Navigator( + initialRoute: CoinNodesView.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + FadePageRoute( + CoinNodesView( + coin: coin, + rootNavigator: true, + ), + const RouteSettings( + name: CoinNodesView.routeName, + ), + ), + ]; + }, + ), + ); + }, + child: Padding( + padding: const EdgeInsets.all( + 12.0, + ), + child: Row( + children: [ + Row( + children: [ + SvgPicture.asset( + Assets.svg.iconFor(coin: coin), + width: 24, + height: 24, + ), + const SizedBox( + width: 12, + ), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "${coin.prettyName} nodes", + style: STextStyles.titleBold12( + context), + ), + Text( + count > 1 + ? "$count nodes" + : "Default", + style: STextStyles.label(context), + ), + ], + ), + ], + ), + Expanded( + child: SvgPicture.asset( + Assets.svg.chevronRight, + alignment: Alignment.centerRight, + ), + ), + ], + ), + ), + ), + ); + }, + separatorBuilder: (context, index) => Container( + height: 1, + color: Theme.of(context) + .extension()! + .background, ), - ], + itemCount: coins.length, + ), ), ), ], diff --git a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart index 9b6c6c85c..7f6aac260 100644 --- a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart +++ b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart @@ -7,6 +7,8 @@ import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; +import '../../../pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart'; + class SyncingPreferencesSettings extends ConsumerStatefulWidget { const SyncingPreferencesSettings({Key? key}) : super(key: key); @@ -62,6 +64,13 @@ class _SyncingPreferencesSettings ), ], ), + + ///TODO: ONLY SHOW SYNC OPTIONS ON BUTTON PRESS + Column( + children: [ + SyncingOptionsView(), + ], + ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: const [ diff --git a/lib/utilities/theme/stack_colors.dart b/lib/utilities/theme/stack_colors.dart index 8a241db06..8249dccf4 100644 --- a/lib/utilities/theme/stack_colors.dart +++ b/lib/utilities/theme/stack_colors.dart @@ -1468,6 +1468,20 @@ class StackColors extends ThemeExtension { } } + ButtonStyle? getDeleteEnabledButtonColor(BuildContext context) => + Theme.of(context).textButtonTheme.style?.copyWith( + backgroundColor: MaterialStateProperty.all( + textFieldErrorBG, + ), + ); + + ButtonStyle? getDeleteDisabledButtonColor(BuildContext context) => + Theme.of(context).textButtonTheme.style?.copyWith( + backgroundColor: MaterialStateProperty.all( + buttonBackSecondaryDisabled, + ), + ); + ButtonStyle? getPrimaryEnabledButtonColor(BuildContext context) => Theme.of(context).textButtonTheme.style?.copyWith( backgroundColor: MaterialStateProperty.all( diff --git a/lib/widgets/desktop/delete_button.dart b/lib/widgets/desktop/delete_button.dart new file mode 100644 index 000000000..e64c85f34 --- /dev/null +++ b/lib/widgets/desktop/delete_button.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/desktop/custom_text_button.dart'; + +class DeleteButton extends StatelessWidget { + const DeleteButton({ + Key? key, + this.width, + this.height, + this.label, + this.onPressed, + this.enabled = true, + this.desktopMed = false, + }) : super(key: key); + + final double? width; + final double? height; + final String? label; + final VoidCallback? onPressed; + final bool enabled; + final bool desktopMed; + + TextStyle getStyle(bool isDesktop, BuildContext context) { + if (isDesktop) { + if (desktopMed) { + return STextStyles.desktopTextExtraSmall(context).copyWith( + color: enabled + ? Theme.of(context).extension()!.accentColorRed + : Theme.of(context) + .extension()! + .buttonTextSecondaryDisabled, + ); + } else { + return enabled + ? STextStyles.desktopButtonSecondaryEnabled(context).copyWith( + color: + Theme.of(context).extension()!.accentColorRed) + : STextStyles.desktopButtonSecondaryDisabled(context); + } + } else { + return STextStyles.button(context).copyWith( + color: enabled + ? Theme.of(context).extension()!.accentColorRed + : Theme.of(context) + .extension()! + .buttonTextSecondaryDisabled, + ); + } + } + + @override + Widget build(BuildContext context) { + final isDesktop = Util.isDesktop; + + return CustomTextButtonBase( + height: desktopMed ? 56 : height, + width: width, + textButton: TextButton( + onPressed: enabled ? onPressed : null, + style: enabled + ? Theme.of(context) + .extension()! + .getDeleteEnabledButtonColor(context) + : Theme.of(context) + .extension()! + .getDeleteDisabledButtonColor(context), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + Assets.svg.trash, + width: 20, + height: 20, + color: enabled + ? Theme.of(context).extension()!.accentColorRed + : Theme.of(context) + .extension()! + .buttonTextSecondaryDisabled, + ), + if (label != null) + const SizedBox( + width: 10, + ), + if (label != null) + Text( + label!, + style: getStyle(isDesktop, context), + ), + ], + ), + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 64c678637..9ba6d4eb9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: Stack Wallet # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.5.13+85 +version: 1.5.14+86 environment: sdk: ">=2.17.0 <3.0.0"