mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
add fiat crypto toggle and crypto selection list
This commit is contained in:
parent
c746eb8865
commit
9724b40848
6 changed files with 754 additions and 88 deletions
|
@ -1,14 +1,14 @@
|
|||
class Currency {
|
||||
/// Currency ticker
|
||||
class Crypto {
|
||||
/// Crypto ticker
|
||||
final String ticker;
|
||||
|
||||
/// Currency name
|
||||
/// Crypto name
|
||||
final String name;
|
||||
|
||||
/// Currency network
|
||||
/// Crypto network
|
||||
final String network;
|
||||
|
||||
/// Currency logo url
|
||||
/// Crypto logo url
|
||||
final String image;
|
||||
|
||||
/// Indicates if a currency has an Extra ID
|
||||
|
@ -33,7 +33,7 @@ class Currency {
|
|||
/// currently supported by change now
|
||||
final bool? isAvailable;
|
||||
|
||||
Currency({
|
||||
Crypto({
|
||||
required this.ticker,
|
||||
required this.name,
|
||||
required this.network,
|
||||
|
@ -47,9 +47,9 @@ class Currency {
|
|||
this.isAvailable,
|
||||
});
|
||||
|
||||
factory Currency.fromJson(Map<String, dynamic> json) {
|
||||
factory Crypto.fromJson(Map<String, dynamic> json) {
|
||||
try {
|
||||
return Currency(
|
||||
return Crypto(
|
||||
ticker: json["ticker"] as String,
|
||||
name: json["name"] as String,
|
||||
network: json["network"] as String? ?? "",
|
||||
|
@ -88,7 +88,7 @@ class Currency {
|
|||
return map;
|
||||
}
|
||||
|
||||
Currency copyWith({
|
||||
Crypto copyWith({
|
||||
String? ticker,
|
||||
String? name,
|
||||
String? network,
|
||||
|
@ -101,7 +101,7 @@ class Currency {
|
|||
bool? supportsFixedRate,
|
||||
bool? isAvailable,
|
||||
}) {
|
||||
return Currency(
|
||||
return Crypto(
|
||||
ticker: ticker ?? this.ticker,
|
||||
name: name ?? this.name,
|
||||
network: network ?? this.network,
|
||||
|
@ -118,6 +118,6 @@ class Currency {
|
|||
|
||||
@override
|
||||
String toString() {
|
||||
return "Currency: ${toJson()}";
|
||||
return "Crypto: ${toJson()}";
|
||||
}
|
||||
}
|
73
lib/models/buy/response_objects/pair.dart
Normal file
73
lib/models/buy/response_objects/pair.dart
Normal file
|
@ -0,0 +1,73 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
|
||||
class Pair {
|
||||
final String from;
|
||||
final String fromNetwork;
|
||||
|
||||
final String to;
|
||||
final String toNetwork;
|
||||
|
||||
final bool fixedRate;
|
||||
final bool floatingRate;
|
||||
|
||||
Pair({
|
||||
required this.from,
|
||||
required this.fromNetwork,
|
||||
required this.to,
|
||||
required this.toNetwork,
|
||||
required this.fixedRate,
|
||||
required this.floatingRate,
|
||||
});
|
||||
|
||||
factory Pair.fromMap(Map<String, dynamic> map) {
|
||||
try {
|
||||
return Pair(
|
||||
from: map["from"] as String,
|
||||
fromNetwork: map["fromNetwork"] as String,
|
||||
to: map["to"] as String,
|
||||
toNetwork: map["toNetwork"] as String,
|
||||
fixedRate: map["fixedRate"] as bool,
|
||||
floatingRate: map["floatingRate"] as bool,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logging.instance.log("Pair.fromMap(): $e\n$s", level: LogLevel.Error);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"from": from,
|
||||
"fromNetwork": fromNetwork,
|
||||
"to": to,
|
||||
"toNetwork": toNetwork,
|
||||
"fixedRate": fixedRate,
|
||||
"floatingRate": floatingRate,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
other is Pair &&
|
||||
from == other.from &&
|
||||
fromNetwork == other.fromNetwork &&
|
||||
to == other.to &&
|
||||
toNetwork == other.toNetwork &&
|
||||
fixedRate == other.fixedRate &&
|
||||
floatingRate == other.floatingRate;
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(
|
||||
from,
|
||||
fromNetwork,
|
||||
to,
|
||||
toNetwork,
|
||||
fixedRate,
|
||||
floatingRate,
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() => "Pair: ${toMap()}";
|
||||
}
|
332
lib/pages/buy_view/buy_coin_selection/crypto_selection_view.dart
Normal file
332
lib/pages/buy_view/buy_coin_selection/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 crypto 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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,12 +1,19 @@
|
|||
import 'package:decimal/decimal.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/models/buy/response_objects/crypto.dart';
|
||||
import 'package:stackwallet/models/buy/response_objects/pair.dart';
|
||||
import 'package:stackwallet/pages/buy_view/buy_coin_selection/crypto_selection_view.dart';
|
||||
import 'package:stackwallet/pages/buy_view/sub_widgets/fiat_crypto_toggle.dart';
|
||||
import 'package:stackwallet/providers/providers.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/desktop/desktop_dialog.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
import 'package:stackwallet/widgets/textfields/buy_textfield.dart';
|
||||
|
||||
class BuyForm extends ConsumerStatefulWidget {
|
||||
|
@ -50,11 +57,245 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
}
|
||||
}
|
||||
|
||||
void selectFiatCurrency() async {
|
||||
void selectFiatCrypto() async {
|
||||
// await Future<void>.delayed(const Duration(milliseconds: 300));
|
||||
//
|
||||
// Navigator.of(context, rootNavigator: true).pop();
|
||||
}
|
||||
|
||||
void cryptoFieldOnChanged(String value) async {
|
||||
if (_cryptoFocusNode.hasFocus) {
|
||||
final newCryptoAmount = Decimal.tryParse(value);
|
||||
|
||||
await ref.read(buyFormStateProvider).setFromAmountAndCalculateToAmount(
|
||||
newCryptoAmount ?? Decimal.zero, true);
|
||||
|
||||
if (newCryptoAmount == null) {
|
||||
_cryptoController.text = "XXX";
|
||||
// ref.read(prefsChangeNotifierProvider).exchangeRateType ==
|
||||
// ExchangeRateType.estimated
|
||||
// ? "-"
|
||||
// : "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void selectCryptoCrypto() async {
|
||||
final fromTicker = ref.read(exchangeFormStateProvider).fromTicker ?? "-";
|
||||
// ref.read(estimatedRateExchangeFormProvider).from?.ticker ?? "-";
|
||||
|
||||
// if (walletInitiated &&
|
||||
// fromTicker.toLowerCase() == coin!.ticker.toLowerCase()) {
|
||||
// // do not allow changing away from wallet coin
|
||||
// return;
|
||||
// }
|
||||
|
||||
List<Crypto> coins;
|
||||
switch (ref.read(currentExchangeNameStateProvider.state).state) {
|
||||
// case ChangeNowExchange.exchangeName:
|
||||
// coins = ref.read(availableChangeNowCurrenciesProvider).coins;
|
||||
// break;
|
||||
// case SimpleSwapExchange.exchangeName:
|
||||
// coins = ref
|
||||
// .read(availableSimpleswapCurrenciesProvider)
|
||||
// .floatingRateCurrencies;
|
||||
// break;
|
||||
default:
|
||||
coins = [];
|
||||
}
|
||||
|
||||
await _showFloatingCryptoSelectionSheet(
|
||||
coins: coins,
|
||||
excludedTicker: ref.read(buyFormStateProvider).toTicker ?? "-",
|
||||
fromTicker: fromTicker,
|
||||
onSelected: (from) =>
|
||||
ref.read(buyFormStateProvider).updateFrom(from, true));
|
||||
|
||||
// unawaited(
|
||||
// showDialog<void>(
|
||||
// context: context,
|
||||
// barrierDismissible: false,
|
||||
// builder: (_) => WillPopScope(
|
||||
// onWillPop: () async => false,
|
||||
// child: Container(
|
||||
// color: Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .overlay
|
||||
// .withOpacity(0.6),
|
||||
// child: const CustomLoadingOverlay(
|
||||
// message: "Updating exchange rate",
|
||||
// eventBus: null,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
|
||||
await Future<void>.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
Navigator.of(context, rootNavigator: true).pop();
|
||||
}
|
||||
|
||||
Future<void> _showFloatingCryptoSelectionSheet({
|
||||
required List<Crypto> coins,
|
||||
required String excludedTicker,
|
||||
required String fromTicker,
|
||||
required void Function(Crypto) onSelected,
|
||||
}) async {
|
||||
_fiatFocusNode.unfocus();
|
||||
_cryptoFocusNode.unfocus();
|
||||
|
||||
List<Pair> allPairs;
|
||||
|
||||
switch (ref.read(currentExchangeNameStateProvider.state).state) {
|
||||
// case ChangeNowExchange.exchangeName:
|
||||
// allPairs = ref.read(availableChangeNowCurrenciesProvider).pairs;
|
||||
// break;
|
||||
// case SimpleSwapExchange.exchangeName:
|
||||
// allPairs = ref.read(exchangeFormStateProvider).exchangeType ==
|
||||
// ExchangeRateType.fixed
|
||||
// ? ref.read(availableSimpleswapCurrenciesProvider).fixedRatePairs
|
||||
// : ref.read(availableSimpleswapCurrenciesProvider).floatingRatePairs;
|
||||
// break;
|
||||
default:
|
||||
allPairs = [];
|
||||
}
|
||||
|
||||
List<Pair> availablePairs;
|
||||
if (fromTicker.isEmpty ||
|
||||
fromTicker == "-" ||
|
||||
excludedTicker.isEmpty ||
|
||||
excludedTicker == "-") {
|
||||
availablePairs = allPairs;
|
||||
} else if (excludedTicker == fromTicker) {
|
||||
availablePairs = allPairs
|
||||
.where((e) => e.from == excludedTicker)
|
||||
.toList(growable: false);
|
||||
} else {
|
||||
availablePairs =
|
||||
allPairs.where((e) => e.to == excludedTicker).toList(growable: false);
|
||||
}
|
||||
|
||||
final List<Crypto> tickers = coins.where((e) {
|
||||
if (excludedTicker == fromTicker) {
|
||||
return e.ticker != excludedTicker &&
|
||||
availablePairs.where((e2) => e2.to == e.ticker).isNotEmpty;
|
||||
} else {
|
||||
return e.ticker != excludedTicker &&
|
||||
availablePairs.where((e2) => e2.from == e.ticker).isNotEmpty;
|
||||
}
|
||||
}).toList(growable: false);
|
||||
|
||||
final result = isDesktop
|
||||
? await showDialog<Crypto?>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DesktopDialog(
|
||||
maxHeight: 700,
|
||||
maxWidth: 580,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 32,
|
||||
),
|
||||
child: Text(
|
||||
"Choose a coin to exchange",
|
||||
style: STextStyles.desktopH3(context),
|
||||
),
|
||||
),
|
||||
const DesktopDialogCloseButton(),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 32,
|
||||
right: 32,
|
||||
bottom: 32,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: RoundedWhiteContainer(
|
||||
padding: const EdgeInsets.all(16),
|
||||
borderColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
child: CryptoSelectionView(
|
||||
coins: tickers,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
})
|
||||
: await Navigator.of(context).push(
|
||||
MaterialPageRoute<dynamic>(
|
||||
builder: (_) => CryptoSelectionView(
|
||||
coins: tickers,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (mounted && result is Crypto) {
|
||||
onSelected(result);
|
||||
}
|
||||
}
|
||||
|
||||
String? _fetchIconUrlFromTicker(String? ticker) {
|
||||
if (ticker == null) return null;
|
||||
|
||||
// Iterable<Crypto> possibleCurrencies;
|
||||
//
|
||||
// switch (ref.read(currentExchangeNameStateProvider.state).state) {
|
||||
// case ChangeNowExchange.exchangeName:
|
||||
// possibleCurrencies = ref
|
||||
// .read(availableChangeNowCurrenciesProvider)
|
||||
// .coins
|
||||
// .where((e) => e.ticker.toUpperCase() == ticker.toUpperCase());
|
||||
// break;
|
||||
// default:
|
||||
// possibleCurrencies = [];
|
||||
// }
|
||||
//
|
||||
// for (final Crypto in possibleCurrencies) {
|
||||
// if (Crypto.image.isNotEmpty) {
|
||||
// return Crypto.image;
|
||||
// }
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
bool isWalletCoin(Coin? coin, bool isSend) {
|
||||
if (coin == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String? ticker;
|
||||
|
||||
if (isSend) {
|
||||
ticker = ref.read(buyFormStateProvider).fromTicker;
|
||||
} else {
|
||||
ticker = ref.read(buyFormStateProvider).toTicker;
|
||||
}
|
||||
|
||||
if (ticker == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return coin.ticker.toUpperCase() == ticker.toUpperCase();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_fiatController = TextEditingController();
|
||||
|
@ -106,20 +347,30 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
SizedBox(
|
||||
height: isDesktop ? 10 : 4,
|
||||
),
|
||||
SizedBox(
|
||||
height: isDesktop ? 10 : 4,
|
||||
BuyTextField(
|
||||
controller: _cryptoController,
|
||||
focusNode: _cryptoFocusNode,
|
||||
textStyle: 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 (_cryptoController.text == "-") {
|
||||
_cryptoController.text = "";
|
||||
}
|
||||
},
|
||||
onChanged: cryptoFieldOnChanged,
|
||||
onButtonTap: selectCryptoCrypto,
|
||||
isWalletCoin: isWalletCoin(coin, true),
|
||||
image: _fetchIconUrlFromTicker(ref
|
||||
.watch(buyFormStateProvider.select((value) => value.fromTicker))),
|
||||
ticker: ref
|
||||
.watch(buyFormStateProvider.select((value) => value.fromTicker)),
|
||||
),
|
||||
SizedBox(
|
||||
height: isDesktop ? 10 : 4,
|
||||
),
|
||||
// if (ref
|
||||
// .watch(buyFormStateProvider.select((value) => value.warning))
|
||||
// .isNotEmpty &&
|
||||
// !ref.watch(buyFormStateProvider.select((value) => value.reversed)))
|
||||
// Text(
|
||||
// ref.watch(buyFormStateProvider.select((value) => value.warning)),
|
||||
// style: STextStyles.errorSmall(context),
|
||||
// ),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
@ -132,58 +383,9 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
),
|
||||
],
|
||||
),
|
||||
// SizedBox(
|
||||
// height: isDesktop ? 10 : 7,
|
||||
// ),
|
||||
// ExchangeTextField(
|
||||
// focusNode: _receiveFocusNode,
|
||||
// controller: _receiveController,
|
||||
// textStyle: 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 (!(ref.read(prefsChangeNotifierProvider).exchangeRateType ==
|
||||
// ExchangeRateType.estimated) &&
|
||||
// _receiveController.text == "-") {
|
||||
// _receiveController.text = "";
|
||||
// }
|
||||
// },
|
||||
// onChanged: receiveFieldOnChanged,
|
||||
// onButtonTap: selectReceiveCurrency,
|
||||
// isWalletCoin: isWalletCoin(coin, true),
|
||||
// image: _fetchIconUrlFromTicker(ref.watch(
|
||||
// buyFormStateProvider.select((value) => value.toTicker))),
|
||||
// ticker: ref.watch(
|
||||
// buyFormStateProvider.select((value) => value.toTicker)),
|
||||
// readOnly: ref.watch(prefsChangeNotifierProvider
|
||||
// .select((value) => value.exchangeRateType)) ==
|
||||
// ExchangeRateType.estimated,
|
||||
// // ||
|
||||
// // ref.watch(exchangeProvider).name ==
|
||||
// // SimpleSwapExchange.exchangeName,
|
||||
// ),
|
||||
// if (ref
|
||||
// .watch(buyFormStateProvider.select((value) => value.warning))
|
||||
// .isNotEmpty &&
|
||||
// ref.watch(buyFormStateProvider.select((value) => value.reversed)))
|
||||
// Text(
|
||||
// ref.watch(buyFormStateProvider.select((value) => value.warning)),
|
||||
// style: STextStyles.errorSmall(context),
|
||||
// ),
|
||||
SizedBox(
|
||||
height: isDesktop ? 20 : 12,
|
||||
height: isDesktop ? 10 : 4,
|
||||
),
|
||||
// SizedBox(
|
||||
// height: 60,
|
||||
// child: RateTypeToggle(
|
||||
// onChanged: onRateTypeChanged,
|
||||
// ),
|
||||
// ),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
@ -194,13 +396,14 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
color: Theme.of(context).extension<StackColors>()!.textDark3,
|
||||
),
|
||||
),
|
||||
const FiatCryptoToggle(),
|
||||
],
|
||||
),
|
||||
// // these reads should be watch
|
||||
// if (ref.watch(buyFormStateProvider).fromAmount != null &&
|
||||
// ref.watch(buyFormStateProvider).fromAmount != Decimal.zero)
|
||||
SizedBox(
|
||||
height: isDesktop ? 20 : 12,
|
||||
height: isDesktop ? 10 : 4,
|
||||
),
|
||||
BuyTextField(
|
||||
controller: _fiatController,
|
||||
|
@ -219,7 +422,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
}
|
||||
},
|
||||
onChanged: fiatFieldOnChanged,
|
||||
onButtonTap: selectFiatCurrency,
|
||||
onButtonTap: selectFiatCrypto,
|
||||
// isWalletCoin: isWalletCoin(coin, true),
|
||||
isWalletCoin: false,
|
||||
// image: _fetchIconUrlFromTicker(ref
|
||||
|
|
58
lib/pages/buy_view/sub_widgets/fiat_crypto_toggle.dart
Normal file
58
lib/pages/buy_view/sub_widgets/fiat_crypto_toggle.dart
Normal file
|
@ -0,0 +1,58 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||
|
||||
class FiatCryptoToggle extends ConsumerWidget {
|
||||
const FiatCryptoToggle({
|
||||
Key? key,
|
||||
// this.onChanged,
|
||||
}) : super(key: key);
|
||||
|
||||
// final void Function(ExchangeRateType)? onChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
final isDesktop = Util.isDesktop;
|
||||
|
||||
// final estimated = ref.watch(prefsChangeNotifierProvider
|
||||
// .select((value) => value.exchangeRateType)) ==
|
||||
// ExchangeRateType.estimated;
|
||||
|
||||
// return Toggle(
|
||||
// onValueChanged: (value) {
|
||||
// // if (!estimated) {
|
||||
// // ref.read(prefsChangeNotifierProvider).exchangeRateType =
|
||||
// // ExchangeRateType.estimated;
|
||||
// // onChanged?.call(ExchangeRateType.estimated);
|
||||
// // } else {
|
||||
// // onChanged?.call(ExchangeRateType.fixed);
|
||||
// // }
|
||||
// },
|
||||
// isOn: true,
|
||||
// onColor: Theme.of(context).extension<StackColors>()!.textFieldDefaultBG,
|
||||
// offColor: isDesktop
|
||||
// ? Theme.of(context).extension<StackColors>()!.buttonBackSecondary
|
||||
// : Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(
|
||||
// Constants.size.circularBorderRadius,
|
||||
// ),
|
||||
// ),
|
||||
// onIcon: Assets.svg.lockOpen,
|
||||
// onText: "Estimate rate",
|
||||
// offIcon: Assets.svg.lock,
|
||||
// offText: "Fixed rate",
|
||||
// );
|
||||
return BlueTextButton(
|
||||
text: "Use crypto amount",
|
||||
textSize: 14,
|
||||
onTap: () {
|
||||
// Navigator.of(context).pushNamed(
|
||||
// ForgotPasswordDesktopView.routeName,
|
||||
// );
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
// import 'package:stackwallet/pages/buy_view/buy_form.dart';
|
||||
// import 'package:stackwallet/pages_desktop_specific/desktop_buy/subwidgets/desktop_buy_history.dart';
|
||||
import 'package:stackwallet/pages/buy_view/buy_form.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class DesktopBuyView extends StatefulWidget {
|
||||
const DesktopBuyView({Key? key}) : super(key: key);
|
||||
|
@ -25,7 +25,7 @@ class _DesktopBuyViewState extends State<DesktopBuyView> {
|
|||
left: 24,
|
||||
),
|
||||
child: Text(
|
||||
"Buy",
|
||||
"Buy crypto",
|
||||
style: STextStyles.desktopH3(context),
|
||||
),
|
||||
),
|
||||
|
@ -44,17 +44,17 @@ class _DesktopBuyViewState extends State<DesktopBuyView> {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Coming soon",
|
||||
style: STextStyles.desktopTextExtraExtraSmall(context),
|
||||
),
|
||||
// Text(
|
||||
// "Coming soon",
|
||||
// style: STextStyles.desktopTextExtraExtraSmall(context),
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
// const RoundedWhiteContainer(
|
||||
// padding: EdgeInsets.all(24),
|
||||
// child: BuyForm(),
|
||||
// ),
|
||||
const RoundedWhiteContainer(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: BuyForm(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue