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 _sharedKeysCache = {}; List _contacts = []; List _allContacts = []; bool _isLoading = false; bool _isFirstLoad = true; String? _error; int? _currentUserId; List get contacts => _contacts; List get allContacts => _allContacts; bool get isLoading => _isLoading; String? get error => _error; Map get sharedKeysCache => _sharedKeysCache; void setSharedKey(int contactId, SecretKey key) { _sharedKeysCache[contactId] = key; } void setCurrentUserId(int? id) { _currentUserId = id; notifyListeners(); } int? getCurrentUserId() { return _currentUserId; } Future 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 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 _enrichContactsWithLastMessages() async { final myPrivKeyBase64 = await _cryptoService.getPrivateKey(); if (myPrivKeyBase64 == null) return; // Создаем локальные копии для передачи final contactsToProcess = List.from(_contacts); final cacheCopy = Map.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 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"); } } }