relatica/lib/riverpod_controllers/direct_message_services.dart

183 wiersze
5.2 KiB
Dart

import 'package:logging/logging.dart';
import 'package:result_monad/result_monad.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:stack_trace/stack_trace.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 '../models/networking/paging_data.dart';
import 'feature_checker_services.dart';
import 'networking/friendica_dms_client_services.dart';
import 'notification_services.dart';
part 'direct_message_services.g.dart';
@Riverpod(keepAlive: true)
class DirectMessageThreadIds extends _$DirectMessageThreadIds {
static final _logger = Logger('DirectMessageThreadIdsProvider');
@override
List<String> build(Profile profile) {
update();
return [];
}
Future<void> update() async {
final threads = <String>[];
await ref.read(directMessagesProvider(profile, PagingData()).future).match(
onSuccess: (update) {
final newThreads = DirectMessageThread.createThreads(profile, update);
for (final t in newThreads) {
threads.add(t.parentUri);
ref
.read(directMessageThreadServiceProvider(profile, t.parentUri)
.notifier)
.update(t);
}
_logger.fine(
'Updated ${update.length} direct messages, across ${newThreads.length} threads');
},
onError: (error) {
_logger.severe(
'Error getting direct messages: $error',
Trace.current(),
);
},
);
state = threads;
}
FutureResult<DirectMessage, ExecError> newThread(
Connection receiver, String text) async {
if (profile.credentials is OAuthCredentials) {
final result = ref.read(featureCheckResultProvider(
profile, RelaticaFeatures.directMessageCreation));
if (result.isFailure) {
return result.errorCast();
}
}
final result = await ref.read(postDirectMessageProvider(
profile,
null,
receiver.id,
text,
).future);
result.match(onSuccess: (newMessage) {
DirectMessageThread.createThreads(profile, [newMessage])
.forEach((thread) {
state = [...state, thread.parentUri];
ref
.read(directMessageThreadServiceProvider(profile, thread.parentUri)
.notifier)
.update(thread);
});
}, onError: (error) {
_logger.severe('Error getting direct messages: $error', Trace.current());
});
ref.invalidateSelf();
return result.execErrorCast();
}
}
@Riverpod(keepAlive: true)
class DirectMessageThreadService extends _$DirectMessageThreadService {
static final _logger = Logger('DirectMessageThreadServiceProvider');
String threadId = '';
@override
DirectMessageThread build(Profile profile, String id) {
_logger.finest('build id = $id');
threadId = id;
state = DirectMessageThread(
messages: [],
participantIds: [],
title: 'Uninitialized',
parentUri: '',
);
return state;
}
void update(DirectMessageThread thread) {
state = thread;
}
Future<void> refresh() async {
await ref
.read(
updateThreadProvider(profile, state.parentUri, PagingData()).future)
.withResult((messages) {
messages.sort((m1, m2) => m1.createdAt.compareTo(m2.createdAt));
state = state.copy(messages: messages);
});
}
FutureResult<DirectMessage, ExecError> newReplyMessage(
DirectMessage original, String text) async {
if (!state.messages.contains(original)) {
final error =
'Message is not for this thread: ${state.parentUri}, $original';
_logger.severe(error, Trace.current());
return buildErrorResult(
type: ErrorType.notFound,
message: error,
);
}
if (profile.credentials is OAuthCredentials) {
final result = ref.read(featureCheckResultProvider(
profile, RelaticaFeatures.directMessageCreation));
if (result.isFailure) {
return result.errorCast();
}
}
final result = await ref.read(postDirectMessageProvider(
profile,
original.id,
original.senderId,
text,
).future);
result.match(onSuccess: (newMessage) {
state.messages.add(newMessage);
}, onError: (error) {
_logger.severe('Error getting direct messages: $error', Trace.current());
});
update(state);
return result.execErrorCast();
}
Future<void> markMessageRead(DirectMessage m) async {
final oldIndex = state.messages.indexOf(m);
if (oldIndex < 0) {
_logger.severe(
'Message is not for this thread: ${state.parentUri}, $m',
Trace.current(),
);
return;
}
await ref.read(markDirectMessageReadProvider(profile, m).future).match(
onSuccess: (updatedItem) {
final newState = state.deepCopy();
newState.messages[oldIndex] = updatedItem;
update(newState);
ref.read(notificationsManagerProvider(profile).notifier).refreshDms();
},
onError: (error) {
_logger.severe(
'Error getting direct messages: $error',
Trace.current(),
);
},
);
}
}