mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
Mweb enhancements 4 (#1768)
* [skip-ci] show mweb confirmations, show last mweb balance while syncing * potential send-all fix * [skip-ci] undo fix that didn't work * [skip-ci] undo unnecessary changes * [skip ci] add export mweb logs screen * [skip ci] cleanup * confirmation fixes * catch electrum call errors * [skip ci] undo some changes * potential electrum fixes + mweb logs display only last 10000 characters * Add question mark and link to MWEB card * updates * show negative unconfirmed mweb balanaces + other fixes [skip ci] * error handling * [skip ci] [wip] check if node supports mweb * check fee before building tx * [skip ci] minor * [skip ci] minor * mweb node setting [wip] [skip ci] * prioritize mweb coins when selecting inputs from the pool * potential connection edgecase fix * translations + mweb node fixes * don't use mweb for exchange refund address * add peg in / out labels and make 6 confs only show up for peg in / out * bump bitcoin_base version to v9 * [skip ci] fix logs page * don't fetch txinfo for non-mweb addresses [skip ci] * fix non-mweb confirmations * rename always scan to enable mweb * Update litecoin_wallet_addresses.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * Update cw_mweb.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * [skip ci] review updates pt.1 * [skip ci] minor code cleanup * [skip ci] use exception handler * exception handling [skip ci] * [skip ci] exception handling * trigger build * pegout label fixes * fix showing change transactions on peg-out * minor code cleanup and minor peg-out fix * final balance fixes * non-mweb confirmations potential fix * [skip ci] wip * trigger build --------- Co-authored-by: tuxpizza <tuxsudo@tux.pizza> Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
co-authored by
Omar Hatem
tuxpizza
parent
109d9b458e
commit
c8cfc2cff1
@@ -35,6 +35,8 @@ import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||
import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
|
||||
import 'package:cake_wallet/entities/wallet_manager.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/address_list_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/mweb_node_page.dart';
|
||||
import 'package:cake_wallet/view_model/link_view_model.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
|
||||
@@ -945,6 +947,10 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactory(() => MwebSettingsPage(getIt.get<MwebSettingsViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => MwebLogsPage(getIt.get<MwebSettingsViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => MwebNodePage(getIt.get<MwebSettingsViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => OtherSettingsPage(getIt.get<OtherSettingsViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => NanoChangeRepPage(
|
||||
|
||||
@@ -54,6 +54,7 @@ class PreferencesKey {
|
||||
static const mwebEnabled = 'mwebEnabled';
|
||||
static const hasEnabledMwebBefore = 'hasEnabledMwebBefore';
|
||||
static const mwebAlwaysScan = 'mwebAlwaysScan';
|
||||
static const mwebNodeUri = 'mwebNodeUri';
|
||||
static const shouldShowReceiveWarning = 'should_show_receive_warning';
|
||||
static const shouldShowYatPopup = 'should_show_yat_popup';
|
||||
static const shouldShowRepWarning = 'should_show_rep_warning';
|
||||
|
||||
@@ -72,6 +72,8 @@ import 'package:cake_wallet/src/screens/settings/desktop_settings/desktop_settin
|
||||
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/domain_lookups_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/mweb_logs_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/mweb_node_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/mweb_settings.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
|
||||
@@ -461,6 +463,14 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<MwebSettingsPage>());
|
||||
|
||||
case Routes.mwebLogs:
|
||||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<MwebLogsPage>());
|
||||
|
||||
case Routes.mwebNode:
|
||||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<MwebNodePage>());
|
||||
|
||||
case Routes.connectionSync:
|
||||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<ConnectionSyncPage>());
|
||||
|
||||
@@ -74,6 +74,8 @@ class Routes {
|
||||
static const webViewPage = '/web_view_page';
|
||||
static const silentPaymentsSettings = '/silent_payments_settings';
|
||||
static const mwebSettings = '/mweb_settings';
|
||||
static const mwebLogs = '/mweb_logs';
|
||||
static const mwebNode = '/mweb_node';
|
||||
static const connectionSync = '/connection_sync_page';
|
||||
static const securityBackupPage = '/security_and_backup_page';
|
||||
static const privacyPage = '/privacy_page';
|
||||
|
||||
@@ -886,17 +886,37 @@ class BalanceRowWidget extends StatelessWidget {
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${secondAvailableBalanceLabel}',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor,
|
||||
height: 1,
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => launchUrl(
|
||||
Uri.parse(
|
||||
"https://guides.cakewallet.com/docs/cryptos/litecoin/#mweb"),
|
||||
mode: LaunchMode.externalApplication,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'${secondAvailableBalanceLabel}',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Icon(Icons.help_outline,
|
||||
size: 16,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import 'dart:io';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
import 'package:cake_wallet/utils/share_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart';
|
||||
import 'package:cw_core/root_dir.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class MwebLogsPage extends BasePage {
|
||||
MwebLogsPage(this.mwebSettingsViewModelBase);
|
||||
|
||||
final MwebSettingsViewModelBase mwebSettingsViewModelBase;
|
||||
|
||||
@override
|
||||
String get title => S.current.litecoin_mweb_logs;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
FutureBuilder<String>(
|
||||
future: mwebSettingsViewModelBase.getAbbreviatedLogs(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
} else if (snapshot.hasError || !snapshot.hasData || snapshot.data!.isEmpty) {
|
||||
return Center(child: Text('No logs found'));
|
||||
} else {
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
snapshot.data!,
|
||||
style: TextStyle(fontFamily: 'Monospace'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
Positioned(
|
||||
child: LoadingPrimaryButton(
|
||||
onPressed: () => onExportLogs(context),
|
||||
text: S.of(context).export_logs,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
),
|
||||
bottom: 24,
|
||||
left: 24,
|
||||
right: 24,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void onExportLogs(BuildContext context) {
|
||||
if (Platform.isAndroid) {
|
||||
onExportAndroid(context);
|
||||
} else if (Platform.isIOS) {
|
||||
share(context);
|
||||
} else {
|
||||
_saveFile();
|
||||
}
|
||||
}
|
||||
|
||||
void onExportAndroid(BuildContext context) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (dialogContext) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).export_backup,
|
||||
alertContent: S.of(context).select_destination,
|
||||
rightButtonText: S.of(context).save_to_downloads,
|
||||
leftButtonText: S.of(context).share,
|
||||
actionRightButton: () async {
|
||||
const downloadDirPath = "/storage/emulated/0/Download";
|
||||
final filePath = downloadDirPath + "/debug.log";
|
||||
await mwebSettingsViewModelBase.saveLogsLocally(filePath);
|
||||
Navigator.of(dialogContext).pop();
|
||||
},
|
||||
actionLeftButton: () async {
|
||||
Navigator.of(dialogContext).pop();
|
||||
try {
|
||||
await share(context);
|
||||
} catch (e, s) {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(
|
||||
exception: e,
|
||||
stack: s,
|
||||
library: "Export Logs",
|
||||
));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> share(BuildContext context) async {
|
||||
final filePath = (await getAppDir()).path + "/debug.log";
|
||||
bool success = await mwebSettingsViewModelBase.saveLogsLocally(filePath);
|
||||
if (!success) return;
|
||||
await ShareUtil.shareFile(filePath: filePath, fileName: "debug.log", context: context);
|
||||
await mwebSettingsViewModelBase.removeLogsLocally(filePath);
|
||||
}
|
||||
|
||||
Future<void> _saveFile() async {
|
||||
String? outputFile = await FilePicker.platform
|
||||
.saveFile(dialogTitle: 'Save Your File to desired location', fileName: "debug.log");
|
||||
|
||||
try {
|
||||
final filePath = (await getApplicationSupportDirectory()).path + "/debug.log";
|
||||
File debugLogFile = File(filePath);
|
||||
await debugLogFile.copy(outputFile!);
|
||||
} catch (exception, stackTrace) {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(
|
||||
exception: exception,
|
||||
stack: stackTrace,
|
||||
library: "Export Logs",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class MwebNodePage extends BasePage {
|
||||
MwebNodePage(this.mwebSettingsViewModelBase)
|
||||
: _nodeUriController = TextEditingController(text: mwebSettingsViewModelBase.mwebNodeUri),
|
||||
super();
|
||||
|
||||
final MwebSettingsViewModelBase mwebSettingsViewModelBase;
|
||||
final TextEditingController _nodeUriController;
|
||||
|
||||
@override
|
||||
String get title => S.current.litecoin_mweb_node;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: BaseTextFormField(controller: _nodeUriController),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
child: Observer(
|
||||
builder: (_) => LoadingPrimaryButton(
|
||||
onPressed: () => save(context),
|
||||
text: S.of(context).save,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
),
|
||||
),
|
||||
bottom: 24,
|
||||
left: 24,
|
||||
right: 24,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void save(BuildContext context) {
|
||||
mwebSettingsViewModelBase.setMwebNodeUri(_nodeUriController.text);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class MwebSettingsPage extends BasePage {
|
||||
},
|
||||
),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.litecoin_mweb_always_scan,
|
||||
title: S.current.litecoin_mweb_enable,
|
||||
value: _mwebSettingsViewModel.mwebEnabled,
|
||||
onValueChange: (_, bool value) {
|
||||
_mwebSettingsViewModel.setMwebEnabled(value);
|
||||
@@ -41,6 +41,14 @@ class MwebSettingsPage extends BasePage {
|
||||
title: S.current.litecoin_mweb_scanning,
|
||||
handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.rescan),
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.litecoin_mweb_logs,
|
||||
handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.mwebLogs),
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.litecoin_mweb_node,
|
||||
handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.mwebNode),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -120,6 +120,7 @@ abstract class SettingsStoreBase with Store {
|
||||
required this.mwebCardDisplay,
|
||||
required this.mwebEnabled,
|
||||
required this.hasEnabledMwebBefore,
|
||||
required this.mwebNodeUri,
|
||||
TransactionPriority? initialBitcoinTransactionPriority,
|
||||
TransactionPriority? initialMoneroTransactionPriority,
|
||||
TransactionPriority? initialWowneroTransactionPriority,
|
||||
@@ -358,8 +359,8 @@ abstract class SettingsStoreBase with Store {
|
||||
|
||||
reaction(
|
||||
(_) => bitcoinSeedType,
|
||||
(BitcoinSeedType bitcoinSeedType) => sharedPreferences.setInt(
|
||||
PreferencesKey.bitcoinSeedType, bitcoinSeedType.raw));
|
||||
(BitcoinSeedType bitcoinSeedType) =>
|
||||
sharedPreferences.setInt(PreferencesKey.bitcoinSeedType, bitcoinSeedType.raw));
|
||||
|
||||
reaction(
|
||||
(_) => nanoSeedType,
|
||||
@@ -442,8 +443,10 @@ abstract class SettingsStoreBase with Store {
|
||||
reaction((_) => useTronGrid,
|
||||
(bool useTronGrid) => _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid));
|
||||
|
||||
reaction((_) => useMempoolFeeAPI,
|
||||
(bool useMempoolFeeAPI) => _sharedPreferences.setBool(PreferencesKey.useMempoolFeeAPI, useMempoolFeeAPI));
|
||||
reaction(
|
||||
(_) => useMempoolFeeAPI,
|
||||
(bool useMempoolFeeAPI) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.useMempoolFeeAPI, useMempoolFeeAPI));
|
||||
|
||||
reaction((_) => defaultNanoRep,
|
||||
(String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep));
|
||||
@@ -591,6 +594,11 @@ abstract class SettingsStoreBase with Store {
|
||||
(bool hasEnabledMwebBefore) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.hasEnabledMwebBefore, hasEnabledMwebBefore));
|
||||
|
||||
reaction(
|
||||
(_) => mwebNodeUri,
|
||||
(String mwebNodeUri) =>
|
||||
_sharedPreferences.setString(PreferencesKey.mwebNodeUri, mwebNodeUri));
|
||||
|
||||
this.nodes.observe((change) {
|
||||
if (change.newValue != null && change.key != null) {
|
||||
_saveCurrentNode(change.newValue!, change.key!);
|
||||
@@ -822,6 +830,9 @@ abstract class SettingsStoreBase with Store {
|
||||
@observable
|
||||
bool hasEnabledMwebBefore;
|
||||
|
||||
@observable
|
||||
String mwebNodeUri;
|
||||
|
||||
final SecureStorage _secureStorage;
|
||||
final SharedPreferences _sharedPreferences;
|
||||
final BackgroundTasks _backgroundTasks;
|
||||
@@ -988,6 +999,8 @@ abstract class SettingsStoreBase with Store {
|
||||
final mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
|
||||
final hasEnabledMwebBefore =
|
||||
sharedPreferences.getBool(PreferencesKey.hasEnabledMwebBefore) ?? false;
|
||||
final mwebNodeUri = sharedPreferences.getString(PreferencesKey.mwebNodeUri) ??
|
||||
"ltc-electrum.cakewallet.com:9333";
|
||||
|
||||
// If no value
|
||||
if (pinLength == null || pinLength == 0) {
|
||||
@@ -1259,6 +1272,7 @@ abstract class SettingsStoreBase with Store {
|
||||
mwebAlwaysScan: mwebAlwaysScan,
|
||||
mwebCardDisplay: mwebCardDisplay,
|
||||
mwebEnabled: mwebEnabled,
|
||||
mwebNodeUri: mwebNodeUri,
|
||||
hasEnabledMwebBefore: hasEnabledMwebBefore,
|
||||
initialMoneroTransactionPriority: moneroTransactionPriority,
|
||||
initialWowneroTransactionPriority: wowneroTransactionPriority,
|
||||
@@ -1686,7 +1700,8 @@ abstract class SettingsStoreBase with Store {
|
||||
deviceName = windowsInfo.productName;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
print('likely digitalProductId is null wait till https://github.com/fluttercommunity/plus_plugins/pull/3188 is merged');
|
||||
print(
|
||||
'likely digitalProductId is null wait till https://github.com/fluttercommunity/plus_plugins/pull/3188 is merged');
|
||||
deviceName = "Windows Device";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ abstract class BalanceViewModelBase with Store {
|
||||
|
||||
bool _hasSecondAdditionalBalanceForWalletType(WalletType type) {
|
||||
if (wallet.type == WalletType.litecoin) {
|
||||
if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) > 0) {
|
||||
if ((wallet.balance[CryptoCurrency.ltc]?.secondAdditional ?? 0) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,25 +56,53 @@ class TransactionListItem extends ActionListItem with Keyable {
|
||||
}
|
||||
|
||||
String get formattedPendingStatus {
|
||||
if (balanceViewModel.wallet.type == WalletType.monero ||
|
||||
balanceViewModel.wallet.type == WalletType.haven) {
|
||||
if (transaction.confirmations >= 0 && transaction.confirmations < 10) {
|
||||
return ' (${transaction.confirmations}/10)';
|
||||
}
|
||||
} else if (balanceViewModel.wallet.type == WalletType.wownero) {
|
||||
if (transaction.confirmations >= 0 && transaction.confirmations < 3) {
|
||||
return ' (${transaction.confirmations}/3)';
|
||||
}
|
||||
switch (balanceViewModel.wallet.type) {
|
||||
case WalletType.monero:
|
||||
case WalletType.haven:
|
||||
if (transaction.confirmations >= 0 && transaction.confirmations < 10) {
|
||||
return ' (${transaction.confirmations}/10)';
|
||||
}
|
||||
break;
|
||||
case WalletType.wownero:
|
||||
if (transaction.confirmations >= 0 && transaction.confirmations < 3) {
|
||||
return ' (${transaction.confirmations}/3)';
|
||||
}
|
||||
break;
|
||||
case WalletType.litecoin:
|
||||
bool isPegIn = (transaction.additionalInfo["isPegIn"] as bool?) ?? false;
|
||||
bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false;
|
||||
bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false;
|
||||
String str = '';
|
||||
if (transaction.confirmations <= 0) {
|
||||
str = S.current.pending;
|
||||
}
|
||||
if ((isPegOut || fromPegOut) && transaction.confirmations >= 0 && transaction.confirmations < 6) {
|
||||
str = " (${transaction.confirmations}/6)";
|
||||
}
|
||||
if (isPegIn) {
|
||||
str += " (Peg In)";
|
||||
}
|
||||
if (isPegOut) {
|
||||
str += " (Peg Out)";
|
||||
}
|
||||
return str;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
String get formattedStatus {
|
||||
if (balanceViewModel.wallet.type == WalletType.monero ||
|
||||
balanceViewModel.wallet.type == WalletType.wownero ||
|
||||
balanceViewModel.wallet.type == WalletType.haven) {
|
||||
if ([
|
||||
WalletType.monero,
|
||||
WalletType.haven,
|
||||
WalletType.wownero,
|
||||
WalletType.litecoin,
|
||||
].contains(balanceViewModel.wallet.type)) {
|
||||
return formattedPendingStatus;
|
||||
}
|
||||
|
||||
return transaction.isPending ? S.current.pending : '';
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
part 'mweb_settings_view_model.g.dart';
|
||||
|
||||
@@ -22,15 +27,60 @@ abstract class MwebSettingsViewModelBase with Store {
|
||||
@observable
|
||||
late bool mwebEnabled;
|
||||
|
||||
@computed
|
||||
String get mwebNodeUri => _settingsStore.mwebNodeUri;
|
||||
|
||||
@action
|
||||
void setMwebCardDisplay(bool value) {
|
||||
_settingsStore.mwebCardDisplay = value;
|
||||
}
|
||||
|
||||
@action
|
||||
void setMwebNodeUri(String value) {
|
||||
_settingsStore.mwebNodeUri = value;
|
||||
}
|
||||
|
||||
@action
|
||||
void setMwebEnabled(bool value) {
|
||||
mwebEnabled = value;
|
||||
bitcoin!.setMwebEnabled(_wallet, value);
|
||||
_settingsStore.mwebAlwaysScan = value;
|
||||
}
|
||||
|
||||
Future<bool> saveLogsLocally(String filePath) async {
|
||||
try {
|
||||
final appSupportPath = (await getApplicationSupportDirectory()).path;
|
||||
final logsFile = File("$appSupportPath/logs/debug.log");
|
||||
if (!logsFile.existsSync()) {
|
||||
throw Exception('Logs file does not exist');
|
||||
}
|
||||
await logsFile.copy(filePath);
|
||||
return true;
|
||||
} catch (e, s) {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(
|
||||
exception: e,
|
||||
stack: s,
|
||||
library: "Export Logs",
|
||||
));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> getAbbreviatedLogs() async {
|
||||
final appSupportPath = (await getApplicationSupportDirectory()).path;
|
||||
final logsFile = File("$appSupportPath/logs/debug.log");
|
||||
if (!logsFile.existsSync()) {
|
||||
return "";
|
||||
}
|
||||
final logs = logsFile.readAsStringSync();
|
||||
// return last 10000 characters:
|
||||
return logs.substring(logs.length > 10000 ? logs.length - 10000 : 0);
|
||||
}
|
||||
|
||||
Future<void> removeLogsLocally(String filePath) async {
|
||||
final logsFile = File(filePath);
|
||||
if (logsFile.existsSync()) {
|
||||
await logsFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user