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 boxNameDBInfo = "dbInfo";
|
||||||
static const String boxNameTheme = "theme";
|
static const String boxNameTheme = "theme";
|
||||||
static const String boxNameDesktopData = "desktopData";
|
static const String boxNameDesktopData = "desktopData";
|
||||||
|
static const String boxNameBuys = "buysBox";
|
||||||
|
|
||||||
String boxNameTxCache({required Coin coin}) => "${coin.name}_txCache";
|
String boxNameTxCache({required Coin coin}) => "${coin.name}_txCache";
|
||||||
String boxNameSetCache({required Coin coin}) =>
|
String boxNameSetCache({required Coin coin}) =>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'buy.g.dart';
|
// part 'buy.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: Buy.typeId)
|
@HiveType(typeId: Buy.typeId)
|
||||||
class Buy {
|
class Buy {
|
||||||
|
@ -10,7 +10,7 @@ class Buy {
|
||||||
final String uuid;
|
final String uuid;
|
||||||
|
|
||||||
@HiveField(1)
|
@HiveField(1)
|
||||||
final String tradeId;
|
final String buyId;
|
||||||
|
|
||||||
@HiveField(2)
|
@HiveField(2)
|
||||||
final String rateType;
|
final String rateType;
|
||||||
|
@ -74,7 +74,7 @@ class Buy {
|
||||||
|
|
||||||
const Buy({
|
const Buy({
|
||||||
required this.uuid,
|
required this.uuid,
|
||||||
required this.tradeId,
|
required this.buyId,
|
||||||
required this.rateType,
|
required this.rateType,
|
||||||
required this.direction,
|
required this.direction,
|
||||||
required this.timestamp,
|
required this.timestamp,
|
||||||
|
@ -97,8 +97,8 @@ class Buy {
|
||||||
required this.exchangeName,
|
required this.exchangeName,
|
||||||
});
|
});
|
||||||
|
|
||||||
Trade copyWith({
|
Buy copyWith({
|
||||||
String? tradeId,
|
String? buyId,
|
||||||
String? rateType,
|
String? rateType,
|
||||||
String? direction,
|
String? direction,
|
||||||
DateTime? timestamp,
|
DateTime? timestamp,
|
||||||
|
@ -122,7 +122,7 @@ class Buy {
|
||||||
}) {
|
}) {
|
||||||
return Buy(
|
return Buy(
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
tradeId: tradeId ?? this.tradeId,
|
buyId: buyId ?? this.buyId,
|
||||||
rateType: rateType ?? this.rateType,
|
rateType: rateType ?? this.rateType,
|
||||||
direction: direction ?? this.direction,
|
direction: direction ?? this.direction,
|
||||||
timestamp: timestamp ?? this.timestamp,
|
timestamp: timestamp ?? this.timestamp,
|
||||||
|
@ -149,7 +149,7 @@ class Buy {
|
||||||
Map<String, String> toMap() {
|
Map<String, String> toMap() {
|
||||||
return {
|
return {
|
||||||
"uuid": uuid,
|
"uuid": uuid,
|
||||||
"tradeId": tradeId,
|
"buyId": buyId,
|
||||||
"rateType": rateType,
|
"rateType": rateType,
|
||||||
"direction": direction,
|
"direction": direction,
|
||||||
"timestamp": timestamp.toIso8601String(),
|
"timestamp": timestamp.toIso8601String(),
|
||||||
|
@ -176,7 +176,7 @@ class Buy {
|
||||||
factory Buy.fromMap(Map<String, dynamic> map) {
|
factory Buy.fromMap(Map<String, dynamic> map) {
|
||||||
return Buy(
|
return Buy(
|
||||||
uuid: map["uuid"] as String,
|
uuid: map["uuid"] as String,
|
||||||
tradeId: map["tradeId"] as String,
|
buyId: map["buyId"] as String,
|
||||||
rateType: map["rateType"] as String,
|
rateType: map["rateType"] as String,
|
||||||
direction: map["direction"] as String,
|
direction: map["direction"] as String,
|
||||||
timestamp: DateTime.parse(map["timestamp"] 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
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return toMap().toString();
|
return toMap().toString();
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
import 'package:decimal/decimal.dart';
|
import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/providers/buy/buy_form_state_provider.dart';
|
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
import 'package:stackwallet/utilities/util.dart';
|
import 'package:stackwallet/utilities/util.dart';
|
||||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
import 'package:stackwallet/widgets/textfields/buy_textfield.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
|
||||||
|
|
||||||
class BuyForm extends ConsumerStatefulWidget {
|
class BuyForm extends ConsumerStatefulWidget {
|
||||||
const BuyForm({
|
const BuyForm({
|
||||||
|
@ -30,7 +27,62 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
||||||
late final String? walletId;
|
late final String? walletId;
|
||||||
late final Coin? coin;
|
late final Coin? coin;
|
||||||
|
|
||||||
|
late final TextEditingController _fiatController;
|
||||||
|
late final TextEditingController _cryptoController;
|
||||||
final isDesktop = Util.isDesktop;
|
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
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
@ -46,7 +98,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"You will send",
|
"I want to buy",
|
||||||
style: STextStyles.itemSubtitle(context).copyWith(
|
style: STextStyles.itemSubtitle(context).copyWith(
|
||||||
color: Theme.of(context).extension<StackColors>()!.textDark3,
|
color: Theme.of(context).extension<StackColors>()!.textDark3,
|
||||||
),
|
),
|
||||||
|
@ -54,30 +106,6 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: isDesktop ? 10 : 4,
|
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(
|
SizedBox(
|
||||||
height: isDesktop ? 10 : 4,
|
height: isDesktop ? 10 : 4,
|
||||||
),
|
),
|
||||||
|
@ -97,48 +125,16 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"You will receive",
|
"I want to pay with",
|
||||||
style: STextStyles.itemSubtitle(context).copyWith(
|
style: STextStyles.itemSubtitle(context).copyWith(
|
||||||
color: Theme.of(context).extension<StackColors>()!.textDark3,
|
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(
|
// SizedBox(
|
||||||
height: isDesktop ? 10 : 7,
|
// height: isDesktop ? 10 : 7,
|
||||||
),
|
// ),
|
||||||
// ExchangeTextField(
|
// ExchangeTextField(
|
||||||
// focusNode: _receiveFocusNode,
|
// focusNode: _receiveFocusNode,
|
||||||
// controller: _receiveController,
|
// controller: _receiveController,
|
||||||
|
@ -188,39 +184,64 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
||||||
// onChanged: onRateTypeChanged,
|
// onChanged: onRateTypeChanged,
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// these reads should be watch
|
Row(
|
||||||
if (ref.watch(buyFormStateProvider).fromAmount != null &&
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
ref.watch(buyFormStateProvider).fromAmount != Decimal.zero)
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
SizedBox(
|
children: [
|
||||||
height: isDesktop ? 20 : 12,
|
Text(
|
||||||
),
|
"Enter amount",
|
||||||
// these reads should be watch
|
style: STextStyles.itemSubtitle(context).copyWith(
|
||||||
|
color: Theme.of(context).extension<StackColors>()!.textDark3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// // these reads should be watch
|
||||||
// if (ref.watch(buyFormStateProvider).fromAmount != null &&
|
// if (ref.watch(buyFormStateProvider).fromAmount != null &&
|
||||||
// ref.watch(buyFormStateProvider).fromAmount != Decimal.zero)
|
// 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(
|
SizedBox(
|
||||||
height: isDesktop ? 20 : 12,
|
height: isDesktop ? 20 : 12,
|
||||||
),
|
),
|
||||||
// PrimaryButton(
|
BuyTextField(
|
||||||
// buttonHeight: isDesktop ? ButtonHeight.l : null,
|
controller: _fiatController,
|
||||||
// enabled: ref
|
focusNode: _fiatFocusNode,
|
||||||
// .watch(buyFormStateProvider.select((value) => value.canExchange)),
|
textStyle: STextStyles.smallMed14(context).copyWith(
|
||||||
// // onPressed: ref.watch(buyFormStateProvider
|
color: Theme.of(context).extension<StackColors>()!.textDark,
|
||||||
// // .select((value) => value.canExchange))
|
),
|
||||||
// // ? onExchangePressed
|
buttonColor:
|
||||||
// // : null,
|
Theme.of(context).extension<StackColors>()!.buttonBackSecondary,
|
||||||
// label: "Exchange",
|
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:flutter/material.dart';
|
||||||
import 'package:stackwallet/pages/buy_view/buy_form.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 {
|
class BuyView extends StatefulWidget {
|
||||||
const BuyView({Key? key}) : super(key: key);
|
const BuyView({Key? key}) : super(key: key);
|
||||||
|
@ -18,155 +15,13 @@ class _BuyViewState extends State<BuyView> {
|
||||||
// debugPrint("BUILD: BuyView");
|
// debugPrint("BUILD: BuyView");
|
||||||
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: NestedScrollView(
|
child: Padding(
|
||||||
floatHeaderSlivers: true,
|
padding: EdgeInsets.only(
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
left: 16,
|
||||||
return [
|
right: 16,
|
||||||
SliverOverlapAbsorber(
|
top: 16,
|
||||||
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: BuyForm(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,7 @@ class WalletNavigationBar extends StatelessWidget {
|
||||||
height: 4,
|
height: 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"Buy2",
|
"Buy",
|
||||||
style: STextStyles.buttonSmall(context),
|
style: STextStyles.buttonSmall(context),
|
||||||
),
|
),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
export './buy/buy_form_state_provider.dart';
|
||||||
export './exchange/available_changenow_currencies_provider.dart';
|
export './exchange/available_changenow_currencies_provider.dart';
|
||||||
export './exchange/available_simpleswap_currencies_provider.dart';
|
export './exchange/available_simpleswap_currencies_provider.dart';
|
||||||
export './exchange/changenow_initial_load_status.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/exchange_send_from_wallet_id_provider.dart';
|
||||||
export './exchange/trade_note_service_provider.dart';
|
export './exchange/trade_note_service_provider.dart';
|
||||||
export './exchange/trade_sent_from_stack_lookup_provider.dart';
|
export './exchange/trade_sent_from_stack_lookup_provider.dart';
|
||||||
|
export './global/buys_service_provider.dart';
|
||||||
export './global/favorites_provider.dart';
|
export './global/favorites_provider.dart';
|
||||||
export './global/locale_provider.dart';
|
export './global/locale_provider.dart';
|
||||||
export './global/node_service_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;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
Buy? get(String BuyId) {
|
Buy? get(String buyId) {
|
||||||
try {
|
try {
|
||||||
return DB.instance
|
return DB.instance
|
||||||
.values<Buy>(boxName: DB.boxNameBuys)
|
.values<Buy>(boxName: DB.boxNameBuys)
|
||||||
.firstWhere((e) => e.BuyId == BuyId);
|
.firstWhere((e) => e.buyId == buyId);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> add({
|
Future<void> add({
|
||||||
required Buy Buy,
|
required Buy buy,
|
||||||
required bool shouldNotifyListeners,
|
required bool shouldNotifyListeners,
|
||||||
}) async {
|
}) async {
|
||||||
await DB.instance
|
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) {
|
if (shouldNotifyListeners) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -34,23 +34,23 @@ class BuysService extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> edit({
|
Future<void> edit({
|
||||||
required Buy Buy,
|
required Buy buy,
|
||||||
required bool shouldNotifyListeners,
|
required bool shouldNotifyListeners,
|
||||||
}) async {
|
}) 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!");
|
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
|
// 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({
|
Future<void> delete({
|
||||||
required Buy Buy,
|
required Buy buy,
|
||||||
required bool shouldNotifyListeners,
|
required bool shouldNotifyListeners,
|
||||||
}) async {
|
}) async {
|
||||||
await deleteByUuid(
|
await deleteByUuid(
|
||||||
uuid: Buy.uuid, shouldNotifyListeners: shouldNotifyListeners);
|
uuid: buy.uuid, shouldNotifyListeners: shouldNotifyListeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteByUuid({
|
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