mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 19:49:22 +00:00
CW-240 Receive fiat currency amount and receive animations (#877)
* Redesign receive amount field * Fix issues with animations * Fix issues with animations * Fix max fraction digit to 8 * add another 0 * Update amount when currency is changed --------- Co-authored-by: Justin Ehrenhofer <justin.ehrenhofer@gmail.com> Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
This commit is contained in:
parent
8ffac75e8c
commit
f2b8dd21a1
13 changed files with 504 additions and 340 deletions
|
@ -1,6 +1,7 @@
|
|||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
|
||||
class AmountValidator extends TextValidator {
|
||||
AmountValidator({
|
||||
|
@ -57,7 +58,7 @@ class SymbolsAmountValidator extends TextValidator {
|
|||
}
|
||||
|
||||
class DecimalAmountValidator extends TextValidator {
|
||||
DecimalAmountValidator({required CryptoCurrency currency, required bool isAutovalidate })
|
||||
DecimalAmountValidator({required Currency currency, required bool isAutovalidate })
|
||||
: super(
|
||||
errorMessage: S.current.decimal_places_error,
|
||||
pattern: _pattern(currency),
|
||||
|
@ -65,7 +66,7 @@ class DecimalAmountValidator extends TextValidator {
|
|||
minLength: 0,
|
||||
maxLength: 0);
|
||||
|
||||
static String _pattern(CryptoCurrency currency) {
|
||||
static String _pattern(Currency currency) {
|
||||
switch (currency) {
|
||||
case CryptoCurrency.xmr:
|
||||
return '^([0-9]+([.\,][0-9]{1,12})?|[.\,][0-9]{1,12})\$';
|
||||
|
|
|
@ -183,6 +183,7 @@ import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart';
|
|||
import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart';
|
||||
import 'package:cake_wallet/core/wallet_loading_service.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
|
||||
final getIt = GetIt.instance;
|
||||
|
||||
|
@ -321,7 +322,9 @@ Future setup(
|
|||
|
||||
getIt.registerFactory<WalletAddressListViewModel>(() =>
|
||||
WalletAddressListViewModel(
|
||||
appStore: getIt.get<AppStore>(), yatStore: getIt.get<YatStore>()));
|
||||
appStore: getIt.get<AppStore>(), yatStore: getIt.get<YatStore>(),
|
||||
fiatConversionStore: getIt.get<FiatConversionStore>()
|
||||
));
|
||||
|
||||
getIt.registerFactory(() => BalanceViewModel(
|
||||
appStore: getIt.get<AppStore>(),
|
||||
|
@ -815,8 +818,8 @@ Future setup(
|
|||
getIt.registerFactory(() => AddressResolver(yatService: getIt.get<YatService>(),
|
||||
walletType: getIt.get<AppStore>().wallet!.type));
|
||||
|
||||
getIt.registerFactoryParam<FullscreenQRPage, String, int?>(
|
||||
(String qrData, int? version) => FullscreenQRPage(qrData: qrData, version: version,));
|
||||
getIt.registerFactoryParam<FullscreenQRPage, QrViewData, void>(
|
||||
(QrViewData viewData, _) => FullscreenQRPage(qrViewData: viewData));
|
||||
|
||||
getIt.registerFactory(() => IoniaApi());
|
||||
|
||||
|
|
11
lib/entities/qr_view_data.dart
Normal file
11
lib/entities/qr_view_data.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
class QrViewData {
|
||||
final int? version;
|
||||
final String? heroTag;
|
||||
final String data;
|
||||
|
||||
QrViewData({
|
||||
this.version,
|
||||
this.heroTag,
|
||||
required this.data,
|
||||
});
|
||||
}
|
|
@ -2,6 +2,7 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
|||
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
||||
import 'package:cake_wallet/entities/contact_record.dart';
|
||||
import 'package:cake_wallet/buy/order.dart';
|
||||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart';
|
||||
import 'package:cake_wallet/src/screens/backup/backup_page.dart';
|
||||
import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
|
||||
|
@ -242,7 +243,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
|
||||
case Routes.receive:
|
||||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<ReceivePage>());
|
||||
builder: (_) => getIt.get<ReceivePage>());
|
||||
|
||||
case Routes.addressPage:
|
||||
return CupertinoPageRoute<void>(
|
||||
|
@ -451,14 +452,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
param1: args));
|
||||
|
||||
case Routes.fullscreenQR:
|
||||
final args = settings.arguments as Map<String, dynamic>;
|
||||
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) =>
|
||||
getIt.get<FullscreenQRPage>(
|
||||
param1: args['qrData'] as String,
|
||||
param2: args['version'] as int?,
|
||||
|
||||
param1: settings.arguments as QrViewData,
|
||||
));
|
||||
|
||||
case Routes.ioniaWelcomePage:
|
||||
|
|
|
@ -26,11 +26,23 @@ class AddressPage extends BasePage {
|
|||
required this.addressListViewModel,
|
||||
required this.dashboardViewModel,
|
||||
required this.receiveOptionViewModel,
|
||||
}) : _cryptoAmountFocus = FocusNode();
|
||||
}) : _cryptoAmountFocus = FocusNode(),
|
||||
_formKey = GlobalKey<FormState>(),
|
||||
_amountController = TextEditingController(){
|
||||
_amountController.addListener(() {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
addressListViewModel.changeAmount(
|
||||
_amountController.text,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final WalletAddressListViewModel addressListViewModel;
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final ReceiveOptionViewModel receiveOptionViewModel;
|
||||
final TextEditingController _amountController;
|
||||
final GlobalKey<FormState> _formKey;
|
||||
|
||||
final FocusNode _cryptoAmountFocus;
|
||||
|
||||
|
@ -69,28 +81,27 @@ class AddressPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget? trailing(BuildContext context) {
|
||||
final shareImage = Image.asset('assets/images/share.png',
|
||||
color: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!);
|
||||
|
||||
return !addressListViewModel.hasAddressList
|
||||
? Material(
|
||||
color: Colors.transparent,
|
||||
child: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: BoxConstraints(),
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
iconSize: 25,
|
||||
onPressed: () {
|
||||
ShareUtil.share(
|
||||
text: addressListViewModel.address.address,
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
icon: shareImage,
|
||||
),
|
||||
)
|
||||
: null;
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: BoxConstraints(),
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
iconSize: 25,
|
||||
onPressed: () {
|
||||
ShareUtil.share(
|
||||
text: addressListViewModel.uri.toString(),
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.share,
|
||||
size: 20,
|
||||
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -137,16 +148,18 @@ class AddressPage extends BasePage {
|
|||
)
|
||||
]),
|
||||
child: Container(
|
||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||
padding: EdgeInsets.fromLTRB(24, 0, 24, 32),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Observer(builder: (_) => QRWidget(
|
||||
addressListViewModel: addressListViewModel,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
isAmountFieldShow: !addressListViewModel.hasAccounts,
|
||||
isLight: dashboardViewModel.settingsStore.currentTheme.type == ThemeType.light))
|
||||
),
|
||||
Expanded(
|
||||
child: Observer(
|
||||
builder: (_) => QRWidget(
|
||||
formKey: _formKey,
|
||||
addressListViewModel: addressListViewModel,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
amountController: _amountController,
|
||||
isLight: dashboardViewModel.settingsStore.currentTheme.type ==
|
||||
ThemeType.light))),
|
||||
Observer(builder: (_) {
|
||||
return addressListViewModel.hasAddressList
|
||||
? GestureDetector(
|
||||
|
|
|
@ -115,10 +115,6 @@ class ExchangePage extends BasePage {
|
|||
WidgetsBinding.instance
|
||||
.addPostFrameCallback((_) => _setReactions(context, exchangeViewModel));
|
||||
|
||||
if (exchangeViewModel.isLowFee) {
|
||||
_showFeeAlert(context);
|
||||
}
|
||||
|
||||
return KeyboardActions(
|
||||
disableScroll: true,
|
||||
config: KeyboardActionsConfig(
|
||||
|
@ -319,6 +315,10 @@ class ExchangePage extends BasePage {
|
|||
return;
|
||||
}
|
||||
|
||||
if (exchangeViewModel.isLowFee) {
|
||||
_showFeeAlert(context);
|
||||
}
|
||||
|
||||
final depositAddressController = depositKey.currentState!.addressController;
|
||||
final depositAmountController = depositKey.currentState!.amountController;
|
||||
final receiveAddressController = receiveKey.currentState!.addressController;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
||||
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
||||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
|
@ -133,10 +134,9 @@ class AnonPayReceivePage extends BasePage {
|
|||
await Navigator.pushNamed(
|
||||
context,
|
||||
Routes.fullscreenQR,
|
||||
arguments: {
|
||||
'qrData': invoiceInfo.clearnetUrl,
|
||||
'version': qr.QrVersions.auto,
|
||||
},
|
||||
arguments: QrViewData(data: invoiceInfo.clearnetUrl,
|
||||
version: qr.QrVersions.auto,
|
||||
)
|
||||
);
|
||||
// ignore: unawaited_futures
|
||||
DeviceDisplayBrightness.setBrightness(brightness);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
|
||||
class FullscreenQRPage extends BasePage {
|
||||
FullscreenQRPage({required this.qrData, int? this.version});
|
||||
FullscreenQRPage({required this.qrViewData});
|
||||
|
||||
final String qrData;
|
||||
final int? version;
|
||||
final QrViewData qrViewData;
|
||||
|
||||
@override
|
||||
Color get backgroundLightColor => currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white;
|
||||
|
@ -63,7 +63,7 @@ class FullscreenQRPage extends BasePage {
|
|||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: MediaQuery.of(context).size.width * 0.05),
|
||||
child: Hero(
|
||||
tag: Key(qrData),
|
||||
tag: Key(qrViewData.heroTag ?? qrViewData.data),
|
||||
child: Center(
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.0,
|
||||
|
@ -71,7 +71,7 @@ class FullscreenQRPage extends BasePage {
|
|||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(width: 3, color: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!)),
|
||||
child: QrImage(data: qrData, version: version),
|
||||
child: QrImage(data: qrViewData.data, version: qrViewData.version),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -21,16 +21,28 @@ import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart';
|
|||
import 'package:keyboard_actions/keyboard_actions.dart';
|
||||
|
||||
class ReceivePage extends BasePage {
|
||||
ReceivePage({required this.addressListViewModel}) : _cryptoAmountFocus = FocusNode();
|
||||
ReceivePage({required this.addressListViewModel})
|
||||
: _cryptoAmountFocus = FocusNode(),
|
||||
_amountController = TextEditingController(),
|
||||
_formKey = GlobalKey<FormState>() {
|
||||
_amountController.addListener(() {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
addressListViewModel.changeAmount(_amountController.text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final WalletAddressListViewModel addressListViewModel;
|
||||
final TextEditingController _amountController;
|
||||
final GlobalKey<FormState> _formKey;
|
||||
static const _heroTag = 'receive_page';
|
||||
|
||||
@override
|
||||
String get title => S.current.receive;
|
||||
|
||||
@override
|
||||
Color get backgroundLightColor => currentTheme.type == ThemeType.bright
|
||||
? Colors.transparent : Colors.white;
|
||||
Color get backgroundLightColor =>
|
||||
currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white;
|
||||
|
||||
@override
|
||||
Color get backgroundDarkColor => Colors.transparent;
|
||||
|
@ -68,162 +80,153 @@ class ReceivePage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
final shareImage =
|
||||
Image.asset('assets/images/share.png',
|
||||
color: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!);
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: Semantics(
|
||||
label: 'Share',
|
||||
child: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: BoxConstraints(),
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
iconSize: 25,
|
||||
onPressed: () {
|
||||
ShareUtil.share(
|
||||
text: addressListViewModel.address.address,
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
icon: shareImage
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: BoxConstraints(),
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
iconSize: 25,
|
||||
onPressed: () {
|
||||
ShareUtil.share(
|
||||
text: addressListViewModel.uri.toString(),
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.share,
|
||||
size: 20,
|
||||
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return (addressListViewModel.type == WalletType.monero || addressListViewModel.type == WalletType.haven)
|
||||
return (addressListViewModel.type == WalletType.monero ||
|
||||
addressListViewModel.type == WalletType.haven)
|
||||
? KeyboardActions(
|
||||
config: KeyboardActionsConfig(
|
||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||
keyboardBarColor: Theme.of(context).accentTextTheme!.bodyText1!
|
||||
.backgroundColor!,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
focusNode: _cryptoAmountFocus,
|
||||
toolbarButtons: [(_) => KeyboardDoneButton()],
|
||||
)
|
||||
]),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 80, 24, 24),
|
||||
child: QRWidget(
|
||||
addressListViewModel: addressListViewModel,
|
||||
isAmountFieldShow: true,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
isLight: currentTheme.type == ThemeType.light),
|
||||
config: KeyboardActionsConfig(
|
||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||
keyboardBarColor: Theme.of(context).accentTextTheme!.bodyText1!.backgroundColor!,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
focusNode: _cryptoAmountFocus,
|
||||
toolbarButtons: [(_) => KeyboardDoneButton()],
|
||||
)
|
||||
]),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 50, 24, 24),
|
||||
child: QRWidget(
|
||||
addressListViewModel: addressListViewModel,
|
||||
formKey: _formKey,
|
||||
heroTag: _heroTag,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
amountController: _amountController,
|
||||
isLight: currentTheme.type == ThemeType.light),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => ListView.separated(
|
||||
padding: EdgeInsets.all(0),
|
||||
separatorBuilder: (context, _) => const SectionDivider(),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: addressListViewModel.items.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = addressListViewModel.items[index];
|
||||
Widget cell = Container();
|
||||
|
||||
if (item is WalletAccountListHeader) {
|
||||
cell = HeaderTile(
|
||||
onTap: () async => await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => getIt.get<MoneroAccountListPage>()),
|
||||
title: S.of(context).accounts,
|
||||
icon: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
color: Theme.of(context).textTheme!.headline4!.color!,
|
||||
));
|
||||
}
|
||||
|
||||
if (item is WalletAddressListHeader) {
|
||||
cell = HeaderTile(
|
||||
onTap: () =>
|
||||
Navigator.of(context).pushNamed(Routes.newSubaddress),
|
||||
title: S.of(context).addresses,
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
size: 20,
|
||||
color: Theme.of(context).textTheme!.headline4!.color!,
|
||||
));
|
||||
}
|
||||
|
||||
if (item is WalletAddressListItem) {
|
||||
cell = Observer(builder: (_) {
|
||||
final isCurrent =
|
||||
item.address == addressListViewModel.address.address;
|
||||
final backgroundColor = isCurrent
|
||||
? Theme.of(context).textTheme!.headline2!.decorationColor!
|
||||
: Theme.of(context).textTheme!.headline3!.decorationColor!;
|
||||
final textColor = isCurrent
|
||||
? Theme.of(context).textTheme!.headline2!.color!
|
||||
: Theme.of(context).textTheme!.headline3!.color!;
|
||||
|
||||
return AddressCell.fromItem(item,
|
||||
isCurrent: isCurrent,
|
||||
backgroundColor: backgroundColor,
|
||||
textColor: textColor,
|
||||
onTap: (_) => addressListViewModel.setAddress(item),
|
||||
onEdit: () => Navigator.of(context)
|
||||
.pushNamed(Routes.newSubaddress, arguments: item));
|
||||
});
|
||||
}
|
||||
|
||||
return index != 0
|
||||
? cell
|
||||
: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(30),
|
||||
topRight: Radius.circular(30)),
|
||||
child: cell,
|
||||
);
|
||||
})),
|
||||
],
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => ListView.separated(
|
||||
padding: EdgeInsets.all(0),
|
||||
separatorBuilder: (context, _) => const SectionDivider(),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: addressListViewModel.items.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = addressListViewModel.items[index];
|
||||
Widget cell = Container();
|
||||
|
||||
if (item is WalletAccountListHeader) {
|
||||
cell = HeaderTile(
|
||||
onTap: () async => await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) =>
|
||||
getIt.get<MoneroAccountListPage>()),
|
||||
title: S.of(context).accounts,
|
||||
icon: Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
color:
|
||||
Theme.of(context).textTheme!.headline4!.color!,
|
||||
));
|
||||
}
|
||||
|
||||
if (item is WalletAddressListHeader) {
|
||||
cell = HeaderTile(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.newSubaddress),
|
||||
title: S.of(context).addresses,
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
size: 20,
|
||||
color:
|
||||
Theme.of(context).textTheme!.headline4!.color!,
|
||||
));
|
||||
}
|
||||
|
||||
if (item is WalletAddressListItem) {
|
||||
cell = Observer(builder: (_) {
|
||||
final isCurrent = item.address ==
|
||||
addressListViewModel.address.address;
|
||||
final backgroundColor = isCurrent
|
||||
? Theme.of(context)
|
||||
.textTheme!
|
||||
.headline2!
|
||||
.decorationColor!
|
||||
: Theme.of(context)
|
||||
.textTheme!
|
||||
.headline3!
|
||||
.decorationColor!;
|
||||
final textColor = isCurrent
|
||||
? Theme.of(context).textTheme!.headline2!.color!
|
||||
: Theme.of(context).textTheme!.headline3!.color!;
|
||||
|
||||
return AddressCell.fromItem(item,
|
||||
isCurrent: isCurrent,
|
||||
backgroundColor: backgroundColor,
|
||||
textColor: textColor,
|
||||
onTap: (_) => addressListViewModel.setAddress(item),
|
||||
onEdit: () => Navigator.of(context).pushNamed(
|
||||
Routes.newSubaddress,
|
||||
arguments: item));
|
||||
});
|
||||
}
|
||||
|
||||
return index != 0
|
||||
? cell
|
||||
: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(30),
|
||||
topRight: Radius.circular(30)),
|
||||
child: cell,
|
||||
);
|
||||
})),
|
||||
],
|
||||
),
|
||||
)) : Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 7,
|
||||
child: QRWidget(
|
||||
addressListViewModel: addressListViewModel,
|
||||
isAmountFieldShow: true,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
isLight: currentTheme.type == ThemeType.light),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: SizedBox(),
|
||||
),
|
||||
Text(S.of(context).electrum_address_disclaimer,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme!
|
||||
.headline3!
|
||||
.backgroundColor!)),
|
||||
],
|
||||
),
|
||||
);
|
||||
))
|
||||
: Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 7,
|
||||
child: QRWidget(
|
||||
formKey: _formKey,
|
||||
heroTag: _heroTag,
|
||||
addressListViewModel: addressListViewModel,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
amountController: _amountController,
|
||||
isLight: currentTheme.type == ThemeType.light),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: SizedBox(),
|
||||
),
|
||||
Text(S.of(context).electrum_address_disclaimer,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: Theme.of(context).accentTextTheme!.headline3!.backgroundColor!)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
120
lib/src/screens/receive/widgets/currency_input_field.dart
Normal file
120
lib/src/screens/receive/widgets/currency_input_field.dart
Normal file
|
@ -0,0 +1,120 @@
|
|||
import 'package:cake_wallet/core/amount_validator.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class CurrencyInputField extends StatelessWidget {
|
||||
const CurrencyInputField({
|
||||
super.key,
|
||||
required this.onTapPicker,
|
||||
required this.selectedCurrency,
|
||||
this.focusNode,
|
||||
required this.controller,
|
||||
});
|
||||
final Function() onTapPicker;
|
||||
final Currency selectedCurrency;
|
||||
final FocusNode? focusNode;
|
||||
final TextEditingController controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final arrowBottomPurple = Image.asset(
|
||||
'assets/images/arrow_bottom_purple_icon.png',
|
||||
color: Colors.white,
|
||||
height: 8,
|
||||
);
|
||||
final _width = MediaQuery.of(context).size.width;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: BaseTextFormField(
|
||||
focusNode: focusNode,
|
||||
controller: controller,
|
||||
keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true),
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d+(\.|\,)?\d{0,8}'))],
|
||||
hintText: '0.000',
|
||||
placeholderTextStyle: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.headline5!.color!,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor!,
|
||||
textColor: Colors.white,
|
||||
textStyle: TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
prefixIcon: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: _width / 4,
|
||||
),
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(right: 8),
|
||||
child: InkWell(
|
||||
onTap: onTapPicker,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 5),
|
||||
child: arrowBottomPurple,
|
||||
),
|
||||
Text(
|
||||
selectedCurrency.name.toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
if (selectedCurrency.tag != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 3.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).primaryTextTheme.headline4!.color!,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(6),
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
selectedCurrency.tag!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline4!
|
||||
.decorationColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 3.0),
|
||||
child: Text(
|
||||
':',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,37 +1,36 @@
|
|||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/currency_input_field.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:device_display_brightness/device_display_brightness.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/core/amount_validator.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||
|
||||
class QRWidget extends StatelessWidget {
|
||||
QRWidget(
|
||||
{required this.addressListViewModel,
|
||||
required this.isLight,
|
||||
this.qrVersion,
|
||||
this.isAmountFieldShow = false,
|
||||
this.amountTextFieldFocusNode})
|
||||
: amountController = TextEditingController(),
|
||||
_formKey = GlobalKey<FormState>() {
|
||||
amountController.addListener(() => addressListViewModel?.amount =
|
||||
_formKey.currentState!.validate() ? amountController.text : '');
|
||||
}
|
||||
QRWidget({
|
||||
required this.addressListViewModel,
|
||||
required this.isLight,
|
||||
this.qrVersion,
|
||||
this.heroTag,
|
||||
required this.amountController,
|
||||
required this.formKey,
|
||||
this.amountTextFieldFocusNode,
|
||||
});
|
||||
|
||||
final WalletAddressListViewModel addressListViewModel;
|
||||
final bool isAmountFieldShow;
|
||||
final TextEditingController amountController;
|
||||
final FocusNode? amountTextFieldFocusNode;
|
||||
final GlobalKey<FormState> _formKey;
|
||||
final GlobalKey<FormState> formKey;
|
||||
final bool isLight;
|
||||
final int? qrVersion;
|
||||
final String? heroTag;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -40,7 +39,7 @@ class QRWidget extends StatelessWidget {
|
|||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
|
@ -63,18 +62,18 @@ class QRWidget extends StatelessWidget {
|
|||
flex: 5,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
changeBrightnessForRoute(() async {
|
||||
await Navigator.pushNamed(
|
||||
context,
|
||||
Routes.fullscreenQR,
|
||||
arguments: {
|
||||
'qrData': addressListViewModel.uri.toString(),
|
||||
},
|
||||
);
|
||||
});
|
||||
changeBrightnessForRoute(
|
||||
() async {
|
||||
await Navigator.pushNamed(context, Routes.fullscreenQR,
|
||||
arguments: QrViewData(
|
||||
data: addressListViewModel.uri.toString(),
|
||||
heroTag: heroTag,
|
||||
));
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Hero(
|
||||
tag: Key(addressListViewModel.uri.toString()),
|
||||
tag: Key(heroTag ?? addressListViewModel.uri.toString()),
|
||||
child: Center(
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.0,
|
||||
|
@ -83,7 +82,8 @@ class QRWidget extends StatelessWidget {
|
|||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 3,
|
||||
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
color:
|
||||
Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
),
|
||||
),
|
||||
child: QrImage(data: addressListViewModel.uri.toString()),
|
||||
|
@ -99,77 +99,77 @@ class QRWidget extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (isAmountFieldShow)
|
||||
Padding(
|
||||
Observer(builder: (_) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: BaseTextFormField(
|
||||
key: formKey,
|
||||
child: CurrencyInputField(
|
||||
focusNode: amountTextFieldFocusNode,
|
||||
controller: amountController,
|
||||
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||
inputFormatters: [FilteringTextInputFormatter.deny(RegExp('[\\-|\\ ]'))],
|
||||
textAlign: TextAlign.center,
|
||||
hintText: S.of(context).receive_amount,
|
||||
textColor: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!,
|
||||
borderColor: Theme.of(context).textTheme!.headline5!.decorationColor!,
|
||||
validator: AmountValidator(
|
||||
currency: walletTypeToCryptoCurrency(addressListViewModel!.type),
|
||||
isAutovalidate: true),
|
||||
// FIX-ME: Check does it equal to autovalidate: true,
|
||||
autovalidateMode: AutovalidateMode.always,
|
||||
placeholderTextStyle: TextStyle(
|
||||
color: Theme.of(context).hoverColor,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
onTapPicker: () => _presentPicker(context),
|
||||
selectedCurrency: addressListViewModel.selectedCurrency,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 8, bottom: 8),
|
||||
child: Builder(
|
||||
builder: (context) => Observer(
|
||||
builder: (context) => GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: addressListViewModel!.address.address));
|
||||
showBar<void>(context, S.of(context).copied_to_clipboard);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
addressListViewModel!.address.address,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
color:
|
||||
Theme.of(context).accentTextTheme!.headline2!.backgroundColor!),
|
||||
),
|
||||
);
|
||||
}),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20, bottom: 8),
|
||||
child: Builder(
|
||||
builder: (context) => Observer(
|
||||
builder: (context) => GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: addressListViewModel.address.address));
|
||||
showBar<void>(context, S.of(context).copied_to_clipboard);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
addressListViewModel.address.address,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12),
|
||||
child: copyImage,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12),
|
||||
child: copyImage,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _presentPicker(BuildContext context) async {
|
||||
await showPopUp<void>(
|
||||
builder: (_) => CurrencyPicker(
|
||||
selectedAtIndex: addressListViewModel.selectedCurrencyIndex,
|
||||
items: addressListViewModel.currencies,
|
||||
hintText: S.of(context).search_currency,
|
||||
onItemSelected: addressListViewModel.selectCurrency,
|
||||
),
|
||||
context: context,
|
||||
);
|
||||
// update amount if currency changed
|
||||
addressListViewModel.changeAmount(amountController.text);
|
||||
}
|
||||
|
||||
Future<void> changeBrightnessForRoute(Future<void> Function() navigation) async {
|
||||
// if not mobile, just navigate
|
||||
if (!DeviceInfo.instance.isMobile) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
import 'package:cake_wallet/src/widgets/section_divider.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:device_display_brightness/device_display_brightness.dart';
|
||||
|
@ -31,9 +32,7 @@ class WalletKeysPage extends BasePage {
|
|||
await Navigator.pushNamed(
|
||||
context,
|
||||
Routes.fullscreenQR,
|
||||
arguments: {
|
||||
'qrData': (await walletKeysViewModel.url).toString(),
|
||||
},
|
||||
arguments: QrViewData(data: await walletKeysViewModel.url.toString()),
|
||||
);
|
||||
// ignore: unawaited_futures
|
||||
DeviceDisplayBrightness.setBrightness(brightness);
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
|
||||
import 'package:cake_wallet/store/yat/yat_store.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cake_wallet/utils/list_item.dart';
|
||||
|
@ -11,37 +14,30 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
|||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'dart:async';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
|
||||
part 'wallet_address_list_view_model.g.dart';
|
||||
|
||||
class WalletAddressListViewModel = WalletAddressListViewModelBase
|
||||
with _$WalletAddressListViewModel;
|
||||
class WalletAddressListViewModel = WalletAddressListViewModelBase with _$WalletAddressListViewModel;
|
||||
|
||||
abstract class PaymentURI {
|
||||
PaymentURI({
|
||||
required this.amount,
|
||||
required this.address});
|
||||
PaymentURI({required this.amount, required this.address});
|
||||
|
||||
final String amount;
|
||||
final String address;
|
||||
}
|
||||
|
||||
class MoneroURI extends PaymentURI {
|
||||
MoneroURI({
|
||||
required String amount,
|
||||
required String address})
|
||||
MoneroURI({required String amount, required String address})
|
||||
: super(amount: amount, address: address);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var base = 'monero:' + address;
|
||||
|
||||
if (amount?.isNotEmpty ?? false) {
|
||||
if (amount.isNotEmpty) {
|
||||
base += '?tx_amount=${amount.replaceAll(',', '.')}';
|
||||
}
|
||||
|
||||
|
@ -50,16 +46,14 @@ class MoneroURI extends PaymentURI {
|
|||
}
|
||||
|
||||
class HavenURI extends PaymentURI {
|
||||
HavenURI({
|
||||
required String amount,
|
||||
required String address})
|
||||
HavenURI({required String amount, required String address})
|
||||
: super(amount: amount, address: address);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var base = 'haven:' + address;
|
||||
|
||||
if (amount?.isNotEmpty ?? false) {
|
||||
if (amount.isNotEmpty) {
|
||||
base += '?tx_amount=${amount.replaceAll(',', '.')}';
|
||||
}
|
||||
|
||||
|
@ -68,16 +62,14 @@ class HavenURI extends PaymentURI {
|
|||
}
|
||||
|
||||
class BitcoinURI extends PaymentURI {
|
||||
BitcoinURI({
|
||||
required String amount,
|
||||
required String address})
|
||||
BitcoinURI({required String amount, required String address})
|
||||
: super(amount: amount, address: address);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var base = 'bitcoin:' + address;
|
||||
|
||||
if (amount?.isNotEmpty ?? false) {
|
||||
if (amount.isNotEmpty) {
|
||||
base += '?amount=${amount.replaceAll(',', '.')}';
|
||||
}
|
||||
|
||||
|
@ -86,16 +78,14 @@ class BitcoinURI extends PaymentURI {
|
|||
}
|
||||
|
||||
class LitecoinURI extends PaymentURI {
|
||||
LitecoinURI({
|
||||
required String amount,
|
||||
required String address})
|
||||
LitecoinURI({required String amount, required String address})
|
||||
: super(amount: amount, address: address);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var base = 'litecoin:' + address;
|
||||
|
||||
if (amount?.isNotEmpty ?? false) {
|
||||
if (amount.isNotEmpty) {
|
||||
base += '?amount=${amount.replaceAll(',', '.')}';
|
||||
}
|
||||
|
||||
|
@ -106,24 +96,33 @@ class LitecoinURI extends PaymentURI {
|
|||
abstract class WalletAddressListViewModelBase with Store {
|
||||
WalletAddressListViewModelBase({
|
||||
required AppStore appStore,
|
||||
required this.yatStore
|
||||
}) : _appStore = appStore,
|
||||
_baseItems = <ListItem>[],
|
||||
_wallet = appStore.wallet!,
|
||||
hasAccounts = appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven,
|
||||
amount = '' {
|
||||
_onWalletChangeReaction = reaction((_) => _appStore.wallet, (WalletBase<
|
||||
Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
||||
wallet) {
|
||||
if (wallet == null) {
|
||||
return;
|
||||
}
|
||||
_wallet = wallet;
|
||||
hasAccounts = _wallet.type == WalletType.monero;
|
||||
});
|
||||
required this.yatStore,
|
||||
required this.fiatConversionStore,
|
||||
}) : _appStore = appStore,
|
||||
_baseItems = <ListItem>[],
|
||||
_wallet = appStore.wallet!,
|
||||
selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
|
||||
_cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
|
||||
hasAccounts =
|
||||
appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven,
|
||||
amount = '' {
|
||||
_init();
|
||||
}
|
||||
|
||||
static const String _cryptoNumberPattern = '0.00000000';
|
||||
|
||||
final NumberFormat _cryptoNumberFormat;
|
||||
|
||||
final FiatConversionStore fiatConversionStore;
|
||||
|
||||
List<Currency> get currencies => [walletTypeToCryptoCurrency(_wallet.type), ...FiatCurrency.all];
|
||||
|
||||
@observable
|
||||
Currency selectedCurrency;
|
||||
|
||||
@computed
|
||||
int get selectedCurrencyIndex => currencies.indexOf(selectedCurrency);
|
||||
|
||||
@observable
|
||||
String amount;
|
||||
|
||||
|
@ -156,8 +155,9 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
}
|
||||
|
||||
@computed
|
||||
ObservableList<ListItem> get items =>
|
||||
ObservableList<ListItem>()..addAll(_baseItems)..addAll(addressList);
|
||||
ObservableList<ListItem> get items => ObservableList<ListItem>()
|
||||
..addAll(_baseItems)
|
||||
..addAll(addressList);
|
||||
|
||||
@computed
|
||||
ObservableList<ListItem> get addressList {
|
||||
|
@ -166,10 +166,7 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
|
||||
if (wallet.type == WalletType.monero) {
|
||||
final primaryAddress = monero!.getSubaddressList(wallet).subaddresses.first;
|
||||
final addressItems = monero
|
||||
!.getSubaddressList(wallet)
|
||||
.subaddresses
|
||||
.map((subaddress) {
|
||||
final addressItems = monero!.getSubaddressList(wallet).subaddresses.map((subaddress) {
|
||||
final isPrimary = subaddress == primaryAddress;
|
||||
|
||||
return WalletAddressListItem(
|
||||
|
@ -183,10 +180,7 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
|
||||
if (wallet.type == WalletType.haven) {
|
||||
final primaryAddress = haven!.getSubaddressList(wallet).subaddresses.first;
|
||||
final addressItems = haven
|
||||
!.getSubaddressList(wallet)
|
||||
.subaddresses
|
||||
.map((subaddress) {
|
||||
final addressItems = haven!.getSubaddressList(wallet).subaddresses.map((subaddress) {
|
||||
final isPrimary = subaddress == primaryAddress;
|
||||
|
||||
return WalletAddressListItem(
|
||||
|
@ -203,8 +197,7 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
final bitcoinAddresses = bitcoin!.getAddresses(wallet).map((addr) {
|
||||
final isPrimary = addr == primaryAddress;
|
||||
|
||||
return WalletAddressListItem(
|
||||
isPrimary: isPrimary, name: null, address: addr);
|
||||
return WalletAddressListItem(isPrimary: isPrimary, name: null, address: addr);
|
||||
});
|
||||
addressList.addAll(bitcoinAddresses);
|
||||
}
|
||||
|
@ -234,8 +227,7 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
bool get hasAddressList => _wallet.type == WalletType.monero || _wallet.type == WalletType.haven;
|
||||
|
||||
@observable
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>
|
||||
_wallet;
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet;
|
||||
|
||||
List<ListItem> _baseItems;
|
||||
|
||||
|
@ -243,8 +235,6 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
|
||||
final YatStore yatStore;
|
||||
|
||||
ReactionDisposer? _onWalletChangeReaction;
|
||||
|
||||
@action
|
||||
void setAddress(WalletAddressListItem address) =>
|
||||
_wallet.walletAddresses.address = address.address;
|
||||
|
@ -258,4 +248,31 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
|
||||
_baseItems.add(WalletAddressListHeader());
|
||||
}
|
||||
|
||||
@action
|
||||
void selectCurrency(Currency currency) {
|
||||
selectedCurrency = currency;
|
||||
}
|
||||
|
||||
@action
|
||||
void changeAmount(String amount) {
|
||||
this.amount = amount;
|
||||
if (selectedCurrency is FiatCurrency) {
|
||||
_convertAmountToCrypto();
|
||||
}
|
||||
}
|
||||
|
||||
void _convertAmountToCrypto() {
|
||||
final cryptoCurrency = walletTypeToCryptoCurrency(_wallet.type);
|
||||
try {
|
||||
final crypto =
|
||||
double.parse(amount.replaceAll(',', '.')) / fiatConversionStore.prices[cryptoCurrency]!;
|
||||
final cryptoAmountTmp = _cryptoNumberFormat.format(crypto);
|
||||
if (amount != cryptoAmountTmp) {
|
||||
amount = cryptoAmountTmp;
|
||||
}
|
||||
} catch (e) {
|
||||
amount = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue