Rescan from height

This commit is contained in:
Hanh 2022-04-01 13:21:28 +08:00
parent 3923afdec9
commit ea83a7dc0c
20 changed files with 299 additions and 137 deletions

View File

@ -5,7 +5,7 @@ RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata
RUN apt-get install -yq curl
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y
RUN apt-get install -yq xz-utils clang cmake git ninja-build pkg-config libgtk-3-dev liblzma-dev
RUN apt-get install -yq unzip xz-utils clang cmake git ninja-build pkg-config libgtk-3-dev liblzma-dev
RUN curl -o flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_2.10.4-stable.tar.xz
RUN tar xvf flutter.tar.xz
RUN rm -f flutter.tar.xz

View File

@ -6,6 +6,7 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:warp_api/warp_api.dart';
import 'backup.dart';
import 'main.dart';
import 'rescan.dart';
import 'store.dart';
import 'generated/l10n.dart';
import 'about.dart';
@ -156,9 +157,9 @@ class AccountManagerState extends State<AccountManagerPage> {
await active.setActiveAccount(account.coin, account.id);
if (syncStatus.accountRestored) {
syncStatus.setAccountRestored(false);
final approved = await rescanDialog(context);
if (approved)
syncStatus.rescan(context);
final height = await rescanDialog(context);
if (height != null)
syncStatus.rescan(context, height);
}
final navigator = Navigator.of(context);

View File

@ -39,23 +39,25 @@ class MessageLookup extends MessageLookupByLibrary {
static String m7(ticker) => "Receive ${ticker}";
static String m8(ticker) => "Send ${ticker}";
static String m8(height) => "Rescan Requested from ${height}...";
static String m9(ticker) => "Send ${ticker} to...";
static String m9(ticker) => "Send ${ticker}";
static String m10(app) => "Sent from ${app}";
static String m10(ticker) => "Send ${ticker} to...";
static String m11(amount, ticker, count) =>
static String m11(app) => "Sent from ${app}";
static String m12(amount, ticker, count) =>
"Sending a total of ${amount} ${ticker} to ${count} recipients";
static String m12(aZEC, ticker, address) =>
static String m13(aZEC, ticker, address) =>
"Sending ${aZEC} ${ticker} to ${address}";
static String m13(name) => "Sub Account of ${name}";
static String m14(name) => "Sub Account of ${name}";
static String m14(text) => "${text} copied to clipboard";
static String m15(text) => "${text} copied to clipboard";
static String m15(currency) => "Use ${currency}";
static String m16(currency) => "Use ${currency}";
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@ -195,6 +197,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Max Amount per Note"),
"memo": MessageLookupByLibrary.simpleMessage("Memo"),
"mm": MessageLookupByLibrary.simpleMessage("M/M"),
"mobileCharges": MessageLookupByLibrary.simpleMessage(
"On Mobile Data, scanning may incur additional charges. Do you want to proceed?"),
"mode": MessageLookupByLibrary.simpleMessage("Mode"),
"multiPay": MessageLookupByLibrary.simpleMessage("Multi Pay"),
"multipay": MessageLookupByLibrary.simpleMessage("MultiPay"),
@ -256,11 +260,9 @@ class MessageLookup extends MessageLookupByLibrary {
"receivePayment":
MessageLookupByLibrary.simpleMessage("Receive Payment"),
"rescan": MessageLookupByLibrary.simpleMessage("Rescan"),
"rescanFrom": MessageLookupByLibrary.simpleMessage("Rescan from..."),
"rescanNeeded": MessageLookupByLibrary.simpleMessage("Rescan Needed"),
"rescanRequested":
MessageLookupByLibrary.simpleMessage("Rescan Requested..."),
"rescanWalletFromTheFirstBlock": MessageLookupByLibrary.simpleMessage(
"Rescan wallet from the first block?"),
"rescanRequested": m8,
"reset": MessageLookupByLibrary.simpleMessage("RESET"),
"restart": MessageLookupByLibrary.simpleMessage("Restart"),
"retrieveTransactionDetails": MessageLookupByLibrary.simpleMessage(
@ -281,11 +283,11 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage(
"Select notes to EXCLUDE from payments"),
"send": MessageLookupByLibrary.simpleMessage("Send"),
"sendCointicker": m8,
"sendCointickerTo": m9,
"sendFrom": m10,
"sendingATotalOfAmountCointickerToCountRecipients": m11,
"sendingAzecCointickerToAddress": m12,
"sendCointicker": m9,
"sendCointickerTo": m10,
"sendFrom": m11,
"sendingATotalOfAmountCointickerToCountRecipients": m12,
"sendingAzecCointickerToAddress": m13,
"server": MessageLookupByLibrary.simpleMessage("Server"),
"settings": MessageLookupByLibrary.simpleMessage("Settings"),
"shieldTranspBalance":
@ -304,7 +306,7 @@ class MessageLookup extends MessageLookupByLibrary {
"spendableBalance":
MessageLookupByLibrary.simpleMessage("Spendable Balance"),
"splitAccount": MessageLookupByLibrary.simpleMessage("Split Account"),
"subAccountOf": m13,
"subAccountOf": m14,
"synching": MessageLookupByLibrary.simpleMessage("Synching"),
"table": MessageLookupByLibrary.simpleMessage("Table"),
"tapAnIconToShowTheQrCode": MessageLookupByLibrary.simpleMessage(
@ -318,7 +320,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Tap QR Code for Transparent Address"),
"tapTransactionForDetails":
MessageLookupByLibrary.simpleMessage("Tap Transaction for Details"),
"textCopiedToClipboard": m14,
"textCopiedToClipboard": m15,
"theme": MessageLookupByLibrary.simpleMessage("Theme"),
"themeEditor": MessageLookupByLibrary.simpleMessage("Theme Editor"),
"thisAccountAlreadyExists": MessageLookupByLibrary.simpleMessage(
@ -347,7 +349,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Unshielded Balance"),
"unsignedTransactionFile":
MessageLookupByLibrary.simpleMessage("Unsigned Transaction File"),
"useSettingscurrency": m15,
"useSettingscurrency": m16,
"useTransparentBalance":
MessageLookupByLibrary.simpleMessage("Use Transparent Balance"),
"useUa": MessageLookupByLibrary.simpleMessage("Use UA"),

View File

@ -38,23 +38,25 @@ class MessageLookup extends MessageLookupByLibrary {
static String m7(ticker) => "Recibir ${ticker}";
static String m8(ticker) => "Enviar ${ticker}";
static String m8(height) => "Escaneo solicitado desde ${height}";
static String m9(ticker) => "Enviar ${ticker} a…";
static String m9(ticker) => "Enviar ${ticker}";
static String m10(app) => "Enviado desde ${app}";
static String m10(ticker) => "Enviar ${ticker} a…";
static String m11(amount, ticker, count) =>
static String m11(app) => "Enviado desde ${app}";
static String m12(amount, ticker, count) =>
"Enviando un total de ${amount} ${ticker} a ${count} direcciones";
static String m12(aZEC, ticker, address) =>
static String m13(aZEC, ticker, address) =>
"Enviado ${aZEC} ${ticker} a ${address}";
static String m13(name) => "Sub Account of ${name}";
static String m14(name) => "Sub Account of ${name}";
static String m14(text) => "${text} copied to clipboard";
static String m15(text) => "${text} copied to clipboard";
static String m15(currency) => "Utilizar ${currency}";
static String m16(currency) => "Utilizar ${currency}";
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@ -195,6 +197,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Monto máximo por nota"),
"memo": MessageLookupByLibrary.simpleMessage("Nota"),
"mm": MessageLookupByLibrary.simpleMessage("M/M"),
"mobileCharges": MessageLookupByLibrary.simpleMessage(
"On Mobile Data, scanning may incur additional charges. Do you want to proceed?"),
"mode": MessageLookupByLibrary.simpleMessage("Modo"),
"multiPay": MessageLookupByLibrary.simpleMessage("Multi Pagos"),
"multipay": MessageLookupByLibrary.simpleMessage("MultiPagos"),
@ -254,12 +258,10 @@ class MessageLookup extends MessageLookupByLibrary {
"receivePayment":
MessageLookupByLibrary.simpleMessage("Recibir un pago"),
"rescan": MessageLookupByLibrary.simpleMessage("Escanear"),
"rescanFrom": MessageLookupByLibrary.simpleMessage("¿Escanear desde?"),
"rescanNeeded":
MessageLookupByLibrary.simpleMessage("Necesita Escanear"),
"rescanRequested":
MessageLookupByLibrary.simpleMessage("Escaneo solicitado…"),
"rescanWalletFromTheFirstBlock": MessageLookupByLibrary.simpleMessage(
"¿Escanear billetera desde el primer bloque?"),
"rescanRequested": m8,
"reset": MessageLookupByLibrary.simpleMessage("RESET"),
"restart": MessageLookupByLibrary.simpleMessage("Reiniciar"),
"retrieveTransactionDetails": MessageLookupByLibrary.simpleMessage(
@ -281,11 +283,11 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage(
"Seleccionar Notas a EXCLUIR de los pagos"),
"send": MessageLookupByLibrary.simpleMessage("Enviar"),
"sendCointicker": m8,
"sendCointickerTo": m9,
"sendFrom": m10,
"sendingATotalOfAmountCointickerToCountRecipients": m11,
"sendingAzecCointickerToAddress": m12,
"sendCointicker": m9,
"sendCointickerTo": m10,
"sendFrom": m11,
"sendingATotalOfAmountCointickerToCountRecipients": m12,
"sendingAzecCointickerToAddress": m13,
"server": MessageLookupByLibrary.simpleMessage("Servidor"),
"settings": MessageLookupByLibrary.simpleMessage("Ajustes"),
"shieldTranspBalance":
@ -301,7 +303,7 @@ class MessageLookup extends MessageLookupByLibrary {
"spendableBalance":
MessageLookupByLibrary.simpleMessage("Saldo Gastable"),
"splitAccount": MessageLookupByLibrary.simpleMessage("Split Account"),
"subAccountOf": m13,
"subAccountOf": m14,
"synching": MessageLookupByLibrary.simpleMessage("Sincronizando"),
"table": MessageLookupByLibrary.simpleMessage("Lista"),
"tapAnIconToShowTheQrCode": MessageLookupByLibrary.simpleMessage(
@ -315,7 +317,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Pinchar QR para Dirección Transparente"),
"tapTransactionForDetails": MessageLookupByLibrary.simpleMessage(
"Toque Transacción para detalles"),
"textCopiedToClipboard": m14,
"textCopiedToClipboard": m15,
"theme": MessageLookupByLibrary.simpleMessage("Tema"),
"themeEditor": MessageLookupByLibrary.simpleMessage("Editora de temas"),
"thisAccountAlreadyExists":
@ -344,7 +346,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Saldo sin blindaje"),
"unsignedTransactionFile": MessageLookupByLibrary.simpleMessage(
"Archivo de transaccion sin firmar"),
"useSettingscurrency": m15,
"useSettingscurrency": m16,
"useTransparentBalance":
MessageLookupByLibrary.simpleMessage("Usar Saldo Transp"),
"useUa": MessageLookupByLibrary.simpleMessage("Usar UA"),

View File

@ -38,23 +38,25 @@ class MessageLookup extends MessageLookupByLibrary {
static String m7(ticker) => "Recevoir ${ticker}";
static String m8(ticker) => "Envoyer ${ticker}";
static String m8(height) => "Parcours demandé à partir de ${height}...";
static String m9(ticker) => "Envoyer ${ticker} à...";
static String m9(ticker) => "Envoyer ${ticker}";
static String m10(app) => "Envoyé via ${app}";
static String m10(ticker) => "Envoyer ${ticker} à...";
static String m11(amount, ticker, count) =>
static String m11(app) => "Envoyé via ${app}";
static String m12(amount, ticker, count) =>
"Envoi d\'un total de ${amount} ${ticker} à ${count} destinataires";
static String m12(aZEC, ticker, address) =>
static String m13(aZEC, ticker, address) =>
"Envoi de ${aZEC} ${ticker} à ${address}";
static String m13(name) => "Sous Compte de ${name}";
static String m14(name) => "Sous Compte de ${name}";
static String m14(text) => "${text} copied to clipboard";
static String m15(text) => "${text} copied to clipboard";
static String m15(currency) => "Utiliser ${currency}";
static String m16(currency) => "Utiliser ${currency}";
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
@ -199,6 +201,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Montant maximum par note"),
"memo": MessageLookupByLibrary.simpleMessage("Mémo"),
"mm": MessageLookupByLibrary.simpleMessage("Virtuel"),
"mobileCharges": MessageLookupByLibrary.simpleMessage(
"Sans Wi-fi, les frais peuvent être élevés. Voulez vous continuer?"),
"mode": MessageLookupByLibrary.simpleMessage("Mode"),
"multiPay": MessageLookupByLibrary.simpleMessage("Envoyer à plusieurs"),
"multipay": MessageLookupByLibrary.simpleMessage("Envoyer à plusieurs"),
@ -259,11 +263,10 @@ class MessageLookup extends MessageLookupByLibrary {
"receivePayment":
MessageLookupByLibrary.simpleMessage("Recevoir un payment"),
"rescan": MessageLookupByLibrary.simpleMessage("Parcourir à nouveau"),
"rescanFrom":
MessageLookupByLibrary.simpleMessage("Reparcourir à partir de...?"),
"rescanNeeded": MessageLookupByLibrary.simpleMessage("Scan nécessaire"),
"rescanRequested":
MessageLookupByLibrary.simpleMessage("Parcours demandé..."),
"rescanWalletFromTheFirstBlock": MessageLookupByLibrary.simpleMessage(
"Reparcourir la chaine à partir du premier bloc?"),
"rescanRequested": m8,
"reset": MessageLookupByLibrary.simpleMessage("RESET"),
"restart": MessageLookupByLibrary.simpleMessage("Redémarrage"),
"retrieveTransactionDetails": MessageLookupByLibrary.simpleMessage(
@ -286,11 +289,11 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage(
"Sélectionnez les billets à EXCLURE des paiements"),
"send": MessageLookupByLibrary.simpleMessage("Envoyer"),
"sendCointicker": m8,
"sendCointickerTo": m9,
"sendFrom": m10,
"sendingATotalOfAmountCointickerToCountRecipients": m11,
"sendingAzecCointickerToAddress": m12,
"sendCointicker": m9,
"sendCointickerTo": m10,
"sendFrom": m11,
"sendingATotalOfAmountCointickerToCountRecipients": m12,
"sendingAzecCointickerToAddress": m13,
"server": MessageLookupByLibrary.simpleMessage("Serveur"),
"settings": MessageLookupByLibrary.simpleMessage("Paramètres"),
"shieldTranspBalance": MessageLookupByLibrary.simpleMessage(
@ -306,7 +309,7 @@ class MessageLookup extends MessageLookupByLibrary {
"spendableBalance":
MessageLookupByLibrary.simpleMessage("Montant dépensable"),
"splitAccount": MessageLookupByLibrary.simpleMessage("Split Account"),
"subAccountOf": m13,
"subAccountOf": m14,
"synching":
MessageLookupByLibrary.simpleMessage("Synchronisation en cours"),
"table": MessageLookupByLibrary.simpleMessage("Tableau"),
@ -321,7 +324,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Appuyez sur le code QR pour l\'adresse transparente"),
"tapTransactionForDetails": MessageLookupByLibrary.simpleMessage(
"Presser sur une Transaction pour plus de details"),
"textCopiedToClipboard": m14,
"textCopiedToClipboard": m15,
"theme": MessageLookupByLibrary.simpleMessage("Thème"),
"themeEditor": MessageLookupByLibrary.simpleMessage("Editeur de Thème"),
"thisAccountAlreadyExists":
@ -350,7 +353,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Solde Transparent"),
"unsignedTransactionFile": MessageLookupByLibrary.simpleMessage(
"Fichier de transaction non signée"),
"useSettingscurrency": m15,
"useSettingscurrency": m16,
"useTransparentBalance": MessageLookupByLibrary.simpleMessage(
"Utiliser le Solde Transparent"),
"useUa": MessageLookupByLibrary.simpleMessage("Utiliser UA"),

View File

@ -310,11 +310,11 @@ class S {
);
}
/// `Rescan wallet from the first block?`
String get rescanWalletFromTheFirstBlock {
/// `Rescan from...`
String get rescanFrom {
return Intl.message(
'Rescan wallet from the first block?',
name: 'rescanWalletFromTheFirstBlock',
'Rescan from...',
name: 'rescanFrom',
desc: '',
args: [],
);
@ -330,13 +330,13 @@ class S {
);
}
/// `Rescan Requested...`
String get rescanRequested {
/// `Rescan Requested from {height}...`
String rescanRequested(Object height) {
return Intl.message(
'Rescan Requested...',
'Rescan Requested from $height...',
name: 'rescanRequested',
desc: '',
args: [],
args: [height],
);
}
@ -2081,6 +2081,16 @@ class S {
args: [],
);
}
/// `On Mobile Data, scanning may incur additional charges. Do you want to proceed?`
String get mobileCharges {
return Intl.message(
'On Mobile Data, scanning may incur additional charges. Do you want to proceed?',
name: 'mobileCharges',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View File

@ -9,13 +9,13 @@ import 'package:warp_api/warp_api.dart';
import 'about.dart';
import 'account.dart';
import 'account_manager.dart';
import 'accounts.dart';
import 'budget.dart';
import 'contact.dart';
import 'history.dart';
import 'generated/l10n.dart';
import 'main.dart';
import 'note.dart';
import 'rescan.dart';
import 'store.dart';
class HomePage extends StatefulWidget {
@ -226,9 +226,9 @@ class HomeInnerState extends State<HomeInnerPage> with SingleTickerProviderState
}
_rescan() async {
final approved = await rescanDialog(context);
if (approved) {
syncStatus.rescan(context);
final height = await rescanDialog(context);
if (height != null) {
syncStatus.rescan(context, height);
}
}

View File

@ -25,9 +25,9 @@
"txId": "TX ID",
"pleaseAuthenticateToShowAccountSeed": "Please authenticate to show account seed",
"noAuthenticationMethod": "No Authentication Method",
"rescanWalletFromTheFirstBlock": "Rescan wallet from the first block?",
"rescanFrom": "Rescan from...",
"cancel": "Cancel",
"rescanRequested": "Rescan Requested...",
"rescanRequested": "Rescan Requested from {height}...",
"doYouWantToDeleteTheSecretKeyAndConvert": "Do you want to DELETE the secret key and convert this account to a watch-only account? You will not be able to spend from this device anymore. This operation is NOT reversible.",
"delete": "DELETE",
"confs": "Confs",
@ -201,5 +201,6 @@
"closeApplication": "Close Application",
"pleaseRestartNow": "Please Restart now",
"disconnected": "Disconnected",
"ledger": "Ledger"
"ledger": "Ledger",
"mobileCharges": "On Mobile Data, scanning may incur additional charges. Do you want to proceed?"
}

View File

@ -25,9 +25,9 @@
"txId":"TX ID:",
"pleaseAuthenticateToShowAccountSeed":"Autentíquese para ver la semilla de la cuenta",
"noAuthenticationMethod":"Sin método de autenticación",
"rescanWalletFromTheFirstBlock":"¿Escanear billetera desde el primer bloque?",
"rescanFrom":"¿Escanear desde?",
"cancel":"Cancelar",
"rescanRequested":"Escaneo solicitado…",
"rescanRequested":"Escaneo solicitado desde {height}…",
"doYouWantToDeleteTheSecretKeyAndConvert":"¿Quiere BORRAR la clave secreta y convertir esta cuenta a solo lectura? Ya no podrá gastar desde este dispositivo. Esta operación NO es reversible.",
"delete":"ELIMINAR",
"confs":"Confs",
@ -199,5 +199,6 @@
"closeApplication": "Close Application",
"pleaseRestartNow": "Please Restart now",
"disconnected": "Disconnected",
"ledger": "Ledger"
"ledger": "Ledger",
"mobileCharges": "On Mobile Data, scanning may incur additional charges. Do you want to proceed?"
}

View File

@ -25,9 +25,9 @@
"txId": "ID de tx",
"pleaseAuthenticateToShowAccountSeed": "Veuillez vous authentifier pour voir la graine du compte",
"noAuthenticationMethod": "Pas de méthode d'authentification",
"rescanWalletFromTheFirstBlock": "Reparcourir la chaine à partir du premier bloc?",
"rescanFrom": "Reparcourir à partir de...?",
"cancel": "Annuler",
"rescanRequested": "Parcours demandé...",
"rescanRequested": "Parcours demandé à partir de {height}...",
"doYouWantToDeleteTheSecretKeyAndConvert": "Voulez-vous SUPPRIMER la clé secrète et convertir ce compte en un compte d'observation ? Vous ne pourrez plus dépenser depuis cet appareil. Cette opération n'est PAS réversible.",
"delete": "SUPPRIMER",
"confs": "Confs",
@ -199,5 +199,6 @@
"closeApplication": "Close Application",
"pleaseRestartNow": "Please Restart now",
"disconnected": "Déconnecté",
"ledger": "Ledger"
"ledger": "Ledger",
"mobileCharges": "Sans Wi-fi, les frais peuvent être élevés. Voulez vous continuer?"
}

View File

@ -23,7 +23,6 @@ import 'package:sqflite/sqflite.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:warp_api/warp_api.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:uni_links/uni_links.dart';
import 'package:quick_actions/quick_actions.dart';
import 'package:sqlite3/open.dart';
@ -453,46 +452,6 @@ void showQR(BuildContext context, String text, String title) {
));
}
Future<bool> rescanDialog(BuildContext context) async {
final approved = await showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (context) =>
AlertDialog(
title: Text(S
.of(context)
.rescan),
content: Text(S
.of(context)
.rescanWalletFromTheFirstBlock),
actions: confirmButtons(
context, () => Navigator.of(context).pop(true),
cancelValue: false))) ?? false;
if (approved)
return await confirmWifi(context);
return false;
}
Future<bool> confirmWifi(BuildContext context) async {
if (!isMobile()) return true;
final connectivity = await Connectivity().checkConnectivity();
if (connectivity == ConnectivityResult.mobile) {
return await showDialog<bool?>(
context: context,
barrierDismissible: false,
builder: (context) =>
AlertDialog(
title: Text(S
.of(context)
.rescan),
content: Text(
'On Mobile Data, scanning may incur additional charges. Do you want to proceed?'),
actions: confirmButtons(
context, () => Navigator.of(context).pop(true),
cancelValue: false))) ?? false;
} return true;
}
Future<bool> showMessageBox(BuildContext context, String title, String content,
String label) async {
final confirm = await showDialog<bool>(

82
lib/rescan.dart Normal file
View File

@ -0,0 +1,82 @@
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:warp_api/warp_api.dart';
import 'generated/l10n.dart';
import 'main.dart';
final rescanKey = GlobalKey<RescanFormState>();
Future<int?> rescanDialog(BuildContext context) async {
final approved = await showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: Text(S.of(context).rescanFrom),
content: RescanForm(key: rescanKey),
actions: confirmButtons(
context, () => Navigator.of(context).pop(true),
cancelValue: false))) ??
false;
if (approved) {
final date = rescanKey.currentState!.startDate;
final height = await WarpApi.getBlockHeightByTime(active.coin, date);
if (await confirmWifi(context)) return height;
}
return null;
}
class RescanForm extends StatefulWidget {
RescanForm({Key? key}) : super(key: key);
@override
RescanFormState createState() => RescanFormState();
}
class RescanFormState extends State<RescanForm> {
DateTime minDate = WarpApi.getActivationDate(active.coin);
DateTime maxDate = DateTime.now();
late DateTime startDate;
@override
void initState() {
super.initState();
startDate = minDate;
}
@override
Widget build(BuildContext context) {
final dateFormat = DateFormat('yyyy-MM-dd');
return SingleChildScrollView(
child: OutlinedButton(onPressed: _showDatePicker, child: Text(dateFormat.format(startDate)))
);
}
_showDatePicker() async {
final date = await showDatePicker(context: context, firstDate: minDate, initialDate: startDate, lastDate: maxDate);
if (date != null) {
setState(() {
startDate = date;
});
}
}
}
Future<bool> confirmWifi(BuildContext context) async {
if (!isMobile()) return true;
final connectivity = await Connectivity().checkConnectivity();
if (connectivity == ConnectivityResult.mobile) {
return await showDialog<bool?>(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: Text(S.of(context).rescan),
content: Text(
S.of(context).mobileCharges),
actions: confirmButtons(
context, () => Navigator.of(context).pop(true),
cancelValue: false))) ??
false;
}
return true;
}

View File

@ -518,13 +518,13 @@ abstract class _SyncStatus with Store {
}
@action
Future<void> rescan(BuildContext context) async {
Future<void> rescan(BuildContext context, int height) async {
eta.reset();
final snackBar = SnackBar(content: Text(S.of(context).rescanRequested));
final snackBar = SnackBar(content: Text(S.of(context).rescanRequested(height)));
rootScaffoldMessengerKey.currentState?.showSnackBar(snackBar);
syncedHeight = 0;
WarpApi.rewindToHeight(active.coin, 0);
syncedHeight = height;
WarpApi.truncateData(active.coin);
WarpApi.rewindToHeight(active.coin, height);
await sync();
}

View File

@ -68,6 +68,10 @@ char *broadcast_txhex(uint8_t coin, char *txhex);
char *ledger_sign(uint8_t coin, char *tx_filename);
uint32_t get_activation_date(uint8_t coin);
uint32_t get_block_by_time(uint8_t coin, uint32_t time);
uint32_t sync_historical_prices(uint8_t coin, int64_t now, uint32_t days, char *currency);
char *get_ua(char *sapling_addr, char *transparent_addr);

View File

@ -311,11 +311,12 @@ pub fn skip_to_last_height(coin: u8) {
}
pub fn rewind_to_height(coin: u8, height: u32) {
let res = || {
let r = get_runtime();
let res = r.block_on(async {
let mut wallet = get_wallet_lock(coin)?;
wallet.rewind_to_height(height)
};
log_result(res())
wallet.rewind_to_height(height).await
});
log_result(res)
}
pub fn mempool_sync(coin: u8) -> i64 {
@ -439,6 +440,24 @@ pub fn ledger_sign(coin: u8, tx_filename: &str) -> String {
log_result_string(res)
}
pub fn get_activation_date(coin: u8) -> u32 {
let r = get_runtime();
let res = r.block_on(async {
let wallet = get_wallet_lock(coin)?;
wallet.get_activation_date().await
});
log_result(res)
}
pub fn get_block_by_time(coin: u8, time: u32) -> u32 {
let r = get_runtime();
let res = r.block_on(async {
let wallet = get_wallet_lock(coin)?;
wallet.get_block_by_time(time).await
});
log_result(res)
}
pub fn sync_historical_prices(coin: u8, now: i64, days: u32, currency: &str) -> u32 {
let r = get_runtime();
let res = r.block_on(async {

View File

@ -181,6 +181,16 @@ pub unsafe extern "C" fn ledger_sign(coin: u8, tx_filename: *mut c_char) -> *mut
CString::new(res).unwrap().into_raw()
}
#[no_mangle]
pub unsafe extern "C" fn get_activation_date(coin: u8) -> u32 {
api::get_activation_date(coin)
}
#[no_mangle]
pub unsafe extern "C" fn get_block_by_time(coin: u8, time: u32) -> u32 {
api::get_block_by_time(coin, time)
}
#[no_mangle]
pub unsafe extern "C" fn sync_historical_prices(
coin: u8,

@ -1 +1 @@
Subproject commit 74bc5be12b23f8b60822ebcf7816e8acb35f5bb2
Subproject commit 5caecd36a60e987a4a920c9207666df91008a58f

View File

@ -60,6 +60,12 @@ class GetTBalanceParams {
GetTBalanceParams(this.coin, this.account);
}
class BlockHeightByTimeParams {
final int coin;
final int time;
BlockHeightByTimeParams(this.coin, this.time);
}
const DEFAULT_ACCOUNT = 1;
final warp_api_lib = init();
@ -220,6 +226,16 @@ class WarpApi {
return res.cast<Utf8>().toDartString();
}
static DateTime getActivationDate(int coin) {
final res = warp_api_lib.get_activation_date(coin);
return DateTime.fromMillisecondsSinceEpoch(res * 1000);
}
static Future<int> getBlockHeightByTime(int coin, DateTime time) async {
final res = await compute(getBlockHeightByTimeIsolateFn, BlockHeightByTimeParams(coin, time.millisecondsSinceEpoch ~/ 1000));
return res;
}
static Future<int> syncHistoricalPrices(int coin, String currency) async {
return await compute(syncHistoricalPricesIsolateFn, SyncHistoricalPricesParams(coin, currency));
}
@ -377,3 +393,7 @@ int getTBalanceIsolateFn(GetTBalanceParams params) {
return warp_api_lib.get_taddr_balance(params.coin, params.account);
}
int getBlockHeightByTimeIsolateFn(BlockHeightByTimeParams params) {
return warp_api_lib.get_block_by_time(params.coin, params.time);
}

View File

@ -388,6 +388,35 @@ class NativeLibrary {
late final _dart_ledger_sign _ledger_sign =
_ledger_sign_ptr.asFunction<_dart_ledger_sign>();
int get_activation_date(
int coin,
) {
return _get_activation_date(
coin,
);
}
late final _get_activation_date_ptr =
_lookup<ffi.NativeFunction<_c_get_activation_date>>(
'get_activation_date');
late final _dart_get_activation_date _get_activation_date =
_get_activation_date_ptr.asFunction<_dart_get_activation_date>();
int get_block_by_time(
int coin,
int time,
) {
return _get_block_by_time(
coin,
time,
);
}
late final _get_block_by_time_ptr =
_lookup<ffi.NativeFunction<_c_get_block_by_time>>('get_block_by_time');
late final _dart_get_block_by_time _get_block_by_time =
_get_block_by_time_ptr.asFunction<_dart_get_block_by_time>();
int sync_historical_prices(
int coin,
int now,
@ -946,6 +975,24 @@ typedef _dart_ledger_sign = ffi.Pointer<ffi.Int8> Function(
ffi.Pointer<ffi.Int8> tx_filename,
);
typedef _c_get_activation_date = ffi.Uint32 Function(
ffi.Uint8 coin,
);
typedef _dart_get_activation_date = int Function(
int coin,
);
typedef _c_get_block_by_time = ffi.Uint32 Function(
ffi.Uint8 coin,
ffi.Uint32 time,
);
typedef _dart_get_block_by_time = int Function(
int coin,
int time,
);
typedef _c_sync_historical_prices = ffi.Uint32 Function(
ffi.Uint8 coin,
ffi.Int64 now,

View File

@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.2.1+209
version: 1.2.1+212
environment:
sdk: ">=2.12.0 <3.0.0"
@ -38,7 +38,7 @@ dependencies:
local_auth: ^1.1.7
shared_preferences: ^2.0.7
flutter_markdown: ^0.6.6
package_info_plus: ^1.0.6
package_info_plus: ^1.4.0
velocity_x: ^3.3.0
decimal: ^1.3.0
flutter_form_builder: ^6.1.0+1