desktop trade steps 3 and 4 mostly laid out

This commit is contained in:
julian 2022-11-21 10:14:27 -06:00
parent 648c896b9e
commit c9e2c4abb7
3 changed files with 295 additions and 31 deletions

View file

@ -18,7 +18,6 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';

View file

@ -1,13 +1,135 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_4_view.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
import 'package:stackwallet/providers/exchange/current_exchange_name_state_provider.dart';
import 'package:stackwallet/providers/exchange/exchange_provider.dart';
import 'package:stackwallet/providers/global/trades_service_provider.dart';
import 'package:stackwallet/services/exchange/exchange_response.dart';
import 'package:stackwallet/services/notifications_api.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/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
class DesktopStep3 extends StatelessWidget {
const DesktopStep3({Key? key}) : super(key: key);
class DesktopStep3 extends ConsumerStatefulWidget {
const DesktopStep3({
Key? key,
required this.model,
}) : super(key: key);
final IncompleteExchangeModel model;
@override
ConsumerState<DesktopStep3> createState() => _DesktopStep3State();
}
class _DesktopStep3State extends ConsumerState<DesktopStep3> {
late final IncompleteExchangeModel model;
Future<void> createTrade() async {
unawaited(
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (_) => WillPopScope(
onWillPop: () async => false,
child: Container(
color: Theme.of(context)
.extension<StackColors>()!
.overlay
.withOpacity(0.6),
child: const CustomLoadingOverlay(
message: "Creating a trade",
eventBus: null,
),
),
),
),
);
final ExchangeResponse<Trade> response =
await ref.read(exchangeProvider).createTrade(
from: model.sendTicker,
to: model.receiveTicker,
fixedRate: model.rateType != ExchangeRateType.estimated,
amount: model.reversed ? model.receiveAmount : model.sendAmount,
addressTo: model.recipientAddress!,
extraId: null,
addressRefund: model.refundAddress!,
refundExtraId: "",
rateId: model.rateId,
reversed: model.reversed,
);
if (response.value == null) {
if (mounted) {
Navigator.of(context).pop();
}
unawaited(showDialog<void>(
context: context,
barrierDismissible: true,
builder: (_) => StackDialog(
title: "Failed to create trade",
message: response.exception?.toString(),
),
));
return;
}
// save trade to hive
await ref.read(tradesServiceProvider).add(
trade: response.value!,
shouldNotifyListeners: true,
);
String status = response.value!.status;
model.trade = response.value!;
// extra info if status is waiting
if (status == "Waiting") {
status += " for deposit";
}
if (mounted) {
Navigator.of(context).pop();
}
unawaited(NotificationApi.showNotification(
changeNowId: model.trade!.tradeId,
title: status,
body: "Trade ID ${model.trade!.tradeId}",
walletId: "",
iconAssetName: Assets.svg.arrowRotate,
date: model.trade!.timestamp,
shouldWatchForUpdates: true,
coinName: "coinName",
));
if (mounted) {
unawaited(Navigator.of(context).pushNamed(
Step4View.routeName,
arguments: model,
));
}
}
@override
void initState() {
model = widget.model;
super.initState();
}
@override
Widget build(BuildContext context) {
@ -25,33 +147,55 @@ class DesktopStep3 extends StatelessWidget {
padding: const EdgeInsets.all(0),
child: Column(
children: [
const DesktopStepItem(
DesktopStepItem(
label: "Exchange",
value: "lol",
value: ref.watch(currentExchangeNameStateProvider.state).state,
),
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
const DesktopStepItem(
DesktopStepItem(
label: "You send",
value: "lol",
value:
"${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}",
),
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
const DesktopStepItem(
DesktopStepItem(
label: "You receive",
value: "lol",
value:
"~${model.receiveAmount.toStringAsFixed(8)} ${model.receiveTicker.toUpperCase()}",
),
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
const DesktopStepItem(
label: "Rate",
value: "lol",
DesktopStepItem(
label: model.rateType == ExchangeRateType.estimated
? "Estimated rate"
: "Fixed rate",
value: model.rateInfo,
),
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
DesktopStepItem(
vertical: true,
label: "Recipient ${model.receiveTicker.toUpperCase()} address",
value: model.recipientAddress!,
),
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
DesktopStepItem(
vertical: true,
label: "Refund ${model.sendTicker.toUpperCase()} address",
value: model.refundAddress!,
),
],
),
@ -77,9 +221,7 @@ class DesktopStep3 extends StatelessWidget {
child: PrimaryButton(
label: "Confirm",
buttonHeight: ButtonHeight.l,
onPressed: () {
// todo
},
onPressed: createTrade,
),
),
],

View file

@ -1,64 +1,187 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/exchange_steps/subwidgets/desktop_step_item.dart';
import 'package:stackwallet/providers/providers.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/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_container.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class DesktopStep4 extends StatelessWidget {
const DesktopStep4({Key? key}) : super(key: key);
class DesktopStep4 extends ConsumerStatefulWidget {
const DesktopStep4({
Key? key,
required this.model,
}) : super(key: key);
final IncompleteExchangeModel model;
@override
ConsumerState<DesktopStep4> createState() => _DesktopStep4State();
}
class _DesktopStep4State extends ConsumerState<DesktopStep4> {
late final IncompleteExchangeModel model;
String _statusString = "New";
Timer? _statusTimer;
bool _isWalletCoinAndHasWallet(String ticker) {
try {
final coin = coinFromTickerCaseInsensitive(ticker);
return ref
.read(walletsChangeNotifierProvider)
.managers
.where((element) => element.coin == coin)
.isNotEmpty;
} catch (_) {
return false;
}
}
Future<void> _updateStatus() async {
final statusResponse =
await ref.read(exchangeProvider).updateTrade(model.trade!);
String status = "Waiting";
if (statusResponse.value != null) {
status = statusResponse.value!.status;
}
// extra info if status is waiting
if (status == "Waiting") {
status += " for deposit";
}
if (mounted) {
setState(() {
_statusString = status;
});
}
}
@override
void initState() {
model = widget.model;
_statusTimer = Timer.periodic(const Duration(seconds: 60), (_) {
_updateStatus();
});
super.initState();
}
@override
void dispose() {
_statusTimer?.cancel();
_statusTimer = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text(
"Confirm amount",
"Send ${model.sendTicker.toUpperCase()} to the address below",
style: STextStyles.desktopTextMedium(context),
),
const SizedBox(
height: 8,
),
Text(
"Network fees and other exchange charges are included in the rate.",
"Send ${model.sendTicker.toUpperCase()} to the address below. Once it is received, ${model.trade!.exchangeName} will send the ${model.receiveTicker.toUpperCase()} to the recipient address you provided. You can find this trade details and check its status in the list of trades.",
style: STextStyles.desktopTextExtraExtraSmall(context),
),
const SizedBox(
height: 20,
),
RoundedContainer(
color: Theme.of(context).extension<StackColors>()!.warningBackground,
child: RichText(
text: TextSpan(
text:
"You must send at least ${model.sendAmount.toString()} ${model.sendTicker}. ",
style: STextStyles.label700(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.warningForeground,
fontSize: 14,
),
children: [
TextSpan(
text:
"If you send less than ${model.sendAmount.toString()} ${model.sendTicker}, your transaction may not be converted and it may not be refunded.",
style: STextStyles.label(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.warningForeground,
fontSize: 14,
),
),
],
),
),
),
const SizedBox(
height: 20,
),
RoundedWhiteContainer(
borderColor: Theme.of(context).extension<StackColors>()!.background,
padding: const EdgeInsets.all(0),
child: Column(
children: [
const DesktopStepItem(
label: "Exchange",
value: "lol",
DesktopStepItem(
vertical: true,
label: "Send ${model.sendTicker.toUpperCase()} to this address",
value: model.trade!.payInAddress,
),
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
const DesktopStepItem(
label: "You send",
value: "lol",
DesktopStepItem(
label: "Amount",
value:
"${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}",
),
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
const DesktopStepItem(
label: "You receive",
value: "lol",
DesktopStepItem(
label: "Trade ID",
value: model.trade!.tradeId,
),
Container(
height: 1,
color: Theme.of(context).extension<StackColors>()!.background,
),
const DesktopStepItem(
label: "Rate",
value: "lol",
Padding(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Status",
style: STextStyles.desktopTextExtraExtraSmall(context),
),
Text(
_statusString,
style: STextStyles.desktopTextExtraExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.colorForStatus(_statusString),
),
),
],
),
),
],
),