...
 
Commits (3)
......@@ -127,7 +127,8 @@ class Members extends Storables<UserId, User> {
if (states.isNotEmpty) {
final state = states.first;
if (at.millisecondsSinceEpoch < state.since.millisecondsSinceEpoch) {
final stateMillis = state.since?.millisecondsSinceEpoch;
if (stateMillis == null || at.millisecondsSinceEpoch < stateMillis) {
return User.fromState(state);
}
}
......@@ -136,11 +137,14 @@ class Members extends Storables<UserId, User> {
final current = states[i];
final next = i + 1 < states.length ? states[i + 1] : null;
final currentMillis = current.since?.millisecondsSinceEpoch;
final currentIsBefore =
current.since.millisecondsSinceEpoch <= at.millisecondsSinceEpoch;
currentMillis == null || currentMillis <= at.millisecondsSinceEpoch;
final nextMillis = next?.since?.millisecondsSinceEpoch;
final nextIsAfterOrNull = next == null ||
next.since.millisecondsSinceEpoch > at.millisecondsSinceEpoch;
nextMillis == null ||
nextMillis > at.millisecondsSinceEpoch;
if (currentIsBefore && nextIsAfterOrNull) {
return User.fromState(current);
......
......@@ -237,9 +237,11 @@ class Room extends Identifiable<RoomId> {
/// @internal
Future<void> processSync(Map<String, dynamic> response) async {
final responseTimeline = response['timeline'];
// Only set previous batch from sync when none is set
if (previousBatch == null) {
previousBatch = response['timeline']['prev_batch'];
if (previousBatch == null && responseTimeline != null) {
previousBatch = responseTimeline['prev_batch'];
}
final summary = response['summary'];
......@@ -256,14 +258,19 @@ class Room extends Identifiable<RoomId> {
final context = ProcessContext(members: members);
await _processEvents(response['state']['events'], context);
var responseState = response['state'] ?? response['invite_state'];
if (responseState != null) {
await _processEvents(responseState['events'], context);
}
final processed = await _processEvents(
response['timeline']['events'],
context,
);
if (responseTimeline != null) {
final processed = await _processEvents(
responseTimeline['events'],
context,
);
await timeline.addAll(processed);
await timeline.addAll(processed);
}
}
Future<List<RoomEvent>> _processEvents(
......@@ -656,6 +663,29 @@ class JoinedRoom extends Room {
}
}
class InvitedRoom extends Room {
InvitedRoom({
@required RoomId id,
@required String scope,
RoomStateEvents stateEvents,
int memberCount,
User directUser,
String previousBatch,
int highlightedUnreadNotificationCount,
int totalUnreadNotificationCount,
}) : super(
id: id,
scope: scope,
stateEvents: stateEvents,
memberCount: memberCount,
directUser: directUser,
previousBatch: previousBatch,
highlightedUnreadNotificationCount:
highlightedUnreadNotificationCount,
totalUnreadNotificationCount: totalUnreadNotificationCount,
);
}
class LeftRoom extends Room {
LeftRoom({
@required RoomId id,
......
......@@ -224,6 +224,13 @@ class LocalUser extends User {
_pushers = Pushers(scope);
}
/// Get all invites for this user. Note that for now this will load
/// all rooms to memory.
Future<List<Invite>> get invites async =>
(await _rooms.get(where: (r) => r is InvitedRoom))
.map((r) => Invite._(scope, r))
.toList(growable: false);
/// Set the display name of this user to the given value.
Future<void> setName(String name) async {
final response = await _client.profileSetDisplayName(
......@@ -397,6 +404,7 @@ class LocalUser extends User {
final processed = List<Room>();
const join = 'join';
const invite = 'invite';
const leave = 'leave';
process(Map<String, dynamic> jsonRooms, {@required String type}) async {
......@@ -411,6 +419,9 @@ class LocalUser extends User {
case join:
room = JoinedRoom(id: roomId, scope: scope);
break;
case invite:
room = InvitedRoom(id: roomId, scope: scope);
break;
case leave:
room = LeftRoom(id: roomId, scope: scope);
break;
......@@ -424,6 +435,14 @@ class LocalUser extends User {
directUser: room.directUser,
previousBatch: room.previousBatch,
);
} else if (room is InvitedRoom && type == join) {
room = JoinedRoom(
id: room.id,
scope: scope,
stateEvents: room.stateEvents,
directUser: room.directUser,
previousBatch: room.previousBatch,
);
}
}
......@@ -437,6 +456,7 @@ class LocalUser extends User {
}
await process(jRooms[join], type: join);
await process(jRooms[invite], type: invite);
await process(jRooms[leave], type: leave);
// Save rooms
......@@ -461,3 +481,15 @@ class SyncState {
SyncState({this.exception, this.dirtyRooms = const []})
: succeeded = exception == null;
}
// TODO: Make use of part directive to split into more files
class Invite {
final Rooms _rooms;
final InvitedRoom to;
Invite._(String scope, this.to) : _rooms = Container().resolve(scope);
/// Accept the invitation and join the room [to].
Future<void> accept() => _rooms.join(id: to.id);
}