124 lines
4.2 KiB
Dart
124 lines
4.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '/data/models/contact_model.dart';
|
|
import '/data/repositories/contact_repository.dart';
|
|
import '/data/datasources/local_db_service.dart';
|
|
import '/domain/services/crypto_service.dart';
|
|
|
|
class ContactProvider extends ChangeNotifier {
|
|
final ContactRepository _repository = ContactRepository();
|
|
final LocalDbService _localDbService = LocalDbService();
|
|
final CryptoService _cryptoService = CryptoService();
|
|
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;
|
|
|
|
void setCurrentUserId(int? id) {
|
|
_currentUserId = id;
|
|
notifyListeners();
|
|
}
|
|
|
|
int? getCurrentUserId() {
|
|
return _currentUserId;
|
|
}
|
|
|
|
Future<void> loadContacts() async {
|
|
if (_isFirstLoad) {
|
|
_isFirstLoad = false;
|
|
_isLoading = true;
|
|
}
|
|
_error = null;
|
|
notifyListeners();
|
|
|
|
try {
|
|
final allContacts = await _repository.fetchChatContacts();
|
|
// Фильтруем: исключаем себя (для основного списка - только чаты)
|
|
_contacts = allContacts
|
|
.where((contact) => contact.id != _currentUserId)
|
|
.toList();
|
|
_allContacts = _contacts;
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
|
|
// Обогащаем превью последним сообщением из локальной БД, не блокируя UI.
|
|
_enrichContactsWithLastMessages();
|
|
} catch (e) {
|
|
_error = e.toString();
|
|
} finally {
|
|
// Если ошибка — выходим из состояния загрузки тут.
|
|
// Если всё ок — `_isLoading` уже сброшен выше, чтобы показать список быстрее.
|
|
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 {
|
|
print("Начинаем обогащать контакты последними сообщениями из локальной БД... Для текущего пользователя ID: $_currentUserId");
|
|
final myId = _currentUserId;
|
|
if (myId == null) return;
|
|
print("Текущий пользователь ID: $myId");
|
|
|
|
final myPrivKey = await _cryptoService.getPrivateKey();
|
|
|
|
final List<Contact> updated = List<Contact>.from(_contacts);
|
|
|
|
for (int i = 0; i < updated.length; i++) {
|
|
final contact = updated[i];
|
|
|
|
// 1) Если сервер уже прислал lastMessage — попробуем расшифровать превью.
|
|
print(contact.lastMessage);
|
|
if (contact.lastMessage != null &&
|
|
contact.lastMessage!.isNotEmpty &&
|
|
myPrivKey != null &&
|
|
contact.publicKey != null) {
|
|
try {
|
|
final sharedSecret = await _cryptoService.deriveSharedSecret(
|
|
myPrivKey,
|
|
contact.publicKey!,
|
|
);
|
|
final decrypted = await _cryptoService.decryptMessage(
|
|
contact.lastMessage!,
|
|
sharedSecret,
|
|
);
|
|
updated[i] = contact.copyWith(lastMessage: decrypted);
|
|
} catch (_) {
|
|
// Если расшифровать не удалось — оставляем как есть, дальше попробуем локальную БД.
|
|
}
|
|
}
|
|
}
|
|
|
|
_contacts = updated;
|
|
_allContacts = updated;
|
|
notifyListeners();
|
|
}
|
|
}
|