CAKE-20 | updated exchange and exchange template pages; created exchange_view_model and applied to exchange and exchange template pages; applied new design to menu widget; changed text validator and amount validator
BIN
assets/images/2.0x/eye_menu.png
Normal file
After Width: | Height: | Size: 939 B |
BIN
assets/images/2.0x/key_menu.png
Normal file
After Width: | Height: | Size: 923 B |
BIN
assets/images/2.0x/monero_menu.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/images/2.0x/nodes_menu.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/images/2.0x/open_book_menu.png
Normal file
After Width: | Height: | Size: 735 B |
BIN
assets/images/2.0x/reconnect_menu.png
Normal file
After Width: | Height: | Size: 875 B |
BIN
assets/images/2.0x/settings_menu.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
assets/images/2.0x/wallet_menu.png
Normal file
After Width: | Height: | Size: 659 B |
BIN
assets/images/3.0x/eye_menu.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/3.0x/key_menu.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/images/3.0x/monero_menu.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
assets/images/3.0x/nodes_menu.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/3.0x/open_book_menu.png
Normal file
After Width: | Height: | Size: 994 B |
BIN
assets/images/3.0x/reconnect_menu.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/images/3.0x/settings_menu.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/3.0x/wallet_menu.png
Normal file
After Width: | Height: | Size: 920 B |
BIN
assets/images/eye_menu.png
Normal file
After Width: | Height: | Size: 536 B |
BIN
assets/images/key_menu.png
Normal file
After Width: | Height: | Size: 518 B |
BIN
assets/images/monero_menu.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/nodes_menu.png
Normal file
After Width: | Height: | Size: 597 B |
BIN
assets/images/open_book_menu.png
Normal file
After Width: | Height: | Size: 454 B |
BIN
assets/images/reconnect_menu.png
Normal file
After Width: | Height: | Size: 495 B |
BIN
assets/images/settings_menu.png
Normal file
After Width: | Height: | Size: 594 B |
BIN
assets/images/wallet_menu.png
Normal file
After Width: | Height: | Size: 358 B |
|
@ -3,10 +3,11 @@ import 'package:cake_wallet/generated/i18n.dart';
|
|||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
|
||||
class AmountValidator extends TextValidator {
|
||||
AmountValidator({WalletType type})
|
||||
AmountValidator({WalletType type, bool isAutovalidate = false})
|
||||
: super(
|
||||
errorMessage: S.current.error_text_amount,
|
||||
pattern: _pattern(type),
|
||||
isAutovalidate: isAutovalidate,
|
||||
minLength: 0,
|
||||
maxLength: 0);
|
||||
|
||||
|
|
|
@ -16,18 +16,20 @@ class TextValidator extends Validator<String> {
|
|||
this.maxLength,
|
||||
this.pattern,
|
||||
this.length,
|
||||
this.isAutovalidate = false,
|
||||
String errorMessage})
|
||||
: super(errorMessage: errorMessage);
|
||||
|
||||
final int minLength;
|
||||
final int maxLength;
|
||||
final List<int> length;
|
||||
final bool isAutovalidate;
|
||||
String pattern;
|
||||
|
||||
@override
|
||||
bool isValid(String value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return false;
|
||||
return isAutovalidate ? true : false;
|
||||
}
|
||||
|
||||
return value.length > (minLength ?? 0) &&
|
||||
|
|
16
lib/di.dart
|
@ -10,6 +10,8 @@ import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart';
|
|||
import 'package:cake_wallet/src/screens/send/send_template_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/settings.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart';
|
||||
import 'package:cake_wallet/store/contact_list_store.dart';
|
||||
import 'package:cake_wallet/store/node_list_store.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
|
@ -42,6 +44,7 @@ import 'package:cake_wallet/view_model/settings/settings_view_model.dart';
|
|||
import 'package:cake_wallet/view_model/wallet_keys_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_seed_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
@ -299,4 +302,17 @@ Future setup(
|
|||
|
||||
getIt.registerFactory(
|
||||
() => NodeCreateOrEditPage(getIt.get<NodeCreateOrEditViewModel>()));
|
||||
|
||||
getIt.registerFactory(() =>
|
||||
ExchangeViewModel(
|
||||
wallet: getIt.get<AppStore>().wallet,
|
||||
exchangeTemplateStore: getIt.get<ExchangeTemplateStore>(),
|
||||
trades: tradesSource
|
||||
));
|
||||
|
||||
getIt.registerFactory(() =>
|
||||
ExchangePage(getIt.get<ExchangeViewModel>()));
|
||||
|
||||
getIt.registerFactory(() =>
|
||||
ExchangeTemplatePage(getIt.get<ExchangeViewModel>()));
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ class S implements WidgetsLocalizations {
|
|||
String get reconnect => "Reconnect";
|
||||
String get reconnect_alert_text => "Are you sure to reconnect?";
|
||||
String get reconnection => "Reconnection";
|
||||
String get refund_address => "Refund address";
|
||||
String get remove => "Remove";
|
||||
String get remove_node => "Remove node";
|
||||
String get remove_node_message => "Are you sure that you want to remove selected node?";
|
||||
|
@ -372,6 +373,8 @@ class $de extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "Unterbezahlt";
|
||||
@override
|
||||
String get refund_address => "Rückerstattungsadresse";
|
||||
@override
|
||||
String get welcome => "Willkommen zu";
|
||||
@override
|
||||
String get share_address => "Adresse teilen ";
|
||||
|
@ -998,6 +1001,8 @@ class $hi extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "के तहत भुगतान किया";
|
||||
@override
|
||||
String get refund_address => "वापसी का पता";
|
||||
@override
|
||||
String get welcome => "स्वागत हे सेवा मेरे";
|
||||
@override
|
||||
String get share_address => "पता साझा करें";
|
||||
|
@ -1624,6 +1629,8 @@ class $ru extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "Недоплаченная";
|
||||
@override
|
||||
String get refund_address => "Адрес возврата";
|
||||
@override
|
||||
String get welcome => "Приветствуем в";
|
||||
@override
|
||||
String get share_address => "Поделиться адресом";
|
||||
|
@ -2250,6 +2257,8 @@ class $ko extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "미지급";
|
||||
@override
|
||||
String get refund_address => "환불 주소";
|
||||
@override
|
||||
String get welcome => "환영 에";
|
||||
@override
|
||||
String get share_address => "주소 공유";
|
||||
|
@ -2876,6 +2885,8 @@ class $pt extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "Parcialmente paga";
|
||||
@override
|
||||
String get refund_address => "Endereço de reembolso";
|
||||
@override
|
||||
String get welcome => "Bem-vindo ao";
|
||||
@override
|
||||
String get share_address => "Compartilhar endereço";
|
||||
|
@ -3502,6 +3513,8 @@ class $uk extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "Недоплачена";
|
||||
@override
|
||||
String get refund_address => "Адреса повернення коштів";
|
||||
@override
|
||||
String get welcome => "Вітаємо в";
|
||||
@override
|
||||
String get share_address => "Поділитися адресою";
|
||||
|
@ -4128,6 +4141,8 @@ class $ja extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "支払不足";
|
||||
@override
|
||||
String get refund_address => "払い戻し住所";
|
||||
@override
|
||||
String get welcome => "ようこそ に";
|
||||
@override
|
||||
String get share_address => "住所を共有する";
|
||||
|
@ -4758,6 +4773,8 @@ class $pl extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "Niedopłacone";
|
||||
@override
|
||||
String get refund_address => "Adres zwrotu";
|
||||
@override
|
||||
String get welcome => "Witamy w";
|
||||
@override
|
||||
String get share_address => "Udostępnij adres";
|
||||
|
@ -5384,6 +5401,8 @@ class $es extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "Poco pagado";
|
||||
@override
|
||||
String get refund_address => "Dirección de reembolso";
|
||||
@override
|
||||
String get welcome => "Bienvenido";
|
||||
@override
|
||||
String get share_address => "Compartir dirección";
|
||||
|
@ -6010,6 +6029,8 @@ class $nl extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "Slecht betaald";
|
||||
@override
|
||||
String get refund_address => "Adres voor terugbetaling";
|
||||
@override
|
||||
String get welcome => "Welkom bij";
|
||||
@override
|
||||
String get share_address => "Deel adres";
|
||||
|
@ -6636,6 +6657,8 @@ class $zh extends S {
|
|||
@override
|
||||
String get trade_state_underpaid => "支付不足";
|
||||
@override
|
||||
String get refund_address => "退款地址";
|
||||
@override
|
||||
String get welcome => "歡迎來到";
|
||||
@override
|
||||
String get share_address => "分享地址";
|
||||
|
|
|
@ -23,8 +23,8 @@ class PaletteDark {
|
|||
static const Color lightDistantBlue = Color.fromRGBO(81, 96, 147, 1.0); // borderCardColor
|
||||
static const Color gray = Color.fromRGBO(140, 153, 201, 1.0); // walletCardText
|
||||
static const Color violetBlue = Color.fromRGBO(51, 63, 104, 1.0); // walletCardAddressField
|
||||
static const Color moderateBlue = Color.fromRGBO(63, 77, 122, 1.0); // walletCardSubAddressField
|
||||
static const Color darkNightBlue = Color.fromRGBO(33, 43, 73, 1.0); // historyPanel
|
||||
//static const Color moderateBlue = Color.fromRGBO(63, 77, 122, 1.0); // walletCardSubAddressField
|
||||
//static const Color darkNightBlue = Color.fromRGBO(33, 43, 73, 1.0); // historyPanel
|
||||
static const Color pigeonBlue = Color.fromRGBO(91, 112, 146, 1.0); // historyPanelText
|
||||
static const Color moderateNightBlue = Color.fromRGBO(39, 53, 96, 1.0); // historyPanelButton
|
||||
static const Color headerNightBlue = Color.fromRGBO(41, 52, 84, 1.0); // menuHeader
|
||||
|
@ -46,6 +46,12 @@ class PaletteDark {
|
|||
static const Color lightBlueGrey = Color.fromRGBO(125, 141, 183, 1.0);
|
||||
static const Color lightVioletBlue = Color.fromRGBO(56, 71, 109, 1.0);
|
||||
static const Color darkVioletBlue = Color.fromRGBO(49, 60, 96, 1.0);
|
||||
static const Color wildVioletBlue = Color.fromRGBO(45, 60, 97, 1.0);
|
||||
static const Color darkNightBlue = Color.fromRGBO(33, 45, 76, 1.0);
|
||||
static const Color blueGrey = Color.fromRGBO(87, 98, 138, 1.0);
|
||||
static const Color moderateBlue = Color.fromRGBO(60, 73, 118, 1.0);
|
||||
static const Color deepPurpleBlue = Color.fromRGBO(19, 29, 56, 1.0);
|
||||
static const Color lightOceanBlue = Color.fromRGBO(30, 42, 73, 1.0);
|
||||
|
||||
// FIXME: Rename.
|
||||
static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);
|
||||
|
|
|
@ -411,45 +411,12 @@ class Router {
|
|||
walletRestorationFromSeedVM: walletRestorationFromSeedVM));
|
||||
|
||||
case Routes.exchange:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => MultiProvider(providers: [
|
||||
Provider(create: (_) {
|
||||
final xmrtoprovider = XMRTOExchangeProvider();
|
||||
|
||||
return ExchangeStore(
|
||||
initialProvider: xmrtoprovider,
|
||||
initialDepositCurrency: CryptoCurrency.xmr,
|
||||
initialReceiveCurrency: CryptoCurrency.btc,
|
||||
trades: trades,
|
||||
providerList: [
|
||||
xmrtoprovider,
|
||||
ChangeNowExchangeProvider(),
|
||||
MorphTokenExchangeProvider(trades: trades)
|
||||
],
|
||||
walletStore: walletStore);
|
||||
}),
|
||||
], child: ExchangePage()));
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => getIt.get<ExchangePage>());
|
||||
|
||||
case Routes.exchangeTemplate:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => Provider(
|
||||
create: (_) {
|
||||
final xmrtoprovider = XMRTOExchangeProvider();
|
||||
|
||||
return ExchangeStore(
|
||||
initialProvider: xmrtoprovider,
|
||||
initialDepositCurrency: CryptoCurrency.xmr,
|
||||
initialReceiveCurrency: CryptoCurrency.btc,
|
||||
trades: trades,
|
||||
providerList: [
|
||||
xmrtoprovider,
|
||||
ChangeNowExchangeProvider(),
|
||||
MorphTokenExchangeProvider(trades: trades)
|
||||
],
|
||||
walletStore: walletStore);
|
||||
},
|
||||
child: ExchangeTemplatePage(),
|
||||
));
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => getIt.get<ExchangeTemplatePage>());
|
||||
|
||||
case Routes.settings:
|
||||
return MaterialPageRoute<void>(
|
||||
|
|
|
@ -19,10 +19,14 @@ abstract class BasePage extends StatelessWidget {
|
|||
|
||||
bool get resizeToAvoidBottomPadding => true;
|
||||
|
||||
Widget get endDrawer => null;
|
||||
|
||||
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
||||
|
||||
Widget Function(BuildContext, Widget) get rootWrapper => null;
|
||||
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
final _backArrowImage = Image.asset('assets/images/back_arrow.png',
|
||||
color: Colors.white);
|
||||
final _backArrowImageDarkTheme =
|
||||
|
@ -32,6 +36,8 @@ abstract class BasePage extends StatelessWidget {
|
|||
final _closeButtonImageDarkTheme =
|
||||
Image.asset('assets/images/close_button_dark_theme.png');
|
||||
|
||||
void onOpenEndDrawer() => _scaffoldKey.currentState.openEndDrawer();
|
||||
|
||||
void onClose(BuildContext context) => Navigator.of(context).pop();
|
||||
|
||||
Widget leading(BuildContext context) {
|
||||
|
@ -123,9 +129,11 @@ abstract class BasePage extends StatelessWidget {
|
|||
final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
|
||||
|
||||
final root = Scaffold(
|
||||
key: _scaffoldKey,
|
||||
backgroundColor:
|
||||
_isDarkTheme ? backgroundDarkColor : backgroundLightColor,
|
||||
resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
|
||||
endDrawer: endDrawer,
|
||||
appBar: appBar(context),
|
||||
body: body(context), //SafeArea(child: ),
|
||||
floatingActionButton: floatingActionButton(context));
|
||||
|
|
|
@ -23,6 +23,12 @@ class DashboardPage extends BasePage {
|
|||
@override
|
||||
Color get backgroundDarkColor => PaletteDark.backgroundColor;
|
||||
|
||||
@override
|
||||
Widget get endDrawer => MenuWidget(
|
||||
name: walletViewModel.name,
|
||||
subname: walletViewModel.subname,
|
||||
type: walletViewModel.type);
|
||||
|
||||
@override
|
||||
Widget middle(BuildContext context) {
|
||||
return SyncIndicator(dashboardViewModel: walletViewModel);
|
||||
|
@ -40,14 +46,7 @@ class DashboardPage extends BasePage {
|
|||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
padding: EdgeInsets.all(0),
|
||||
onPressed: () async {
|
||||
await showDialog<void>(
|
||||
builder: (_) => MenuWidget(
|
||||
name: walletViewModel.name,
|
||||
subname: walletViewModel.subname,
|
||||
type: walletViewModel.type),
|
||||
context: context);
|
||||
},
|
||||
onPressed: () => onOpenEndDrawer(),
|
||||
child: menuButton
|
||||
)
|
||||
);
|
||||
|
|
|
@ -20,13 +20,13 @@ class WalletMenu {
|
|||
];
|
||||
|
||||
final List<Image> images = [
|
||||
Image.asset('assets/images/reconnect.png'),
|
||||
Image.asset('assets/images/wallet.png'),
|
||||
Image.asset('assets/images/nodes.png'),
|
||||
Image.asset('assets/images/eye.png'),
|
||||
Image.asset('assets/images/key.png'),
|
||||
Image.asset('assets/images/open_book.png'),
|
||||
Image.asset('assets/images/settings.png'),
|
||||
Image.asset('assets/images/reconnect_menu.png', height: 16, width: 16),
|
||||
Image.asset('assets/images/wallet_menu.png', height: 16, width: 16),
|
||||
Image.asset('assets/images/nodes_menu.png', height: 16, width: 16),
|
||||
Image.asset('assets/images/eye_menu.png', height: 16, width: 16),
|
||||
Image.asset('assets/images/key_menu.png', height: 16, width: 16),
|
||||
Image.asset('assets/images/open_book_menu.png', height: 16, width: 16),
|
||||
Image.asset('assets/images/settings_menu.png', height: 16, width: 16),
|
||||
];
|
||||
|
||||
final BuildContext context;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:ui';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
|
||||
|
@ -15,7 +16,7 @@ class MenuWidget extends StatefulWidget {
|
|||
}
|
||||
|
||||
class MenuWidgetState extends State<MenuWidget> {
|
||||
final moneroIcon = Image.asset('assets/images/monero.png');
|
||||
final moneroIcon = Image.asset('assets/images/monero_menu.png');
|
||||
final bitcoinIcon = Image.asset('assets/images/bitcoin.png');
|
||||
final largeScreen = 731;
|
||||
|
||||
|
@ -36,10 +37,10 @@ class MenuWidgetState extends State<MenuWidget> {
|
|||
screenHeight = 0;
|
||||
opacity = 0;
|
||||
|
||||
headerHeight = 120;
|
||||
headerHeight = 125;
|
||||
tileHeight = 75;
|
||||
fromTopEdge = 50;
|
||||
fromBottomEdge = 30;
|
||||
fromBottomEdge = 21;//30;
|
||||
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback(afterLayout);
|
||||
|
@ -66,189 +67,139 @@ class MenuWidgetState extends State<MenuWidget> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletMenu = WalletMenu(context);
|
||||
// final walletStore = Provider.of<WalletStore>(context);
|
||||
final itemCount = walletMenu.items.length;
|
||||
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
return SafeArea(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 24),
|
||||
child: Container(
|
||||
height: 60,
|
||||
width: 4,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(2)),
|
||||
color: Theme.of(context).hintColor),
|
||||
borderRadius: BorderRadius.all(Radius.circular(2)),
|
||||
color: Theme.of(context).hintColor),
|
||||
)),
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => null,
|
||||
child: Container(
|
||||
width: menuWidth,
|
||||
height: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(24),
|
||||
bottomLeft: Radius.circular(24)),
|
||||
color: Theme.of(context).primaryTextTheme.display1.color),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(24),
|
||||
bottomLeft: Radius.circular(24)),
|
||||
child: ListView.separated(
|
||||
itemBuilder: (_, index) {
|
||||
if (index == 0) {
|
||||
return Container(
|
||||
height: headerHeight,
|
||||
padding: EdgeInsets.only(
|
||||
left: 24,
|
||||
top: fromTopEdge,
|
||||
right: 24,
|
||||
bottom: fromBottomEdge),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.only(topLeft: Radius.circular(24)),
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.display2
|
||||
.color),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_iconFor(type: widget.type),
|
||||
SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Container(
|
||||
height: 40,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: widget.subname != null
|
||||
? MainAxisAlignment.spaceBetween
|
||||
: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
widget.name,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color,
|
||||
decoration: TextDecoration.none,
|
||||
fontFamily: 'Avenir Next',
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (widget.subname != null)
|
||||
Text(
|
||||
widget.subname,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.caption
|
||||
.color,
|
||||
decoration: TextDecoration.none,
|
||||
fontFamily: 'Avenir Next',
|
||||
fontSize: 12),
|
||||
)
|
||||
],
|
||||
),
|
||||
))
|
||||
],
|
||||
child: Container(
|
||||
width: menuWidth,
|
||||
height: double.infinity,
|
||||
color: PaletteDark.deepPurpleBlue,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
height: headerHeight,
|
||||
padding: EdgeInsets.only(
|
||||
left: 24,
|
||||
top: fromTopEdge,
|
||||
right: 24,
|
||||
bottom: fromBottomEdge),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_iconFor(type: widget.type),
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Container(
|
||||
height: 42,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: widget.subname != null
|
||||
? MainAxisAlignment.spaceBetween
|
||||
: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
widget.name,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (widget.subname != null)
|
||||
Text(
|
||||
widget.subname,
|
||||
style: TextStyle(
|
||||
color: PaletteDark.darkCyanBlue,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12),
|
||||
)
|
||||
],
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
Container(
|
||||
height: 1,
|
||||
color: PaletteDark.lightOceanBlue,
|
||||
),
|
||||
ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (_, index) {
|
||||
|
||||
index -= 1;
|
||||
final item = walletMenu.items[index];
|
||||
final image = walletMenu.images[index] ?? Offstage();
|
||||
final item = walletMenu.items[index];
|
||||
final image = walletMenu.images[index] ?? Offstage();
|
||||
final isLastTile = index == itemCount - 1;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
walletMenu.action(index);
|
||||
},
|
||||
child: index == itemCount - 1
|
||||
? Container(
|
||||
height: headerHeight,
|
||||
padding: EdgeInsets.only(
|
||||
left: 24,
|
||||
right: 24,
|
||||
top: fromBottomEdge,
|
||||
bottom: fromTopEdge),
|
||||
alignment: Alignment.topLeft,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(24)),
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.display1
|
||||
.color,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
image,
|
||||
SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Text(
|
||||
item,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color,
|
||||
fontFamily: 'Avenir Next',
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold),
|
||||
))
|
||||
],
|
||||
),
|
||||
)
|
||||
: Container(
|
||||
height: tileHeight,
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.display1
|
||||
.color,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
image,
|
||||
SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Text(
|
||||
item,
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title
|
||||
.color,
|
||||
fontFamily: 'Avenir Next',
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold),
|
||||
))
|
||||
],
|
||||
),
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
walletMenu.action(index);
|
||||
},
|
||||
child: Container(
|
||||
height: isLastTile
|
||||
? headerHeight
|
||||
: tileHeight,
|
||||
padding: isLastTile
|
||||
? EdgeInsets.only(
|
||||
left: 24,
|
||||
right: 24,
|
||||
top: fromBottomEdge,
|
||||
bottom: fromTopEdge)
|
||||
: EdgeInsets.only(left: 24, right: 24),
|
||||
alignment: isLastTile ? Alignment.topLeft : null,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
image,
|
||||
SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Text(
|
||||
item,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold),
|
||||
))
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, index) => Container(
|
||||
height: 1,
|
||||
color: PaletteDark.lightOceanBlue,
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, index) => Container(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
itemCount: itemCount + 1),
|
||||
),
|
||||
),
|
||||
))
|
||||
],
|
||||
itemCount: itemCount)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,66 +1,40 @@
|
|||
import 'dart:ui';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange/exchange_store.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange_template/exchange_template_store.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/base_exchange_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/trail_button.dart';
|
||||
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
|
||||
|
||||
class ExchangePage extends BasePage {
|
||||
ExchangePage(this.exchangeViewModel);
|
||||
|
||||
final ExchangeViewModel exchangeViewModel;
|
||||
|
||||
@override
|
||||
String get title => S.current.exchange;
|
||||
|
||||
@override
|
||||
Color get backgroundLightColor => Palette.darkLavender;
|
||||
Color get backgroundLightColor => PaletteDark.wildVioletBlue;
|
||||
|
||||
@override
|
||||
Color get backgroundDarkColor => PaletteDark.moderateBlue;
|
||||
Color get backgroundDarkColor => PaletteDark.wildVioletBlue;
|
||||
|
||||
@override
|
||||
Widget middle(BuildContext context) {
|
||||
final exchangeStore = Provider.of<ExchangeStore>(context);
|
||||
|
||||
return PresentProviderPicker(exchangeStore: exchangeStore);
|
||||
}
|
||||
Widget middle(BuildContext context) =>
|
||||
PresentProviderPicker(exchangeViewModel: exchangeViewModel);
|
||||
|
||||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
final exchangeStore = Provider.of<ExchangeStore>(context);
|
||||
|
||||
return TrailButton(
|
||||
caption: S.of(context).reset,
|
||||
onPressed: () => exchangeStore.reset()
|
||||
);
|
||||
}
|
||||
Widget trailing(BuildContext context) =>
|
||||
TrailButton(
|
||||
caption: S.of(context).reset,
|
||||
onPressed: () => exchangeViewModel.reset()
|
||||
);
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => ExchangeForm();
|
||||
}
|
||||
|
||||
class ExchangeForm extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => ExchangeFormState();
|
||||
}
|
||||
|
||||
class ExchangeFormState extends State<ExchangeForm> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final exchangeStore = Provider.of<ExchangeStore>(context);
|
||||
final walletStore = Provider.of<WalletStore>(context);
|
||||
final exchangeTemplateStore = Provider.of<ExchangeTemplateStore>(context);
|
||||
|
||||
return BaseExchangeWidget(
|
||||
exchangeStore: exchangeStore,
|
||||
walletStore: walletStore,
|
||||
exchangeTemplateStore: exchangeTemplateStore,
|
||||
isTemplate: false
|
||||
);
|
||||
}
|
||||
Widget body(BuildContext context) =>
|
||||
BaseExchangeWidget(exchangeViewModel: exchangeViewModel);
|
||||
}
|
||||
|
|
|
@ -1,55 +1,32 @@
|
|||
import 'dart:ui';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange/exchange_store.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange_template/exchange_template_store.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/base_exchange_widget.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
|
||||
|
||||
class ExchangeTemplatePage extends BasePage {
|
||||
ExchangeTemplatePage(this.exchangeViewModel);
|
||||
|
||||
final ExchangeViewModel exchangeViewModel;
|
||||
|
||||
@override
|
||||
String get title => S.current.exchange_new_template;
|
||||
|
||||
@override
|
||||
Color get backgroundLightColor => Palette.darkLavender;
|
||||
Color get backgroundLightColor => PaletteDark.wildVioletBlue;
|
||||
|
||||
@override
|
||||
Color get backgroundDarkColor => PaletteDark.moderateBlue;
|
||||
Color get backgroundDarkColor => PaletteDark.wildVioletBlue;
|
||||
|
||||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
final exchangeStore = Provider.of<ExchangeStore>(context);
|
||||
|
||||
return PresentProviderPicker(exchangeStore: exchangeStore);
|
||||
}
|
||||
Widget trailing(BuildContext context) =>
|
||||
PresentProviderPicker(exchangeViewModel: exchangeViewModel);
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => ExchangeTemplateForm();
|
||||
}
|
||||
|
||||
class ExchangeTemplateForm extends StatefulWidget{
|
||||
@override
|
||||
ExchangeTemplateFormState createState() => ExchangeTemplateFormState();
|
||||
}
|
||||
|
||||
class ExchangeTemplateFormState extends State<ExchangeTemplateForm> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final exchangeStore = Provider.of<ExchangeStore>(context);
|
||||
final walletStore = Provider.of<WalletStore>(context);
|
||||
final exchangeTemplateStore = Provider.of<ExchangeTemplateStore>(context);
|
||||
|
||||
return BaseExchangeWidget(
|
||||
exchangeStore: exchangeStore,
|
||||
walletStore: walletStore,
|
||||
exchangeTemplateStore: exchangeTemplateStore,
|
||||
isTemplate: true
|
||||
);
|
||||
}
|
||||
Widget body(BuildContext context) =>
|
||||
BaseExchangeWidget(exchangeViewModel: exchangeViewModel, isTemplate: true);
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
import 'dart:ui';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/exchange_template.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/template_tile.dart';
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
@ -12,49 +14,37 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
|||
import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange/limits_state.dart';
|
||||
import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange/exchange_store.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/widgets/top_panel.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange_template/exchange_template_store.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
|
||||
|
||||
class BaseExchangeWidget extends StatefulWidget {
|
||||
BaseExchangeWidget({
|
||||
@ required this.exchangeStore,
|
||||
@ required this.walletStore,
|
||||
@ required this.exchangeTemplateStore,
|
||||
@ required this.isTemplate,
|
||||
@ required this.exchangeViewModel,
|
||||
this.isTemplate = false,
|
||||
});
|
||||
|
||||
final ExchangeStore exchangeStore;
|
||||
final WalletStore walletStore;
|
||||
final ExchangeTemplateStore exchangeTemplateStore;
|
||||
final ExchangeViewModel exchangeViewModel;
|
||||
final bool isTemplate;
|
||||
|
||||
@override
|
||||
BaseExchangeWidgetState createState() =>
|
||||
BaseExchangeWidgetState(
|
||||
exchangeStore: exchangeStore,
|
||||
walletStore: walletStore,
|
||||
exchangeTemplateStore: exchangeTemplateStore,
|
||||
exchangeViewModel: exchangeViewModel,
|
||||
isTemplate: isTemplate
|
||||
);
|
||||
}
|
||||
|
||||
class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
||||
BaseExchangeWidgetState({
|
||||
@ required this.exchangeStore,
|
||||
@ required this.walletStore,
|
||||
@ required this.exchangeTemplateStore,
|
||||
@ required this.exchangeViewModel,
|
||||
@ required this.isTemplate,
|
||||
});
|
||||
|
||||
final ExchangeStore exchangeStore;
|
||||
final WalletStore walletStore;
|
||||
final ExchangeTemplateStore exchangeTemplateStore;
|
||||
final ExchangeViewModel exchangeViewModel;
|
||||
final bool isTemplate;
|
||||
|
||||
final depositKey = GlobalKey<ExchangeCardState>();
|
||||
|
@ -64,31 +54,31 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Image arrowBottomPurple = Image.asset(
|
||||
final arrowBottomPurple = Image.asset(
|
||||
'assets/images/arrow_bottom_purple_icon.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
color: Colors.white,
|
||||
height: 8,
|
||||
);
|
||||
final Image arrowBottomCakeGreen = Image.asset(
|
||||
final arrowBottomCakeGreen = Image.asset(
|
||||
'assets/images/arrow_bottom_cake_green.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
color: Colors.white,
|
||||
height: 8,
|
||||
);
|
||||
|
||||
final depositWalletName =
|
||||
exchangeStore.depositCurrency == CryptoCurrency.xmr
|
||||
? walletStore.name
|
||||
exchangeViewModel.depositCurrency == CryptoCurrency.xmr
|
||||
? exchangeViewModel.wallet.name
|
||||
: null;
|
||||
final receiveWalletName =
|
||||
exchangeStore.receiveCurrency == CryptoCurrency.xmr
|
||||
? walletStore.name
|
||||
exchangeViewModel.receiveCurrency == CryptoCurrency.xmr
|
||||
? exchangeViewModel.wallet.name
|
||||
: null;
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) => _setReactions(context, exchangeStore, walletStore));
|
||||
(_) => _setReactions(context, exchangeViewModel));
|
||||
|
||||
return Container(
|
||||
color: Theme.of(context).backgroundColor,
|
||||
color: PaletteDark.backgroundColor,
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ScrollableWithBottomSection(
|
||||
|
@ -96,73 +86,60 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
content: Column(
|
||||
children: <Widget>[
|
||||
TopPanel(
|
||||
color: Theme.of(context).accentTextTheme.title.backgroundColor,
|
||||
edgeInsets: EdgeInsets.only(bottom: 24),
|
||||
color: PaletteDark.darkNightBlue,
|
||||
edgeInsets: EdgeInsets.only(bottom: 32),
|
||||
widget: Column(
|
||||
children: <Widget>[
|
||||
TopPanel(
|
||||
color: Theme.of(context).accentTextTheme.title.color,
|
||||
edgeInsets: EdgeInsets.fromLTRB(24, 29, 24, 32),
|
||||
color: PaletteDark.wildVioletBlue,
|
||||
widget: Observer(
|
||||
builder: (_) => ExchangeCard(
|
||||
key: depositKey,
|
||||
title: S.of(context).you_will_send,
|
||||
initialCurrency: exchangeStore.depositCurrency,
|
||||
initialCurrency: exchangeViewModel.depositCurrency,
|
||||
initialWalletName: depositWalletName,
|
||||
initialAddress:
|
||||
exchangeStore.depositCurrency == walletStore.type
|
||||
? walletStore.address
|
||||
: exchangeStore.depositAddress,
|
||||
exchangeViewModel.depositCurrency == exchangeViewModel.wallet.currency
|
||||
? exchangeViewModel.wallet.address
|
||||
: exchangeViewModel.depositAddress,
|
||||
initialIsAmountEditable: true,
|
||||
initialIsAddressEditable: exchangeStore.isDepositAddressEnabled,
|
||||
initialIsAddressEditable: exchangeViewModel.isDepositAddressEnabled,
|
||||
isAmountEstimated: false,
|
||||
currencies: CryptoCurrency.all,
|
||||
onCurrencySelected: (currency) =>
|
||||
exchangeStore.changeDepositCurrency(currency: currency),
|
||||
exchangeViewModel.changeDepositCurrency(currency: currency),
|
||||
imageArrow: arrowBottomPurple,
|
||||
currencyButtonColor: Theme.of(context).accentTextTheme.title.color,
|
||||
addressButtonsColor: Theme.of(context).accentTextTheme.title.backgroundColor,
|
||||
currencyValueValidator: (value) {
|
||||
exchangeStore.validateCryptoCurrency(value);
|
||||
return exchangeStore.errorMessage;
|
||||
},
|
||||
addressTextFieldValidator: (value) {
|
||||
exchangeStore.validateAddress(value,
|
||||
cryptoCurrency: exchangeStore.depositCurrency);
|
||||
return exchangeStore.errorMessage;
|
||||
},
|
||||
currencyButtonColor: PaletteDark.wildVioletBlue,
|
||||
addressButtonsColor: PaletteDark.moderateBlue,
|
||||
currencyValueValidator: exchangeViewModel.amountValidator,
|
||||
addressTextFieldValidator: exchangeViewModel.addressValidator,
|
||||
),
|
||||
)
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 32, left: 24, right: 24),
|
||||
padding: EdgeInsets.only(top: 29, left: 24, right: 24),
|
||||
child: Observer(
|
||||
builder: (_) => ExchangeCard(
|
||||
key: receiveKey,
|
||||
title: S.of(context).you_will_get,
|
||||
initialCurrency: exchangeStore.receiveCurrency,
|
||||
initialCurrency: exchangeViewModel.receiveCurrency,
|
||||
initialWalletName: receiveWalletName,
|
||||
initialAddress:
|
||||
exchangeStore.receiveCurrency == walletStore.type
|
||||
? walletStore.address
|
||||
: exchangeStore.receiveAddress,
|
||||
exchangeViewModel.receiveCurrency == exchangeViewModel.wallet.currency
|
||||
? exchangeViewModel.wallet.address
|
||||
: exchangeViewModel.receiveAddress,
|
||||
initialIsAmountEditable: false,
|
||||
initialIsAddressEditable: exchangeStore.isReceiveAddressEnabled,
|
||||
initialIsAddressEditable: exchangeViewModel.isReceiveAddressEnabled,
|
||||
isAmountEstimated: true,
|
||||
currencies: CryptoCurrency.all,
|
||||
onCurrencySelected: (currency) => exchangeStore
|
||||
onCurrencySelected: (currency) => exchangeViewModel
|
||||
.changeReceiveCurrency(currency: currency),
|
||||
imageArrow: arrowBottomCakeGreen,
|
||||
currencyButtonColor: Theme.of(context).accentTextTheme.title.backgroundColor,
|
||||
addressButtonsColor: Theme.of(context).accentTextTheme.title.color,
|
||||
currencyValueValidator: (value) {
|
||||
exchangeStore.validateCryptoCurrency(value);
|
||||
return exchangeStore.errorMessage;
|
||||
},
|
||||
addressTextFieldValidator: (value) {
|
||||
exchangeStore.validateAddress(value,
|
||||
cryptoCurrency: exchangeStore.receiveCurrency);
|
||||
return exchangeStore.errorMessage;
|
||||
},
|
||||
currencyButtonColor: PaletteDark.darkNightBlue,
|
||||
addressButtonsColor: PaletteDark.moderateBlue,
|
||||
currencyValueValidator: exchangeViewModel.amountValidator,
|
||||
addressTextFieldValidator: exchangeViewModel.addressValidator,
|
||||
)),
|
||||
)
|
||||
],
|
||||
|
@ -172,7 +149,7 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
? Offstage()
|
||||
: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: 32,
|
||||
top: 30,
|
||||
left: 24,
|
||||
bottom: 24
|
||||
),
|
||||
|
@ -184,7 +161,7 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
color: PaletteDark.darkCyanBlue
|
||||
),
|
||||
)
|
||||
],
|
||||
|
@ -196,66 +173,90 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
height: 40,
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(left: 24),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
final itemCount = exchangeTemplateStore.templates.length + 1;
|
||||
|
||||
return ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: itemCount,
|
||||
itemBuilder: (context, index) {
|
||||
|
||||
if (index == 0) {
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.exchangeTemplate),
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(right: 10),
|
||||
child: DottedBorder(
|
||||
borderType: BorderType.RRect,
|
||||
dashPattern: [8, 4],
|
||||
color: Theme.of(context).accentTextTheme.title.backgroundColor,
|
||||
strokeWidth: 2,
|
||||
radius: Radius.circular(20),
|
||||
child: Container(
|
||||
height: 40,
|
||||
width: 75,
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
color: Colors.transparent,
|
||||
),
|
||||
child: Text(
|
||||
S.of(context).send_new,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
),
|
||||
),
|
||||
)
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.exchangeTemplate),
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 1, right: 10),
|
||||
child: DottedBorder(
|
||||
borderType: BorderType.RRect,
|
||||
dashPattern: [6, 4],
|
||||
color: PaletteDark.darkCyanBlue,
|
||||
strokeWidth: 2,
|
||||
radius: Radius.circular(20),
|
||||
child: Container(
|
||||
height: 34,
|
||||
width: 75,
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
color: Colors.transparent,
|
||||
),
|
||||
child: Text(
|
||||
S.of(context).send_new,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: PaletteDark.darkCyanBlue
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) {
|
||||
final templates = exchangeViewModel.templates;
|
||||
final itemCount = exchangeViewModel.templates.length;
|
||||
|
||||
index -= 1;
|
||||
return ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: itemCount,
|
||||
itemBuilder: (context, index) {
|
||||
final template = templates[index];
|
||||
|
||||
final template = exchangeTemplateStore.templates[index];
|
||||
|
||||
return TemplateTile(
|
||||
amount: template.amount,
|
||||
from: template.depositCurrency,
|
||||
to: template.receiveCurrency,
|
||||
onTap: () {
|
||||
applyTemplate(exchangeStore, template);
|
||||
return TemplateTile(
|
||||
key: UniqueKey(),
|
||||
amount: template.amount,
|
||||
from: template.depositCurrency,
|
||||
to: template.receiveCurrency,
|
||||
onTap: () {
|
||||
applyTemplate(exchangeViewModel, template);
|
||||
},
|
||||
onRemove: () {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (dialogContext) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).template,
|
||||
alertContent: S.of(context).confirm_delete_template,
|
||||
leftButtonText: S.of(context).delete,
|
||||
rightButtonText: S.of(context).cancel,
|
||||
actionLeftButton: () {
|
||||
Navigator.of(dialogContext).pop();
|
||||
exchangeViewModel.exchangeTemplateStore.remove(template: template);
|
||||
exchangeViewModel.exchangeTemplateStore.update();
|
||||
},
|
||||
actionRightButton: () => Navigator.of(dialogContext).pop()
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -265,14 +266,15 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
padding: EdgeInsets.only(bottom: 15),
|
||||
child: Observer(builder: (_) {
|
||||
final description =
|
||||
exchangeStore.provider is XMRTOExchangeProvider
|
||||
exchangeViewModel.provider is XMRTOExchangeProvider
|
||||
? S.of(context).amount_is_guaranteed
|
||||
: S.of(context).amount_is_estimate;
|
||||
return Center(
|
||||
child: Text(
|
||||
description,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.caption.color,
|
||||
color: PaletteDark.darkCyanBlue,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12
|
||||
),
|
||||
),
|
||||
|
@ -283,15 +285,15 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
? PrimaryButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState.validate()) {
|
||||
exchangeTemplateStore.addTemplate(
|
||||
amount: exchangeStore.depositAmount,
|
||||
depositCurrency: exchangeStore.depositCurrency.toString(),
|
||||
receiveCurrency: exchangeStore.receiveCurrency.toString(),
|
||||
provider: exchangeStore.provider.toString(),
|
||||
depositAddress: exchangeStore.depositAddress,
|
||||
receiveAddress: exchangeStore.receiveAddress
|
||||
exchangeViewModel.exchangeTemplateStore.addTemplate(
|
||||
amount: exchangeViewModel.depositAmount,
|
||||
depositCurrency: exchangeViewModel.depositCurrency.toString(),
|
||||
receiveCurrency: exchangeViewModel.receiveCurrency.toString(),
|
||||
provider: exchangeViewModel.provider.toString(),
|
||||
depositAddress: exchangeViewModel.depositAddress,
|
||||
receiveAddress: exchangeViewModel.receiveAddress
|
||||
);
|
||||
exchangeTemplateStore.update();
|
||||
exchangeViewModel.exchangeTemplateStore.update();
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
|
@ -304,41 +306,47 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
text: S.of(context).exchange,
|
||||
onPressed: () {
|
||||
if (_formKey.currentState.validate()) {
|
||||
exchangeStore.createTrade();
|
||||
exchangeViewModel.createTrade();
|
||||
}
|
||||
},
|
||||
color: Colors.blue,
|
||||
textColor: Colors.white,
|
||||
isLoading: exchangeStore.tradeState is TradeIsCreating,
|
||||
isLoading: exchangeViewModel.tradeState is TradeIsCreating,
|
||||
)),
|
||||
]),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
void applyTemplate(ExchangeStore store, ExchangeTemplate template) {
|
||||
store.changeDepositCurrency(currency: CryptoCurrency.fromString(template.depositCurrency));
|
||||
store.changeReceiveCurrency(currency: CryptoCurrency.fromString(template.receiveCurrency));
|
||||
void applyTemplate(ExchangeViewModel exchangeViewModel,
|
||||
ExchangeTemplate template) {
|
||||
exchangeViewModel.changeDepositCurrency(
|
||||
currency: CryptoCurrency.fromString(template.depositCurrency));
|
||||
exchangeViewModel.changeReceiveCurrency(
|
||||
currency: CryptoCurrency.fromString(template.receiveCurrency));
|
||||
|
||||
switch (template.provider) {
|
||||
case 'XMR.TO':
|
||||
store.changeProvider(provider: store.providerList[0]);
|
||||
exchangeViewModel.changeProvider(
|
||||
provider: exchangeViewModel.providerList[0]);
|
||||
break;
|
||||
case 'ChangeNOW':
|
||||
store.changeProvider(provider: store.providerList[1]);
|
||||
exchangeViewModel.changeProvider(
|
||||
provider: exchangeViewModel.providerList[1]);
|
||||
break;
|
||||
case 'MorphToken':
|
||||
store.changeProvider(provider: store.providerList[2]);
|
||||
exchangeViewModel.changeProvider(
|
||||
provider: exchangeViewModel.providerList[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
store.changeDepositAmount(amount: template.amount);
|
||||
store.depositAddress = template.depositAddress;
|
||||
store.receiveAddress = template.receiveAddress;
|
||||
exchangeViewModel.changeDepositAmount(amount: template.amount);
|
||||
exchangeViewModel.depositAddress = template.depositAddress;
|
||||
exchangeViewModel.receiveAddress = template.receiveAddress;
|
||||
}
|
||||
|
||||
void _setReactions(
|
||||
BuildContext context, ExchangeStore store, WalletStore walletStore) {
|
||||
BuildContext context, ExchangeViewModel exchangeViewModel) {
|
||||
if (_isReactionsSet) {
|
||||
return;
|
||||
}
|
||||
|
@ -347,7 +355,7 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
final depositAmountController = depositKey.currentState.amountController;
|
||||
final receiveAddressController = receiveKey.currentState.addressController;
|
||||
final receiveAmountController = receiveKey.currentState.amountController;
|
||||
final limitsState = store.limitsState;
|
||||
final limitsState = exchangeViewModel.limitsState;
|
||||
|
||||
if (limitsState is LimitsLoadedSuccessfully) {
|
||||
final min = limitsState.limits.min != null
|
||||
|
@ -360,63 +368,62 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
key.currentState.changeLimits(min: min, max: max);
|
||||
}
|
||||
|
||||
_onCurrencyChange(store.receiveCurrency, walletStore, receiveKey);
|
||||
_onCurrencyChange(store.depositCurrency, walletStore, depositKey);
|
||||
_onCurrencyChange(exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey);
|
||||
_onCurrencyChange(exchangeViewModel.depositCurrency, exchangeViewModel, depositKey);
|
||||
|
||||
reaction(
|
||||
(_) => walletStore.name,
|
||||
(_) => exchangeViewModel.wallet.name,
|
||||
(String _) => _onWalletNameChange(
|
||||
walletStore, store.receiveCurrency, receiveKey));
|
||||
exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey));
|
||||
|
||||
reaction(
|
||||
(_) => walletStore.name,
|
||||
(_) => exchangeViewModel.wallet.name,
|
||||
(String _) => _onWalletNameChange(
|
||||
walletStore, store.depositCurrency, depositKey));
|
||||
exchangeViewModel, exchangeViewModel.depositCurrency, depositKey));
|
||||
|
||||
reaction(
|
||||
(_) => store.receiveCurrency,
|
||||
(_) => exchangeViewModel.receiveCurrency,
|
||||
(CryptoCurrency currency) =>
|
||||
_onCurrencyChange(currency, walletStore, receiveKey));
|
||||
_onCurrencyChange(currency, exchangeViewModel, receiveKey));
|
||||
|
||||
reaction(
|
||||
(_) => store.depositCurrency,
|
||||
(_) => exchangeViewModel.depositCurrency,
|
||||
(CryptoCurrency currency) =>
|
||||
_onCurrencyChange(currency, walletStore, depositKey));
|
||||
_onCurrencyChange(currency, exchangeViewModel, depositKey));
|
||||
|
||||
reaction((_) => store.depositAmount, (String amount) {
|
||||
reaction((_) => exchangeViewModel.depositAmount, (String amount) {
|
||||
if (depositKey.currentState.amountController.text != amount) {
|
||||
depositKey.currentState.amountController.text = amount;
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => store.depositAddress, (String address) {
|
||||
reaction((_) => exchangeViewModel.depositAddress, (String address) {
|
||||
if (depositKey.currentState.addressController.text != address) {
|
||||
depositKey.currentState.addressController.text = address;
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => store.isDepositAddressEnabled, (bool isEnabled) {
|
||||
reaction((_) => exchangeViewModel.isDepositAddressEnabled, (bool isEnabled) {
|
||||
depositKey.currentState.isAddressEditable(isEditable: isEnabled);
|
||||
});
|
||||
|
||||
reaction((_) => store.receiveAmount, (String amount) {
|
||||
if (receiveKey.currentState.amountController.text !=
|
||||
store.receiveAmount) {
|
||||
reaction((_) => exchangeViewModel.receiveAmount, (String amount) {
|
||||
if (receiveKey.currentState.amountController.text != amount) {
|
||||
receiveKey.currentState.amountController.text = amount;
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => store.receiveAddress, (String address) {
|
||||
reaction((_) => exchangeViewModel.receiveAddress, (String address) {
|
||||
if (receiveKey.currentState.addressController.text != address) {
|
||||
receiveKey.currentState.addressController.text = address;
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => store.isReceiveAddressEnabled, (bool isEnabled) {
|
||||
reaction((_) => exchangeViewModel.isReceiveAddressEnabled, (bool isEnabled) {
|
||||
receiveKey.currentState.isAddressEditable(isEditable: isEnabled);
|
||||
});
|
||||
|
||||
reaction((_) => store.tradeState, (ExchangeTradeState state) {
|
||||
reaction((_) => exchangeViewModel.tradeState, (ExchangeTradeState state) {
|
||||
if (state is TradeIsCreatedFailure) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showDialog<void>(
|
||||
|
@ -437,7 +444,7 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
}
|
||||
});
|
||||
|
||||
reaction((_) => store.limitsState, (LimitsState state) {
|
||||
reaction((_) => exchangeViewModel.limitsState, (LimitsState state) {
|
||||
String min;
|
||||
String max;
|
||||
|
||||
|
@ -461,29 +468,29 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
});
|
||||
|
||||
depositAddressController.addListener(
|
||||
() => store.depositAddress = depositAddressController.text);
|
||||
() => exchangeViewModel.depositAddress = depositAddressController.text);
|
||||
|
||||
depositAmountController.addListener(() {
|
||||
if (depositAmountController.text != store.depositAmount) {
|
||||
store.changeDepositAmount(amount: depositAmountController.text);
|
||||
if (depositAmountController.text != exchangeViewModel.depositAmount) {
|
||||
exchangeViewModel.changeDepositAmount(amount: depositAmountController.text);
|
||||
}
|
||||
});
|
||||
|
||||
receiveAddressController.addListener(
|
||||
() => store.receiveAddress = receiveAddressController.text);
|
||||
() => exchangeViewModel.receiveAddress = receiveAddressController.text);
|
||||
|
||||
receiveAmountController.addListener(() {
|
||||
if (receiveAmountController.text != store.receiveAmount) {
|
||||
store.changeReceiveAmount(amount: receiveAmountController.text);
|
||||
if (receiveAmountController.text != exchangeViewModel.receiveAmount) {
|
||||
exchangeViewModel.changeReceiveAmount(amount: receiveAmountController.text);
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => walletStore.address, (String address) {
|
||||
if (store.depositCurrency == CryptoCurrency.xmr) {
|
||||
reaction((_) => exchangeViewModel.wallet.address, (String address) {
|
||||
if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) {
|
||||
depositKey.currentState.changeAddress(address: address);
|
||||
}
|
||||
|
||||
if (store.receiveCurrency == CryptoCurrency.xmr) {
|
||||
if (exchangeViewModel.receiveCurrency == CryptoCurrency.xmr) {
|
||||
receiveKey.currentState.changeAddress(address: address);
|
||||
}
|
||||
});
|
||||
|
@ -491,28 +498,33 @@ class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
|
|||
_isReactionsSet = true;
|
||||
}
|
||||
|
||||
void _onCurrencyChange(CryptoCurrency currency, WalletStore walletStore,
|
||||
void _onCurrencyChange(CryptoCurrency currency,
|
||||
ExchangeViewModel exchangeViewModel,
|
||||
GlobalKey<ExchangeCardState> key) {
|
||||
final isCurrentTypeWallet = currency == walletStore.type;
|
||||
final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
|
||||
|
||||
key.currentState.changeSelectedCurrency(currency);
|
||||
key.currentState
|
||||
.changeWalletName(isCurrentTypeWallet ? walletStore.name : null);
|
||||
.changeWalletName(isCurrentTypeWallet
|
||||
? exchangeViewModel.wallet.name : null);
|
||||
|
||||
key.currentState
|
||||
.changeAddress(address: isCurrentTypeWallet ? walletStore.address : '');
|
||||
.changeAddress(address: isCurrentTypeWallet
|
||||
? exchangeViewModel.wallet.address : '');
|
||||
|
||||
key.currentState.changeAmount(amount: '');
|
||||
}
|
||||
|
||||
void _onWalletNameChange(WalletStore walletStore, CryptoCurrency currency,
|
||||
void _onWalletNameChange(ExchangeViewModel exchangeViewModel,
|
||||
CryptoCurrency currency,
|
||||
GlobalKey<ExchangeCardState> key) {
|
||||
final isCurrentTypeWallet = currency == walletStore.type;
|
||||
final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
|
||||
|
||||
if (isCurrentTypeWallet) {
|
||||
key.currentState.changeWalletName(walletStore.name);
|
||||
key.currentState.addressController.text = walletStore.address;
|
||||
} else if (key.currentState.addressController.text == walletStore.address) {
|
||||
key.currentState.changeWalletName(exchangeViewModel.wallet.name);
|
||||
key.currentState.addressController.text = exchangeViewModel.wallet.address;
|
||||
} else if (key.currentState.addressController.text ==
|
||||
exchangeViewModel.wallet.address) {
|
||||
key.currentState.changeWalletName(null);
|
||||
key.currentState.addressController.text = null;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
|||
import 'package:cake_wallet/src/widgets/address_text_field.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
|
||||
class ExchangeCard extends StatefulWidget {
|
||||
ExchangeCard(
|
||||
|
@ -57,6 +58,10 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
bool _isAddressEditable;
|
||||
bool _isAmountEstimated;
|
||||
|
||||
final copyImage = Image.asset('assets/images/copy_content.png',
|
||||
height: 16, width: 16,
|
||||
color: Colors.white);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_title = widget.title;
|
||||
|
@ -114,6 +119,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
width: double.infinity,
|
||||
color: Colors.transparent,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
|
@ -123,13 +129,13 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color
|
||||
color: PaletteDark.lightBlueGrey
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
BaseTextFormField(
|
||||
|
@ -143,7 +149,20 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
RegExp('[\\-|\\ |\\,]'))
|
||||
],
|
||||
hintText: '0.0000',
|
||||
validator: widget.currencyValueValidator
|
||||
borderColor: PaletteDark.blueGrey,
|
||||
textStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white
|
||||
),
|
||||
placeholderTextStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: PaletteDark.lightBlueGrey
|
||||
),
|
||||
validator: _isAmountEditable
|
||||
? widget.currencyValueValidator
|
||||
: null
|
||||
),
|
||||
Positioned(
|
||||
top: 8,
|
||||
|
@ -163,7 +182,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
color: Theme.of(context).primaryTextTheme.title.color)),
|
||||
color: Colors.white)),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 5),
|
||||
child: widget.imageArrow,
|
||||
|
@ -181,45 +200,96 @@ class ExchangeCardState extends State<ExchangeCard> {
|
|||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
_min != null
|
||||
? Text(
|
||||
? Text(
|
||||
S.of(context).min_value(
|
||||
_min, _selectedCurrency.toString()),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
height: 1.2,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color),
|
||||
color: PaletteDark.lightBlueGrey),
|
||||
)
|
||||
: Offstage(),
|
||||
: Offstage(),
|
||||
_min != null ? SizedBox(width: 10) : Offstage(),
|
||||
_max != null
|
||||
? Text(
|
||||
? Text(
|
||||
S.of(context).max_value(
|
||||
_max, _selectedCurrency.toString()),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
height: 1.2,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color))
|
||||
: Offstage(),
|
||||
color: PaletteDark.lightBlueGrey))
|
||||
: Offstage(),
|
||||
]),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: AddressTextField(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Text(
|
||||
_isAddressEditable
|
||||
? S.of(context).widgets_address
|
||||
: S.of(context).refund_address,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: PaletteDark.lightBlueGrey
|
||||
),
|
||||
)
|
||||
),
|
||||
_isAddressEditable
|
||||
? AddressTextField(
|
||||
controller: addressController,
|
||||
isActive: _isAddressEditable,
|
||||
options: _isAddressEditable
|
||||
? _walletName != null
|
||||
? []
|
||||
: [
|
||||
options: [
|
||||
AddressTextFieldOption.paste,
|
||||
AddressTextFieldOption.qrCode,
|
||||
AddressTextFieldOption.addressBook,
|
||||
]
|
||||
: [],
|
||||
],
|
||||
placeholder: '',
|
||||
isBorderExist: false,
|
||||
textStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white),
|
||||
buttonColor: widget.addressButtonsColor,
|
||||
validator: widget.addressTextFieldValidator,
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Builder(
|
||||
builder: (context) => GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(
|
||||
text: addressController.text));
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: Text(
|
||||
S.of(context).copied_to_clipboard,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
backgroundColor: Colors.green,
|
||||
duration: Duration(milliseconds: 500),
|
||||
));
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
addressController.text,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16),
|
||||
child: copyImage,
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange/exchange_store.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
|
||||
class PresentProviderPicker extends StatelessWidget {
|
||||
PresentProviderPicker({@required this.exchangeStore});
|
||||
PresentProviderPicker({@required this.exchangeViewModel});
|
||||
|
||||
final ExchangeStore exchangeStore;
|
||||
final ExchangeViewModel exchangeViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Image arrowBottom =
|
||||
final arrowBottom =
|
||||
Image.asset('assets/images/arrow_bottom_purple_icon.png',
|
||||
color: Theme.of(context).primaryTextTheme.title.color,
|
||||
color: Colors.white,
|
||||
height: 6);
|
||||
|
||||
return FlatButton(
|
||||
|
@ -33,19 +34,19 @@ class PresentProviderPicker extends StatelessWidget {
|
|||
Text(S.of(context).exchange,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).primaryTextTheme.title.color)),
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white)),
|
||||
Observer(
|
||||
builder: (_) => Text('${exchangeStore.provider.title}',
|
||||
builder: (_) => Text('${exchangeViewModel.provider.title}',
|
||||
style: TextStyle(
|
||||
fontSize: 10.0,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).primaryTextTheme.caption.color)))
|
||||
fontWeight: FontWeight.w500,
|
||||
color: PaletteDark.lightBlueGrey)))
|
||||
],
|
||||
),
|
||||
SizedBox(width: 5),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
padding: EdgeInsets.only(top: 12),
|
||||
child: arrowBottom,
|
||||
)
|
||||
],
|
||||
|
@ -54,11 +55,11 @@ class PresentProviderPicker extends StatelessWidget {
|
|||
}
|
||||
|
||||
void _presentProviderPicker(BuildContext context) {
|
||||
final items = exchangeStore.providersForCurrentPair();
|
||||
final selectedItem = items.indexOf(exchangeStore.provider);
|
||||
final images = List<Image>();
|
||||
final items = exchangeViewModel.providersForCurrentPair();
|
||||
final selectedItem = items.indexOf(exchangeViewModel.provider);
|
||||
final images = <Image>[];
|
||||
|
||||
for (ExchangeProvider provider in items) {
|
||||
for (var provider in items) {
|
||||
switch (provider.description) {
|
||||
case ExchangeProviderDescription.xmrto:
|
||||
images.add(Image.asset('assets/images/xmr_btc.png'));
|
||||
|
@ -79,7 +80,7 @@ class PresentProviderPicker extends StatelessWidget {
|
|||
selectedAtIndex: selectedItem,
|
||||
title: S.of(context).change_exchange_provider,
|
||||
onItemSelected: (ExchangeProvider provider) =>
|
||||
exchangeStore.changeProvider(provider: provider)),
|
||||
exchangeViewModel.changeProvider(provider: provider)),
|
||||
context: context);
|
||||
}
|
||||
}
|
|
@ -125,7 +125,7 @@ class ReceivePage extends BasePage {
|
|||
.headline5
|
||||
.color
|
||||
.withOpacity(0.4),
|
||||
validator: AmountValidator(),
|
||||
validator: AmountValidator(isAutovalidate: true),
|
||||
autovalidate: true,
|
||||
placeholderTextStyle: TextStyle(
|
||||
color: Theme.of(context)
|
||||
|
|
|
@ -72,6 +72,10 @@ class BaseTextFormField extends StatelessWidget {
|
|||
borderSide: BorderSide(
|
||||
color: borderColor ?? Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
disabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: borderColor ?? Theme.of(context).dividerColor,
|
||||
width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: borderColor ?? Theme.of(context).dividerColor,
|
||||
|
|
|
@ -71,6 +71,8 @@ class NavBar extends StatelessWidget implements ObstructingPreferredSizeWidget {
|
|||
EdgeInsetsDirectional.only(bottom: _paddingBottom, top: paddingTop),
|
||||
child: CupertinoNavigationBar(
|
||||
leading: leading,
|
||||
automaticallyImplyLeading: false,
|
||||
automaticallyImplyMiddle: false,
|
||||
middle: middle,
|
||||
trailing: trailing,
|
||||
backgroundColor: backgroundColor,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
|
||||
class TrailButton extends StatelessWidget {
|
||||
TrailButton({
|
||||
|
@ -21,7 +22,7 @@ class TrailButton extends StatelessWidget {
|
|||
child: Text(
|
||||
caption,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.caption.color,
|
||||
color: PaletteDark.lightBlueGrey,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14),
|
||||
),
|
||||
|
|
306
lib/view_model/exchange/exchange_view_model.dart
Normal file
|
@ -0,0 +1,306 @@
|
|||
import 'package:cake_wallet/core/address_validator.dart';
|
||||
import 'package:cake_wallet/core/amount_validator.dart';
|
||||
import 'package:cake_wallet/core/template_validator.dart';
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/core/wallet_base.dart';
|
||||
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/limits.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/trade.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange/limits_state.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/changenow/changenow_exchange_provider.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/changenow/changenow_request.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/trade_request.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_trade_request.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_exchange_provider.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/morphtoken/morphtoken_request.dart';
|
||||
import 'package:cake_wallet/store/templates/exchange_template_store.dart';
|
||||
import 'package:cake_wallet/src/domain/exchange/exchange_template.dart';
|
||||
|
||||
part 'exchange_view_model.g.dart';
|
||||
|
||||
class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel;
|
||||
|
||||
abstract class ExchangeViewModelBase with Store {
|
||||
ExchangeViewModelBase({this.wallet, this.trades, this.exchangeTemplateStore}) {
|
||||
providerList = [
|
||||
XMRTOExchangeProvider(),
|
||||
ChangeNowExchangeProvider(),
|
||||
MorphTokenExchangeProvider(trades: trades)
|
||||
];
|
||||
|
||||
provider = providerList[ 0 ];
|
||||
|
||||
depositCurrency = CryptoCurrency.xmr;
|
||||
receiveCurrency = CryptoCurrency.btc;
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
||||
depositAmount = '';
|
||||
receiveAmount = '';
|
||||
depositAddress = '';
|
||||
receiveAddress = '';
|
||||
limitsState = LimitsInitialState();
|
||||
tradeState = ExchangeTradeStateInitial();
|
||||
_cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12;
|
||||
loadLimits();
|
||||
}
|
||||
|
||||
final WalletBase wallet;
|
||||
final Box<Trade> trades;
|
||||
final ExchangeTemplateStore exchangeTemplateStore;
|
||||
|
||||
@observable
|
||||
ExchangeProvider provider;
|
||||
|
||||
@observable
|
||||
List<ExchangeProvider> providerList;
|
||||
|
||||
@observable
|
||||
CryptoCurrency depositCurrency;
|
||||
|
||||
@observable
|
||||
CryptoCurrency receiveCurrency;
|
||||
|
||||
@observable
|
||||
LimitsState limitsState;
|
||||
|
||||
@observable
|
||||
ExchangeTradeState tradeState;
|
||||
|
||||
@observable
|
||||
String depositAmount;
|
||||
|
||||
@observable
|
||||
String receiveAmount;
|
||||
|
||||
@observable
|
||||
String depositAddress;
|
||||
|
||||
@observable
|
||||
String receiveAddress;
|
||||
|
||||
@observable
|
||||
bool isDepositAddressEnabled;
|
||||
|
||||
@observable
|
||||
bool isReceiveAddressEnabled;
|
||||
|
||||
@observable
|
||||
bool isValid;
|
||||
|
||||
@observable
|
||||
String errorMessage;
|
||||
|
||||
Limits limits;
|
||||
|
||||
NumberFormat _cryptoNumberFormat;
|
||||
|
||||
Validator get amountValidator => AmountValidator(type: wallet.type);
|
||||
|
||||
Validator get addressValidator => AddressValidator(type: wallet.currency);
|
||||
|
||||
Validator get templateValidator => TemplateValidator();
|
||||
|
||||
@computed
|
||||
ObservableList<ExchangeTemplate> get templates =>
|
||||
exchangeTemplateStore.templates;
|
||||
|
||||
@action
|
||||
void changeProvider({ExchangeProvider provider}) {
|
||||
this.provider = provider;
|
||||
depositAmount = '';
|
||||
receiveAmount = '';
|
||||
loadLimits();
|
||||
}
|
||||
|
||||
@action
|
||||
void changeDepositCurrency({CryptoCurrency currency}) {
|
||||
depositCurrency = currency;
|
||||
_onPairChange();
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
||||
}
|
||||
|
||||
@action
|
||||
void changeReceiveCurrency({CryptoCurrency currency}) {
|
||||
receiveCurrency = currency;
|
||||
_onPairChange();
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
||||
}
|
||||
|
||||
@action
|
||||
void changeReceiveAmount({String amount}) {
|
||||
receiveAmount = amount;
|
||||
|
||||
if (amount == null || amount.isEmpty) {
|
||||
depositAmount = '';
|
||||
receiveAmount = '';
|
||||
return;
|
||||
}
|
||||
|
||||
final _amount = double.parse(amount) ?? 0;
|
||||
|
||||
provider
|
||||
.calculateAmount(
|
||||
from: depositCurrency, to: receiveCurrency, amount: _amount)
|
||||
.then((amount) => _cryptoNumberFormat.format(amount).toString().replaceAll(RegExp("\\,"), ""))
|
||||
.then((amount) => depositAmount = amount);
|
||||
}
|
||||
|
||||
@action
|
||||
void changeDepositAmount({String amount}) {
|
||||
depositAmount = amount;
|
||||
|
||||
if (amount == null || amount.isEmpty) {
|
||||
depositAmount = '';
|
||||
receiveAmount = '';
|
||||
return;
|
||||
}
|
||||
|
||||
final _amount = double.parse(amount);
|
||||
provider
|
||||
.calculateAmount(
|
||||
from: depositCurrency, to: receiveCurrency, amount: _amount)
|
||||
.then((amount) => _cryptoNumberFormat.format(amount).toString().replaceAll(RegExp("\\,"), ""))
|
||||
.then((amount) => receiveAmount = amount);
|
||||
}
|
||||
|
||||
@action
|
||||
Future loadLimits() async {
|
||||
limitsState = LimitsIsLoading();
|
||||
|
||||
try {
|
||||
limits = await provider.fetchLimits(
|
||||
from: depositCurrency, to: receiveCurrency);
|
||||
limitsState = LimitsLoadedSuccessfully(limits: limits);
|
||||
} catch (e) {
|
||||
limitsState = LimitsLoadedFailure(error: e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future createTrade() async {
|
||||
TradeRequest request;
|
||||
String amount;
|
||||
CryptoCurrency currency;
|
||||
|
||||
if (provider is XMRTOExchangeProvider) {
|
||||
request = XMRTOTradeRequest(
|
||||
from: depositCurrency,
|
||||
to: receiveCurrency,
|
||||
amount: depositAmount,
|
||||
address: receiveAddress,
|
||||
refundAddress: depositAddress);
|
||||
amount = depositAmount;
|
||||
currency = depositCurrency;
|
||||
}
|
||||
|
||||
if (provider is ChangeNowExchangeProvider) {
|
||||
request = ChangeNowRequest(
|
||||
from: depositCurrency,
|
||||
to: receiveCurrency,
|
||||
amount: depositAmount,
|
||||
refundAddress: depositAddress,
|
||||
address: receiveAddress);
|
||||
amount = depositAmount;
|
||||
currency = depositCurrency;
|
||||
}
|
||||
|
||||
if (provider is MorphTokenExchangeProvider) {
|
||||
request = MorphTokenRequest(
|
||||
from: depositCurrency,
|
||||
to: receiveCurrency,
|
||||
amount: depositAmount,
|
||||
refundAddress: depositAddress,
|
||||
address: receiveAddress);
|
||||
amount = depositAmount;
|
||||
currency = depositCurrency;
|
||||
}
|
||||
|
||||
if (limitsState is LimitsLoadedSuccessfully && amount != null) {
|
||||
if (double.parse(amount) < limits.min) {
|
||||
tradeState = TradeIsCreatedFailure(error: S.current.error_text_minimal_limit('${provider.description}',
|
||||
'${limits.min}', currency.toString()));
|
||||
} else if (limits.max != null && double.parse(amount) > limits.max) {
|
||||
tradeState = TradeIsCreatedFailure(error: S.current.error_text_maximum_limit('${provider.description}',
|
||||
'${limits.max}', currency.toString()));
|
||||
} else {
|
||||
try {
|
||||
tradeState = TradeIsCreating();
|
||||
final trade = await provider.createTrade(request: request);
|
||||
trade.walletId = wallet.id;
|
||||
await trades.add(trade);
|
||||
tradeState = TradeIsCreatedSuccessfully(trade: trade);
|
||||
} catch (e) {
|
||||
tradeState = TradeIsCreatedFailure(error: e.toString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tradeState = TradeIsCreatedFailure(error: S.current.error_text_limits_loading_failed("${provider.description}"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@action
|
||||
void reset() {
|
||||
depositAmount = '';
|
||||
receiveAmount = '';
|
||||
depositCurrency = CryptoCurrency.xmr;
|
||||
receiveCurrency = CryptoCurrency.btc;
|
||||
depositAddress = depositCurrency == wallet.currency ? wallet.address : '';
|
||||
receiveAddress = receiveCurrency == wallet.currency ? wallet.address : '';
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
|
||||
_onPairChange();
|
||||
}
|
||||
|
||||
List<ExchangeProvider> providersForCurrentPair() {
|
||||
return _providersForPair(from: depositCurrency, to: receiveCurrency);
|
||||
}
|
||||
|
||||
List<ExchangeProvider> _providersForPair(
|
||||
{CryptoCurrency from, CryptoCurrency to}) {
|
||||
final providers = providerList
|
||||
.where((provider) => provider.pairList
|
||||
.where((pair) =>
|
||||
pair.from == depositCurrency && pair.to == receiveCurrency)
|
||||
.isNotEmpty)
|
||||
.toList();
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
void _onPairChange() {
|
||||
final isPairExist = provider.pairList
|
||||
.where((pair) =>
|
||||
pair.from == depositCurrency && pair.to == receiveCurrency)
|
||||
.isNotEmpty;
|
||||
|
||||
if (!isPairExist) {
|
||||
final provider =
|
||||
_providerForPair(from: depositCurrency, to: receiveCurrency);
|
||||
|
||||
if (provider != null) {
|
||||
changeProvider(provider: provider);
|
||||
}
|
||||
}
|
||||
|
||||
depositAmount = '';
|
||||
receiveAmount = '';
|
||||
|
||||
loadLimits();
|
||||
}
|
||||
|
||||
ExchangeProvider _providerForPair({CryptoCurrency from, CryptoCurrency to}) {
|
||||
final providers = _providersForPair(from: from, to: to);
|
||||
return providers.isNotEmpty ? providers[0] : null;
|
||||
}
|
||||
|
||||
}
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "Austausch",
|
||||
"clear" : "klar",
|
||||
"refund_address" : "Rückerstattungsadresse",
|
||||
"change_exchange_provider" : "Wechseln Sie den Exchange-Anbieter",
|
||||
"you_will_send" : "Du wirst senden",
|
||||
"you_will_get" : "Sie erhalten",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "Exchange",
|
||||
"clear" : "Clear",
|
||||
"refund_address" : "Refund address",
|
||||
"change_exchange_provider" : "Change Exchange Provider",
|
||||
"you_will_send" : "You will send",
|
||||
"you_will_get" : "You will get",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "Intercambiar",
|
||||
"clear" : "Claro",
|
||||
"refund_address" : "Dirección de reembolso",
|
||||
"change_exchange_provider" : "Cambiar proveedor de intercambio",
|
||||
"you_will_send" : "Enviarás",
|
||||
"you_will_get" : "Conseguirás",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "अदला बदली",
|
||||
"clear" : "स्पष्ट",
|
||||
"refund_address" : "वापसी का पता",
|
||||
"change_exchange_provider" : "एक्सचेंज प्रदाता बदलें",
|
||||
"you_will_send" : "तुम भेजोगे",
|
||||
"you_will_get" : "आपको मिल जायेगा",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "交換する",
|
||||
"clear" : "クリア",
|
||||
"refund_address" : "払い戻し住所",
|
||||
"change_exchange_provider" : "Exchangeプロバイダーの変更",
|
||||
"you_will_send" : "送ります",
|
||||
"you_will_get" : "あなたが取得します",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "교환",
|
||||
"clear" : "명확한",
|
||||
"refund_address" : "환불 주소",
|
||||
"change_exchange_provider" : "교환 공급자 변경",
|
||||
"you_will_send" : "보내드립니다",
|
||||
"you_will_get" : "당신은 얻을 것이다",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "Uitwisseling",
|
||||
"clear" : "Duidelijk",
|
||||
"refund_address" : "Adres voor terugbetaling",
|
||||
"change_exchange_provider" : "Wijzig Exchange Provider",
|
||||
"you_will_send" : "Je zal versturen",
|
||||
"you_will_get" : "Je zult krijgen",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "Wymieniać się",
|
||||
"clear" : "Wyczyść",
|
||||
"refund_address" : "Adres zwrotu",
|
||||
"change_exchange_provider" : "Zmień dostawcę programu Exchange",
|
||||
"you_will_send" : "Wyślesz",
|
||||
"you_will_get" : "Dostaniesz",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "Trocar",
|
||||
"clear" : "Limpar",
|
||||
"refund_address" : "Endereço de reembolso",
|
||||
"change_exchange_provider" : "Alterar o provedor de troca",
|
||||
"you_will_send" : "Você enviará",
|
||||
"you_will_get" : "Você receberá",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "Обмен",
|
||||
"clear" : "Очистить",
|
||||
"refund_address" : "Адрес возврата",
|
||||
"change_exchange_provider" : "Изменить провайдера обмена",
|
||||
"you_will_send" : "Вы отправите",
|
||||
"you_will_get" : "Вы получите",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "Обмін",
|
||||
"clear" : "Очистити",
|
||||
"refund_address" : "Адреса повернення коштів",
|
||||
"change_exchange_provider" : "Змінити провайдера обміну",
|
||||
"you_will_send" : "Ви відправите",
|
||||
"you_will_get" : "Ви отримаєте",
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
|
||||
"exchange" : "交换",
|
||||
"clear" : "明确",
|
||||
"refund_address" : "退款地址",
|
||||
"change_exchange_provider" : "更改交易所提供商",
|
||||
"you_will_send" : "您将发送",
|
||||
"you_will_get" : "你会得到",
|
||||
|
|