151 lines
4.5 KiB
Dart
151 lines
4.5 KiB
Dart
import 'package:flutter/material.dart';
|
||
import '/data/models/contact_model.dart';
|
||
import '/data/repositories/contact_repository.dart';
|
||
import '/domain/services/crypto_service.dart';
|
||
import 'dart:isolate';
|
||
import 'package:cryptography/cryptography.dart';
|
||
import 'package:flutter/foundation.dart';
|
||
|
||
class ContactProvider extends ChangeNotifier {
|
||
final ContactRepository _repository = ContactRepository();
|
||
final CryptoService _cryptoService;
|
||
|
||
ContactProvider(this._cryptoService);
|
||
final Map<int, SecretKey> _sharedKeysCache = {};
|
||
List<Contact> _contacts = [];
|
||
List<Contact> _allContacts = [];
|
||
bool _isLoading = false;
|
||
bool _isFirstLoad = true;
|
||
String? _error;
|
||
int? _currentUserId;
|
||
|
||
List<Contact> get contacts => _contacts;
|
||
List<Contact> get allContacts => _allContacts;
|
||
bool get isLoading => _isLoading;
|
||
String? get error => _error;
|
||
Map<int, SecretKey> get sharedKeysCache => _sharedKeysCache;
|
||
|
||
void setSharedKey(int contactId, SecretKey key) {
|
||
_sharedKeysCache[contactId] = key;
|
||
}
|
||
|
||
void setCurrentUserId(int? id) {
|
||
_currentUserId = id;
|
||
notifyListeners();
|
||
}
|
||
|
||
int? getCurrentUserId() {
|
||
return _currentUserId;
|
||
}
|
||
|
||
Future<void> loadContacts({bool enrichContacts = true}) async {
|
||
if (_isFirstLoad) {
|
||
_isFirstLoad = false;
|
||
_isLoading = true;
|
||
}
|
||
_error = null;
|
||
notifyListeners();
|
||
|
||
try {
|
||
final allContacts = await _repository.fetchChatContacts();
|
||
final userIdCopy = _currentUserId;
|
||
_contacts = await Isolate.run(() {
|
||
return allContacts
|
||
.where((contact) => contact.id != userIdCopy)
|
||
.toList();
|
||
});
|
||
// Check if user changed during isolate execution
|
||
if (userIdCopy != _currentUserId) {
|
||
return; // Discard stale data
|
||
}
|
||
_allContacts = _contacts;
|
||
_isLoading = false;
|
||
notifyListeners();
|
||
|
||
if (enrichContacts) {
|
||
await _enrichContactsWithLastMessages();
|
||
}
|
||
} catch (e) {
|
||
_error = e.toString();
|
||
print("❌ ОШИБКА ПРИ ЗАГРУЗКЕ КОНТАКТОВ: $_error");
|
||
} finally {
|
||
if (_error != null) {
|
||
_isLoading = false;
|
||
}
|
||
notifyListeners();
|
||
}
|
||
}
|
||
|
||
Future<void> loadAllContactsForNewChat() async {
|
||
_isLoading = true;
|
||
_error = null;
|
||
notifyListeners();
|
||
|
||
try {
|
||
final allContacts = await _repository.fetchAllUsers();
|
||
_allContacts = allContacts
|
||
.where((contact) => contact.id != _currentUserId)
|
||
.toList();
|
||
} catch (e) {
|
||
_error = e.toString();
|
||
} finally {
|
||
_isLoading = false;
|
||
notifyListeners();
|
||
}
|
||
}
|
||
|
||
Future<void> _enrichContactsWithLastMessages() async {
|
||
final myPrivKeyBase64 = await _cryptoService.getPrivateKey();
|
||
if (myPrivKeyBase64 == null) return;
|
||
|
||
// Создаем локальные копии для передачи
|
||
final contactsToProcess = List<Contact>.from(_contacts);
|
||
final cacheCopy = Map<int, SecretKey>.from(_sharedKeysCache);
|
||
|
||
print('Avialable cache for contacts: ${cacheCopy.length}');
|
||
|
||
try {
|
||
final updatedContacts = await compute(
|
||
CryptoService.bulkDecryptContacts,
|
||
{
|
||
'contacts': contactsToProcess,
|
||
'privKey': myPrivKeyBase64,
|
||
'cache': cacheCopy,
|
||
},
|
||
);
|
||
for (var contact in updatedContacts) {
|
||
print('Decrypted contact: ${contact.name} ${contact.surname}, lastMessage: ${contact.lastMessage}, isDecrypted: ${contact.isLastMsgDecrypted}');
|
||
}
|
||
_contacts = updatedContacts;
|
||
notifyListeners();
|
||
} catch (e) {
|
||
print("Ошибка дешифровки: $e");
|
||
}
|
||
}
|
||
|
||
Future<void> updateContact(int userId) async {
|
||
try {
|
||
final updatedContact = await _repository.fetchContactById(userId);
|
||
final index = _contacts.indexWhere((c) => c.id == userId);
|
||
if (index != -1) {
|
||
// Обновляем только поля профиля, сохраняя lastMessage и т.д.
|
||
final existing = _contacts[index];
|
||
_contacts[index] = existing.copyWith(
|
||
username: updatedContact.username,
|
||
name: updatedContact.name,
|
||
surname: updatedContact.surname,
|
||
avatarUrl: updatedContact.avatarUrl,
|
||
avatarFileId: updatedContact.avatarFileId,
|
||
isOnline: updatedContact.isOnline,
|
||
publicKey: updatedContact.publicKey,
|
||
);
|
||
print("Контакт ${updatedContact.name} ${updatedContact.surname} ${updatedContact.id} ${updatedContact.avatarFileId} ${updatedContact.avatarUrl} обновлен");
|
||
notifyListeners();
|
||
}
|
||
} catch (e) {
|
||
print("Error updating contact: $e");
|
||
}
|
||
}
|
||
|
||
}
|