Повторный вход в аккаунт, очистка кэша

This commit is contained in:
Халимов Рустам
2026-05-15 00:10:34 +03:00
parent 0b013def2e
commit 40589dbb75
21 changed files with 1732 additions and 309 deletions
@@ -90,10 +90,16 @@ class ChatLocalDataSourceImpl implements ChatLocalDataSource {
@override
Future<Result<void>> clearCache() async {
// ignore: avoid_print
print('[DEBUG] ChatLocalDataSource.clearCache calling isar.clear()');
try {
await isar.writeTxn(() => isar.clear());
// ignore: avoid_print
print('[DEBUG] ChatLocalDataSource.clearCache SUCCESS');
return const Result.success(null);
} catch (e) {
// ignore: avoid_print
print('[DEBUG] ChatLocalDataSource.clearCache ERROR: $e');
return Result.failure(AppError.database(message: e.toString()));
}
}
@@ -137,16 +137,23 @@ class ChatRemoteDataSourceImpl implements ChatRemoteDataSource {
}
Chat _mapChatJson(Map<String, dynamic> json, {String? currentUserId}) {
final members = (json['members'] as List<dynamic>?)?.map((m) {
final userData = m['user'] as Map<String, dynamic>?;
final membersData = json['members'] ?? json['participants'];
final members = (membersData as List<dynamic>?)?.map((m) {
final userData = m is Map<String, dynamic> ? (m['user'] ?? m) : m;
return User(
id: m['userId'] ?? (userData?['id'] ?? ''),
name: userData?['displayName'] ?? '',
avatarUrl: userData?['avatar'],
id: (m is Map ? m['userId'] : null) ?? (userData?['id'] ?? ''),
name: userData?['displayName'] ?? (userData?['name'] ?? ''),
avatarUrl: userData?['avatar'] ?? userData?['avatarUrl'],
isOnline: userData?['isOnline'] ?? userData?['IsOnline'] ?? false,
lastSeen: _parseDateTime(userData?['lastSeen'] ?? userData?['LastSeen']),
);
}).toList();
final lastMsgJson = json['lastMessage'] ?? (json['messages'] as List?)?.firstOrNull;
dynamic lastMsgRaw = json['lastMessage'];
if (lastMsgRaw is List && lastMsgRaw.isNotEmpty) {
lastMsgRaw = lastMsgRaw.first;
}
final lastMsgJson = lastMsgRaw ?? (json['messages'] as List?)?.firstOrNull;
final type = json['type']?.toString().toLowerCase() ?? 'personal';
String title = json['name'] ?? '';
@@ -171,21 +178,36 @@ class ChatRemoteDataSourceImpl implements ChatRemoteDataSource {
participants: members,
unreadCount: json['unreadCount'] ?? 0,
isPinned: json['isPinned'] ?? false,
lastMessage: lastMsgJson != null ? _mapMessageJson(lastMsgJson) : null,
lastMessageTime: lastMsgJson != null ? DateTime.parse(lastMsgJson['createdAt']) : null,
lastMessage: lastMsgJson != null && lastMsgJson is Map<String, dynamic>
? _mapMessageJson(lastMsgJson)
: null,
lastMessageTime: lastMsgJson != null && lastMsgJson is Map<String, dynamic>
? _parseDateTime(lastMsgJson['createdAt'])
: null,
);
}
Message _mapMessageJson(Map<String, dynamic> json) {
return Message(
id: json['id'],
chatId: json['chatId'],
senderId: json['senderId'],
id: json['id'] ?? '',
chatId: json['chatId'] ?? '',
senderId: json['userId'] ?? (json['senderId'] ?? ''),
content: json['content'] ?? '',
messageType: json['type'] ?? 'Text',
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
isRead: (json['readBy'] as List?)?.isNotEmpty ?? false,
messageType: json['type']?.toString().toLowerCase() ?? 'text',
createdAt: _parseDateTime(json['createdAt']),
updatedAt: _parseDateTime(json['updatedAt']),
isRead: json['isRead'] ?? false,
media: json['media'] is Map<String, dynamic> ? json['media'] as Map<String, dynamic> : null,
);
}
DateTime? _parseDateTime(String? dateStr) {
if (dateStr == null) return null;
// If it doesn't have a timezone indicator, assume it's UTC
String normalized = dateStr;
if (!normalized.endsWith('Z') && !normalized.contains('+')) {
normalized += 'Z';
}
return DateTime.parse(normalized).toLocal();
}
}
@@ -21,6 +21,12 @@ class ChatRepositoryImpl implements ChatRepository {
@override
Stream<Message> get messageStream => signalRService.messages;
@override
Stream<Map<String, dynamic>> get typingStream => signalRService.typingUpdates;
@override
Future<void> sendTypingStatus(String chatId, bool isTyping) => signalRService.sendTypingStatus(chatId, isTyping);
@override
Future<void> initSignalR() => signalRService.init();
@@ -29,6 +35,8 @@ class ChatRepositoryImpl implements ChatRepository {
@override
Future<Result<List<Chat>>> getChats({String? currentUserId}) async {
// ignore: avoid_print
print('[DEBUG] ChatRepository.getChats for user: $currentUserId');
// 1. Return cached chats immediately if available
final cachedResult = await localDataSource.getCachedChats();
@@ -36,10 +44,14 @@ class ChatRepositoryImpl implements ChatRepository {
final remoteResult = await remoteDataSource.getChats(currentUserId: currentUserId);
if (remoteResult.isSuccess) {
final chats = remoteResult.data!;
// ignore: avoid_print
print('[DEBUG] Remote getChats success: ${chats.length} chats');
await localDataSource.cacheChats(chats);
return Result.success(chats);
}
// ignore: avoid_print
print('[DEBUG] Remote getChats failed or empty');
// If remote fails, return cached or error
return cachedResult;
}
@@ -97,13 +109,19 @@ class ChatRepositoryImpl implements ChatRepository {
@override
Future<Result<List<Message>>> getMessages(String chatId, {String? cursor}) async {
// ignore: avoid_print
print('[DEBUG] ChatRepository.getMessages for chat: $chatId');
if (cursor == null) {
final cached = await localDataSource.getMessagesFromCache(chatId);
final remote = await remoteDataSource.getMessages(chatId);
if (remote.isSuccess) {
// ignore: avoid_print
print('[DEBUG] Remote getMessages success: ${remote.data!.length} messages');
await localDataSource.cacheMessages(chatId, remote.data!);
return remote;
}
// ignore: avoid_print
print('[DEBUG] Remote getMessages failed: ${remote.failure?.message}');
return cached;
} else {
return remoteDataSource.getMessages(chatId, cursor: cursor);
@@ -130,4 +148,7 @@ class ChatRepositoryImpl implements ChatRepository {
}
return result;
}
@override
Future<Result<void>> clearCache() => localDataSource.clearCache();
}