CAKE-177. CAKE-176. CAKE-115.
M committed
Nov 16, 2020 at 20:17 UTC
6418b28c08736aef5b4ef5092e046c64ae734d1f
5 files changed
+142
-100
lib/di.dart
+2
-1
@@ -203,7 +203,8 @@ Future setup(
203
authPageState.changeProcessText('Loading the wallet');
204
205
if (loginError != null) {
206
- authPageState.changeProcessText('ERROR: ${loginError.toString()}');
206
+ authPageState
207
+ .changeProcessText('ERROR: ${loginError.toString()}');
208
}
209
210
ReactionDisposer _reaction;
lib/monero/pending_monero_transaction.dart
+20
-1
@@ -5,6 +5,14 @@ import 'package:cake_wallet/entities/crypto_currency.dart';
5
import 'package:cake_wallet/core/amount_converter.dart';
6
import 'package:cake_wallet/core/pending_transaction.dart';
7
8
+class DoubleSpendException implements Exception {
9
+ DoubleSpendException();
10
+
11
+ @override
12
+ String toString() =>
13
+ 'This transaction cannot be committed. This can be due to many reasons including the wallet not being synced, there is not enough XMR in your available balance, or previous transactions are not yet fully processed.';
14
+}
15
+
16
class PendingMoneroTransaction with PendingTransaction {
17
PendingMoneroTransaction(this.pendingTransactionDescription);
18
@@ -22,7 +30,18 @@ class PendingMoneroTransaction with PendingTransaction {
30
CryptoCurrency.xmr, pendingTransactionDescription.fee);
31
32
@override
25
- Future<void> commit() async =>
33
+ Future<void> commit() async {
34
+ try {
35
monero_transaction_history.commitTransactionFromPointerAddress(
36
address: pendingTransactionDescription.pointerAddress);
37
+ } catch (e) {
38
+ final message = e.toString();
39
+
40
+ if (message.contains('Reason: double spend')) {
41
+ throw DoubleSpendException();
42
+ }
43
+
44
+ rethrow;
45
+ }
46
+ }
47
}
lib/src/screens/auth/auth_page.dart
+6
-8
@@ -39,14 +39,12 @@ class AuthPageState extends State<AuthPage> {
39
_reaction ??=
40
reaction((_) => widget.authViewModel.state, (ExecutionState state) {
41
if (state is ExecutedSuccessfullyState) {
42
- WidgetsBinding.instance.addPostFrameCallback((_) {
43
- if (widget.onAuthenticationFinished != null) {
44
- widget.onAuthenticationFinished(true, this);
45
- } else {
46
- _authBar?.dismiss();
47
- showBar<void>(context, S.of(context).authenticated);
48
- }
49
- });
42
+ if (widget.onAuthenticationFinished != null) {
43
+ widget.onAuthenticationFinished(true, this);
44
+ } else {
45
+ _authBar?.dismiss();
46
+ showBar<void>(context, S.of(context).authenticated);
47
+ }
48
}
49
50
if (state is IsExecutingState) {
lib/src/screens/receive/receive_page.dart
+108
-88
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
2
import 'package:cake_wallet/utils/show_pop_up.dart';
3
import 'package:flutter/material.dart';
4
import 'package:flutter/cupertino.dart';
@@ -15,9 +16,10 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_h
16
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
17
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
18
import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart';
19
+import 'package:keyboard_actions/keyboard_actions.dart';
20
21
class ReceivePage extends BasePage {
20
- ReceivePage({this.addressListViewModel});
22
+ ReceivePage({this.addressListViewModel}) : _cryptoAmountFocus = FocusNode();
23
24
final WalletAddressListViewModel addressListViewModel;
25
@@ -33,6 +35,8 @@ class ReceivePage extends BasePage {
35
@override
36
Color get titleColor => Colors.white;
37
38
+ final FocusNode _cryptoAmountFocus;
39
+
40
@override
41
Widget Function(BuildContext, Widget) get rootWrapper =>
42
(BuildContext context, Widget scaffold) => Container(
@@ -67,93 +71,109 @@ class ReceivePage extends BasePage {
71
72
@override
73
Widget body(BuildContext context) {
70
- return SingleChildScrollView(
71
- child: Column(
72
- children: <Widget>[
73
- Padding(
74
- padding: EdgeInsets.fromLTRB(24, 80, 24, 40),
75
- child: QRWidget(
76
- addressListViewModel: addressListViewModel,
77
- isAmountFieldShow: true,
78
- ),
74
+ return KeyboardActions(
75
+ config: KeyboardActionsConfig(
76
+ keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
77
+ keyboardBarColor: isDarkTheme
78
+ ? Color.fromRGBO(48, 51, 60, 1.0)
79
+ : Color.fromRGBO(98, 98, 98, 1.0),
80
+ nextFocus: false,
81
+ actions: [
82
+ KeyboardActionsItem(
83
+ focusNode: _cryptoAmountFocus,
84
+ toolbarButtons: [(_) => KeyboardDoneButton()],
85
+ )
86
+ ]),
87
+ child: SingleChildScrollView(
88
+ child: Column(
89
+ children: <Widget>[
90
+ Padding(
91
+ padding: EdgeInsets.fromLTRB(24, 80, 24, 40),
92
+ child: QRWidget(
93
+ addressListViewModel: addressListViewModel,
94
+ isAmountFieldShow: true,
95
+ amountTextFieldFocusNode: _cryptoAmountFocus),
96
+ ),
97
+ Observer(
98
+ builder: (_) => ListView.separated(
99
+ padding: EdgeInsets.all(0),
100
+ separatorBuilder: (context, _) => Container(
101
+ height: 1, color: Theme.of(context).dividerColor),
102
+ shrinkWrap: true,
103
+ physics: NeverScrollableScrollPhysics(),
104
+ itemCount: addressListViewModel.items.length,
105
+ itemBuilder: (context, index) {
106
+ final item = addressListViewModel.items[index];
107
+ Widget cell = Container();
108
+
109
+ if (item is WalletAccountListHeader) {
110
+ cell = HeaderTile(
111
+ onTap: () async => await showPopUp<void>(
112
+ context: context,
113
+ builder: (_) =>
114
+ getIt.get<MoneroAccountListPage>()),
115
+ title: S.of(context).accounts,
116
+ icon: Icon(
117
+ Icons.arrow_forward_ios,
118
+ size: 14,
119
+ color:
120
+ Theme.of(context).textTheme.display1.color,
121
+ ));
122
+ }
123
+
124
+ if (item is WalletAddressListHeader) {
125
+ cell = HeaderTile(
126
+ onTap: () => Navigator.of(context)
127
+ .pushNamed(Routes.newSubaddress),
128
+ title: S.of(context).addresses,
129
+ icon: Icon(
130
+ Icons.add,
131
+ size: 20,
132
+ color:
133
+ Theme.of(context).textTheme.display1.color,
134
+ ));
135
+ }
136
+
137
+ if (item is WalletAddressListItem) {
138
+ cell = Observer(builder: (_) {
139
+ final isCurrent = item.address ==
140
+ addressListViewModel.address.address;
141
+ final backgroundColor = isCurrent
142
+ ? Theme.of(context)
143
+ .textTheme
144
+ .display3
145
+ .decorationColor
146
+ : Theme.of(context)
147
+ .textTheme
148
+ .display2
149
+ .decorationColor;
150
+ final textColor = isCurrent
151
+ ? Theme.of(context).textTheme.display3.color
152
+ : Theme.of(context).textTheme.display2.color;
153
+
154
+ return AddressCell.fromItem(item,
155
+ isCurrent: isCurrent,
156
+ backgroundColor: backgroundColor,
157
+ textColor: textColor,
158
+ onTap: (_) =>
159
+ addressListViewModel.setAddress(item),
160
+ onEdit: () => Navigator.of(context).pushNamed(
161
+ Routes.newSubaddress,
162
+ arguments: item));
163
+ });
164
+ }
165
+
166
+ return index != 0
167
+ ? cell
168
+ : ClipRRect(
169
+ borderRadius: BorderRadius.only(
170
+ topLeft: Radius.circular(30),
171
+ topRight: Radius.circular(30)),
172
+ child: cell,
173
+ );
174
+ })),
175
+ ],
176
),
80
- Observer(
81
- builder: (_) => ListView.separated(
82
- padding: EdgeInsets.all(0),
83
- separatorBuilder: (context, _) => Container(
84
- height: 1, color: Theme.of(context).dividerColor),
85
- shrinkWrap: true,
86
- physics: NeverScrollableScrollPhysics(),
87
- itemCount: addressListViewModel.items.length,
88
- itemBuilder: (context, index) {
89
- final item = addressListViewModel.items[index];
90
- Widget cell = Container();
91
-
92
- if (item is WalletAccountListHeader) {
93
- cell = HeaderTile(
94
- onTap: () async => await showPopUp<void>(
95
- context: context,
96
- builder: (_) =>
97
- getIt.get<MoneroAccountListPage>()),
98
- title: S.of(context).accounts,
99
- icon: Icon(
100
- Icons.arrow_forward_ios,
101
- size: 14,
102
- color: Theme.of(context).textTheme.display1.color,
103
- ));
104
- }
105
-
106
- if (item is WalletAddressListHeader) {
107
- cell = HeaderTile(
108
- onTap: () => Navigator.of(context)
109
- .pushNamed(Routes.newSubaddress),
110
- title: S.of(context).addresses,
111
- icon: Icon(
112
- Icons.add,
113
- size: 20,
114
- color: Theme.of(context).textTheme.display1.color,
115
- ));
116
- }
117
-
118
- if (item is WalletAddressListItem) {
119
- cell = Observer(builder: (_) {
120
- final isCurrent = item.address ==
121
- addressListViewModel.address.address;
122
- final backgroundColor = isCurrent
123
- ? Theme.of(context)
124
- .textTheme
125
- .display3
126
- .decorationColor
127
- : Theme.of(context)
128
- .textTheme
129
- .display2
130
- .decorationColor;
131
- final textColor = isCurrent
132
- ? Theme.of(context).textTheme.display3.color
133
- : Theme.of(context).textTheme.display2.color;
134
-
135
- return AddressCell.fromItem(item,
136
- isCurrent: isCurrent,
137
- backgroundColor: backgroundColor,
138
- textColor: textColor,
139
- onTap: (_) => addressListViewModel.setAddress(item),
140
- onEdit: () => Navigator.of(context).pushNamed(
141
- Routes.newSubaddress,
142
- arguments: item));
143
- });
144
- }
145
-
146
- return index != 0
147
- ? cell
148
- : ClipRRect(
149
- borderRadius: BorderRadius.only(
150
- topLeft: Radius.circular(30),
151
- topRight: Radius.circular(30)),
152
- child: cell,
153
- );
154
- })),
155
- ],
156
- ),
157
- );
177
+ ));
178
}
179
}
lib/src/screens/receive/widgets/qr_widget.dart
+6
-2
@@ -11,7 +11,9 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_v
11
12
class QRWidget extends StatelessWidget {
13
QRWidget(
14
- {@required this.addressListViewModel, this.isAmountFieldShow = false})
14
+ {@required this.addressListViewModel,
15
+ this.isAmountFieldShow = false,
16
+ this.amountTextFieldFocusNode})
17
: amountController = TextEditingController(),
18
_formKey = GlobalKey<FormState>() {
19
amountController.addListener(() => addressListViewModel.amount =
@@ -21,6 +23,7 @@ class QRWidget extends StatelessWidget {
23
final WalletAddressListViewModel addressListViewModel;
24
final bool isAmountFieldShow;
25
final TextEditingController amountController;
26
+ final FocusNode amountTextFieldFocusNode;
27
final GlobalKey<FormState> _formKey;
28
29
@override
@@ -45,7 +48,7 @@ class QRWidget extends StatelessWidget {
48
data: addressListViewModel.uri.toString(),
49
backgroundColor: Colors.transparent,
50
foregroundColor: Colors.white,
48
- //Theme.of(context).textTheme.headline.color,
51
+ //Theme.of(context).textTheme.headline.color,
52
))))),
53
Spacer(flex: 3)
54
]),
@@ -68,6 +71,7 @@ class QRWidget extends StatelessWidget {
71
child: Form(
72
key: _formKey,
73
child: BaseTextFormField(
74
+ focusNode: amountTextFieldFocusNode,
75
controller: amountController,
76
keyboardType: TextInputType.numberWithOptions(
77
decimal: true),