1
import 'package:cake_wallet/routes.dart';
2
+import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart';
3
+import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
4
+import 'package:cake_wallet/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart';
5
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
6
+import 'package:cake_wallet/themes/theme_base.dart';
7
import 'dart:ui';
4
-import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
8
import 'package:cake_wallet/utils/request_review_handler.dart';
9
+import 'package:cake_wallet/utils/responsive_layout_util.dart';
10
import 'package:mobx/mobx.dart';
11
import 'package:flutter_mobx/flutter_mobx.dart';
12
import 'package:flutter/material.dart';
9
-import 'package:flutter/services.dart';
13
import 'package:cake_wallet/generated/i18n.dart';
14
import 'package:cake_wallet/core/execution_state.dart';
15
import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart';
16
import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
14
-import 'package:cake_wallet/src/widgets/list_row.dart';
15
-import 'package:cake_wallet/utils/show_bar.dart';
17
import 'package:cake_wallet/utils/show_pop_up.dart';
18
import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
19
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
19
-import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
20
import 'package:cake_wallet/src/screens/base_page.dart';
21
import 'package:cake_wallet/src/screens/exchange_trade/widgets/timer_widget.dart';
22
import 'package:cake_wallet/src/widgets/primary_button.dart';
30
final walletName = exchangeTradeViewModel.wallet.name;
31
32
final information = exchangeTradeViewModel.isSendable
33
- ? S.current.exchange_result_confirm(
34
- trade.amount, trade.from.toString(), walletName) +
33
+ ? S.current.exchange_trade_result_confirm(trade.amount, trade.from.toString(), walletName) +
34
exchangeTradeViewModel.extraInfo
35
: S.current.exchange_result_description(
36
trade.amount, trade.from.toString()) +
49
final ExchangeTradeViewModel exchangeTradeViewModel;
50
51
@override
53
- String get title => S.current.exchange;
52
+ String get title => S.current.swap;
53
+
54
+ @override
55
+ bool get gradientBackground => true;
56
+
57
+ @override
58
+ bool get gradientAll => true;
59
+
60
+ @override
61
+ bool get resizeToAvoidBottomInset => false;
62
+
63
+ @override
64
+ bool get extendBodyBehindAppBar => true;
65
+
66
+ @override
67
+ AppBarStyle get appBarStyle => AppBarStyle.transparent;
68
69
@override
70
Widget trailing(BuildContext context) {
88
}
89
90
@override
77
- Widget body(BuildContext context) =>
78
- ExchangeTradeForm(exchangeTradeViewModel);
91
+ Widget body(BuildContext context) => ExchangeTradeForm(
92
+ exchangeTradeViewModel,
93
+ currentTheme,
94
+ );
95
}
96
97
class ExchangeTradeForm extends StatefulWidget {
82
- ExchangeTradeForm(this.exchangeTradeViewModel);
98
+ ExchangeTradeForm(
99
+ this.exchangeTradeViewModel,
100
+ this.currentTheme,
101
+ );
102
103
final ExchangeTradeViewModel exchangeTradeViewModel;
104
+ final ThemeBase currentTheme;
105
106
@override
107
ExchangeTradeState createState() => ExchangeTradeState();
135
136
@override
137
Widget build(BuildContext context) {
118
- final copyImage = Image.asset('assets/images/copy_content.png',
119
- height: 16,
120
- width: 16,
121
- color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor);
122
-
138
_setEffects();
139
140
return Container(
141
child: ScrollableWithBottomSection(
127
- contentPadding: EdgeInsets.only(top: 10, bottom: 16),
128
- content: Observer(builder: (_) {
129
- final trade = widget.exchangeTradeViewModel.trade;
130
-
131
- return Column(
132
- children: <Widget>[
133
- trade.expiredAt != null
134
- ? Row(
135
- mainAxisSize: MainAxisSize.max,
136
- mainAxisAlignment: MainAxisAlignment.center,
137
- children: <Widget>[
138
- Text(
139
- S.of(context).offer_expires_in,
140
- style: TextStyle(
141
- fontSize: 14.0,
142
- fontWeight: FontWeight.w500,
143
- color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
144
- ),
145
- if (trade.expiredAt != null)
146
- TimerWidget(trade.expiredAt!,
147
- color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)
148
- ])
149
- : Offstage(),
150
- Padding(
151
- padding: EdgeInsets.only(top: 32),
152
- child: Row(children: <Widget>[
153
- Spacer(flex: 3),
154
- Flexible(
155
- flex: 4,
156
- child: Center(
157
- child: AspectRatio(
158
- aspectRatio: 1.0,
159
- child: Container(
160
- padding: EdgeInsets.all(5),
161
- decoration: BoxDecoration(
162
- border: Border.all(
163
- width: 3,
164
- color: Theme.of(context).extension<ExchangePageTheme>()!.qrCodeColor
165
- )
166
- ),
167
- child: QrImage(data: trade.inputAddress ?? fetchingLabel),
168
- )))),
169
- Spacer(flex: 3)
170
- ]),
171
- ),
172
- Padding(
173
- padding: EdgeInsets.only(top: 16),
174
- child: ListView.separated(
175
- shrinkWrap: true,
176
- physics: NeverScrollableScrollPhysics(),
177
- itemCount: widget.exchangeTradeViewModel.items.length,
178
- separatorBuilder: (context, index) => Container(
179
- height: 1,
180
- color: Theme.of(context).extension<ExchangePageTheme>()!.dividerCodeColor,
181
- ),
182
- itemBuilder: (context, index) {
183
- final item = widget.exchangeTradeViewModel.items[index];
184
- final value = item.data;
185
-
186
- final content = ListRow(
187
- title: item.title,
188
- value: value,
189
- valueFontSize: 14,
190
- image: item.isCopied ? copyImage : null,
191
- );
192
-
193
- return item.isCopied
194
- ? Builder(
195
- builder: (context) => GestureDetector(
196
- onTap: () {
197
- Clipboard.setData(
198
- ClipboardData(text: value));
199
- showBar<void>(context,
200
- S.of(context).copied_to_clipboard);
201
- },
202
- child: content,
203
- ))
204
- : content;
205
- },
206
- ),
207
- ),
208
- ],
209
- );
210
- }),
211
- bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24),
212
- bottomSection: Observer(builder: (_) {
213
- final trade = widget.exchangeTradeViewModel.trade;
214
- final sendingState =
215
- widget.exchangeTradeViewModel.sendViewModel.state;
216
-
217
- return widget.exchangeTradeViewModel.isSendable &&
218
- !(sendingState is TransactionCommitted)
219
- ? LoadingPrimaryButton(
220
- key: ValueKey('exchange_trade_page_confirm_sending_button_key'),
221
- isDisabled: trade.inputAddress == null ||
222
- trade.inputAddress!.isEmpty,
223
- isLoading: sendingState is IsExecutingState,
224
- onPressed: () =>
225
- widget.exchangeTradeViewModel.confirmSending(),
226
- text: S.of(context).confirm,
227
- color: Theme.of(context).primaryColor,
228
- textColor: Colors.white)
229
- : Offstage();
230
- })),
142
+ contentPadding: EdgeInsets.only(top: 10, bottom: 16),
143
+ content: Observer(builder: (_) {
144
+ final trade = widget.exchangeTradeViewModel.trade;
145
+
146
+ return Column(
147
+ children: <Widget>[
148
+ trade.expiredAt != null
149
+ ? Row(
150
+ mainAxisSize: MainAxisSize.max,
151
+ mainAxisAlignment: MainAxisAlignment.center,
152
+ children: <Widget>[
153
+ Text(
154
+ S.of(context).offer_expires_in,
155
+ style: TextStyle(
156
+ fontSize: 14.0,
157
+ fontWeight: FontWeight.w500,
158
+ color: Theme.of(context)
159
+ .extension<TransactionTradeTheme>()!
160
+ .detailsTitlesColor),
161
+ ),
162
+ if (trade.expiredAt != null)
163
+ TimerWidget(trade.expiredAt!,
164
+ color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)
165
+ ])
166
+ : Offstage(),
167
+ _ExchangeTradeItemsCardSection(
168
+ viewModel: widget.exchangeTradeViewModel,
169
+ currentTheme: widget.currentTheme,
170
+ ),
171
+ ],
172
+ );
173
+ }),
174
+ bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24),
175
+ bottomSection: Column(
176
+ children: [
177
+ PrimaryButton(
178
+ key: ValueKey('exchange_trade_page_send_from_external_button_key'),
179
+ text: S.current.send_from_external_wallet,
180
+ onPressed: () async {
181
+ Navigator.of(context).pushNamed(Routes.exchangeTradeExternalSendPage);
182
+ },
183
+ color: Theme.of(context).cardColor,
184
+ textColor: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor,
185
+ ),
186
+ SizedBox(height: 16),
187
+ Observer(
188
+ builder: (_) {
189
+ final trade = widget.exchangeTradeViewModel.trade;
190
+ final sendingState = widget.exchangeTradeViewModel.sendViewModel.state;
191
+
192
+ return widget.exchangeTradeViewModel.isSendable &&
193
+ !(sendingState is TransactionCommitted)
194
+ ? LoadingPrimaryButton(
195
+ key: ValueKey('exchange_trade_page_send_from_cake_button_key'),
196
+ isDisabled: trade.inputAddress == null || trade.inputAddress!.isEmpty,
197
+ isLoading: sendingState is IsExecutingState,
198
+ onPressed: () => widget.exchangeTradeViewModel.confirmSending(),
199
+ text:S.current.send_from_cake_wallet,
200
+ color: Theme.of(context).primaryColor,
201
+ textColor: Colors.white,
202
+ )
203
+ : Offstage();
204
+ },
205
+ ),
206
+ ],
207
+ ),
208
+ ),
209
);
210
}
211
390
}
391
}
392
}
393
+
394
+class _ExchangeTradeItemsCardSection extends StatelessWidget {
395
+ const _ExchangeTradeItemsCardSection({
396
+ required this.viewModel,
397
+ required this.currentTheme,
398
+ });
399
+
400
+ final ExchangeTradeViewModel viewModel;
401
+ final ThemeBase currentTheme;
402
+
403
+ @override
404
+ Widget build(BuildContext context) {
405
+ final firstExchangeCard = ExchangeTradeCardItemWidget(
406
+ currentTheme: currentTheme,
407
+ isReceiveDetailsCard: true,
408
+ exchangeTradeViewModel: viewModel,
409
+ );
410
+
411
+ final secondExchangeCard = ExchangeTradeCardItemWidget(
412
+ currentTheme: currentTheme,
413
+ isReceiveDetailsCard: false,
414
+ exchangeTradeViewModel: viewModel,
415
+ );
416
+
417
+ if (responsiveLayoutUtil.shouldRenderMobileUI) {
418
+ return MobileExchangeCardsSection(
419
+ firstExchangeCard: firstExchangeCard,
420
+ secondExchangeCard: secondExchangeCard,
421
+ );
422
+ }
423
+
424
+ return DesktopExchangeCardsSection(
425
+ firstExchangeCard: firstExchangeCard,
426
+ secondExchangeCard: secondExchangeCard,
427
+ );
428
+ }
429
+}