desktop exchange choose from stack address ui

This commit is contained in:
julian 2022-11-21 13:21:52 -06:00
parent 7e8f0db967
commit 04b982fb25
2 changed files with 364 additions and 15 deletions

View file

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_choose_from_stack.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart';
import 'package:stackwallet/providers/exchange/exchange_send_from_wallet_id_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
@ -64,12 +64,21 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
final coin = coinFromTickerCaseInsensitive(
model.receiveTicker,
);
Navigator.of(context)
.pushNamed(
ChooseFromStackView.routeName,
arguments: coin,
)
.then((value) async {
showDialog<String?>(
context: context,
barrierColor: Colors.transparent,
builder: (context) => DesktopDialog(
maxWidth: 720,
maxHeight: 670,
child: Padding(
padding: const EdgeInsets.all(32),
child: DesktopChooseFromStack(
coin: coin,
),
),
),
).then((value) async {
if (value is String) {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(value);
@ -88,12 +97,21 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
final coin = coinFromTickerCaseInsensitive(
model.sendTicker,
);
Navigator.of(context)
.pushNamed(
ChooseFromStackView.routeName,
arguments: coin,
)
.then((value) async {
showDialog<String?>(
context: context,
barrierColor: Colors.transparent,
builder: (context) => DesktopDialog(
maxWidth: 720,
maxHeight: 670,
child: Padding(
padding: const EdgeInsets.all(32),
child: DesktopChooseFromStack(
coin: coin,
),
),
),
).then((value) async {
if (value is String) {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(value);
@ -366,7 +384,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
? const ClipboardIcon()
: const XIcon(),
),
if (_toController.text.isEmpty)
if (_toController.text.isEmpty &&
isStackCoin(model.receiveTicker))
TextFieldIconButton(
key: const Key("sendViewAddressBookButtonKey"),
onTap: selectRecipientFromAddressBook,
@ -488,7 +507,8 @@ class _DesktopStep2State extends ConsumerState<DesktopStep2> {
? const ClipboardIcon()
: const XIcon(),
),
if (_refundController.text.isEmpty)
if (_refundController.text.isEmpty &&
isStackCoin(model.sendTicker))
TextFieldIconButton(
key: const Key("sendViewAddressBookButtonKey"),
onTap: selectRefundFromAddressBook,

View file

@ -0,0 +1,329 @@
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/animated_text.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart';
import 'package:stackwallet/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart';
class DesktopChooseFromStack extends ConsumerStatefulWidget {
const DesktopChooseFromStack({
Key? key,
required this.coin,
}) : super(key: key);
final Coin coin;
@override
ConsumerState<DesktopChooseFromStack> createState() =>
_DesktopChooseFromStackState();
}
class _DesktopChooseFromStackState
extends ConsumerState<DesktopChooseFromStack> {
late final TextEditingController _searchController;
late final FocusNode searchFieldFocusNode;
String _searchTerm = "";
List<String> filter(List<String> walletIds, String searchTerm) {
if (searchTerm.isEmpty) {
return walletIds;
}
final List<String> result = [];
for (final walletId in walletIds) {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId);
if (manager.walletName.toLowerCase().contains(searchTerm.toLowerCase())) {
result.add(walletId);
}
}
return result;
}
@override
void initState() {
searchFieldFocusNode = FocusNode();
_searchController = TextEditingController();
super.initState();
}
@override
void dispose() {
_searchController.dispose();
searchFieldFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Choose from Stack",
style: STextStyles.desktopH3(context),
),
const SizedBox(
height: 28,
),
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
autocorrect: false,
enableSuggestions: false,
controller: _searchController,
focusNode: searchFieldFocusNode,
onChanged: (value) {
setState(() {
_searchTerm = value;
});
},
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveText,
height: 1.8,
),
decoration: standardInputDecoration(
"Search",
searchFieldFocusNode,
context,
desktopMed: true,
).copyWith(
prefixIcon: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 18,
),
child: SvgPicture.asset(
Assets.svg.search,
width: 20,
height: 20,
),
),
suffixIcon: _searchController.text.isNotEmpty
? Padding(
padding: const EdgeInsets.only(right: 0),
child: UnconstrainedBox(
child: Row(
children: [
TextFieldIconButton(
child: const XIcon(),
onTap: () async {
setState(() {
_searchController.text = "";
_searchTerm = "";
});
},
),
],
),
),
)
: null,
),
),
),
const SizedBox(
height: 16,
),
Flexible(
child: Builder(
builder: (context) {
List<String> walletIds = ref.watch(
walletsChangeNotifierProvider.select(
(value) => value.getWalletIdsFor(coin: widget.coin),
),
);
if (walletIds.isEmpty) {
return Column(
children: [
RoundedWhiteContainer(
borderColor: Theme.of(context)
.extension<StackColors>()!
.background,
child: Center(
child: Text(
"No ${widget.coin.ticker.toUpperCase()} wallets",
style:
STextStyles.desktopTextExtraExtraSmall(context),
),
),
),
],
);
}
walletIds = filter(walletIds, _searchTerm);
return ListView.separated(
primary: false,
itemCount: walletIds.length,
separatorBuilder: (_, __) => const SizedBox(
height: 5,
),
itemBuilder: (context, index) {
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletIds[index])));
return RoundedWhiteContainer(
borderColor:
Theme.of(context).extension<StackColors>()!.background,
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 14,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
children: [
WalletInfoCoinIcon(coin: widget.coin),
const SizedBox(
width: 12,
),
Text(
manager.walletName,
style: STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
),
),
],
),
const Spacer(),
BalanceDisplay(
walletId: walletIds[index],
),
const SizedBox(
width: 80,
),
BlueTextButton(
text: "Select wallet",
onTap: () {
Navigator.of(context).pop(manager.walletId);
},
),
],
),
);
},
);
},
),
),
const SizedBox(
height: 20,
),
Row(
children: [
const Spacer(),
const SizedBox(
width: 16,
),
Expanded(
child: SecondaryButton(
label: "Cancel",
buttonHeight: ButtonHeight.l,
onPressed: Navigator.of(context).pop,
),
),
],
)
],
);
}
}
class BalanceDisplay extends ConsumerStatefulWidget {
const BalanceDisplay({
Key? key,
required this.walletId,
}) : super(key: key);
final String walletId;
@override
ConsumerState<BalanceDisplay> createState() => _BalanceDisplayState();
}
class _BalanceDisplayState extends ConsumerState<BalanceDisplay> {
late final String walletId;
Decimal? _cachedBalance;
static const loopedText = [
"Loading balance ",
"Loading balance. ",
"Loading balance.. ",
"Loading balance..."
];
@override
void initState() {
walletId = widget.walletId;
super.initState();
}
@override
Widget build(BuildContext context) {
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId)));
final locale = ref.watch(
localeServiceChangeNotifierProvider.select((value) => value.locale));
return FutureBuilder(
future: manager.availableBalance,
builder: (context, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.data != null) {
_cachedBalance = snapshot.data;
}
if (_cachedBalance == null) {
return AnimatedText(
stringsToLoopThrough: loopedText,
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textSubtitle1,
),
);
} else {
return Text(
"${Format.localizedStringAsFixed(
value: _cachedBalance!,
locale: locale,
decimalPlaces: 8,
)} ${manager.coin.ticker}",
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textSubtitle1,
),
textAlign: TextAlign.right,
);
}
},
);
}
}