Chepuhagram/lib/logic/contact_provider.dart

150 lines
4.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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,
);
notifyListeners();
}
} catch (e) {
print("Error updating contact: $e");
}
}
}