138 lines
4.7 KiB
Dart
138 lines
4.7 KiB
Dart
import 'package:YWallet/chart.dart';
|
|
import 'package:YWallet/dualmoneyinput.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:warp_api/warp_api.dart';
|
|
import 'generated/l10n.dart';
|
|
import 'main.dart';
|
|
|
|
class PoolsPage extends StatefulWidget {
|
|
@override
|
|
State<StatefulWidget> createState() => PoolsState();
|
|
}
|
|
|
|
class PoolsState extends State<PoolsPage> {
|
|
final _formKey = GlobalKey<FormState>();
|
|
int _fromPool = 0;
|
|
int _toPool = 1;
|
|
final _amountKey = GlobalKey<DualMoneyInputState>();
|
|
var _maxAmountController = TextEditingController(text: amountToString(0, precision(settings.useMillis)));
|
|
var _memoController = TextEditingController();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
active.poolBalances.update();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final s = S.of(context);
|
|
var pools = ['Transparent', 'Sapling', 'Orchard'];
|
|
|
|
final b = active.poolBalances;
|
|
final balances = [b.transparent, b.sapling, b.orchard].map((v) => v / ZECUNIT).toList();
|
|
if (!active.coinDef.supportsUA) {
|
|
pools.removeAt(2);
|
|
balances.removeAt(2);
|
|
}
|
|
return Scaffold(
|
|
appBar: AppBar(title: Text(s.pools)),
|
|
body: SingleChildScrollView(
|
|
child: Padding(
|
|
padding: EdgeInsets.all(16),
|
|
child: Form(key: _formKey, child: Column(children: [
|
|
HorizontalBarChart(balances, height: 40),
|
|
Padding(padding: EdgeInsets.symmetric(vertical: 8.0)),
|
|
DropdownButtonFormField<int>(
|
|
decoration:
|
|
InputDecoration(labelText: s.fromPool),
|
|
value: _fromPool,
|
|
items: pools.asMap().entries
|
|
.map((e) => DropdownMenuItem(
|
|
child: Text(e.value), value: e.key))
|
|
.toList(),
|
|
onChanged: (v) {
|
|
setState(() {
|
|
_fromPool = v!;
|
|
});
|
|
}
|
|
),
|
|
DropdownButtonFormField<int>(
|
|
decoration:
|
|
InputDecoration(labelText: s.toPool),
|
|
value: _toPool,
|
|
items: pools.asMap().entries
|
|
.map((e) => DropdownMenuItem(
|
|
child: Text(e.value), value: e.key))
|
|
.toList(),
|
|
onChanged: (v) {
|
|
setState(() {
|
|
_toPool = v!;
|
|
});
|
|
}
|
|
),
|
|
DualMoneyInputWidget(key: _amountKey, initialValue: 0, spendable: _spendable, max: true),
|
|
Text(s.maxSpendableAmount(amountToString(_spendable, MAX_PRECISION), active.coinDef.ticker)),
|
|
Padding(padding: EdgeInsets.symmetric(vertical: 8.0)),
|
|
TextFormField(
|
|
decoration:
|
|
InputDecoration(labelText: s.memo),
|
|
minLines: 4,
|
|
maxLines: null,
|
|
keyboardType: TextInputType.multiline,
|
|
controller: _memoController),
|
|
Padding(padding: EdgeInsets.symmetric(vertical: 8.0)),
|
|
TextFormField(
|
|
decoration: InputDecoration(
|
|
labelText: s.maxAmountPerNote),
|
|
keyboardType: TextInputType.number,
|
|
controller: _maxAmountController,
|
|
inputFormatters: [
|
|
makeInputFormatter(settings.useMillis)
|
|
],
|
|
validator: _checkMaxAmountPerNote),
|
|
Padding(padding: EdgeInsets.symmetric(vertical: 8.0)),
|
|
ElevatedButton.icon(onPressed: _transfer, icon: Icon(Icons.currency_exchange), label: Text(s.transfer))
|
|
]))),
|
|
));
|
|
}
|
|
|
|
int get _spendable {
|
|
final b = active.poolBalances;
|
|
switch (_fromPool) {
|
|
case 0: return b.transparent;
|
|
case 1: return b.sapling;
|
|
case 2: return b.orchard;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
_transfer() async {
|
|
final form = _formKey.currentState;
|
|
if (form == null) return;
|
|
|
|
if (form.validate()) {
|
|
form.save();
|
|
final amount = _amountKey.currentState?.amount ?? 0;
|
|
final includeFee = _amountKey.currentState?.feeIncluded ?? false;
|
|
try {
|
|
final txPlan = await WarpApi.transferPools(active.coin, active.id, 1 << _fromPool, 1 << _toPool, amount,
|
|
includeFee, _memoController.text, stringToAmount(_maxAmountController.text), settings.anchorOffset);
|
|
Navigator.of(context).pushReplacementNamed('/txplan', arguments: txPlan);
|
|
}
|
|
on String catch (message) {
|
|
showSnackBar(message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
String? _checkMaxAmountPerNote(String? vs) {
|
|
final s = S.current;
|
|
if (vs == null) return s.amountMustBeANumber;
|
|
if (!checkNumber(vs)) return s.amountMustBeANumber;
|
|
final v = parseNumber(vs);
|
|
if (v < 0.0) return s.amountMustBePositive;
|
|
return null;
|
|
}
|