mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 03:49:22 +00:00
23-1-10 updates
nonatomic updates
This commit is contained in:
parent
290adfec21
commit
c746eb8865
9 changed files with 410 additions and 295 deletions
|
@ -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}) =>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ class WalletNavigationBar extends StatelessWidget {
|
|||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Buy2",
|
||||
"Buy",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
Spacer(),
|
||||
|
|
|
@ -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';
|
||||
|
|
24
lib/services/buy/buy_response.dart
Normal file
24
lib/services/buy/buy_response.dart
Normal 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}";
|
||||
}
|
||||
}
|
|
@ -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({
|
||||
|
|
242
lib/widgets/textfields/buy_textfield.dart
Normal file
242
lib/widgets/textfields/buy_textfield.dart
Normal 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue