diff --git a/assets/default_themes/dark.zip b/assets/default_themes/dark.zip index ba8404f9c..1d8899567 100644 Binary files a/assets/default_themes/dark.zip and b/assets/default_themes/dark.zip differ diff --git a/assets/default_themes/light.zip b/assets/default_themes/light.zip index 8cfefa953..093a1b2eb 100644 Binary files a/assets/default_themes/light.zip and b/assets/default_themes/light.zip differ diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart index b32ee3595..845c29411 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart @@ -35,6 +35,12 @@ class _ManageExplorerViewState extends ConsumerState { .replaceAll("%5BTXID%5D", "[TXID]")); } + @override + void dispose() { + textEditingController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Background( @@ -93,13 +99,19 @@ class _ManageExplorerViewState extends ConsumerState { style: Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context), - onPressed: () { + onPressed: () async { textEditingController.text = textEditingController.text.trim(); - setBlockExplorerForCoin( - coin: widget.coin, - url: Uri.parse(textEditingController.text)) - .then((value) => Navigator.of(context).pop()); + await setBlockExplorerForCoin( + coin: widget.coin, + url: Uri.parse( + textEditingController.text, + ), + ); + + if (mounted) { + Navigator.of(context).pop(); + } }, child: Text( "Save", diff --git a/lib/pages/token_view/sub_widgets/token_summary.dart b/lib/pages/token_view/sub_widgets/token_summary.dart index 11156020c..51679c4d6 100644 --- a/lib/pages/token_view/sub_widgets/token_summary.dart +++ b/lib/pages/token_view/sub_widgets/token_summary.dart @@ -308,14 +308,23 @@ class TokenOptionsButton extends StatelessWidget { child: child, ), ), - child: SvgPicture.file( - File(iconAssetPathSVG), - color: Theme.of(context) - .extension()! - .tokenSummaryIcon, - width: iconSize, - height: iconSize, - ), + child: iconAssetPathSVG.startsWith("assets/") + ? SvgPicture.asset( + iconAssetPathSVG, + color: Theme.of(context) + .extension()! + .tokenSummaryIcon, + width: iconSize, + height: iconSize, + ) + : SvgPicture.file( + File(iconAssetPathSVG), + color: Theme.of(context) + .extension()! + .tokenSummaryIcon, + width: iconSize, + height: iconSize, + ), ), ), ), diff --git a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart index cb4c7a557..08eba6c0f 100644 --- a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart +++ b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/advanced_settings.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/debug_info_dialog.dart'; +import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_manage_block_explorers_dialog.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; @@ -58,7 +59,7 @@ class _AdvancedSettings extends ConsumerState { ), TextSpan( text: - "\n\nConfigurate these settings only if you know what you are doing!", + "\n\nConfigure these settings only if you know what you are doing!", style: STextStyles.desktopTextExtraExtraSmall( context), ), @@ -183,7 +184,7 @@ class _AdvancedSettings extends ConsumerState { PrimaryButton( label: "Change", buttonHeight: ButtonHeight.xs, - width: 86, + width: 101, onPressed: () async { await showDialog( context: context, @@ -207,8 +208,6 @@ class _AdvancedSettings extends ConsumerState { thickness: 0.5, ), ), - - /// TODO: Make a dialog popup Padding( padding: const EdgeInsets.all(10), child: Row( @@ -241,6 +240,44 @@ class _AdvancedSettings extends ConsumerState { ], ), ), + const Padding( + padding: EdgeInsets.all(10.0), + child: Divider( + thickness: 0.5, + ), + ), + Padding( + padding: const EdgeInsets.all(10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Block explorers", + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark), + textAlign: TextAlign.left, + ), + PrimaryButton( + buttonHeight: ButtonHeight.xs, + label: "Edit", + width: 101, + onPressed: () async { + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return const DesktopManageBlockExplorersDialog(); + }, + ); + }, + ), + ], + ), + ), ], ), ), diff --git a/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_manage_block_explorers_dialog.dart b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_manage_block_explorers_dialog.dart new file mode 100644 index 000000000..9042f41d4 --- /dev/null +++ b/lib/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_manage_block_explorers_dialog.dart @@ -0,0 +1,266 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/themes/coin_icon_provider.dart'; +import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/block_explorers.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/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/rounded_white_container.dart'; + +class DesktopManageBlockExplorersDialog extends ConsumerWidget { + const DesktopManageBlockExplorersDialog({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context, WidgetRef ref) { + bool showTestNet = ref.watch( + prefsChangeNotifierProvider.select((value) => value.showTestNetCoins), + ); + + final List coins = showTestNet + ? Coin.values + : Coin.values.sublist(0, Coin.values.length - kTestNetCoinCount); + + return DesktopDialog( + maxHeight: 850, + maxWidth: 600, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(32), + child: Text( + "Manage block explorers", + style: STextStyles.desktopH3(context), + textAlign: TextAlign.center, + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: ListView.separated( + itemCount: coins.length, + separatorBuilder: (_, __) => const SizedBox( + height: 12, + ), + itemBuilder: (_, index) { + final coin = coins[index]; + + return RoundedWhiteContainer( + padding: const EdgeInsets.symmetric( + vertical: 16, + horizontal: 14, + ), + borderColor: Theme.of(context) + .extension()! + .textSubtitle6, + child: Row( + children: [ + SvgPicture.file( + File( + ref.watch(coinIconProvider(coin)), + ), + width: 24, + height: 24, + ), + const SizedBox( + width: 12, + ), + Expanded( + child: Text( + "${coin.prettyName} block explorer", + style: STextStyles.desktopTextSmall(context), + ), + ), + const SizedBox( + width: 12, + ), + SvgPicture.asset( + Assets.svg.chevronRight, + width: 20, + height: 20, + ), + ], + ), + onPressed: () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return _DesktopEditBlockExplorerDialog( + coin: coin, + ); + }, + ); + }, + ); + }, + ), + ), + ), + ], + ), + ); + } +} + +class _DesktopEditBlockExplorerDialog extends ConsumerStatefulWidget { + const _DesktopEditBlockExplorerDialog({Key? key, required this.coin}) + : super(key: key); + + final Coin coin; + + @override + ConsumerState<_DesktopEditBlockExplorerDialog> createState() => + _DesktopEditBlockExplorerDialogState(); +} + +class _DesktopEditBlockExplorerDialogState + extends ConsumerState<_DesktopEditBlockExplorerDialog> { + late final TextEditingController _textEditingController; + late final FocusNode _focusNode; + + @override + void initState() { + _textEditingController = TextEditingController( + text: + getBlockExplorerTransactionUrlFor(coin: widget.coin, txid: "[TXID]") + .toString() + .replaceAll("%5BTXID%5D", "[TXID]")); + _focusNode = FocusNode(); + super.initState(); + } + + @override + void dispose() { + _textEditingController.dispose(); + _focusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return DesktopDialog( + maxHeight: double.infinity, + maxWidth: 600, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(32), + child: Text( + "${widget.coin.prettyName} block explorer", + style: STextStyles.desktopH3(context), + textAlign: TextAlign.center, + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: false, + enableSuggestions: false, + key: const Key("addCustomNodeNodeAddressFieldKey"), + controller: _textEditingController, + focusNode: _focusNode, + style: STextStyles.field(context), + ), + ), + const SizedBox( + height: 16, + ), + RoundedWhiteContainer( + borderColor: + Theme.of(context).extension()!.textSubtitle6, + child: Text( + "Edit your block explorer above. Keep in mind that" + " every block explorer has a slightly different URL scheme." + "\n\n" + "Paste in your block explorer of choice, then edit in" + " [TXID] where the transaction ID should go, and Stack" + " Wallet will auto fill the transaction ID in that place" + " of the URL.", + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ), + const SizedBox( + height: 16, + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + buttonHeight: ButtonHeight.l, + onPressed: Navigator.of(context).pop, + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + label: "Save", + buttonHeight: ButtonHeight.l, + onPressed: () async { + _textEditingController.text = + _textEditingController.text.trim(); + await setBlockExplorerForCoin( + coin: widget.coin, + url: Uri.parse( + _textEditingController.text, + ), + ); + + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + ), + ], + ) + ], + ), + ) + ], + ), + ); + } +} diff --git a/lib/widgets/rounded_container.dart b/lib/widgets/rounded_container.dart index c30f7a186..ef679472b 100644 --- a/lib/widgets/rounded_container.dart +++ b/lib/widgets/rounded_container.dart @@ -46,6 +46,12 @@ class RoundedContainer extends StatelessWidget { borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius * radiusMultiplier, ), + side: borderColor == null + ? BorderSide.none + : BorderSide( + color: borderColor!, + width: 1.2, + ), ), onPressed: onPressed, child: child,