Merge pull request #261 from cypherstack/desktop

Desktop
This commit is contained in:
Diego Salazar 2022-12-12 16:13:24 -07:00 committed by GitHub
commit f2eced2662
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 170 additions and 80 deletions

View file

@ -272,7 +272,16 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
SizedBox( SizedBox(
height: isDesktop ? 16 : 8, height: isDesktop ? 16 : 8,
), ),
RoundedWhiteContainer( GestureDetector(
onTap: () async {
textEditingController.text =
await _generateRandomWalletName();
setState(() {
_nextEnabled = true;
_showDiceIcon = false;
});
},
child: RoundedWhiteContainer(
child: Center( child: Center(
child: Text( child: Text(
"Roll the dice to pick a random name.", "Roll the dice to pick a random name.",
@ -286,6 +295,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
), ),
), ),
), ),
),
if (!isDesktop) if (!isDesktop)
const Spacer( const Spacer(
flex: 4, flex: 4,

View file

@ -70,20 +70,13 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
switch (coin) { switch (coin) {
case Coin.epicCash: case Coin.epicCash:
try { try {
final uri = Uri.parse(formData.host!); final data = await testEpicNodeConnection(formData);
if (uri.scheme.startsWith("http")) {
final String path = uri.path.isEmpty ? "/v1/version" : uri.path;
String uriString = if (data != null) {
"${uri.scheme}://${uri.host}:${formData.port ?? 0}$path"; testPassed = true;
ref.read(nodeFormDataProvider).host = data.host;
if (uri.host == "https") { ref.read(nodeFormDataProvider).port = data.port;
ref.read(nodeFormDataProvider).useSSL = true; ref.read(nodeFormDataProvider).useSSL = data.useSSL;
} else {
ref.read(nodeFormDataProvider).useSSL = false;
}
testPassed = await testEpicBoxNodeConnection(Uri.parse(uriString));
} }
} catch (e, s) { } catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning); Logging.instance.log("$e\n$s", level: LogLevel.Warning);
@ -315,7 +308,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
// strip unused path // strip unused path
String address = formData.host!; String address = formData.host!;
if (coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash) { if (coin == Coin.monero || coin == Coin.wownero) {
if (address.startsWith("http")) { if (address.startsWith("http")) {
final uri = Uri.parse(address); final uri = Uri.parse(address);
address = "${uri.scheme}://${uri.host}"; address = "${uri.scheme}://${uri.host}";
@ -673,6 +666,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
bool _useSSL = false; bool _useSSL = false;
bool _isFailover = false; bool _isFailover = false;
int? port; int? port;
late bool enableSSLCheckbox;
late final bool enableAuthFields; late final bool enableAuthFields;
@ -692,9 +686,9 @@ class _NodeFormState extends ConsumerState<NodeForm> {
case Coin.bitcoincashTestnet: case Coin.bitcoincashTestnet:
case Coin.firoTestNet: case Coin.firoTestNet:
case Coin.dogecoinTestNet: case Coin.dogecoinTestNet:
case Coin.epicCash:
return false; return false;
case Coin.epicCash:
case Coin.monero: case Coin.monero:
case Coin.wownero: case Coin.wownero:
return true; return true;
@ -768,11 +762,19 @@ class _NodeFormState extends ConsumerState<NodeForm> {
_usernameController.text = node.loginName ?? ""; _usernameController.text = node.loginName ?? "";
_useSSL = node.useSSL; _useSSL = node.useSSL;
_isFailover = node.isFailover; _isFailover = node.isFailover;
if (widget.coin == Coin.epicCash) {
enableSSLCheckbox = !node.host.startsWith("http");
}
print("enableSSLCheckbox: $enableSSLCheckbox");
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
// update provider state object so test connection works without having to modify a field in the ui first // update provider state object so test connection works without having to modify a field in the ui first
_updateState(); _updateState();
}); });
} else {
enableSSLCheckbox = true;
// default to port 3413
// _portController.text = "3413";
} }
super.initState(); super.initState();
@ -858,9 +860,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
focusNode: _hostFocusNode, focusNode: _hostFocusNode,
style: STextStyles.field(context), style: STextStyles.field(context),
decoration: standardInputDecoration( decoration: standardInputDecoration(
(widget.coin != Coin.monero && (widget.coin != Coin.monero && widget.coin != Coin.wownero)
widget.coin != Coin.wownero &&
widget.coin != Coin.epicCash)
? "IP address" ? "IP address"
: "Url", : "Url",
_hostFocusNode, _hostFocusNode,
@ -886,6 +886,17 @@ class _NodeFormState extends ConsumerState<NodeForm> {
: null, : null,
), ),
onChanged: (newValue) { onChanged: (newValue) {
if (widget.coin == Coin.epicCash) {
if (newValue.startsWith("https://")) {
_useSSL = true;
enableSSLCheckbox = false;
} else if (newValue.startsWith("http://")) {
_useSSL = false;
enableSSLCheckbox = false;
} else {
enableSSLCheckbox = true;
}
}
_updateState(); _updateState();
setState(() {}); setState(() {});
}, },
@ -1040,20 +1051,18 @@ class _NodeFormState extends ConsumerState<NodeForm> {
const SizedBox( const SizedBox(
height: 8, height: 8,
), ),
if (widget.coin != Coin.monero && if (widget.coin != Coin.monero && widget.coin != Coin.wownero)
widget.coin != Coin.wownero &&
widget.coin != Coin.epicCash)
Row( Row(
children: [ children: [
GestureDetector( GestureDetector(
onTap: widget.readOnly onTap: !widget.readOnly && enableSSLCheckbox
? null ? () {
: () {
setState(() { setState(() {
_useSSL = !_useSSL; _useSSL = !_useSSL;
}); });
_updateState(); _updateState();
}, }
: null,
child: Container( child: Container(
color: Colors.transparent, color: Colors.transparent,
child: Row( child: Row(
@ -1062,22 +1071,22 @@ class _NodeFormState extends ConsumerState<NodeForm> {
width: 20, width: 20,
height: 20, height: 20,
child: Checkbox( child: Checkbox(
fillColor: widget.readOnly fillColor: !widget.readOnly && enableSSLCheckbox
? MaterialStateProperty.all(Theme.of(context) ? null
: MaterialStateProperty.all(Theme.of(context)
.extension<StackColors>()! .extension<StackColors>()!
.checkboxBGDisabled) .checkboxBGDisabled),
: null,
materialTapTargetSize: materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap, MaterialTapTargetSize.shrinkWrap,
value: _useSSL, value: _useSSL,
onChanged: widget.readOnly onChanged: !widget.readOnly && enableSSLCheckbox
? null ? (newValue) {
: (newValue) {
setState(() { setState(() {
_useSSL = newValue!; _useSSL = newValue!;
}); });
_updateState(); _updateState();
}, }
: null,
), ),
), ),
const SizedBox( const SizedBox(

View file

@ -70,14 +70,15 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
switch (coin) { switch (coin) {
case Coin.epicCash: case Coin.epicCash:
try { try {
final uri = Uri.parse(node!.host);
if (uri.scheme.startsWith("http")) {
final String path = uri.path.isEmpty ? "/v1/version" : uri.path;
String uriString = "${uri.scheme}://${uri.host}:${node.port}$path"; testPassed = await testEpicNodeConnection(
NodeFormData()
..host = node!.host
..useSSL = node.useSSL
..port = node.port,
) !=
null;
testPassed = await testEpicBoxNodeConnection(Uri.parse(uriString));
}
} catch (e, s) { } catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning); Logging.instance.log("$e\n$s", level: LogLevel.Warning);
testPassed = false; testPassed = false;

View file

@ -18,7 +18,6 @@ import 'package:stackwallet/providers/global/secure_store_provider.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
@ -218,9 +217,11 @@ class _EditAutoBackupViewState extends ConsumerState<EditAutoBackupView> {
passwordController.text = ""; passwordController.text = "";
passwordRepeatController.text = ""; passwordRepeatController.text = "";
if (!Util.isDesktop) {
Navigator.of(context) Navigator.of(context)
.popUntil(ModalRoute.withName(AutoBackupView.routeName)); .popUntil(ModalRoute.withName(AutoBackupView.routeName));
} }
}
} else { } else {
await showDialog<dynamic>( await showDialog<dynamic>(
context: context, context: context,

View file

@ -1095,8 +1095,9 @@ abstract class SWB {
ExchangeTransaction? exTx; ExchangeTransaction? exTx;
try { try {
exTx = ExchangeTransaction.fromJson(trades[i] as Map<String, dynamic>); exTx = ExchangeTransaction.fromJson(trades[i] as Map<String, dynamic>);
} catch (e, s) { } catch (e) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning); // unneeded log
// Logging.instance.log("$e\n$s", level: LogLevel.Warning);
} }
Trade trade; Trade trade;
@ -1117,8 +1118,9 @@ abstract class SWB {
try { try {
exTx = exTx =
ExchangeTransaction.fromJson(trades.last as Map<String, dynamic>); ExchangeTransaction.fromJson(trades.last as Map<String, dynamic>);
} catch (e, s) { } catch (e) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning); // unneeded log
// Logging.instance.log("$e\n$s", level: LogLevel.Warning);
} }
Trade trade; Trade trade;

View file

@ -1,6 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_menu_item.dart';
@ -219,7 +218,8 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
value: 7, value: 7,
onChanged: (_) { onChanged: (_) {
// todo: save stuff/ notify before exit? // todo: save stuff/ notify before exit?
exit(0); // exit(0);
SystemNavigator.pop();
}, },
controller: controllers[7], controller: controllers[7],
), ),

View file

@ -9,7 +9,6 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/backup_and_restore/create_auto_backup.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/backup_and_restore/create_auto_backup.dart';
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/backup_and_restore/enable_backup_dialog.dart'; import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/backup_and_restore/enable_backup_dialog.dart';
import 'package:stackwallet/providers/global/auto_swb_service_provider.dart'; import 'package:stackwallet/providers/global/auto_swb_service_provider.dart';
import 'package:stackwallet/providers/global/locale_provider.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
@ -73,8 +72,10 @@ class _BackupRestoreSettings extends ConsumerState<BackupRestoreSettings> {
} else { } else {
// if greater than a week return the actual date // if greater than a week return the actual date
return DateFormat.yMMMMd( return DateFormat.yMMMMd(
ref.read(localeServiceChangeNotifierProvider).locale) // en_CA locale breaks things?
.format(time); // ref.read(localeServiceChangeNotifierProvider).locale,
"en_US",
).format(time);
} }
if (value == 1) { if (value == 1) {

View file

@ -15,6 +15,7 @@ import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart'; import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart'; import 'package:stackwallet/models/paymint/transactions_model.dart';
import 'package:stackwallet/models/paymint/utxo_model.dart'; import 'package:stackwallet/models/paymint/utxo_model.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart';
import 'package:stackwallet/services/coins/coin_service.dart'; import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/event_bus/events/global/blocks_remaining_event.dart'; import 'package:stackwallet/services/event_bus/events/global/blocks_remaining_event.dart';
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
@ -276,7 +277,16 @@ Future<String> deleteEpicWallet({
final wallet = await secureStore.read(key: '${walletId}_wallet'); final wallet = await secureStore.read(key: '${walletId}_wallet');
return compute(_deleteWalletWrapper, wallet!); if (wallet == null) {
return "Tried to delete non existent epic wallet file with walletId=$walletId";
} else {
try {
return compute(_deleteWalletWrapper, wallet);
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Error);
return "deleteEpicWallet($walletId) failed...";
}
}
} }
Future<String> _initWalletWrapper( Future<String> _initWalletWrapper(
@ -543,6 +553,9 @@ class EpicCashWallet extends CoinServiceAPI {
DefaultNodes.getNodeFor(coin); DefaultNodes.getNodeFor(coin);
// TODO notify ui/ fire event for node changed? // TODO notify ui/ fire event for node changed?
String stringConfig = await getConfig();
await _secureStore.write(key: '${_walletId}_config', value: stringConfig);
if (shouldRefresh) { if (shouldRefresh) {
unawaited(refresh()); unawaited(refresh());
} }
@ -1253,8 +1266,12 @@ class EpicCashWallet extends CoinServiceAPI {
} }
final NodeModel node = _epicNode!; final NodeModel node = _epicNode!;
final String nodeAddress = node.host; final String nodeAddress = node.host;
int port = node.port; final int port = node.port;
final String nodeApiAddress = "$nodeAddress:$port";
final uri = Uri.parse(nodeAddress).replace(port: port);
final String nodeApiAddress = uri.toString();
final walletDir = await currentWalletDirPath(); final walletDir = await currentWalletDirPath();
final Map<String, dynamic> config = {}; final Map<String, dynamic> config = {};
@ -1263,7 +1280,8 @@ class EpicCashWallet extends CoinServiceAPI {
config["chain"] = "mainnet"; config["chain"] = "mainnet";
config["account"] = "default"; config["account"] = "default";
config["api_listen_port"] = port; config["api_listen_port"] = port;
config["api_listen_interface"] = nodeAddress; config["api_listen_interface"] =
nodeApiAddress.replaceFirst(uri.scheme, "");
String stringConfig = json.encode(config); String stringConfig = json.encode(config);
return stringConfig; return stringConfig;
} }
@ -2013,11 +2031,13 @@ class EpicCashWallet extends CoinServiceAPI {
try { try {
// force unwrap optional as we want connection test to fail if wallet // force unwrap optional as we want connection test to fail if wallet
// wasn't initialized or epicbox node was set to null // wasn't initialized or epicbox node was set to null
final String uriString = return await testEpicNodeConnection(
"${_epicNode!.host}:${_epicNode!.port}/v1/version"; NodeFormData()
..host = _epicNode!.host
final Uri uri = Uri.parse(uriString); ..useSSL = _epicNode!.useSSL
return await testEpicBoxNodeConnection(uri); ..port = _epicNode!.port,
) !=
null;
} catch (e, s) { } catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning); Logging.instance.log("$e\n$s", level: LogLevel.Warning);
return false; return false;

View file

@ -1,15 +1,16 @@
import 'dart:convert'; import 'dart:convert';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
Future<bool> testEpicBoxNodeConnection(Uri uri) async { Future<bool> _testEpicBoxNodeConnection(Uri uri) async {
try { try {
final client = http.Client(); final client = http.Client();
final response = await client.get( final response = await client.get(
uri, uri,
headers: {'Content-Type': 'application/json'}, headers: {'Content-Type': 'application/json'},
).timeout(const Duration(milliseconds: 1200), ).timeout(const Duration(milliseconds: 2000),
onTimeout: () async => http.Response('Error', 408)); onTimeout: () async => http.Response('Error', 408));
final json = jsonDecode(response.body); final json = jsonDecode(response.body);
@ -24,3 +25,38 @@ Future<bool> testEpicBoxNodeConnection(Uri uri) async {
return false; return false;
} }
} }
// returns node data with properly formatted host/url if successful, otherwise null
Future<NodeFormData?> testEpicNodeConnection(NodeFormData data) async {
if (data.host == null || data.port == null || data.useSSL == null) {
return null;
}
const String path_postfix = "/v1/version";
if (data.host!.startsWith("https://")) {
data.useSSL = true;
} else if (data.host!.startsWith("http://")) {
data.useSSL = false;
} else {
if (data.useSSL!) {
data.host = "https://${data.host!}";
} else {
data.host = "http://${data.host!}";
}
}
Uri uri = Uri.parse(data.host! + path_postfix);
uri = uri.replace(port: data.port);
try {
if (await _testEpicBoxNodeConnection(uri)) {
return data;
} else {
return null;
}
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning);
return null;
}
}

View file

@ -6,6 +6,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/notifications/show_flush_bar.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/manage_nodes_views/node_details_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart';
import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
@ -93,9 +94,13 @@ class _NodeCardState extends ConsumerState<NodeCard> {
switch (widget.coin) { switch (widget.coin) {
case Coin.epicCash: case Coin.epicCash:
try { try {
final String uriString = "${node.host}:${node.port}/v1/version"; testPassed = await testEpicNodeConnection(
NodeFormData()
testPassed = await testEpicBoxNodeConnection(Uri.parse(uriString)); ..host = node.host
..useSSL = node.useSSL
..port = node.port,
) !=
null;
} catch (e, s) { } catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning); Logging.instance.log("$e\n$s", level: LogLevel.Warning);
} }

View file

@ -6,6 +6,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/notifications/show_flush_bar.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/manage_nodes_views/node_details_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart';
import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
@ -76,9 +77,13 @@ class NodeOptionsSheet extends ConsumerWidget {
switch (coin) { switch (coin) {
case Coin.epicCash: case Coin.epicCash:
try { try {
final String uriString = "${node.host}:${node.port}/v1/version"; testPassed = await testEpicNodeConnection(
NodeFormData()
testPassed = await testEpicBoxNodeConnection(Uri.parse(uriString)); ..host = node.host
..useSSL = node.useSSL
..port = node.port,
) !=
null;
} catch (e, s) { } catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning); Logging.instance.log("$e\n$s", level: LogLevel.Warning);
} }