WIP custom token addition

This commit is contained in:
julian 2023-02-28 16:03:56 -06:00
parent 70335286be
commit 0e4b664e63
4 changed files with 224 additions and 6 deletions

View file

@ -0,0 +1,189 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/ethereum/eth_token.dart';
import 'package:stackwallet/services/ethereum/ethereum_api.dart';
import 'package:stackwallet/utilities/show_loading.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/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
class AddCustomTokenView extends ConsumerStatefulWidget {
const AddCustomTokenView({
Key? key,
required this.walletId,
}) : super(key: key);
final String walletId;
static const routeName = "/addCustomToken";
@override
ConsumerState<AddCustomTokenView> createState() => _AddCustomTokenViewState();
}
class _AddCustomTokenViewState extends ConsumerState<AddCustomTokenView> {
final isDesktop = Util.isDesktop;
final contractController = TextEditingController();
final nameController = TextEditingController();
final symbolController = TextEditingController();
final decimalsController = TextEditingController();
bool enableSubFields = false;
bool addTokenButtonEnabled = false;
EthToken? currentToken;
@override
Widget build(BuildContext context) {
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () {
Navigator.of(context).pop();
},
),
),
body: Padding(
padding: const EdgeInsets.only(
top: 10,
left: 16,
right: 16,
bottom: 16,
),
child: Column(
children: [
Text(
"Add custom ETH token",
style: STextStyles.pageTitleH1(context),
),
const SizedBox(
height: 16,
),
Text("Add custom ETH token"),
const SizedBox(
height: 16,
),
TextField(
autocorrect: !isDesktop,
enableSuggestions: !isDesktop,
controller: contractController,
style: STextStyles.field(context),
decoration: InputDecoration(
hintText: "Contract address",
hintStyle: STextStyles.fieldLabel(context),
),
),
const SizedBox(
height: 8,
),
PrimaryButton(
label: "Search",
onPressed: () async {
final response = await showLoading(
whileFuture: EthereumAPI.getTokenByContractAddress(
contractController.text),
context: context,
message: "Looking up contract",
);
currentToken = response.value;
if (currentToken != null) {
nameController.text = currentToken!.name;
symbolController.text = currentToken!.symbol;
decimalsController.text = currentToken!.decimals.toString();
} else {
nameController.text = "";
symbolController.text = "";
decimalsController.text = "";
unawaited(
showDialog<void>(
context: context,
builder: (context) => StackOkDialog(
title: "Failed to look up token",
message: response.exception?.message,
),
),
);
}
setState(() {
addTokenButtonEnabled = currentToken != null;
});
},
),
const SizedBox(
height: 8,
),
TextField(
enabled: enableSubFields,
autocorrect: !isDesktop,
enableSuggestions: !isDesktop,
controller: nameController,
style: STextStyles.field(context),
decoration: InputDecoration(
hintText: "Token name",
hintStyle: STextStyles.fieldLabel(context),
),
),
const SizedBox(
height: 8,
),
TextField(
enabled: enableSubFields,
autocorrect: !isDesktop,
enableSuggestions: !isDesktop,
controller: symbolController,
style: STextStyles.field(context),
decoration: InputDecoration(
hintText: "Ticker",
hintStyle: STextStyles.fieldLabel(context),
),
),
const SizedBox(
height: 8,
),
TextField(
enabled: enableSubFields,
autocorrect: !isDesktop,
enableSuggestions: !isDesktop,
controller: decimalsController,
style: STextStyles.field(context),
inputFormatters: [
TextInputFormatter.withFunction((oldValue, newValue) =>
RegExp(r'^([0-9]*)$').hasMatch(newValue.text)
? newValue
: oldValue),
],
keyboardType: const TextInputType.numberWithOptions(
signed: false,
decimal: false,
),
decoration: InputDecoration(
hintText: "Decimals",
hintStyle: STextStyles.fieldLabel(context),
),
),
const SizedBox(
height: 16,
),
const Spacer(),
PrimaryButton(
label: "Add token",
enabled: addTokenButtonEnabled,
onPressed: () {},
),
],
),
),
),
);
}
}

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_custom_token_view.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.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_list_element.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_text.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/add_token_text.dart';
@ -70,6 +71,13 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
print("SELECTED TOKENS: $selectedTokens"); print("SELECTED TOKENS: $selectedTokens");
} }
void onAddCustomTokenPressed() {
Navigator.of(context).pushNamed(
AddCustomTokenView.routeName,
arguments: widget.walletId,
);
}
@override @override
void initState() { void initState() {
_searchFieldController = TextEditingController(); _searchFieldController = TextEditingController();
@ -196,6 +204,7 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
), ),
Expanded( Expanded(
child: AddTokenList( child: AddTokenList(
walletId: widget.walletId,
items: filter(_searchTerm, tokenEntities), items: filter(_searchTerm, tokenEntities),
), ),
), ),
@ -244,9 +253,7 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
.extension<StackColors>()! .extension<StackColors>()!
.topNavIconPrimary, .topNavIconPrimary,
), ),
onPressed: () { onPressed: onAddCustomTokenPressed,
// todo add custom token
},
), ),
), ),
), ),
@ -323,6 +330,7 @@ class _AddTokenViewState extends ConsumerState<AddTokenView> {
), ),
Expanded( Expanded(
child: AddTokenList( child: AddTokenList(
walletId: widget.walletId,
items: filter(_searchTerm, tokenEntities), items: filter(_searchTerm, tokenEntities),
), ),
), ),

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_custom_token_view.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_list_element.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/constants.dart';
@ -10,9 +11,11 @@ import 'package:stackwallet/widgets/conditional_parent.dart';
class AddTokenList extends StatelessWidget { class AddTokenList extends StatelessWidget {
const AddTokenList({ const AddTokenList({
Key? key, Key? key,
required this.walletId,
required this.items, required this.items,
}) : super(key: key); }) : super(key: key);
final String walletId;
final List<AddTokenListElementData> items; final List<AddTokenListElementData> items;
@override @override
@ -29,7 +32,7 @@ class AddTokenList extends StatelessWidget {
children: [ children: [
child, child,
Padding( Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.symmetric(vertical: 4),
child: RawMaterialButton( child: RawMaterialButton(
fillColor: fillColor:
Theme.of(context).extension<StackColors>()!.popupBG, Theme.of(context).extension<StackColors>()!.popupBG,
@ -44,7 +47,10 @@ class AddTokenList extends StatelessWidget {
), ),
), ),
onPressed: () { onPressed: () {
// todo add custom token Navigator.of(context).pushNamed(
AddCustomTokenView.routeName,
arguments: walletId,
);
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
@ -73,7 +79,7 @@ class AddTokenList extends StatelessWidget {
], ],
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.symmetric(vertical: 4),
child: AddTokenListElement( child: AddTokenListElement(
data: items[index], data: items[index],
), ),

View file

@ -12,6 +12,7 @@ import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart'
import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/paynym/paynym_account_lite.dart'; import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
import 'package:stackwallet/models/send_view_auto_fill_data.dart'; import 'package:stackwallet/models/send_view_auto_fill_data.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_custom_token_view.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_token_view.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_token_view.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart'; import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart';
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart'; import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart';
@ -218,6 +219,20 @@ class RouteGenerator {
} }
return _routeError("${settings.name} invalid args: ${args.toString()}"); return _routeError("${settings.name} invalid args: ${args.toString()}");
case AddCustomTokenView.routeName:
if (args is String) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => AddCustomTokenView(
walletId: args,
),
settings: RouteSettings(
name: settings.name,
),
);
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case PaynymClaimView.routeName: case PaynymClaimView.routeName:
if (args is String) { if (args is String) {
return getRoute( return getRoute(