You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.4 KiB
175 lines
4.4 KiB
2 years ago
|
part of '../neon_spreed.dart';
|
||
|
|
||
|
abstract class SpreedRoomBlocEvents {
|
||
|
void loadMoreMessages();
|
||
|
|
||
|
void sendMessage(final String message);
|
||
|
|
||
|
Future<void> leaveRoom();
|
||
|
}
|
||
|
|
||
|
abstract class SpreedRoomBlocStates {
|
||
|
BehaviorSubject<Result<spreed.Room>> get room;
|
||
|
|
||
|
BehaviorSubject<Result<List<spreed.ChatMessageInterface>>> get messages;
|
||
|
|
||
|
BehaviorSubject<bool> get allLoaded;
|
||
|
|
||
|
BehaviorSubject<String?> get sendingMessage;
|
||
|
|
||
|
BehaviorSubject<int?> get lastCommonReadMessageId;
|
||
|
}
|
||
|
|
||
|
class SpreedRoomBloc extends InteractiveBloc implements SpreedRoomBlocEvents, SpreedRoomBlocStates {
|
||
|
SpreedRoomBloc(
|
||
|
this.options,
|
||
|
this.account,
|
||
|
final spreed.Room r,
|
||
|
) {
|
||
|
roomToken = r.token;
|
||
|
room.add(Result.success(r));
|
||
|
|
||
|
unawaited(refresh());
|
||
|
}
|
||
|
|
||
|
final SpreedAppSpecificOptions options;
|
||
|
final Account account;
|
||
|
late final String roomToken;
|
||
|
final _limit = 100;
|
||
|
|
||
|
int? _lastKnownMessageId;
|
||
|
|
||
|
@override
|
||
|
void dispose() {
|
||
|
unawaited(room.close());
|
||
|
unawaited(messages.close());
|
||
|
unawaited(allLoaded.close());
|
||
|
unawaited(sendingMessage.close());
|
||
|
unawaited(lastCommonReadMessageId.close());
|
||
|
super.dispose();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
BehaviorSubject<bool> allLoaded = BehaviorSubject.seeded(false);
|
||
|
|
||
|
@override
|
||
|
BehaviorSubject<int?> lastCommonReadMessageId = BehaviorSubject.seeded(null);
|
||
|
|
||
|
@override
|
||
|
BehaviorSubject<Result<List<spreed.ChatMessageInterface>>> messages = BehaviorSubject();
|
||
|
|
||
|
@override
|
||
|
BehaviorSubject<Result<spreed.Room>> room = BehaviorSubject();
|
||
|
|
||
|
@override
|
||
|
BehaviorSubject<String?> sendingMessage = BehaviorSubject.seeded(null);
|
||
|
|
||
|
@override
|
||
|
Future<void> refresh() async {
|
||
|
await RequestManager.instance.wrapNextcloud(
|
||
|
account.id,
|
||
|
'spreed-room-$roomToken',
|
||
|
room,
|
||
|
account.client.spreed.room.joinRoomRaw(token: roomToken),
|
||
|
(final response) => response.body.ocs.data,
|
||
|
);
|
||
|
await _loadMessages(force: true);
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
// ignore: avoid_void_async
|
||
|
void sendMessage(final String message) async {
|
||
|
try {
|
||
|
sendingMessage.add(message);
|
||
|
await account.client.spreed.chat.sendMessage(
|
||
|
token: roomToken,
|
||
|
message: message,
|
||
|
);
|
||
|
await _loadMessages(force: true);
|
||
|
} catch (e, s) {
|
||
|
debugPrint(e.toString());
|
||
|
debugPrint(s.toString());
|
||
|
addError(e);
|
||
|
} finally {
|
||
|
sendingMessage.add(null);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Future<void> loadMoreMessages() async {
|
||
|
await _loadMessages(force: false);
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Future<void> leaveRoom() async {
|
||
|
try {
|
||
|
await account.client.spreed.room.leaveRoom(token: roomToken);
|
||
|
} catch (e, s) {
|
||
|
debugPrint(e.toString());
|
||
|
debugPrint(s.toString());
|
||
|
addError(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Future<void> _loadMessages({required final bool force}) async {
|
||
|
if (!force && (allLoaded.valueOrNull ?? false)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
final previousData = messages.valueOrNull?.data;
|
||
|
try {
|
||
|
messages.add(
|
||
|
Result(
|
||
|
previousData,
|
||
|
null,
|
||
|
isLoading: true,
|
||
|
isCached: true,
|
||
|
),
|
||
|
);
|
||
|
final data = await account.client.spreed.chat.receiveMessages(
|
||
|
token: roomToken,
|
||
|
lookIntoFuture: 0,
|
||
|
includeLastKnown: 1,
|
||
|
limit: _limit,
|
||
|
lastKnownMessageId: (force ? null : _lastKnownMessageId) ?? 0,
|
||
|
lastCommonReadId: lastCommonReadMessageId.valueOrNull ?? 0,
|
||
|
);
|
||
|
|
||
|
_lastKnownMessageId = data.headers.xChatLastGiven != null ? int.parse(data.headers.xChatLastGiven!) : null;
|
||
|
lastCommonReadMessageId.add(
|
||
|
data.headers.xChatLastCommonRead != null ? int.parse(data.headers.xChatLastCommonRead!) : null,
|
||
|
);
|
||
|
|
||
|
if (data.body.ocs.data.length < _limit) {
|
||
|
allLoaded.add(true);
|
||
|
}
|
||
|
|
||
|
messages.add(
|
||
|
Result.success(
|
||
|
{
|
||
|
if (previousData != null) ..._messagesToUniqueMap(previousData),
|
||
|
..._messagesToUniqueMap(data.body.ocs.data.toList()),
|
||
|
}.values.sorted((final a, final b) => b.id.compareTo(a.id)).toList(),
|
||
|
),
|
||
|
);
|
||
|
} catch (e, s) {
|
||
|
debugPrint(e.toString());
|
||
|
debugPrint(s.toString());
|
||
|
messages.add(
|
||
|
Result(
|
||
|
previousData,
|
||
|
e,
|
||
|
isLoading: false,
|
||
|
isCached: true,
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Map<int, spreed.ChatMessageInterface> _messagesToUniqueMap(final List<spreed.ChatMessageInterface> messages) => {
|
||
|
for (final message in messages) ...{
|
||
|
message.id: message,
|
||
|
},
|
||
|
};
|
||
|
}
|