diff --git a/assets/icons/close.svg b/assets/icons/close.svg new file mode 100644 index 00000000..eee3db46 --- /dev/null +++ b/assets/icons/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/components/transaction_details.dart b/lib/components/transaction_details.dart index 709da65a..f19bbf82 100644 --- a/lib/components/transaction_details.dart +++ b/lib/components/transaction_details.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:intl/intl.dart'; import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart'; import 'package:qubic_wallet/components/copy_button.dart'; @@ -16,6 +17,7 @@ import 'package:qubic_wallet/pages/main/wallet_contents/explorer/explorer_result import 'package:qubic_wallet/stores/application_store.dart'; // ignore: depend_on_referenced_packages import 'package:collection/collection.dart'; +import 'package:qubic_wallet/styles/app_icons.dart'; import 'package:qubic_wallet/styles/text_styles.dart'; import 'package:qubic_wallet/styles/themed_controls.dart'; import 'transaction_direction_item.dart'; @@ -90,18 +92,18 @@ class TransactionDetails extends StatelessWidget { return element.publicId == id; }); if (source != null) { - return Container( + return SizedBox( width: double.infinity, child: Text( l10n.generalLabelToFromAccount(prepend, source.name), textAlign: TextAlign.start, - style: TextStyles.lightGreyTextSmallBold)); + style: TextStyles.lightGreyTextNormal)); } - return Container( + return SizedBox( width: double.infinity, child: Text(l10n.generalLabelToFromAddress(prepend), textAlign: TextAlign.start, - style: TextStyles.lightGreyTextSmallBold)); + style: TextStyles.lightGreyTextNormal)); }), Text(id, style: Theme.of(context) @@ -117,12 +119,12 @@ class TransactionDetails extends StatelessWidget { return Flex(direction: Axis.horizontal, children: [ Expanded( child: Column(mainAxisAlignment: MainAxisAlignment.end, children: [ - Container( + SizedBox( width: double.infinity, - child: Text("$text", + child: Text(text, textAlign: TextAlign.start, - style: TextStyles.lightGreyTextSmallBold)), - Container( + style: TextStyles.lightGreyTextNormal)), + SizedBox( width: double.infinity, child: Text(value, textAlign: TextAlign.start, style: TextStyles.textNormal)) @@ -141,11 +143,8 @@ class TransactionDetails extends StatelessWidget { maxHeight: MediaQuery.of(context).size.height * 0.8), child: Card( child: Padding( - padding: const EdgeInsets.fromLTRB( - ThemePaddings.normalPadding, - ThemePaddings.normalPadding, - ThemePaddings.normalPadding, - 0), + padding: const EdgeInsets.fromLTRB(ThemePaddings.normalPadding, + ThemePaddings.smallPadding, ThemePaddings.normalPadding, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, @@ -154,12 +153,25 @@ class TransactionDetails extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - ThemedControls.pageHeader( - headerText: l10n.transactionItemLabelDetails, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const IconButton( + onPressed: null, icon: SizedBox.shrink()), + Text( + l10n.transactionItemLabelDetails, + textAlign: TextAlign.center, + style: TextStyles.labelText, + ), + IconButton( + onPressed: () => Navigator.pop(context), + icon: SvgPicture.asset(AppIcons.close), + ), + ], ), ThemedControls.spacerVerticalNormal(), TransactionStatusItem(item: item), - Container( + SizedBox( width: double.infinity, child: FittedBox( child: CopyableText( @@ -196,28 +208,6 @@ class TransactionDetails extends StatelessWidget { ThemedControls.spacerVerticalSmall(), getFromTo(context, l10n.generalLabelTo, item.destId), ThemedControls.spacerVerticalSmall(), - getCopyableDetails( - context, - l10n.transactionItemLabelLeadToMoneyFlow, - item.moneyFlow - ? l10n.generalLabelYes - : l10n.generalLabelNo), - ThemedControls.spacerVerticalSmall(), - getCopyableDetails( - context, - l10n.transactionItemLabelCreatedDate, - item.broadcasted != null - ? formatter.format(item.created!.toLocal()) - : l10n.generalLabelUnknown), - ThemedControls.spacerVerticalSmall(), - getCopyableDetails( - context, - l10n.transactionItemLabelBroadcastedDate, - item.broadcasted != null - ? formatter - .format(item.broadcasted!.toLocal()) - : l10n.generalLabelUnknown), - ThemedControls.spacerVerticalSmall(), getCopyableDetails( context, l10n.transactionItemLabelConfirmedDate, diff --git a/lib/components/transaction_item.dart b/lib/components/transaction_item.dart index d28900bd..d1f529e3 100644 --- a/lib/components/transaction_item.dart +++ b/lib/components/transaction_item.dart @@ -30,12 +30,7 @@ import 'package:qubic_wallet/extensions/asThousands.dart'; import 'package:qubic_wallet/l10n/l10n.dart'; import 'package:qubic_wallet/helpers/target_tick.dart'; -enum CardItem { - details, - resend, - explorer, - clipboardCopy, -} +enum CardItem { details, resend, explorer, clipboardCopy, delete } class TransactionItem extends StatelessWidget { final TransactionVm item; @@ -134,13 +129,17 @@ class TransactionItem extends StatelessWidget { if (menuItem == CardItem.details) { showDetails(context); } + if (menuItem == CardItem.delete) { + appStore.removeIgnoredTransactions(item.id); + } }, itemBuilder: (BuildContext context) => >[ PopupMenuItem( value: CardItem.details, child: Text(l10n.transactionItemButtonViewDetails), ), - if (appStore.currentTick >= item.targetTick) + if (appStore.currentTick >= item.targetTick && + item.getStatus() != ComputedTransactionStatus.invalid) PopupMenuItem( value: CardItem.explorer, child: Text(l10n.transactionItemButtonViewInExplorer), @@ -149,10 +148,18 @@ class TransactionItem extends StatelessWidget { value: CardItem.clipboardCopy, child: Text(l10n.transactionItemButtonCopyToClipboard), ), - if ((item.getStatus() == ComputedTransactionStatus.failure)) + // sally: commenting this temporary until we improve the resend to support all transfers + //if (appStore.currentQubicIDs + // .any((e) => e.publicId == item.sourceId) && + //item.getStatus() != ComputedTransactionStatus.pending) + //PopupMenuItem( + //value: CardItem.resend, + //child: Text(l10n.transactionItemButtonResend), + //), + if (item.getStatus() == ComputedTransactionStatus.invalid) PopupMenuItem( - value: CardItem.resend, - child: Text(l10n.transactionItemButtonResend), + value: CardItem.delete, + child: Text(l10n.generalButtonDelete), ) ]); } diff --git a/lib/di.dart b/lib/di.dart index d822590f..2cec0bee 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -2,6 +2,7 @@ import 'package:get_it/get_it.dart'; import 'package:qubic_wallet/helpers/global_snack_bar.dart'; import 'package:qubic_wallet/resources/apis/archive/qubic_archive_api.dart'; import 'package:qubic_wallet/resources/apis/live/qubic_live_api.dart'; +import 'package:qubic_wallet/resources/hive_storage.dart'; import 'package:qubic_wallet/resources/qubic_cmd.dart'; import 'package:qubic_wallet/resources/qubic_hub.dart'; import 'package:qubic_wallet/resources/qubic_li.dart'; @@ -27,6 +28,7 @@ void setupDI() { getIt.registerSingleton(ExplorerStore()); getIt.registerSingleton(QubicHubStore()); getIt.registerSingleton(SecureStorage()); + getIt.registerSingleton(HiveStorage()); //Providers getIt.registerSingleton(GlobalSnackBar()); diff --git a/lib/helpers/sendTransaction.dart b/lib/helpers/sendTransaction.dart index b2294c81..f939935b 100644 --- a/lib/helpers/sendTransaction.dart +++ b/lib/helpers/sendTransaction.dart @@ -3,9 +3,10 @@ import 'package:qubic_wallet/di.dart'; import 'package:qubic_wallet/helpers/platform_helpers.dart'; import 'package:qubic_wallet/helpers/show_alert_dialog.dart'; import 'package:qubic_wallet/l10n/l10n.dart'; +import 'package:qubic_wallet/models/transaction_vm.dart'; import 'package:qubic_wallet/resources/apis/live/qubic_live_api.dart'; import 'package:qubic_wallet/resources/qubic_cmd.dart'; -import 'package:qubic_wallet/resources/qubic_li.dart'; +import 'package:qubic_wallet/smart_contracts/qx_info.dart'; import 'package:qubic_wallet/stores/application_store.dart'; void showTamperedWalletAlert(BuildContext context) { @@ -39,7 +40,18 @@ Future sendAssetTransferTransactionDialog( try { transactionKey = await qubicCmd.createAssetTransferTransaction(seed, destinationId, assetName, issuer, numberOfAssets, destinationTick); - await getIt.get().submitTransaction(transactionKey); + final transactionId = + await getIt.get().submitTransaction(transactionKey); + final pendingTransaction = TransactionVm( + id: transactionId, + sourceId: sourceId, + destId: destinationId, + amount: QxInfo.transferAssetFee, + status: ComputedTransactionStatus.pending.name, + targetTick: destinationTick, + isPending: true, + moneyFlow: true); + getIt.get().addPendingTransaction(pendingTransaction); return true; } catch (e) { if (e.toString().startsWith("Exception: CRITICAL:")) { @@ -80,7 +92,18 @@ Future sendTransactionDialog(BuildContext context, String sourceId, //We have the transaction, now let's call the API try { - await getIt.get().submitTransaction(transactionKey); + final transactionId = + await getIt.get().submitTransaction(transactionKey); + final pendingTransaction = TransactionVm( + id: transactionId, + sourceId: sourceId, + destId: destinationId, + amount: value, + status: ComputedTransactionStatus.pending.name, + targetTick: destinationTick, + isPending: true, + moneyFlow: value > 0); + getIt.get().addPendingTransaction(pendingTransaction); } catch (e) { showAlertDialog( context, l10n.sendItemDialogErrorGeneralTitle, e.toString()); diff --git a/lib/helpers/transaction_UI_helpers.dart b/lib/helpers/transaction_UI_helpers.dart index f156ee1c..ab29047e 100644 --- a/lib/helpers/transaction_UI_helpers.dart +++ b/lib/helpers/transaction_UI_helpers.dart @@ -70,8 +70,6 @@ Widget getEmptyTransactionsWidget( IconData getTransactionStatusIcon(ComputedTransactionStatus status) { switch (status) { - case ComputedTransactionStatus.confirmed: - return Icons.check_circle; case ComputedTransactionStatus.failure: return Icons.highlight_remove_outlined; case ComputedTransactionStatus.invalid: @@ -85,8 +83,6 @@ IconData getTransactionStatusIcon(ComputedTransactionStatus status) { Color getTransactionStatusColor(ComputedTransactionStatus status) { switch (status) { - case ComputedTransactionStatus.confirmed: - return Colors.blue; case ComputedTransactionStatus.failure: return LightThemeColors.error; case ComputedTransactionStatus.invalid: @@ -102,8 +98,6 @@ String getTransactionStatusText( ComputedTransactionStatus status, BuildContext context) { final l10n = l10nOf(context); switch (status) { - case ComputedTransactionStatus.confirmed: - return l10n.transactionLabelStatusConfirmed; case ComputedTransactionStatus.failure: return l10n.transactionLabelStatusFailed; case ComputedTransactionStatus.invalid: diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 7f0e6fbf..c2601ef5 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -188,7 +188,7 @@ "explorerTickResultLabelTickLeader": "Tick-Leader", "explorerTickResultLabelNoTransactionsFound": "Keine Transaktionen in diesem Tick", "explorerTickResultLabelTransactionsFound": "{count, plural, =1{1 Transaktion im Tick} other{{count} Transaktionen im Tick}}", - "explorerTickResultLabelShowingOneTransaction": "{count, plural, =1{Zeigt 1 von 1 Transaktion im Tick} other{Zeigt 1 von {count} Transaktionen im Tick}}}", + "explorerTickResultLabelShowingOneTransaction": "{count, plural, =1{Zeigt 1 von 1 Transaktion im Tick} other{Zeigt 1 von {count} Transaktionen im Tick}}", "settingsTitle": "Einstellungen", "settingsHeaderAccountsAndData": "Konten und Daten", "settingsLockWallet": "Wallet sperren", @@ -398,9 +398,7 @@ "transactionItemButtonViewDetails": "Details anzeigen", "transactionItemButtonResend": "Erneut senden", "transactionItemLabelLeadToMoneyFlow": "Führen zu Geldfluss", - "transactionItemLabelCreatedDate": "Erstellungsdatum", - "transactionItemLabelBroadcastedDate": "Sendedatum", - "transactionItemLabelConfirmedDate": "Bestätigungsdatum", + "transactionItemLabelConfirmedDate": "Zeitstempel", "transactionItemLabelDetails": "Überweisungsdetails", "sendItemLabelTargetTick": "Ziel-Tick", "sendItemLabelTargetTickAutomatic": "Automatisch: Aktuell + {addingTicks}", @@ -414,7 +412,7 @@ "sendItemLabelTargetTickManual": "Manuelles Überschreiben", "sendItemLabelDetermineTargetTick": "Ziel-Tick bestimmen", "sendItemDialogErrorGeneralTitle": "Fehler beim Generieren der Transaktion.", - "sendItemDialogResendTitle": "Fehlgeschlagene Transaktion erneut senden?", + "sendItemDialogResendTitle": "Transaktion erneut senden?", "sendItemLabelResendTargetTickValue": "{formattedTargetTick} (aktuell {formattedCurrentTick})", "@sendItemLabelResendTargetTickValue": { "placeholders": { diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 7b551ce0..4e805846 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -196,7 +196,7 @@ "explorerTickResultLabelTickLeader": "Tick Leader", "explorerTickResultLabelNoTransactionsFound": "No transactions in this tick", "explorerTickResultLabelTransactionsFound": "{count, plural, =1{1 transaction in tick} other{{count} transactions in tick}}", - "explorerTickResultLabelShowingOneTransaction": "{count, plural, =1{Showing 1 of 1 transaction in tick} other{Showing 1 of {count} transactions in tick}}}", + "explorerTickResultLabelShowingOneTransaction": "{count, plural, =1{Showing 1 of 1 transaction in tick} other{Showing 1 of {count} transactions in tick}}", "settingsTitle": "Settings", "settingsHeaderAccountsAndData": "Accounts and Data", "settingsLockWallet": "Lock Wallet", @@ -408,9 +408,7 @@ "transactionItemButtonViewDetails": "View Details", "transactionItemButtonResend": "Resend", "transactionItemLabelLeadToMoneyFlow": "Lead to Money Flow", - "transactionItemLabelCreatedDate": "Created Date", - "transactionItemLabelBroadcastedDate": "Broadcasted Date", - "transactionItemLabelConfirmedDate": "Confirmed Date", + "transactionItemLabelConfirmedDate": "Timestamp", "transactionItemLabelDetails": "Transfer Details", "sendItemLabelTargetTick": "Target Tick", "sendItemLabelTargetTickAutomatic": "Automatically: Current + {addingTicks}", @@ -424,7 +422,7 @@ "sendItemLabelTargetTickManual": "Manual Override", "sendItemLabelDetermineTargetTick": "Determine Target Tick", "sendItemDialogErrorGeneralTitle": "Error while generating transaction", - "sendItemDialogResendTitle": "Resend failed transaction?", + "sendItemDialogResendTitle": "Resend transaction?", "sendItemLabelResendTargetTickValue": "{formattedTargetTick} (current {formattedCurrentTick})", "@sendItemLabelResendTargetTickValue": { "placeholders": { @@ -608,7 +606,7 @@ } } }, - "generalAllTransactionDetails": "ID: {trxId}\nSource: {sourceId}\nDestination: {destId}\nAmount: {amount}\nStatus: {status}\nCreated: {created}\nStored: {stored}\nStaged: {staged}\nBroadcasted: {broadcasted}\nConfirmed: {confirmed}\nStatusUpdate: {statusUpdate}\nTarget Tick: {targetTick}\nIs Pending: {isPending}\nPrice: {price} \nQuantity: {quantity}\nMoney Flow: {moneyFlow}", + "generalAllTransactionDetails": "Transaction ID: {trxId}\nSource: {sourceId}\nDestination: {destId}\nAmount: {amount}\nStatus: {status}\nTimestamp: {confirmed}\nTick: {targetTick}", "@generalAllTransactionDetails": { "description": "This contains the string that will be copied to the clipboard containing all the transaction details ", "placeholders": { diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index a56684ae..c99dc3e4 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -397,9 +397,7 @@ "transactionItemButtonViewDetails": "Ver Detalles", "transactionItemButtonResend": "Reenviar", "transactionItemLabelLeadToMoneyFlow": "Conduce a un Flujo de Dinero", - "transactionItemLabelCreatedDate": "Fecha de Creación", - "transactionItemLabelBroadcastedDate": "Fecha de Transmisión", - "transactionItemLabelConfirmedDate": "Fecha de Confirmación", + "transactionItemLabelConfirmedDate": "Fecha y hora", "transactionItemLabelDetails": "Detalles de la Transferencia", "sendItemLabelTargetTick": "Tick de Ejecución", "sendItemLabelTargetTickAutomatic": "Automáticamente: Actual + {addingTicks}", @@ -413,7 +411,7 @@ "sendItemLabelTargetTickManual": "Sobreescribir manualmente", "sendItemLabelDetermineTargetTick": "Determinar el Target de Ejecución", "sendItemDialogErrorGeneralTitle": "Error al generar la transacción", - "sendItemDialogResendTitle": "¿Deseas reenviar la transacción fallida?", + "sendItemDialogResendTitle": "¿Deseas reenviar la transacción?", "sendItemLabelResendTargetTickValue": "{formattedTargetTick} (actual {formattedCurrentTick})", "@sendItemLabelResendTargetTickValue": { "placeholders": { diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index e9b5bbe1..fd9377b3 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -398,9 +398,7 @@ "transactionItemButtonViewDetails": "Voir les Détails", "transactionItemButtonResend": "Renvoyer", "transactionItemLabelLeadToMoneyFlow": "Conduit à un Flux Monétaire", - "transactionItemLabelCreatedDate": "Date de Création", - "transactionItemLabelBroadcastedDate": "Date de Diffusion", - "transactionItemLabelConfirmedDate": "Date de Confirmation", + "transactionItemLabelConfirmedDate": "Horodatage", "transactionItemLabelDetails": "Détails du Transfert", "sendItemLabelTargetTick": "Tick Cible", "sendItemLabelTargetTickAutomatic": "Automatiquement: Actuel + {addingTicks}", @@ -414,7 +412,7 @@ "sendItemLabelTargetTickManual": "Remplacement Manuel", "sendItemLabelDetermineTargetTick": "Déterminer le Tick Cible", "sendItemDialogErrorGeneralTitle": "Erreur lors de la génération de la transaction", - "sendItemDialogResendTitle": "Renvoyer la transaction échouée?", + "sendItemDialogResendTitle": "Renvoyer la transaction?", "sendItemLabelResendTargetTickValue": "{formattedTargetTick} (actuel {formattedCurrentTick})", "@sendItemLabelResendTargetTickValue": { "placeholders": { diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index aca518cb..d0a31cb7 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -397,9 +397,7 @@ "transactionItemButtonViewDetails": "Детали", "transactionItemButtonResend": "Переслать", "transactionItemLabelLeadToMoneyFlow": "Lead to Money Flow", - "transactionItemLabelCreatedDate": "Создать дату", - "transactionItemLabelBroadcastedDate": "Дата выхода", - "transactionItemLabelConfirmedDate": "Дата подтверждения", + "transactionItemLabelConfirmedDate": "Метка времени", "transactionItemLabelDetails": "Детали транзакции", "sendItemLabelTargetTick": "На каком тике", "sendItemLabelTargetTickAutomatic": "Автоматически: этот тик + {addingTicks}", @@ -413,7 +411,7 @@ "sendItemLabelTargetTickManual": "Ручное управление", "sendItemLabelDetermineTargetTick": "Определите целевой тик", "sendItemDialogErrorGeneralTitle": "Ошибка при генерации транзакции", - "sendItemDialogResendTitle": "Повторно отправить неудачную транзакцию?", + "sendItemDialogResendTitle": "Повторно отправить транзакцию?", "sendItemLabelResendTargetTickValue": "{formattedTargetTick} (current {formattedCurrentTick})", "@sendItemLabelResendTargetTickValue": { "placeholders": { diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 62f8f195..10858c97 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -397,9 +397,7 @@ "transactionItemButtonViewDetails": "Detayları Göster", "transactionItemButtonResend": "Yeniden Gönder", "transactionItemLabelLeadToMoneyFlow": "Para Akışını Yönlendir", - "transactionItemLabelCreatedDate": "Oluşturulma Tarihi", - "transactionItemLabelBroadcastedDate": "Yayınlanma Tarihi", - "transactionItemLabelConfirmedDate": "Onaylanma Tarihi", + "transactionItemLabelConfirmedDate": "Zaman damgası", "transactionItemLabelDetails": "Transfer Detayları", "sendItemLabelTargetTick": "Hedef Tick", "sendItemLabelTargetTickAutomatic": "Otomatik olarak: Mevcut + {addingTicks}", @@ -413,7 +411,7 @@ "sendItemLabelTargetTickManual": "Manuel Geçersiz Kılma", "sendItemLabelDetermineTargetTick": "Hedef Tick'i Belirle", "sendItemDialogErrorGeneralTitle": "Transfer oluşturulurken bir hata oluştu", - "sendItemDialogResendTitle": "Başarısız olan işlem yeniden gönderilsin mi?", + "sendItemDialogResendTitle": "Işlem yeniden gönderilsin mi?", "sendItemLabelResendTargetTickValue": "{formattedTargetTick} (current {formattedCurrentTick})", "@sendItemLabelResendTargetTickValue": { "placeholders": { diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index bd5c2b1d..4f967055 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -398,9 +398,7 @@ "transactionItemButtonViewDetails": "查看详情", "transactionItemButtonResend": "重新发送", "transactionItemLabelLeadToMoneyFlow": "Lead to Money Flow", - "transactionItemLabelCreatedDate": "创建日期", - "transactionItemLabelBroadcastedDate": "广播日期", - "transactionItemLabelConfirmedDate": "确认日期", + "transactionItemLabelConfirmedDate": "时间戳", "transactionItemLabelDetails": "转账详情", "sendItemLabelTargetTick": "目标刻度", "sendItemLabelTargetTickAutomatic": "自动:当前刻度 + {addingTicks}", @@ -414,7 +412,7 @@ "sendItemLabelTargetTickManual": "手动调整", "sendItemLabelDetermineTargetTick": "确定目标刻度", "sendItemDialogErrorGeneralTitle": "生成交易时出现错误", - "sendItemDialogResendTitle": "重新发送失败的交易?", + "sendItemDialogResendTitle": "重新发送交易?", "sendItemLabelResendTargetTickValue": "{formattedTargetTick} (当前 {formattedCurrentTick})", "@sendItemLabelResendTargetTickValue": { "placeholders": { diff --git a/lib/models/transaction_vm.dart b/lib/models/transaction_vm.dart index a10106c2..b4c21e4b 100644 --- a/lib/models/transaction_vm.dart +++ b/lib/models/transaction_vm.dart @@ -1,20 +1,20 @@ import 'dart:core'; import 'package:flutter/material.dart'; +import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:qubic_wallet/dtos/transaction_dto.dart'; +import 'package:qubic_wallet/extensions/asThousands.dart'; import 'package:qubic_wallet/l10n/l10n.dart'; enum ComputedTransactionStatus { //** Transfer is broadcasted but pending */ pending, - //** Transfer is confirmed */ - confirmed, //** Transfer is successful (processed by computors) */ success, //** Transfer has failed */ failure, - //** Transfer is invalid (may be successful but invalidated) */ + //** Transfer is invalid (ignored by network) */ invalid, } @@ -69,39 +69,36 @@ class TransactionVm { bool moneyFlow; TransactionVm( - this.id, - this.sourceId, - this.destId, - this.amount, - this.status, + {required this.id, + required this.sourceId, + required this.destId, + required this.amount, + required this.status, this.created, this.stored, this.staged, this.broadcasted, this.confirmed, this.statusUpdate, - this.targetTick, - this.isPending, + required this.targetTick, + required this.isPending, this.price, this.quantity, - this.moneyFlow); + required this.moneyFlow}); ComputedTransactionStatus getStatus() { if (isPending) { return ComputedTransactionStatus.pending; } - if ((status == 'Confirmed') || (status == 'Staged')) { - return ComputedTransactionStatus.confirmed; - } if ((status == 'Success')) { if (moneyFlow == true) { return ComputedTransactionStatus.success; } else { - return ComputedTransactionStatus.invalid; + return ComputedTransactionStatus.failure; } } - if ((status == 'Failed')) { - return ComputedTransactionStatus.failure; + if ((status == 'Invalid')) { + return ComputedTransactionStatus.invalid; } return ComputedTransactionStatus.pending; } @@ -112,7 +109,7 @@ class TransactionVm { id, sourceId, destId, - amount.toString(), + amount.asThousands(), status, created.toString(), stored.toString(), @@ -157,21 +154,51 @@ class TransactionVm { factory TransactionVm.fromTransactionDto(TransactionDto original) { return TransactionVm( - original.id, - original.sourceId, - original.destId, - original.amount, - original.status, - original.created, - original.stored, - original.staged, - original.broadcasted, - original.confirmed, - original.statusUpdate, - original.targetTick, - original.isPending, - original.price, - original.quantity, - original.moneyFlow); + id: original.id, + sourceId: original.sourceId, + destId: original.destId, + amount: original.amount, + status: original.status, + created: original.created, + stored: original.stored, + staged: original.staged, + broadcasted: original.broadcasted, + confirmed: original.confirmed, + statusUpdate: original.statusUpdate, + targetTick: original.targetTick, + isPending: original.isPending, + price: original.price, + quantity: original.quantity, + moneyFlow: original.moneyFlow); + } +} + +class TransactionVmAdapter extends TypeAdapter { + @override + TransactionVm read(BinaryReader reader) { + return TransactionVm( + id: reader.readString(), + sourceId: reader.readString(), + destId: reader.readString(), + amount: reader.readInt(), + status: reader.readString(), + targetTick: reader.readInt(), + isPending: reader.readBool(), + moneyFlow: reader.readBool()); + } + + @override + int get typeId => 0; + + @override + void write(BinaryWriter writer, TransactionVm obj) { + writer.writeString(obj.id); + writer.writeString(obj.sourceId); + writer.writeString(obj.destId); + writer.writeInt(obj.amount); + writer.writeString(obj.status); + writer.writeInt(obj.targetTick); + writer.writeBool(obj.isPending); + writer.writeBool(obj.moneyFlow); } } diff --git a/lib/pages/auth/sign_in.dart b/lib/pages/auth/sign_in.dart index e9f04ef6..2a1028f5 100644 --- a/lib/pages/auth/sign_in.dart +++ b/lib/pages/auth/sign_in.dart @@ -16,6 +16,7 @@ import 'package:qubic_wallet/pages/auth/erase_wallet_sheet.dart'; import 'package:qubic_wallet/pages/auth/import_selector.dart'; import 'package:qubic_wallet/pages/auth/sign_up.dart'; import 'package:qubic_wallet/pages/main/download_cmd_utils.dart'; +import 'package:qubic_wallet/resources/hive_storage.dart'; import 'package:qubic_wallet/resources/qubic_li.dart'; import 'package:qubic_wallet/resources/secure_storage.dart'; import 'package:qubic_wallet/stores/application_store.dart'; @@ -44,6 +45,7 @@ class _SignInState extends State final LocalAuthentication _auth = LocalAuthentication(); final ApplicationStore _appStore = getIt(); final SettingsStore _settingsStore = getIt(); + final HiveStorage _hiveStorage = getIt(); final QubicHubStore _qubicHubStore = getIt(); final TimedController _timedController = getIt(); final SecureStorage _secureStorage = getIt(); @@ -342,6 +344,7 @@ class _SignInState extends State child: EraseWalletSheet(onAccept: () async { await _secureStorage.deleteWallet(); await _settingsStore.loadSettings(); + await _hiveStorage.clear(); _appStore.checkWalletIsInitialized(); _appStore.signOut(); _timedController.stopFetchTimers(); diff --git a/lib/pages/main/main_screen.dart b/lib/pages/main/main_screen.dart index df7d82cc..755ee13a 100644 --- a/lib/pages/main/main_screen.dart +++ b/lib/pages/main/main_screen.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:developer'; import 'package:animated_snack_bar/animated_snack_bar.dart'; import 'package:flutter/material.dart'; @@ -11,11 +10,13 @@ import 'package:qubic_wallet/components/change_foreground.dart'; import 'package:qubic_wallet/config.dart'; import 'package:qubic_wallet/di.dart'; import 'package:qubic_wallet/flutter_flow/theme_paddings.dart'; +import 'package:qubic_wallet/l10n/l10n.dart'; import 'package:qubic_wallet/pages/main/download_cmd_utils.dart'; import 'package:qubic_wallet/pages/main/tab_explorer.dart'; import 'package:qubic_wallet/pages/main/tab_settings/tab_settings.dart'; import 'package:qubic_wallet/pages/main/tab_transfers.dart'; import 'package:qubic_wallet/pages/main/tab_wallet_contents.dart'; +import 'package:qubic_wallet/pages/main/wallet_contents/add_account_modal_bottom_sheet.dart'; import 'package:qubic_wallet/resources/qubic_cmd.dart'; import 'package:qubic_wallet/stores/application_store.dart'; import 'package:qubic_wallet/stores/qubic_hub_store.dart'; @@ -23,8 +24,6 @@ import 'package:qubic_wallet/stores/settings_store.dart'; import 'package:qubic_wallet/styles/text_styles.dart'; import 'package:qubic_wallet/timed_controller.dart'; import 'package:universal_platform/universal_platform.dart'; -import 'package:qubic_wallet/l10n/l10n.dart'; -import 'package:qubic_wallet/pages/main/wallet_contents/add_account_modal_bottom_sheet.dart'; class MainScreen extends StatefulWidget { final int initialTabIndex; @@ -173,6 +172,7 @@ class _MainScreenState extends State with WidgetsBindingObserver { } } }); + getIt().initPendingAndIgonredTransactions(); } @override diff --git a/lib/pages/main/tab_settings/components/erase_wallet_data_button.dart b/lib/pages/main/tab_settings/components/erase_wallet_data_button.dart index 9574743e..f6a5642b 100644 --- a/lib/pages/main/tab_settings/components/erase_wallet_data_button.dart +++ b/lib/pages/main/tab_settings/components/erase_wallet_data_button.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:local_auth/local_auth.dart'; import 'package:qubic_wallet/di.dart'; import 'package:qubic_wallet/flutter_flow/theme_paddings.dart'; import 'package:qubic_wallet/helpers/global_snack_bar.dart'; import 'package:qubic_wallet/l10n/l10n.dart'; import 'package:qubic_wallet/pages/auth/erase_wallet_sheet.dart'; +import 'package:qubic_wallet/resources/hive_storage.dart'; import 'package:qubic_wallet/resources/secure_storage.dart'; import 'package:qubic_wallet/stores/application_store.dart'; -import 'package:qubic_wallet/stores/qubic_hub_store.dart'; import 'package:qubic_wallet/stores/settings_store.dart'; import 'package:qubic_wallet/styles/text_styles.dart'; import 'package:qubic_wallet/styles/themed_controls.dart'; @@ -17,6 +16,7 @@ import 'package:qubic_wallet/timed_controller.dart'; class EraseWalletDataButton extends StatelessWidget { final ApplicationStore appStore = getIt(); final SettingsStore settingsStore = getIt(); + final HiveStorage _hiveStorage = getIt(); final SecureStorage secureStorage = getIt(); final _globalSnackBar = getIt(); final TimedController timedController = getIt(); @@ -44,6 +44,7 @@ class EraseWalletDataButton extends StatelessWidget { if (!context.mounted) return; await secureStorage.deleteWallet(); await settingsStore.loadSettings(); + await _hiveStorage.clear(); appStore.checkWalletIsInitialized(); appStore.signOut(); timedController.stopFetchTimers(); diff --git a/lib/pages/main/wallet_contents/transfer_asset.dart b/lib/pages/main/wallet_contents/transfer_asset.dart index c4a7ebb3..049aa1a9 100644 --- a/lib/pages/main/wallet_contents/transfer_asset.dart +++ b/lib/pages/main/wallet_contents/transfer_asset.dart @@ -1,36 +1,34 @@ -import 'dart:async'; - import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_multi_formatter/flutter_multi_formatter.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:intl/intl.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart'; import 'package:qubic_wallet/components/id_list_item_select.dart'; import 'package:qubic_wallet/di.dart'; import 'package:qubic_wallet/dtos/qubic_asset_dto.dart'; import 'package:qubic_wallet/extensions/asThousands.dart'; import 'package:qubic_wallet/flutter_flow/theme_paddings.dart'; +import 'package:qubic_wallet/helpers/global_snack_bar.dart'; import 'package:qubic_wallet/helpers/id_validators.dart'; import 'package:qubic_wallet/helpers/platform_helpers.dart'; import 'package:qubic_wallet/helpers/re_auth_dialog.dart'; import 'package:qubic_wallet/helpers/sendTransaction.dart'; -import 'package:qubic_wallet/helpers/global_snack_bar.dart'; +import 'package:qubic_wallet/helpers/target_tick.dart'; +import 'package:qubic_wallet/l10n/l10n.dart'; import 'package:qubic_wallet/models/qubic_list_vm.dart'; -import 'package:qubic_wallet/resources/apis/archive/qubic_archive_api.dart'; import 'package:qubic_wallet/resources/apis/live/qubic_live_api.dart'; import 'package:qubic_wallet/resources/qubic_cmd.dart'; import 'package:qubic_wallet/resources/qubic_li.dart'; +import 'package:qubic_wallet/smart_contracts/qx_info.dart'; import 'package:qubic_wallet/stores/application_store.dart'; -import 'package:mobile_scanner/mobile_scanner.dart'; -import 'package:intl/intl.dart'; import 'package:qubic_wallet/styles/edge_insets.dart'; import 'package:qubic_wallet/styles/input_decorations.dart'; import 'package:qubic_wallet/styles/text_styles.dart'; import 'package:qubic_wallet/styles/themed_controls.dart'; import 'package:qubic_wallet/timed_controller.dart'; -import 'package:qubic_wallet/l10n/l10n.dart'; -import 'package:qubic_wallet/helpers/target_tick.dart'; class TransferAsset extends StatefulWidget { final QubicListVm item; @@ -487,7 +485,8 @@ class _TransferAssetState extends State { style: TextStyles.labelTextNormal), ThemedControls.spacerVerticalMini(), ThemedControls.inputboxlikeLabel( - child: Text("1,000,000 ${l10n.generalLabelCurrencyQubic}", + child: Text( + "${QxInfo.transferAssetFee.asThousands()} ${l10n.generalLabelCurrencyQubic}", textAlign: TextAlign.center, style: TextStyles.inputBoxNormalStyle .copyWith(fontWeight: FontWeight.w500))), diff --git a/lib/pages/main/wallet_contents/transfers/filter_transactions.dart b/lib/pages/main/wallet_contents/transfers/filter_transactions.dart index 6b582daa..697aade3 100644 --- a/lib/pages/main/wallet_contents/transfers/filter_transactions.dart +++ b/lib/pages/main/wallet_contents/transfers/filter_transactions.dart @@ -177,7 +177,6 @@ class _FilterTransactionsState extends State { List statusOptions = [ null, ComputedTransactionStatus.pending, - ComputedTransactionStatus.confirmed, ComputedTransactionStatus.success, ComputedTransactionStatus.failure, ComputedTransactionStatus.invalid, diff --git a/lib/resources/apis/live/qubic_live_api.dart b/lib/resources/apis/live/qubic_live_api.dart index bbefd373..e313fa57 100644 --- a/lib/resources/apis/live/qubic_live_api.dart +++ b/lib/resources/apis/live/qubic_live_api.dart @@ -23,12 +23,12 @@ class QubicLiveApi { } } - Future submitTransaction(String transaction) async { + Future submitTransaction(String transaction) async { try { _appStore.incrementPendingRequests(); - await _dio.post('$_baseUrl${Config.submitTransaction}', + final response = await _dio.post('$_baseUrl${Config.submitTransaction}', data: {"encodedTransaction": transaction}); - return; + return response.data["transactionId"]; } catch (error) { throw ErrorHandler.handleError(error); } finally { diff --git a/lib/resources/hive_storage.dart b/lib/resources/hive_storage.dart new file mode 100644 index 00000000..f2fa0e7a --- /dev/null +++ b/lib/resources/hive_storage.dart @@ -0,0 +1,59 @@ +import 'dart:developer'; + +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:qubic_wallet/models/transaction_vm.dart'; + +enum HiveBoxesNames { + pendingTransactions, + ignoredTransactions, +} + +class HiveStorage { + HiveStorage() { + _init(); + } + late final Box pendingTransactions; + late final Box ignoredTransactions; + + Future _init() async { + await Hive.initFlutter(); + Hive.registerAdapter(TransactionVmAdapter()); + openTransactionBoxes(); + } + + Future openTransactionBoxes() async { + pendingTransactions = await Hive.openBox( + HiveBoxesNames.pendingTransactions.name); + ignoredTransactions = await Hive.openBox( + HiveBoxesNames.ignoredTransactions.name); + } + + void addPendingTransaction(TransactionVm transactionVm) { + pendingTransactions.put(transactionVm.id, transactionVm); + } + + void removePendingTransaction(String transactionId) { + pendingTransactions.delete(transactionId); + } + + List getPendingTransactions() { + return pendingTransactions.values.toList(); + } + + void addIgnoredTransaction(TransactionVm transactionVm) { + ignoredTransactions.put(transactionVm.id, transactionVm); + } + + void removeIgnoredTransaction(String transactionId) { + ignoredTransactions.delete(transactionId); + } + + List getIgnoredTransactions() { + return ignoredTransactions.values.toList(); + } + + Future clear() async { + await ignoredTransactions.clear(); + await pendingTransactions.clear(); + } +} diff --git a/lib/resources/secure_storage.dart b/lib/resources/secure_storage.dart index 679ac8f9..48d1c43f 100644 --- a/lib/resources/secure_storage.dart +++ b/lib/resources/secure_storage.dart @@ -7,6 +7,7 @@ import 'package:qubic_wallet/models/critical_settings.dart'; import 'package:qubic_wallet/models/qubic_id.dart'; import 'package:qubic_wallet/models/qubic_list_vm.dart'; import 'package:qubic_wallet/models/settings.dart'; +import 'package:qubic_wallet/models/transaction_vm.dart'; class SecureStorageKeys { static const prepend = kReleaseMode @@ -228,9 +229,8 @@ class SecureStorage { CriticalSettings settings = await getCriticalSettings(); List list = []; for (int i = 0; i < settings.publicIds.length; i++) { - list.add(QubicListVm( - settings.publicIds[i], settings.names[i], null, null, null, - settings.isWatchOnly[i])); + list.add(QubicListVm(settings.publicIds[i], settings.names[i], null, null, + null, settings.isWatchOnly[i])); } return list; } @@ -289,7 +289,7 @@ class SecureStorage { throw Exception("ID not found"); } return QubicId(settings.privateSeeds[i], settings.publicIds[i], - settings.names[i], null); + settings.names[i], null); } //Removes a Qubic ID from the secure Storage (Based on its public key) diff --git a/lib/stores/application_store.dart b/lib/stores/application_store.dart index 93229cfa..f8594723 100644 --- a/lib/stores/application_store.dart +++ b/lib/stores/application_store.dart @@ -10,6 +10,7 @@ import 'package:qubic_wallet/models/qubic_id.dart'; import 'package:qubic_wallet/models/qubic_list_vm.dart'; import 'package:qubic_wallet/models/transaction_filter.dart'; import 'package:qubic_wallet/models/transaction_vm.dart'; +import 'package:qubic_wallet/resources/hive_storage.dart'; import 'package:qubic_wallet/resources/secure_storage.dart'; // ignore: depend_on_referenced_packages import 'package:collection/collection.dart'; @@ -21,6 +22,7 @@ class ApplicationStore = _ApplicationStore with _$ApplicationStore; abstract class _ApplicationStore with Store { late final SecureStorage secureStorage = getIt(); + late final HiveStorage _hiveStorage = getIt(); /// If there are stored wallet settings in the device @observable @@ -72,7 +74,12 @@ abstract class _ApplicationStore with Store { @observable ObservableList currentTransactions = ObservableList(); - + @observable + ObservableList ignoredTransactions = + ObservableList(); + @observable + ObservableList pendingTransactions = + ObservableList(); @observable TransactionFilter? transactionFilter = TransactionFilter(); @@ -89,8 +96,10 @@ abstract class _ApplicationStore with Store { @computed double get totalAmountsInUSD { if (marketInfo == null) return -1; - return currentQubicIDs.where((qubic) => !qubic.watchOnly).fold(0, - (sum, qubic) => sum + (qubic.amount ?? 0) * marketInfo!.price!.toDouble()); + return currentQubicIDs.where((qubic) => !qubic.watchOnly).fold( + 0, + (sum, qubic) => + sum + (qubic.amount ?? 0) * marketInfo!.price!.toDouble()); } //The market info for $QUBIC @@ -232,6 +241,7 @@ abstract class _ApplicationStore with Store { @action Future signUp(String password) async { await secureStorage.deleteWallet(); + await _hiveStorage.clear(); final result = await secureStorage.createWallet(password); isSignedIn = result; currentQubicIDs = ObservableList(); @@ -356,19 +366,73 @@ abstract class _ApplicationStore with Store { @action Future updateTransactions(List transactions) async { - for (var i = 0; i < transactions.length; i++) { - var currentIndex = currentTransactions - .indexWhere((element) => element.id == transactions[i].id); - if (currentIndex == -1) { - currentTransactions - .add(TransactionVm.fromTransactionDto(transactions[i])); + _addOrUpdateCurrentTransactions(transactions); + _restoreIgnoredTransactions(); + _restorePendingTransaction(); + } + + @action + initPendingAndIgonredTransactions() { + pendingTransactions.addAll(_hiveStorage.getPendingTransactions()); + ignoredTransactions.addAll(_hiveStorage.getIgnoredTransactions()); + } + + void _addOrUpdateCurrentTransactions(List transactions) { + for (var transaction in transactions) { + var index = currentTransactions + .indexWhere((element) => element.id == transaction.id); + var transactionVm = TransactionVm.fromTransactionDto(transaction); + if (index == -1) { + currentTransactions.add(transactionVm); } else { - currentTransactions[currentIndex] = - TransactionVm.fromTransactionDto(transactions[i]); + currentTransactions[index] = transactionVm; } } } + @action + void _restoreIgnoredTransactions() { + _addTransactionInOrder(ignoredTransactions); + } + + @action + void removeIgnoredTransactions(String transactionId) { + _hiveStorage.removeIgnoredTransaction(transactionId); + ignoredTransactions.removeWhere((element) => element.id == transactionId); + currentTransactions.removeWhere((element) => element.id == transactionId); + } + + @action + void _restorePendingTransaction() { + _addTransactionInOrder(pendingTransactions); + } + + @action + addPendingTransaction(TransactionVm transaction) { + _hiveStorage.addPendingTransaction(transaction); + pendingTransactions.add(transaction); + } + + @action + validatePendingTransactions(int currentTick) { + pendingTransactions.removeWhere((trx) { + if (currentTick > trx.targetTick) { + addIgnoredTransaction(trx); + _hiveStorage.removePendingTransaction(trx.id); + return true; + } + return false; + }); + } + + @action + addIgnoredTransaction(TransactionVm pendingTransaction) { + pendingTransaction.isPending = false; + pendingTransaction.status = "Invalid"; + _hiveStorage.addIgnoredTransaction(pendingTransaction); + ignoredTransactions.add(pendingTransaction); + } + int getQubicIDsWithPublicId(String publicId) { return currentQubicIDs .where((element) => element.publicId == publicId.replaceAll(",", "_")) @@ -394,4 +458,20 @@ abstract class _ApplicationStore with Store { (el) => el.publicId == element.destId.replaceAll(",", "_")) == false); } + + @action + void _addTransactionInOrder(List transactions) { + for (var trx in transactions) { + if (!currentTransactions.any((element) => element.id == trx.id)) { + int insertIndex = currentTransactions.indexWhere( + (element) => element.targetTick > trx.targetTick, + ); + if (insertIndex == -1) { + currentTransactions.add(trx); + } else { + currentTransactions.insert(insertIndex, trx); + } + } + } + } } diff --git a/lib/stores/application_store.g.dart b/lib/stores/application_store.g.dart index 2215cf14..7b2e2063 100644 --- a/lib/stores/application_store.g.dart +++ b/lib/stores/application_store.g.dart @@ -176,6 +176,38 @@ mixin _$ApplicationStore on _ApplicationStore, Store { }); } + late final _$ignoredTransactionsAtom = + Atom(name: '_ApplicationStore.ignoredTransactions', context: context); + + @override + ObservableList get ignoredTransactions { + _$ignoredTransactionsAtom.reportRead(); + return super.ignoredTransactions; + } + + @override + set ignoredTransactions(ObservableList value) { + _$ignoredTransactionsAtom.reportWrite(value, super.ignoredTransactions, () { + super.ignoredTransactions = value; + }); + } + + late final _$pendingTransactionsAtom = + Atom(name: '_ApplicationStore.pendingTransactions', context: context); + + @override + ObservableList get pendingTransactions { + _$pendingTransactionsAtom.reportRead(); + return super.pendingTransactions; + } + + @override + set pendingTransactions(ObservableList value) { + _$pendingTransactionsAtom.reportWrite(value, super.pendingTransactions, () { + super.pendingTransactions = value; + }); + } + late final _$transactionFilterAtom = Atom(name: '_ApplicationStore.transactionFilter', context: context); @@ -465,6 +497,94 @@ mixin _$ApplicationStore on _ApplicationStore, Store { } } + @override + dynamic initPendingAndIgonredTransactions() { + final _$actionInfo = _$_ApplicationStoreActionController.startAction( + name: '_ApplicationStore.initPendingAndIgonredTransactions'); + try { + return super.initPendingAndIgonredTransactions(); + } finally { + _$_ApplicationStoreActionController.endAction(_$actionInfo); + } + } + + @override + void _restoreIgnoredTransactions() { + final _$actionInfo = _$_ApplicationStoreActionController.startAction( + name: '_ApplicationStore._restoreIgnoredTransactions'); + try { + return super._restoreIgnoredTransactions(); + } finally { + _$_ApplicationStoreActionController.endAction(_$actionInfo); + } + } + + @override + void removeIgnoredTransactions(String transactionId) { + final _$actionInfo = _$_ApplicationStoreActionController.startAction( + name: '_ApplicationStore.removeIgnoredTransactions'); + try { + return super.removeIgnoredTransactions(transactionId); + } finally { + _$_ApplicationStoreActionController.endAction(_$actionInfo); + } + } + + @override + void _restorePendingTransaction() { + final _$actionInfo = _$_ApplicationStoreActionController.startAction( + name: '_ApplicationStore._restorePendingTransaction'); + try { + return super._restorePendingTransaction(); + } finally { + _$_ApplicationStoreActionController.endAction(_$actionInfo); + } + } + + @override + dynamic addPendingTransaction(TransactionVm transaction) { + final _$actionInfo = _$_ApplicationStoreActionController.startAction( + name: '_ApplicationStore.addPendingTransaction'); + try { + return super.addPendingTransaction(transaction); + } finally { + _$_ApplicationStoreActionController.endAction(_$actionInfo); + } + } + + @override + dynamic validatePendingTransactions(int currentTick) { + final _$actionInfo = _$_ApplicationStoreActionController.startAction( + name: '_ApplicationStore.validatePendingTransactions'); + try { + return super.validatePendingTransactions(currentTick); + } finally { + _$_ApplicationStoreActionController.endAction(_$actionInfo); + } + } + + @override + dynamic addIgnoredTransaction(TransactionVm pendingTransaction) { + final _$actionInfo = _$_ApplicationStoreActionController.startAction( + name: '_ApplicationStore.addIgnoredTransaction'); + try { + return super.addIgnoredTransaction(pendingTransaction); + } finally { + _$_ApplicationStoreActionController.endAction(_$actionInfo); + } + } + + @override + void _addTransactionInOrder(List transactions) { + final _$actionInfo = _$_ApplicationStoreActionController.startAction( + name: '_ApplicationStore._addTransactionInOrder'); + try { + return super._addTransactionInOrder(transactions); + } finally { + _$_ApplicationStoreActionController.endAction(_$actionInfo); + } + } + @override String toString() { return ''' @@ -477,6 +597,8 @@ currentTabIndex: ${currentTabIndex}, showAddAccountModal: ${showAddAccountModal}, currentQubicIDs: ${currentQubicIDs}, currentTransactions: ${currentTransactions}, +ignoredTransactions: ${ignoredTransactions}, +pendingTransactions: ${pendingTransactions}, transactionFilter: ${transactionFilter}, pendingRequests: ${pendingRequests}, marketInfo: ${marketInfo}, diff --git a/lib/styles/app_icons.dart b/lib/styles/app_icons.dart index a2b6b216..9d066bd7 100644 --- a/lib/styles/app_icons.dart +++ b/lib/styles/app_icons.dart @@ -22,4 +22,5 @@ abstract class AppIcons { static const String eye = '${_path}eye.svg'; static const String plusCircular = '${_path}plus_circular.svg'; static const String import = '${_path}import.svg'; + static const String close = '${_path}close.svg'; } diff --git a/lib/styles/text_styles.dart b/lib/styles/text_styles.dart index dc0ebd0d..5cf950bc 100644 --- a/lib/styles/text_styles.dart +++ b/lib/styles/text_styles.dart @@ -94,6 +94,11 @@ class TextStyles { fontWeight: FontWeight.bold, color: LightThemeColors.textLightGrey); + static TextStyle lightGreyTextNormal = const TextStyle( + fontSize: ThemeFontSizes.normal, + fontWeight: FontWeight.normal, + color: LightThemeColors.textLightGrey); + static TextStyle labelText = const TextStyle( fontSize: ThemeFontSizes.label, fontWeight: FontWeight.bold, diff --git a/lib/timed_controller.dart b/lib/timed_controller.dart index 84609c83..5f5ba73d 100644 --- a/lib/timed_controller.dart +++ b/lib/timed_controller.dart @@ -104,6 +104,7 @@ class TimedController extends WidgetsBindingObserver { //Fetch the ticks int tick = (await _liveApi.getCurrentTick()).tick; appStore.currentTick = tick; + appStore.validatePendingTransactions(tick); _getNetworkBalancesAndAssets(); lastFetch = DateTime.now(); } on Exception catch (e) { diff --git a/pubspec.lock b/pubspec.lock index 8ecfde21..ffb9a435 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -717,6 +717,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" + hive: + dependency: "direct main" + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" html: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a3748978..8564cfc8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,6 +58,8 @@ dependencies: blur: ^4.0.0 http_interceptor: ^2.0.0 flutter_svg: ^2.0.10+1 + hive: ^2.2.3 + hive_flutter: ^1.1.0 dev_dependencies: flutter_test: