Commit 805a8415 authored by Wilko Manger's avatar Wilko Manger

Add Room.readReceipts getter

parent b791d920
......@@ -5,7 +5,9 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import 'dart:collection';
import 'dart:convert';
import 'dart:math';
import 'package:kiwi/kiwi.dart';
import 'package:matrix_sdk/src/api/client.dart';
......@@ -99,6 +101,10 @@ class Room extends Identifiable<RoomId> {
List<User> get typingUsers => _typingUsers;
Set<ReadReceipt> _readReceipts;
Set<ReadReceipt> get readReceipts => _readReceipts;
int _highlightedUnreadNotificationCount = 0;
int get highlightedUnreadNotificationCount =>
......@@ -121,6 +127,7 @@ class Room extends Identifiable<RoomId> {
String previousBatch,
int highlightedUnreadNotificationCount,
int totalUnreadNotificationCount,
ReadReceiptSet readReceipts,
}) : _scope = scope,
_stateEvents = stateEvents ?? RoomStateEvents(),
_directUser = directUser,
......@@ -128,6 +135,7 @@ class Room extends Identifiable<RoomId> {
_highlightedUnreadNotificationCount =
highlightedUnreadNotificationCount ?? 0,
_totalUnreadNotificationCount = totalUnreadNotificationCount ?? 0,
_readReceipts = readReceipts ?? ReadReceiptSet(),
_me = Container().resolve(scope),
_store = Container().resolve(scope) {
_members = Members(this, memberCount, scope);
......@@ -399,14 +407,25 @@ class Room extends Identifiable<RoomId> {
final events = raw['ephemeral']['events'] as List<dynamic>;
final rawTypingEvent = events.firstWhere(
final typingEvent = events.firstWhere(
(rawEvent) => rawEvent['type'] == 'm.typing',
orElse: () => null,
);
if (rawTypingEvent == null) return;
await _processTypingEvent(typingEvent);
final receiptEvent = events.firstWhere(
(rawEvent) => rawEvent['type'] == 'm.receipt',
orElse: () => null,
);
final typingUsers = (await Future.wait(rawTypingEvent['content']['user_ids']
await _progressReceiptEvent(receiptEvent);
}
Future<void> _processTypingEvent(Map<String, dynamic> typingEvent) async {
if (typingEvent == null) return;
final typingUsers = (await Future.wait(typingEvent['content']['user_ids']
.map((id) => Future.sync(() => members[UserId(id)]))
.cast<Future<User>>()))
.cast<User>();
......@@ -414,6 +433,40 @@ class Room extends Identifiable<RoomId> {
_typingUsers = typingUsers;
}
Future<void> _progressReceiptEvent(Map<String, dynamic> receiptEvent) async {
if (receiptEvent == null) return;
final Map<String, dynamic> content = receiptEvent['content'];
final receipts = List<ReadReceipt>();
for (final MapEntry<String, dynamic> rawEventId in content.entries) {
final eventId = EventId(rawEventId.key);
for (final MapEntry<String, dynamic> rawUserId
in rawEventId.value['m.read'].entries) {
UserId userId;
try {
userId = UserId(rawUserId.key);
} on ArgumentError {
continue;
}
final time = DateTime.fromMillisecondsSinceEpoch(rawUserId.value['ts']);
receipts.add(
ReadReceipt(
userId: userId,
eventId: eventId,
time: time,
),
);
}
}
_readReceipts.addAll(receipts);
}
/// Whether someone (not you) is typing.
bool get isSomeoneElseTyping =>
typingUsers.isNotEmpty && !typingUsers.any((user) => user == _me);
......@@ -453,6 +506,7 @@ class JoinedRoom extends Room {
String previousBatch,
int highlightedUnreadNotificationCount,
int totalUnreadNotificationCount,
ReadReceiptSet readReceipts,
}) : super(
id: id,
scope: scope,
......@@ -463,6 +517,7 @@ class JoinedRoom extends Room {
highlightedUnreadNotificationCount:
highlightedUnreadNotificationCount,
totalUnreadNotificationCount: totalUnreadNotificationCount,
readReceipts: readReceipts,
);
@override
......@@ -697,6 +752,7 @@ class InvitedRoom extends Room {
String previousBatch,
int highlightedUnreadNotificationCount,
int totalUnreadNotificationCount,
ReadReceiptSet readReceipts,
}) : super(
id: id,
scope: scope,
......@@ -707,6 +763,7 @@ class InvitedRoom extends Room {
highlightedUnreadNotificationCount:
highlightedUnreadNotificationCount,
totalUnreadNotificationCount: totalUnreadNotificationCount,
readReceipts: readReceipts,
);
}
......@@ -720,6 +777,7 @@ class LeftRoom extends Room {
String previousBatch,
int highlightedUnreadNotificationCount,
int totalUnreadNotificationCount,
ReadReceiptSet readReceipts,
}) : super(
id: id,
scope: scope,
......@@ -730,6 +788,7 @@ class LeftRoom extends Room {
highlightedUnreadNotificationCount:
highlightedUnreadNotificationCount,
totalUnreadNotificationCount: totalUnreadNotificationCount,
readReceipts: readReceipts,
);
}
......@@ -809,3 +868,36 @@ class PowerLevelDefaults {
PowerLevelDefaults(PowerLevelsChangeEvent event) : _content = event?.content;
}
class ReadReceipt {
final UserId userId;
final EventId eventId;
final DateTime time;
ReadReceipt({
@required this.userId,
@required this.eventId,
@required this.time,
});
@override
bool operator ==(other) {
if (other is ReadReceipt) {
return this.userId == other.userId &&
this.eventId == other.eventId &&
this.time == other.time;
} else {
return false;
}
}
@override
int get hashCode => userId.hashCode + eventId.hashCode + time.hashCode;
}
class ReadReceiptSet extends SplayTreeSet<ReadReceipt> {
ReadReceiptSet() : super((a, b) => a.userId == b.userId ? 0 : -1);
factory ReadReceiptSet.of(Iterable<ReadReceipt> receipts) =>
ReadReceiptSet()..addAll(receipts);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment