import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; import 'package:result_monad/result_monad.dart'; import '../friendica_client/friendica_client.dart'; import '../friendica_client/paging_data.dart'; import '../globals.dart'; import '../models/auth/oauth_credentials.dart'; import '../models/auth/profile.dart'; import '../models/connection.dart'; import '../models/direct_message.dart'; import '../models/direct_message_thread.dart'; import '../models/exec_error.dart'; import 'feature_version_checker.dart'; class DirectMessageService extends ChangeNotifier { static final _logger = Logger('$DirectMessageService'); final _threads = {}; final Profile profile; var _firstLoading = true; DirectMessageService(this.profile); void clear() { _threads.clear(); _firstLoading = true; notifyListeners(); } List getThreads({bool unreadyOnly = false}) { if (_threads.isEmpty && _firstLoading) { updateThreads(); _firstLoading = false; } if (unreadyOnly) { return _threads.values.where((t) => !t.allSeen).toList(); } return _threads.values.toList(); } Result getThreadByParentUri(String uri) { if (_threads.containsKey(uri)) { return Result.ok(_threads[uri]!); } return buildErrorResult( type: ErrorType.notFound, message: 'Thread ID not found: $uri'); } Future updateThreads() async { await DirectMessagingClient(profile).getDirectMessages(PagingData()).match( onSuccess: (update) { final newThreads = DirectMessageThread.createThreads(update); _threads.clear(); for (final t in newThreads) { //TODO do merge operation _threads[t.parentUri] = t; } _logger.fine( 'Updated ${update.length} direct messages, across ${newThreads.length} threads'); notifyListeners(); }, onError: (error) { _logger.severe('Error getting direct messages: $error'); }, ); notifyListeners(); } FutureResult newThread( Connection receiver, String text) async { if (profile.credentials is OAuthCredentials) { final result = getIt() .canUseFeatureResult(RelaticaFeatures.directMessageCreation); if (result.isFailure) { return result.errorCast(); } } final result = await DirectMessagingClient(profile).postDirectMessage( null, receiver.id, text, ); result.match(onSuccess: (newMessage) { DirectMessageThread.createThreads([newMessage]).forEach((thread) { _threads[thread.parentUri] = thread; }); notifyListeners(); }, onError: (error) { _logger.severe('Error getting direct messages: $error'); }); return result.execErrorCast(); } FutureResult newReplyMessage( String threadId, DirectMessage original, String text) async { final thread = _threads[threadId]; if (thread == null) { final error = 'Message is not for this thread: $threadId, $original'; _logger.severe(error); return buildErrorResult( type: ErrorType.notFound, message: error, ); } if (!thread.messages.contains(original)) { final error = 'Message is not for this thread: $threadId, $original'; _logger.severe(error); return buildErrorResult( type: ErrorType.notFound, message: error, ); } if (profile.credentials is OAuthCredentials) { final result = getIt() .canUseFeatureResult(RelaticaFeatures.directMessageCreation); if (result.isFailure) { return result.errorCast(); } } final result = await DirectMessagingClient(profile).postDirectMessage( original.id, original.senderId, text, ); result.match(onSuccess: (newMessage) { thread.messages.add(newMessage); notifyListeners(); }, onError: (error) { _logger.severe('Error getting direct messages: $error'); }); return result.execErrorCast(); } Future markMessageRead(String threadId, DirectMessage m) async { final thread = _threads[threadId]; if (thread == null) { _logger.severe('Message is not for this thread: $threadId, $m'); return; } final oldIndex = thread.messages.indexOf(m); if (oldIndex < 0) { _logger.severe('Message is not for this thread: $threadId, $m'); return; } await DirectMessagingClient(profile).markDirectMessageRead(m).match( onSuccess: (update) { thread.messages.removeAt(oldIndex); thread.messages.insert(oldIndex, update); notifyListeners(); }, onError: (error) { _logger.severe('Error getting direct messages: $error'); }, ); } }