23-1-10 updates

nonatomic updates
This commit is contained in:
sneurlax 2023-01-11 09:54:39 -06:00
parent 290adfec21
commit c746eb8865
9 changed files with 410 additions and 295 deletions

View file

@ -33,6 +33,7 @@ class DB {
static const String boxNameDBInfo = "dbInfo";
static const String boxNameTheme = "theme";
static const String boxNameDesktopData = "desktopData";
static const String boxNameBuys = "buysBox";
String boxNameTxCache({required Coin coin}) => "${coin.name}_txCache";
String boxNameSetCache({required Coin coin}) =>

View file

@ -1,6 +1,6 @@
import 'package:hive/hive.dart';
part 'buy.g.dart';
// part 'buy.g.dart';
@HiveType(typeId: Buy.typeId)
class Buy {
@ -10,7 +10,7 @@ class Buy {
final String uuid;
@HiveField(1)
final String tradeId;
final String buyId;
@HiveField(2)
final String rateType;
@ -74,7 +74,7 @@ class Buy {
const Buy({
required this.uuid,
required this.tradeId,
required this.buyId,
required this.rateType,
required this.direction,
required this.timestamp,
@ -97,8 +97,8 @@ class Buy {
required this.exchangeName,
});
Trade copyWith({
String? tradeId,
Buy copyWith({
String? buyId,
String? rateType,
String? direction,
DateTime? timestamp,
@ -122,7 +122,7 @@ class Buy {
}) {
return Buy(
uuid: uuid,
tradeId: tradeId ?? this.tradeId,
buyId: buyId ?? this.buyId,
rateType: rateType ?? this.rateType,
direction: direction ?? this.direction,
timestamp: timestamp ?? this.timestamp,
@ -149,7 +149,7 @@ class Buy {
Map<String, String> toMap() {
return {
"uuid": uuid,
"tradeId": tradeId,
"buyId": buyId,
"rateType": rateType,
"direction": direction,
"timestamp": timestamp.toIso8601String(),
@ -176,7 +176,7 @@ class Buy {
factory Buy.fromMap(Map<String, dynamic> map) {
return Buy(
uuid: map["uuid"] as String,
tradeId: map["tradeId"] as String,
buyId: map["buyId"] as String,
rateType: map["rateType"] as String,
direction: map["direction"] as String,
timestamp: DateTime.parse(map["timestamp"] as String),
@ -200,36 +200,6 @@ class Buy {
);
}
// factory Trade.fromExchangeTransaction(
// ExchangeTransaction exTx, bool reversed) {
// return Buy(
// uuid: exTx.uuid,
// tradeId: exTx.id,
// rateType: "",
// direction: reversed ? "reverse" : "direct",
// timestamp: exTx.date,
// updatedAt: DateTime.tryParse(exTx.statusObject!.updatedAt) ?? exTx.date,
// payInCurrency: exTx.fromCurrency,
// payInAmount: exTx.statusObject!.amountSendDecimal.isEmpty
// ? exTx.statusObject!.expectedSendAmountDecimal
// : exTx.statusObject!.amountSendDecimal,
// payInAddress: exTx.payinAddress,
// payInNetwork: "",
// payInExtraId: exTx.payinExtraId,
// payInTxid: exTx.statusObject!.payinHash,
// payOutCurrency: exTx.toCurrency,
// payOutAmount: exTx.amount,
// payOutAddress: exTx.payoutAddress,
// payOutNetwork: "",
// payOutExtraId: exTx.payoutExtraId,
// payOutTxid: exTx.statusObject!.payoutHash,
// refundAddress: exTx.refundAddress,
// refundExtraId: exTx.refundExtraId,
// status: exTx.statusObject!.status.name,
// exchangeName: ChangeNowExchange.exchangeName,
// );
// }
@override
String toString() {
return toMap().toString();

View file

@ -1,16 +1,13 @@
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/buy/buy_form_state_provider.dart';
import 'package:stackwallet/utilities/assets.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/conditional_parent.dart';
import 'package:stackwallet/widgets/rounded_container.dart';
import 'package:stackwallet/widgets/textfields/buy_textfield.dart';
class BuyForm extends ConsumerStatefulWidget {
const BuyForm({
@ -30,7 +27,62 @@ class _BuyFormState extends ConsumerState<BuyForm> {
late final String? walletId;
late final Coin? coin;
late final TextEditingController _fiatController;
late final TextEditingController _cryptoController;
final isDesktop = Util.isDesktop;
final FocusNode _fiatFocusNode = FocusNode();
final FocusNode _cryptoFocusNode = FocusNode();
void fiatFieldOnChanged(String value) async {
if (_fiatFocusNode.hasFocus) {
final newFromAmount = Decimal.tryParse(value);
await ref.read(buyFormStateProvider).setFromAmountAndCalculateToAmount(
newFromAmount ?? Decimal.zero, true);
if (newFromAmount == null) {
// _cryptoController.text =
// ref.read(prefsChangeNotifierProvider).exchangeRateType ==
// ExchangeRateType.estimated
// ? "-"
// : "";
}
}
}
void selectFiatCurrency() async {
// await Future<void>.delayed(const Duration(milliseconds: 300));
//
// Navigator.of(context, rootNavigator: true).pop();
}
@override
void initState() {
_fiatController = TextEditingController();
_cryptoController = TextEditingController();
walletId = widget.walletId;
coin = widget.coin;
// walletInitiated = walletId != null && coin != null;
//
// if (walletInitiated) {
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// ref.read(buyFormStateProvider).clearAmounts(true);
// // ref.read(fixedRateExchangeFormProvider);
// });
// } else {
// final isEstimated =
// ref.read(prefsChangeNotifierProvider).exchangeRateType ==
// ExchangeRateType.estimated;
_fiatController.text = ref.read(buyFormStateProvider).fromAmountString;
_cryptoController
.text = /*isEstimated
? "-" //ref.read(estimatedRateExchangeFormProvider).toAmountString
:*/
ref.read(buyFormStateProvider).toAmountString;
// }
super.initState();
}
@override
void dispose() {
@ -46,7 +98,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"You will send",
"I want to buy",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
@ -54,30 +106,6 @@ class _BuyFormState extends ConsumerState<BuyForm> {
SizedBox(
height: isDesktop ? 10 : 4,
),
// ExchangeTextField(
// controller: _sendController,
// focusNode: _sendFocusNode,
// 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 (_sendController.text == "-") {
// _sendController.text = "";
// }
// },
// onChanged: sendFieldOnChanged,
// onButtonTap: selectSendCurrency,
// 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,
),
@ -97,48 +125,16 @@ class _BuyFormState extends ConsumerState<BuyForm> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"You will receive",
"I want to pay with",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
),
ConditionalParent(
condition: isDesktop,
builder: (child) => MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
),
child: RoundedContainer(
padding: isDesktop
? const EdgeInsets.all(6)
: const EdgeInsets.all(2),
color: Theme.of(context)
.extension<StackColors>()!
.buttonBackSecondary,
radiusMultiplier: 0.75,
child: GestureDetector(
// onTap: () async {
// await _swap();
// },
child: Padding(
padding: const EdgeInsets.all(4),
child: SvgPicture.asset(
Assets.svg.swap,
width: 20,
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
),
),
),
],
),
SizedBox(
height: isDesktop ? 10 : 7,
),
// SizedBox(
// height: isDesktop ? 10 : 7,
// ),
// ExchangeTextField(
// focusNode: _receiveFocusNode,
// controller: _receiveController,
@ -188,39 +184,64 @@ class _BuyFormState extends ConsumerState<BuyForm> {
// onChanged: onRateTypeChanged,
// ),
// ),
// these reads should be watch
if (ref.watch(buyFormStateProvider).fromAmount != null &&
ref.watch(buyFormStateProvider).fromAmount != Decimal.zero)
SizedBox(
height: isDesktop ? 20 : 12,
),
// these reads should be watch
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Enter amount",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
),
],
),
// // these reads should be watch
// if (ref.watch(buyFormStateProvider).fromAmount != null &&
// ref.watch(buyFormStateProvider).fromAmount != Decimal.zero)
// ExchangeProviderOptions(
// from: ref.watch(buyFormStateProvider).fromTicker,
// to: ref.watch(buyFormStateProvider).toTicker,
// fromAmount: ref.watch(buyFormStateProvider).fromAmount,
// toAmount: ref.watch(buyFormStateProvider).toAmount,
// fixedRate: ref.watch(prefsChangeNotifierProvider
// .select((value) => value.exchangeRateType)) ==
// ExchangeRateType.fixed,
// reversed: ref
// .watch(buyFormStateProvider.select((value) => value.reversed)),
// ),
SizedBox(
height: isDesktop ? 20 : 12,
),
// PrimaryButton(
// buttonHeight: isDesktop ? ButtonHeight.l : null,
// enabled: ref
// .watch(buyFormStateProvider.select((value) => value.canExchange)),
// // onPressed: ref.watch(buyFormStateProvider
// // .select((value) => value.canExchange))
// // ? onExchangePressed
// // : null,
// label: "Exchange",
// )
BuyTextField(
controller: _fiatController,
focusNode: _fiatFocusNode,
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 (_fiatController.text == "-") {
_fiatController.text = "";
}
},
onChanged: fiatFieldOnChanged,
onButtonTap: selectFiatCurrency,
// isWalletCoin: isWalletCoin(coin, true),
isWalletCoin: false,
// image: _fetchIconUrlFromTicker(ref
// .watch(buyFormStateProvider.select((value) => value.fromTicker))),
// ticker: ref
// .watch(buyFormStateProvider.select((value) => value.fromTicker)),
),
SizedBox(
height: isDesktop ? 20 : 12,
),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Enter receiving address",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
),
],
),
],
);
}

View file

@ -1,8 +1,5 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/pages/buy_view/buy_form.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
class BuyView extends StatefulWidget {
const BuyView({Key? key}) : super(key: key);
@ -18,155 +15,13 @@ class _BuyViewState extends State<BuyView> {
// debugPrint("BUILD: BuyView");
return SafeArea(
child: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: const SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.only(
left: 16,
right: 16,
top: 16,
),
child: BuyForm(),
),
),
)
];
},
body: Builder(
builder: (buildContext) {
// final buys =
// ref.watch(buysServiceProvider.select((value) => value.buys));
// final buyCount = buys.length;
// final hasHistory = buyCount > 0;
const hasHistory = false;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: CustomScrollView(
slivers: [
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
buildContext,
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 12,
),
Text(
"Trades",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
const SizedBox(
height: 12,
),
],
),
),
),
// if (hasHistory)
// SliverList(
// delegate: SliverChildBuilderDelegate((context, index) {
// return Padding(
// padding: const EdgeInsets.all(4),
// child: TradeCard(
// key: Key("tradeCard_${trades[index].uuid}"),
// trade: trades[index],
// onTap: () async {
// final String tradeId = trades[index].tradeId;
//
// final lookup = ref
// .read(tradeSentFromStackLookupProvider)
// .all;
//
// //todo: check if print needed
// // debugPrint("ALL: $lookup");
//
// final String? txid = ref
// .read(tradeSentFromStackLookupProvider)
// .getTxidForTradeId(tradeId);
// final List<String>? walletIds = ref
// .read(tradeSentFromStackLookupProvider)
// .getWalletIdsForTradeId(tradeId);
//
// if (txid != null &&
// walletIds != null &&
// walletIds.isNotEmpty) {
// final manager = ref
// .read(walletsChangeNotifierProvider)
// .getManager(walletIds.first);
//
// //todo: check if print needed
// // debugPrint("name: ${manager.walletName}");
//
// // TODO store tx data completely locally in isar so we don't lock up ui here when querying txData
// final txData = await manager.transactionData;
//
// final tx = txData.getAllTransactions()[txid];
//
// if (mounted) {
// unawaited(Navigator.of(context).pushNamed(
// TradeDetailsView.routeName,
// arguments: Tuple4(tradeId, tx,
// walletIds.first, manager.walletName),
// ));
// }
// } else {
// unawaited(Navigator.of(context).pushNamed(
// TradeDetailsView.routeName,
// arguments: Tuple4(
// tradeId, null, walletIds?.first, null),
// ));
// }
// },
// ),
// );
// }, childCount: tradeCount),
// ),
if (!hasHistory)
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
"Trades will appear here",
textAlign: TextAlign.center,
style: STextStyles.itemSubtitle(context),
),
),
),
),
),
],
),
);
},
),
child: Padding(
padding: EdgeInsets.only(
left: 16,
right: 16,
top: 16,
),
);
child: BuyForm(),
));
}
}

