dev
dart 150 lines 4.41 KB
Raw
1 import 'package:cake_wallet/core/address_resolver/address_resolver_service.dart';
2 import 'package:cake_wallet/core/address_resolver/parsed_address.dart';
3 import 'package:cake_wallet/core/address_validator.dart';
4 import 'package:cake_wallet/di.dart';
5 import 'package:cake_wallet/entities/contact_record.dart';
6 import 'package:cake_wallet/main.dart';
7 import 'package:cake_wallet/store/app_store.dart';
8 import 'package:cw_core/utils/print_verbose.dart';
9 import 'package:flutter/material.dart';
10 import 'package:hive/hive.dart';
11 import 'package:mobx/mobx.dart';
12 import 'package:cake_wallet/core/execution_state.dart';
13 import 'package:cake_wallet/generated/i18n.dart';
14 import 'package:cake_wallet/entities/contact.dart';
15 import 'package:cw_core/crypto_currency.dart';
16
17 part 'contact_view_model.g.dart';
18
19 class ContactViewModel = ContactViewModelBase with _$ContactViewModel;
20
21 abstract class ContactViewModelBase with Store {
22 ContactViewModelBase(this._contacts, this.appStore, this.adrResService, {ContactRecord? contact})
23 : state = InitialExecutionState(),
24 currencies = CryptoCurrency.all,
25 _contact = contact,
26 name = contact?.name ?? '',
27 address = contact?.address ?? '',
28 displayName = contact?.displayName ?? '',
29 currency = contact?.type,
30 lastChange = contact?.lastChange;
31
32 final AppStore appStore;
33 final AddressResolverService adrResService;
34
35 @observable
36 ExecutionState state;
37
38 @observable
39 String name;
40
41 @observable
42 String address;
43
44 @observable
45 String displayName;
46
47 @observable
48 CryptoCurrency? currency;
49
50 DateTime? lastChange;
51
52 @computed
53 bool get isReady =>
54 name.isNotEmpty && (currency?.toString().isNotEmpty ?? false) && address.isNotEmpty;
55
56 final List<CryptoCurrency> currencies;
57 final Box<Contact> _contacts;
58 final ContactRecord? _contact;
59
60 @action
61 void reset() {
62 address = '';
63 name = '';
64 displayName = '';
65 currency = null;
66 }
67
68 Future<ParsedAddress?> extractParsedAddress(BuildContext context) async {
69 final wallet = appStore.wallet;
70 final currentCurrency = currency;
71 final query = address.trim();
72
73 if (wallet == null) return null;
74 if (currentCurrency == null) return null;
75 if (query.isEmpty) return null;
76
77 // Check if the address is valid for the current currency (except for Zano, which can use handles as addresses)
78 if (currentCurrency != CryptoCurrency.zano) {
79 final isValidAddress = AddressValidator(type: currentCurrency).isValid(query);
80 if (isValidAddress) return null;
81 }
82
83 final parsedAddresses = await adrResService.resolve(
84 query: query,
85 wallet: wallet,
86 currency: currentCurrency,
87 );
88
89 if (parsedAddresses.isEmpty) return null;
90
91 final resolvedAddress = parsedAddresses.first.parsedAddressByCurrencyMap[currentCurrency];
92 if (resolvedAddress == null || resolvedAddress.isEmpty) return null;
93
94 return parsedAddresses.first;
95 }
96
97 @action
98 void applyParsedAddress(ParsedAddress parsedAddress) {
99 final currentCurrency = currency;
100 if (currentCurrency == null) return;
101
102 final resolvedAddress = parsedAddress.parsedAddressByCurrencyMap[currentCurrency];
103 if (resolvedAddress == null || resolvedAddress.isEmpty) return;
104
105 address = resolvedAddress;
106 displayName =
107 parsedAddress.profileName.isNotEmpty ? parsedAddress.profileName : parsedAddress.handle;
108 }
109
110 Future<void> save() async {
111 try {
112 state = IsExecutingState();
113 final now = DateTime.now();
114
115 final nameExists = _contact == null
116 ? doesContactNameExist(name)
117 : doesContactNameExist(name) && _contact.original.name != name;
118
119 if (nameExists) {
120 state = FailureState(S.current.contact_name_exists);
121 return;
122 }
123
124 if (_contact != null && _contact.original.isInBox) {
125 _contact.name = name;
126 _contact.address = address;
127 _contact.type = currency!;
128 _contact.displayName = displayName;
129 _contact.lastChange = now;
130 await _contact.save();
131 } else {
132 await _contacts.add(Contact(
133 name: name,
134 address: address,
135 type: currency!,
136 lastChange: now,
137 displayName: displayName));
138 }
139
140 lastChange = now;
141 state = ExecutedSuccessfullyState();
142 } catch (e) {
143 state = FailureState(e.toString());
144 }
145 }
146
147 bool doesContactNameExist(String name) {
148 return _contacts.values.any((contact) => contact.name == name);
149 }
150 }