stub pages for mobile and desktop

lots of extra code, lots of commented sections, the models are wrong, the pages just load on desktop and mobile.  need to complete the form and ... well, there's a lot, really
This commit is contained in:
sneurlax 2023-01-10 15:25:20 -06:00
parent 30ea0cc24f
commit 290adfec21
12 changed files with 1318 additions and 60 deletions

View file

@ -0,0 +1,428 @@
import 'package:decimal/decimal.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:stackwallet/services/buy/buy.dart';
class BuyFormState extends ChangeNotifier {
Buy? _buy;
Buy? get buy => _buy;
set buy(Buy? value) {
_buy = value;
_onBuyTypeChanged();
}
// BuyRateType _buyType = BuyRateType.estimated;
// BuyRateType get buyType => _buyType;
// set buyType(BuyRateType value) {
// _buyType = value;
// _onBuyRateTypeChanged();
// }
bool reversed = false;
Decimal? fromAmount;
Decimal? toAmount;
Decimal? minAmount;
Decimal? maxAmount;
Decimal? rate;
// Estimate? estimate;
//
// dynamic? _market;
// dynamic? get market => _market;
//
// dynamic? _from;
// dynamic? _to;
@override
String toString() {
return 'BuyFormState: {test: "test"}';
// return 'BuyFormState: {_buy: $_buy, _buyType: $_buyType, reversed: $reversed, fromAmount: $fromAmount, toAmount: $toAmount, minAmount: $minAmount, maxAmount: $maxAmount, rate: $rate, estimate: $estimate, _market: $_market, _from: $_from, _to: $_to, _onError: $_onError}';
}
String? get fromTicker {
// switch (buyType) {
// case BuyRateType.estimated:
// return _from?.ticker;
// case BuyRateType.fixed:
// switch (buy?.name) {
// // case SimpleSwapBuy.buyName:
// // return _from?.ticker;
// case ChangeNowBuy.buyName:
// return market?.from;
// default:
// return null;
// }
// }
}
String? get toTicker {
// switch (buyType) {
// case BuyRateType.estimated:
// return _to?.ticker;
// case BuyRateType.fixed:
// switch (buy?.name) {
// // case SimpleSwapBuy.buyName:
// // return _to?.ticker;
// case ChangeNowBuy.buyName:
// return market?.to;
// default:
// return null;
// }
// }
}
void Function(String)? _onError;
// dynamic? get from => _from;
// dynamic? get to => _to;
//
// void setCurrencies(dynamic from, dynamic to) {
// _from = from;
// _to = to;
// }
String get warning {
// if (reversed) {
// if (toTicker != null && toAmount != null) {
// if (minAmount != null &&
// toAmount! < minAmount! &&
// toAmount! > Decimal.zero) {
// return "Minimum amount ${minAmount!.toString()} ${toTicker!.toUpperCase()}";
// } else if (maxAmount != null && toAmount! > maxAmount!) {
// return "Maximum amount ${maxAmount!.toString()} ${toTicker!.toUpperCase()}";
// }
// }
// } else {
// if (fromTicker != null && fromAmount != null) {
// if (minAmount != null &&
// fromAmount! < minAmount! &&
// fromAmount! > Decimal.zero) {
// return "Minimum amount ${minAmount!.toString()} ${fromTicker!.toUpperCase()}";
// } else if (maxAmount != null && fromAmount! > maxAmount!) {
// return "Maximum amount ${maxAmount!.toString()} ${fromTicker!.toUpperCase()}";
// }
// }
// }
return "";
}
String get fromAmountString => fromAmount?.toStringAsFixed(8) ?? "";
String get toAmountString => toAmount?.toStringAsFixed(8) ?? "";
bool get canBuy {
// if (buy?.name == ChangeNowBuy.buyName && buyType == BuyRateType.fixed) {
// return _market != null &&
// fromAmount != null &&
// toAmount != null &&
// warning.isEmpty;
// } else {
// return fromAmount != null &&
// fromAmount != Decimal.zero &&
// toAmount != null &&
// rate != null &&
// warning.isEmpty;
// }
return true;
}
void clearAmounts(bool shouldNotifyListeners) {
// fromAmount = null;
// toAmount = null;
// minAmount = null;
// maxAmount = null;
// rate = null;
//
// if (shouldNotifyListeners) {
// notifyListeners();
// }
}
Future<void> setFromAmountAndCalculateToAmount(
Decimal newFromAmount,
bool shouldNotifyListeners,
) async {
// if (newFromAmount == Decimal.zero) {
// toAmount = Decimal.zero;
// }
//
// fromAmount = newFromAmount;
// reversed = false;
//
// await updateRanges(shouldNotifyListeners: false);
//
// await updateEstimate(
// shouldNotifyListeners: false,
// reversed: reversed,
// );
//
// if (shouldNotifyListeners) {
// notifyListeners();
// }
}
Future<void> setToAmountAndCalculateFromAmount(
Decimal newToAmount,
bool shouldNotifyListeners,
) async {
// if (newToAmount == Decimal.zero) {
// fromAmount = Decimal.zero;
// }
//
// toAmount = newToAmount;
// reversed = true;
//
// await updateRanges(shouldNotifyListeners: false);
//
// await updateEstimate(
// shouldNotifyListeners: false,
// reversed: reversed,
// );
//
// if (shouldNotifyListeners) {
// notifyListeners();
// }
}
// Future<void> updateTo(dynamic to, bool shouldNotifyListeners) async {
Future<void> updateTo(dynamic to, bool shouldNotifyListeners) async {
// try {
// _to = to;
// if (_from == null) {
// rate = null;
// notifyListeners();
// return;
// }
//
// await updateRanges(shouldNotifyListeners: false);
//
// await updateEstimate(
// shouldNotifyListeners: false,
// reversed: reversed,
// );
//
// //todo: check if print needed
// // debugPrint(
// // "_updated TO: _from=${_from!.ticker} _to=${_to!.ticker} _fromAmount=$fromAmount _toAmount=$toAmount rate:$rate for: $buy");
//
// if (shouldNotifyListeners) {
// notifyListeners();
// }
// } catch (e, s) {
// Logging.instance.log("$e\n$s", level: LogLevel.Error);
// }
}
// Future<void> updateFrom(dynamic from, bool shouldNotifyListeners) async {
Future<void> updateFrom(dynamic from, bool shouldNotifyListeners) async {
// try {
// _from = from;
//
// if (_to == null) {
// rate = null;
// notifyListeners();
// return;
// }
//
// await updateRanges(shouldNotifyListeners: false);
//
// await updateEstimate(
// shouldNotifyListeners: false,
// reversed: reversed,
// );
//
// //todo: check if print needed
// // debugPrint(
// // "_updated FROM: _from=${_from!.ticker} _to=${_to!.ticker} _fromAmount=$fromAmount _toAmount=$toAmount rate:$rate for: $buy");
// if (shouldNotifyListeners) {
// notifyListeners();
// }
// } catch (e, s) {
// Logging.instance.log("$e\n$s", level: LogLevel.Error);
// }
}
Future<void> updateMarket(
// dynamic? market,
dynamic? market,
bool shouldNotifyListeners,
) async {
// _market = market;
//
// if (_market == null) {
// fromAmount = null;
// toAmount = null;
// } else {
// if (fromAmount != null) {
// if (fromAmount! <= Decimal.zero) {
// toAmount = Decimal.zero;
// } else {
// await updateRanges(shouldNotifyListeners: false);
// await updateEstimate(
// shouldNotifyListeners: false,
// reversed: reversed,
// );
// }
// }
// }
//
// if (shouldNotifyListeners) {
// notifyListeners();
// }
}
void _onBuyRateTypeChanged() {
// print("_onBuyRateTypeChanged");
// updateRanges(shouldNotifyListeners: true).then(
// (_) => updateEstimate(
// shouldNotifyListeners: true,
// reversed: reversed,
// ),
// );
}
void _onBuyTypeChanged() {
// updateRanges(shouldNotifyListeners: true).then(
// (_) => updateEstimate(
// shouldNotifyListeners: true,
// reversed: reversed,
// ),
// );
}
Future<void> updateRanges({required bool shouldNotifyListeners}) async {
// // if (buy?.name == SimpleSwapBuy.buyName) {
// // reversed = false;
// // }
// final _fromTicker = reversed ? toTicker : fromTicker;
// final _toTicker = reversed ? fromTicker : toTicker;
// if (_fromTicker == null || _toTicker == null) {
// Logging.instance.log(
// "Tried to $runtimeType.updateRanges where (from: $_fromTicker || to: $_toTicker) for: $buy",
// level: LogLevel.Info,
// );
// return;
// }
// final response = await buy?.getRange(
// _fromTicker,
// _toTicker,
// buyType == BuyRateType.fixed,
// );
//
// if (response?.value == null) {
// Logging.instance.log(
// "Tried to $runtimeType.updateRanges for: $buy where response: $response",
// level: LogLevel.Info,
// );
// return;
// }
//
// final range = response!.value!;
//
// minAmount = range.min;
// maxAmount = range.max;
//
// //todo: check if print needed
// // debugPrint(
// // "updated range for: $buy for $_fromTicker-$_toTicker: $range");
//
// if (shouldNotifyListeners) {
// notifyListeners();
// }
}
Future<void> updateEstimate({
required bool shouldNotifyListeners,
required bool reversed,
}) async {
// // if (buy?.name == SimpleSwapBuy.buyName) {
// // reversed = false;
// // }
// final amount = reversed ? toAmount : fromAmount;
// if (fromTicker == null ||
// toTicker == null ||
// amount == null ||
// amount <= Decimal.zero) {
// Logging.instance.log(
// "Tried to $runtimeType.updateEstimate for: $buy where (from: $fromTicker || to: $toTicker || amount: $amount)",
// level: LogLevel.Info,
// );
// return;
// }
// final response = await buy?.getEstimate(
// fromTicker!,
// toTicker!,
// amount,
// buyType == BuyRateType.fixed,
// reversed,
// );
//
// if (response?.value == null) {
// Logging.instance.log(
// "Tried to $runtimeType.updateEstimate for: $buy where response: $response",
// level: LogLevel.Info,
// );
// return;
// }
//
// estimate = response!.value!;
//
// if (reversed) {
// fromAmount = estimate!.estimatedAmount;
// } else {
// toAmount = estimate!.estimatedAmount;
// }
//
// rate = (toAmount! / fromAmount!).toDecimal(scaleOnInfinitePrecision: 12);
//
// //todo: check if print needed
// // debugPrint(
// // "updated estimate for: $buy for $fromTicker-$toTicker: $estimate");
//
// if (shouldNotifyListeners) {
// notifyListeners();
// }
}
void setOnError({
required void Function(String)? onError,
bool shouldNotifyListeners = false,
}) {
// _onError = onError;
// if (shouldNotifyListeners) {
// notifyListeners();
// }
}
Future<void> swap({dynamic? market}) async {
// final Decimal? newToAmount = fromAmount;
// final Decimal? newFromAmount = toAmount;
//
// fromAmount = newFromAmount;
// toAmount = newToAmount;
//
// minAmount = null;
// maxAmount = null;
//
// if (buyType == BuyRateType.fixed && buy?.name == ChangeNowBuy.buyName) {
// await updateMarket(market, false);
// } else {
// final dynamic? newTo = from;
// final dynamic? newFrom = to;
//
// _to = newTo;
// _from = newFrom;
//
// await updateRanges(shouldNotifyListeners: false);
//
// await updateEstimate(
// shouldNotifyListeners: false,
// reversed: reversed,
// );
// }
//
// notifyListeners();
}
}

