choose from stack exchange wallet addresses

This commit is contained in:
julian 2022-09-30 10:16:11 -06:00
parent f81784c1c3
commit f02683581d
3 changed files with 241 additions and 22 deletions

View file

@ -0,0 +1,128 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/wallet_info_row/sub_widgets/wallet_info_row_balance_future.dart';
import 'package:stackwallet/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart';
class ChooseFromStackView extends ConsumerStatefulWidget {
const ChooseFromStackView({
Key? key,
required this.coin,
}) : super(key: key);
final Coin coin;
static const String routeName = "/chooseFromStack";
@override
ConsumerState<ChooseFromStackView> createState() =>
_ChooseFromStackViewState();
}
class _ChooseFromStackViewState extends ConsumerState<ChooseFromStackView> {
late final Coin coin;
@override
void initState() {
coin = widget.coin;
super.initState();
}
@override
Widget build(BuildContext context) {
final walletIds = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getWalletIdsFor(coin: coin)));
return Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: const AppBarBackButton(),
title: Text(
"Edit trade note",
style: STextStyles.navBarTitle(context),
),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: walletIds.isEmpty
? Column(
children: [
RoundedWhiteContainer(
child: Center(
child: Text(
"No ${coin.ticker.toUpperCase()} wallets",
style: STextStyles.itemSubtitle(context),
),
),
),
],
)
: ListView.builder(
itemCount: walletIds.length,
itemBuilder: (context, index) {
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletIds[index])));
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: RawMaterialButton(
splashColor:
Theme.of(context).extension<StackColors>()!.highlight,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
padding: const EdgeInsets.all(0),
// color: Theme.of(context).extension<StackColors>()!.popupBG,
elevation: 0,
onPressed: () async {
if (mounted) {
Navigator.of(context).pop(manager.walletId);
}
},
child: RoundedWhiteContainer(
// color: Colors.transparent,
child: Row(
children: [
WalletInfoCoinIcon(coin: coin),
const SizedBox(
width: 12,
),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
manager.walletName,
style: STextStyles.titleBold12(context),
overflow: TextOverflow.ellipsis,
),
const SizedBox(
height: 2,
),
WalletInfoRowBalanceFuture(
walletId: walletIds[index],
),
],
),
)
],
),
),
),
);
},
),
),
);
}
}

View file

