desktop wallets search

This commit is contained in:
julian 2023-04-07 17:21:11 -06:00
parent 51211b34f5
commit bb85defaea
2 changed files with 156 additions and 60 deletions

View file

@ -2,8 +2,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/providers/db/main_db_provider.dart';
import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart'; import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
import 'package:stackwallet/services/coins/manager.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';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -19,6 +22,7 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
import 'package:stackwallet/widgets/wallet_card.dart'; import 'package:stackwallet/widgets/wallet_card.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_balance_future.dart';
import 'package:stackwallet/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart'; import 'package:stackwallet/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart';
import 'package:tuple/tuple.dart';
class DesktopCoinWalletsDialog extends ConsumerStatefulWidget { class DesktopCoinWalletsDialog extends ConsumerStatefulWidget {
const DesktopCoinWalletsDialog({ const DesktopCoinWalletsDialog({
@ -44,7 +48,50 @@ class _DesktopCoinWalletsDialogState
String _searchString = ""; String _searchString = "";
final List<String> walletIds = []; final List<Tuple2<Manager, List<EthContract>>> wallets = [];
List<Tuple2<Manager, List<EthContract>>> _filter(String searchTerm) {
if (searchTerm.isEmpty) {
return wallets;
}
final List<Tuple2<Manager, List<EthContract>>> results = [];
final term = searchTerm.toLowerCase();
for (final tuple in wallets) {
bool includeManager = false;
// search wallet name and total balance
includeManager |= _elementContains(tuple.item1.walletName, term);
includeManager |= _elementContains(
tuple.item1.balance.total.decimal.toString(),
term,
);
final List<EthContract> contracts = [];
for (final contract in tuple.item2) {
if (_elementContains(contract.name, term)) {
contracts.add(contract);
} else if (_elementContains(contract.symbol, term)) {
contracts.add(contract);
} else if (_elementContains(contract.type.name, term)) {
contracts.add(contract);
} else if (_elementContains(contract.address, term)) {
contracts.add(contract);
}
}
if (includeManager || contracts.isNotEmpty) {
results.add(Tuple2(tuple.item1, contracts));
}
}
return results;
}
bool _elementContains(String element, String term) {
return element.toLowerCase().contains(term);
}
@override @override
void initState() { void initState() {
@ -54,9 +101,55 @@ class _DesktopCoinWalletsDialogState
final walletsData = final walletsData =
ref.read(walletsServiceChangeNotifierProvider).fetchWalletsData(); ref.read(walletsServiceChangeNotifierProvider).fetchWalletsData();
walletsData.removeWhere((key, value) => value.coin != widget.coin); walletsData.removeWhere((key, value) => value.coin != widget.coin);
walletIds.clear();
walletIds.addAll(walletsData.values.map((e) => e.walletId)); if (widget.coin == Coin.ethereum) {
for (final data in walletsData.values) {
final List<EthContract> contracts = [];
final manager =
ref.read(walletsChangeNotifierProvider).getManager(data.walletId);
final contractAddresses = (manager.wallet as EthereumWallet)
.getWalletTokenContractAddresses();
// fetch each contract
for (final contractAddress in contractAddresses) {
final contract = ref
.read(
mainDBProvider,
)
.getEthContractSync(
contractAddress,
);
// add it to list if it exists in DB
if (contract != null) {
contracts.add(contract);
}
}
// add tuple to list
wallets.add(
Tuple2(
ref.read(walletsChangeNotifierProvider).getManager(
data.walletId,
),
contracts,
),
);
}
} else {
// add non token wallet tuple to list
for (final data in walletsData.values) {
wallets.add(
Tuple2(
ref.read(walletsChangeNotifierProvider).getManager(
data.walletId,
),
[],
),
);
}
}
super.initState(); super.initState();
} }
@ -137,10 +230,14 @@ class _DesktopCoinWalletsDialogState
height: 16, height: 16,
), ),
Expanded( Expanded(
child: ListView.separated( child: Builder(builder: (context) {
final data = _filter(_searchString);
return ListView.separated(
itemBuilder: (_, index) => widget.coin == Coin.ethereum itemBuilder: (_, index) => widget.coin == Coin.ethereum
? _DesktopWalletCard( ? _DesktopWalletCard(
walletId: walletIds[index], key: Key(
"${data[index].item1.walletName}_${data[index].item2.map((e) => e.address).join()}"),
data: data[index],
navigatorState: widget.navigatorState, navigatorState: widget.navigatorState,
) )
: RoundedWhiteContainer( : RoundedWhiteContainer(
@ -152,7 +249,7 @@ class _DesktopCoinWalletsDialogState
.extension<StackColors>()! .extension<StackColors>()!
.backgroundAppBar, .backgroundAppBar,
child: WalletSheetCard( child: WalletSheetCard(
walletId: walletIds[index], walletId: data[index].item1.walletId,
popPrevious: true, popPrevious: true,
desktopNavigatorState: widget.navigatorState, desktopNavigatorState: widget.navigatorState,
), ),
@ -160,48 +257,39 @@ class _DesktopCoinWalletsDialogState
separatorBuilder: (_, __) => const SizedBox( separatorBuilder: (_, __) => const SizedBox(
height: 10, height: 10,
), ),
itemCount: walletIds.length, itemCount: data.length,
), );
}),
), ),
], ],
); );
} }
} }
class _DesktopWalletCard extends ConsumerStatefulWidget { class _DesktopWalletCard extends StatefulWidget {
const _DesktopWalletCard({ const _DesktopWalletCard({
Key? key, Key? key,
required this.walletId, required this.data,
required this.navigatorState, required this.navigatorState,
}) : super(key: key); }) : super(key: key);
final String walletId; final Tuple2<Manager, List<EthContract>> data;
final NavigatorState navigatorState; final NavigatorState navigatorState;
@override @override
ConsumerState<_DesktopWalletCard> createState() => _DesktopWalletCardState(); State<_DesktopWalletCard> createState() => _DesktopWalletCardState();
} }
class _DesktopWalletCardState extends ConsumerState<_DesktopWalletCard> { class _DesktopWalletCardState extends State<_DesktopWalletCard> {
final expandableController = ExpandableController(); final expandableController = ExpandableController();
final rotateIconController = RotateIconController(); final rotateIconController = RotateIconController();
final List<String> tokenContractAddresses = []; final List<String> tokenContractAddresses = [];
late final Coin coin;
@override @override
void initState() { void initState() {
coin = ref if (widget.data.item1.hasTokenSupport) {
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.coin;
if (coin == Coin.ethereum) {
tokenContractAddresses.addAll( tokenContractAddresses.addAll(
(ref widget.data.item2.map((e) => e.address),
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as EthereumWallet)
.getWalletTokenContractAddresses(),
); );
} }
@ -214,6 +302,9 @@ class _DesktopWalletCardState extends ConsumerState<_DesktopWalletCard> {
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
borderColor: Theme.of(context).extension<StackColors>()!.backgroundAppBar, borderColor: Theme.of(context).extension<StackColors>()!.backgroundAppBar,
child: Expandable( child: Expandable(
initialState: widget.data.item1.hasTokenSupport
? ExpandableState.expanded
: ExpandableState.collapsed,
controller: expandableController, controller: expandableController,
expandOverride: () {}, expandOverride: () {},
header: Padding( header: Padding(
@ -231,19 +322,13 @@ class _DesktopWalletCardState extends ConsumerState<_DesktopWalletCard> {
child: Row( child: Row(
children: [ children: [
WalletInfoCoinIcon( WalletInfoCoinIcon(
coin: coin, coin: widget.data.item1.coin,
), ),
const SizedBox( const SizedBox(
width: 12, width: 12,
), ),
Text( Text(
ref.watch( widget.data.item1.walletName,
walletsChangeNotifierProvider.select(
(value) => value
.getManager(widget.walletId)
.walletName,
),
),
style: STextStyles.desktopTextExtraSmall(context) style: STextStyles.desktopTextExtraSmall(context)
.copyWith( .copyWith(
color: Theme.of(context) color: Theme.of(context)
@ -257,7 +342,7 @@ class _DesktopWalletCardState extends ConsumerState<_DesktopWalletCard> {
Expanded( Expanded(
flex: 4, flex: 4,
child: WalletInfoRowBalance( child: WalletInfoRowBalance(
walletId: widget.walletId, walletId: widget.data.item1.walletId,
), ),
), ),
], ],
@ -290,10 +375,13 @@ class _DesktopWalletCardState extends ConsumerState<_DesktopWalletCard> {
}, },
child: RotateIcon( child: RotateIcon(
controller: rotateIconController, controller: rotateIconController,
icon: SvgPicture.asset( icon: RotatedBox(
quarterTurns: 2,
child: SvgPicture.asset(
Assets.svg.chevronDown, Assets.svg.chevronDown,
width: 14, width: 14,
), ),
),
curve: Curves.easeInOut, curve: Curves.easeInOut,
), ),
), ),
@ -318,7 +406,7 @@ class _DesktopWalletCardState extends ConsumerState<_DesktopWalletCard> {
bottom: 14, bottom: 14,
), ),
child: WalletSheetCard( child: WalletSheetCard(
walletId: widget.walletId, walletId: widget.data.item1.walletId,
popPrevious: true, popPrevious: true,
desktopNavigatorState: widget.navigatorState, desktopNavigatorState: widget.navigatorState,
), ),
@ -332,7 +420,7 @@ class _DesktopWalletCardState extends ConsumerState<_DesktopWalletCard> {
bottom: 14, bottom: 14,
), ),
child: WalletSheetCard( child: WalletSheetCard(
walletId: widget.walletId, walletId: widget.data.item1.walletId,
contractAddress: e, contractAddress: e,
popPrevious: true, popPrevious: true,
desktopNavigatorState: widget.navigatorState, desktopNavigatorState: widget.navigatorState,

View file

@ -23,6 +23,7 @@ class Expandable extends StatefulWidget {
this.controller, this.controller,
this.expandOverride, this.expandOverride,
this.curve = Curves.easeInOut, this.curve = Curves.easeInOut,
this.initialState = ExpandableState.collapsed,
}) : super(key: key); }) : super(key: key);
final Widget header; final Widget header;
@ -35,6 +36,7 @@ class Expandable extends StatefulWidget {
final ExpandableController? controller; final ExpandableController? controller;
final VoidCallback? expandOverride; final VoidCallback? expandOverride;
final Curve curve; final Curve curve;
final ExpandableState initialState;
@override @override
State<Expandable> createState() => _ExpandableState(); State<Expandable> createState() => _ExpandableState();
@ -46,7 +48,7 @@ class _ExpandableState extends State<Expandable> with TickerProviderStateMixin {
late final Duration duration; late final Duration duration;
late final ExpandableController? controller; late final ExpandableController? controller;
ExpandableState _toggleState = ExpandableState.collapsed; late ExpandableState _toggleState;
Future<void> toggle() async { Future<void> toggle() async {
if (animation.isDismissed) { if (animation.isDismissed) {
@ -65,6 +67,7 @@ class _ExpandableState extends State<Expandable> with TickerProviderStateMixin {
@override @override
void initState() { void initState() {
_toggleState = widget.initialState;
controller = widget.controller; controller = widget.controller;
controller?.toggle = toggle; controller?.toggle = toggle;
@ -76,8 +79,13 @@ class _ExpandableState extends State<Expandable> with TickerProviderStateMixin {
vsync: this, vsync: this,
duration: duration, duration: duration,
); );
final tween = _toggleState == ExpandableState.collapsed
? Tween<double>(begin: 0.0, end: 1.0)
: Tween<double>(begin: 1.0, end: 0.0);
animation = widget.animation ?? animation = widget.animation ??
Tween<double>(begin: 0.0, end: 1.0).animate( tween.animate(
CurvedAnimation( CurvedAnimation(
curve: widget.curve, curve: widget.curve,
parent: animationController, parent: animationController,