View file

@ -222,7 +222,7 @@ class WalletNavigationBar extends StatelessWidget {
height: 4,
),
Text(
"Buy2",
"Buy",
style: STextStyles.buttonSmall(context),
),
Spacer(),

View file

@ -1,3 +1,4 @@
export './buy/buy_form_state_provider.dart';
export './exchange/available_changenow_currencies_provider.dart';
export './exchange/available_simpleswap_currencies_provider.dart';
export './exchange/changenow_initial_load_status.dart';
@ -8,6 +9,7 @@ export './exchange/exchange_provider.dart';
export './exchange/exchange_send_from_wallet_id_provider.dart';
export './exchange/trade_note_service_provider.dart';
export './exchange/trade_sent_from_stack_lookup_provider.dart';
export './global/buys_service_provider.dart';
export './global/favorites_provider.dart';
export './global/locale_provider.dart';
export './global/node_service_provider.dart';

View file

@ -0,0 +1,24 @@
enum ExchangeExceptionType { generic, serializeResponseError }
class ExchangeException implements Exception {
String errorMessage;
ExchangeExceptionType type;
ExchangeException(this.errorMessage, this.type);
@override
String toString() {
return errorMessage;
}
}
class ExchangeResponse<T> {
late final T? value;
late final ExchangeException? exception;
ExchangeResponse({this.value, this.exception});
@override
String toString() {
return "{error: $exception, value: $value}";
}
}

