Skip to content

Commit

Permalink
Redacting membership events should immediately reset the displayname …
Browse files Browse the repository at this point in the history
…& avatar of room members.

element-hq/element-ios#443

- MXEventTimeline: prepare state event redaction.
- MXRoom Notification break: rename "kMXRoomSyncWithLimitedTimelineNotification" with "kMXRoomDidFlushMessagesNotification"
  • Loading branch information
giomfo committed Jul 15, 2016
1 parent c40327d commit 7af3872
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 13 deletions.
152 changes: 143 additions & 9 deletions MatrixSDK/Data/MXEventTimeline.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#import "MXSession.h"
#import "MXMemoryStore.h"

#import "MXEvent+MatrixKit.h"

#import "MXError.h"

NSString *const kMXRoomInviteStateEventIdPrefix = @"invite-";
Expand Down Expand Up @@ -47,6 +49,11 @@ @interface MXEventTimeline ()
// past timelines is managed locally.
NSString *forwardsPaginationToken;
BOOL hasReachedHomeServerForwardsPaginationEnd;

/**
The current pending request.
*/
MXHTTPOperation *httpOperation;
}
@end

Expand Down Expand Up @@ -102,6 +109,13 @@ - (void)initialiseState:(NSArray<MXEvent *> *)stateEvents