View file

@ -0,0 +1,237 @@
import 'package:hive/hive.dart';
part 'buy.g.dart';
@HiveType(typeId: Buy.typeId)
class Buy {
static const typeId = 22;
@HiveField(0)
final String uuid;
@HiveField(1)
final String tradeId;
@HiveField(2)
final String rateType;
@HiveField(3)
final String direction;
@HiveField(4)
final DateTime timestamp;
@HiveField(5)
final DateTime updatedAt;
@HiveField(6)
final String payInCurrency;
@HiveField(7)
final String payInAmount;
@HiveField(8)
final String payInAddress;
@HiveField(9)
final String payInNetwork;
@HiveField(10)
final String payInExtraId;
@HiveField(11)
final String payInTxid;
@HiveField(12)
final String payOutCurrency;
@HiveField(13)
final String payOutAmount;
@HiveField(14)
final String payOutAddress;
@HiveField(15)
final String payOutNetwork;
@HiveField(16)
final String payOutExtraId;
@HiveField(17)
final String payOutTxid;
@HiveField(18)
final String refundAddress;
@HiveField(19)
final String refundExtraId;
@HiveField(20)
final String status;
@HiveField(21)
final String exchangeName;
const Buy({
required this.uuid,
required this.tradeId,
required this.rateType,
required this.direction,
required this.timestamp,
required this.updatedAt,
required this.payInCurrency,
required this.payInAmount,
required this.payInAddress,
required this.payInNetwork,
required this.payInExtraId,
required this.payInTxid,
required this.payOutCurrency,
required this.payOutAmount,
required this.payOutAddress,
required this.payOutNetwork,
required this.payOutExtraId,
required this.payOutTxid,
required this.refundAddress,
required this.refundExtraId,
required this.status,
required this.exchangeName,
});
Trade copyWith({
String? tradeId,
String? rateType,
String? direction,
DateTime? timestamp,
DateTime? updatedAt,
String? payInCurrency,
String? payInAmount,
String? payInAddress,
String? payInNetwork,
String? payInExtraId,
String? payInTxid,
String? payOutCurrency,
String? payOutAmount,
String? payOutAddress,
String? payOutNetwork,
String? payOutExtraId,
String? payOutTxid,
String? refundAddress,
String? refundExtraId,
String? status,
String? exchangeName,
}) {
return Buy(
uuid: uuid,
tradeId: tradeId ?? this.tradeId,
rateType: rateType ?? this.rateType,
direction: direction ?? this.direction,
timestamp: timestamp ?? this.timestamp,
updatedAt: updatedAt ?? this.updatedAt,
payInCurrency: payInCurrency ?? this.payInCurrency,
payInAmount: payInAmount ?? this.payInAmount,
payInAddress: payInAddress ?? this.payInAddress,
payInNetwork: payInNetwork ?? this.payInNetwork,
payInExtraId: payInExtraId ?? this.payInExtraId,
payInTxid: payInTxid ?? this.payInTxid,
payOutCurrency: payOutCurrency ?? this.payOutCurrency,
payOutAmount: payOutAmount ?? this.payOutAmount,
payOutAddress: payOutAddress ?? this.payOutAddress,
payOutNetwork: payOutNetwork ?? this.payOutNetwork,
payOutExtraId: payOutExtraId ?? this.payOutExtraId,
payOutTxid: payOutTxid ?? this.payOutTxid,
refundAddress: refundAddress ?? this.refundAddress,
refundExtraId: refundExtraId ?? this.refundExtraId,
status: status ?? this.status,
exchangeName: exchangeName ?? this.exchangeName,
);
}
Map<String, String> toMap() {
return {
"uuid": uuid,
"tradeId": tradeId,
"rateType": rateType,
"direction": direction,
"timestamp": timestamp.toIso8601String(),
"updatedAt": updatedAt.toIso8601String(),
"payInCurrency": payInCurrency,
"payInAmount": payInAmount,
"payInAddress": payInAddress,
"payInNetwork": payInNetwork,
"payInExtraId": payInExtraId,
"payInTxid": payInTxid,
"payOutCurrency": payOutCurrency,
"payOutAmount": payOutAmount,
"payOutAddress": payOutAddress,
"payOutNetwork": payOutNetwork,
"payOutExtraId": payOutExtraId,
"payOutTxid": payOutTxid,
"refundAddress": refundAddress,
"refundExtraId": refundExtraId,
"status": status,
"exchangeName": exchangeName,
};
}
factory Buy.fromMap(Map<String, dynamic> map) {
return Buy(
uuid: map["uuid"] as String,
tradeId: map["tradeId"] as String,
rateType: map["rateType"] as String,
direction: map["direction"] as String,
timestamp: DateTime.parse(map["timestamp"] as String),
updatedAt: DateTime.parse(map["updatedAt"] as String),
payInCurrency: map["payInCurrency"] as String,
payInAmount: map["payInAmount"] as String,
payInAddress: map["payInAddress"] as String,
payInNetwork: map["payInNetwork"] as String,
payInExtraId: map["payInExtraId"] as String,
payInTxid: map["payInTxid"] as String,
payOutCurrency: map["payOutCurrency"] as String,
payOutAmount: map["payOutAmount"] as String,
payOutAddress: map["payOutAddress"] as String,
payOutNetwork: map["payOutNetwork"] as String,
payOutExtraId: map["payOutExtraId"] as String,
payOutTxid: map["payOutTxid"] as String,
refundAddress: map["refundAddress"] as String,
refundExtraId: map["refundExtraId"] as String,
status: map["status"] as String,
exchangeName: map["exchangeName"] as String,
);
}
// 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

@ -0,0 +1,123 @@
class Currency {
/// Currency ticker
final String ticker;
/// Currency name
final String name;
/// Currency network
final String network;
/// Currency logo url
final String image;
/// Indicates if a currency has an Extra ID
final bool hasExternalId;
/// external id if it exists
final String? externalId;
/// Indicates if a currency is a fiat currency (EUR, USD)
final bool isFiat;
/// Indicates if a currency is popular
final bool featured;
/// Indicates if a currency is stable
final bool isStable;
/// Indicates if a currency is available on a fixed-rate flow
final bool supportsFixedRate;
/// (Optional - based on api call) Indicates whether the pair is
/// currently supported by change now
final bool? isAvailable;
Currency({
required this.ticker,
required this.name,
required this.network,
required this.image,
required this.hasExternalId,
this.externalId,
required this.isFiat,
required this.featured,
required this.isStable,
required this.supportsFixedRate,
this.isAvailable,
});
factory Currency.fromJson(Map<String, dynamic> json) {
try {
return Currency(
ticker: json["ticker"] as String,
name: json["name"] as String,
network: json["network"] as String? ?? "",
image: json["image"] as String,
hasExternalId: json["hasExternalId"] as bool,
externalId: json["externalId"] as String?,
isFiat: json["isFiat"] as bool,
featured: json["featured"] as bool,
isStable: json["isStable"] as bool,
supportsFixedRate: json["supportsFixedRate"] as bool,
isAvailable: json["isAvailable"] as bool?,
);
} catch (e) {
rethrow;
}
}
Map<String, dynamic> toJson() {
final map = {
"ticker": ticker,
"name": name,
"network": network,
"image": image,
"hasExternalId": hasExternalId,
"externalId": externalId,
"isFiat": isFiat,
"featured": featured,
"isStable": isStable,
"supportsFixedRate": supportsFixedRate,
};
if (isAvailable != null) {
map["isAvailable"] = isAvailable!;
}
return map;
}
Currency copyWith({
String? ticker,
String? name,
String? network,
String? image,
bool? hasExternalId,
String? externalId,
bool? isFiat,
bool? featured,
bool? isStable,
bool? supportsFixedRate,
bool? isAvailable,
}) {
return Currency(
ticker: ticker ?? this.ticker,
name: name ?? this.name,
network: network ?? this.network,
image: image ?? this.image,
hasExternalId: hasExternalId ?? this.hasExternalId,
externalId: externalId ?? this.externalId,
isFiat: isFiat ?? this.isFiat,
featured: featured ?? this.featured,
isStable: isStable ?? this.isStable,
supportsFixedRate: supportsFixedRate ?? this.supportsFixedRate,
isAvailable: isAvailable ?? this.isAvailable,
);
}
@override
String toString() {
return "Currency: ${toJson()}";
}
}

View file

@ -0,0 +1,227 @@
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/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';
class BuyForm extends ConsumerStatefulWidget {
const BuyForm({
Key? key,
this.walletId,
this.coin,
}) : super(key: key);
final String? walletId;
final Coin? coin;
@override
ConsumerState<BuyForm> createState() => _BuyFormState();
}
class _BuyFormState extends ConsumerState<BuyForm> {
late final String? walletId;
late final Coin? coin;
final isDesktop = Util.isDesktop;
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"You will send",
style: STextStyles.itemSubtitle(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
),
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,
),
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,
children: [
Text(
"You will receive",
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,
),
// 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,
),
// SizedBox(
// height: 60,
// child: RateTypeToggle(
// 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
// 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",
// )
],
);
}
}