View file

@ -11,22 +11,22 @@ class BuysService extends ChangeNotifier {
return list;
}
Buy? get(String BuyId) {
Buy? get(String buyId) {
try {
return DB.instance
.values<Buy>(boxName: DB.boxNameBuys)
.firstWhere((e) => e.BuyId == BuyId);
.firstWhere((e) => e.buyId == buyId);
} catch (_) {
return null;
}
}
Future<void> add({
required Buy Buy,
required Buy buy,
required bool shouldNotifyListeners,
}) async {
await DB.instance
.put<Buy>(boxName: DB.boxNameBuys, key: Buy.uuid, value: Buy);
.put<Buy>(boxName: DB.boxNameBuys, key: buy.uuid, value: buy);
if (shouldNotifyListeners) {
notifyListeners();
@ -34,23 +34,23 @@ class BuysService extends ChangeNotifier {
}
Future<void> edit({
required Buy Buy,
required Buy buy,
required bool shouldNotifyListeners,
}) async {
if (DB.instance.get<Buy>(boxName: DB.boxNameBuys, key: Buy.uuid) == null) {
if (DB.instance.get<Buy>(boxName: DB.boxNameBuys, key: buy.uuid) == null) {
throw Exception("Attempted to edit a Buy that does not exist in Hive!");
}
// add overwrites so this edit function is just a wrapper with an extra check
await add(Buy: Buy, shouldNotifyListeners: shouldNotifyListeners);
await add(buy: buy, shouldNotifyListeners: shouldNotifyListeners);
}
Future<void> delete({
required Buy Buy,
required Buy buy,
required bool shouldNotifyListeners,
}) async {
await deleteByUuid(
uuid: Buy.uuid, shouldNotifyListeners: shouldNotifyListeners);
uuid: buy.uuid, shouldNotifyListeners: shouldNotifyListeners);
}
Future<void> deleteByUuid({

View file

@ -0,0 +1,242 @@
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,
),
],
),
),
),
),
),
],
),
),
);
}
}