Merge pull request #601 from cake-tech/CW-159-Filter-address-book-by-type

[CW-159] filter contacts and wallets by type
This commit is contained in:
Omar Hatem 2022-12-08 13:51:01 +02:00 committed by GitHub
commit f3b89a2c7f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 61 additions and 105 deletions

View file

@ -160,6 +160,7 @@ import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart';
import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart';
import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cw_core/crypto_currency.dart';
final getIt = GetIt.instance; final getIt = GetIt.instance;
@ -472,12 +473,11 @@ Future setup(
(ContactRecord? contact, _) => (ContactRecord? contact, _) =>
ContactViewModel(_contactSource, contact: contact)); ContactViewModel(_contactSource, contact: contact));
getIt.registerFactory( getIt.registerFactoryParam<ContactListViewModel, CryptoCurrency?, void>(
() => ContactListViewModel(_contactSource, _walletInfoSource)); (CryptoCurrency? cur, _) => ContactListViewModel(_contactSource, _walletInfoSource, cur));
getIt.registerFactoryParam<ContactListPage, bool, void>( getIt.registerFactoryParam<ContactListPage, CryptoCurrency?, void>((CryptoCurrency? cur, _)
(bool isEditable, _) => ContactListPage(getIt.get<ContactListViewModel>(), => ContactListPage(getIt.get<ContactListViewModel>(param1: cur)));
isEditable: isEditable));
getIt.registerFactoryParam<ContactPage, ContactRecord?, void>( getIt.registerFactoryParam<ContactPage, ContactRecord?, void>(
(ContactRecord? contact, _) => (ContactRecord? contact, _) =>

View file

@ -80,6 +80,7 @@ import 'package:cake_wallet/src/screens/ionia/ionia.dart';
import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart';
import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart';
import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart';
import 'package:cw_core/crypto_currency.dart';
late RouteSettings currentRouteSettings; late RouteSettings currentRouteSettings;
@ -320,11 +321,13 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.addressBook: case Routes.addressBook:
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
builder: (_) => getIt.get<ContactListPage>(param1: true)); builder: (_) =>
getIt.get<ContactListPage>());
case Routes.pickerAddressBook: case Routes.pickerAddressBook:
final selectedCurrency = settings.arguments as CryptoCurrency;
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
builder: (_) => getIt.get<ContactListPage>(param1: false)); builder: (_) => getIt.get<ContactListPage>(param1: selectedCurrency));
case Routes.addressBookAddContact: case Routes.addressBookAddContact:
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(

View file

@ -9,24 +9,22 @@ import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
import 'package:cake_wallet/src/widgets/collapsible_standart_list.dart'; import 'package:cake_wallet/src/widgets/collapsible_standart_list.dart';
class ContactListPage extends BasePage { class ContactListPage extends BasePage {
ContactListPage(this.contactListViewModel, {this.isEditable = true}); ContactListPage(this.contactListViewModel);
final ContactListViewModel contactListViewModel; final ContactListViewModel contactListViewModel;
final bool isEditable;
@override @override
String get title => S.current.address_book; String get title => S.current.address_book;
@override @override
Widget? trailing(BuildContext context) { Widget? trailing(BuildContext context) {
if (!isEditable) { if (!contactListViewModel.isEditable) {
return null; return null;
} }
@ -60,11 +58,14 @@ class ContactListPage extends BasePage {
@override @override
Widget body(BuildContext context) { Widget body(BuildContext context) {
return Container( return Container(
padding: EdgeInsets.only(top: 20.0, bottom: 20.0), padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
child: Observer( child: Observer(
builder: (_) { builder: (_) {
return CollapsibleSectionList( final contacts = contactListViewModel.contactsToShow;
final walletContacts = contactListViewModel.walletContactsToShow;
return CollapsibleSectionList(
context: context, context: context,
sectionCount: 2, sectionCount: 2,
themeColor: Theme.of(context).primaryTextTheme.headline6!.color!, themeColor: Theme.of(context).primaryTextTheme.headline6!.color!,
@ -82,35 +83,37 @@ class ContactListPage extends BasePage {
child: Text(title, style: TextStyle(fontSize: 36))); child: Text(title, style: TextStyle(fontSize: 36)));
}, },
itemCounter: (int sectionIndex) => sectionIndex == 0 itemCounter: (int sectionIndex) => sectionIndex == 0
? contactListViewModel.walletContacts.length ? walletContacts.length
: contactListViewModel.contacts.length, : contacts.length,
itemBuilder: (_, sectionIndex, index) { itemBuilder: (_, sectionIndex, index) {
if (sectionIndex == 0) { if (sectionIndex == 0) {
final walletInfo = contactListViewModel.walletContacts[index]; final walletInfo = walletContacts[index];
return generateRaw(context, walletInfo); return generateRaw(context, walletInfo);
} }
final contact = contactListViewModel.contacts[index]; final contact = contacts[index];
final content = generateRaw(context, contact); final content = generateRaw(context, contact);
return !isEditable return contactListViewModel.isEditable
? content ? Slidable(
: Slidable(
key: Key('${contact.key}'), key: Key('${contact.key}'),
endActionPane: _actionPane(context, contact), endActionPane: _actionPane(context, contact),
child: content, child: content,
); )
: content;
}, },
); );})
}, );
));
} }
Widget generateRaw(BuildContext context, ContactBase contact) { Widget generateRaw(BuildContext context, ContactBase contact) {
final image = _getCurrencyImage(contact.type); final image = contact.type.iconPath;
final currencyIcon = image != null ? Image.asset(image, height: 24, width: 24)
: const SizedBox(height: 24, width: 24);
return GestureDetector( return GestureDetector(
onTap: () async { onTap: () async {
if (!isEditable) { if (!contactListViewModel.isEditable) {
Navigator.of(context).pop(contact); Navigator.of(context).pop(contact);
return; return;
} }
@ -131,12 +134,10 @@ class ContactListPage extends BasePage {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[ children: <Widget>[
image ?? Offstage(), currencyIcon,
Expanded( Expanded(
child: Padding( child: Padding(
padding: image != null padding: EdgeInsets.only(left: 12),
? EdgeInsets.only(left: 12)
: EdgeInsets.only(left: 0),
child: Text( child: Text(
contact.name, contact.name,
style: TextStyle( style: TextStyle(
@ -152,69 +153,6 @@ class ContactListPage extends BasePage {
); );
} }
Image? _getCurrencyImage(CryptoCurrency currency) {
Image? image;
switch (currency) {
case CryptoCurrency.xmr:
image =
Image.asset('assets/images/monero_logo.png', height: 24, width: 24);
break;
case CryptoCurrency.ada:
image = Image.asset('assets/images/ada.png', height: 24, width: 24);
break;
case CryptoCurrency.bch:
image = Image.asset('assets/images/bch.png', height: 24, width: 24);
break;
case CryptoCurrency.bnb:
image = Image.asset('assets/images/bnb.png', height: 24, width: 24);
break;
case CryptoCurrency.btc:
image = Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
break;
case CryptoCurrency.dai:
image = Image.asset('assets/images/dai.png', height: 24, width: 24);
break;
case CryptoCurrency.dash:
image = Image.asset('assets/images/dash.png', height: 24, width: 24);
break;
case CryptoCurrency.eos:
image = Image.asset('assets/images/eos.png', height: 24, width: 24);
break;
case CryptoCurrency.eth:
image = Image.asset('assets/images/eth.png', height: 24, width: 24);
break;
case CryptoCurrency.ltc:
image =
Image.asset('assets/images/litecoin.png', height: 24, width: 24);
break;
case CryptoCurrency.nano:
image = Image.asset('assets/images/nano.png', height: 24, width: 24);
break;
case CryptoCurrency.trx:
image = Image.asset('assets/images/trx.png', height: 24, width: 24);
break;
case CryptoCurrency.usdt:
image = Image.asset('assets/images/usdt.png', height: 24, width: 24);
break;
case CryptoCurrency.usdterc20:
image = Image.asset('assets/images/usdterc.png', height: 24, width: 24);
break;
case CryptoCurrency.xlm:
image = Image.asset('assets/images/xlm.png', height: 24, width: 24);
break;
case CryptoCurrency.xrp:
image = Image.asset('assets/images/xrp.png', height: 24, width: 24);
break;
case CryptoCurrency.xhv:
image = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);
break;
default:
image = null;
}
return image;
}
Future<bool> showAlertDialog(BuildContext context) async { Future<bool> showAlertDialog(BuildContext context) async {
return await showPopUp<bool>( return await showPopUp<bool>(
context: context, context: context,

View file

@ -395,7 +395,8 @@ class ExchangeCardState extends State<ExchangeCard> {
buttonColor: widget.addressButtonsColor, buttonColor: widget.addressButtonsColor,
validator: widget.addressTextFieldValidator, validator: widget.addressTextFieldValidator,
onPushPasteButton: widget.onPushPasteButton, onPushPasteButton: widget.onPushPasteButton,
onPushAddressBookButton: widget.onPushAddressBookButton onPushAddressBookButton: widget.onPushAddressBookButton,
selectedCurrency: _selectedCurrency
), ),
) )

View file

@ -154,6 +154,7 @@ class SendCardState extends State<SendCard>
await output.fetchParsedAddress(context); await output.fetchParsedAddress(context);
}, },
validator: validator, validator: validator,
selectedCurrency: sendViewModel.currency,
); );
}), }),
if (output.isParsedAddress) Padding( if (output.isParsedAddress) Padding(

View file

@ -4,6 +4,7 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:cake_wallet/entities/qr_scanner.dart';
import 'package:cake_wallet/entities/contact_base.dart'; import 'package:cake_wallet/entities/contact_base.dart';
import 'package:cw_core/crypto_currency.dart';
enum AddressTextFieldOption { paste, qrCode, addressBook } enum AddressTextFieldOption { paste, qrCode, addressBook }
@ -26,7 +27,8 @@ class AddressTextField extends StatelessWidget {
this.hintStyle, this.hintStyle,
this.validator, this.validator,
this.onPushPasteButton, this.onPushPasteButton,
this.onPushAddressBookButton}); this.onPushAddressBookButton,
this.selectedCurrency});
static const prefixIconWidth = 34.0; static const prefixIconWidth = 34.0;
static const prefixIconHeight = 34.0; static const prefixIconHeight = 34.0;
@ -47,6 +49,7 @@ class AddressTextField extends StatelessWidget {
final FocusNode? focusNode; final FocusNode? focusNode;
final Function(BuildContext context)? onPushPasteButton; final Function(BuildContext context)? onPushPasteButton;
final Function(BuildContext context)? onPushAddressBookButton; final Function(BuildContext context)? onPushAddressBookButton;
final CryptoCurrency? selectedCurrency;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -207,7 +210,7 @@ class AddressTextField extends StatelessWidget {
Future<void> _presetAddressBookPicker(BuildContext context) async { Future<void> _presetAddressBookPicker(BuildContext context) async {
final contact = await Navigator.of(context, rootNavigator: true) final contact = await Navigator.of(context, rootNavigator: true)
.pushNamed(Routes.pickerAddressBook); .pushNamed(Routes.pickerAddressBook,arguments: selectedCurrency);
if (contact is ContactBase && contact.address != null) { if (contact is ContactBase && contact.address != null) {
controller?.text = contact.address; controller?.text = contact.address;

View file

@ -7,27 +7,26 @@ import 'package:mobx/mobx.dart';
import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/contact_record.dart';
import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/entities/contact.dart';
import 'package:cake_wallet/utils/mobx.dart'; import 'package:cake_wallet/utils/mobx.dart';
import 'package:cw_core/crypto_currency.dart';
part 'contact_list_view_model.g.dart'; part 'contact_list_view_model.g.dart';
class ContactListViewModel = ContactListViewModelBase class ContactListViewModel = ContactListViewModelBase with _$ContactListViewModel;
with _$ContactListViewModel;
abstract class ContactListViewModelBase with Store { abstract class ContactListViewModelBase with Store {
ContactListViewModelBase(this.contactSource, this.walletInfoSource) ContactListViewModelBase(this.contactSource, this.walletInfoSource, this._currency)
: contacts = ObservableList<ContactRecord>(), : contacts = ObservableList<ContactRecord>(),
walletContacts = [] { walletContacts = [] {
walletInfoSource.values.forEach((info) { walletInfoSource.values.forEach((info) {
if (info.addresses?.isNotEmpty ?? false) { if (info.addresses?.isNotEmpty ?? false) {
info.addresses?.forEach((address, label) { info.addresses?.forEach((address, label) {
final name = label.isNotEmpty final name = label.isNotEmpty ? info.name + ' ($label)' : info.name;
? info.name + ' ($label)'
: info.name;
walletContacts.add(WalletContact( walletContacts.add(WalletContact(
address, address,
name, name,
walletTypeToCryptoCurrency(info.type))); walletTypeToCryptoCurrency(info.type),
));
}); });
} }
}); });
@ -41,7 +40,18 @@ abstract class ContactListViewModelBase with Store {
final Box<WalletInfo> walletInfoSource; final Box<WalletInfo> walletInfoSource;
final ObservableList<ContactRecord> contacts; final ObservableList<ContactRecord> contacts;
final List<WalletContact> walletContacts; final List<WalletContact> walletContacts;
final CryptoCurrency? _currency;
StreamSubscription<BoxEvent>? _subscription; StreamSubscription<BoxEvent>? _subscription;
bool get isEditable => _currency == null;
Future<void> delete(ContactRecord contact) async => contact.original.delete(); Future<void> delete(ContactRecord contact) async => contact.original.delete();
@computed
List<ContactRecord> get contactsToShow =>
contacts.where((element) => _currency == null || element.type == _currency).toList();
@computed
List<WalletContact> get walletContactsToShow =>
walletContacts.where((element) => _currency == null || element.type == _currency).toList();
} }