Отображение чатов
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import 'package:isar/isar.dart';
|
||||
import '../../../../core/errors/result.dart';
|
||||
import '../../../../core/errors/errors.dart';
|
||||
import '../../domain/entities/chat.dart';
|
||||
import '../../domain/entities/message.dart';
|
||||
import '../models/chat_model.dart';
|
||||
import '../models/message_model.dart';
|
||||
import 'chat_local_datasource.dart';
|
||||
|
||||
class ChatLocalDataSourceImpl implements ChatLocalDataSource {
|
||||
final Isar isar;
|
||||
|
||||
ChatLocalDataSourceImpl(this.isar);
|
||||
|
||||
@override
|
||||
Future<Result<List<Chat>>> getCachedChats() async {
|
||||
try {
|
||||
final chatModels = await isar.chatModels.where().sortByLastMessageTimeDesc().findAll();
|
||||
return Result.success(chatModels.map((m) => m.toEntity()).toList());
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.database(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> cacheChats(List<Chat> chats) async {
|
||||
try {
|
||||
final models = chats.map((c) => ChatModel.fromEntity(c)).toList();
|
||||
await isar.writeTxn(() async {
|
||||
await isar.chatModels.putAll(models);
|
||||
});
|
||||
return const Result.success(null);
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.database(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Chat>> getChatFromCache(String chatId) async {
|
||||
try {
|
||||
final model = await isar.chatModels.filter().idEqualTo(chatId).findFirst();
|
||||
if (model != null) {
|
||||
return Result.success(model.toEntity());
|
||||
}
|
||||
return const Result.failure(AppError.notFound(message: 'Chat not found in cache'));
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.database(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> cacheChat(Chat chat) async {
|
||||
try {
|
||||
final model = ChatModel.fromEntity(chat);
|
||||
await isar.writeTxn(() async {
|
||||
await isar.chatModels.put(model);
|
||||
});
|
||||
return const Result.success(null);
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.database(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Message>>> getMessagesFromCache(String chatId) async {
|
||||
try {
|
||||
final messageModels = await isar.messageModels
|
||||
.filter()
|
||||
.chatIdEqualTo(chatId)
|
||||
.sortByCreatedAtDesc()
|
||||
.findAll();
|
||||
return Result.success(messageModels.map((m) => m.toEntity()).toList());
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.database(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> cacheMessages(String chatId, List<Message> messages) async {
|
||||
try {
|
||||
final models = messages.map((m) => MessageModel.fromEntity(m)).toList();
|
||||
await isar.writeTxn(() async {
|
||||
await isar.messageModels.putAll(models);
|
||||
});
|
||||
return const Result.success(null);
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.database(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> clearCache() async {
|
||||
try {
|
||||
await isar.writeTxn(() => isar.clear());
|
||||
return const Result.success(null);
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.database(message: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,13 @@ import '../../domain/entities/chat.dart';
|
||||
import '../../domain/entities/message.dart';
|
||||
|
||||
abstract class ChatRemoteDataSource {
|
||||
Future<Result<List<Chat>>> getChats();
|
||||
Future<Result<List<Chat>>> getChats({String? currentUserId});
|
||||
Future<Result<Chat>> getChatById(String chatId);
|
||||
Future<Result<void>> createChat(String title, List<String> participantIds);
|
||||
Future<Result<void>> sendMessage(String chatId, Message message);
|
||||
Future<Result<List<Message>>> getMessages(String chatId, {int? limit, String? lastMessageId});
|
||||
Stream<Result<Message>> listenToMessages(String chatId);
|
||||
Future<Result<Chat>> createPersonalChat(String userId);
|
||||
Future<Result<Chat>> createGroupChat(String name, List<String> memberIds);
|
||||
Future<Result<Chat>> getOrCreateFavorites();
|
||||
Future<Result<Message>> sendMessage(String chatId, String content, {String? type, List<Map<String, dynamic>>? attachments});
|
||||
Future<Result<List<Message>>> getMessages(String chatId, {String? cursor});
|
||||
Future<Result<void>> togglePin(String chatId);
|
||||
Future<Result<void>> clearChat(String chatId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
import '../../../../core/network/api_client.dart';
|
||||
import '../../../../core/errors/result.dart';
|
||||
import '../../../../core/errors/errors.dart';
|
||||
import '../../domain/entities/chat.dart';
|
||||
import '../../domain/entities/message.dart';
|
||||
import '../../domain/entities/user.dart';
|
||||
import 'chat_remote_datasource.dart';
|
||||
|
||||
class ChatRemoteDataSourceImpl implements ChatRemoteDataSource {
|
||||
final ApiClient apiClient;
|
||||
|
||||
ChatRemoteDataSourceImpl(this.apiClient);
|
||||
|
||||
@override
|
||||
Future<Result<List<Chat>>> getChats({String? currentUserId}) async {
|
||||
final result = await apiClient.get<List<dynamic>>('/api/chats');
|
||||
return result.fold(
|
||||
(error) => Result.failure(error),
|
||||
(data) {
|
||||
try {
|
||||
final chats = data.map((json) => _mapChatJson(json, currentUserId: currentUserId)).toList();
|
||||
// Sort: favorites first, then by last message time or creation time
|
||||
chats.sort((a, b) {
|
||||
if (a.type == 'favorites') return -1;
|
||||
if (b.type == 'favorites') return 1;
|
||||
final timeA = a.lastMessageTime ?? DateTime.fromMillisecondsSinceEpoch(0);
|
||||
final timeB = b.lastMessageTime ?? DateTime.fromMillisecondsSinceEpoch(0);
|
||||
return timeB.compareTo(timeA);
|
||||
});
|
||||
return Result.success(chats);
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.parsing(message: 'Failed to parse chats: $e'));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Chat>> getChatById(String chatId) async {
|
||||
final result = await apiClient.get<Map<String, dynamic>>('/api/chats/$chatId');
|
||||
return result.fold(
|
||||
(error) => Result.failure(error),
|
||||
(data) {
|
||||
try {
|
||||
return Result.success(_mapChatJson(data));
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.parsing(message: 'Failed to parse chat: $e'));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Chat>> createPersonalChat(String userId) async {
|
||||
final result = await apiClient.post<Map<String, dynamic>>(
|
||||
'/api/chats/personal',
|
||||
data: {'userId': userId},
|
||||
);
|
||||
return result.fold(
|
||||
(error) => Result.failure(error),
|
||||
(data) => Result.success(_mapChatJson(data)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Chat>> createGroupChat(String name, List<String> memberIds) async {
|
||||
final result = await apiClient.post<Map<String, dynamic>>(
|
||||
'/api/chats/group',
|
||||
data: {
|
||||
'name': name,
|
||||
'memberIds': memberIds,
|
||||
},
|
||||
);
|
||||
return result.fold(
|
||||
(error) => Result.failure(error),
|
||||
(data) => Result.success(_mapChatJson(data)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Chat>> getOrCreateFavorites() async {
|
||||
final result = await apiClient.post<Map<String, dynamic>>('/api/chats/favorites');
|
||||
return result.fold(
|
||||
(error) => Result.failure(error),
|
||||
(data) => Result.success(_mapChatJson(data)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Message>> sendMessage(String chatId, String content, {String? type, List<Map<String, dynamic>>? attachments}) async {
|
||||
final result = await apiClient.post<Map<String, dynamic>>(
|
||||
'/api/messages/chat/$chatId',
|
||||
data: {
|
||||
'content': content,
|
||||
'type': type ?? 'Text',
|
||||
'attachments': attachments,
|
||||
},
|
||||
);
|
||||
return result.fold(
|
||||
(error) => Result.failure(error),
|
||||
(data) {
|
||||
try {
|
||||
return Result.success(_mapMessageJson(data));
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.parsing(message: 'Failed to parse message: $e'));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Message>>> getMessages(String chatId, {String? cursor}) async {
|
||||
final result = await apiClient.get<List<dynamic>>(
|
||||
'/api/messages/chat/$chatId',
|
||||
queryParameters: cursor != null ? {'cursor': cursor} : null,
|
||||
);
|
||||
return result.fold(
|
||||
(error) => Result.failure(error),
|
||||
(data) {
|
||||
try {
|
||||
return Result.success(data.map((json) => _mapMessageJson(json)).toList());
|
||||
} catch (e) {
|
||||
return Result.failure(AppError.parsing(message: 'Failed to parse messages: $e'));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> togglePin(String chatId) async {
|
||||
return await apiClient.post('/api/chats/$chatId/pin');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> clearChat(String chatId) async {
|
||||
return await apiClient.post('/api/chats/$chatId/clear');
|
||||
}
|
||||
|
||||
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>?;
|
||||
return User(
|
||||
id: m['userId'] ?? (userData?['id'] ?? ''),
|
||||
name: userData?['displayName'] ?? '',
|
||||
avatarUrl: userData?['avatar'],
|
||||
);
|
||||
}).toList();
|
||||
|
||||
final lastMsgJson = json['lastMessage'] ?? (json['messages'] as List?)?.firstOrNull;
|
||||
final type = json['type']?.toString().toLowerCase() ?? 'personal';
|
||||
|
||||
String title = json['name'] ?? '';
|
||||
if (title.isEmpty && type == 'personal' && members != null && members.isNotEmpty) {
|
||||
// If personal chat and no title, use the OTHER member's name
|
||||
try {
|
||||
final otherMember = members.firstWhere(
|
||||
(m) => m.id != currentUserId && m.name.isNotEmpty,
|
||||
orElse: () => members.firstWhere((m) => m.id != currentUserId, orElse: () => members[0]),
|
||||
);
|
||||
title = otherMember.name;
|
||||
} catch (_) {
|
||||
title = members[0].name;
|
||||
}
|
||||
}
|
||||
|
||||
return Chat(
|
||||
id: json['id'],
|
||||
type: type,
|
||||
title: title,
|
||||
avatarUrl: json['avatar'],
|
||||
participants: members,
|
||||
unreadCount: json['unreadCount'] ?? 0,
|
||||
isPinned: json['isPinned'] ?? false,
|
||||
lastMessage: lastMsgJson != null ? _mapMessageJson(lastMsgJson) : null,
|
||||
lastMessageTime: lastMsgJson != null ? DateTime.parse(lastMsgJson['createdAt']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
Message _mapMessageJson(Map<String, dynamic> json) {
|
||||
return Message(
|
||||
id: json['id'],
|
||||
chatId: json['chatId'],
|
||||
senderId: 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import 'package:isar/isar.dart';
|
||||
import '../../domain/entities/chat.dart';
|
||||
import '../../domain/entities/user.dart';
|
||||
import '../../domain/entities/message.dart';
|
||||
import 'message_model.dart';
|
||||
|
||||
part 'chat_model.g.dart';
|
||||
|
||||
@collection
|
||||
class ChatModel {
|
||||
Id isarId = Isar.autoIncrement;
|
||||
|
||||
@Index(unique: true, replace: true)
|
||||
late String id;
|
||||
|
||||
late String type;
|
||||
late String title;
|
||||
String? avatarUrl;
|
||||
|
||||
late List<UserModel> participants;
|
||||
|
||||
LastMessageModel? lastMessage;
|
||||
|
||||
DateTime? lastMessageTime;
|
||||
|
||||
int unreadCount = 0;
|
||||
bool isMuted = false;
|
||||
bool isPinned = false;
|
||||
|
||||
Chat toEntity() {
|
||||
return Chat(
|
||||
id: id,
|
||||
type: type,
|
||||
title: title,
|
||||
avatarUrl: avatarUrl,
|
||||
participants: participants.map((u) => u.toEntity()).toList(),
|
||||
lastMessage: lastMessage?.toEntity(),
|
||||
lastMessageTime: lastMessageTime,
|
||||
unreadCount: unreadCount,
|
||||
isMuted: isMuted,
|
||||
isPinned: isPinned,
|
||||
);
|
||||
}
|
||||
|
||||
static ChatModel fromEntity(Chat chat) {
|
||||
return ChatModel()
|
||||
..id = chat.id
|
||||
..type = chat.type
|
||||
..title = chat.title
|
||||
..avatarUrl = chat.avatarUrl
|
||||
..participants = chat.participants?.map((u) => UserModel.fromEntity(u)).toList() ?? []
|
||||
..lastMessage = chat.lastMessage != null ? LastMessageModel.fromEntity(chat.lastMessage!) : null
|
||||
..lastMessageTime = chat.lastMessageTime
|
||||
..unreadCount = chat.unreadCount
|
||||
..isMuted = chat.isMuted
|
||||
..isPinned = chat.isPinned;
|
||||
}
|
||||
}
|
||||
|
||||
@embedded
|
||||
class LastMessageModel {
|
||||
late String id;
|
||||
late String content;
|
||||
late String messageType;
|
||||
DateTime? createdAt;
|
||||
|
||||
Message toEntity() {
|
||||
return Message(
|
||||
id: id,
|
||||
chatId: '', // Не критично для превью в списке чатов
|
||||
senderId: '',
|
||||
content: content,
|
||||
messageType: messageType,
|
||||
createdAt: createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
static LastMessageModel fromEntity(Message message) {
|
||||
return LastMessageModel()
|
||||
..id = message.id
|
||||
..content = message.content
|
||||
..messageType = message.messageType
|
||||
..createdAt = message.createdAt;
|
||||
}
|
||||
}
|
||||
|
||||
@embedded
|
||||
class UserModel {
|
||||
late String id;
|
||||
late String name;
|
||||
String? avatarUrl;
|
||||
String? role;
|
||||
DateTime? lastSeen;
|
||||
bool? isOnline;
|
||||
|
||||
User toEntity() {
|
||||
return User(
|
||||
id: id,
|
||||
name: name,
|
||||
avatarUrl: avatarUrl,
|
||||
role: role,
|
||||
lastSeen: lastSeen,
|
||||
isOnline: isOnline,
|
||||
);
|
||||
}
|
||||
|
||||
static UserModel fromEntity(User user) {
|
||||
return UserModel()
|
||||
..id = user.id
|
||||
..name = user.name
|
||||
..avatarUrl = user.avatarUrl
|
||||
..role = user.role
|
||||
..lastSeen = user.lastSeen
|
||||
..isOnline = user.isOnline;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
import 'package:isar/isar.dart';
|
||||
import '../../domain/entities/message.dart';
|
||||
|
||||
part 'message_model.g.dart';
|
||||
|
||||
@collection
|
||||
class MessageModel {
|
||||
Id isarId = Isar.autoIncrement;
|
||||
|
||||
@Index(unique: true, replace: true)
|
||||
late String id;
|
||||
|
||||
@Index()
|
||||
late String chatId;
|
||||
|
||||
late String senderId;
|
||||
late String content;
|
||||
late String messageType;
|
||||
|
||||
@Index()
|
||||
DateTime? createdAt;
|
||||
|
||||
DateTime? updatedAt;
|
||||
bool isRead = false;
|
||||
|
||||
// For simplicity, store media as a JSON string or ignore for now
|
||||
String? mediaJson;
|
||||
|
||||
Message toEntity() {
|
||||
return Message(
|
||||
id: id,
|
||||
chatId: chatId,
|
||||
senderId: senderId,
|
||||
content: content,
|
||||
messageType: messageType,
|
||||
createdAt: createdAt,
|
||||
updatedAt: updatedAt,
|
||||
isRead: isRead,
|
||||
);
|
||||
}
|
||||
|
||||
static MessageModel fromEntity(Message message) {
|
||||
return MessageModel()
|
||||
..id = message.id
|
||||
..chatId = message.chatId
|
||||
..senderId = message.senderId
|
||||
..content = message.content
|
||||
..messageType = message.messageType
|
||||
..createdAt = message.createdAt
|
||||
..updatedAt = message.updatedAt
|
||||
..isRead = message.isRead ?? false;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,47 +1,133 @@
|
||||
import '../../../../core/errors/errors.dart';
|
||||
import 'dart:async';
|
||||
import '../../../../core/errors/result.dart';
|
||||
import '../../../../core/network/signalr_service.dart';
|
||||
import '../../domain/entities/chat.dart';
|
||||
import '../../domain/entities/message.dart';
|
||||
import '../../domain/repositories/chat_repository.dart';
|
||||
import '../datasources/chat_local_datasource.dart';
|
||||
import '../datasources/chat_remote_datasource.dart';
|
||||
|
||||
class ChatRepositoryImpl implements ChatRepository {
|
||||
@override
|
||||
Future<Result<void>> createChat(String title, List<String> participantIds) async {
|
||||
return const Result.success(null);
|
||||
}
|
||||
final ChatRemoteDataSource remoteDataSource;
|
||||
final ChatLocalDataSource localDataSource;
|
||||
final SignalRService signalRService;
|
||||
|
||||
ChatRepositoryImpl({
|
||||
required this.remoteDataSource,
|
||||
required this.localDataSource,
|
||||
required this.signalRService,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Result<void>> deleteChat(String chatId) async {
|
||||
return const Result.success(null);
|
||||
Stream<Message> get messageStream => signalRService.messages;
|
||||
|
||||
@override
|
||||
Future<void> initSignalR() => signalRService.init();
|
||||
|
||||
@override
|
||||
Future<void> disposeSignalR() => signalRService.stop();
|
||||
|
||||
@override
|
||||
Future<Result<List<Chat>>> getChats({String? currentUserId}) async {
|
||||
// 1. Return cached chats immediately if available
|
||||
final cachedResult = await localDataSource.getCachedChats();
|
||||
|
||||
// 2. Fetch from remote and update cache
|
||||
final remoteResult = await remoteDataSource.getChats(currentUserId: currentUserId);
|
||||
if (remoteResult.isSuccess) {
|
||||
final chats = remoteResult.data!;
|
||||
await localDataSource.cacheChats(chats);
|
||||
return Result.success(chats);
|
||||
}
|
||||
|
||||
// If remote fails, return cached or error
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Chat>> getChatById(String chatId) async {
|
||||
return const Result.failure(AppError.notFound(message: 'Chat not found'));
|
||||
final remoteResult = await remoteDataSource.getChatById(chatId);
|
||||
if (remoteResult.isSuccess) {
|
||||
await localDataSource.cacheChat(remoteResult.data!);
|
||||
return remoteResult;
|
||||
}
|
||||
return localDataSource.getChatFromCache(chatId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Chat>>> getChats() async {
|
||||
// Return empty list for now
|
||||
return const Result.success([]);
|
||||
Future<Result<Chat>> createPersonalChat(String userId) async {
|
||||
final result = await remoteDataSource.createPersonalChat(userId);
|
||||
if (result.isSuccess) {
|
||||
await localDataSource.cacheChat(result.data!);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Message>>> getMessages(
|
||||
String chatId, {
|
||||
int? limit,
|
||||
String? lastMessageId,
|
||||
}) async {
|
||||
return const Result.success([]);
|
||||
Future<Result<Chat>> createGroupChat(String name, List<String> memberIds) async {
|
||||
final result = await remoteDataSource.createGroupChat(name, memberIds);
|
||||
if (result.isSuccess) {
|
||||
await localDataSource.cacheChat(result.data!);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> sendMessage(String chatId, Message message) async {
|
||||
return const Result.success(null);
|
||||
Future<Result<Chat>> getOrCreateFavorites() async {
|
||||
final result = await remoteDataSource.getOrCreateFavorites();
|
||||
if (result.isSuccess) {
|
||||
await localDataSource.cacheChat(result.data!);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> updateChat(String chatId, String title) async {
|
||||
return const Result.success(null);
|
||||
Future<Result<Message>> sendMessage(String chatId, String content, {String? type}) async {
|
||||
final result = await remoteDataSource.sendMessage(chatId, content, type: type);
|
||||
if (result.isSuccess) {
|
||||
// We don't cache individual messages here usually,
|
||||
// let SignalR ReceiveMessage handle it or update list
|
||||
final messagesResult = await getMessages(chatId);
|
||||
if (messagesResult.isSuccess) {
|
||||
await localDataSource.cacheMessages(chatId, messagesResult.data!);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Message>>> getMessages(String chatId, {String? cursor}) async {
|
||||
if (cursor == null) {
|
||||
final cached = await localDataSource.getMessagesFromCache(chatId);
|
||||
final remote = await remoteDataSource.getMessages(chatId);
|
||||
if (remote.isSuccess) {
|
||||
await localDataSource.cacheMessages(chatId, remote.data!);
|
||||
return remote;
|
||||
}
|
||||
return cached;
|
||||
} else {
|
||||
return remoteDataSource.getMessages(chatId, cursor: cursor);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> togglePin(String chatId) async {
|
||||
final result = await remoteDataSource.togglePin(chatId);
|
||||
if (result.isSuccess) {
|
||||
final chat = await getChatById(chatId);
|
||||
if (chat.isSuccess) {
|
||||
await localDataSource.cacheChat(chat.data!);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> clearChat(String chatId) async {
|
||||
final result = await remoteDataSource.clearChat(chatId);
|
||||
if (result.isSuccess) {
|
||||
await localDataSource.cacheMessages(chatId, []);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user