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.
174 lines
4.4 KiB
174 lines
4.4 KiB
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, |
|
}, |
|
}; |
|
}
|
|
|