mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-16 17:27:37 +00:00
Merge redesign part 3.
This commit is contained in:
parent
42ed4faf73
commit
70ff011fc6
13 changed files with 156 additions and 76 deletions
|
@ -87,7 +87,7 @@ class ElectrumClient {
|
|||
|
||||
Future<void> ping() async {
|
||||
try {
|
||||
await callWithTimeout(method: 'server.ping');
|
||||
// await callWithTimeout(method: 'server.ping');
|
||||
_setIsConnected(true);
|
||||
} on RequestFailedTimeoutException catch (_) {
|
||||
_setIsConnected(false);
|
||||
|
|
|
@ -12,7 +12,7 @@ class ContactService {
|
|||
|
||||
Future add(Contact contact) async {
|
||||
await contactSource.add(contact);
|
||||
contactListStore.contacts.add(contact);
|
||||
// contactListStore.contacts.add(contact);
|
||||
}
|
||||
|
||||
Future update(Contact contact) async {
|
||||
|
|
|
@ -294,11 +294,13 @@ Future setup(
|
|||
|
||||
getIt.registerFactoryParam<ContactViewModel, Contact, void>(
|
||||
(Contact contact, _) => ContactViewModel(
|
||||
getIt.get<ContactService>(), getIt.get<AppStore>().wallet,
|
||||
contactSource, getIt.get<AppStore>().wallet,
|
||||
contact: contact));
|
||||
|
||||
getIt.registerFactory(() => ContactListViewModel(
|
||||
getIt.get<AppStore>().contactListStore, getIt.get<ContactService>()));
|
||||
getIt.get<AppStore>().contactListStore,
|
||||
getIt.get<ContactService>(),
|
||||
contactSource));
|
||||
|
||||
getIt.registerFactory(
|
||||
() => ContactListPage(getIt.get<ContactListViewModel>()));
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
||||
import 'package:cake_wallet/utils/mobx.dart';
|
||||
|
||||
part 'contact.g.dart';
|
||||
|
||||
@HiveType(typeId: 0)
|
||||
class Contact extends HiveObject {
|
||||
class Contact extends HiveObject with Keyable {
|
||||
Contact({@required this.name, @required this.address, CryptoCurrency type})
|
||||
: raw = type?.raw;
|
||||
|
||||
|
@ -22,6 +23,9 @@ class Contact extends HiveObject {
|
|||
|
||||
CryptoCurrency get type => CryptoCurrency.deserialize(raw: raw);
|
||||
|
||||
@override
|
||||
dynamic get keyIndex => key;
|
||||
|
||||
@override
|
||||
bool operator ==(Object o) => o is Contact && o.key == key;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/utils/mobx.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
@ -8,7 +9,7 @@ import 'package:cake_wallet/src/domain/common/digest_request.dart';
|
|||
part 'node.g.dart';
|
||||
|
||||
@HiveType(typeId: 1)
|
||||
class Node extends HiveObject {
|
||||
class Node extends HiveObject with Keyable {
|
||||
Node(
|
||||
{@required this.uri,
|
||||
@required WalletType type,
|
||||
|
|
|
@ -108,7 +108,7 @@ class NodeListPage extends BasePage {
|
|||
});
|
||||
|
||||
final dismissibleRow = Dismissible(
|
||||
key: Key('${node.value.key}'),
|
||||
key: Key('${node.keyIndex}'),
|
||||
confirmDismiss: (direction) async {
|
||||
return await showDialog(
|
||||
context: context,
|
||||
|
|
|
@ -44,9 +44,9 @@ abstract class SettingsStoreBase with Store {
|
|||
languageCode = initialLanguageCode;
|
||||
currentLocale = initialCurrentLocale;
|
||||
itemHeaders = {};
|
||||
this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
||||
_sharedPreferences = sharedPreferences;
|
||||
_nodeSource = nodeSource;
|
||||
_nodes = nodes;
|
||||
}
|
||||
|
||||
static const currentNodeIdKey = 'current_node_id';
|
||||
|
@ -101,9 +101,9 @@ abstract class SettingsStoreBase with Store {
|
|||
SharedPreferences _sharedPreferences;
|
||||
Box<Node> _nodeSource;
|
||||
|
||||
Map<WalletType, Node> _nodes;
|
||||
ObservableMap<WalletType, Node> nodes;
|
||||
|
||||
Node getCurrentNode(WalletType walletType) => _nodes[walletType];
|
||||
Node getCurrentNode(WalletType walletType) => nodes[walletType];
|
||||
|
||||
Future<void> setCurrentNode(Node node, WalletType walletType) async {
|
||||
switch (walletType) {
|
||||
|
@ -118,7 +118,7 @@ abstract class SettingsStoreBase with Store {
|
|||
break;
|
||||
}
|
||||
|
||||
_nodes[walletType] = node;
|
||||
nodes[walletType] = node;
|
||||
}
|
||||
|
||||
static Future<SettingsStore> load(
|
||||
|
|
11
lib/utils/item_cell.dart
Normal file
11
lib/utils/item_cell.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cake_wallet/utils/mobx.dart';
|
||||
|
||||
class ItemCell<Item> with Keyable {
|
||||
ItemCell(this.value, {@required this.isSelected, @required dynamic key}) {
|
||||
keyIndex = key;
|
||||
}
|
||||
|
||||
final Item value;
|
||||
final bool isSelected;
|
||||
}
|
|
@ -1,46 +1,90 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
void connectDifferent<T, Y>(
|
||||
mixin Keyable {
|
||||
dynamic keyIndex;
|
||||
}
|
||||
|
||||
void connectDifferent<T extends Keyable, Y extends Keyable>(
|
||||
ObservableList<T> source, ObservableList<Y> dest, Y Function(T) transform,
|
||||
{bool Function(T) filter}) {
|
||||
source.observe((ListChange<T> change) {
|
||||
// switch (change.type) {
|
||||
// case OperationType.add:
|
||||
// final _values = change.added;
|
||||
// Iterable<T> values;
|
||||
change.elementChanges.forEach((change) {
|
||||
switch (change.type) {
|
||||
case OperationType.add:
|
||||
if (filter?.call(change.newValue as T) ?? true) {
|
||||
dest.add(transform(change.newValue as T));
|
||||
}
|
||||
break;
|
||||
case OperationType.remove:
|
||||
// Hive could has equal index and key
|
||||
dest.removeWhere(
|
||||
(elem) => elem.keyIndex == (change.oldValue.key ?? change.index));
|
||||
break;
|
||||
case OperationType.update:
|
||||
for (var i = 0; i < dest.length; i++) {
|
||||
final item = dest[i];
|
||||
|
||||
// if (filter != null) {
|
||||
// values = _values.where(filter);
|
||||
// }
|
||||
|
||||
// dest.addAll(values.map((e) => transform(e)));
|
||||
// break;
|
||||
// case OperationType.remove:
|
||||
// change.removed.forEach((element) {
|
||||
// dest.remove(element);
|
||||
// });
|
||||
|
||||
// // dest.removeAt(change.index);
|
||||
// break;
|
||||
// case OperationType.update:
|
||||
// // change.index
|
||||
// break;
|
||||
// }
|
||||
if (item.keyIndex == change.newValue.key) {
|
||||
dest[i] = transform(change.newValue as T);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void connect<T>(ObservableList<T> source, ObservableList<T> dest) {
|
||||
void connect<T extends Keyable>(
|
||||
ObservableList<T> source, ObservableList<T> dest) {
|
||||
source.observe((ListChange<T> change) {
|
||||
// switch (change.type) {
|
||||
// case OperationType.add:
|
||||
// dest.addAll(change.added);
|
||||
// break;
|
||||
// case OperationType.remove:
|
||||
// dest.removeAt(change.index);
|
||||
// break;
|
||||
// case OperationType.update:
|
||||
// // change.index
|
||||
// break;
|
||||
// }
|
||||
source.observe((ListChange<T> change) {
|
||||
change.elementChanges.forEach((change) {
|
||||
switch (change.type) {
|
||||
case OperationType.add:
|
||||
// if (filter?.call(change.newValue as T) ?? true) {
|
||||
dest.add(change.newValue as T);
|
||||
// }
|
||||
break;
|
||||
case OperationType.remove:
|
||||
// Hive could has equal index and key
|
||||
dest.removeWhere((elem) =>
|
||||
elem.keyIndex == (change.oldValue.key ?? change.index));
|
||||
break;
|
||||
case OperationType.update:
|
||||
for (var i = 0; i < dest.length; i++) {
|
||||
final item = dest[i];
|
||||
|
||||
if (item.keyIndex == change.newValue.key) {
|
||||
dest[i] = change.newValue as T;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription<BoxEvent> bindBox<T extends Keyable>(
|
||||
Box<T> source, ObservableList<T> dest) {
|
||||
return source.watch().listen((event) {
|
||||
if (event.deleted) {
|
||||
dest.removeWhere((el) => el.keyIndex == event.key);
|
||||
}
|
||||
|
||||
final dynamic value = event.value;
|
||||
|
||||
if (value is T) {
|
||||
final elIndex = dest.indexWhere((el) => el.keyIndex == value.keyIndex);
|
||||
|
||||
if (elIndex > -1) {
|
||||
dest[elIndex] = value;
|
||||
} else {
|
||||
dest.add(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,20 +1,34 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/core/contact_service.dart';
|
||||
import 'package:cake_wallet/store/contact_list_store.dart';
|
||||
import 'package:cake_wallet/src/domain/common/contact.dart';
|
||||
import 'package:cake_wallet/utils/mobx.dart';
|
||||
|
||||
part 'contact_list_view_model.g.dart';
|
||||
|
||||
class ContactListViewModel = ContactListViewModelBase with _$ContactListViewModel;
|
||||
class ContactListViewModel = ContactListViewModelBase
|
||||
with _$ContactListViewModel;
|
||||
|
||||
abstract class ContactListViewModelBase with Store {
|
||||
ContactListViewModelBase(this.addressBookStore, this.contactService);
|
||||
ContactListViewModelBase(
|
||||
this.addressBookStore, this.contactService, this.contactSource) {
|
||||
_subscription = bindBox(contactSource, addressBookStore.contacts);
|
||||
}
|
||||
|
||||
final ContactListStore addressBookStore;
|
||||
final ContactService contactService;
|
||||
final Box<Contact> contactSource;
|
||||
|
||||
@computed
|
||||
ObservableList<Contact> get contacts => addressBookStore.contacts;
|
||||
|
||||
StreamSubscription<BoxEvent> _subscription;
|
||||
|
||||
void dispose() {
|
||||
_subscription.cancel();
|
||||
}
|
||||
|
||||
Future<void> delete(Contact contact) async => contactService.delete(contact);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/core/wallet_base.dart';
|
||||
import 'package:cake_wallet/core/contact_service.dart';
|
||||
|
@ -10,7 +11,7 @@ part 'contact_view_model.g.dart';
|
|||
class ContactViewModel = ContactViewModelBase with _$ContactViewModel;
|
||||
|
||||
abstract class ContactViewModelBase with Store {
|
||||
ContactViewModelBase(this._contactService, this._wallet, {Contact contact})
|
||||
ContactViewModelBase(this._contacts, this._wallet, {Contact contact})
|
||||
: state = InitialContactViewModelState(),
|
||||
currencies = CryptoCurrency.all,
|
||||
_contact = contact {
|
||||
|
@ -33,12 +34,14 @@ abstract class ContactViewModelBase with Store {
|
|||
|
||||
@computed
|
||||
bool get isReady =>
|
||||
(name?.isNotEmpty ?? false) && (currency?.toString()?.isNotEmpty ?? false)
|
||||
&& (address?.isNotEmpty ?? false);
|
||||
(name?.isNotEmpty ?? false) &&
|
||||
(currency?.toString()?.isNotEmpty ?? false) &&
|
||||
(address?.isNotEmpty ?? false);
|
||||
|
||||
final List<CryptoCurrency> currencies;
|
||||
final ContactService _contactService;
|
||||
// final ContactService _contactService;
|
||||
final WalletBase _wallet;
|
||||
final Box<Contact> _contacts;
|
||||
final Contact _contact;
|
||||
|
||||
@action
|
||||
|
@ -57,10 +60,13 @@ abstract class ContactViewModelBase with Store {
|
|||
_contact.name = name;
|
||||
_contact.address = address;
|
||||
_contact.updateCryptoCurrency(currency: currency);
|
||||
await _contactService.update(_contact);
|
||||
await _contacts.put(_contact.key, _contact);
|
||||
// await _contactService.update(_contact);
|
||||
} else {
|
||||
await _contactService
|
||||
await _contacts
|
||||
.add(Contact(name: name, address: address, type: currency));
|
||||
// await _contactService
|
||||
// .add(Contact(name: name, address: address, type: currency));
|
||||
}
|
||||
|
||||
state = ContactSavingSuccessfully();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/utils/item_cell.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -14,13 +15,6 @@ part 'node_list_view_model.g.dart';
|
|||
|
||||
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
|
||||
|
||||
class ItemCell<Item> {
|
||||
ItemCell(this.value, {@required this.isSelected});
|
||||
|
||||
final Item value;
|
||||
final bool isSelected;
|
||||
}
|
||||
|
||||
abstract class NodeListViewModelBase with Store {
|
||||
NodeListViewModelBase(
|
||||
this._nodeListStore, this._nodeSource, this._wallet, this._settingsStore)
|
||||
|
@ -29,16 +23,16 @@ abstract class NodeListViewModelBase with Store {
|
|||
final values = _nodeListStore.nodes;
|
||||
nodes.clear();
|
||||
nodes.addAll(values.where((Node node) => node.type == _wallet.type).map(
|
||||
(Node val) =>
|
||||
ItemCell<Node>(val, isSelected: val.key == currentNode.key)));
|
||||
(Node val) => ItemCell<Node>(val,
|
||||
isSelected: val.key == currentNode.key, key: val.key)));
|
||||
connectDifferent(
|
||||
_nodeListStore.nodes,
|
||||
nodes,
|
||||
(Node val) =>
|
||||
ItemCell<Node>(val, isSelected: val.key == currentNode.key),
|
||||
filter: (Node val) {
|
||||
return val.type == _wallet.type;
|
||||
});
|
||||
(Node val) => ItemCell<Node>(val,
|
||||
isSelected: val.key == currentNode.key, key: val.key),
|
||||
filter: (Node val) => val.type == _wallet.type);
|
||||
reaction((_) => _settingsStore.nodes[_wallet.type],
|
||||
(Node _) => _updateCurrentNode());
|
||||
}
|
||||
|
||||
ObservableList<ItemCell<Node>> nodes;
|
||||
|
@ -66,17 +60,18 @@ abstract class NodeListViewModelBase with Store {
|
|||
break;
|
||||
}
|
||||
|
||||
await _wallet.connectToNode(node: node);
|
||||
await setAsCurrent(node);
|
||||
}
|
||||
|
||||
Future<void> delete(Node node) async => _nodeSource.delete(node.key);
|
||||
|
||||
Future<void> setAsCurrent(Node node) async {
|
||||
await _wallet.connectToNode(node: node);
|
||||
await _settingsStore.setCurrentNode(node, _wallet.type);
|
||||
_updateCurrentNode();
|
||||
await _wallet.connectToNode(node: node);
|
||||
}
|
||||
|
||||
@action
|
||||
void _updateCurrentNode() {
|
||||
final currentNode = _settingsStore.getCurrentNode(_wallet.type);
|
||||
|
||||
|
@ -85,7 +80,8 @@ abstract class NodeListViewModelBase with Store {
|
|||
final isSelected = item.value.key == currentNode.key;
|
||||
|
||||
if (item.isSelected != isSelected) {
|
||||
nodes[i] = ItemCell<Node>(item.value, isSelected: isSelected);
|
||||
nodes[i] = ItemCell<Node>(item.value,
|
||||
isSelected: isSelected, key: item.keyIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,8 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
WalletType get type => _wallet.type;
|
||||
|
||||
@computed
|
||||
WalletAddressListItem get address => WalletAddressListItem(address: _wallet.address);
|
||||
WalletAddressListItem get address =>
|
||||
WalletAddressListItem(address: _wallet.address);
|
||||
|
||||
@computed
|
||||
PaymentURI get uri {
|
||||
|
@ -100,15 +101,16 @@ abstract class WalletAddressListViewModelBase with Store {
|
|||
}
|
||||
|
||||
if (wallet is BitcoinWallet) {
|
||||
final bitcoinAddresses = wallet.addresses.map(
|
||||
(addr) => WalletAddressListItem(name: addr.label, address: addr.address));
|
||||
final bitcoinAddresses = wallet.addresses.map((addr) =>
|
||||
WalletAddressListItem(name: addr.label, address: addr.address));
|
||||
addressList.addAll(bitcoinAddresses);
|
||||
}
|
||||
|
||||
return addressList;
|
||||
}
|
||||
|
||||
set address(WalletAddressListItem address) => _wallet.address = address.address;
|
||||
set address(WalletAddressListItem address) =>
|
||||
_wallet.address = address.address;
|
||||
|
||||
bool hasAccounts;
|
||||
|
||||
|
|
Loading…
Reference in a new issue