View file

@ -1,5 +1,8 @@
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);
@ -13,37 +16,156 @@ class _BuyViewState extends State<BuyView> {
Widget build(BuildContext context) {
//todo: check if print needed
// debugPrint("BUILD: BuyView");
return SafeArea(
child: Center(
child: SingleChildScrollView(
child: Column(
children: [
Center(
child: Text(
"Coming soon",
style: STextStyles.pageTitleH1(context),
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: Column(
// children: [
// Container(
// color: Colors.green,
// child: Text("BuyView"),
// ),
// Container(
// color: Colors.green,
// child: Text("BuyView"),
// ),
// Spacer(),
// Container(
// color: Colors.green,
// child: Text("BuyView"),
// ),
// ],
// ),
),
);
}

View file

@ -308,7 +308,7 @@ class _HomeViewState extends ConsumerState<HomeView> {
if (next == 1) {
_exchangeDataLoadingService.loadAll(ref);
}
if (next >= 0 && next <= 1) {
if (next >= 0 && next <= 2) {
_pageController.animateToPage(
next,
duration: const Duration(milliseconds: 300),

View file

@ -153,7 +153,7 @@ class _HomeViewButtonBarState extends ConsumerState<HomeViewButtonBar> {
"Buy",
style: STextStyles.button(context).copyWith(
fontSize: 14,
color: selectedIndex == 1
color: selectedIndex == 2
? Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary

View file

@ -200,37 +200,37 @@ class WalletNavigationBar extends StatelessWidget {
),
// TODO: Do not delete this code.
// only temporarily disabled
// Spacer(
// flex: 2,
// ),
// GestureDetector(
// onTap: onBuyPressed,
// child: Container(
// color: Colors.transparent,
// child: Padding(
// padding: const EdgeInsets.symmetric(vertical: 2.0),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Spacer(),
// SvgPicture.asset(
// Assets.svg.buy,
// width: 24,
// height: 24,
// ),
// SizedBox(
// height: 4,
// ),
// Text(
// "Buy",
// style: STextStyles.buttonSmall(context),
// ),
// Spacer(),
// ],
// ),
// ),
// ),
// ),
Spacer(
flex: 2,
),
GestureDetector(
onTap: onBuyPressed,
child: Container(
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Spacer(),
SvgPicture.asset(
Assets.svg.buyDesktop,
width: 24,
height: 24,
),
SizedBox(
height: 4,
),
Text(
"Buy2",
style: STextStyles.buttonSmall(context),
),
Spacer(),
],
),
),
),
),
],
),
),

View file

@ -0,0 +1,6 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/buy/buy_form_state.dart';
final buyFormStateProvider = ChangeNotifierProvider<BuyFormState>(
(ref) => BuyFormState(),
);

View file

@ -0,0 +1,5 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/services/buys_service.dart';
final buysServiceProvider =
ChangeNotifierProvider<BuysService>((ref) => BuysService());

44
lib/services/buy/buy.dart Normal file
View file

@ -0,0 +1,44 @@
abstract class Buy {
String get name;
// Future<BuyResponse<List<Currency>>> getAllCurrencies(bool fixedRate);
//
// Future<BuyResponse<List<Pair>>> getPairsFor(
// String currency,
// bool fixedRate,
// );
//
// Future<BuyResponse<List<Pair>>> getAllPairs(bool fixedRate);
//
// Future<BuyResponse<Trade>> getTrade(String tradeId);
// Future<BuyResponse<Trade>> updateTrade(Trade trade);
//
// Future<BuyResponse<List<Trade>>> getTrades();
//
// Future<BuyResponse<Range>> getRange(
// String from,
// String to,
// bool fixedRate,
// );
//
// Future<BuyResponse<Estimate>> getEstimate(
// String from,
// String to,
// Decimal amount,
// bool fixedRate,
// bool reversed,
// );
//
// Future<BuyResponse<Trade>> createTrade({
// required String from,
// required String to,
// required bool fixedRate,
// required Decimal amount,
// required String addressTo,
// String? extraId,
// required String addressRefund,
// required String refundExtraId,
// String? rateId,
// required bool reversed,
// });
}

View file

@ -0,0 +1,66 @@
import 'package:flutter/cupertino.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/buy/response_objects/buy.dart';
class BuysService extends ChangeNotifier {
List<Buy> get Buys {
final list = DB.instance.values<Buy>(boxName: DB.boxNameBuys);
list.sort((a, b) =>
b.timestamp.millisecondsSinceEpoch -
a.timestamp.millisecondsSinceEpoch);
return list;
}
Buy? get(String BuyId) {
try {
return DB.instance
.values<Buy>(boxName: DB.boxNameBuys)
.firstWhere((e) => e.BuyId == BuyId);
} catch (_) {
return null;
}
}
Future<void> add({
required Buy Buy,
required bool shouldNotifyListeners,
}) async {
await DB.instance
.put<Buy>(boxName: DB.boxNameBuys, key: Buy.uuid, value: Buy);
if (shouldNotifyListeners) {
notifyListeners();
}
}
Future<void> edit({
required Buy Buy,
required bool shouldNotifyListeners,
}) async {
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);
}
Future<void> delete({
required Buy Buy,
required bool shouldNotifyListeners,
}) async {
await deleteByUuid(
uuid: Buy.uuid, shouldNotifyListeners: shouldNotifyListeners);
}
Future<void> deleteByUuid({
required String uuid,
required bool shouldNotifyListeners,
}) async {
await DB.instance.delete<Buy>(boxName: DB.boxNameBuys, key: uuid);
if (shouldNotifyListeners) {
notifyListeners();
}
}
}