mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-30 16:22:39 +00:00
Console: support m.room.redaction event in live event stream.
TODO: add the option to redact event from iOS console.
This commit is contained in:
parent
614b5bb7c8
commit
f4187bf6d6
10 changed files with 274 additions and 46 deletions
|
@ -126,8 +126,7 @@ static MatrixSDKHandler *sharedHandler = nil;
|
|||
kMXEventTypeStringRoomName,
|
||||
kMXEventTypeStringRoomTopic,
|
||||
kMXEventTypeStringRoomMember,
|
||||
kMXEventTypeStringRoomMessage,
|
||||
kMXEventTypeStringRoomRedaction
|
||||
kMXEventTypeStringRoomMessage
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -689,7 +688,9 @@ static MatrixSDKHandler *sharedHandler = nil;
|
|||
if (!isSubtitle && ![AppSettings sharedSettings].hideRedactedInformation) {
|
||||
redactedInfo = @"<redacted>";
|
||||
if ([event.redactedBecause isKindOfClass:[NSDictionary class]]) {
|
||||
NSString *redactedBy = [roomState memberName:event.redactedBecause[@"user_id"]];
|
||||
// Consider live room state to resolve redactor name if no roomState is provided
|
||||
MXRoomState *aRoomState = roomState ? roomState : [self.mxSession roomWithRoomId:event.roomId].state;
|
||||
NSString *redactedBy = [aRoomState memberName:event.redactedBecause[@"user_id"]];
|
||||
NSString *redactedReason = event.redactedBecause[@"reason"];
|
||||
if (redactedReason.length) {
|
||||
if (redactedBy.length) {
|
||||
|
@ -711,10 +712,10 @@ static MatrixSDKHandler *sharedHandler = nil;
|
|||
// Prepare returned description
|
||||
NSString *displayText = nil;
|
||||
// Prepare display name for concerned users
|
||||
NSString *senderDisplayName = [self senderDisplayNameForEvent:event withRoomState:roomState];
|
||||
NSString *senderDisplayName = roomState ? [self senderDisplayNameForEvent:event withRoomState:roomState] : event.userId;
|
||||
NSString *targetDisplayName = nil;
|
||||
if (event.stateKey) {
|
||||
targetDisplayName = [roomState memberName:event.stateKey];
|
||||
targetDisplayName = roomState ? [roomState memberName:event.stateKey] : event.stateKey;
|
||||
}
|
||||
|
||||
switch (event.eventType) {
|
||||
|
@ -845,7 +846,7 @@ static MatrixSDKHandler *sharedHandler = nil;
|
|||
case MXEventTypeRoomCreate: {
|
||||
NSString *creatorId = event.content[@"creator"];
|
||||
if (creatorId) {
|
||||
displayText = [NSString stringWithFormat:@"%@ created the room", [roomState memberName:creatorId]];
|
||||
displayText = [NSString stringWithFormat:@"%@ created the room", (roomState ? [roomState memberName:creatorId] : creatorId)];
|
||||
// Append redacted info if any
|
||||
if (redactedInfo) {
|
||||
displayText = [NSString stringWithFormat:@"%@ %@", displayText, redactedInfo];
|
||||
|
@ -996,7 +997,7 @@ static MatrixSDKHandler *sharedHandler = nil;
|
|||
break;
|
||||
}
|
||||
case MXEventTypeRoomRedaction: {
|
||||
if ([AppSettings sharedSettings].displayAllEvents) {
|
||||
if ([self.eventsFilterForMessages indexOfObject:kMXEventTypeStringRoomRedaction] != NSNotFound) {
|
||||
NSString *eventId = event.redacts;
|
||||
displayText = [NSString stringWithFormat:@"%@ redacted an event (id: %@)", senderDisplayName, eventId];
|
||||
} else {
|
||||
|
|
|
@ -23,6 +23,9 @@ NSString *const kRecentRoomUpdatedByBackPagination = @"kRecentRoomUpdatedByBackP
|
|||
MXRoom *mxRoom;
|
||||
id backPaginationListener;
|
||||
NSOperation *backPaginationOperation;
|
||||
|
||||
// Keep reference on last event (used in case of redaction)
|
||||
MXEvent *lastEvent;
|
||||
}
|
||||
@end
|
||||
|
||||
|
@ -36,24 +39,12 @@ NSString *const kRecentRoomUpdatedByBackPagination = @"kRecentRoomUpdatedByBackP
|
|||
_lastEventOriginServerTs = event.originServerTs;
|
||||
_unreadCount = isUnread ? 1 : 0;
|
||||
|
||||
// Keep ref on event
|
||||
lastEvent = event;
|
||||
|
||||
if (!_lastEventDescription.length) {
|
||||
// Trigger back pagination to get an event with a non empty description
|
||||
mxRoom = [mxHandler.mxSession roomWithRoomId:event.roomId];
|
||||
if (mxRoom) {
|
||||
backPaginationListener = [mxRoom listenToEventsOfTypes:mxHandler.eventsFilterForMessages onEvent:^(MXEvent *event, MXEventDirection direction, MXRoomState *roomState) {
|
||||
// Handle only backward events (Sanity check: be sure that the description has not been set by an other way)
|
||||
if (direction == MXEventDirectionBackwards && !_lastEventDescription.length) {
|
||||
if ([self updateWithLastEvent:event andRoomState:roomState markAsUnread:NO]) {
|
||||
// Force recents refresh
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kRecentRoomUpdatedByBackPagination object:nil];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
// Trigger a back pagination by reseting first backState to get room history from live
|
||||
[mxRoom resetBackState];
|
||||
[self triggerBackPagination];
|
||||
}
|
||||
[self triggerBackPagination];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
|
@ -65,12 +56,35 @@ NSString *const kRecentRoomUpdatedByBackPagination = @"kRecentRoomUpdatedByBackP
|
|||
if (description.length) {
|
||||
[self cancelBackPagination];
|
||||
// Update current last event
|
||||
lastEvent = event;
|
||||
_lastEventDescription = description;
|
||||
_lastEventOriginServerTs = event.originServerTs;
|
||||
if (isUnread) {
|
||||
_unreadCount ++;
|
||||
}
|
||||
return YES;
|
||||
} else if (_lastEventDescription.length) {
|
||||
// Here we tried to update the last event with a new live one, but the description of this new one is empty.
|
||||
// Consider the specific case of redaction event
|
||||
if (event.eventType == MXEventTypeRoomRedaction) {
|
||||
// Check whether the redacted event is the current last event
|
||||
if ([event.redacts isEqualToString:lastEvent.eventId]) {
|
||||
// Update last event description
|
||||
MXEvent *redactedEvent = [lastEvent prune];
|
||||
redactedEvent.redactedBecause = event.originalDictionary;
|
||||
|
||||
_lastEventDescription = [[MatrixSDKHandler sharedHandler] displayTextForEvent:redactedEvent withRoomState:nil inSubtitleMode:YES];
|
||||
if (!_lastEventDescription.length) {
|
||||
// The current last event must be removed, decrement the unread count (if not null)
|
||||
if (_unreadCount) {
|
||||
_unreadCount--;
|
||||
}
|
||||
// Trigger back pagination to get an event with a non empty description
|
||||
[self triggerBackPagination];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
@ -81,10 +95,33 @@ NSString *const kRecentRoomUpdatedByBackPagination = @"kRecentRoomUpdatedByBackP
|
|||
|
||||
- (void)dealloc {
|
||||
[self cancelBackPagination];
|
||||
lastEvent = nil;
|
||||
_lastEventDescription = nil;
|
||||
}
|
||||
|
||||
- (void)triggerBackPagination {
|
||||
// Add listener if it is not already done
|
||||
if (!backPaginationListener) {
|
||||
MatrixSDKHandler *mxHandler = [MatrixSDKHandler sharedHandler];
|
||||
mxRoom = [mxHandler.mxSession roomWithRoomId:_roomId];
|
||||
if (mxRoom) {
|
||||
backPaginationListener = [mxRoom listenToEventsOfTypes:mxHandler.eventsFilterForMessages onEvent:^(MXEvent *event, MXEventDirection direction, MXRoomState *roomState) {
|
||||
// Handle only backward events (Sanity check: be sure that the description has not been set by an other way)
|
||||
if (direction == MXEventDirectionBackwards && !_lastEventDescription.length) {
|
||||
if ([self updateWithLastEvent:event andRoomState:roomState markAsUnread:NO]) {
|
||||
// Force recents refresh
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kRecentRoomUpdatedByBackPagination object:_roomId];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
// Trigger a back pagination by reseting first backState to get room history from live
|
||||
[mxRoom resetBackState];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mxRoom.canPaginate) {
|
||||
backPaginationOperation = [mxRoom paginateBackMessages:10 complete:^{
|
||||
backPaginationOperation = nil;
|
||||
|
@ -98,6 +135,8 @@ NSString *const kRecentRoomUpdatedByBackPagination = @"kRecentRoomUpdatedByBackP
|
|||
[self cancelBackPagination];
|
||||
}];
|
||||
} else {
|
||||
// Force recents refresh
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kRecentRoomUpdatedByBackPagination object:_roomId];
|
||||
[self cancelBackPagination];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,10 @@ typedef enum : NSUInteger {
|
|||
// Remove the item defined with this event id
|
||||
// Return false if the event id is not found
|
||||
- (BOOL)removeEvent:(NSString*)eventId;
|
||||
// Looks for the item defined with the same id than the provided event, then updates it with the redacted event.
|
||||
// Return false if the event id is not found
|
||||
- (BOOL)updateRedactedEvent:(MXEvent*)redactedEvent;
|
||||
|
||||
// Returns the component from the eventId
|
||||
- (RoomMessageComponent*)componentWithEventId:(NSString *)eventId;
|
||||
// Return true if the event id is one of the message items
|
||||
|
|
|
@ -217,6 +217,101 @@ static NSAttributedString *messageSeparator = nil;
|
|||
}
|
||||
}
|
||||
// here the provided eventId has not been found
|
||||
} else {
|
||||
// Consider here message with no more than one element
|
||||
if (messageComponents.count) {
|
||||
RoomMessageComponent *msgComponent = [messageComponents firstObject];
|
||||
if ([msgComponent.eventId isEqualToString:eventId]) {
|
||||
[messageComponents removeObjectAtIndex:0];
|
||||
// Reset content size
|
||||
_contentSize = CGSizeZero;
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)updateRedactedEvent:(MXEvent*)redactedEvent {
|
||||
// Check whether the provided event is a redacted one
|
||||
if (!redactedEvent.redactedBecause) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (_messageType == RoomMessageTypeText) {
|
||||
NSUInteger index = messageComponents.count;
|
||||
while (index--) {
|
||||
RoomMessageComponent* msgComponent = [messageComponents objectAtIndex:index];
|
||||
if ([msgComponent.eventId isEqualToString:redactedEvent.eventId]) {
|
||||
// Update component with redacted event, remove it if the resulting string is empty
|
||||
[msgComponent updateWithRedactedEvent:redactedEvent];
|
||||
if (!msgComponent.textMessage.length) {
|
||||
[self removeEvent:redactedEvent.eventId];
|
||||
} else {
|
||||
// Compute the SIGNED difference of length (old length - new length)
|
||||
NSInteger diffLength = msgComponent.range.length - msgComponent.textMessage.length;
|
||||
|
||||
// Refresh global attributed string (if any)
|
||||
if (currentAttributedTextMsg) {
|
||||
// Replace the component string
|
||||
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:msgComponent.textMessage attributes:[msgComponent stringAttributes]];
|
||||
[currentAttributedTextMsg replaceCharactersInRange:msgComponent.range withAttributedString:attributedString];
|
||||
|
||||
// Update the component range
|
||||
NSRange updatedRange = msgComponent.range;
|
||||
updatedRange.length = msgComponent.textMessage.length;
|
||||
msgComponent.range = updatedRange;
|
||||
|
||||
// Reset content size
|
||||
_contentSize = CGSizeZero;
|
||||
} // else let the getter "attributedTextMessage" build it
|
||||
|
||||
// Adjust range for components displayed after this updated component
|
||||
for (index++; index < messageComponents.count; index++) {
|
||||
msgComponent = [messageComponents objectAtIndex:index];
|
||||
NSRange range = msgComponent.range;
|
||||
NSAssert((diffLength < 0) || (range.location >= diffLength), @"RoomMessage: the ranges of msg components are corrupted");
|
||||
range.location -= diffLength;
|
||||
msgComponent.range = range;
|
||||
}
|
||||
|
||||
// Height of each components should be updated
|
||||
shouldUpdateComponentsHeight = YES;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Consider here message related to attachment (This message has no more than one element)
|
||||
if (messageComponents.count) {
|
||||
RoomMessageComponent *msgComponent = [messageComponents firstObject];
|
||||
if ([msgComponent.eventId isEqualToString:redactedEvent.eventId]) {
|
||||
// Redaction removes the attachment information, the message becomes a text message
|
||||
_messageType = RoomMessageTypeText;
|
||||
_attachmentURL = nil;
|
||||
_attachmentInfo = nil;
|
||||
_thumbnailURL = nil;
|
||||
_thumbnailInfo = nil;
|
||||
_previewURL = nil;
|
||||
_uploadId = nil;
|
||||
_uploadProgress = -1;
|
||||
|
||||
[msgComponent updateWithRedactedEvent:redactedEvent];
|
||||
if (!msgComponent.textMessage.length) {
|
||||
[self removeEvent:redactedEvent.eventId];
|
||||
} else {
|
||||
// Set text range
|
||||
msgComponent.range = NSMakeRange(0, msgComponent.textMessage.length);
|
||||
|
||||
// Compute the height of the text component
|
||||
msgComponent.height = [self rawTextHeight:self.attributedTextMessage];
|
||||
shouldUpdateComponentsHeight = NO;
|
||||
// Reset content size
|
||||
_contentSize = CGSizeZero;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ typedef enum : NSUInteger {
|
|||
@property (nonatomic) BOOL isRedactedEvent;
|
||||
@property (nonatomic) BOOL isIncomingMsg;
|
||||
|
||||
// Keep a reference on related event (used in case of redaction)
|
||||
@property (nonatomic, readonly) MXEvent *event;
|
||||
|
||||
// The following properties are defined to store information on component.
|
||||
// They must be handled by the object which creates the RoomMessageComponent instance.
|
||||
@property (nonatomic) CGFloat height;
|
||||
|
@ -48,4 +51,6 @@ typedef enum : NSUInteger {
|
|||
- (id)initWithEvent:(MXEvent*)event andRoomState:(MXRoomState*)roomState;
|
||||
- (NSDictionary *)stringAttributes;
|
||||
|
||||
- (void)updateWithRedactedEvent:(MXEvent*)redactedEvent;
|
||||
|
||||
@end
|
|
@ -48,6 +48,8 @@ NSString *const kFailedEventIdPrefix = @"failedEventId-";
|
|||
|
||||
// Set eventId -> set the component style
|
||||
self.eventId = event.eventId;
|
||||
// Keep ref on event (used in case of redaction)
|
||||
_event = event;
|
||||
} else {
|
||||
// Ignore this event
|
||||
self = nil;
|
||||
|
@ -56,6 +58,15 @@ NSString *const kFailedEventIdPrefix = @"failedEventId-";
|
|||
return self;
|
||||
}
|
||||
|
||||
- (void)updateWithRedactedEvent:(MXEvent*)redactedEvent {
|
||||
MatrixSDKHandler *mxHandler = [MatrixSDKHandler sharedHandler];
|
||||
|
||||
// Build text component related to this event (Note: we don't have valid room state here, userId will be used as display name)
|
||||
_textMessage = [mxHandler displayTextForEvent:redactedEvent withRoomState:nil inSubtitleMode:NO];
|
||||
_isRedactedEvent = YES;
|
||||
_event = redactedEvent;
|
||||
}
|
||||
|
||||
- (void)setEventId:(NSString *)eventId {
|
||||
_eventId = eventId;
|
||||
|
||||
|
@ -72,6 +83,9 @@ NSString *const kFailedEventIdPrefix = @"failedEventId-";
|
|||
} else {
|
||||
_style = RoomMessageComponentStyleDefault;
|
||||
}
|
||||
|
||||
// Update stored event id (Note: Only local event Ids are supposed to change)
|
||||
_event.eventId = eventId;
|
||||
}
|
||||
|
||||
- (NSDictionary*)stringAttributes {
|
||||
|
|
|
@ -250,8 +250,16 @@
|
|||
}
|
||||
unreadCount = 0;
|
||||
|
||||
// Check whether redaction event belongs to the listened events list
|
||||
NSArray *listenedEventTypes = mxHandler.eventsFilterForMessages;
|
||||
BOOL hideRedactionEvent = ([listenedEventTypes indexOfObject:kMXEventTypeStringRoomRedaction] == NSNotFound);
|
||||
if (hideRedactionEvent) {
|
||||
// Add redaction event to the listened events list in order to take into account redaction of the last event in recents.
|
||||
// (See [RecentRoom updateWithLastEvent:...] for more details)
|
||||
listenedEventTypes = [listenedEventTypes arrayByAddingObject:kMXEventTypeStringRoomRedaction];
|
||||
}
|
||||
// Register recent listener
|
||||
recentsListener = [mxHandler.mxSession listenToEventsOfTypes:mxHandler.eventsFilterForMessages onEvent:^(MXEvent *event, MXEventDirection direction, MXRoomState *roomState) {
|
||||
recentsListener = [mxHandler.mxSession listenToEventsOfTypes:listenedEventTypes onEvent:^(MXEvent *event, MXEventDirection direction, MXRoomState *roomState) {
|
||||
// Consider first live event
|
||||
if (direction == MXEventDirectionForwards) {
|
||||
// Check user's membership in live room state (We will remove left rooms from recents)
|
||||
|
@ -268,6 +276,9 @@
|
|||
RecentRoom *recentRoom = [recents objectAtIndex:index];
|
||||
if ([event.roomId isEqualToString:recentRoom.roomId]) {
|
||||
isFound = YES;
|
||||
// Decrement here unreads count for this recent (we will add later the refreshed count)
|
||||
unreadCount -= recentRoom.unreadCount;
|
||||
|
||||
if (isLeft) {
|
||||
// Remove left room
|
||||
[recents removeObjectAtIndex:index];
|
||||
|
@ -292,13 +303,13 @@
|
|||
[filteredRecents insertObject:recentRoom atIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
if (isUnread) {
|
||||
unreadCount++;
|
||||
[self updateTitleView];
|
||||
}
|
||||
}
|
||||
// Refresh global unreads count
|
||||
unreadCount += recentRoom.unreadCount;
|
||||
}
|
||||
|
||||
// Refresh title
|
||||
[self updateTitleView];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -357,7 +368,7 @@
|
|||
if (recents) {
|
||||
// Add observer to force refresh when a recent last description is updated thanks to back pagination
|
||||
// (This happens when the current last event description is blank, a back pagination is triggered to display non empty description)
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRecentRoomUpdatedByBackPagination) name:kRecentRoomUpdatedByBackPagination object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRecentRoomUpdatedByBackPagination:) name:kRecentRoomUpdatedByBackPagination object:nil];
|
||||
} else {
|
||||
// Remove potential listener
|
||||
if (recentsListener && mxHandler.mxSession) {
|
||||
|
@ -369,8 +380,20 @@
|
|||
[self updateTitleView];
|
||||
}
|
||||
|
||||
- (void)onRecentRoomUpdatedByBackPagination {
|
||||
- (void)onRecentRoomUpdatedByBackPagination:(NSNotification *)notif{
|
||||
[self.tableView reloadData];
|
||||
[self updateTitleView];
|
||||
|
||||
if ([notif.object isKindOfClass:[NSString class]]) {
|
||||
NSString* roomId = notif.object;
|
||||
// Check whether this room is currently displayed in RoomViewController
|
||||
if ([[AppDelegate theDelegate].masterTabBarController.visibleRoomId isEqualToString:roomId]) {
|
||||
// For sanity reason, we have to force a full refresh in order to restore back state of the room
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[currentRoomViewController forceRefresh];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateTitleView {
|
||||
|
|
|
@ -22,5 +22,7 @@
|
|||
|
||||
@property (strong, nonatomic) NSString *roomId;
|
||||
|
||||
- (void)forceRefresh;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -137,10 +137,11 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
|
|||
// Messages
|
||||
@property (strong, nonatomic)NSMutableArray *messages;
|
||||
@property (strong, nonatomic)id messagesListener;
|
||||
@property (strong, nonatomic)id redactionListener;
|
||||
@end
|
||||
|
||||
@implementation RoomViewController
|
||||
@synthesize messages, messagesListener;
|
||||
@synthesize messages;
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
@ -211,9 +212,11 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
|
|||
[self hideAttachmentView];
|
||||
|
||||
messages = nil;
|
||||
if (messagesListener) {
|
||||
[self.mxRoom removeListener:messagesListener];
|
||||
messagesListener = nil;
|
||||
if (_messagesListener) {
|
||||
[self.mxRoom removeListener:_messagesListener];
|
||||
_messagesListener = nil;
|
||||
[self.mxRoom removeListener:_redactionListener];
|
||||
_redactionListener = nil;
|
||||
[[AppSettings sharedSettings] removeObserver:self forKeyPath:@"hideRedactedInformation"];
|
||||
[[AppSettings sharedSettings] removeObserver:self forKeyPath:@"hideUnsupportedEvents"];
|
||||
[[MatrixSDKHandler sharedHandler] removeObserver:self forKeyPath:@"status"];
|
||||
|
@ -439,18 +442,22 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - room ID
|
||||
#pragma mark -
|
||||
|
||||
- (void)setRoomId:(NSString *)roomId {
|
||||
if ([self.roomId isEqualToString:roomId] == NO) {
|
||||
_roomId = roomId;
|
||||
// Reload room data here
|
||||
[self configureView];
|
||||
// Update UI
|
||||
[self updateUI];
|
||||
[self forceRefresh];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)forceRefresh {
|
||||
// Reload room data here
|
||||
[self configureView];
|
||||
// Update UI
|
||||
[self updateUI];
|
||||
}
|
||||
|
||||
#pragma mark - UIGestureRecognizer delegate
|
||||
|
||||
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
|
||||
|
@ -543,9 +550,11 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
|
|||
|
||||
if (self.mxRoom) {
|
||||
// Remove potential listener
|
||||
if (messagesListener){
|
||||
[self.mxRoom removeListener:messagesListener];
|
||||
messagesListener = nil;
|
||||
if (_messagesListener){
|
||||
[self.mxRoom removeListener:_messagesListener];
|
||||
_messagesListener = nil;
|
||||
[self.mxRoom removeListener:_redactionListener];
|
||||
_redactionListener = nil;
|
||||
[[AppSettings sharedSettings] removeObserver:self forKeyPath:@"hideRedactedInformation"];
|
||||
[[AppSettings sharedSettings] removeObserver:self forKeyPath:@"hideUnsupportedEvents"];
|
||||
[[MatrixSDKHandler sharedHandler] removeObserver:self forKeyPath:@"status"];
|
||||
|
@ -603,7 +612,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
|
|||
[mxHandler addObserver:self forKeyPath:@"status" options:0 context:nil];
|
||||
[mxHandler addObserver:self forKeyPath:@"isResumeDone" options:0 context:nil];
|
||||
// Register a listener to handle messages
|
||||
messagesListener = [self.mxRoom listenToEventsOfTypes:mxHandler.eventsFilterForMessages onEvent:^(MXEvent *event, MXEventDirection direction, MXRoomState *roomState) {
|
||||
_messagesListener = [self.mxRoom listenToEventsOfTypes:mxHandler.eventsFilterForMessages onEvent:^(MXEvent *event, MXEventDirection direction, MXRoomState *roomState) {
|
||||
// Handle first live events
|
||||
if (direction == MXEventDirectionForwards) {
|
||||
// Check user's membership in live room state (Indeed we have to go back on recents when user leaves, or is kicked/banned)
|
||||
|
@ -758,6 +767,42 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
|
|||
}
|
||||
}];
|
||||
|
||||
// Register a listener to handle redaction in live stream
|
||||
_redactionListener = [self.mxRoom listenToEventsOfTypes:@[kMXEventTypeStringRoomRedaction] onEvent:^(MXEvent *redactionEvent, MXEventDirection direction, MXRoomState *roomState) {
|
||||
// Consider only live redaction events
|
||||
if (direction == MXEventDirectionForwards) {
|
||||
// Update Table on processing queue
|
||||
dispatch_async(mxHandler.processingQueue, ^{
|
||||
// Check whether a message contains the redacted event
|
||||
RoomMessage *message = [self messageWithEventId:redactionEvent.redacts];
|
||||
if (message) {
|
||||
// Retrieve the original to redact it
|
||||
MXEvent *originalEvent = [message componentWithEventId:redactionEvent.redacts].event;
|
||||
MXEvent *redactedEvent = [originalEvent prune];
|
||||
redactedEvent.redactedBecause = redactionEvent.originalDictionary;
|
||||
|
||||
if (redactedEvent.isState) {
|
||||
// FIXME: The room state must be refreshed here since this redacted event.
|
||||
NSLog(@"CAUTION: a state event has been redacted, room state may not be up to date");
|
||||
}
|
||||
|
||||
// We replace the event with the redacted one
|
||||
[message updateRedactedEvent:redactedEvent];
|
||||
if (!message.components.count) {
|
||||
[self removeMessage:message];
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh table display except if a back pagination is in progress
|
||||
if (!isBackPaginationInProgress) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.messagesTableView reloadData];
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}];
|
||||
|
||||
// Add typing notification listener
|
||||
typingNotifListener = [self.mxRoom listenToEventsOfTypes:@[kMXEventTypeStringTypingNotification] onEvent:^(MXEvent *event, MXEventDirection direction, MXRoomState *roomState) {
|
||||
// Handle only live events
|
||||
|
@ -2356,7 +2401,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop";
|
|||
|
||||
if (cellView) {
|
||||
RoomMessage* roomMessage = ((RoomMessageTableCell*)cellView).message;
|
||||
RoomMessageComponent* component =[roomMessage componentWithEventId:eventID];
|
||||
RoomMessageComponent* component = [roomMessage componentWithEventId:eventID];
|
||||
|
||||
// sanity check
|
||||
if (component) {
|
||||
|
|
|
@ -993,7 +993,7 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl
|
|||
notificationsCell.settingLabel.text = @"Enable In-App notifications";
|
||||
notificationsCell.settingSwitch.on = [[AppSettings sharedSettings] enableInAppNotifications];
|
||||
inAppNotificationsSwitch = notificationsCell.settingSwitch;
|
||||
} else /* SETTINGS_SECTION_NOTIFICATIONS_PUSH_NOTIFICATION_INDEX */{
|
||||
} else /* enablePushNotifRowIndex */{
|
||||
notificationsCell.settingLabel.text = @"Enable push notifications";
|
||||
notificationsCell.settingSwitch.on = [[APNSHandler sharedHandler] isActive];
|
||||
apnsNotificationsSwitch = notificationsCell.settingSwitch;
|
||||
|
|
Loading…
Reference in a new issue