- (void)destroy
{
if (httpOperation)
{
// Cancel the current server request
[httpOperation cancel];
httpOperation = nil;
}

if (!_isLiveTimeline)
{
// Release past timeline events stored in memory
Expand Down Expand Up @@ -409,7 +423,7 @@ - (void)handleJoinedRoomSync:(MXRoomSync *)roomSync
else if (roomSync.timeline.limited)
{
// The room has been resync with a limited timeline - Post notification
[[NSNotificationCenter defaultCenter] postNotificationName:kMXRoomSyncWithLimitedTimelineNotification
[[NSNotificationCenter defaultCenter] postNotificationName:kMXRoomDidFlushMessagesNotification
object:room
userInfo:nil];
}
Expand Down Expand Up @@ -537,23 +551,143 @@ - (void)addEvent:(MXEvent*)event direction:(MXTimelineDirection)direction fromSt
#pragma mark - Specific events Handling
- (void)handleRedaction:(MXEvent*)redactionEvent
{
// Check whether the redacted event has been already processed
NSLog(@"[MXEventTimeline] handle an event redaction");

// Check whether the redacted event is stored in room messages
MXEvent *redactedEvent = [store eventWithEventId:redactionEvent.redacts inRoom:_state.roomId];
if (redactedEvent)
{
// Redact the stored event
redactedEvent = [redactedEvent prune];
redactedEvent.redactedBecause = redactionEvent.JSONDictionary;

if (redactedEvent.isState) {
// FIXME: The room state must be refreshed here since this redacted event.
}

// Store the event
// Store the updated event
[store replaceEvent:redactedEvent inRoom:_state.roomId];
}

// Check whether the current room state depends on this redacted event.
if (!redactedEvent || redactedEvent.isState)
{
// FIXME: Is @autoreleasepool block required or not here?
NSArray *stateEvents = _state.stateEvents;

for (MXEvent *stateEvent in stateEvents)
{
if ([stateEvent.eventId isEqualToString:redactionEvent.redacts])
{
NSLog(@"[MXEventTimeline] the current room state has been modified by the event redaction.");

// Redact the stored event
redactedEvent = [stateEvent prune];
redactedEvent.redactedBecause = redactionEvent.JSONDictionary;

// Reset the room state. //FIXME: is it possible to handle only the redacted event?
_state = [[MXRoomState alloc] initWithRoomId:room.roomId andMatrixSession:room.mxSession andDirection:YES];
[self initialiseState:stateEvents];

// Update store with new room state when all state event have been processed
if ([store respondsToSelector:@selector(storeStateForRoom:stateEvents:)])
{
[store storeStateForRoom:_state.roomId stateEvents:_state.stateEvents];
}

// Reset the current pagination
// FIXME: Shall we let the kMXRoomStateHasBeenRedactedNotification listener trigger this reset? (like [MXKRoomDataSource reload] do)
[self resetPagination];

// Notify that room history has been flushed
[[NSNotificationCenter defaultCenter] postNotificationName:kMXRoomDidFlushMessagesNotification
object:room
userInfo:nil];
return;
}
}
}

// Re-sync the room in case of redacted state event from the past.
// Indeed, redacted information shouldn't spontaneously appear when you backpaginate...
if (!redactedEvent)
{
// Use a /context request to check whether the redacted event is a state event or not.
httpOperation = [room.mxSession.matrixRestClient contextOfEvent:redactionEvent.redacts inRoom:room.roomId limit:1 success:^(MXEventContext *eventContext) {

if (!httpOperation)
{
return;
}
httpOperation = nil;

if (eventContext.event.isState)
{
NSLog(@"[MXEventTimeline] the redacted event is a state event from the past");
[self forceRoomServerSync];
}

} failure:^(NSError *error) {

if (!httpOperation)
{
return;
}
httpOperation = nil;

NSLog(@"[MXEventTimeline] handleRedaction: failed to retrieved the redacted event");
[self forceRoomServerSync];
}];
}
else if (redactedEvent.isState)
{
NSLog(@"[MXEventTimeline] the redacted event is a former state event");
[self forceRoomServerSync];
}
}

- (void)forceRoomServerSync
{
// Reset the storage of this room. Re-sync it from the server
NSLog(@"[MXEventTimeline] re-sync room (%@) from the server.", room.roomId);
[store deleteRoom:room.roomId];

// Make an /initialSync request to get data
// Use a 0 messages limit for now because:
// - /initialSync is marked as obsolete in the spec
// - MXEventTimeline does not have methods to handle /initialSync responses
// So, avoid to write temparary code and let the user uses [MXEventTimeline paginate]
// to get room messages.
httpOperation = [room.mxSession.matrixRestClient initialSyncOfRoom:room.roomId withLimit:0 success:^(MXRoomInitialSync *roomInitialSync) {

if (!httpOperation)
{
return;
}
httpOperation = nil;

_state = [[MXRoomState alloc] initWithRoomId:room.roomId andMatrixSession:room.mxSession andDirection:YES];
[self initialiseState:roomInitialSync.state];

// Update store with new room state when all state event have been processed
if ([store respondsToSelector:@selector(storeStateForRoom:stateEvents:)])
{
[store storeStateForRoom:_state.roomId stateEvents:_state.stateEvents];
}

[self resetPagination];

// Notify that room history has been flushed
[[NSNotificationCenter defaultCenter] postNotificationName:kMXRoomDidFlushMessagesNotification
object:room
userInfo:nil];

} failure:^(NSError *error) {

NSLog(@"[MXEventTimeline] forceRoomServerSync failed.");

// FIXME: Reload entirely the app?
// [[NSNotificationCenter defaultCenter] postNotificationName:kMXSessionIgnoredUsersDidChangeNotification
// object:room.mxSession
// userInfo:nil];
}];
}

#pragma mark - State events handling
- (void)cloneState:(MXTimelineDirection)direction
Expand Down Expand Up @@ -584,8 +718,8 @@ - (void)handleStateEvent:(MXEvent*)event direction:(MXTimelineDirection)directio
// Forwards events update the current state of the room
[_state handleStateEvent:event];

// Special handling for presence
if (_isLiveTimeline && MXEventTypeRoomMember == event.eventType)
// Special handling for presence (CAUTION: ignore redacted state event here)
if (_isLiveTimeline && MXEventTypeRoomMember == event.eventType && !event.isRedactedEvent)
{
// Update MXUser data
MXUser *user = [room.mxSession getOrCreateUser:event.sender];
Expand Down
6 changes: 3 additions & 3 deletions MatrixSDK/Data/MXRoom.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@
FOUNDATION_EXPORT NSString *const kMXRoomInitialSyncNotification;

/**
Posted when a limited timeline is observed for an existing room during server sync.
All the existing messages have been removed from the room storage. Only the messages received during this sync are available.
Posted when the messages of an existing room has been flushed during server sync.
This flush may be due to a limited timeline in the room sync, or the redaction of a state event.
The token where to start back pagination has been updated.
The notification object is the concerned room (MXRoom instance).
*/
FOUNDATION_EXPORT NSString *const kMXRoomSyncWithLimitedTimelineNotification;
FOUNDATION_EXPORT NSString *const kMXRoomDidFlushMessagesNotification;

/**
Posted when the number of unread notifications ('notificationCount' and 'highlightCount' properties) are updated.
Expand Down
2 changes: 1 addition & 1 deletion MatrixSDK/Data/MXRoom.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

#import "MXError.h"

NSString *const kMXRoomSyncWithLimitedTimelineNotification = @"kMXRoomSyncWithLimitedTimelineNotification";
NSString *const kMXRoomDidFlushMessagesNotification = @"kMXRoomDidFlushMessagesNotification";
NSString *const kMXRoomInitialSyncNotification = @"kMXRoomInitialSyncNotification";
NSString *const kMXRoomDidUpdateUnreadNotification = @"kMXRoomDidUpdateUnreadNotification";

Expand Down

0 comments on commit 7af3872

Please # to comment.