@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_3_view.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
import 'package:stackwallet/providers/exchange/exchange_flow_is_active_state_provider.dart';
@ -17,6 +18,7 @@ import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart';
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
@ -54,6 +56,15 @@ class _Step2ViewState extends ConsumerState<Step2View> {
late final FocusNode _toFocusNode;
late final FocusNode _refundFocusNode;
bool isStackCoin(String ticker) {
try {
coinFromTickerCaseInsensitive(ticker);
return true;
} on ArgumentError catch (_) {
return false;
}
}
@override
void initState() {
model = widget.model;
@ -74,7 +85,10 @@ class _Step2ViewState extends ConsumerState<Step2View> {
.read(walletsChangeNotifierProvider)
.getManager(tuple.item1)
.currentReceivingAddress
.then((value) => _toController.text = value);
.then((value) {
_toController.text = value;
model.recipientAddress = _toController.text;
});
}
}
@ -158,15 +172,36 @@ class _Step2ViewState extends ConsumerState<Step2View> {
"Recipient Wallet",
style: STextStyles.smallMed12(context),
),
// GestureDetector(
// onTap: () {
// // TODO: choose from stack?
// },
// child: Text(
// "Choose from Stack",
// style: STextStyles.link2(context),
// ),
// ),
if (isStackCoin(model.receiveTicker))
BlueTextButton(
text: "Choose from stack",
onTap: () {
try {
final coin = coinFromTickerCaseInsensitive(
model.receiveTicker,
);
Navigator.of(context)
.pushNamed(
ChooseFromStackView.routeName,
arguments: coin,
)
.then((value) async {
if (value is String) {
final manager = ref
.read(walletsChangeNotifierProvider)
.getManager(value);
_toController.text = manager.walletName;
model.recipientAddress = await manager
.currentReceivingAddress;
}
});
} catch (e, s) {
Logging.instance
.log("$e\n$s", level: LogLevel.Info);
}
},
),
],
),
const SizedBox(
@ -195,6 +230,9 @@ class _Step2ViewState extends ConsumerState<Step2View> {
),
focusNode: _toFocusNode,
style: STextStyles.field(context),
onChanged: (value) {
setState(() {});
},
decoration: standardInputDecoration(
"Enter the ${model.receiveTicker.toUpperCase()} payout address",
_toFocusNode,
@ -221,6 +259,8 @@ class _Step2ViewState extends ConsumerState<Step2View> {
"sendViewClearAddressFieldButtonKey"),
onTap: () {
_toController.text = "";
model.recipientAddress =
_toController.text;
setState(() {});
},
@ -239,6 +279,8 @@ class _Step2ViewState extends ConsumerState<Step2View> {
data.text!.trim();
_toController.text = content;
model.recipientAddress =
_toController.text;
setState(() {});
}
@ -299,11 +341,15 @@ class _Step2ViewState extends ConsumerState<Step2View> {
// auto fill address
_toController.text =
results["address"] ?? "";
model.recipientAddress =
_toController.text;
setState(() {});
} else {
_toController.text =
qrResult.rawContent;
model.recipientAddress =
_toController.text;
setState(() {});
}
@ -348,15 +394,37 @@ class _Step2ViewState extends ConsumerState<Step2View> {
"Refund Wallet (required)",
style: STextStyles.smallMed12(context),
),
// GestureDetector(
// onTap: () {
// // TODO: choose from stack?
// },
// child: Text(
// "Choose from Stack",
// style: STextStyles.link2(context),
// ),
// ),
if (isStackCoin(model.sendTicker))
BlueTextButton(
text: "Choose from stack",
onTap: () {
try {
final coin = coinFromTickerCaseInsensitive(
model.sendTicker,
);
Navigator.of(context)
.pushNamed(
ChooseFromStackView.routeName,
arguments: coin,
)
.then((value) async {
if (value is String) {
final manager = ref
.read(walletsChangeNotifierProvider)
.getManager(value);
_refundController.text =
manager.walletName;
model.refundAddress = await manager
.currentReceivingAddress;
}
});
} catch (e, s) {
Logging.instance
.log("$e\n$s", level: LogLevel.Info);
}
},
),
],
),
const SizedBox(
@ -384,6 +452,9 @@ class _Step2ViewState extends ConsumerState<Step2View> {
),
focusNode: _refundFocusNode,
style: STextStyles.field(context),
onChanged: (value) {
setState(() {});
},
decoration: standardInputDecoration(
"Enter ${model.sendTicker.toUpperCase()} refund address",
_refundFocusNode,
@ -410,6 +481,8 @@ class _Step2ViewState extends ConsumerState<Step2View> {
"sendViewClearAddressFieldButtonKey"),
onTap: () {
_refundController.text = "";
model.refundAddress =
_refundController.text;
setState(() {});
},
@ -429,6 +502,8 @@ class _Step2ViewState extends ConsumerState<Step2View> {
_refundController.text =
content;
model.refundAddress =
_refundController.text;
setState(() {});
}
@ -490,11 +565,15 @@ class _Step2ViewState extends ConsumerState<Step2View> {
// auto fill address
_refundController.text =
results["address"] ?? "";
model.refundAddress =
_refundController.text;
setState(() {});
} else {
_refundController.text =
qrResult.rawContent;
model.refundAddress =
_refundController.text;
setState(() {});
}
@ -556,9 +635,6 @@ class _Step2ViewState extends ConsumerState<Step2View> {
Expanded(
child: TextButton(
onPressed: () {
model.recipientAddress = _toController.text;
model.refundAddress = _refundController.text;
Navigator.of(context).pushNamed(
Step3View.routeName,
arguments: model);

View file

@ -20,6 +20,7 @@ import 'package:stackwallet/pages/address_book_views/subviews/address_book_filte
import 'package:stackwallet/pages/address_book_views/subviews/contact_details_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart';
import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
import 'package:stackwallet/pages/exchange_view/edit_trade_note_view.dart';
import 'package:stackwallet/pages/exchange_view/exchange_loading_overlay.dart';
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_1_view.dart';
@ -879,6 +880,20 @@ class RouteGenerator {
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case ChooseFromStackView.routeName:
if (args is Coin) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => ChooseFromStackView(
coin: args,
),
settings: RouteSettings(
name: settings.name,
),
);
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
// == Desktop specific routes ============================================
case CreatePasswordView.routeName:
return getRoute(