mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
desktop wallets search
This commit is contained in:
parent
51211b34f5
commit
bb85defaea
2 changed files with 156 additions and 60 deletions
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue