mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-29 10:38:49 +00:00
change amount widget as in send views, read currency selections from API
This commit is contained in:
parent
7e3cad5a06
commit
cfe40c76d9
6 changed files with 434 additions and 308 deletions
lib
models/buy/simplex
pages/buy_view
services/buy
widgets/textfields
|
@ -1,16 +1,16 @@
|
|||
// import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
||||
// import 'package:stackwallet/models/buy/response_objects/fiat.dart';
|
||||
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
||||
import 'package:stackwallet/models/buy/response_objects/fiat.dart';
|
||||
// import 'package:stackwallet/models/buy/response_objects/pair.dart';
|
||||
|
||||
class SimplexSupportedCurrencies {
|
||||
dynamic supportedCryptos = [];
|
||||
dynamic supportedFiats = [];
|
||||
List<Crypto> supportedCryptos = [];
|
||||
List<Fiat> supportedFiats = [];
|
||||
|
||||
void updateSupportedCryptos(dynamic newCryptos) {
|
||||
void updateSupportedCryptos(List<Crypto> newCryptos) {
|
||||
supportedCryptos = newCryptos;
|
||||
}
|
||||
|
||||
void updateSupportedFiats(dynamic newFiats) {
|
||||
void updateSupportedFiats(List<Fiat> newFiats) {
|
||||
supportedFiats = newFiats;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
||||
import 'package:stackwallet/models/buy/response_objects/fiat.dart';
|
||||
import 'package:stackwallet/pages/buy_view/sub_widgets/crypto_selection_view.dart';
|
||||
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_crypto_toggle.dart';
|
||||
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_selection_view.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/buy/buy_data_loading_service.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||
|
@ -26,7 +28,6 @@ import 'package:stackwallet/widgets/rounded_container.dart';
|
|||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/textfields/buy_textfield.dart';
|
||||
|
||||
class BuyForm extends ConsumerStatefulWidget {
|
||||
const BuyForm({
|
||||
|
@ -47,14 +48,16 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
late final BarcodeScannerInterface scanner;
|
||||
|
||||
late final TextEditingController _receiveAddressController;
|
||||
late final TextEditingController _fiatController;
|
||||
late final TextEditingController _cryptoController;
|
||||
late final TextEditingController _buyAmountController;
|
||||
final FocusNode _receiveAddressFocusNode = FocusNode();
|
||||
final FocusNode _fiatFocusNode = FocusNode();
|
||||
final FocusNode _cryptoFocusNode = FocusNode();
|
||||
final FocusNode _buyAmountFocusNode = FocusNode();
|
||||
|
||||
final isDesktop = Util.isDesktop;
|
||||
|
||||
List<Crypto>? coins;
|
||||
List<Fiat>? fiats;
|
||||
String? _address;
|
||||
|
||||
bool buyWithFiat = true;
|
||||
|
@ -67,13 +70,11 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
void cryptoFieldOnChanged(String value) async {}
|
||||
|
||||
void selectCrypto() async {
|
||||
final fromTicker = ref.read(buyFormStateProvider).fromTicker ?? "-";
|
||||
final supportedCoins = ref.watch(supportedSimplexCurrenciesProvider);
|
||||
|
||||
List<Crypto> coins = [];
|
||||
final supportedCoins =
|
||||
ref.watch(supportedSimplexCurrenciesProvider).supportedCryptos;
|
||||
|
||||
await _showFloatingCryptoSelectionSheet(
|
||||
coins: coins,
|
||||
coins: supportedCoins,
|
||||
onSelected: (from) =>
|
||||
ref.read(buyFormStateProvider).updateFrom(from, true));
|
||||
}
|
||||
|
@ -102,7 +103,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
left: 32,
|
||||
),
|
||||
child: Text(
|
||||
"Choose a fiat currency with which to pay",
|
||||
"Choose a crypto to buy",
|
||||
style: STextStyles.desktopH3(context),
|
||||
),
|
||||
),
|
||||
|
@ -124,8 +125,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
borderColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
child: FiatSelectionView(
|
||||
fiats: coins,
|
||||
child: CryptoSelectionView(
|
||||
coins: coins,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -139,23 +140,23 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
})
|
||||
: await Navigator.of(context).push(
|
||||
MaterialPageRoute<dynamic>(
|
||||
builder: (_) => FiatSelectionView(
|
||||
fiats: coins,
|
||||
builder: (_) => CryptoSelectionView(
|
||||
coins: coins,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (mounted && result is Fiat) {
|
||||
if (mounted && result is Crypto) {
|
||||
onSelected(result);
|
||||
}
|
||||
}
|
||||
|
||||
void selectFiat() async {
|
||||
List<Fiat> fiats;
|
||||
fiats = [];
|
||||
final supportedFiats =
|
||||
ref.watch(supportedSimplexCurrenciesProvider).supportedFiats;
|
||||
|
||||
await _showFloatingFiatSelectionSheet(
|
||||
fiats: fiats,
|
||||
fiats: supportedFiats,
|
||||
onSelected: (from) =>
|
||||
ref.read(buyFormStateProvider).updateFrom(from, true));
|
||||
}
|
||||
|
@ -279,13 +280,15 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
_fiatController = TextEditingController();
|
||||
_cryptoController = TextEditingController();
|
||||
_receiveAddressController = TextEditingController();
|
||||
_buyAmountController = TextEditingController();
|
||||
|
||||
clipboard = widget.clipboard;
|
||||
scanner = widget.scanner;
|
||||
|
||||
coins = ref.read(supportedSimplexCurrenciesProvider).supportedCryptos;
|
||||
fiats = ref.read(supportedSimplexCurrenciesProvider).supportedFiats;
|
||||
|
||||
// TODO set initial crypto to open wallet if a wallet is open
|
||||
|
||||
super.initState();
|
||||
|
@ -325,6 +328,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
onExit: (_) => setState(() => _hovering1 = false),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
BuyDataLoadingService().loadAll(ref);
|
||||
selectCrypto();
|
||||
},
|
||||
child: RoundedContainer(
|
||||
|
@ -474,32 +478,57 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
SizedBox(
|
||||
height: isDesktop ? 10 : 4,
|
||||
),
|
||||
BuyTextField(
|
||||
controller: _fiatController,
|
||||
focusNode: _fiatFocusNode,
|
||||
textStyle: STextStyles.smallMed14(context).copyWith(
|
||||
TextField(
|
||||
autocorrect: Util.isDesktop ? false : true,
|
||||
enableSuggestions: Util.isDesktop ? false : true,
|
||||
style: STextStyles.smallMed14(context).copyWith(
|
||||
color: Theme.of(context).extension<StackColors>()!.textDark,
|
||||
),
|
||||
buttonColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.buttonBackSecondary,
|
||||
borderRadius: Constants.size.circularBorderRadius,
|
||||
background: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
onTap: () {
|
||||
if (_fiatController.text == "-") {
|
||||
_fiatController.text = "";
|
||||
}
|
||||
},
|
||||
onChanged: fiatFieldOnChanged,
|
||||
onButtonTap: selectFiat,
|
||||
// isWalletCoin: isWalletCoin(coin, true),
|
||||
isWalletCoin: false,
|
||||
// image: _fetchIconUrlFromTicker(ref
|
||||
// .watch(buyFormStateProvider.select((value) => value.fromTicker))),
|
||||
// ticker: ref
|
||||
// .watch(buyFormStateProvider.select((value) => value.fromTicker)),
|
||||
key: const Key("amountInputFieldCryptoTextFieldKey"),
|
||||
controller: _buyAmountController,
|
||||
focusNode: _buyAmountFocusNode,
|
||||
keyboardType: Util.isDesktop
|
||||
? null
|
||||
: const TextInputType.numberWithOptions(
|
||||
signed: false,
|
||||
decimal: true,
|
||||
),
|
||||
textAlign: TextAlign.right,
|
||||
inputFormatters: [
|
||||
// TODO reactivate formatter
|
||||
// regex to validate a crypto amount with 8 decimal places
|
||||
// TextInputFormatter.withFunction((oldValue, newValue) =>
|
||||
// RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
||||
// .hasMatch(newValue.text)
|
||||
// ? newValue
|
||||
// : oldValue),
|
||||
],
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.only(
|
||||
top: 22,
|
||||
right: 12,
|
||||
bottom: 22,
|
||||
),
|
||||
hintText: "0",
|
||||
hintStyle: STextStyles.desktopTextExtraSmall(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultText,
|
||||
),
|
||||
prefixIcon: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Text(
|
||||
"BTC",
|
||||
style: STextStyles.smallMed14(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: isDesktop ? 20 : 12,
|
||||
|
|
332
lib/pages/buy_view/sub_widgets/crypto_selection_view.dart
Normal file
332
lib/pages/buy_view/sub_widgets/crypto_selection_view.dart
Normal file
|
@ -0,0 +1,332 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||
import 'package:stackwallet/widgets/loading_indicator.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||
|
||||
class CryptoSelectionView extends StatefulWidget {
|
||||
const CryptoSelectionView({
|
||||
Key? key,
|
||||
required this.coins,
|
||||
}) : super(key: key);
|
||||
|
||||
final List<Crypto> coins;
|
||||
|
||||
@override
|
||||
State<CryptoSelectionView> createState() => _CryptoSelectionViewState();
|
||||
}
|
||||
|
||||
class _CryptoSelectionViewState extends State<CryptoSelectionView> {
|
||||
late TextEditingController _searchController;
|
||||
final _searchFocusNode = FocusNode();
|
||||
|
||||
late final List<Crypto> coins;
|
||||
late List<Crypto> _coins;
|
||||
|
||||
void filter(String text) {
|
||||
setState(() {
|
||||
_coins = [
|
||||
...coins.where((e) =>
|
||||
e.name.toLowerCase().contains(text.toLowerCase()) ||
|
||||
e.ticker.toLowerCase().contains(text.toLowerCase()))
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_searchController = TextEditingController();
|
||||
|
||||
coins = [...widget.coins];
|
||||
coins.sort(
|
||||
(a, b) => a.ticker.toLowerCase().compareTo(b.ticker.toLowerCase()));
|
||||
for (Coin coin in Coin.values.reversed) {
|
||||
int index = coins.indexWhere((element) =>
|
||||
element.ticker.toLowerCase() == coin.ticker.toLowerCase());
|
||||
if (index > 0) {
|
||||
final currency = coins.removeAt(index);
|
||||
coins.insert(0, currency);
|
||||
}
|
||||
}
|
||||
|
||||
_coins = [...coins];
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchController.dispose();
|
||||
_searchFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isDesktop = Util.isDesktop;
|
||||
return ConditionalParent(
|
||||
condition: !isDesktop,
|
||||
builder: (child) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
backgroundColor:
|
||||
Theme.of(context).extension<StackColors>()!.background,
|
||||
appBar: AppBar(
|
||||
leading: AppBarBackButton(
|
||||
onPressed: () async {
|
||||
if (FocusScope.of(context).hasFocus) {
|
||||
FocusScope.of(context).unfocus();
|
||||
await Future<void>.delayed(
|
||||
const Duration(milliseconds: 50));
|
||||
}
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
title: Text(
|
||||
"Choose a coin to buy",
|
||||
style: STextStyles.pageTitleH2(context),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max,
|
||||
children: [
|
||||
if (!isDesktop)
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: TextField(
|
||||
autofocus: isDesktop,
|
||||
autocorrect: !isDesktop,
|
||||
enableSuggestions: !isDesktop,
|
||||
controller: _searchController,
|
||||
focusNode: _searchFocusNode,
|
||||
onChanged: filter,
|
||||
style: STextStyles.field(context),
|
||||
decoration: standardInputDecoration(
|
||||
"Search",
|
||||
_searchFocusNode,
|
||||
context,
|
||||
desktopMed: isDesktop,
|
||||
).copyWith(
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 16,
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
Assets.svg.search,
|
||||
width: 16,
|
||||
height: 16,
|
||||
),
|
||||
),
|
||||
suffixIcon: _searchController.text.isNotEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(right: 0),
|
||||
child: UnconstrainedBox(
|
||||
child: Row(
|
||||
children: [
|
||||
TextFieldIconButton(
|
||||
child: const XIcon(),
|
||||
onTap: () async {
|
||||
setState(() {
|
||||
_searchController.text = "";
|
||||
});
|
||||
filter("");
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
"Popular coins",
|
||||
style: STextStyles.smallMed12(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Flexible(
|
||||
child: Builder(builder: (context) {
|
||||
final items = _coins
|
||||
.where((e) => Coin.values
|
||||
.where((coin) =>
|
||||
coin.ticker.toLowerCase() == e.ticker.toLowerCase())
|
||||
.isNotEmpty)
|
||||
.toList(growable: false);
|
||||
|
||||
return RoundedWhiteContainer(
|
||||
padding: const EdgeInsets.all(0),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
primary: isDesktop ? false : null,
|
||||
itemCount: items.length,
|
||||
itemBuilder: (builderContext, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop(items[index]);
|
||||
},
|
||||
child: RoundedWhiteContainer(
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: SvgPicture.network(
|
||||
items[index].image,
|
||||
width: 24,
|
||||
height: 24,
|
||||
placeholderBuilder: (_) =>
|
||||
const LoadingIndicator(),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
items[index].name,
|
||||
style: STextStyles.largeMedium14(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
Text(
|
||||
items[index].ticker.toUpperCase(),
|
||||
style: STextStyles.smallMed12(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textSubtitle1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
"All coins",
|
||||
style: STextStyles.smallMed12(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Flexible(
|
||||
child: RoundedWhiteContainer(
|
||||
padding: const EdgeInsets.all(0),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
primary: isDesktop ? false : null,
|
||||
itemCount: _coins.length,
|
||||
itemBuilder: (builderContext, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop(_coins[index]);
|
||||
},
|
||||
child: RoundedWhiteContainer(
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: SvgPicture.network(
|
||||
_coins[index].image,
|
||||
width: 24,
|
||||
height: 24,
|
||||
placeholderBuilder: (_) =>
|
||||
const LoadingIndicator(),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
_coins[index].name,
|
||||
style: STextStyles.largeMedium14(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
Text(
|
||||
_coins[index].ticker.toUpperCase(),
|
||||
style: STextStyles.smallMed12(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textSubtitle1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -29,10 +29,9 @@ class BuyDataLoadingService {
|
|||
final response = await SimplexAPI.instance.getSupported();
|
||||
|
||||
if (response['supportedCryptos'] != null) {
|
||||
print(response['supportedCryptos']);
|
||||
ref
|
||||
.read(supportedSimplexCurrenciesProvider)
|
||||
.updateSupportedCryptos(response['supportedCryptos']!);
|
||||
.updateSupportedCryptos(response['supportedCryptos']);
|
||||
} else {
|
||||
error = true;
|
||||
Logging.instance.log(
|
||||
|
@ -40,11 +39,11 @@ class BuyDataLoadingService {
|
|||
level: LogLevel.Warning,
|
||||
);
|
||||
}
|
||||
|
||||
if (response['supportedFiats'] != null) {
|
||||
print(response['supportedFiats']);
|
||||
ref
|
||||
.read(supportedSimplexCurrenciesProvider)
|
||||
.updateSupportedFiats(response['supportedFiats']!);
|
||||
.updateSupportedFiats(response['supportedFiats']);
|
||||
} else {
|
||||
error = true;
|
||||
Logging.instance.log(
|
||||
|
@ -56,8 +55,8 @@ class BuyDataLoadingService {
|
|||
if (error) {
|
||||
// _loadSimplexCurrencies() again?
|
||||
} else {
|
||||
ref.read(changeNowEstimatedInitialLoadStatusStateProvider.state).state =
|
||||
ChangeNowLoadStatus.success;
|
||||
ref.read(simplexLoadStatusStateProvider.state).state =
|
||||
SimplexLoadStatus.success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
||||
// import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.dart';
|
||||
// import 'package:stackwallet/models/exchange/response_objects/pair.dart';
|
||||
// import 'package:stackwallet/models/exchange/response_objects/range.dart';
|
||||
|
@ -180,23 +181,30 @@ class SimplexAPI {
|
|||
|
||||
dynamic /*BuyResponse<List<Fiat>>*/ _parseSupported(dynamic jsonArray) {
|
||||
try {
|
||||
List<Fiat> cryptos = [];
|
||||
List<Crypto> cryptos = [];
|
||||
List<Fiat> fiats = [];
|
||||
|
||||
var supportedCryptos =
|
||||
jsonArray['result']['supported_digital_currencies'];
|
||||
// for (final ticker in supportedCryptos as List) {
|
||||
// cryptos.add(Fiat.fromString(ticker as String));
|
||||
// }
|
||||
// TODO map List<String> supportedCryptos to List<Crypto>
|
||||
for (final ticker in supportedCryptos as List) {
|
||||
cryptos.add(Crypto.fromJson({
|
||||
'ticker': ticker as String,
|
||||
'name': ticker as String,
|
||||
'image': ticker as String,
|
||||
}));
|
||||
}
|
||||
var supportedFiats = jsonArray['result']['supported_fiat_currencies'];
|
||||
// for (final ticker in supportedFiats as List) {
|
||||
// fiats.add(Fiat.fromString(ticker as String));
|
||||
// }
|
||||
// TODO map List<String> supportedFiats to List<Fiat>
|
||||
for (final ticker in supportedFiats as List) {
|
||||
fiats.add(Fiat.fromJson({
|
||||
'ticker': ticker as String,
|
||||
'name': ticker as String,
|
||||
'image': ticker as String,
|
||||
}));
|
||||
}
|
||||
|
||||
var supported = {
|
||||
'supportedCryptos': supportedCryptos,
|
||||
'supportedFiats': supportedFiats
|
||||
};
|
||||
var supported = {'supportedCryptos': cryptos, 'supportedFiats': fiats};
|
||||
|
||||
return supported;
|
||||
} catch (e, s) {
|
||||
|
|
|
@ -1,242 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/loading_indicator.dart';
|
||||
|
||||
class BuyTextField extends StatefulWidget {
|
||||
const BuyTextField({
|
||||
Key? key,
|
||||
this.borderRadius = 0,
|
||||
this.background,
|
||||
required this.controller,
|
||||
this.buttonColor,
|
||||
required this.focusNode,
|
||||
this.buttonContent,
|
||||
required this.textStyle,
|
||||
this.onButtonTap,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.onTap,
|
||||
required this.isWalletCoin,
|
||||
this.image,
|
||||
this.ticker,
|
||||
this.readOnly = false,
|
||||
}) : super(key: key);
|
||||
|
||||
final double borderRadius;
|
||||
final Color? background;
|
||||
final Color? buttonColor;
|
||||
final Widget? buttonContent;
|
||||
final TextEditingController controller;
|
||||
final FocusNode focusNode;
|
||||
final TextStyle textStyle;
|
||||
final VoidCallback? onTap;
|
||||
final VoidCallback? onButtonTap;
|
||||
final void Function(String)? onChanged;
|
||||
final void Function(String)? onSubmitted;
|
||||
|
||||
final bool isWalletCoin;
|
||||
final bool readOnly;
|
||||
final String? image;
|
||||
final String? ticker;
|
||||
|
||||
@override
|
||||
State<BuyTextField> createState() => _BuyTextFieldState();
|
||||
}
|
||||
|
||||
class _BuyTextFieldState extends State<BuyTextField> {
|
||||
late final TextEditingController controller;
|
||||
late final FocusNode focusNode;
|
||||
late final TextStyle textStyle;
|
||||
|
||||
late final double borderRadius;
|
||||
|
||||
late final Color? background;
|
||||
late final Color? buttonColor;
|
||||
late final Widget? buttonContent;
|
||||
late final VoidCallback? onButtonTap;
|
||||
late final VoidCallback? onTap;
|
||||
late final void Function(String)? onChanged;
|
||||
late final void Function(String)? onSubmitted;
|
||||
|
||||
final isDesktop = Util.isDesktop;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
borderRadius = widget.borderRadius;
|
||||
background = widget.background;
|
||||
buttonColor = widget.buttonColor;
|
||||
controller = widget.controller;
|
||||
focusNode = widget.focusNode;
|
||||
buttonContent = widget.buttonContent;
|
||||
textStyle = widget.textStyle;
|
||||
onButtonTap = widget.onButtonTap;
|
||||
onChanged = widget.onChanged;
|
||||
onSubmitted = widget.onSubmitted;
|
||||
onTap = widget.onTap;
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: background,
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
),
|
||||
child: IntrinsicHeight(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
style: textStyle,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
onChanged: onChanged,
|
||||
onTap: onTap,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
readOnly: widget.readOnly,
|
||||
keyboardType: isDesktop
|
||||
? null
|
||||
: const TextInputType.numberWithOptions(
|
||||
signed: false,
|
||||
decimal: true,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.only(
|
||||
top: 12,
|
||||
left: 12,
|
||||
),
|
||||
hintText: "0",
|
||||
hintStyle: STextStyles.fieldLabel(context).copyWith(
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
inputFormatters: [
|
||||
// regex to validate a crypto amount with 8 decimal places
|
||||
TextInputFormatter.withFunction((oldValue, newValue) =>
|
||||
RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
|
||||
.hasMatch(newValue.text)
|
||||
? newValue
|
||||
: oldValue),
|
||||
],
|
||||
),
|
||||
),
|
||||
MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: () => onButtonTap?.call(),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: buttonColor,
|
||||
borderRadius: BorderRadius.horizontal(
|
||||
right: Radius.circular(
|
||||
borderRadius,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 18,
|
||||
height: 18,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final image = widget.image;
|
||||
|
||||
if (image != null && image.isNotEmpty) {
|
||||
return Center(
|
||||
child: SvgPicture.network(
|
||||
image,
|
||||
height: 18,
|
||||
placeholderBuilder: (_) => Container(
|
||||
width: 18,
|
||||
height: 18,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
borderRadius: BorderRadius.circular(
|
||||
18,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
18,
|
||||
),
|
||||
child: const LoadingIndicator(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container(
|
||||
width: 18,
|
||||
height: 18,
|
||||
decoration: BoxDecoration(
|
||||
// color: Theme.of(context).extension<StackColors>()!.accentColorDark
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
Assets.svg.circleQuestion,
|
||||
width: 18,
|
||||
height: 18,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 6,
|
||||
),
|
||||
Text(
|
||||
widget.ticker?.toUpperCase() ?? "-",
|
||||
style: STextStyles.smallMed14(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
),
|
||||
),
|
||||
if (!widget.isWalletCoin)
|
||||
const SizedBox(
|
||||
width: 6,
|
||||
),
|
||||
if (!widget.isWalletCoin)
|
||||
SvgPicture.asset(
|
||||
Assets.svg.chevronDown,
|
||||
width: 5,
|
||||
height: 2.5,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue