diff --git a/.gitignore b/.gitignore index e58a9412f..b7924307d 100644 --- a/.gitignore +++ b/.gitignore @@ -57,8 +57,3 @@ libepic_cash_wallet.dll libmobileliblelantus.dll libtor_ffi.dll /libisar.so -libtor_ffi.so - -tor_logs.txt - -torrc diff --git a/assets/gif/stacy_onion.gif b/assets/gif/stacy_onion.gif new file mode 100644 index 000000000..3486058e5 Binary files /dev/null and b/assets/gif/stacy_onion.gif differ diff --git a/lib/db/hive/db.dart b/lib/db/hive/db.dart index f2f5bc630..00fdc13f7 100644 --- a/lib/db/hive/db.dart +++ b/lib/db/hive/db.dart @@ -46,6 +46,7 @@ class DB { // in use (keep for now) static const String boxNameDBInfo = "dbInfo"; static const String boxNamePrefs = "prefs"; + static const String boxNameOneTimeDialogsShown = "oneTimeDialogsShown"; String _boxNameTxCache({required Coin coin}) => "${coin.name}_txCache"; diff --git a/lib/electrumx_rpc/rpc.dart b/lib/electrumx_rpc/rpc.dart index 3d2d499a6..a4185e104 100644 --- a/lib/electrumx_rpc/rpc.dart +++ b/lib/electrumx_rpc/rpc.dart @@ -15,9 +15,9 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:mutex/mutex.dart'; import 'package:stackwallet/exceptions/json_rpc/json_rpc_exception.dart'; -import 'package:stackwallet/networking/socks_socket.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; +import 'package:tor_ffi_plugin/socks_socket.dart'; // Json RPC class to handle connecting to electrumx servers class JsonRPC { @@ -247,6 +247,8 @@ class JsonRPC { cancelOnError: true, ); } + + return; } } diff --git a/lib/networking/socks_socket.dart b/lib/networking/socks_socket.dart deleted file mode 100644 index 03dc60945..000000000 --- a/lib/networking/socks_socket.dart +++ /dev/null @@ -1,343 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -/// A SOCKS5 socket. -/// -/// This class is a wrapper around a Socket that connects to a SOCKS5 proxy -/// server and sends all data through the proxy. -/// -/// This class is used to connect to the Tor proxy server. -/// -/// Attributes: -/// - [proxyHost]: The host of the SOCKS5 proxy server. -/// - [proxyPort]: The port of the SOCKS5 proxy server. -/// - [_socksSocket]: The underlying [Socket] that connects to the SOCKS5 proxy -/// server. -/// - [_responseController]: A [StreamController] that listens to the -/// [_socksSocket] and broadcasts the response. -/// -/// Methods: -/// - connect: Connects to the SOCKS5 proxy server. -/// - connectTo: Connects to the specified [domain] and [port] through the -/// SOCKS5 proxy server. -/// - write: Converts [object] to a String by invoking [Object.toString] and -/// sends the encoding of the result to the socket. -/// - sendServerFeaturesCommand: Sends the server.features command to the -/// proxy server. -/// - close: Closes the connection to the Tor proxy. -/// -/// Usage: -/// ```dart -/// // Instantiate a socks socket at localhost and on the port selected by the -/// // tor service. -/// var socksSocket = await SOCKSSocket.create( -/// proxyHost: InternetAddress.loopbackIPv4.address, -/// proxyPort: tor.port, -/// // sslEnabled: true, // For SSL connections. -/// ); -/// -/// // Connect to the socks instantiated above. -/// await socksSocket.connect(); -/// -/// // Connect to bitcoincash.stackwallet.com on port 50001 via socks socket. -/// await socksSocket.connectTo( -/// 'bitcoincash.stackwallet.com', 50001); -/// -/// // Send a server features command to the connected socket, see method for -/// // more specific usage example.. -/// await socksSocket.sendServerFeaturesCommand(); -/// await socksSocket.close(); -/// ``` -/// -/// See also: -/// - SOCKS5 protocol(https://www.ietf.org/rfc/rfc1928.txt) -class SOCKSSocket { - /// The host of the SOCKS5 proxy server. - final String proxyHost; - - /// The port of the SOCKS5 proxy server. - final int proxyPort; - - /// The underlying Socket that connects to the SOCKS5 proxy server. - late final Socket _socksSocket; - - /// Getter for the underlying Socket that connects to the SOCKS5 proxy server. - Socket get socket => sslEnabled ? _secureSocksSocket : _socksSocket; - - /// A wrapper around the _socksSocket that enables SSL connections. - late final Socket _secureSocksSocket; - - /// A StreamController that listens to the _socksSocket and broadcasts. - final StreamController<List<int>> _responseController = - StreamController.broadcast(); - - /// A StreamController that listens to the _secureSocksSocket and broadcasts. - final StreamController<List<int>> _secureResponseController = - StreamController.broadcast(); - - /// Getter for the StreamController that listens to the _socksSocket and - /// broadcasts, or the _secureSocksSocket and broadcasts if SSL is enabled. - StreamController<List<int>> get responseController => - sslEnabled ? _secureResponseController : _responseController; - - /// A StreamSubscription that listens to the _socksSocket or the - /// _secureSocksSocket if SSL is enabled. - StreamSubscription<List<int>>? _subscription; - - /// Getter for the StreamSubscription that listens to the _socksSocket or the - /// _secureSocksSocket if SSL is enabled. - StreamSubscription<List<int>>? get subscription => _subscription; - - /// Is SSL enabled? - final bool sslEnabled; - - /// Private constructor. - SOCKSSocket._(this.proxyHost, this.proxyPort, this.sslEnabled); - - /// Creates a SOCKS5 socket to the specified [proxyHost] and [proxyPort]. - /// - /// This method is a factory constructor that returns a Future that resolves - /// to a SOCKSSocket instance. - /// - /// Parameters: - /// - [proxyHost]: The host of the SOCKS5 proxy server. - /// - [proxyPort]: The port of the SOCKS5 proxy server. - /// - /// Returns: - /// A Future that resolves to a SOCKSSocket instance. - static Future<SOCKSSocket> create( - {required String proxyHost, - required int proxyPort, - bool sslEnabled = false}) async { - // Create a SOCKS socket instance. - var instance = SOCKSSocket._(proxyHost, proxyPort, sslEnabled); - - // Initialize the SOCKS socket. - await instance._init(); - - // Return the SOCKS socket instance. - return instance; - } - - /// Constructor. - SOCKSSocket( - {required this.proxyHost, - required this.proxyPort, - required this.sslEnabled}) { - _init(); - } - - /// Initializes the SOCKS socket. - /// - /// This method is a private method that is called by the constructor. - /// - /// Returns: - /// A Future that resolves to void. - Future<void> _init() async { - // Connect to the SOCKS proxy server. - _socksSocket = await Socket.connect( - proxyHost, - proxyPort, - ); - - // Listen to the socket. - _subscription = _socksSocket.listen( - (data) { - // Add the data to the response controller. - _responseController.add(data); - }, - onError: (e) { - // Handle errors. - if (e is Object) { - _responseController.addError(e); - } - - // If the error is not an object, send the error as a string. - _responseController.addError("$e"); - // TODO make sure sending error as string is acceptable. - }, - onDone: () { - // Close the response controller when the socket is closed. - _responseController.close(); - }, - ); - } - - /// Connects to the SOCKS socket. - /// - /// Returns: - /// A Future that resolves to void. - Future<void> connect() async { - // Greeting and method selection. - _socksSocket.add([0x05, 0x01, 0x00]); - - // Wait for server response. - var response = await _responseController.stream.first; - - // Check if the connection was successful. - if (response[1] != 0x00) { - throw Exception( - 'socks_socket.connect(): Failed to connect to SOCKS5 proxy.'); - } - } - - /// Connects to the specified [domain] and [port] through the SOCKS socket. - /// - /// Parameters: - /// - [domain]: The domain to connect to. - /// - [port]: The port to connect to. - /// - /// Returns: - /// A Future that resolves to void. - Future<void> connectTo(String domain, int port) async { - // Connect command. - var request = [ - 0x05, // SOCKS version. - 0x01, // Connect command. - 0x00, // Reserved. - 0x03, // Domain name. - domain.length, - ...domain.codeUnits, - (port >> 8) & 0xFF, - port & 0xFF - ]; - - // Send the connect command to the SOCKS proxy server. - _socksSocket.add(request); - - // Wait for server response. - var response = await _responseController.stream.first; - - // Check if the connection was successful. - if (response[1] != 0x00) { - throw Exception( - 'socks_socket.connectTo(): Failed to connect to target through SOCKS5 proxy.'); - } - - // Upgrade to SSL if needed - if (sslEnabled) { - // Upgrade to SSL. - _secureSocksSocket = await SecureSocket.secure( - _socksSocket, - host: domain, - // onBadCertificate: (_) => true, // Uncomment this to bypass certificate validation (NOT recommended for production). - ); - - // Listen to the secure socket. - _subscription = _secureSocksSocket.listen( - (data) { - // Add the data to the response controller. - _secureResponseController.add(data); - }, - onError: (e) { - // Handle errors. - if (e is Object) { - _secureResponseController.addError(e); - } - - // If the error is not an object, send the error as a string. - _secureResponseController.addError("$e"); - // TODO make sure sending error as string is acceptable. - }, - onDone: () { - // Close the response controller when the socket is closed. - _secureResponseController.close(); - }, - ); - } - - return; - } - - /// Converts [object] to a String by invoking [Object.toString] and - /// sends the encoding of the result to the socket. - /// - /// Parameters: - /// - [object]: The object to write to the socket. - /// - /// Returns: - /// A Future that resolves to void. - void write(Object? object) { - // Don't write null. - if (object == null) return; - - // Write the data to the socket. - List<int> data = utf8.encode(object.toString()); - if (sslEnabled) { - _secureSocksSocket.add(data); - } else { - _socksSocket.add(data); - } - } - - /// Sends the server.features command to the proxy server. - /// - /// This method is used to send the server.features command to the proxy - /// server. This command is used to request the features of the proxy server. - /// It serves as a demonstration of how to send commands to the proxy server. - /// - /// Returns: - /// A Future that resolves to void. - Future<void> sendServerFeaturesCommand() async { - // The server.features command. - const String command = - '{"jsonrpc":"2.0","id":"0","method":"server.features","params":[]}'; - - if (!sslEnabled) { - // Send the command to the proxy server. - _socksSocket.writeln(command); - - // Wait for the response from the proxy server. - var responseData = await _responseController.stream.first; - print("responseData: ${utf8.decode(responseData)}"); - } else { - // Send the command to the proxy server. - _secureSocksSocket.writeln(command); - - // Wait for the response from the proxy server. - var responseData = await _secureResponseController.stream.first; - print("secure responseData: ${utf8.decode(responseData)}"); - } - - return; - } - - /// Closes the connection to the Tor proxy. - /// - /// Returns: - /// A Future that resolves to void. - Future<void> close() async { - // Ensure all data is sent before closing. - // - // TODO test this. - if (sslEnabled) { - await _socksSocket.flush(); - await _secureResponseController.close(); - } - await _socksSocket.flush(); - await _responseController.close(); - return await _socksSocket.close(); - } - - StreamSubscription<List<int>> listen( - void Function(List<int> data)? onData, { - Function? onError, - void Function()? onDone, - bool? cancelOnError, - }) { - return sslEnabled - ? _secureResponseController.stream.listen( - onData, - onError: onError, - onDone: onDone, - cancelOnError: cancelOnError, - ) - : _responseController.stream.listen( - onData, - onError: onError, - onDone: onDone, - cancelOnError: cancelOnError, - ); - } -} diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index ada195455..78afc54c0 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -18,6 +18,7 @@ import 'package:stackwallet/models/isar/exchange_cache/currency.dart'; import 'package:stackwallet/models/isar/exchange_cache/pair.dart'; import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; +import 'package:stackwallet/services/exchange/exchange.dart'; import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart'; import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart'; import 'package:stackwallet/themes/stack_colors.dart'; @@ -40,8 +41,6 @@ import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; -import '../../../services/exchange/exchange.dart'; - class ExchangeCurrencySelectionView extends StatefulWidget { const ExchangeCurrencySelectionView({ Key? key, diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index a81f758a6..a233a35c7 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -36,14 +36,12 @@ import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart import 'package:stackwallet/services/exchange/exchange_response.dart'; import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart'; import 'package:stackwallet/services/exchange/trocador/trocador_exchange.dart'; -import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/amount/amount_unit.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/enums/exchange_rate_type_enum.dart'; -import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; @@ -80,11 +78,17 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> { late final Coin? coin; late final bool walletInitiated; - var exchanges = [ - MajesticBankExchange.instance, - ChangeNowExchange.instance, - TrocadorExchange.instance, - ]; + List<Exchange> get usableExchanges { + if (ref.read(prefsChangeNotifierProvider).useTor) { + return Exchange.exchangesWithTorSupport; + } else { + return [ + MajesticBankExchange.instance, + ChangeNowExchange.instance, + TrocadorExchange.instance, + ]; + } + } late final TextEditingController _sendController; late final TextEditingController _receiveController; @@ -623,7 +627,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> { final uuid = const Uuid().v1(); _latestUuid = uuid; _addUpdate(uuid); - for (final exchange in exchanges) { + for (final exchange in usableExchanges) { ref.read(efEstimatesListProvider(exchange.name).notifier).state = null; } @@ -644,7 +648,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> { final Map<String, Tuple2<ExchangeResponse<List<Estimate>>, Range?>> results = {}; - for (final exchange in exchanges) { + for (final exchange in usableExchanges) { final sendCurrency = pair.send?.forExchange(exchange.name); final receiveCurrency = pair.receive?.forExchange(exchange.name); @@ -674,7 +678,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> { } } - for (final exchange in exchanges) { + for (final exchange in usableExchanges) { if (uuid == _latestUuid) { ref.read(efEstimatesListProvider(exchange.name).notifier).state = results[exchange.name]; @@ -775,14 +779,6 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> { }); } - // Instantiate the Tor service. - torService = TorService.sharedInstance; - - // Filter exchanges based on Tor support. - if (Prefs.instance.useTor) { - exchanges = Exchange.exchangesWithTorSupport; - } - super.initState(); } @@ -1017,7 +1013,4 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> { ], ); } - - // TorService instance. - late TorService torService; } diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index 2303333e1..b99d8cd1c 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -33,6 +33,7 @@ import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/onetime_popups/tor_has_been_add_dialog.dart'; import 'package:stackwallet/widgets/small_tor_icon.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; @@ -129,19 +130,9 @@ class _HomeViewState extends ConsumerState<HomeView> { ref.read(notificationsProvider).startCheckingWatchedNotifications(); - /// todo change to watch tor network - // if (ref.read(managerProvider).isRefreshing) { - // _currentSyncStatus = WalletSyncStatus.syncing; - // _currentNodeStatus = NodeConnectionStatus.connected; - // } else { - // _currentSyncStatus = WalletSyncStatus.synced; - // if (ref.read(managerProvider).isConnected) { - // _currentNodeStatus = NodeConnectionStatus.connected; - // } else { - // _currentNodeStatus = NodeConnectionStatus.disconnected; - // _currentSyncStatus = WalletSyncStatus.unableToSync; - // } - // } + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + showOneTimeTorHasBeenAddedDialogIfRequired(context); + }); super.initState(); } diff --git a/lib/pages/ordinals/ordinal_details_view.dart b/lib/pages/ordinals/ordinal_details_view.dart index b0e478535..4154618c9 100644 --- a/lib/pages/ordinals/ordinal_details_view.dart +++ b/lib/pages/ordinals/ordinal_details_view.dart @@ -242,7 +242,8 @@ class _OrdinalImageGroup extends ConsumerWidget { ); if (response.code != 200) { - throw Exception("statusCode=${response.code} body=${response.bodyBytes}"); + throw Exception( + "OrdinalDetailsView _savePngToFile statusCode=${response.code} body=${response.bodyBytes}"); } final bytes = response.bodyBytes; diff --git a/lib/pages/settings_views/global_settings_view/hidden_settings.dart b/lib/pages/settings_views/global_settings_view/hidden_settings.dart index 52a523f22..924524de7 100644 --- a/lib/pages/settings_views/global_settings_view/hidden_settings.dart +++ b/lib/pages/settings_views/global_settings_view/hidden_settings.dart @@ -12,13 +12,20 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/providers/global/debug_service_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/themes/stack_colors.dart'; +import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/onetime_popups/tor_has_been_add_dialog.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; class HiddenSettings extends StatelessWidget { @@ -32,9 +39,29 @@ class HiddenSettings extends StatelessWidget { child: Scaffold( backgroundColor: Theme.of(context).extension<StackColors>()!.background, appBar: AppBar( - leading: Container(), + leading: Util.isDesktop + ? Padding( + padding: const EdgeInsets.all(8.0), + child: AppBarIconButton( + size: 32, + color: Theme.of(context) + .extension<StackColors>()! + .textFieldDefaultBG, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: Theme.of(context) + .extension<StackColors>()! + .topNavIconPrimary, + ), + onPressed: Navigator.of(context).pop, + ), + ) + : Container(), title: Text( - "Not so secret anymore", + "Dev options", style: STextStyles.navBarTitle(context), ), ), @@ -146,6 +173,48 @@ class HiddenSettings extends StatelessWidget { ), ); }), + const SizedBox( + height: 12, + ), + Consumer(builder: (_, ref, __) { + return GestureDetector( + onTap: () async { + await showOneTimeTorHasBeenAddedDialogIfRequired( + context, + ); + }, + child: RoundedWhiteContainer( + child: Text( + "Test tor stacy popup", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension<StackColors>()! + .accentColorDark), + ), + ), + ); + }), + const SizedBox( + height: 12, + ), + Consumer(builder: (_, ref, __) { + return GestureDetector( + onTap: () async { + final box = await Hive.openBox<bool>( + DB.boxNameOneTimeDialogsShown); + await box.clear(); + }, + child: RoundedWhiteContainer( + child: Text( + "Reset tor stacy popup", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension<StackColors>()! + .accentColorDark), + ), + ), + ); + }), // const SizedBox( // height: 12, // ), diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index a395d3897..f0a944cb5 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -225,11 +225,11 @@ class _TorAnimatedButtonState extends ConsumerState<TorAnimatedButton> // Connect or disconnect when the user taps the status. switch (_status) { case TorConnectionStatus.disconnected: - await _connectTor(ref, context); + await connectTor(ref, context); break; case TorConnectionStatus.connected: - await _disconnectTor(ref, context); + await disconnectTor(ref, context); break; @@ -435,11 +435,11 @@ class _TorButtonState extends ConsumerState<TorButton> { // Connect or disconnect when the user taps the status. switch (_status) { case TorConnectionStatus.disconnected: - await _connectTor(ref, context); + await connectTor(ref, context); break; case TorConnectionStatus.connected: - await _disconnectTor(ref, context); + await disconnectTor(ref, context); break; @@ -583,7 +583,7 @@ class _UpperCaseTorTextState extends ConsumerState<UpperCaseTorText> { /// Throws an exception if the Tor service fails to start. /// /// Returns a Future that completes when the Tor service has started. -Future<void> _connectTor(WidgetRef ref, BuildContext context) async { +Future<void> connectTor(WidgetRef ref, BuildContext context) async { try { // Init the Tor service if it hasn't already been. final torDir = await StackFileSystem.applicationTorDirectory(); @@ -600,8 +600,6 @@ Future<void> _connectTor(WidgetRef ref, BuildContext context) async { ); // TODO: show dialog with error message } - - return; } /// Disconnect from the Tor network. @@ -611,7 +609,7 @@ Future<void> _connectTor(WidgetRef ref, BuildContext context) async { /// Throws an exception if the Tor service fails to stop. /// /// Returns a Future that completes when the Tor service has stopped. -Future<void> _disconnectTor(WidgetRef ref, BuildContext context) async { +Future<void> disconnectTor(WidgetRef ref, BuildContext context) async { // Stop the Tor service. try { await ref.read(pTorService).disable(); diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index ad91b3b07..8ae18a581 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -16,6 +16,7 @@ import 'package:flutter/material.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/add_edit_node_view.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart'; import 'package:stackwallet/pages/settings_views/sub_widgets/nodes_list.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/confirm_full_rescan.dart'; import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/rescanning_dialog.dart'; @@ -35,8 +36,6 @@ import 'package:stackwallet/themes/stack_colors.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/logger.dart'; -import 'package:stackwallet/utilities/stack_file_system.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/animated_text.dart'; @@ -100,6 +99,26 @@ class _WalletNetworkSettingsViewState /// The current status of the Tor connection. late TorConnectionStatus _torConnectionStatus; + bool _buttonLockTor = false; + Future<void> onTorTapped() async { + if (_buttonLockTor) { + return; + } + _buttonLockTor = true; + try { + if (ref.read(prefsChangeNotifierProvider).useTor) { + await disconnectTor(ref, context); + } else { + await connectTor(ref, context); + } + } catch (_) { + // Nothing. Just using finally to ensure button lock is reset in case + // some unexpected error happens + } finally { + _buttonLockTor = false; + } + } + Future<void> _attemptRescan() async { if (!Platform.isLinux) await Wakelock.enable(); @@ -477,17 +496,14 @@ class _WalletNetworkSettingsViewState ? STextStyles.desktopTextExtraExtraSmall(context) : STextStyles.smallMed12(context), ), - GestureDetector( + CustomTextButton( + text: "Resync", onTap: () { ref .read(walletsChangeNotifierProvider) .getManager(widget.walletId) .refresh(); }, - child: Text( - "Resync", - style: STextStyles.link2(context), - ), ), ], ), @@ -769,55 +785,13 @@ class _WalletNetworkSettingsViewState ? STextStyles.desktopTextExtraExtraSmall(context) : STextStyles.smallMed12(context), ), - if (ref.watch( - prefsChangeNotifierProvider.select((value) => value.useTor))) - GestureDetector( - onTap: () async { - // Stop the Tor service. - try { - await ref.read(pTorService).disable(); - - // Toggle the useTor preference on success. - ref.read(prefsChangeNotifierProvider).useTor = false; - } catch (e, s) { - Logging.instance.log( - "Error stopping tor: $e\n$s", - level: LogLevel.Error, - ); - } - }, - child: Text( - "Disconnect", - style: STextStyles.link2(context), - ), - ), - if (!ref.watch( - prefsChangeNotifierProvider.select((value) => value.useTor))) - GestureDetector( - onTap: () async { - try { - // Init the Tor service if it hasn't already been. - final torDir = - await StackFileSystem.applicationTorDirectory(); - ref.read(pTorService).init(torDataDirPath: torDir.path); - // Start the Tor service. - await ref.read(pTorService).start(); - - // Toggle the useTor preference on success. - ref.read(prefsChangeNotifierProvider).useTor = true; - } catch (e, s) { - Logging.instance.log( - "Error starting tor: $e\n$s", - level: LogLevel.Error, - ); - // TODO: show dialog with error message - } - }, - child: Text( - "Connect", - style: STextStyles.link2(context), - ), - ), + CustomTextButton( + text: ref.watch(prefsChangeNotifierProvider + .select((value) => value.useTor)) + ? "Disconnect" + : "Connect", + onTap: onTorTapped, + ), ], ), SizedBox( diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart index fcacc60d4..6b7e57bef 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart @@ -13,6 +13,7 @@ import 'dart:async'; import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/models/epicbox_config_model.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/address_book_views/address_book_view.dart'; @@ -36,11 +37,14 @@ import 'package:stackwallet/services/event_bus/global_event_bus.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/show_loading.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; +import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:tuple/tuple.dart'; /// [eventBus] should only be set during testing @@ -306,6 +310,61 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> { ); }, ), + if (coin == Coin.firo) + const SizedBox( + height: 8, + ), + if (coin == Coin.firo) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.eye, + title: "Clear electrumx cache", + onPressed: () async { + String? result; + await showDialog<void>( + useSafeArea: false, + barrierDismissible: true, + context: context, + builder: (_) => StackOkDialog( + title: + "Are you sure you want to clear " + "${coin.prettyName} electrumx cache?", + onOkPressed: (value) { + result = value; + }, + leftButton: SecondaryButton( + label: "Cancel", + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + ); + + if (result == "OK" && mounted) { + await showLoading( + whileFuture: Future.wait<void>( + [ + Future.delayed( + const Duration( + milliseconds: 1500, + ), + ), + DB.instance + .clearSharedTransactionCache( + coin: coin, + ), + ], + ), + context: context, + message: "Clearing cache...", + ); + } + }, + ); + }, + ), if (coin == Coin.nano || coin == Coin.banano) const SizedBox( height: 8, diff --git a/lib/pages/wallet_view/sub_widgets/tx_icon.dart b/lib/pages/wallet_view/sub_widgets/tx_icon.dart index d86ad6e8d..bcf7c3780 100644 --- a/lib/pages/wallet_view/sub_widgets/tx_icon.dart +++ b/lib/pages/wallet_view/sub_widgets/tx_icon.dart @@ -47,7 +47,7 @@ class TxIcon extends ConsumerWidget { if (isReceived) { if (isCancelled) { - return assets.receive; + return assets.receiveCancelled; } if (isPending) { return assets.receivePending; diff --git a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart index f358aef5e..54b528245 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart @@ -358,8 +358,6 @@ class _TransactionDetailsViewState final currentHeight = ref.watch(walletsChangeNotifierProvider .select((value) => value.getManager(walletId).currentHeight)); - print("THIS TRANSACTION IS $_transaction"); - return ConditionalParent( condition: !isDesktop, builder: (child) => Background( diff --git a/lib/pages_desktop_specific/desktop_home_view.dart b/lib/pages_desktop_specific/desktop_home_view.dart index 37fbd9693..1d0755b8f 100644 --- a/lib/pages_desktop_specific/desktop_home_view.dart +++ b/lib/pages_desktop_specific/desktop_home_view.dart @@ -30,6 +30,7 @@ import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; import 'package:stackwallet/widgets/background.dart'; +import 'package:stackwallet/widgets/onetime_popups/tor_has_been_add_dialog.dart'; final currentWalletIdProvider = StateProvider<String?>((_) => null); @@ -53,6 +54,11 @@ class _DesktopHomeViewState extends ConsumerState<DesktopHomeView> { onGenerateRoute: RouteGenerator.generateRoute, initialRoute: MyStackView.routeName, ); + + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + showOneTimeTorHasBeenAddedDialogIfRequired(context); + }); + super.initState(); } diff --git a/lib/pages_desktop_specific/my_stack_view/my_stack_view.dart b/lib/pages_desktop_specific/my_stack_view/my_stack_view.dart index 819ec2a90..f510b8289 100644 --- a/lib/pages_desktop_specific/my_stack_view/my_stack_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/my_stack_view.dart @@ -13,11 +13,13 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/hidden_settings.dart'; import 'package:stackwallet/pages/wallets_view/sub_widgets/empty_wallets.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/my_wallets.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/themes/theme_providers.dart'; import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; @@ -52,27 +54,77 @@ class _MyStackViewState extends ConsumerState<MyStackView> { } } -class DesktopMyStackTitle extends ConsumerWidget { - const DesktopMyStackTitle({Key? key}) : super(key: key); +class DesktopMyStackTitle extends ConsumerStatefulWidget { + const DesktopMyStackTitle({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState<DesktopMyStackTitle> createState() => + _DesktopMyStackTitleState(); +} + +class _DesktopMyStackTitleState extends ConsumerState<DesktopMyStackTitle> { + late final RotateIconController _rotateIconController; + + DateTime _hiddenTime = DateTime.now(); + int _hiddenCount = 0; + + void _hiddenOptions() { + _rotateIconController.reset?.call(); + _rotateIconController.forward?.call(); + if (_hiddenCount == 5) { + Navigator.of(context).pushNamed(HiddenSettings.routeName); + } + final now = DateTime.now(); + const timeout = Duration(seconds: 1); + if (now.difference(_hiddenTime) < timeout) { + _hiddenCount++; + } else { + _hiddenCount = 0; + } + _hiddenTime = now; + } + + @override + void initState() { + _rotateIconController = RotateIconController(); + + super.initState(); + } + + @override + dispose() { + _rotateIconController.forward = null; + _rotateIconController.reverse = null; + _rotateIconController.reset = null; + super.dispose(); + } + + @override + Widget build(BuildContext context) { return Row( children: [ const SizedBox( width: 24, ), - SizedBox( - width: 32, - height: 32, - child: SvgPicture.file( - File( - ref.watch( - themeProvider.select( - (value) => value.assets.stackIcon, + GestureDetector( + onTap: _hiddenOptions, + child: RotateIcon( + icon: SizedBox( + width: 32, + height: 32, + child: SvgPicture.file( + File( + ref.watch( + themeProvider.select( + (value) => value.assets.stackIcon, + ), + ), ), ), ), + curve: Curves.easeInOutCubic, + rotationPercent: 1.0, + controller: _rotateIconController, ), ), const SizedBox( diff --git a/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart b/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart index 44135c3b2..0b778031c 100644 --- a/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart +++ b/lib/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart @@ -62,7 +62,8 @@ class _DesktopOrdinalDetailsViewState ); if (response.code != 200) { - throw Exception("statusCode=${response.code} body=${response.bodyBytes}"); + throw Exception( + "DesktopOrdinalDetailsView _savePngToFile statusCode=${response.code} body=${response.bodyBytes}"); } final bytes = response.bodyBytes; diff --git a/lib/services/coins/epiccash/epiccash_wallet.dart b/lib/services/coins/epiccash/epiccash_wallet.dart index 2dacb1639..bdf803e4b 100644 --- a/lib/services/coins/epiccash/epiccash_wallet.dart +++ b/lib/services/coins/epiccash/epiccash_wallet.dart @@ -457,7 +457,6 @@ class EpicCashWallet extends CoinServiceAPI // TODO determine whether it is worth sending change to a change address. dynamic message; - print("THIS TX DATA IS $txData"); String receiverAddress = txData['addresss'] as String; diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index eecb80462..6b34fd438 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -162,18 +162,21 @@ class ExchangeDataLoadingService { // await _loadChangeNowEstimatedRatePairs(); */ + // Exchanges which support Tor just get treated normally. + final futures = [ + loadMajesticBankCurrencies(), + loadTrocadorCurrencies(), + ]; + // If using Tor, don't load data for exchanges which don't support Tor. // // Add to this list when adding an exchange which doesn't supports Tor. if (!Prefs.instance.useTor) { - await _loadChangeNowCurrencies(); + futures.add(_loadChangeNowCurrencies()); } - // Exchanges which support Tor just get treated normally. - await Future.wait([ - loadMajesticBankCurrencies(), - loadTrocadorCurrencies(), - ]); + // wait for all loading futures to complete + await Future.wait(futures); Logging.instance.log( "ExchangeDataLoadingService.loadAll finished in ${DateTime.now().difference(start).inSeconds} seconds", diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index f6a454b7f..c664849b3 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -21,6 +21,7 @@ abstract class Assets { static const socials = _SOCIALS(); static const exchange = _EXCHANGE(); static const buy = _BUY(); + static const gif = _GIF(); } class _SOCIALS { @@ -260,3 +261,9 @@ class _ANIMATIONS { String get arrowRotate => "assets/lottie/arrow_rotate.json"; String get onionTor => "assets/lottie/onion_animation.json"; } + +class _GIF { + const _GIF(); + + String get stacyOnion => "assets/gif/stacy_onion.gif"; +} diff --git a/lib/widgets/desktop/desktop_tor_status_button.dart b/lib/widgets/desktop/desktop_tor_status_button.dart index 8b7e96ec2..da429e9ec 100644 --- a/lib/widgets/desktop/desktop_tor_status_button.dart +++ b/lib/widgets/desktop/desktop_tor_status_button.dart @@ -120,50 +120,56 @@ class _DesktopTorStatusButtonState extends ConsumerState<DesktopTorStatusButton> .extension<StackColors>()! .getDesktopMenuButtonStyle(context), onPressed: widget.onPressed, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - AnimatedContainer( - duration: widget.transitionDuration, - width: _iconOnly ? 0 : 16, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + vertical: 16, ), - SvgPicture.asset( - Assets.svg.tor, - color: _color(_torConnectionStatus), - width: 20, - height: 20, - ), - AnimatedOpacity( - duration: widget.transitionDuration, - opacity: _iconOnly ? 0 : 1.0, - child: SizeTransition( - sizeFactor: animationController, - axis: Axis.horizontal, - axisAlignment: -1, - child: SizedBox( - width: labelLength, - child: Row( - children: [ - const SizedBox( - width: 12, - ), - Text( - _torConnectionStatus.name.capitalize(), - style: STextStyles.smallMed12(context).copyWith( - color: _color(_torConnectionStatus), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AnimatedContainer( + duration: widget.transitionDuration, + width: _iconOnly ? 0 : 16, + ), + SvgPicture.asset( + Assets.svg.tor, + color: _color(_torConnectionStatus), + width: 20, + height: 20, + ), + AnimatedOpacity( + duration: widget.transitionDuration, + opacity: _iconOnly ? 0 : 1.0, + child: SizeTransition( + sizeFactor: animationController, + axis: Axis.horizontal, + axisAlignment: -1, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + width: 12, ), - ), - ], + Text( + _torConnectionStatus.name.capitalize(), + style: STextStyles.smallMed12(context).copyWith( + color: _color(_torConnectionStatus), + ), + ), + const SizedBox( + width: 21, + ), + ], + ), ), ), - ), + ], ), - ], - ), + ), + ], ), ); } diff --git a/lib/widgets/onetime_popups/tor_has_been_add_dialog.dart b/lib/widgets/onetime_popups/tor_has_been_add_dialog.dart new file mode 100644 index 000000000..8f316c012 --- /dev/null +++ b/lib/widgets/onetime_popups/tor_has_been_add_dialog.dart @@ -0,0 +1,167 @@ +import 'package:flutter/material.dart'; +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:stackwallet/db/hive/db.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/conditional_parent.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/stack_dialog.dart'; + +const _kOneTimeTorHasBeenAddedDialogWasShown = + "oneTimeTorHasBeenAddedDialogWasShown"; + +Future<void> showOneTimeTorHasBeenAddedDialogIfRequired( + BuildContext context) async { + final box = await Hive.openBox<bool>(DB.boxNameOneTimeDialogsShown); + + if (!box.get( + _kOneTimeTorHasBeenAddedDialogWasShown, + defaultValue: false, + )! && + context.mounted) { + await showDialog<void>( + context: context, + barrierDismissible: false, + builder: (_) => const _TorHasBeenAddedDialog(), + ); + } +} + +class _TorHasBeenAddedDialog extends StatefulWidget { + const _TorHasBeenAddedDialog({super.key}); + + @override + State<_TorHasBeenAddedDialog> createState() => _TorHasBeenAddedDialogState(); +} + +class _TorHasBeenAddedDialogState extends State<_TorHasBeenAddedDialog> { + bool _lock = false; + + void setDoNotShowAgain() async { + if (_lock) { + return; + } + _lock = true; + try { + final box = await Hive.openBox<bool>(DB.boxNameOneTimeDialogsShown); + await box.put(_kOneTimeTorHasBeenAddedDialogWasShown, true); + } catch (_) { + // + } finally { + _lock = false; + } + } + + @override + Widget build(BuildContext context) { + return ConditionalParent( + condition: Util.isDesktop, + builder: (child) => DesktopDialog( + maxHeight: double.infinity, + maxWidth: 450, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "", + style: STextStyles.desktopH3(context), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: () { + setDoNotShowAgain(); + Navigator.of(context).pop(); + }, + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: child, + ), + Padding( + padding: const EdgeInsets.all(32), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + PrimaryButton( + buttonHeight: ButtonHeight.l, + width: 180, + label: "Ok", + onPressed: () { + setDoNotShowAgain(); + Navigator.of(context).pop(); + }, + ), + ], + ), + ) + ], + ), + ), + child: ConditionalParent( + condition: !Util.isDesktop, + builder: (child) => StackDialogBase( + child: Column( + children: [ + child, + const SizedBox( + height: 28, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: MediaQuery.of(context).size.width / 2, + child: PrimaryButton( + label: "Ok", + onPressed: () { + setDoNotShowAgain(); + Navigator.of(context).pop(); + }, + ), + ), + ], + ), + ], + ), + ), + child: Column( + children: [ + const StacyOnion(), + SizedBox( + height: Util.isDesktop ? 24 : 16, + ), + Text( + "Tor has been added to help keep your connections private and secure!", + style: Util.isDesktop + ? STextStyles.desktopTextMedium(context) + : STextStyles.smallMed14(context), + ), + ], + ), + ), + ); + } +} + +class StacyOnion extends StatelessWidget { + const StacyOnion({super.key}); + + @override + Widget build(BuildContext context) { + return Image( + height: 200, + image: AssetImage( + Assets.gif.stacyOnion, + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 934394e2a..5bfe671b9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: "direct main" description: name: archive - sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + sha256: e0902a06f0e00414e4e3438a084580161279f137aeb862274710f29ec10cf01e url: "https://pub.dev" source: hosted - version: "3.3.7" + version: "3.3.9" args: dependency: transitive description: @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: asn1lib - sha256: b74e3842a52c61f8819a1ec8444b4de5419b41a7465e69d4aa681445377398b0 + sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd" url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.5.0" async: dependency: "direct main" description: @@ -178,10 +178,10 @@ packages: dependency: transitive description: name: build_resolvers - sha256: "6c4dd11d05d056e76320b828a1db0fc01ccd376922526f8e9d6c796a5adbac20" + sha256: d912852cce27c9e80a93603db721c267716894462e7033165178b91138587972 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.2" build_runner: dependency: "direct dev" description: @@ -210,10 +210,10 @@ packages: dependency: transitive description: name: built_value - sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + sha256: ff627b645b28fb8bdb69e645f910c2458fd6b65f6585c3a53e0626024897dedf url: "https://pub.dev" source: hosted - version: "8.6.1" + version: "8.6.2" characters: dependency: transitive description: @@ -250,10 +250,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + sha256: "315a598c7fbe77f22de1c9da7cfd6fd21816312f16ffa124453b4fc679e540f1" url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.6.0" coinlib: dependency: "direct main" description: @@ -274,10 +274,10 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: "8599ae9edca5ff96163fca3e36f8e481ea917d1e71cdad912c084b5579913f34" + sha256: "77a180d6938f78ca7d2382d2240eb626c0f6a735d0bfdce227d8ffb80f95c48b" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" connectivity_plus_platform_interface: dependency: transitive description: @@ -306,10 +306,10 @@ packages: dependency: transitive description: name: cross_file - sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb url: "https://pub.dev" source: hosted - version: "0.3.3+4" + version: "0.3.3+5" crypto: dependency: "direct main" description: @@ -398,10 +398,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + sha256: abd7625e16f51f554ea244d090292945ec4d4be7bfbaf2ec8cccea568919d334 url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" dartx: dependency: transitive description: @@ -438,18 +438,18 @@ packages: dependency: "direct main" description: name: desktop_drop - sha256: "4ca4d960f4b11c032e9adfd2a0a8ac615bc3fddb4cbe73dcf840dd8077582186" + sha256: ebba9c9cb0b54385998a977d741cc06fd8324878c08d5a36e9da61cd56b04cc6 url: "https://pub.dev" source: hosted - version: "0.4.1" + version: "0.4.3" device_info_plus: dependency: "direct main" description: name: device_info_plus - sha256: "2c35b6d1682b028e42d07b3aee4b98fa62996c10bc12cb651ec856a80d6a761b" + sha256: "86add5ef97215562d2e090535b0a16f197902b10c369c558a100e74ea06e8659" url: "https://pub.dev" source: hosted - version: "9.0.2" + version: "9.0.3" device_info_plus_platform_interface: dependency: transitive description: @@ -478,10 +478,10 @@ packages: dependency: "direct main" description: name: dropdown_button2 - sha256: "83c54a5022f898d63e3abe21240b64b937e676103207287e6705d3f9bb04d654" + sha256: b0fe8d49a030315e9eef6c7ac84ca964250155a6224d491c1365061bc974a9e1 url: "https://pub.dev" source: hosted - version: "2.3.6" + version: "2.3.9" eip1559: dependency: transitive description: @@ -510,10 +510,10 @@ packages: dependency: transitive description: name: encrypt - sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "5.0.3" equatable: dependency: "direct main" description: @@ -631,10 +631,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" flutter_local_notifications: dependency: "direct main" description: @@ -671,18 +671,18 @@ packages: dependency: "direct main" description: name: flutter_native_splash - sha256: ba45d8cfbd778478a74696b012f33ffb6b1760c9bc531b21e2964444a4870dae + sha256: ecff62b3b893f2f665de7e4ad3de89f738941fcfcaaba8ee601e749efafa4698 url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" + sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" flutter_riverpod: dependency: "direct main" description: @@ -703,50 +703,50 @@ packages: dependency: "direct main" description: name: flutter_secure_storage - sha256: "98352186ee7ad3639ccc77ad7924b773ff6883076ab952437d20f18a61f0a7c5" + sha256: "22dbf16f23a4bcf9d35e51be1c84ad5bb6f627750565edd70dab70f3ff5fff8f" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.1.0" flutter_secure_storage_linux: dependency: transitive description: name: flutter_secure_storage_linux - sha256: "0912ae29a572230ad52d8a4697e5518d7f0f429052fd51df7e5a7952c7efe2a3" + sha256: "3d5032e314774ee0e1a7d0a9f5e2793486f0dff2dd9ef5a23f4e3fb2a0ae6a9e" url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "1.2.0" flutter_secure_storage_macos: dependency: transitive description: name: flutter_secure_storage_macos - sha256: "083add01847fc1c80a07a08e1ed6927e9acd9618a35e330239d4422cd2a58c50" + sha256: bd33935b4b628abd0b86c8ca20655c5b36275c3a3f5194769a7b3f37c905369c url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" flutter_secure_storage_platform_interface: dependency: transitive description: name: flutter_secure_storage_platform_interface - sha256: b3773190e385a3c8a382007893d678ae95462b3c2279e987b55d140d3b0cb81b + sha256: "0d4d3a5dd4db28c96ae414d7ba3b8422fd735a8255642774803b2532c9a61d7e" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" flutter_secure_storage_web: dependency: transitive description: name: flutter_secure_storage_web - sha256: "42938e70d4b872e856e678c423cc0e9065d7d294f45bc41fc1981a4eb4beaffe" + sha256: "30f84f102df9dcdaa2241866a958c2ec976902ebdaa8883fbfe525f1f2f3cf20" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" flutter_secure_storage_windows: dependency: transitive description: name: flutter_secure_storage_windows - sha256: fc2910ec9b28d60598216c29ea763b3a96c401f0ce1d13cdf69ccb0e5c93c3ee + sha256: "38f9501c7cb6f38961ef0e1eacacee2b2d4715c63cc83fe56449c4d3d0b47255" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.1" flutter_svg: dependency: "direct main" description: @@ -830,10 +830,10 @@ packages: dependency: "direct dev" description: name: hive_generator - sha256: "65998cc4d2cd9680a3d9709d893d2f6bb15e6c1f92626c3f1fa650b4b3281521" + sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.0.1" hive_test: dependency: "direct dev" description: @@ -1010,10 +1010,10 @@ packages: dependency: "direct main" description: name: lottie - sha256: "0793a5866062e5cc8a8b24892fa94c3095953ea914a7fdf790f550dd7537fe60" + sha256: b8bdd54b488c54068c57d41ae85d02808da09e2bee8b8dd1f59f441e7efa60cd url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.6.0" matcher: dependency: transitive description: @@ -1130,10 +1130,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: ceb027f6bc6a60674a233b4a90a7658af1aebdea833da0b5b53c1e9821a78c7b + sha256: "6ff267fcd9d48cb61c8df74a82680e8b82e940231bb5f68356672fde0397334a" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.0" package_info_plus_platform_interface: dependency: transitive description: @@ -1218,10 +1218,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: "6901d50f4d4b9a27e1749dbd4adbf06aa00d90a21a2db563405d5ce27ee120ac" + sha256: f23cfe9af0d49c6b9fd8a8b09f7b3301ca7e346204939b5afef4404d36d2608f url: "https://pub.dev" source: hosted - version: "11.0.0" + version: "11.0.1" permission_handler_apple: dependency: transitive description: @@ -1274,10 +1274,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.6" pointycastle: dependency: "direct main" description: @@ -1402,18 +1402,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: ed3fcea4f789ed95913328e629c0c53e69e80e08b6c24542f1b3576046c614e8 + sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11" url: "https://pub.dev" source: hosted - version: "7.0.2" + version: "7.1.0" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "0c6e61471bd71b04a138b8b588fa388e66d8b005e6f2deda63371c5c505a0981" + sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.3.0" shelf: dependency: transitive description: @@ -1656,8 +1656,8 @@ packages: dependency: "direct main" description: path: "." - ref: "8a26a160bdc4dcac2ba5a0350a151a345d1dead9" - resolved-ref: "8a26a160bdc4dcac2ba5a0350a151a345d1dead9" + ref: "7123505a9e5f702dba1c0c9aa12b289b5dfbb3bf" + resolved-ref: "7123505a9e5f702dba1c0c9aa12b289b5dfbb3bf" url: "https://github.com/cypherstack/tor.git" source: git version: "0.0.1" @@ -1697,66 +1697,66 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e" + sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" url: "https://pub.dev" source: hosted - version: "6.1.12" + version: "6.1.14" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "78cb6dea3e93148615109e58e42c35d1ffbf5ef66c44add673d0ab75f12ff3af" + sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 url: "https://pub.dev" source: hosted - version: "6.0.37" + version: "6.1.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "6.1.5" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" + sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea + sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.5" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 + sha256: ba140138558fcc3eead51a1c42e92a9fb074a1b1149ed3c73e66035b2ccd94f2 url: "https://pub.dev" source: hosted - version: "2.0.18" + version: "2.0.19" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" + sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "3.0.8" uuid: dependency: "direct main" description: @@ -1898,10 +1898,10 @@ packages: dependency: transitive description: name: webkit_inspection_protocol - sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" websocket_universal: dependency: "direct main" description: @@ -1914,10 +1914,10 @@ packages: dependency: transitive description: name: win32 - sha256: dfdf0136e0aa7a1b474ea133e67cb0154a0acd2599c4f3ada3b49d38d38793ee + sha256: c97defd418eef4ec88c0d1652cdce84b9f7b63dd7198e266d06ac1710d527067 url: "https://pub.dev" source: hosted - version: "5.0.5" + version: "5.0.8" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5c3c50059..a87ba8824 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,7 +60,7 @@ dependencies: tor_ffi_plugin: git: url: https://github.com/cypherstack/tor.git - ref: 8a26a160bdc4dcac2ba5a0350a151a345d1dead9 + ref: 7123505a9e5f702dba1c0c9aa12b289b5dfbb3bf # Utility plugins http: ^0.13.0 @@ -373,6 +373,9 @@ flutter: # buy - assets/svg/buy/ + # gif + - assets/gif/ + # lottie animations # basic - assets/lottie/test2.json diff --git a/scripts/android/build_all.sh b/scripts/android/build_all.sh index 111fea934..19e2ec64c 100755 --- a/scripts/android/build_all.sh +++ b/scripts/android/build_all.sh @@ -1,5 +1,11 @@ #!/bin/bash +set -e + +# libepiccash requires old rust +source ../rust_version.sh +set_rust_to_1680 + mkdir build . ./config.sh ./install_ndk.sh @@ -7,7 +13,10 @@ mkdir build (cd ../../crypto_plugins/flutter_liblelantus/scripts/android && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/android && ./install_ndk.sh && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/android/ && ./build_all.sh ) & -(cd ../../crypto_plugins/tor/scripts/android && ./install_ndk.sh && ./build_all.sh ) & wait echo "Done building" + +# set rust (back) to a more recent stable release to allow stack wallet to build tor +set_rust_to_1720 + diff --git a/scripts/ios/build_all.sh b/scripts/ios/build_all.sh index fa6f2ac93..5ff7cb2f4 100755 --- a/scripts/ios/build_all.sh +++ b/scripts/ios/build_all.sh @@ -1,8 +1,25 @@ #!/bin/bash +set -e + +# libepiccash requires old rust +source ../rust_version.sh +set_rust_to_1680 + +# ensure ios rust triples are there +rustup target add aarch64-apple-ios +rustup target add x86_64-apple-ios + (cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/ios && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/ios/ && ./build_all.sh ) & wait -echo "Done building" \ No newline at end of file +echo "Done building" + +# set rust (back) to a more recent stable release to allow stack wallet to build tor +set_rust_to_1720 + +# ensure ios rust triples are there +rustup target add aarch64-apple-ios +rustup target add x86_64-apple-ios diff --git a/scripts/linux/build_all.sh b/scripts/linux/build_all.sh index 9a119d0d6..9a6ee34d9 100755 --- a/scripts/linux/build_all.sh +++ b/scripts/linux/build_all.sh @@ -1,5 +1,11 @@ #!/bin/bash +set -e + +# libepiccash requires old rust +source ../rust_version.sh +set_rust_to_1680 + # for arm # flutter-elinux clean # flutter-elinux pub get @@ -9,7 +15,10 @@ mkdir -p build (cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/linux && ./build_monero_all.sh && ./build_sharedfile.sh ) & -(cd ../../crypto_plugins/tor/scripts/linux && ./build_all.sh ) & wait echo "Done building" + +# set rust (back) to a more recent stable release to allow stack wallet to build tor +set_rust_to_1720 + diff --git a/scripts/macos/build_all.sh b/scripts/macos/build_all.sh index 646274593..a91fb73b2 100755 --- a/scripts/macos/build_all.sh +++ b/scripts/macos/build_all.sh @@ -1,8 +1,17 @@ #!/bin/bash +set -e + +# libepiccash requires old rust +source ../rust_version.sh +set_rust_to_1680 + (cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libepiccash/scripts/macos && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_libmonero/scripts/macos/ && ./build_all.sh ) & wait -echo "Done building" \ No newline at end of file +echo "Done building" + +# set rust (back) to a more recent stable release to allow stack wallet to build tor +set_rust_to_1720 diff --git a/scripts/rust_version.sh b/scripts/rust_version.sh new file mode 100755 index 000000000..91ead188d --- /dev/null +++ b/scripts/rust_version.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +set_rust_to_1680() { + if rustup toolchain list | grep -q "1.68.0"; then + rustup default 1.68.0 + else + echo "Rust version 1.68.0 is not installed. Please install it using 'rustup install 1.68.0'." >&2 + exit 1 + fi +} + +set_rust_to_1720() { + if rustup toolchain list | grep -q "1.72.0"; then + rustup default 1.72.0 + else + echo "Rust version 1.72.0 is not installed. Please install it using 'rustup install 1.72.0'." >&2 + exit 1 + fi +} \ No newline at end of file diff --git a/scripts/windows/build_all.sh b/scripts/windows/build_all.sh index a96271cc3..54d340b5e 100755 --- a/scripts/windows/build_all.sh +++ b/scripts/windows/build_all.sh @@ -1,9 +1,18 @@ #!/bin/bash +set -e + +# libepiccash requires old rust +source ../rust_version.sh +set_rust_to_1680 + mkdir -p build (cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./build_all.sh ) & (cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh ) & -# (cd ../../crypto_plugins/flutter_libmonero/scripts/windows && ./build_all.sh) & +(cd ../../crypto_plugins/flutter_libmonero/scripts/windows && ./build_all.sh) & wait echo "Done building" + +# set rust (back) to a more recent stable release to allow stack wallet to build tor +set_rust_to_1720 diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt index b9e550fba..17411a8ab 100644 --- a/windows/runner/CMakeLists.txt +++ b/windows/runner/CMakeLists.txt @@ -20,6 +20,13 @@ add_executable(${BINARY_NAME} WIN32 # that need different build settings. apply_standard_settings(${BINARY_NAME}) +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + # Disable Windows macros that collide with C++ standard library functions. target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index 5fa3067e5..d23cd8ce6 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -60,14 +60,14 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" // Version // -#ifdef FLUTTER_BUILD_NUMBER -#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD #else -#define VERSION_AS_NUMBER 1,0,0 +#define VERSION_AS_NUMBER 1,0,0,0 #endif -#ifdef FLUTTER_BUILD_NAME -#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION #else #define VERSION_AS_STRING "1.0.0" #endif