UI Tweaks of Spend page

This commit is contained in:
Hanh 2021-09-27 16:57:55 +08:00
parent 62af231eed
commit 8fc383032b
13 changed files with 247 additions and 172 deletions

View File

@ -124,6 +124,7 @@ class MessageLookup extends MessageLookupByLibrary {
"Another contact has this address"),
"enterSeed": MessageLookupByLibrary.simpleMessage(
"Enter Seed, Secret Key or Viewing Key. Leave blank for a new account"),
"excludedNotes": MessageLookupByLibrary.simpleMessage("Excluded Notes"),
"gold": MessageLookupByLibrary.simpleMessage("Gold"),
"height": MessageLookupByLibrary.simpleMessage("Height"),
"history": MessageLookupByLibrary.simpleMessage("History"),
@ -221,6 +222,8 @@ class MessageLookup extends MessageLookupByLibrary {
"shieldingInProgress":
MessageLookupByLibrary.simpleMessage("Shielding in progress..."),
"spendable": MessageLookupByLibrary.simpleMessage("Spendable"),
"spendableBalance":
MessageLookupByLibrary.simpleMessage("Spendable Balance"),
"synching": MessageLookupByLibrary.simpleMessage("Synching"),
"table": MessageLookupByLibrary.simpleMessage("Table"),
"tapAnIconToShowTheQrCode": MessageLookupByLibrary.simpleMessage(
@ -243,13 +246,18 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage(
"To make a contact, send them a memo with Contact:"),
"total": MessageLookupByLibrary.simpleMessage("Total"),
"totalBalance": MessageLookupByLibrary.simpleMessage("Total Balance"),
"tradingChartRange":
MessageLookupByLibrary.simpleMessage("Trading Chart Range"),
"tradingPl": MessageLookupByLibrary.simpleMessage("Wallet P&L"),
"transactionDetails":
MessageLookupByLibrary.simpleMessage("Transaction Details"),
"txId": MessageLookupByLibrary.simpleMessage("TX ID"),
"underConfirmed":
MessageLookupByLibrary.simpleMessage("Under Confirmed"),
"unshielded": MessageLookupByLibrary.simpleMessage("Unshielded"),
"unshieldedBalance":
MessageLookupByLibrary.simpleMessage("Unshielded Balance"),
"unsignedTransactionFile":
MessageLookupByLibrary.simpleMessage("Unsigned Transaction File"),
"useSettingscurrency": m7,

View File

@ -124,6 +124,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Cuenta duplicada"),
"enterSeed": MessageLookupByLibrary.simpleMessage(
"Ingrese Semilla, Clave Secreta o Clave Lectura. Dejar en blanco para una nueva cuenta "),
"excludedNotes": MessageLookupByLibrary.simpleMessage("Excluded Notes"),
"gold": MessageLookupByLibrary.simpleMessage("Oro"),
"height": MessageLookupByLibrary.simpleMessage("Altura"),
"history": MessageLookupByLibrary.simpleMessage("Historia"),
@ -219,6 +220,8 @@ class MessageLookup extends MessageLookupByLibrary {
"shieldingInProgress":
MessageLookupByLibrary.simpleMessage("Blindaje en progreso…"),
"spendable": MessageLookupByLibrary.simpleMessage("Gastable"),
"spendableBalance":
MessageLookupByLibrary.simpleMessage("Spendable Balance"),
"synching": MessageLookupByLibrary.simpleMessage("Sincronizando"),
"table": MessageLookupByLibrary.simpleMessage("Lista"),
"tapAnIconToShowTheQrCode": MessageLookupByLibrary.simpleMessage(
@ -241,13 +244,18 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage(
"Para hacer un contacto, enviarles una nota con Contact:"),
"total": MessageLookupByLibrary.simpleMessage("Total"),
"totalBalance": MessageLookupByLibrary.simpleMessage("Total Balance"),
"tradingChartRange":
MessageLookupByLibrary.simpleMessage("Rango de Gráfico"),
"tradingPl": MessageLookupByLibrary.simpleMessage("Intercambio G&P"),
"transactionDetails":
MessageLookupByLibrary.simpleMessage("Detalles de transacción"),
"txId": MessageLookupByLibrary.simpleMessage("TX ID:"),
"underConfirmed":
MessageLookupByLibrary.simpleMessage("Under Confirmed"),
"unshielded": MessageLookupByLibrary.simpleMessage("Unshielded"),
"unshieldedBalance":
MessageLookupByLibrary.simpleMessage("Unshielded Balance"),
"unsignedTransactionFile": MessageLookupByLibrary.simpleMessage(
"Archivo de transaccion sin firmar"),
"useSettingscurrency": m7,

View File

@ -124,6 +124,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Compte en double"),
"enterSeed": MessageLookupByLibrary.simpleMessage(
"Entrez la graine, la clé secrète ou la clé de visualisation. Laissez vide pour un nouveau compte"),
"excludedNotes": MessageLookupByLibrary.simpleMessage("Excluded Notes"),
"gold": MessageLookupByLibrary.simpleMessage("Gold"),
"height": MessageLookupByLibrary.simpleMessage("Hauteur"),
"history": MessageLookupByLibrary.simpleMessage("Historique"),
@ -219,6 +220,8 @@ class MessageLookup extends MessageLookupByLibrary {
"shieldingInProgress":
MessageLookupByLibrary.simpleMessage("Masquage en cours..."),
"spendable": MessageLookupByLibrary.simpleMessage("Dépensable"),
"spendableBalance":
MessageLookupByLibrary.simpleMessage("Spendable Balance"),
"synching":
MessageLookupByLibrary.simpleMessage("Synchronisation en cours"),
"table": MessageLookupByLibrary.simpleMessage("Tableau"),
@ -242,13 +245,18 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage(
"Pour établir un contact, envoyez-lui un mémo avec Contact:"),
"total": MessageLookupByLibrary.simpleMessage("Total"),
"totalBalance": MessageLookupByLibrary.simpleMessage("Total Balance"),
"tradingChartRange": MessageLookupByLibrary.simpleMessage(
"Domaine de temps des graphiques"),
"tradingPl": MessageLookupByLibrary.simpleMessage("Profit et Pertes"),
"transactionDetails":
MessageLookupByLibrary.simpleMessage("Détails de la transaction"),
"txId": MessageLookupByLibrary.simpleMessage("ID de tx"),
"underConfirmed":
MessageLookupByLibrary.simpleMessage("Under Confirmed"),
"unshielded": MessageLookupByLibrary.simpleMessage("Unshielded"),
"unshieldedBalance":
MessageLookupByLibrary.simpleMessage("Unshielded Balance"),
"unsignedTransactionFile": MessageLookupByLibrary.simpleMessage(
"Fichier de transaction non signée"),
"useSettingscurrency": m7,

View File

@ -112,6 +112,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Duplicate Account"),
"enterSeed":
MessageLookupByLibrary.simpleMessage("輸入種子,秘密鎖匙或查看鎖匙\n留空預備新帳戶"),
"excludedNotes": MessageLookupByLibrary.simpleMessage("Excluded Notes"),
"gold": MessageLookupByLibrary.simpleMessage("Gold"),
"height": MessageLookupByLibrary.simpleMessage("高度"),
"history": MessageLookupByLibrary.simpleMessage("過去記錄"),
@ -190,6 +191,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("屏蔽你的公開結餘"),
"shieldingInProgress": MessageLookupByLibrary.simpleMessage("屏蔽進行中"),
"spendable": MessageLookupByLibrary.simpleMessage("可使用的"),
"spendableBalance":
MessageLookupByLibrary.simpleMessage("Spendable Balance"),
"synching": MessageLookupByLibrary.simpleMessage("同步"),
"table": MessageLookupByLibrary.simpleMessage("表列"),
"tapAnIconToShowTheQrCode":
@ -210,11 +213,16 @@ class MessageLookup extends MessageLookupByLibrary {
"toMakeAContactSendThemAMemoWithContact":
MessageLookupByLibrary.simpleMessage("發送備忘到 Contact:"),
"total": MessageLookupByLibrary.simpleMessage("總數"),
"totalBalance": MessageLookupByLibrary.simpleMessage("Total Balance"),
"tradingChartRange": MessageLookupByLibrary.simpleMessage("交易範圍"),
"tradingPl": MessageLookupByLibrary.simpleMessage("交易"),
"transactionDetails": MessageLookupByLibrary.simpleMessage("交易資料"),
"txId": MessageLookupByLibrary.simpleMessage("TX ID:"),
"underConfirmed":
MessageLookupByLibrary.simpleMessage("Under Confirmed"),
"unshielded": MessageLookupByLibrary.simpleMessage("Unshielded"),
"unshieldedBalance":
MessageLookupByLibrary.simpleMessage("Unshielded Balance"),
"unsignedTransactionFile":
MessageLookupByLibrary.simpleMessage("未簽署交易文件"),
"useSettingscurrency": m7,

View File

@ -1491,6 +1491,56 @@ class S {
args: [],
);
}
/// `Unshielded Balance`
String get unshieldedBalance {
return Intl.message(
'Unshielded Balance',
name: 'unshieldedBalance',
desc: '',
args: [],
);
}
/// `Total Balance`
String get totalBalance {
return Intl.message(
'Total Balance',
name: 'totalBalance',
desc: '',
args: [],
);
}
/// `Under Confirmed`
String get underConfirmed {
return Intl.message(
'Under Confirmed',
name: 'underConfirmed',
desc: '',
args: [],
);
}
/// `Excluded Notes`
String get excludedNotes {
return Intl.message(
'Excluded Notes',
name: 'excludedNotes',
desc: '',
args: [],
);
}
/// `Spendable Balance`
String get spendableBalance {
return Intl.message(
'Spendable Balance',
name: 'spendableBalance',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View File

@ -142,5 +142,10 @@
"protectSend": "Protect Send",
"protectSendSettingChanged": "Protect Send setting changed",
"pleaseAuthenticateToSend": "Please authenticate to Send",
"unshielded": "Unshielded"
"unshielded": "Unshielded",
"unshieldedBalance": "Unshielded Balance",
"totalBalance": "Total Balance",
"underConfirmed": "Under Confirmed",
"excludedNotes": "Excluded Notes",
"spendableBalance": "Spendable Balance"
}

View File

@ -142,5 +142,10 @@
"protectSend": "Protect Send",
"protectSendSettingChanged": "Protect Send setting changed",
"pleaseAuthenticateToSend": "Please authenticate to Send",
"unshielded": "Unshielded"
"unshielded": "Unshielded",
"unshieldedBalance": "Unshielded Balance",
"totalBalance": "Total Balance",
"underConfirmed": "Under Confirmed",
"excludedNotes": "Excluded Notes",
"spendableBalance": "Spendable Balance"
}

View File

@ -142,5 +142,10 @@
"protectSend": "Protect Send",
"protectSendSettingChanged": "Protect Send setting changed",
"pleaseAuthenticateToSend": "Please authenticate to Send",
"unshielded": "Unshielded"
"unshielded": "Unshielded",
"unshieldedBalance": "Unshielded Balance",
"totalBalance": "Total Balance",
"underConfirmed": "Under Confirmed",
"excludedNotes": "Excluded Notes",
"spendableBalance": "Spendable Balance"
}

View File

@ -138,5 +138,10 @@
"protectSend": "Protect Send",
"protectSendSettingChanged": "Protect Send setting changed",
"pleaseAuthenticateToSend": "Please authenticate to Send",
"unshielded": "Unshielded"
"unshielded": "Unshielded",
"unshieldedBalance": "Unshielded Balance",
"totalBalance": "Total Balance",
"underConfirmed": "Under Confirmed",
"excludedNotes": "Excluded Notes",
"spendableBalance": "Spendable Balance"
}

View File

@ -32,8 +32,8 @@ class SendState extends State<SendPage> {
var _address = "";
var _amount = 0;
var _maxAmountPerNote = Decimal.zero;
var _totalBalance = 0;
var _tbalance = 0;
var _sBalance = 0;
var _tBalance = 0;
var _excludedBalance = 0;
var _underConfirmedBalance = 0;
final _addressController = TextEditingController();
@ -43,7 +43,6 @@ class SendState extends State<SendPage> {
var _zecAmountController = TextEditingController(text: zero);
var _fiatAmountController = TextEditingController(text: zero);
final _maxAmountController = TextEditingController(text: zero);
var _includeFee = false;
var _isExpanded = false;
var _shieldTransparent = settings.shieldBalance;
ReactionDisposer? _priceAutorunDispose;
@ -54,8 +53,6 @@ class SendState extends State<SendPage> {
if (widget.contact != null)
_addressController.text = widget.contact!.address;
Future.microtask(() async {
});
_updateFiatAmount();
super.initState();
@ -64,13 +61,15 @@ class SendState extends State<SendPage> {
});
_newBlockAutorunDispose = autorun((_) async {
final balance = await accountManager.getSpendableBalance();
final tbalance = accountManager.tbalance;
final _ = accountManager.dataEpoch;
final sBalance = await accountManager.getShieldedBalance();
final tBalance = accountManager.tbalance;
final excludedBalance = await accountManager.getExcludedBalance();
final underConfirmedBalance = await accountManager.getUnderConfirmedBalance();
final underConfirmedBalance =
await accountManager.getUnderConfirmedBalance();
setState(() {
_totalBalance = math.max(balance - DEFAULT_FEE, 0);
_tbalance = tbalance;
_sBalance = sBalance;
_tBalance = tBalance;
_excludedBalance = excludedBalance;
_underConfirmedBalance = underConfirmedBalance;
});
@ -100,31 +99,29 @@ class SendState extends State<SendPage> {
child: Column(children: <Widget>[
Row(children: <Widget>[
Expanded(
child: TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
controller: _addressController,
decoration: InputDecoration(
labelText: s.sendCointickerTo(coin.ticker)),
minLines: 4,
maxLines: 10,
keyboardType: TextInputType.multiline,
),
onSaved: _onAddress,
validator: _checkAddress,
onSuggestionSelected: (Contact contact) {
_addressController.text = contact.name;
},
suggestionsCallback: (String pattern) {
return contacts.contacts.where((c) =>
c.name
.toLowerCase()
.contains(pattern.toLowerCase()));
},
itemBuilder: (BuildContext context, Contact c) =>
ListTile(title: Text(c.name)),
noItemsFoundBuilder: (_) => SizedBox(),
child: TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
controller: _addressController,
decoration: InputDecoration(
labelText: s.sendCointickerTo(coin.ticker)),
minLines: 4,
maxLines: 10,
keyboardType: TextInputType.multiline,
),
),
onSaved: _onAddress,
validator: _checkAddress,
onSuggestionSelected: (Contact contact) {
_addressController.text = contact.name;
},
suggestionsCallback: (String pattern) {
return contacts.contacts.where((c) => c.name
.toLowerCase()
.contains(pattern.toLowerCase()));
},
itemBuilder: (BuildContext context, Contact c) =>
ListTile(title: Text(c.name)),
noItemsFoundBuilder: (_) => SizedBox(),
)),
IconButton(
icon: new Icon(MdiIcons.qrcodeScan),
onPressed: _onScan)
@ -132,50 +129,48 @@ class SendState extends State<SendPage> {
Row(children: [
Expanded(
child: TextFormField(
style: !_inputInZEC
? TextStyle(fontWeight: FontWeight.w200)
: TextStyle(),
decoration: InputDecoration(
labelText: s.amountInSettingscurrency(coin.ticker)),
controller: _zecAmountController,
keyboardType: TextInputType.number,
inputFormatters: [makeInputFormatter(_mZEC)],
validator: _checkAmount,
onTap: () =>
setState(() {
_inputInZEC = true;
}),
onChanged: (_) {
_updateFiatAmount();
},
onSaved: _onAmount,
)),
TextButton(
child: Text(s.max), onPressed: _onMax),
style: !_inputInZEC
? TextStyle(fontWeight: FontWeight.w200)
: TextStyle(),
decoration: InputDecoration(
labelText:
s.amountInSettingscurrency(coin.ticker)),
controller: _zecAmountController,
keyboardType: TextInputType.number,
inputFormatters: [makeInputFormatter(_mZEC)],
validator: _checkAmount,
onTap: () => setState(() {
_inputInZEC = true;
}),
onChanged: (_) {
_updateFiatAmount();
},
onSaved: _onAmount,
)),
TextButton(child: Text(s.max), onPressed: _onMax),
]),
Row(children: [
Expanded(
child: TextFormField(
style: _inputInZEC
? TextStyle(fontWeight: FontWeight.w200)
: TextStyle(),
decoration: InputDecoration(
labelText: s.amountInSettingscurrency(
settings.currency)),
controller: _fiatAmountController,
keyboardType: TextInputType.number,
inputFormatters: [makeInputFormatter(_mZEC)],
validator: (v) => _checkAmount(v, isFiat: true),
onTap: () =>
setState(() {
_inputInZEC = false;
}),
onChanged: (_) {
_updateAmount();
},
),
),
child: TextFormField(
style: _inputInZEC
? TextStyle(fontWeight: FontWeight.w200)
: TextStyle(),
decoration: InputDecoration(
labelText: s.amountInSettingscurrency(
settings.currency)),
controller: _fiatAmountController,
keyboardType: TextInputType.number,
inputFormatters: [makeInputFormatter(_mZEC)],
validator: (v) => _checkAmount(v, isFiat: true),
onTap: () => setState(() {
_inputInZEC = false;
}),
onChanged: (_) {
_updateAmount();
}))
]),
BalanceTable(_sBalance, _tBalance, _excludedBalance,
_underConfirmedBalance),
ExpansionPanelList(
expansionCallback: (_, isExpanded) {
setState(() {
@ -185,13 +180,12 @@ class SendState extends State<SendPage> {
children: [
ExpansionPanel(
headerBuilder: (_, __) =>
ListTile(
title: Text(s.advancedOptions)),
ListTile(title: Text(s.advancedOptions)),
body: Column(children: [
ListTile(
title: TextFormField(
decoration: InputDecoration(
labelText: s.memo),
decoration:
InputDecoration(labelText: s.memo),
minLines: 4,
maxLines: null,
keyboardType: TextInputType.multiline,
@ -202,41 +196,30 @@ class SendState extends State<SendPage> {
title: Text(s.roundToMillis),
value: _mZEC,
onChanged: _onChangedmZEC),
CheckboxListTile(
title:
Text(s.includeFeeInAmount),
value: _includeFee,
onChanged: _onChangedIncludeFee),
if (accountManager.canPay)
CheckboxListTile(
title: Text(
s.shieldTransparentBalance),
title: Text(s.shieldTransparentBalance),
value: _shieldTransparent,
onChanged: _onChangedShieldBalance,
),
ListTile(
title: TextFormField(
decoration: InputDecoration(
labelText:
s.maxAmountPerNote),
keyboardType: TextInputType.number,
controller: _maxAmountController,
inputFormatters: [
makeInputFormatter(_mZEC)
],
validator: _checkMaxAmountPerNote,
onSaved: _onSavedMaxAmountPerNote,
)),
decoration: InputDecoration(
labelText: s.maxAmountPerNote),
keyboardType: TextInputType.number,
controller: _maxAmountController,
inputFormatters: [makeInputFormatter(_mZEC)],
validator: _checkMaxAmountPerNote,
onSaved: _onSavedMaxAmountPerNote,
)),
]),
isExpanded: _isExpanded,
)
]),
Padding(padding: EdgeInsets.all(8)),
BalanceTable(_totalBalance, _tbalance, _excludedBalance, _underConfirmedBalance),
ButtonBar(
children: confirmButtons(context, _onSend,
okLabel: s.send,
okIcon: Icon(MdiIcons.send)))
okLabel: s.send, okIcon: Icon(MdiIcons.send)))
])))));
}
@ -258,7 +241,7 @@ class SendState extends State<SendPage> {
final v = parseNumber(vs);
if (v < 0.0) return s.amountMustBePositive;
if (!isFiat && v == 0.0) return s.amountMustBePositive;
if (!isFiat && amountInZAT(Decimal.parse(v.toString())) > _totalBalance)
if (!isFiat && amountInZAT(Decimal.parse(v.toString())) > spendable)
return s.notEnoughBalance;
return null;
}
@ -275,18 +258,11 @@ class SendState extends State<SendPage> {
void _onMax() {
setState(() {
_mZEC = false;
_includeFee = false;
_zecAmountController.text = amountToString(spendable);
_updateFiatAmount();
});
}
void _onChangedIncludeFee(bool? v) {
setState(() {
_includeFee = v ?? false;
});
}
void _onChangedmZEC(bool? v) {
if (v == null) return;
setState(() {
@ -375,30 +351,27 @@ class SendState extends State<SendPage> {
final approved = await showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) =>
AlertDialog(
title: Text(s.pleaseConfirm),
content: SingleChildScrollView(
child: Text(s.sendingAzecCointickerToAddress(
aZEC, coin.ticker, _address))),
actions: confirmButtons(
context, () => Navigator.of(context).pop(true),
okLabel: s.approve, cancelValue: false)));
builder: (BuildContext context) => AlertDialog(
title: Text(s.pleaseConfirm),
content: SingleChildScrollView(
child: Text(s.sendingAzecCointickerToAddress(
aZEC, coin.ticker, _address))),
actions: confirmButtons(
context, () => Navigator.of(context).pop(true),
okLabel: s.approve, cancelValue: false)));
if (approved) {
Navigator.of(context).pop();
final snackBar1 = SnackBar(content: Text(s.preparingTransaction));
rootScaffoldMessengerKey.currentState?.showSnackBar(snackBar1);
if (_includeFee) _amount -= DEFAULT_FEE;
int maxAmountPerNote = (_maxAmountPerNote * ZECUNIT_DECIMAL).toInt();
final memo = _memoController.text;
final address = unwrapUA(_address);
if (accountManager.canPay) {
if (settings.protectSend &&
!await authenticate(
context, s.pleaseAuthenticateToSend)) return;
!await authenticate(context, s.pleaseAuthenticateToSend)) return;
final tx = await compute(
sendPayment,
PaymentParams(
@ -418,14 +391,8 @@ class SendState extends State<SendPage> {
Directory tempDir = await getTemporaryDirectory();
String filename = "${tempDir.path}/tx.json";
final msg = WarpApi.prepareTx(
accountManager.active.id,
address,
_amount,
memo,
maxAmountPerNote,
settings.anchorOffset,
filename);
final msg = WarpApi.prepareTx(accountManager.active.id, address,
_amount, memo, maxAmountPerNote, settings.anchorOffset, filename);
Share.shareFiles([filename], subject: s.unsignedTransactionFile);
@ -450,62 +417,70 @@ class SendState extends State<SendPage> {
return decimalFormat(vv, precision(_mZEC));
}
get spendable => _totalBalance - _excludedBalance;
get spendable => math.max(
_sBalance - _excludedBalance - _underConfirmedBalance - DEFAULT_FEE, 0);
}
class BalanceTable extends StatelessWidget {
final int balance;
final int tbalance;
final int sBalance;
final int tBalance;
final int excludedBalance;
final int underConfirmedBalance;
BalanceTable(this.balance, this.tbalance, this.excludedBalance, this.underConfirmedBalance);
BalanceTable(this.sBalance, this.tBalance, this.excludedBalance,
this.underConfirmedBalance);
@override
Widget build(BuildContext context) {
final tbalanceLabel = Text.rich(
TextSpan(children: [
TextSpan(text: 'Unshielded Balance'),
WidgetSpan(
child: GestureDetector(
child: Icon(Icons.shield_outlined),
onTap: () {
shieldTAddr(context);
},
),
)
]));
return Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BalanceRow(Text('Total Balance'), balance + tbalance + underConfirmedBalance),
BalanceRow(Text('Under Confirmed'), -underConfirmedBalance),
BalanceRow(Text('Excluded Notes'), -excludedBalance),
BalanceRow(tbalanceLabel, -tbalance),
BalanceRow(Text('Spendable Balance', style: TextStyle(color: Theme.of(context).primaryColor)), balance - excludedBalance),
]
final theme = Theme.of(context);
final tBalanceLabel = Text.rich(TextSpan(children: [
TextSpan(text: S.of(context).unshieldedBalance + ' '),
WidgetSpan(
child: GestureDetector(
child: Icon(Icons.shield_outlined),
onTap: () {
shieldTAddr(context);
},
),
)
);
]));
return Container(
decoration: BoxDecoration(border: Border.all(color: theme.dividerColor, width: 1),
borderRadius: BorderRadius.circular(8)),
child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
BalanceRow(Text(S.of(context).totalBalance), totalBalance),
BalanceRow(Text(S.of(context).underConfirmed), -underConfirmedBalance),
BalanceRow(Text(S.of(context).excludedNotes), -excludedBalance),
BalanceRow(tBalanceLabel, -tBalance),
BalanceRow(Text(S.of(context).spendableBalance), spendable,
style: TextStyle(color: Theme.of(context).primaryColor)),
]));
}
get totalBalance => sBalance + tBalance;
get spendable => math.max(
sBalance - excludedBalance - underConfirmedBalance - DEFAULT_FEE, 0);
}
class BalanceRow extends StatelessWidget {
final label;
final amount;
BalanceRow(this.label, this.amount);
final style;
BalanceRow(this.label, this.amount, {this.style});
@override
Widget build(BuildContext context) {
return ListTile(title: label,
trailing: Text(amountToString(amount), style: TextStyle(fontFeatures: [FontFeature.tabularFigures()])),
return ListTile(
title: label,
trailing: Text(amountToString(amount),
style: TextStyle(fontFeatures: [FontFeature.tabularFigures()]).merge(style)),
visualDensity: VisualDensity(horizontal: 0, vertical: -4));
}
}
sendPayment(PaymentParams param) async {
param.port.send(0);
final tx = await WarpApi.sendPayment(

View File

@ -407,12 +407,10 @@ abstract class _AccountManager with Store {
return res[0]['value'] ?? 0;
}
Future<int> getSpendableBalance() async {
final height = syncStatus.latestHeight - settings.anchorOffset;
Future<int> getShieldedBalance() async {
return Sqflite.firstIntValue(await db.rawQuery(
"SELECT SUM(value) AS value FROM received_notes WHERE account = ?1 AND spent IS NULL "
"AND height <= ?2",
[active.id, height])) ?? 0;
"SELECT SUM(value) AS value FROM received_notes WHERE account = ?1 AND spent IS NULL",
[active.id])) ?? 0;
}
Future<int> getUnderConfirmedBalance() async {

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.0.10+155
version: 1.0.10+156
environment:
sdk: ">=2.12.0 <3.0.0"

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.0.10+155
version: 1.0.10+156
environment:
sdk: ">=2.12.0 <3.0.0"