mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 03:49:22 +00:00
add token list ui
This commit is contained in:
parent
6a734e28f0
commit
695d43bbd5
8 changed files with 311 additions and 28 deletions
|
@ -12,4 +12,15 @@ class EthToken {
|
|||
final String symbol;
|
||||
final int decimals;
|
||||
final int balance;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "$runtimeType: { "
|
||||
"name: $name, "
|
||||
"symbol: $symbol, "
|
||||
"contractAddress: $contractAddress, "
|
||||
"decimals: $decimals, "
|
||||
"balance: $balance"
|
||||
" }";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
|
||||
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/add_wallet_entity_list.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/add_wallet_text.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/next_button.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_text.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_eth_tokens.dart';
|
||||
|
@ -17,6 +16,7 @@ import 'package:stackwallet/widgets/background.dart';
|
|||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_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';
|
||||
|
@ -25,8 +25,11 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
|||
class AddTokenView extends ConsumerStatefulWidget {
|
||||
const AddTokenView({
|
||||
Key? key,
|
||||
required this.walletId,
|
||||
}) : super(key: key);
|
||||
|
||||
final String walletId;
|
||||
|
||||
static const routeName = "/addToken";
|
||||
|
||||
@override
|
||||
|
@ -39,36 +42,42 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
|
||||
String _searchTerm = "";
|
||||
|
||||
final List<AddWalletListEntity> tokenEntities = [];
|
||||
final List<AddTokenListElementData> tokenEntities = [];
|
||||
|
||||
final bool isDesktop = Util.isDesktop;
|
||||
|
||||
List<AddWalletListEntity> filter(
|
||||
List<AddTokenListElementData> filter(
|
||||
String text,
|
||||
List<AddWalletListEntity> entities,
|
||||
List<AddTokenListElementData> entities,
|
||||
) {
|
||||
final _entities = [...entities];
|
||||
if (text.isNotEmpty) {
|
||||
final lowercaseTerm = text.toLowerCase();
|
||||
_entities.retainWhere(
|
||||
(e) =>
|
||||
e.ticker.toLowerCase().contains(lowercaseTerm) ||
|
||||
e.name.toLowerCase().contains(lowercaseTerm) ||
|
||||
(e is EthTokenEntity &&
|
||||
e.token.contractAddress.toLowerCase().contains(lowercaseTerm)),
|
||||
e.token.name.toLowerCase().contains(lowercaseTerm) ||
|
||||
e.token.symbol.toLowerCase().contains(lowercaseTerm) ||
|
||||
e.token.contractAddress.toLowerCase().contains(lowercaseTerm),
|
||||
);
|
||||
}
|
||||
|
||||
return _entities;
|
||||
}
|
||||
|
||||
void onNextPressed() {
|
||||
final selectedTokens =
|
||||
tokenEntities.where((e) => e.selected).map((e) => e.token);
|
||||
print("SELECTED TOKENS: $selectedTokens");
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_searchFieldController = TextEditingController();
|
||||
_searchFocusNode = FocusNode();
|
||||
|
||||
tokenEntities.addAll(DefaultTokens.list.map((e) => EthTokenEntity(e)));
|
||||
tokenEntities.sort((a, b) => a.name.compareTo(b.name));
|
||||
tokenEntities
|
||||
.addAll(DefaultTokens.list.map((e) => AddTokenListElementData(e)));
|
||||
tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name));
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
@ -83,6 +92,8 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
final walletName = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).walletName));
|
||||
|
||||
if (isDesktop) {
|
||||
return DesktopScaffold(
|
||||
|
@ -93,8 +104,9 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
),
|
||||
body: Column(
|
||||
children: [
|
||||
const AddWalletText(
|
||||
AddTokenText(
|
||||
isDesktop: true,
|
||||
walletName: walletName,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
|
@ -183,8 +195,8 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
),
|
||||
),
|
||||
Expanded(
|
||||
child: AddWalletEntityList(
|
||||
entities: filter(_searchTerm, tokenEntities),
|
||||
child: AddTokenList(
|
||||
items: filter(_searchTerm, tokenEntities),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -195,11 +207,12 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
const SizedBox(
|
||||
SizedBox(
|
||||
height: 70,
|
||||
width: 480,
|
||||
child: AddWalletNextButton(
|
||||
isDesktop: true,
|
||||
child: PrimaryButton(
|
||||
label: "Next",
|
||||
onPressed: onNextPressed,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
|
@ -219,6 +232,25 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: AppBarIconButton(
|
||||
icon: SvgPicture.asset(
|
||||
Assets.svg.circlePlusFilled,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.topNavIconPrimary,
|
||||
),
|
||||
onPressed: () {
|
||||
// todo add custom token
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Container(
|
||||
color: Theme.of(context).extension<StackColors>()!.background,
|
||||
|
@ -227,8 +259,9 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const AddWalletText(
|
||||
AddTokenText(
|
||||
isDesktop: false,
|
||||
walletName: walletName,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
|
@ -289,15 +322,16 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
|
|||
height: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: AddWalletEntityList(
|
||||
entities: filter(_searchTerm, tokenEntities),
|
||||
child: AddTokenList(
|
||||
items: filter(_searchTerm, tokenEntities),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
const AddWalletNextButton(
|
||||
isDesktop: false,
|
||||
PrimaryButton(
|
||||
label: "Next",
|
||||
onPressed: onNextPressed,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
|
||||
class AddTokenList extends StatelessWidget {
|
||||
const AddTokenList({
|
||||
Key? key,
|
||||
required this.items,
|
||||
}) : super(key: key);
|
||||
|
||||
final List<AddTokenListElementData> items;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
primary: false,
|
||||
itemCount: items.length,
|
||||
itemBuilder: (ctx, index) {
|
||||
return ConditionalParent(
|
||||
condition: index == items.length - 1,
|
||||
builder: (child) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
child,
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: RawMaterialButton(
|
||||
fillColor:
|
||||
Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
elevation: 0,
|
||||
focusElevation: 0,
|
||||
hoverElevation: 0,
|
||||
highlightElevation: 0,
|
||||
constraints: const BoxConstraints(),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
// todo add custom token
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.circlePlusFilled,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Text(
|
||||
"Add custom token",
|
||||
style: STextStyles.w600_14(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: AddTokenListElement(
|
||||
data: items[index],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/models/ethereum/eth_token.dart';
|
||||
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
|
||||
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
|
||||
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class AddTokenListElementData {
|
||||
AddTokenListElementData(this.token);
|
||||
|
||||
final EthToken token;
|
||||
bool selected = false;
|
||||
}
|
||||
|
||||
class AddTokenListElement extends StatefulWidget {
|
||||
const AddTokenListElement({Key? key, required this.data}) : super(key: key);
|
||||
|
||||
final AddTokenListElementData data;
|
||||
|
||||
@override
|
||||
State<AddTokenListElement> createState() => _AddTokenListElementState();
|
||||
}
|
||||
|
||||
class _AddTokenListElementState extends State<AddTokenListElement> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final currency = ExchangeDataLoadingService.instance.isar.currencies
|
||||
.where()
|
||||
.tickerExchangeNameEqualToAnyName(
|
||||
"${widget.data.token.symbol}ERC20",
|
||||
ChangeNowExchange.exchangeName,
|
||||
)
|
||||
.or()
|
||||
.tickerExchangeNameEqualToAnyName(
|
||||
widget.data.token.symbol,
|
||||
ChangeNowExchange.exchangeName,
|
||||
)
|
||||
.or()
|
||||
.tickerExchangeNameEqualToAnyName(
|
||||
"${widget.data.token.symbol}BSC",
|
||||
ChangeNowExchange.exchangeName,
|
||||
)
|
||||
.filter()
|
||||
.imageIsNotEmpty()
|
||||
.findFirstSync();
|
||||
return RoundedWhiteContainer(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
currency != null
|
||||
? SvgPicture.network(
|
||||
currency.image,
|
||||
width: 24,
|
||||
height: 24,
|
||||
)
|
||||
: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
color: Colors.red,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Text(
|
||||
"${widget.data.token.name} (${widget.data.token.symbol})",
|
||||
style: STextStyles.w600_14(context),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
width: 40,
|
||||
child: DraggableSwitchButton(
|
||||
isOn: widget.data.selected,
|
||||
onValueChanged: (newValue) {
|
||||
widget.data.selected = newValue;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
|
||||
class AddTokenText extends StatelessWidget {
|
||||
const AddTokenText({
|
||||
Key? key,
|
||||
required this.isDesktop,
|
||||
required this.walletName,
|
||||
}) : super(key: key);
|
||||
|
||||
final String walletName;
|
||||
final bool isDesktop;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
walletName,
|
||||
textAlign: TextAlign.center,
|
||||
style: isDesktop
|
||||
? STextStyles.sectionLabelMedium12(context) // todo: fixme
|
||||
: STextStyles.sectionLabelMedium12(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Add Tokens",
|
||||
textAlign: TextAlign.center,
|
||||
style: isDesktop
|
||||
? STextStyles.desktopH2(context)
|
||||
: STextStyles.pageTitleH1(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Text(
|
||||
"You can also do it later in your wallet",
|
||||
textAlign: TextAlign.center,
|
||||
style: isDesktop
|
||||
? STextStyles.desktopSubtitleH2(context)
|
||||
: STextStyles.subtitle(context),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -113,6 +113,7 @@ class _VerifyRecoveryPhraseViewState
|
|||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
AddTokenView.routeName,
|
||||
arguments: widget.manager.walletId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -148,6 +148,7 @@ class _TokenDetailsViewState extends ConsumerState<MyTokensView> {
|
|||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
AddTokenView.routeName,
|
||||
arguments: widget.walletId,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -205,10 +205,18 @@ class RouteGenerator {
|
|||
settings: RouteSettings(name: settings.name));
|
||||
|
||||
case AddTokenView.routeName:
|
||||
if (args is String) {
|
||||
return getRoute(
|
||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||
builder: (_) => const AddTokenView(),
|
||||
settings: RouteSettings(name: settings.name));
|
||||
builder: (_) => AddTokenView(
|
||||
walletId: args,
|
||||
),
|
||||
settings: RouteSettings(
|
||||
name: settings.name,
|
||||
),
|
||||
);
|
||||
}
|
||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||
|
||||
case PaynymClaimView.routeName:
|
||||
if (args is String) {
|
||||
|
|
Loading…
Reference in a new issue