Merge pull request #536 from cypherstack/address_book_isar

Address book isar
This commit is contained in:
julian-CStack 2023-05-15 15:29:28 -06:00 committed by GitHub
commit 8446653a75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 2270 additions and 485 deletions

View file

@ -41,7 +41,6 @@ class DB {
String boxNameUsedSerialsCache({required Coin coin}) => String boxNameUsedSerialsCache({required Coin coin}) =>
"${coin.name}_usedSerialsCache"; "${coin.name}_usedSerialsCache";
Box<dynamic>? _boxAddressBook;
Box<String>? _boxDebugInfo; Box<String>? _boxDebugInfo;
Box<NodeModel>? _boxNodeModels; Box<NodeModel>? _boxNodeModels;
Box<NodeModel>? _boxPrimaryNodes; Box<NodeModel>? _boxPrimaryNodes;
@ -100,7 +99,6 @@ class DB {
_boxPrefs = await Hive.openBox<dynamic>(boxNamePrefs); _boxPrefs = await Hive.openBox<dynamic>(boxNamePrefs);
} }
_boxAddressBook = await Hive.openBox<dynamic>(boxNameAddressBook);
_boxDebugInfo = await Hive.openBox<String>(boxNameDebugInfo); _boxDebugInfo = await Hive.openBox<String>(boxNameDebugInfo);
if (Hive.isBoxOpen(boxNameNodeModels)) { if (Hive.isBoxOpen(boxNameNodeModels)) {

View file

@ -3,6 +3,7 @@ import 'package:flutter_native_splash/cli_commands.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:stackwallet/exceptions/main_db/main_db_exception.dart'; import 'package:stackwallet/exceptions/main_db/main_db_exception.dart';
import 'package:stackwallet/models/isar/models/block_explorer.dart'; import 'package:stackwallet/models/isar/models/block_explorer.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/isar/stack_theme.dart'; import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/amount/amount.dart';
@ -37,6 +38,7 @@ class MainDB {
EthContractSchema, EthContractSchema,
TransactionBlockExplorerSchema, TransactionBlockExplorerSchema,
StackThemeSchema, StackThemeSchema,
ContactEntrySchema,
], ],
directory: (await StackFileSystem.applicationIsarDirectory()).path, directory: (await StackFileSystem.applicationIsarDirectory()).path,
// inspector: kDebugMode, // inspector: kDebugMode,
@ -47,6 +49,45 @@ class MainDB {
return true; return true;
} }
// contact entries
List<ContactEntry> getContactEntries(){
return isar.contactEntrys.where().findAllSync();
}
Future<bool> deleteContactEntry({required String id}) {
try {
return isar.writeTxn(() async {
await isar.contactEntrys.deleteByCustomId(id);
return true;
});
} catch (e) {
throw MainDBException("failed deleteContactEntry: $id", e);
}
}
Future<bool> isContactEntryExists({required String id}) async {
return isar.contactEntrys
.where()
.customIdEqualTo(id)
.count()
.then((value) => value > 0);
}
ContactEntry? getContactEntry({required String id}) {
return isar.contactEntrys.where().customIdEqualTo(id).findFirstSync();
}
Future<bool> putContactEntry({required ContactEntry contactEntry}) async {
try {
return await isar.writeTxn(() async {
await isar.contactEntrys.put(contactEntry);
return true;
});
} catch (e) {
throw MainDBException("failed putContactEntry: $contactEntry", e);
}
}
// tx block explorers // tx block explorers
TransactionBlockExplorer? getTransactionBlockExplorer({required Coin coin}) { TransactionBlockExplorer? getTransactionBlockExplorer({required Coin coin}) {
return isar.transactionBlockExplorers return isar.transactionBlockExplorers

View file

@ -162,7 +162,7 @@ void main() async {
int dbVersion = DB.instance.get<dynamic>( int dbVersion = DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ?? boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
0; 0;
if (dbVersion < Constants.currentHiveDbVersion) { if (dbVersion < Constants.currentDataVersion) {
try { try {
await DbVersionMigrator().migrate( await DbVersionMigrator().migrate(
dbVersion, dbVersion,

View file

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:stackwallet/models/contact_address_entry.dart'; import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
@Deprecated("Use lib/models/isar/models/contact_entry.dart instead")
class Contact { class Contact {
final String? emojiChar; final String? emojiChar;
final String name; final String name;

View file

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
@Deprecated("Use lib/models/isar/models/contact_entry.dart instead")
class ContactAddressEntry { class ContactAddressEntry {
final Coin coin; final Coin coin;
final String address; final String address;

View file

@ -1,5 +1,5 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:stackwallet/models/contact_address_entry.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/utilities/address_utils.dart'; import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -57,7 +57,7 @@ class AddressEntryData extends ChangeNotifier {
} }
bool get isValidAddress { bool get isValidAddress {
if ( coin == null) { if (coin == null) {
return true; return true;
} }
if (_address == null) { if (_address == null) {
@ -67,8 +67,11 @@ class AddressEntryData extends ChangeNotifier {
} }
ContactAddressEntry buildAddressEntry() { ContactAddressEntry buildAddressEntry() {
return ContactAddressEntry( return ContactAddressEntry()
coin: coin!, address: address!, label: addressLabel!); ..coinName = coin!.name
..address = address!
..other = null
..label = addressLabel!;
} }
@override @override

View file

@ -0,0 +1,108 @@
import 'package:isar/isar.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
part 'contact_entry.g.dart';
@collection
class ContactEntry {
ContactEntry({
this.emojiChar,
required this.name,
required this.addresses,
required this.isFavorite,
required this.customId,
});
Id id = Isar.autoIncrement;
late final String? emojiChar;
late final String name;
late final List<ContactAddressEntry> addresses;
late final bool isFavorite;
@Index(unique: true, replace: true)
late final String customId;
ContactEntry copyWith({
bool shouldCopyEmojiWithNull = false,
String? emojiChar,
String? name,
List<ContactAddressEntry>? addresses,
bool? isFavorite,
}) {
List<ContactAddressEntry> _addresses = [];
if (addresses == null) {
for (var e in this.addresses) {
_addresses.add(e.copyWith());
}
} else {
for (var e in addresses) {
_addresses.add(e.copyWith());
}
}
String? newEmoji;
if (shouldCopyEmojiWithNull) {
newEmoji = emojiChar;
} else {
newEmoji = emojiChar ?? this.emojiChar;
}
return ContactEntry(
emojiChar: newEmoji,
name: name ?? this.name,
addresses: _addresses,
isFavorite: isFavorite ?? this.isFavorite,
customId: customId,
);
}
Map<String, dynamic> toMap() {
return {
"emoji": emojiChar,
"name": name,
"addresses": addresses.map((e) => e.toMap()).toList(),
"id": customId,
"isFavorite": isFavorite,
};
}
}
@embedded
class ContactAddressEntry {
late final String coinName;
late final String address;
late final String label;
late final String? other;
@ignore
Coin get coin => Coin.values.byName(coinName);
ContactAddressEntry();
ContactAddressEntry copyWith({
Coin? coin,
String? address,
String? label,
String? other,
}) {
return ContactAddressEntry()
..coinName = coin?.name ?? coinName
..address = address ?? this.address
..label = label ?? this.label
..other = other ?? this.other;
}
Map<String, String> toMap() {
return {
"label": label,
"address": address,
"coin": coin.name,
"other": other ?? "",
};
}
@override
String toString() {
return "AddressBookEntry: ${toMap()}";
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,8 +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/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart'; import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart'; import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart';
@ -73,19 +72,18 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
final managers = ref.read(walletsChangeNotifierProvider).managers; final managers = ref.read(walletsChangeNotifierProvider).managers;
for (final manager in managers) { for (final manager in managers) {
addresses.add( addresses.add(
ContactAddressEntry( ContactAddressEntry()
coin: manager.coin, ..coinName = manager.coin.name
address: await manager.currentReceivingAddress, ..address = await manager.currentReceivingAddress
label: "Current Receiving", ..label = "Current Receiving"
other: manager.walletName, ..other = manager.walletName,
),
); );
} }
final self = Contact( final self = ContactEntry(
name: "My Stack", name: "My Stack",
addresses: addresses, addresses: addresses,
isFavorite: true, isFavorite: true,
id: "default", customId: "default",
); );
await ref.read(addressBookServiceProvider).editContact(self); await ref.read(addressBookServiceProvider).editContact(self);
}); });
@ -306,8 +304,8 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
.where((element) => element.isFavorite) .where((element) => element.isFavorite)
.map( .map(
(e) => AddressBookCard( (e) => AddressBookCard(
key: Key("favContactCard_${e.id}_key"), key: Key("favContactCard_${e.customId}_key"),
contactId: e.id, contactId: e.customId,
), ),
), ),
], ],
@ -352,8 +350,9 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
.matches(widget.filterTerm ?? _searchTerm, e)) .matches(widget.filterTerm ?? _searchTerm, e))
.map( .map(
(e) => AddressBookCard( (e) => AddressBookCard(
key: Key("desktopContactCard_${e.id}_key"), key:
contactId: e.id, Key("desktopContactCard_${e.customId}_key"),
contactId: e.customId,
), ),
), ),
], ],

View file

@ -2,8 +2,7 @@ import 'package:emojis/emoji.dart';
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/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart'; import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart'; import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
@ -28,6 +27,7 @@ import 'package:stackwallet/widgets/emoji_select_sheet.dart';
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart';
import 'package:uuid/uuid.dart';
class AddAddressBookEntryView extends ConsumerStatefulWidget { class AddAddressBookEntryView extends ConsumerStatefulWidget {
const AddAddressBookEntryView({ const AddAddressBookEntryView({
@ -688,11 +688,12 @@ class _AddAddressBookEntryViewState
forms[i].id)) forms[i].id))
.buildAddressEntry()); .buildAddressEntry());
} }
Contact contact = Contact( ContactEntry contact = ContactEntry(
emojiChar: _selectedEmoji?.char, emojiChar: _selectedEmoji?.char,
name: nameController.text, name: nameController.text,
addresses: entries, addresses: entries,
isFavorite: _isFavorite, isFavorite: _isFavorite,
customId: const Uuid().v1(),
); );
if (await ref if (await ref

View file

@ -1,8 +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/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart'; import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart'; import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
@ -208,7 +207,7 @@ class _AddNewContactAddressViewState
.read(addressEntryDataProvider(0)) .read(addressEntryDataProvider(0))
.buildAddressEntry()); .buildAddressEntry());
Contact editedContact = ContactEntry editedContact =
contact.copyWith(addresses: entries); contact.copyWith(addresses: entries);
if (await ref if (await ref

View file

@ -199,7 +199,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
onPressed: () { onPressed: () {
ref ref
.read(addressBookServiceProvider) .read(addressBookServiceProvider)
.removeContact(_contact.id); .removeContact(_contact.customId);
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).pop(); Navigator.of(context).pop();
showFloatingFlushBar( showFloatingFlushBar(

View file

@ -1,8 +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/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart'; import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart'; import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
@ -49,7 +48,7 @@ class _EditContactAddressViewState
late final BarcodeScannerInterface barcodeScanner; late final BarcodeScannerInterface barcodeScanner;
late final ClipboardInterface clipboard; late final ClipboardInterface clipboard;
Future<void> save(Contact contact) async { Future<void> save(ContactEntry contact) async {
if (FocusScope.of(context).hasFocus) { if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
await Future<void>.delayed( await Future<void>.delayed(
@ -73,7 +72,7 @@ class _EditContactAddressViewState
entries.insert(index, editedEntry); entries.insert(index, editedEntry);
Contact editedContact = contact.copyWith(addresses: entries); ContactEntry editedContact = contact.copyWith(addresses: entries);
if (await ref.read(addressBookServiceProvider).editContact(editedContact)) { if (await ref.read(addressBookServiceProvider).editContact(editedContact)) {
if (mounted) { if (mounted) {
@ -226,7 +225,8 @@ class _EditContactAddressViewState
); );
_addresses.remove(entry); _addresses.remove(entry);
Contact editedContact = contact.copyWith(addresses: _addresses); ContactEntry editedContact =
contact.copyWith(addresses: _addresses);
if (await ref if (await ref
.read(addressBookServiceProvider) .read(addressBookServiceProvider)
.editContact(editedContact)) { .editContact(editedContact)) {

View file

@ -5,10 +5,9 @@ import 'dart:typed_data';
import 'package:stack_wallet_backup/stack_wallet_backup.dart'; import 'package:stack_wallet_backup/stack_wallet_backup.dart';
import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'; import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/models/stack_restoring_ui_state.dart'; import 'package:stackwallet/models/stack_restoring_ui_state.dart';
import 'package:stackwallet/models/trade_wallet_lookup.dart'; import 'package:stackwallet/models/trade_wallet_lookup.dart';
@ -266,7 +265,7 @@ abstract class SWB {
); );
AddressBookService addressBookService = AddressBookService(); AddressBookService addressBookService = AddressBookService();
var addresses = await addressBookService.addressBookEntries; var addresses = addressBookService.contacts;
backupJson['addressBookEntries'] = backupJson['addressBookEntries'] =
addresses.map((e) => e.toMap()).toList(); addresses.map((e) => e.toMap()).toList();
@ -799,7 +798,7 @@ abstract class SWB {
// contacts // contacts
final addressBookService = AddressBookService(); final addressBookService = AddressBookService();
final allContactIds = addressBookService.contacts.map((e) => e.id); final allContactIds = addressBookService.contacts.map((e) => e.customId);
if (addressBookEntries == null) { if (addressBookEntries == null) {
// if no contacts were present before attempted restore then delete any that // if no contacts were present before attempted restore then delete any that
@ -823,21 +822,20 @@ abstract class SWB {
List<ContactAddressEntry> addresses = []; List<ContactAddressEntry> addresses = [];
for (var address in (contact['addresses'] as List<dynamic>)) { for (var address in (contact['addresses'] as List<dynamic>)) {
addresses.add( addresses.add(
ContactAddressEntry( ContactAddressEntry()
coin: Coin.values ..coinName = address['coin'] as String
.firstWhere((element) => element.name == address['coin']), ..address = address['address'] as String
address: address['address'] as String, ..label = address['label'] as String
label: address['label'] as String, ..other = address['other'] as String?,
),
); );
} }
await addressBookService.editContact( await addressBookService.editContact(
Contact( ContactEntry(
emojiChar: contact['emoji'] as String?, emojiChar: contact['emoji'] as String?,
name: contact['name'] as String, name: contact['name'] as String,
addresses: addresses, addresses: addresses,
isFavorite: contact['isFavorite'] as bool, isFavorite: contact['isFavorite'] as bool,
id: contact['id'] as String, customId: contact['id'] as String,
), ),
); );
} else { } else {
@ -1026,21 +1024,20 @@ abstract class SWB {
List<ContactAddressEntry> addresses = []; List<ContactAddressEntry> addresses = [];
for (var address in (contact['addresses'] as List<dynamic>)) { for (var address in (contact['addresses'] as List<dynamic>)) {
addresses.add( addresses.add(
ContactAddressEntry( ContactAddressEntry()
coin: Coin.values ..coinName = address['coin'] as String
.firstWhere((element) => element.name == address['coin']), ..address = address['address'] as String
address: address['address'] as String, ..label = address['label'] as String
label: address['label'] as String, ..other = address['other'] as String?,
),
); );
} }
await addressBookService.addContact( await addressBookService.addContact(
Contact( ContactEntry(
emojiChar: contact['emoji'] as String?, emojiChar: contact['emoji'] as String?,
name: contact['name'] as String, name: contact['name'] as String,
addresses: addresses, addresses: addresses,
isFavorite: contact['isFavorite'] as bool, isFavorite: contact['isFavorite'] as bool,
id: contact['id'] as String, customId: contact['id'] as String,
), ),
); );
} }

View file

@ -3,8 +3,8 @@ import 'dart:async';
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/models/contact.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/transaction_filter.dart'; import 'package:stackwallet/models/transaction_filter.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart'; import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart';
@ -120,8 +120,8 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
}).toList(); }).toList();
} }
bool _isKeywordMatch(Transaction tx, String keyword, List<Contact> contacts, bool _isKeywordMatch(Transaction tx, String keyword,
Map<String, String> notes) { List<ContactEntry> contacts, Map<String, String> notes) {
if (keyword.isEmpty) { if (keyword.isEmpty) {
return true; return true;
} }

View file

@ -1,8 +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/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart'; import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart'; import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_book_scaffold.dart'; import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_book_scaffold.dart';
@ -105,19 +104,18 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
final managers = ref.read(walletsChangeNotifierProvider).managers; final managers = ref.read(walletsChangeNotifierProvider).managers;
for (final manager in managers) { for (final manager in managers) {
addresses.add( addresses.add(
ContactAddressEntry( ContactAddressEntry()
coin: manager.coin, ..coinName = manager.coin.name
address: await manager.currentReceivingAddress, ..address = await manager.currentReceivingAddress
label: "Current Receiving", ..label = "Current Receiving"
other: manager.walletName, ..other = manager.walletName,
),
); );
} }
final self = Contact( final self = ContactEntry(
name: "My Stack", name: "My Stack",
addresses: addresses, addresses: addresses,
isFavorite: true, isFavorite: true,
id: "default", customId: "default",
); );
await ref.read(addressBookServiceProvider).editContact(self); await ref.read(addressBookServiceProvider).editContact(self);
}); });
@ -323,14 +321,14 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
.extension<StackColors>()! .extension<StackColors>()!
.accentColorDark .accentColorDark
.withOpacity( .withOpacity(
currentContactId == favorites[i].id currentContactId == favorites[i].customId
? 0.08 ? 0.08
: 0, : 0,
), ),
child: RawMaterialButton( child: RawMaterialButton(
onPressed: () { onPressed: () {
setState(() { setState(() {
currentContactId = favorites[i].id; currentContactId = favorites[i].customId;
}); });
}, },
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@ -346,8 +344,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
), ),
child: AddressBookCard( child: AddressBookCard(
key: Key( key: Key(
"favContactCard_${favorites[i].id}_key"), "favContactCard_${favorites[i].customId}_key"),
contactId: favorites[i].id, contactId: favorites[i].customId,
desktopSendFrom: false, desktopSendFrom: false,
), ),
), ),
@ -393,14 +391,16 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
.extension<StackColors>()! .extension<StackColors>()!
.accentColorDark .accentColorDark
.withOpacity( .withOpacity(
currentContactId == allContacts[i].id currentContactId ==
allContacts[i].customId
? 0.08 ? 0.08
: 0, : 0,
), ),
child: RawMaterialButton( child: RawMaterialButton(
onPressed: () { onPressed: () {
setState(() { setState(() {
currentContactId = allContacts[i].id; currentContactId =
allContacts[i].customId;
}); });
}, },
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@ -416,8 +416,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
), ),
child: AddressBookCard( child: AddressBookCard(
key: Key( key: Key(
"favContactCard_${allContacts[i].id}_key"), "favContactCard_${allContacts[i].customId}_key"),
contactId: allContacts[i].id, contactId: allContacts[i].customId,
desktopSendFrom: false, desktopSendFrom: false,
), ),
), ),

View file

@ -2,12 +2,12 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.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:stackwallet/models/contact_address_entry.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart'; import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart'; import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart'; import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart'; import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';

View file

@ -5,7 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart'; import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart';
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_card.dart'; import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_card.dart';
@ -43,7 +43,7 @@ class DesktopContactDetails extends ConsumerStatefulWidget {
class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> { class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
List<Tuple2<String, Transaction>> _cachedTransactions = []; List<Tuple2<String, Transaction>> _cachedTransactions = [];
bool _contactHasAddress(String address, Contact contact) { bool _contactHasAddress(String address, ContactEntry contact) {
for (final entry in contact.addresses) { for (final entry in contact.addresses) {
if (entry.address == address) { if (entry.address == address) {
return true; return true;
@ -83,7 +83,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// provider hack to prevent trying to update widget with deleted contact // provider hack to prevent trying to update widget with deleted contact
Contact? _contact; ContactEntry? _contact;
try { try {
_contact = ref.watch(addressBookServiceProvider _contact = ref.watch(addressBookServiceProvider
.select((value) => value.getContactById(widget.contactId))); .select((value) => value.getContactById(widget.contactId)));
@ -118,7 +118,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
.textFieldDefaultBG, .textFieldDefaultBG,
borderRadius: BorderRadius.circular(32), borderRadius: BorderRadius.circular(32),
), ),
child: contact.id == "default" child: contact.customId == "default"
? Center( ? Center(
child: SvgPicture.file( child: SvgPicture.file(
File( File(
@ -162,7 +162,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
barrierColor: Colors.transparent, barrierColor: Colors.transparent,
builder: (context) { builder: (context) {
return DesktopContactOptionsMenuPopup( return DesktopContactOptionsMenuPopup(
contactId: contact.id, contactId: contact.customId,
); );
}, },
); );
@ -264,7 +264,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
padding: const EdgeInsets.all(18), padding: const EdgeInsets.all(18),
child: DesktopAddressCard( child: DesktopAddressCard(
entry: contact.addresses[i], entry: contact.addresses[i],
contactId: contact.id, contactId: contact.customId,
), ),
), ),
], ],

View file

@ -147,7 +147,7 @@ class _DesktopContactOptionsMenuPopupState
onPressed: () { onPressed: () {
ref ref
.read(addressBookServiceProvider) .read(addressBookServiceProvider)
.removeContact(contact.id); .removeContact(contact.customId);
Navigator.of(context).pop(); Navigator.of(context).pop();
showFloatingFlushBar( showFloatingFlushBar(
type: FlushBarType.success, type: FlushBarType.success,

View file

@ -1,7 +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/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/stack_colors.dart';
@ -34,7 +34,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
String _searchTerm = ""; String _searchTerm = "";
int _compareContactFavorite(Contact a, Contact b) { int _compareContactFavorite(ContactEntry a, ContactEntry b) {
if (a.isFavorite && b.isFavorite) { if (a.isFavorite && b.isFavorite) {
return 0; return 0;
} else if (a.isFavorite) { } else if (a.isFavorite) {
@ -44,8 +44,8 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
} }
} }
List<Contact> pullOutFavorites(List<Contact> contacts) { List<ContactEntry> pullOutFavorites(List<ContactEntry> contacts) {
final List<Contact> favorites = []; final List<ContactEntry> favorites = [];
contacts.removeWhere((contact) { contacts.removeWhere((contact) {
if (contact.isFavorite) { if (contact.isFavorite) {
favorites.add(contact); favorites.add(contact);
@ -57,7 +57,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
return favorites; return favorites;
} }
List<Contact> filter(List<Contact> contacts, String searchTerm) { List<ContactEntry> filter(List<ContactEntry> contacts, String searchTerm) {
if (widget.coin != null) { if (widget.coin != null) {
contacts.removeWhere( contacts.removeWhere(
(e) => e.addresses.where((a) => a.coin == widget.coin!).isEmpty); (e) => e.addresses.where((a) => a.coin == widget.coin!).isEmpty);
@ -75,7 +75,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
return contacts; return contacts;
} }
bool _matches(String term, Contact contact) { bool _matches(String term, ContactEntry contact) {
final text = term.toLowerCase(); final text = term.toLowerCase();
if (contact.name.toLowerCase().contains(text)) { if (contact.name.toLowerCase().contains(text)) {
return true; return true;
@ -191,7 +191,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
), ),
child: Consumer( child: Consumer(
builder: (context, ref, _) { builder: (context, ref, _) {
List<Contact> contacts = ref List<ContactEntry> contacts = ref
.watch(addressBookServiceProvider .watch(addressBookServiceProvider
.select((value) => value.contacts)) .select((value) => value.contacts))
.toList(); .toList();
@ -228,7 +228,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
), ),
); );
} else if (index < favorites.length + 1) { } else if (index < favorites.length + 1) {
final id = favorites[index - 1].id; final id = favorites[index - 1].customId;
return ContactListItem( return ContactListItem(
key: Key("contactContactListItem_${id}_key"), key: Key("contactContactListItem_${id}_key"),
contactId: id, contactId: id,
@ -248,7 +248,8 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
), ),
); );
} else { } else {
final id = contacts[index - favorites.length - 2].id; final id =
contacts[index - favorites.length - 2].customId;
return ContactListItem( return ContactListItem(
key: Key("contactContactListItem_${id}_key"), key: Key("contactContactListItem_${id}_key"),
contactId: id, contactId: id,

View file

@ -55,7 +55,7 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
int dbVersion = DB.instance.get<dynamic>( int dbVersion = DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ?? boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
0; 0;
if (dbVersion < Constants.currentHiveDbVersion) { if (dbVersion < Constants.currentDataVersion) {
try { try {
await DbVersionMigrator().migrate( await DbVersionMigrator().migrate(
dbVersion, dbVersion,

View file

@ -5,7 +5,6 @@ import 'package:isar/isar.dart';
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.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/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart';
import 'package:stackwallet/models/buy/response_objects/quote.dart'; import 'package:stackwallet/models/buy/response_objects/quote.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart'; import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart'; import 'package:stackwallet/models/isar/models/isar_models.dart';
@ -153,6 +152,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/widgets/choose_coin_view.dart'; import 'package:stackwallet/widgets/choose_coin_view.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
import 'models/isar/models/contact_entry.dart';
class RouteGenerator { class RouteGenerator {
static const bool useMaterialPageRoute = true; static const bool useMaterialPageRoute = true;

View file

@ -1,55 +1,33 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
class AddressBookService extends ChangeNotifier { class AddressBookService extends ChangeNotifier {
Contact getContactById(String id) { ContactEntry getContactById(String id) {
final json = DB.instance ContactEntry? contactEntry = MainDB.instance.getContactEntry(id: id);
.get<dynamic>(boxName: DB.boxNameAddressBook, key: id) as Map?; if (contactEntry == null) {
if (json == null) {
Logging.instance
.log("Attempted to get non existing contact", level: LogLevel.Fatal);
throw Exception('Contact ID "$id" not found!'); throw Exception('Contact ID "$id" not found!');
} else {
return contactEntry;
} }
return Contact.fromJson(Map<String, dynamic>.from(json));
} }
List<Contact> get contacts { List<ContactEntry> get contacts => MainDB.instance.getContactEntries();
final keys = List<String>.from(
DB.instance.keys<dynamic>(boxName: DB.boxNameAddressBook));
final _contacts = keys
.map((id) => Contact.fromJson(Map<String, dynamic>.from(DB.instance
.get<dynamic>(boxName: DB.boxNameAddressBook, key: id) as Map)))
.toList(growable: false);
_contacts
.sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()));
return _contacts;
}
Future<List<Contact>>? _addressBookEntries;
Future<List<Contact>> get addressBookEntries =>
_addressBookEntries ??= _fetchAddressBookEntries();
// Load address book contact entries
Future<List<Contact>> _fetchAddressBookEntries() async {
return contacts;
}
/// search address book entries /// search address book entries
//TODO optimize address book search? //TODO search using isar queries
Future<List<Contact>> search(String text) async { Future<List<ContactEntry>> search(String text) async {
if (text.isEmpty) return addressBookEntries; if (text.isEmpty) return contacts;
var results = (await addressBookEntries).toList(); var results = contacts.toList();
results.retainWhere((contact) => matches(text, contact)); results.retainWhere((contact) => matches(text, contact));
return results; return results;
} }
bool matches(String term, Contact contact) { bool matches(String term, ContactEntry contact) {
if (term.isEmpty) { if (term.isEmpty) {
return true; return true;
} }
@ -73,44 +51,27 @@ class AddressBookService extends ChangeNotifier {
/// ///
/// returns false if it provided [contact]'s id already exists in the database /// returns false if it provided [contact]'s id already exists in the database
/// other true if the [contact] was saved /// other true if the [contact] was saved
Future<bool> addContact(Contact contact) async { Future<bool> addContact(ContactEntry contact) async {
if (DB.instance.containsKey<dynamic>( if (await MainDB.instance.isContactEntryExists(id: contact.customId)) {
boxName: DB.boxNameAddressBook, key: contact.id)) {
return false; return false;
} } else {
await MainDB.instance.putContactEntry(contactEntry: contact);
await DB.instance.put<dynamic>( notifyListeners();
boxName: DB.boxNameAddressBook,
key: contact.id,
value: contact.toMap());
Logging.instance.log("add address book entry saved", level: LogLevel.Info);
await _refreshAddressBookEntries();
return true; return true;
} }
}
/// Edit contact /// Edit contact
Future<bool> editContact(Contact editedContact) async { Future<bool> editContact(ContactEntry editedContact) async {
// over write the contact with edited version // over write the contact with edited version
await DB.instance.put<dynamic>( await MainDB.instance.putContactEntry(contactEntry: editedContact);
boxName: DB.boxNameAddressBook, notifyListeners();
key: editedContact.id,
value: editedContact.toMap());
Logging.instance.log("edit address book entry saved", level: LogLevel.Info);
await _refreshAddressBookEntries();
return true; return true;
} }
/// Remove address book contact entry from db if it exists /// Remove address book contact entry from db if it exists
Future<void> removeContact(String id) async { Future<void> removeContact(String id) async {
await DB.instance.delete<dynamic>(key: id, boxName: DB.boxNameAddressBook); await MainDB.instance.deleteContactEntry(id: id);
await _refreshAddressBookEntries();
}
Future<void> _refreshAddressBookEntries() async {
final newAddressBookEntries = await _fetchAddressBookEntries();
_addressBookEntries = Future(() => newAddressBookEntries);
notifyListeners(); notifyListeners();
} }
} }

View file

@ -42,7 +42,7 @@ abstract class Constants {
// Enable Logger.print statements // Enable Logger.print statements
static const bool disableLogger = false; static const bool disableLogger = false;
static const int currentHiveDbVersion = 9; static const int currentDataVersion = 10;
static const int rescanV1 = 1; static const int rescanV1 = 1;

View file

@ -3,9 +3,12 @@ import 'package:isar/isar.dart';
import 'package:stackwallet/db/hive/db.dart'; import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart'; import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'; import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart'
as isar_contact;
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models; import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/models.dart'; import 'package:stackwallet/models/models.dart';
import 'package:stackwallet/models/node_model.dart'; import 'package:stackwallet/models/node_model.dart';
@ -321,6 +324,17 @@ class DbVersionMigrator with WalletDB {
// try to continue migrating // try to continue migrating
return await migrate(9, secureStore: secureStore); return await migrate(9, secureStore: secureStore);
case 9:
// migrate
await _v9();
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 10);
// try to continue migrating
return await migrate(10, secureStore: secureStore);
default: default:
// finally return // finally return
return; return;
@ -478,4 +492,50 @@ class DbVersionMigrator with WalletDB {
} }
} }
} }
Future<void> _v9() async {
final addressBookBox = await Hive.openBox<dynamic>(DB.boxNameAddressBook);
await MainDB.instance.initMainDB();
final keys = List<String>.from(addressBookBox.keys);
final contacts = keys
.map((id) => Contact.fromJson(
Map<String, dynamic>.from(
addressBookBox.get(id) as Map,
),
))
.toList(growable: false);
final List<isar_contact.ContactEntry> newContacts = [];
for (final contact in contacts) {
final List<isar_contact.ContactAddressEntry> newContactAddressEntries =
[];
for (final entry in contact.addresses) {
newContactAddressEntries.add(
isar_contact.ContactAddressEntry()
..coinName = entry.coin.name
..address = entry.address
..label = entry.label
..other = entry.other,
);
}
final newContact = isar_contact.ContactEntry(
name: contact.name,
addresses: newContactAddressEntries,
isFavorite: contact.isFavorite,
customId: contact.id,
);
newContacts.add(newContact);
}
await MainDB.instance.isar.writeTxn(() async {
await MainDB.instance.isar.contactEntrys.putAll(newContacts);
});
await addressBookBox.deleteFromDisk();
}
} }

View file

@ -3,7 +3,7 @@ import 'dart:io';
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/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart'; import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/stack_colors.dart';
@ -49,7 +49,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// provider hack to prevent trying to update widget with deleted contact // provider hack to prevent trying to update widget with deleted contact
Contact? _contact; ContactEntry? _contact;
try { try {
_contact = ref.watch(addressBookServiceProvider _contact = ref.watch(addressBookServiceProvider
.select((value) => value.getContactById(contactId))); .select((value) => value.getContactById(contactId)));
@ -82,7 +82,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
width: 32, width: 32,
height: 32, height: 32,
decoration: BoxDecoration( decoration: BoxDecoration(
color: contact.id == "default" color: contact.customId == "default"
? Theme.of(context) ? Theme.of(context)
.extension<StackColors>()! .extension<StackColors>()!
.myStackContactIconBG .myStackContactIconBG
@ -91,7 +91,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
.textFieldDefaultBG, .textFieldDefaultBG,
borderRadius: BorderRadius.circular(32), borderRadius: BorderRadius.circular(32),
), ),
child: contact.id == "default" child: contact.customId == "default"
? Center( ? Center(
child: SvgPicture.file( child: SvgPicture.file(
File( File(
@ -179,7 +179,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
useSafeArea: true, useSafeArea: true,
barrierDismissible: true, barrierDismissible: true,
builder: (_) => ContactPopUp( builder: (_) => ContactPopUp(
contactId: contact.id, contactId: contact.customId,
), ),
); );
}, },

View file

@ -1,174 +0,0 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hive/hive.dart';
import 'package:hive_test/hive_test.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/services/address_book_service.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
void main() {
group("Empty DB tests", () {
setUp(() async {
await setUpTestHive();
await Hive.openBox<dynamic>(DB.boxNameAddressBook);
});
test("get empty contacts", () {
final service = AddressBookService();
expect(service.contacts, <Contact>[]);
});
test("get empty addressBookEntries", () async {
final service = AddressBookService();
expect(await service.addressBookEntries, <Contact>[]);
});
test("getContactById from empty db", () {
final service = AddressBookService();
expect(() => service.getContactById("some id"), throwsException);
});
tearDown(() async {
await tearDownTestHive();
});
});
group("Preloaded DB tests", () {
final contactA = Contact(name: "john", addresses: [], isFavorite: true);
final contactB = Contact(
name: "JANE",
addresses: [
const ContactAddressEntry(
coin: Coin.bitcoin,
address: "some btc address",
label: "rent",
),
],
isFavorite: false);
final contactC = Contact(
name: "Bill",
addresses: [
const ContactAddressEntry(
coin: Coin.monero,
address: "some xmr address",
label: "market",
),
const ContactAddressEntry(
coin: Coin.epicCash,
address: "some epic address",
label: "gas",
),
],
isFavorite: true);
setUp(() async {
await setUpTestHive();
await Hive.openBox<dynamic>(DB.boxNameAddressBook);
await DB.instance.put<dynamic>(
boxName: DB.boxNameAddressBook,
key: contactA.id,
value: contactA.toMap());
await DB.instance.put<dynamic>(
boxName: DB.boxNameAddressBook,
key: contactB.id,
value: contactB.toMap());
await DB.instance.put<dynamic>(
boxName: DB.boxNameAddressBook,
key: contactC.id,
value: contactC.toMap());
});
test("getContactById with non existing ID", () {
final service = AddressBookService();
expect(() => service.getContactById("some id"), throwsException);
});
test("getContactById with existing ID", () {
final service = AddressBookService();
expect(
service.getContactById(contactA.id).toString(), contactA.toString());
});
test("get contacts", () {
final service = AddressBookService();
expect(service.contacts.toString(),
[contactC, contactB, contactA].toString());
});
test("get addressBookEntries", () async {
final service = AddressBookService();
expect((await service.addressBookEntries).toString(),
[contactC, contactB, contactA].toString());
});
test("search contacts", () async {
final service = AddressBookService();
final results = await service.search("j");
expect(results.toString(), [contactB, contactA].toString());
final results2 = await service.search("ja");
expect(results2.toString(), [contactB].toString());
final results3 = await service.search("john");
expect(results3.toString(), [contactA].toString());
final results4 = await service.search("po");
expect(results4.toString(), <Contact>[].toString());
final results5 = await service.search("");
expect(results5.toString(), [contactC, contactB, contactA].toString());
final results6 = await service.search("epic address");
expect(results6.toString(), [contactC].toString());
});
test("add new contact", () async {
final service = AddressBookService();
final contactD = Contact(name: "tim", addresses: [], isFavorite: true);
final result = await service.addContact(contactD);
expect(result, true);
expect(service.contacts.length, 4);
expect(
service.getContactById(contactD.id).toString(), contactD.toString());
});
test("add duplicate contact", () async {
final service = AddressBookService();
final result = await service.addContact(contactA);
expect(result, false);
expect(service.contacts.length, 3);
expect(service.contacts.toString(),
[contactC, contactB, contactA].toString());
});
test("edit contact", () async {
final service = AddressBookService();
final editedContact = contactB.copyWith(name: "Mike");
expect(await service.editContact(editedContact), true);
expect(service.contacts.length, 3);
expect(service.contacts.toString(),
[contactC, contactA, editedContact].toString());
});
test("remove existing contact", () async {
final service = AddressBookService();
await service.removeContact(contactB.id);
expect(service.contacts.length, 2);
expect(service.contacts.toString(), [contactC, contactA].toString());
});
test("remove non existing contact", () async {
final service = AddressBookService();
await service.removeContact("some id");
expect(service.contacts.length, 3);
expect(service.contacts.toString(),
[contactC, contactB, contactA].toString());
});
tearDown(() async {
await tearDownTestHive();
});
});
}

View file

@ -7,7 +7,7 @@ import 'dart:async' as _i4;
import 'dart:ui' as _i5; import 'dart:ui' as _i5;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/contact.dart' as _i2; import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/services/address_book_service.dart' as _i3; import 'package:stackwallet/services/address_book_service.dart' as _i3;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@ -21,8 +21,8 @@ import 'package:stackwallet/services/address_book_service.dart' as _i3;
// ignore_for_file: camel_case_types // ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class // ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact { class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContact_0( _FakeContactEntry_0(
Object parent, Object parent,
Invocation parentInvocation, Invocation parentInvocation,
) : super( ) : super(
@ -37,46 +37,43 @@ class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
class MockAddressBookService extends _i1.Mock class MockAddressBookService extends _i1.Mock
implements _i3.AddressBookService { implements _i3.AddressBookService {
@override @override
List<_i2.Contact> get contacts => (super.noSuchMethod( List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts), Invocation.getter(#contacts),
returnValue: <_i2.Contact>[], returnValue: <_i2.ContactEntry>[],
) as List<_i2.Contact>); ) as List<_i2.ContactEntry>);
@override
_i4.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
@override @override
bool get hasListeners => (super.noSuchMethod( bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners), Invocation.getter(#hasListeners),
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i2.Contact getContactById(String? id) => (super.noSuchMethod( _i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
returnValue: _FakeContact_0( returnValue: _FakeContactEntry_0(
this, this,
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
), ),
) as _i2.Contact); ) as _i2.ContactEntry);
@override @override
_i4.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod( _i4.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method( Invocation.method(
#search, #search,
[text], [text],
), ),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]), returnValue:
) as _i4.Future<List<_i2.Contact>>); _i4.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i4.Future<List<_i2.ContactEntry>>);
@override @override
bool matches( bool matches(
String? term, String? term,
_i2.Contact? contact, _i2.ContactEntry? contact,
) => ) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
@ -89,7 +86,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i4.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod( _i4.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#addContact, #addContact,
[contact], [contact],
@ -97,7 +94,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i4.Future<bool>.value(false), returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>); ) as _i4.Future<bool>);
@override @override
_i4.Future<bool> editContact(_i2.Contact? editedContact) => _i4.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
#editContact, #editContact,

View file

@ -9,7 +9,7 @@ import 'dart:ui' as _i11;
import 'package:barcode_scan2/barcode_scan2.dart' as _i2; import 'package:barcode_scan2/barcode_scan2.dart' as _i2;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i6; import 'package:stackwallet/models/balance.dart' as _i6;
import 'package:stackwallet/models/contact.dart' as _i3; import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i3;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i14; import 'package:stackwallet/models/isar/models/isar_models.dart' as _i14;
import 'package:stackwallet/models/models.dart' as _i5; import 'package:stackwallet/models/models.dart' as _i5;
import 'package:stackwallet/services/address_book_service.dart' as _i10; import 'package:stackwallet/services/address_book_service.dart' as _i10;
@ -40,8 +40,8 @@ class _FakeScanResult_0 extends _i1.SmartFake implements _i2.ScanResult {
); );
} }
class _FakeContact_1 extends _i1.SmartFake implements _i3.Contact { class _FakeContactEntry_1 extends _i1.SmartFake implements _i3.ContactEntry {
_FakeContact_1( _FakeContactEntry_1(
Object parent, Object parent,
Invocation parentInvocation, Invocation parentInvocation,
) : super( ) : super(
@ -126,46 +126,43 @@ class MockBarcodeScannerWrapper extends _i1.Mock
class MockAddressBookService extends _i1.Mock class MockAddressBookService extends _i1.Mock
implements _i10.AddressBookService { implements _i10.AddressBookService {
@override @override
List<_i3.Contact> get contacts => (super.noSuchMethod( List<_i3.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts), Invocation.getter(#contacts),
returnValue: <_i3.Contact>[], returnValue: <_i3.ContactEntry>[],
) as List<_i3.Contact>); ) as List<_i3.ContactEntry>);
@override
_i9.Future<List<_i3.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i9.Future<List<_i3.Contact>>.value(<_i3.Contact>[]),
) as _i9.Future<List<_i3.Contact>>);
@override @override
bool get hasListeners => (super.noSuchMethod( bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners), Invocation.getter(#hasListeners),
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i3.Contact getContactById(String? id) => (super.noSuchMethod( _i3.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
returnValue: _FakeContact_1( returnValue: _FakeContactEntry_1(
this, this,
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
), ),
) as _i3.Contact); ) as _i3.ContactEntry);
@override @override
_i9.Future<List<_i3.Contact>> search(String? text) => (super.noSuchMethod( _i9.Future<List<_i3.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method( Invocation.method(
#search, #search,
[text], [text],
), ),
returnValue: _i9.Future<List<_i3.Contact>>.value(<_i3.Contact>[]), returnValue:
) as _i9.Future<List<_i3.Contact>>); _i9.Future<List<_i3.ContactEntry>>.value(<_i3.ContactEntry>[]),
) as _i9.Future<List<_i3.ContactEntry>>);
@override @override
bool matches( bool matches(
String? term, String? term,
_i3.Contact? contact, _i3.ContactEntry? contact,
) => ) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
@ -178,7 +175,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i9.Future<bool> addContact(_i3.Contact? contact) => (super.noSuchMethod( _i9.Future<bool> addContact(_i3.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#addContact, #addContact,
[contact], [contact],
@ -186,7 +183,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i9.Future<bool>.value(false), returnValue: _i9.Future<bool>.value(false),
) as _i9.Future<bool>); ) as _i9.Future<bool>);
@override @override
_i9.Future<bool> editContact(_i3.Contact? editedContact) => _i9.Future<bool> editContact(_i3.ContactEntry? editedContact) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
#editContact, #editContact,

View file

@ -8,7 +8,7 @@ import 'dart:ui' as _i9;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5; import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/contact.dart' as _i2; import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i12; import 'package:stackwallet/models/isar/models/isar_models.dart' as _i12;
import 'package:stackwallet/models/models.dart' as _i4; import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/services/address_book_service.dart' as _i7; import 'package:stackwallet/services/address_book_service.dart' as _i7;
@ -30,8 +30,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i11;
// ignore_for_file: camel_case_types // ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class // ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact { class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContact_0( _FakeContactEntry_0(
Object parent, Object parent,
Invocation parentInvocation, Invocation parentInvocation,
) : super( ) : super(
@ -87,46 +87,43 @@ class _FakeAmount_4 extends _i1.SmartFake implements _i6.Amount {
class MockAddressBookService extends _i1.Mock class MockAddressBookService extends _i1.Mock
implements _i7.AddressBookService { implements _i7.AddressBookService {
@override @override
List<_i2.Contact> get contacts => (super.noSuchMethod( List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts), Invocation.getter(#contacts),
returnValue: <_i2.Contact>[], returnValue: <_i2.ContactEntry>[],
) as List<_i2.Contact>); ) as List<_i2.ContactEntry>);
@override
_i8.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i8.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i8.Future<List<_i2.Contact>>);
@override @override
bool get hasListeners => (super.noSuchMethod( bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners), Invocation.getter(#hasListeners),
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i2.Contact getContactById(String? id) => (super.noSuchMethod( _i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
returnValue: _FakeContact_0( returnValue: _FakeContactEntry_0(
this, this,
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
), ),
) as _i2.Contact); ) as _i2.ContactEntry);
@override @override
_i8.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod( _i8.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method( Invocation.method(
#search, #search,
[text], [text],
), ),
returnValue: _i8.Future<List<_i2.Contact>>.value(<_i2.Contact>[]), returnValue:
) as _i8.Future<List<_i2.Contact>>); _i8.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i8.Future<List<_i2.ContactEntry>>);
@override @override
bool matches( bool matches(
String? term, String? term,
_i2.Contact? contact, _i2.ContactEntry? contact,
) => ) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
@ -139,7 +136,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i8.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod( _i8.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#addContact, #addContact,
[contact], [contact],
@ -147,7 +144,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i8.Future<bool>.value(false), returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>); ) as _i8.Future<bool>);
@override @override
_i8.Future<bool> editContact(_i2.Contact? editedContact) => _i8.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
#editContact, #editContact,

View file

@ -8,7 +8,7 @@ import 'dart:ui' as _i9;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/balance.dart' as _i5; import 'package:stackwallet/models/balance.dart' as _i5;
import 'package:stackwallet/models/contact.dart' as _i2; import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i12; import 'package:stackwallet/models/isar/models/isar_models.dart' as _i12;
import 'package:stackwallet/models/models.dart' as _i4; import 'package:stackwallet/models/models.dart' as _i4;
import 'package:stackwallet/services/address_book_service.dart' as _i7; import 'package:stackwallet/services/address_book_service.dart' as _i7;
@ -28,8 +28,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i11;
// ignore_for_file: camel_case_types // ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class // ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact { class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContact_0( _FakeContactEntry_0(
Object parent, Object parent,
Invocation parentInvocation, Invocation parentInvocation,
) : super( ) : super(
@ -85,46 +85,43 @@ class _FakeAmount_4 extends _i1.SmartFake implements _i6.Amount {
class MockAddressBookService extends _i1.Mock class MockAddressBookService extends _i1.Mock
implements _i7.AddressBookService { implements _i7.AddressBookService {
@override @override
List<_i2.Contact> get contacts => (super.noSuchMethod( List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts), Invocation.getter(#contacts),
returnValue: <_i2.Contact>[], returnValue: <_i2.ContactEntry>[],
) as List<_i2.Contact>); ) as List<_i2.ContactEntry>);
@override
_i8.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i8.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i8.Future<List<_i2.Contact>>);
@override @override
bool get hasListeners => (super.noSuchMethod( bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners), Invocation.getter(#hasListeners),
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i2.Contact getContactById(String? id) => (super.noSuchMethod( _i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
returnValue: _FakeContact_0( returnValue: _FakeContactEntry_0(
this, this,
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
), ),
) as _i2.Contact); ) as _i2.ContactEntry);
@override @override
_i8.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod( _i8.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method( Invocation.method(
#search, #search,
[text], [text],
), ),
returnValue: _i8.Future<List<_i2.Contact>>.value(<_i2.Contact>[]), returnValue:
) as _i8.Future<List<_i2.Contact>>); _i8.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i8.Future<List<_i2.ContactEntry>>);
@override @override
bool matches( bool matches(
String? term, String? term,
_i2.Contact? contact, _i2.ContactEntry? contact,
) => ) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
@ -137,7 +134,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i8.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod( _i8.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#addContact, #addContact,
[contact], [contact],
@ -145,7 +142,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i8.Future<bool>.value(false), returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>); ) as _i8.Future<bool>);
@override @override
_i8.Future<bool> editContact(_i2.Contact? editedContact) => _i8.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
#editContact, #editContact,

View file

@ -7,7 +7,7 @@ import 'dart:async' as _i4;
import 'dart:ui' as _i5; import 'dart:ui' as _i5;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/contact.dart' as _i2; import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/services/address_book_service.dart' as _i6; import 'package:stackwallet/services/address_book_service.dart' as _i6;
import 'package:stackwallet/services/locale_service.dart' as _i7; import 'package:stackwallet/services/locale_service.dart' as _i7;
import 'package:stackwallet/services/notes_service.dart' as _i3; import 'package:stackwallet/services/notes_service.dart' as _i3;
@ -23,8 +23,8 @@ import 'package:stackwallet/services/notes_service.dart' as _i3;
// ignore_for_file: camel_case_types // ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class // ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact { class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContact_0( _FakeContactEntry_0(
Object parent, Object parent,
Invocation parentInvocation, Invocation parentInvocation,
) : super( ) : super(
@ -141,46 +141,43 @@ class MockNotesService extends _i1.Mock implements _i3.NotesService {
class MockAddressBookService extends _i1.Mock class MockAddressBookService extends _i1.Mock
implements _i6.AddressBookService { implements _i6.AddressBookService {
@override @override
List<_i2.Contact> get contacts => (super.noSuchMethod( List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts), Invocation.getter(#contacts),
returnValue: <_i2.Contact>[], returnValue: <_i2.ContactEntry>[],
) as List<_i2.Contact>); ) as List<_i2.ContactEntry>);
@override
_i4.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
@override @override
bool get hasListeners => (super.noSuchMethod( bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners), Invocation.getter(#hasListeners),
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i2.Contact getContactById(String? id) => (super.noSuchMethod( _i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
returnValue: _FakeContact_0( returnValue: _FakeContactEntry_0(
this, this,
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
), ),
) as _i2.Contact); ) as _i2.ContactEntry);
@override @override
_i4.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod( _i4.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method( Invocation.method(
#search, #search,
[text], [text],
), ),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]), returnValue:
) as _i4.Future<List<_i2.Contact>>); _i4.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i4.Future<List<_i2.ContactEntry>>);
@override @override
bool matches( bool matches(
String? term, String? term,
_i2.Contact? contact, _i2.ContactEntry? contact,
) => ) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
@ -193,7 +190,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i4.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod( _i4.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#addContact, #addContact,
[contact], [contact],
@ -201,7 +198,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i4.Future<bool>.value(false), returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>); ) as _i4.Future<bool>);
@override @override
_i4.Future<bool> editContact(_i2.Contact? editedContact) => _i4.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
#editContact, #editContact,

View file

@ -7,7 +7,7 @@ import 'dart:async' as _i4;
import 'dart:ui' as _i5; import 'dart:ui' as _i5;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/contact.dart' as _i2; import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/services/address_book_service.dart' as _i3; import 'package:stackwallet/services/address_book_service.dart' as _i3;
import 'package:stackwallet/services/notes_service.dart' as _i6; import 'package:stackwallet/services/notes_service.dart' as _i6;
@ -22,8 +22,8 @@ import 'package:stackwallet/services/notes_service.dart' as _i6;
// ignore_for_file: camel_case_types // ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class // ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact { class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContact_0( _FakeContactEntry_0(
Object parent, Object parent,
Invocation parentInvocation, Invocation parentInvocation,
) : super( ) : super(
@ -38,46 +38,43 @@ class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact {
class MockAddressBookService extends _i1.Mock class MockAddressBookService extends _i1.Mock
implements _i3.AddressBookService { implements _i3.AddressBookService {
@override @override
List<_i2.Contact> get contacts => (super.noSuchMethod( List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts), Invocation.getter(#contacts),
returnValue: <_i2.Contact>[], returnValue: <_i2.ContactEntry>[],
) as List<_i2.Contact>); ) as List<_i2.ContactEntry>);
@override
_i4.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
@override @override
bool get hasListeners => (super.noSuchMethod( bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners), Invocation.getter(#hasListeners),
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i2.Contact getContactById(String? id) => (super.noSuchMethod( _i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
returnValue: _FakeContact_0( returnValue: _FakeContactEntry_0(
this, this,
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
), ),
) as _i2.Contact); ) as _i2.ContactEntry);
@override @override
_i4.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod( _i4.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method( Invocation.method(
#search, #search,
[text], [text],
), ),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]), returnValue:
) as _i4.Future<List<_i2.Contact>>); _i4.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i4.Future<List<_i2.ContactEntry>>);
@override @override
bool matches( bool matches(
String? term, String? term,
_i2.Contact? contact, _i2.ContactEntry? contact,
) => ) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
@ -90,7 +87,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i4.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod( _i4.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#addContact, #addContact,
[contact], [contact],
@ -98,7 +95,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i4.Future<bool>.value(false), returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>); ) as _i4.Future<bool>);
@override @override
_i4.Future<bool> editContact(_i2.Contact? editedContact) => _i4.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
#editContact, #editContact,

View file

@ -5,18 +5,17 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart'; import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:stackwallet/models/contact.dart'; import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/isar/stack_theme.dart'; import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart'; import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/services/address_book_service.dart'; import 'package:stackwallet/services/address_book_service.dart';
import '../sample_data/theme_json.dart';
import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/address_book_card.dart'; import 'package:stackwallet/widgets/address_book_card.dart';
import '../sample_data/theme_json.dart';
import 'address_book_card_test.mocks.dart'; import 'address_book_card_test.mocks.dart';
class MockedFunctions extends Mock { class MockedFunctions extends Mock {
@ -27,18 +26,20 @@ class MockedFunctions extends Mock {
void main() { void main() {
testWidgets('test returns Contact Address Entry', (widgetTester) async { testWidgets('test returns Contact Address Entry', (widgetTester) async {
final service = MockAddressBookService(); final service = MockAddressBookService();
final applicationThemesDirectoryPath = ""; const applicationThemesDirectoryPath = "";
when(service.getContactById("default")).thenAnswer( when(service.getContactById("default")).thenAnswer(
(realInvocation) => Contact( (realInvocation) => ContactEntry(
name: "John Doe", name: "John Doe",
addresses: [ addresses: [
const ContactAddressEntry( ContactAddressEntry()
coin: Coin.bitcoincash, ..coinName = Coin.bitcoincash.name
address: "some bch address", ..address = "some bch address"
label: "Bills") ..label = "Bills"
..other = null
], ],
isFavorite: true, isFavorite: true,
customId: '',
), ),
); );

View file

@ -7,7 +7,7 @@ import 'dart:async' as _i4;
import 'dart:ui' as _i5; import 'dart:ui' as _i5;
import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/contact.dart' as _i2; import 'package:stackwallet/models/isar/models/contact_entry.dart' as _i2;
import 'package:stackwallet/services/address_book_service.dart' as _i3; import 'package:stackwallet/services/address_book_service.dart' as _i3;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@ -21,8 +21,8 @@ import 'package:stackwallet/services/address_book_service.dart' as _i3;
// ignore_for_file: camel_case_types // ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class // ignore_for_file: subtype_of_sealed_class
class _FakeContact_0 extends _i1.SmartFake implements _i2.Contact { class _FakeContactEntry_0 extends _i1.SmartFake implements _i2.ContactEntry {
_FakeContact_0( _FakeContactEntry_0(
Object parent, Object parent,
Invocation parentInvocation, Invocation parentInvocation,
) : super( ) : super(
@ -41,46 +41,43 @@ class MockAddressBookService extends _i1.Mock
} }
@override @override
List<_i2.Contact> get contacts => (super.noSuchMethod( List<_i2.ContactEntry> get contacts => (super.noSuchMethod(
Invocation.getter(#contacts), Invocation.getter(#contacts),
returnValue: <_i2.Contact>[], returnValue: <_i2.ContactEntry>[],
) as List<_i2.Contact>); ) as List<_i2.ContactEntry>);
@override
_i4.Future<List<_i2.Contact>> get addressBookEntries => (super.noSuchMethod(
Invocation.getter(#addressBookEntries),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]),
) as _i4.Future<List<_i2.Contact>>);
@override @override
bool get hasListeners => (super.noSuchMethod( bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners), Invocation.getter(#hasListeners),
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i2.Contact getContactById(String? id) => (super.noSuchMethod( _i2.ContactEntry getContactById(String? id) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
returnValue: _FakeContact_0( returnValue: _FakeContactEntry_0(
this, this,
Invocation.method( Invocation.method(
#getContactById, #getContactById,
[id], [id],
), ),
), ),
) as _i2.Contact); ) as _i2.ContactEntry);
@override @override
_i4.Future<List<_i2.Contact>> search(String? text) => (super.noSuchMethod( _i4.Future<List<_i2.ContactEntry>> search(String? text) =>
(super.noSuchMethod(
Invocation.method( Invocation.method(
#search, #search,
[text], [text],
), ),
returnValue: _i4.Future<List<_i2.Contact>>.value(<_i2.Contact>[]), returnValue:
) as _i4.Future<List<_i2.Contact>>); _i4.Future<List<_i2.ContactEntry>>.value(<_i2.ContactEntry>[]),
) as _i4.Future<List<_i2.ContactEntry>>);
@override @override
bool matches( bool matches(
String? term, String? term,
_i2.Contact? contact, _i2.ContactEntry? contact,
) => ) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
@ -93,7 +90,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: false, returnValue: false,
) as bool); ) as bool);
@override @override
_i4.Future<bool> addContact(_i2.Contact? contact) => (super.noSuchMethod( _i4.Future<bool> addContact(_i2.ContactEntry? contact) => (super.noSuchMethod(
Invocation.method( Invocation.method(
#addContact, #addContact,
[contact], [contact],
@ -101,7 +98,7 @@ class MockAddressBookService extends _i1.Mock
returnValue: _i4.Future<bool>.value(false), returnValue: _i4.Future<bool>.value(false),
) as _i4.Future<bool>); ) as _i4.Future<bool>);
@override @override
_i4.Future<bool> editContact(_i2.Contact? editedContact) => _i4.Future<bool> editContact(_i2.ContactEntry? editedContact) =>
(super.noSuchMethod( (super.noSuchMethod(
Invocation.method( Invocation.method(
#editContact, #editContact,