From a754b92c346ab07e1e98f0c9ec243bc9508152b8 Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 1 Feb 2016 13:20:29 +0100 Subject: [PATCH 01/17] Room page loading improvement: [MXRoom paginateBackMessages]: added an argument to load message only available messages from the store --- MatrixSDK/Data/MXRoom.h | 6 ++++-- MatrixSDK/Data/MXRoom.m | 13 +++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/MatrixSDK/Data/MXRoom.h b/MatrixSDK/Data/MXRoom.h index 040b7b05b5..da1806ceb3 100644 --- a/MatrixSDK/Data/MXRoom.h +++ b/MatrixSDK/Data/MXRoom.h @@ -178,6 +178,7 @@ typedef void (^MXOnRoomEvent)(MXEvent *event, MXEventDirection direction, MXRoom The retrieved events will be sent to registered listeners. @param numItems the number of items to get. + @param onlyFromStore if YES, return available events from the store, do not make a pagination request to the homeserver. @param complete A block object called when the operation is complete. @param failure A block object called when the operation fails. @@ -185,8 +186,9 @@ typedef void (^MXOnRoomEvent)(MXEvent *event, MXEventDirection direction, MXRoom if no request to the home server is required. */ - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems - complete:(void (^)())complete - failure:(void (^)(NSError *error))failure; + onlyFromStore:(BOOL)onlyFromStore + complete:(void (^)())complete + failure:(void (^)(NSError *error))failure; /** diff --git a/MatrixSDK/Data/MXRoom.m b/MatrixSDK/Data/MXRoom.m index a655ab539c..373fb38d82 100644 --- a/MatrixSDK/Data/MXRoom.m +++ b/MatrixSDK/Data/MXRoom.m @@ -528,8 +528,9 @@ - (void)resetBackState } - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems - complete:(void (^)())complete - failure:(void (^)(NSError *error))failure + onlyFromStore:(BOOL)onlyFromStore + complete:(void (^)())complete + failure:(void (^)(NSError *error))failure { MXHTTPOperation *operation; @@ -561,6 +562,14 @@ - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems } } + if (onlyFromStore && messagesFromStoreCount) + { + complete(); + + NSLog(@"[MXRoom] paginateBackMessages : is done from the store"); + return nil; + } + if (0 < numItems && NO == [mxSession.store hasReachedHomeServerPaginationEndForRoom:_state.roomId]) { // Not enough messages: make a pagination request to the home server From d4d2bfd13db67f2f98f5d78195d415468feeacf5 Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 1 Feb 2016 13:25:16 +0100 Subject: [PATCH 02/17] Room page loading improvement: [MXRoom paginateBackMessages]: added an argument to load message only available messages from the store --- MatrixSDK/Data/MXRoom.h | 6 ++++-- MatrixSDK/Data/MXRoom.m | 13 +++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/MatrixSDK/Data/MXRoom.h b/MatrixSDK/Data/MXRoom.h index 040b7b05b5..da1806ceb3 100644 --- a/MatrixSDK/Data/MXRoom.h +++ b/MatrixSDK/Data/MXRoom.h @@ -178,6 +178,7 @@ typedef void (^MXOnRoomEvent)(MXEvent *event, MXEventDirection direction, MXRoom The retrieved events will be sent to registered listeners. @param numItems the number of items to get. + @param onlyFromStore if YES, return available events from the store, do not make a pagination request to the homeserver. @param complete A block object called when the operation is complete. @param failure A block object called when the operation fails. @@ -185,8 +186,9 @@ typedef void (^MXOnRoomEvent)(MXEvent *event, MXEventDirection direction, MXRoom if no request to the home server is required. */ - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems - complete:(void (^)())complete - failure:(void (^)(NSError *error))failure; + onlyFromStore:(BOOL)onlyFromStore + complete:(void (^)())complete + failure:(void (^)(NSError *error))failure; /** diff --git a/MatrixSDK/Data/MXRoom.m b/MatrixSDK/Data/MXRoom.m index a655ab539c..373fb38d82 100644 --- a/MatrixSDK/Data/MXRoom.m +++ b/MatrixSDK/Data/MXRoom.m @@ -528,8 +528,9 @@ - (void)resetBackState } - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems - complete:(void (^)())complete - failure:(void (^)(NSError *error))failure + onlyFromStore:(BOOL)onlyFromStore + complete:(void (^)())complete + failure:(void (^)(NSError *error))failure { MXHTTPOperation *operation; @@ -561,6 +562,14 @@ - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems } } + if (onlyFromStore && messagesFromStoreCount) + { + complete(); + + NSLog(@"[MXRoom] paginateBackMessages : is done from the store"); + return nil; + } + if (0 < numItems && NO == [mxSession.store hasReachedHomeServerPaginationEndForRoom:_state.roomId]) { // Not enough messages: make a pagination request to the home server From 5c617775da8cb7db8a65a64ae0a3898549ecec95 Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 1 Feb 2016 14:56:23 +0100 Subject: [PATCH 03/17] Revert "Room page loading improvement: [MXRoom paginateBackMessages]: added an argument to load message only available messages from the store" This reverts commit a754b92c346ab07e1e98f0c9ec243bc9508152b8. --- MatrixSDK/Data/MXRoom.h | 6 ++---- MatrixSDK/Data/MXRoom.m | 13 ++----------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/MatrixSDK/Data/MXRoom.h b/MatrixSDK/Data/MXRoom.h index da1806ceb3..040b7b05b5 100644 --- a/MatrixSDK/Data/MXRoom.h +++ b/MatrixSDK/Data/MXRoom.h @@ -178,7 +178,6 @@ typedef void (^MXOnRoomEvent)(MXEvent *event, MXEventDirection direction, MXRoom The retrieved events will be sent to registered listeners. @param numItems the number of items to get. - @param onlyFromStore if YES, return available events from the store, do not make a pagination request to the homeserver. @param complete A block object called when the operation is complete. @param failure A block object called when the operation fails. @@ -186,9 +185,8 @@ typedef void (^MXOnRoomEvent)(MXEvent *event, MXEventDirection direction, MXRoom if no request to the home server is required. */ - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems - onlyFromStore:(BOOL)onlyFromStore - complete:(void (^)())complete - failure:(void (^)(NSError *error))failure; + complete:(void (^)())complete + failure:(void (^)(NSError *error))failure; /** diff --git a/MatrixSDK/Data/MXRoom.m b/MatrixSDK/Data/MXRoom.m index 373fb38d82..a655ab539c 100644 --- a/MatrixSDK/Data/MXRoom.m +++ b/MatrixSDK/Data/MXRoom.m @@ -528,9 +528,8 @@ - (void)resetBackState } - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems - onlyFromStore:(BOOL)onlyFromStore - complete:(void (^)())complete - failure:(void (^)(NSError *error))failure + complete:(void (^)())complete + failure:(void (^)(NSError *error))failure { MXHTTPOperation *operation; @@ -562,14 +561,6 @@ - (MXHTTPOperation*)paginateBackMessages:(NSUInteger)numItems } } - if (onlyFromStore && messagesFromStoreCount) - { - complete(); - - NSLog(@"[MXRoom] paginateBackMessages : is done from the store"); - return nil; - } - if (0 < numItems && NO == [mxSession.store hasReachedHomeServerPaginationEndForRoom:_state.roomId]) { // Not enough messages: make a pagination request to the home server From 2e1ef0e686a33434d5f90a9ef6fd2f1363d827e8 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 2 Feb 2016 08:28:23 +0100 Subject: [PATCH 04/17] Email invitation: Added inviteUserByEmail method --- MatrixSDK/Data/MXRoom.h | 13 ++++++++ MatrixSDK/Data/MXRoom.m | 7 ++++ MatrixSDK/MXError.h | 5 +++ MatrixSDK/MXError.m | 4 ++- MatrixSDK/MXRestClient.h | 32 ++++++++++++++++++ MatrixSDK/MXRestClient.m | 70 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 130 insertions(+), 1 deletion(-) diff --git a/MatrixSDK/Data/MXRoom.h b/MatrixSDK/Data/MXRoom.h index 040b7b05b5..b5272ffd39 100644 --- a/MatrixSDK/Data/MXRoom.h +++ b/MatrixSDK/Data/MXRoom.h @@ -335,6 +335,19 @@ typedef void (^MXOnRoomEvent)(MXEvent *event, MXEventDirection direction, MXRoom success:(void (^)())success failure:(void (^)(NSError *error))failure; +/** + Invite a user to a room based on their email address to this room. + + @param email the user email. + @param success A block object called when the operation succeeds. + @param failure A block object called when the operation fails. + + @return a MXHTTPOperation instance. + */ +- (MXHTTPOperation*)inviteUserByEmail:(NSString*)email + success:(void (^)())success + failure:(void (^)(NSError *error))failure; + /** Kick a user from this room. diff --git a/MatrixSDK/Data/MXRoom.m b/MatrixSDK/Data/MXRoom.m index a655ab539c..9b5697b107 100644 --- a/MatrixSDK/Data/MXRoom.m +++ b/MatrixSDK/Data/MXRoom.m @@ -722,6 +722,13 @@ - (MXHTTPOperation*)inviteUser:(NSString*)userId return [mxSession.matrixRestClient inviteUser:userId toRoom:_state.roomId success:success failure:failure]; } +- (MXHTTPOperation*)inviteUserByEmail:(NSString*)email + success:(void (^)())success + failure:(void (^)(NSError *error))failure +{ + return [mxSession.matrixRestClient inviteUserByEmail:email toRoom:_state.roomId success:success failure:failure]; +} + - (MXHTTPOperation*)kickUser:(NSString*)userId reason:(NSString*)reason success:(void (^)())success diff --git a/MatrixSDK/MXError.h b/MatrixSDK/MXError.h index 7a917912a2..f9a0bd3cdc 100644 --- a/MatrixSDK/MXError.h +++ b/MatrixSDK/MXError.h @@ -36,6 +36,11 @@ FOUNDATION_EXPORT NSString *const kMXErrCodeStringBadPagination; FOUNDATION_EXPORT NSString *const kMXErrorStringInvalidToken; +/** + Error codes generated by the Matrix SDK. + */ +FOUNDATION_EXPORT NSString *const kMXSDKErrCodeStringMissingParameters; + /** `MXError` represents an error sent by the home server. MXErrors are encapsulated in NSError. This class is an helper to create NSError or extract MXError from NSError. diff --git a/MatrixSDK/MXError.m b/MatrixSDK/MXError.m index f191ce58fc..2fd4e3c004 100644 --- a/MatrixSDK/MXError.m +++ b/MatrixSDK/MXError.m @@ -31,7 +31,9 @@ NSString *const kMXErrCodeStringRoomInUse = @"M_ROOM_IN_USE"; NSString *const kMXErrCodeStringBadPagination = @"M_BAD_PAGINATION"; -NSString *const kMXErrorStringInvalidToken = @"Invalid token"; +NSString *const kMXErrorStringInvalidToken = @"Invalid token"; + +NSString *const kMXSDKErrCodeStringMissingParameters = @"org.matrix.sdk.missing_parameters"; // Random NSError code diff --git a/MatrixSDK/MXRestClient.h b/MatrixSDK/MXRestClient.h index 56f8fe1c70..d209da149a 100644 --- a/MatrixSDK/MXRestClient.h +++ b/MatrixSDK/MXRestClient.h @@ -589,6 +589,37 @@ typedef enum : NSUInteger toRoom:(NSString*)roomId success:(void (^)())success failure:(void (^)(NSError *error))failure; +/** + Invite a user to a room based on their email address. + + @param email the user email. + @param roomId the id of the room. + @param success A block object called when the operation succeeds. + @param failure A block object called when the operation fails. + + @return a MXHTTPOperation instance. + */ +- (MXHTTPOperation*)inviteUserByEmail:(NSString*)email + toRoom:(NSString*)roomId + success:(void (^)())success + failure:(void (^)(NSError *error))failure; + +/** + Invite a user to a room based on a third-party identifier. + + @param medium the medium to invite the user e.g. "email". + @param medium address the address for the specified medium. + @param roomId the id of the room. + @param success A block object called when the operation succeeds. + @param failure A block object called when the operation fails. + + @return a MXHTTPOperation instance. + */ +- (MXHTTPOperation*)inviteByThreePid:(NSString*)medium + address:(NSString*)address + toRoom:(NSString*)roomId + success:(void (^)())success + failure:(void (^)(NSError *error))failure; /** Kick a user from a room. @@ -637,6 +668,7 @@ typedef enum : NSUInteger success:(void (^)())success failure:(void (^)(NSError *error))failure; + /** Create a room. diff --git a/MatrixSDK/MXRestClient.m b/MatrixSDK/MXRestClient.m index a68b19899f..d23877d78f 100644 --- a/MatrixSDK/MXRestClient.m +++ b/MatrixSDK/MXRestClient.m @@ -18,6 +18,7 @@ #import "MXJSONModel.h" #import "MXTools.h" +#import "MXError.h" #pragma mark - Constants definitions /** @@ -1025,6 +1026,75 @@ - (MXHTTPOperation*)inviteUser:(NSString*)userId success:success failure:failure]; } +- (MXHTTPOperation*)inviteUserByEmail:(NSString*)email + toRoom:(NSString*)roomId + success:(void (^)())success + failure:(void (^)(NSError *error))failure +{ + return [self inviteByThreePid:@"email" + address:email + toRoom:roomId + success:success failure:failure]; +} + +- (MXHTTPOperation*)inviteByThreePid:(NSString*)medium + address:(NSString*)address + toRoom:(NSString*)roomId + success:(void (^)())success + failure:(void (^)(NSError *error))failure +{ + // The identity server must be defined + if (!_identityServer) + { + if (failure) + { + MXError *error = [[MXError alloc] initWithErrorCode:kMXSDKErrCodeStringMissingParameters error:@"No supplied identity server URL"]; + failure([error createNSError]); + } + return nil; + } + + NSString *path = [NSString stringWithFormat:@"api/v1/rooms/%@/invite", roomId]; + + // This request must not have the protocol part + NSString *identityServer = _identityServer; + if ([identityServer hasPrefix:@"http://"] || [identityServer hasPrefix:@"https://"]) + { + identityServer = [identityServer substringFromIndex:[identityServer rangeOfString:@"://"].location + 3]; + } + + NSDictionary *parameters = @{ + @"id_server": identityServer, + @"medium": medium, + @"address": address + }; + + return [httpClient requestWithMethod:@"POST" + path:path + parameters:parameters + success:^(NSDictionary *JSONResponse) { + if (success) + { + // Use here the processing queue in order to keep the server response order + dispatch_async(processingQueue, ^{ + + dispatch_async(dispatch_get_main_queue(), ^{ + + success(JSONResponse); + + }); + + }); + } + } + failure:^(NSError *error) { + if (failure) + { + failure(error); + } + }]; +} + - (MXHTTPOperation*)kickUser:(NSString*)userId fromRoom:(NSString*)roomId reason:(NSString*)reason From 26ea0387f79029f7b26335a27a7e4a1dcb2f27d9 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 2 Feb 2016 15:01:05 +0100 Subject: [PATCH 05/17] Email invitation: Defined "m.room.third_party_invite" events --- MatrixSDK/Data/MXRoom.m | 1 + MatrixSDK/Data/MXRoomState.h | 4 ++-- MatrixSDK/Data/MXRoomState.m | 5 +++++ MatrixSDK/Data/Store/MXFileStore/MXFileStore.m | 2 +- MatrixSDK/JSONModels/MXEvent.h | 2 ++ MatrixSDK/JSONModels/MXEvent.m | 1 + MatrixSDK/Utils/MXTools.m | 1 + 7 files changed, 13 insertions(+), 3 deletions(-) diff --git a/MatrixSDK/Data/MXRoom.m b/MatrixSDK/Data/MXRoom.m index 9b5697b107..4c4543a3b6 100644 --- a/MatrixSDK/Data/MXRoom.m +++ b/MatrixSDK/Data/MXRoom.m @@ -72,6 +72,7 @@ - (id)initWithRoomId:(NSString *)roomId andMatrixSession:(MXSession *)mxSession2 kMXEventTypeStringRoomMessage, kMXEventTypeStringRoomMessageFeedback, kMXEventTypeStringRoomRedaction, + kMXEventTypeStringRoomThirdPartyInvite, kMXEventTypeStringCallInvite, kMXEventTypeStringCallCandidates, kMXEventTypeStringCallAnswer, diff --git a/MatrixSDK/Data/MXRoomState.h b/MatrixSDK/Data/MXRoomState.h index cc7a80540e..8cc85ebb2e 100644 --- a/MatrixSDK/Data/MXRoomState.h +++ b/MatrixSDK/Data/MXRoomState.h @@ -52,7 +52,7 @@ /** A copy of the list of room members (actually MXRoomMember instances). */ -@property (nonatomic, readonly) NSArray *members; +@property (nonatomic, readonly) NSArray *members; /** The power level of room members @@ -131,7 +131,7 @@ */ - (id)initWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)matrixSession - andInitialSync:(MXRoomInitialSync*)initialSync + andInitialSync:(MXRoomInitialSync*)initialSync andDirection:(BOOL)isLive; /** diff --git a/MatrixSDK/Data/MXRoomState.m b/MatrixSDK/Data/MXRoomState.m index b801d3fc4e..b083e0f2aa 100644 --- a/MatrixSDK/Data/MXRoomState.m +++ b/MatrixSDK/Data/MXRoomState.m @@ -447,6 +447,11 @@ - (void)handleStateEvent:(MXEvent*)event break; } + case MXEventTypeRoomThirdPartyInvite: + { + // TODO + break; + } case MXEventTypeRoomPowerLevels: { powerLevels = [MXRoomPowerLevels modelFromJSON:[self contentOfEvent:event]]; diff --git a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m index 52b5b9d08b..b4ec102a4d 100644 --- a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m +++ b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m @@ -20,7 +20,7 @@ #import "MXFileStoreMetaData.h" -NSUInteger const kMXFileVersion = 18; +NSUInteger const kMXFileVersion = 19; NSString *const kMXFileStoreFolder = @"MXFileStore"; NSString *const kMXFileStoreMedaDataFile = @"MXFileStore"; diff --git a/MatrixSDK/JSONModels/MXEvent.h b/MatrixSDK/JSONModels/MXEvent.h index 9d463b0504..028309395e 100644 --- a/MatrixSDK/JSONModels/MXEvent.h +++ b/MatrixSDK/JSONModels/MXEvent.h @@ -40,6 +40,7 @@ typedef enum : NSUInteger MXEventTypeRoomMessage, MXEventTypeRoomMessageFeedback, MXEventTypeRoomRedaction, + MXEventTypeRoomThirdPartyInvite, MXEventTypeRoomTag, MXEventTypePresence, MXEventTypeTypingNotification, @@ -70,6 +71,7 @@ FOUNDATION_EXPORT NSString *const kMXEventTypeStringRoomCanonicalAlias; FOUNDATION_EXPORT NSString *const kMXEventTypeStringRoomMessage; FOUNDATION_EXPORT NSString *const kMXEventTypeStringRoomMessageFeedback; FOUNDATION_EXPORT NSString *const kMXEventTypeStringRoomRedaction; +FOUNDATION_EXPORT NSString *const kMXEventTypeStringRoomThirdPartyInvite; FOUNDATION_EXPORT NSString *const kMXEventTypeStringRoomTag; FOUNDATION_EXPORT NSString *const kMXEventTypeStringPresence; FOUNDATION_EXPORT NSString *const kMXEventTypeStringTypingNotification; diff --git a/MatrixSDK/JSONModels/MXEvent.m b/MatrixSDK/JSONModels/MXEvent.m index 5d363ff8c2..4a1309d41f 100644 --- a/MatrixSDK/JSONModels/MXEvent.m +++ b/MatrixSDK/JSONModels/MXEvent.m @@ -32,6 +32,7 @@ NSString *const kMXEventTypeStringRoomMessage = @"m.room.message"; NSString *const kMXEventTypeStringRoomMessageFeedback = @"m.room.message.feedback"; NSString *const kMXEventTypeStringRoomRedaction = @"m.room.redaction"; +NSString *const kMXEventTypeStringRoomThirdPartyInvite= @"m.room.third_party_invite"; NSString *const kMXEventTypeStringRoomTag = @"m.tag"; NSString *const kMXEventTypeStringPresence = @"m.presence"; NSString *const kMXEventTypeStringTypingNotification = @"m.typing"; diff --git a/MatrixSDK/Utils/MXTools.m b/MatrixSDK/Utils/MXTools.m index 503b803823..90e0841a3b 100644 --- a/MatrixSDK/Utils/MXTools.m +++ b/MatrixSDK/Utils/MXTools.m @@ -38,6 +38,7 @@ + (NSDictionary*)eventTypesMap kMXEventTypeStringRoomMessage: [NSNumber numberWithUnsignedInteger:MXEventTypeRoomMessage], kMXEventTypeStringRoomMessageFeedback: [NSNumber numberWithUnsignedInteger:MXEventTypeRoomMessageFeedback], kMXEventTypeStringRoomRedaction: [NSNumber numberWithUnsignedInteger:MXEventTypeRoomRedaction], + kMXEventTypeStringRoomThirdPartyInvite: [NSNumber numberWithUnsignedInteger:MXEventTypeRoomThirdPartyInvite], kMXEventTypeStringRoomTag: [NSNumber numberWithUnsignedInteger:MXEventTypeRoomTag], kMXEventTypeStringPresence: [NSNumber numberWithUnsignedInteger:MXEventTypePresence], kMXEventTypeStringTypingNotification: [NSNumber numberWithUnsignedInteger:MXEventTypeTypingNotification], From dc3a7bf748f48905f5825db5cde26ed5dbcb128b Mon Sep 17 00:00:00 2001 From: giomfo Date: Tue, 2 Feb 2016 23:48:37 +0100 Subject: [PATCH 06/17] Bug Fix: App crashes on resume Take into account pending Pause (if any) at the end of resume. --- MatrixSDK/MXSession.m | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index f09b966c72..c1c64994b2 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -342,8 +342,6 @@ - (void)startWithMessagesLimit:(NSUInteger)messagesLimit NSDate *startDate2 = [NSDate date]; [self resume:^{ NSLog(@"[MXSession] Events stream resumed in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate2] * 1000); - - [self setState:MXSessionStateRunning]; onServerSyncDone(); }]; }; @@ -465,22 +463,24 @@ - (void)streamEventsFromToken:(NSString*)token withLongPoll:(BOOL)longPoll serve } } - // the event stream is running by now + // The event stream is running by now + // CAUTION: Update the session state before calling the onResumeDone block (if any). + // Indeed if a Pause is pending, it will be applied on this state change. [self setState:MXSessionStateRunning]; // If we are resuming inform the app that it received the last uptodate data if (onResumeDone) { NSLog(@"[MXSession] Events stream resumed with %tu new events", events.count); - + onResumeDone(); onResumeDone = nil; - - // Check SDK user did not called [MXSession close] in onResumeDone - if (nil == _myUser) - { - return; - } + } + + // Check SDK user did not called [MXSession close] or [MXSession pause] + if (nil == _myUser || _state == MXSessionStatePaused) + { + return; } // Go streaming from the returned token @@ -1006,6 +1006,7 @@ - (void)initialServerSync:(void (^)())onServerSyncDone [self streamEventsFromToken:_store.eventStreamToken withLongPoll:YES]; [self setState:MXSessionStateRunning]; + onServerSyncDone(); } failure:^(NSError *error) { @@ -1181,6 +1182,11 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout } } + // The event stream is running by now + // CAUTION: Update the session state before calling the onResumeDone block (if any). + // Indeed if a Pause is pending, it will be applied on this state change. + [self setState:MXSessionStateRunning]; + // If we are resuming inform the app that it received the last uptodate data if (onResumeDone) { @@ -1188,16 +1194,13 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout onResumeDone(); onResumeDone = nil; - - // Check SDK user did not called [MXSession close] in onResumeDone - if (nil == _myUser) - { - return; - } } - // the event stream is running by now - [self setState:MXSessionStateRunning]; + // Check SDK user did not called [MXSession close] or [MXSession pause] + if (nil == _myUser || _state == MXSessionStatePaused) + { + return; + } // Pursue live events listening (long polling) [self serverSyncWithServerTimeout:SERVER_TIMEOUT_MS success:nil failure:nil clientTimeout:CLIENT_TIMEOUT_MS setPresence:nil]; From bed57bf61ea8eef61545c87cd38143925c91ad56 Mon Sep 17 00:00:00 2001 From: giomfo Date: Wed, 3 Feb 2016 11:02:09 +0100 Subject: [PATCH 07/17] Bug Fix: App crashes on resume Prevent user from changing the session state during the resume callback --- MatrixSDK/MXSession.h | 7 +++++-- MatrixSDK/MXSession.m | 20 ++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index e1bffb3860..3b786d92d2 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -250,8 +250,11 @@ FOUNDATION_EXPORT NSString *const kMXSessionNoRoomTag; /** Resume the session events stream. - @param resumeDone A block called when the SDK has been successfully resumed and - the app has received uptodate data/events. + @param resumeDone A block called when the SDK has been successfully resumed and the app + has received uptodate data/events. The live event listening (long polling) + is not launched yet. + CAUTION The session state is updated (to MXSessionStateRunning) after + calling this block. It MUST not be modified by this block. */ - (void)resume:(void (^)())resumeDone; diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index c1c64994b2..2b87520372 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -462,11 +462,6 @@ - (void)streamEventsFromToken:(NSString*)token withLongPoll:(BOOL)longPoll serve NSLog(@"[MXSession] resume after a background Sync "); } } - - // The event stream is running by now - // CAUTION: Update the session state before calling the onResumeDone block (if any). - // Indeed if a Pause is pending, it will be applied on this state change. - [self setState:MXSessionStateRunning]; // If we are resuming inform the app that it received the last uptodate data if (onResumeDone) @@ -477,7 +472,10 @@ - (void)streamEventsFromToken:(NSString*)token withLongPoll:(BOOL)longPoll serve onResumeDone = nil; } - // Check SDK user did not called [MXSession close] or [MXSession pause] + // The event stream is running by now + [self setState:MXSessionStateRunning]; + + // Check SDK user did not called [MXSession close] or [MXSession pause] during the session state change notification handling. if (nil == _myUser || _state == MXSessionStatePaused) { return; @@ -1182,11 +1180,6 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout } } - // The event stream is running by now - // CAUTION: Update the session state before calling the onResumeDone block (if any). - // Indeed if a Pause is pending, it will be applied on this state change. - [self setState:MXSessionStateRunning]; - // If we are resuming inform the app that it received the last uptodate data if (onResumeDone) { @@ -1196,7 +1189,10 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout onResumeDone = nil; } - // Check SDK user did not called [MXSession close] or [MXSession pause] + // The event stream is running by now + [self setState:MXSessionStateRunning]; + + // Check SDK user did not called [MXSession close] or [MXSession pause] during the session state change notification handling. if (nil == _myUser || _state == MXSessionStatePaused) { return; From 3d892b530da2d24609a903d60592c9bc8de80150 Mon Sep 17 00:00:00 2001 From: giomfo Date: Wed, 3 Feb 2016 11:07:31 +0100 Subject: [PATCH 08/17] code cleaning --- MatrixSDK/MXSession.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index 3b786d92d2..24d4cac429 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -251,8 +251,8 @@ FOUNDATION_EXPORT NSString *const kMXSessionNoRoomTag; Resume the session events stream. @param resumeDone A block called when the SDK has been successfully resumed and the app - has received uptodate data/events. The live event listening (long polling) - is not launched yet. + has received uptodate data/events. The live event listening + (long polling) is not launched yet. CAUTION The session state is updated (to MXSessionStateRunning) after calling this block. It MUST not be modified by this block. */ From 248f05411563f1f504926de8c933223c41dadc12 Mon Sep 17 00:00:00 2001 From: giomfo Date: Wed, 3 Feb 2016 12:00:16 +0100 Subject: [PATCH 09/17] Bug Fix: App crashes on resume Operations on session may occur during registered callback block. For example, [MXSession close] or [MXSession pause] may be triggered. Run a copy of the block to prevent app from crashing if the block is released by one of these operations. --- MatrixSDK/MXSession.h | 2 +- MatrixSDK/MXSession.m | 44 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index 24d4cac429..8c079ecf7c 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -254,7 +254,7 @@ FOUNDATION_EXPORT NSString *const kMXSessionNoRoomTag; has received uptodate data/events. The live event listening (long polling) is not launched yet. CAUTION The session state is updated (to MXSessionStateRunning) after - calling this block. It MUST not be modified by this block. + calling this block. It SHOULD not be modified by this block. */ - (void)resume:(void (^)())resumeDone; diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index 2b87520372..7ac0130b28 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -446,7 +446,11 @@ - (void)streamEventsFromToken:(NSString*)token withLongPoll:(BOOL)longPoll serve if (onBackgroundSyncDone) { NSLog(@"[MXSession] background Sync with %tu new events", events.count); - onBackgroundSyncDone(); + + // Operations on session may occur during this block. For example, [MXSession close] may be triggered. + // We run a copy of the block to prevent app from crashing if the block is released by one of these operations. + MXOnBackgroundSyncDone onBackgroundSyncDoneCpy = [onBackgroundSyncDone copy]; + onBackgroundSyncDoneCpy(); onBackgroundSyncDone = nil; // check that the application was not resumed while catching up @@ -468,8 +472,17 @@ - (void)streamEventsFromToken:(NSString*)token withLongPoll:(BOOL)longPoll serve { NSLog(@"[MXSession] Events stream resumed with %tu new events", events.count); - onResumeDone(); + // Operations on session may occur during this block. For example, [MXSession close] or [MXSession pause] may be triggered. + // We run a copy of the block to prevent app from crashing if the block is released by one of these operations. + MXOnResumeDone onResumeDoneCpy = [onResumeDone copy]; + onResumeDoneCpy(); onResumeDone = nil; + + // Stop here if [MXSession close] or [MXSession pause] has been triggered during onResumeDone block. + if (nil == _myUser || _state == MXSessionStatePaused) + { + return; + } } // The event stream is running by now @@ -496,7 +509,10 @@ - (void)streamEventsFromToken:(NSString*)token withLongPoll:(BOOL)longPoll serve { NSLog(@"[MXSession] background Sync fails %@", error); - onBackgroundSyncFail(error); + // Operations on session may occur during this block. For example, [MXSession close] may be triggered. + // We run a copy of the block to prevent app from crashing if the block is released by one of these operations. + MXOnBackgroundSyncFail onBackgroundSyncFailCpy = [onBackgroundSyncFail copy]; + onBackgroundSyncFailCpy(error); onBackgroundSyncFail = nil; // check that the application was not resumed while catching up in background @@ -1163,7 +1179,11 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout if (onBackgroundSyncDone) { NSLog(@"[MXSession] Events stream background Sync succeeded"); - onBackgroundSyncDone(); + + // Operations on session may occur during this block. For example, [MXSession close] may be triggered. + // We run a copy of the block to prevent app from crashing if the block is released by one of these operations. + MXOnBackgroundSyncDone onBackgroundSyncDoneCpy = [onBackgroundSyncDone copy]; + onBackgroundSyncDoneCpy(); onBackgroundSyncDone = nil; // check that the application was not resumed while catching up in background @@ -1185,8 +1205,17 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout { NSLog(@"[MXSession] Events stream resumed"); - onResumeDone(); + // Operations on session may occur during this block. For example, [MXSession close] or [MXSession pause] may be triggered. + // We run a copy of the block to prevent app from crashing if the block is released by one of these operations. + MXOnResumeDone onResumeDoneCpy = [onResumeDone copy]; + onResumeDoneCpy(); onResumeDone = nil; + + // Stop here if [MXSession close] or [MXSession pause] has been triggered during onResumeDone block. + if (nil == _myUser || _state == MXSessionStatePaused) + { + return; + } } // The event stream is running by now @@ -1224,7 +1253,10 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout { NSLog(@"[MXSession] background Sync fails %@", error); - onBackgroundSyncFail(error); + // Operations on session may occur during this block. For example, [MXSession close] may be triggered. + // We run a copy of the block to prevent app from crashing if the block is released by one of these operations. + MXOnBackgroundSyncFail onBackgroundSyncFailCpy = [onBackgroundSyncFail copy]; + onBackgroundSyncFailCpy(error); onBackgroundSyncFail = nil; // check that the application was not resumed while catching up in background From a8b077c7ceec83cc7b2c0e2211a533b0056e3df2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 3 Feb 2016 17:26:15 +0100 Subject: [PATCH 10/17] Email invitation: Added MXRoomThirdPartyInvite to store 3pid invite in the room state --- MatrixSDK.xcodeproj/project.pbxproj | 8 ++++ MatrixSDK/Data/MXRoomState.h | 6 +++ MatrixSDK/Data/MXRoomState.m | 38 ++++++++++++++++++- MatrixSDK/Data/MXRoomThirdPartyInvite.h | 49 +++++++++++++++++++++++++ MatrixSDK/Data/MXRoomThirdPartyInvite.m | 35 ++++++++++++++++++ 5 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 MatrixSDK/Data/MXRoomThirdPartyInvite.h create mode 100644 MatrixSDK/Data/MXRoomThirdPartyInvite.m diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 01fff8b721..0cd351ceb8 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -76,6 +76,8 @@ 327E37B61A974F75007F026F /* MXLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 327E37B41A974F75007F026F /* MXLogger.h */; }; 327E37B71A974F75007F026F /* MXLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 327E37B51A974F75007F026F /* MXLogger.m */; }; 327E37B91A977810007F026F /* MXLoggerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 327E37B81A977810007F026F /* MXLoggerTests.m */; }; + 327F8DB21C6112BA00581CA3 /* MXRoomThirdPartyInvite.h in Headers */ = {isa = PBXBuildFile; fileRef = 327F8DB01C6112BA00581CA3 /* MXRoomThirdPartyInvite.h */; }; + 327F8DB31C6112BA00581CA3 /* MXRoomThirdPartyInvite.m in Sources */ = {isa = PBXBuildFile; fileRef = 327F8DB11C6112BA00581CA3 /* MXRoomThirdPartyInvite.m */; }; 3281E89E19E299C000976E1A /* MXErrorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3281E89D19E299C000976E1A /* MXErrorTests.m */; }; 3281E8A019E2CC1200976E1A /* MXHTTPClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3281E89F19E2CC1200976E1A /* MXHTTPClientTests.m */; }; 3281E8A219E2DE4300976E1A /* MXSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3281E8A119E2DE4300976E1A /* MXSessionTests.m */; }; @@ -219,6 +221,8 @@ 327E37B41A974F75007F026F /* MXLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXLogger.h; sourceTree = ""; }; 327E37B51A974F75007F026F /* MXLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXLogger.m; sourceTree = ""; }; 327E37B81A977810007F026F /* MXLoggerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXLoggerTests.m; sourceTree = ""; }; + 327F8DB01C6112BA00581CA3 /* MXRoomThirdPartyInvite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXRoomThirdPartyInvite.h; sourceTree = ""; }; + 327F8DB11C6112BA00581CA3 /* MXRoomThirdPartyInvite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXRoomThirdPartyInvite.m; sourceTree = ""; }; 3281E89D19E299C000976E1A /* MXErrorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXErrorTests.m; sourceTree = ""; }; 3281E89F19E2CC1200976E1A /* MXHTTPClientTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXHTTPClientTests.m; sourceTree = ""; }; 3281E8A119E2DE4300976E1A /* MXSessionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = MXSessionTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; @@ -325,6 +329,8 @@ 3220094419EFBF30008DE41D /* MXSessionEventListener.m */, 329FB1731A0A3A1600A5E88E /* MXRoomMember.h */, 329FB1741A0A3A1600A5E88E /* MXRoomMember.m */, + 327F8DB01C6112BA00581CA3 /* MXRoomThirdPartyInvite.h */, + 327F8DB11C6112BA00581CA3 /* MXRoomThirdPartyInvite.m */, 329FB17D1A0B665800A5E88E /* MXUser.h */, 329FB17E1A0B665800A5E88E /* MXUser.m */, 327137251A24D50A00DB6757 /* MXMyUser.h */, @@ -608,6 +614,7 @@ 32CE6FB81A409B1F00317F1E /* MXFileStoreMetaData.h in Headers */, 3281E8B719E42DFE00976E1A /* MXJSONModel.h in Headers */, 323E0C5B1A306D7A00A31D73 /* MXEvent.h in Headers */, + 327F8DB21C6112BA00581CA3 /* MXRoomThirdPartyInvite.h in Headers */, 322360521A8E610500A3CA81 /* MXPushRuleDisplayNameCondtionChecker.h in Headers */, 3245A7521AF7B2930001D8A7 /* MXCallManager.h in Headers */, 3264E2A21BDF8D1500F89A86 /* MXCoreDataRoomState.h in Headers */, @@ -789,6 +796,7 @@ 32DC15D51A8CF874006F9AD3 /* MXPushRuleEventMatchConditionChecker.m in Sources */, 32CAB1081A91EA34008C5BB9 /* MXPushRuleRoomMemberCountConditionChecker.m in Sources */, 3245A7511AF7B2930001D8A7 /* MXCall.m in Sources */, + 327F8DB31C6112BA00581CA3 /* MXRoomThirdPartyInvite.m in Sources */, 323B2AE21BCD4CB600B11F34 /* MXCoreDataAccount.m in Sources */, 3264E2A51BDF8D1500F89A86 /* MXCoreDataRoomState+CoreDataProperties.m in Sources */, 329FB1761A0A3A1600A5E88E /* MXRoomMember.m in Sources */, diff --git a/MatrixSDK/Data/MXRoomState.h b/MatrixSDK/Data/MXRoomState.h index 8cc85ebb2e..b8a52eed77 100644 --- a/MatrixSDK/Data/MXRoomState.h +++ b/MatrixSDK/Data/MXRoomState.h @@ -19,6 +19,7 @@ #import "MXEvent.h" #import "MXJSONModels.h" #import "MXRoomMember.h" +#import "MXRoomThirdPartyInvite.h" #import "MXRoomPowerLevels.h" @class MXSession; @@ -54,6 +55,11 @@ */ @property (nonatomic, readonly) NSArray *members; +/** +A copy of the list of third party invites (actually MXRoomThirdPartyInvite instances). +*/ +@property (nonatomic, readonly) NSArray *thirdPartyInvites; + /** The power level of room members */ diff --git a/MatrixSDK/Data/MXRoomState.m b/MatrixSDK/Data/MXRoomState.m index b083e0f2aa..fcd479fc5a 100644 --- a/MatrixSDK/Data/MXRoomState.m +++ b/MatrixSDK/Data/MXRoomState.m @@ -27,8 +27,13 @@ @interface MXRoomState () NSMutableDictionary *stateEvents; NSMutableDictionary *members; + + /** + The third party invites. The key is the token provided by the homeserver. + */ + NSMutableDictionary *thirdPartyInvites; - /* + /** Additional and optional metadata got from initialSync */ MXMembership membership; @@ -71,6 +76,7 @@ - (id)initWithRoomId:(NSString*)roomId stateEvents = [NSMutableDictionary dictionary]; members = [NSMutableDictionary dictionary]; membersNamesCache = [NSMutableDictionary dictionary]; + thirdPartyInvites = [NSMutableDictionary dictionary]; } return self; } @@ -146,6 +152,13 @@ - (NSArray *)stateEvents { [state addObject:roomMember.originalEvent]; } + + // Third party invites are state events too + for (MXRoomThirdPartyInvite *thirdPartyInvite in self.thirdPartyInvites) + { + [state addObject:thirdPartyInvite.originalEvent]; + } + return state; } @@ -154,6 +167,11 @@ - (NSArray *)members return [members allValues]; } +- (NSArray *)thirdPartyInvites +{ + return [thirdPartyInvites allValues]; +} + - (void)setIsPublic:(BOOL)isPublicValue { isPublic = isPublicValue; @@ -449,7 +467,21 @@ - (void)handleStateEvent:(MXEvent*)event } case MXEventTypeRoomThirdPartyInvite: { - // TODO + // The content and the prev_content of a m.room.third_party_invite event are the same. + // So, use isLive to know if the invite must be added or removed (case of back state). + if (_isLive) + { + MXRoomThirdPartyInvite *thirdPartyInvite = [[MXRoomThirdPartyInvite alloc] initWithMXEvent:event]; + if (thirdPartyInvite) + { + thirdPartyInvites[thirdPartyInvite.token] = thirdPartyInvite; + } + } + else + { + // Note: the 3pid invite token is stored in the event state key + [thirdPartyInvites removeObjectForKey:event.stateKey]; + } break; } case MXEventTypeRoomPowerLevels: @@ -596,6 +628,8 @@ - (id)copyWithZone:(NSZone *)zone // membership change (ex: "invited" -> "joined") stateCopy->members = [[NSMutableDictionary allocWithZone:zone] initWithDictionary:members]; + stateCopy->thirdPartyInvites = [[NSMutableDictionary allocWithZone:zone] initWithDictionary:thirdPartyInvites]; + if (visibility) { stateCopy->visibility = [visibility copyWithZone:zone]; diff --git a/MatrixSDK/Data/MXRoomThirdPartyInvite.h b/MatrixSDK/Data/MXRoomThirdPartyInvite.h new file mode 100644 index 0000000000..cfcee4cdce --- /dev/null +++ b/MatrixSDK/Data/MXRoomThirdPartyInvite.h @@ -0,0 +1,49 @@ +/* + Copyright 2016 OpenMarket Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#import "MXEvent.h" + +/** + `MXRoomThirdPartyInvite` is the information about a user invited via a third party medium. + */ +@interface MXRoomThirdPartyInvite : NSObject + +/** + The user display name as provided by the home sever. + */ +@property (nonatomic, readonly) NSString *displayname; + +/** + The token generated by the identity server. + */ +@property (nonatomic, readonly) NSString *token; + +/** + The event used to build the MXRoomThirdPartyInvite. + */ +@property (nonatomic, readonly) MXEvent *originalEvent; + +/** + Create the MXRoomThirdPartyInvite member from a Matrix m.room.third_party_invite event by + specifying the content to use.. + + @param roomThirdPartyInviteEvent The m.room.third_party_invite event. + */ +- (instancetype)initWithMXEvent:(MXEvent *)roomThirdPartyInviteEvent; + +@end diff --git a/MatrixSDK/Data/MXRoomThirdPartyInvite.m b/MatrixSDK/Data/MXRoomThirdPartyInvite.m new file mode 100644 index 0000000000..1ca2f0ca2e --- /dev/null +++ b/MatrixSDK/Data/MXRoomThirdPartyInvite.m @@ -0,0 +1,35 @@ +/* + Copyright 2016 OpenMarket Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "MXRoomThirdPartyInvite.h" + +#import "MXJSONModels.h" + +@implementation MXRoomThirdPartyInvite + +- (instancetype)initWithMXEvent:(MXEvent *)roomThirdPartyInviteEvent +{ + self = [super init]; + if (self) + { + MXJSONModelSetString(_displayname, roomThirdPartyInviteEvent.content[@"display_name"]); + MXJSONModelSetString(_token, roomThirdPartyInviteEvent.stateKey); + _originalEvent = roomThirdPartyInviteEvent; + } + return self; +} + +@end From 833778495368fffc1492d4a4ba40cb692ffe90f7 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 4 Feb 2016 11:37:07 +0100 Subject: [PATCH 11/17] Email invitation: Managed third_party_invite field in m.room.member events --- MatrixSDK/Data/MXRoomMember.h | 7 ++++++- MatrixSDK/Data/MXRoomMember.m | 1 + MatrixSDK/Data/MXRoomState.h | 21 +++++++++++++++++++++ MatrixSDK/Data/MXRoomState.m | 27 +++++++++++++++++++++++++-- MatrixSDK/JSONModels/MXJSONModels.h | 6 ++++++ MatrixSDK/JSONModels/MXJSONModels.m | 5 +++++ 6 files changed, 64 insertions(+), 3 deletions(-) diff --git a/MatrixSDK/Data/MXRoomMember.h b/MatrixSDK/Data/MXRoomMember.h index 5fc338a5fe..ce7365794f 100644 --- a/MatrixSDK/Data/MXRoomMember.h +++ b/MatrixSDK/Data/MXRoomMember.h @@ -53,9 +53,14 @@ */ @property (nonatomic, readonly) NSString *originUserId; +/** + If the m.room.member event is the successor of a m.room.third_party_invite event, + 'thirdPartyInviteToken' is the token of this event. Else, nil. + */ +@property (nonatomic, readonly) NSString *thirdPartyInviteToken; + /** The event used to build the MXRoomMember. - // @TODO: Consider MXRoomMember as a child class of MXEvent to avoid such data duplication. */ @property (nonatomic, readonly) MXEvent *originalEvent; diff --git a/MatrixSDK/Data/MXRoomMember.m b/MatrixSDK/Data/MXRoomMember.m index be2c5e67f4..2d6788389a 100644 --- a/MatrixSDK/Data/MXRoomMember.m +++ b/MatrixSDK/Data/MXRoomMember.m @@ -50,6 +50,7 @@ - (instancetype)initWithMXEvent:(MXEvent*)roomMemberEvent // We ignore non mxc avatar url _avatarUrl = ([roomMemberContent.avatarUrl hasPrefix:kMXContentUriScheme] ? roomMemberContent.avatarUrl : nil); _membership = [MXTools membership:roomMemberContent.membership]; + _thirdPartyInviteToken = roomMemberContent.thirdPartyInviteToken; _originalEvent = roomMemberEvent; // Set who is this member diff --git a/MatrixSDK/Data/MXRoomState.h b/MatrixSDK/Data/MXRoomState.h index b8a52eed77..19c8498009 100644 --- a/MatrixSDK/Data/MXRoomState.h +++ b/MatrixSDK/Data/MXRoomState.h @@ -164,6 +164,27 @@ A copy of the list of third party invites (actually MXRoomThirdPartyInvite insta */ - (MXRoomMember*)memberWithUserId:(NSString*)userId; +/** + Return the member who was invited by a 3pid medium with the given token. + + When invited by a 3pid medium like email, the not-yet-registered-to-matrix user is indicated + in the room state by a m.room.third_party_invite event. + Once he registers, the homeserver adds a m.room.membership event to the room state. + This event then contains the token of the previous m.room.third_party_invite event. + + @param thirdPartyInviteToken the m.room.third_party_invite token to look for. + @return the room member. + */ +- (MXRoomMember*)memberWithThirdPartyInviteToken:(NSString*)thirdPartyInviteToken; + +/** + Return 3pid invite with the given token. + + @param thirdPartyInviteToken the m.room.third_party_invite token to look for. + @return the 3pid invite. + */ +- (MXRoomThirdPartyInvite*)thirdPartyInviteWithToken:(NSString*)thirdPartyInviteToken; + /** Return a display name for a member. It is his displayname member or, if nil, his userId diff --git a/MatrixSDK/Data/MXRoomState.m b/MatrixSDK/Data/MXRoomState.m index fcd479fc5a..deafa51e20 100644 --- a/MatrixSDK/Data/MXRoomState.m +++ b/MatrixSDK/Data/MXRoomState.m @@ -54,7 +54,13 @@ @interface MXRoomState () The key is the user id. The value, the member name to display. This cache is resetted when there is new room member event. */ - NSMutableDictionary *membersNamesCache; + NSMutableDictionary *membersNamesCache; + + /** + Cache for [self memberWithThirdPartyInviteToken]. + The key is the 3pid invite token. + */ + NSMutableDictionary *membersWithThirdPartyInviteTokenCache; } @end @@ -75,8 +81,9 @@ - (id)initWithRoomId:(NSString*)roomId stateEvents = [NSMutableDictionary dictionary]; members = [NSMutableDictionary dictionary]; - membersNamesCache = [NSMutableDictionary dictionary]; thirdPartyInvites = [NSMutableDictionary dictionary]; + membersNamesCache = [NSMutableDictionary dictionary]; + membersWithThirdPartyInviteTokenCache = [NSMutableDictionary dictionary]; } return self; } @@ -444,6 +451,12 @@ - (void)handleStateEvent:(MXEvent*)event // Force to use an identicon url roomMember.avatarUrl = [mxSession.matrixRestClient urlOfIdenticon:roomMember.userId]; } + + // Cache room member event that is successor of a third party invite event + if (roomMember.thirdPartyInviteToken) + { + membersWithThirdPartyInviteTokenCache[roomMember.thirdPartyInviteToken] = roomMember; + } } else { @@ -516,6 +529,16 @@ - (MXRoomMember*)memberWithUserId:(NSString *)userId return members[userId]; } +- (MXRoomMember *)memberWithThirdPartyInviteToken:(NSString *)thirdPartyInviteToken +{ + return membersWithThirdPartyInviteTokenCache[thirdPartyInviteToken]; +} + +- (MXRoomThirdPartyInvite *)thirdPartyInviteWithToken:(NSString *)thirdPartyInviteToken +{ + return thirdPartyInvites[thirdPartyInviteToken]; +} + - (NSString*)memberName:(NSString*)userId { // First, lookup in the cache diff --git a/MatrixSDK/JSONModels/MXJSONModels.h b/MatrixSDK/JSONModels/MXJSONModels.h index 294e9ef377..c7030e095f 100644 --- a/MatrixSDK/JSONModels/MXJSONModels.h +++ b/MatrixSDK/JSONModels/MXJSONModels.h @@ -209,6 +209,12 @@ FOUNDATION_EXPORT NSString *const kMXLoginFlowTypeRecaptcha; */ @property (nonatomic) NSString *membership; + /** + If the m.room.member event is the successor of a m.room.third_party_invite event, + 'thirdPartyInviteToken' is the token of this event. Else, nil. + */ + @property (nonatomic) NSString *thirdPartyInviteToken; + @end diff --git a/MatrixSDK/JSONModels/MXJSONModels.m b/MatrixSDK/JSONModels/MXJSONModels.m index bddf895a92..d92fff5df7 100644 --- a/MatrixSDK/JSONModels/MXJSONModels.m +++ b/MatrixSDK/JSONModels/MXJSONModels.m @@ -173,6 +173,11 @@ + (id)modelFromJSON:(NSDictionary *)JSONDictionary MXJSONModelSetString(roomMemberEventContent.displayname, JSONDictionary[@"displayname"]); MXJSONModelSetString(roomMemberEventContent.avatarUrl, JSONDictionary[@"avatar_url"]); MXJSONModelSetString(roomMemberEventContent.membership, JSONDictionary[@"membership"]); + + if (JSONDictionary[@"third_party_invite"] && JSONDictionary[@"third_party_invite"][@"signed"]) + { + MXJSONModelSetString(roomMemberEventContent.thirdPartyInviteToken, JSONDictionary[@"third_party_invite"][@"signed"][@"token"]); + } } return roomMemberEventContent; From d970bbae97bb5af55206df6c650449d6d6abe452 Mon Sep 17 00:00:00 2001 From: giomfo Date: Thu, 4 Feb 2016 19:10:16 +0100 Subject: [PATCH 12/17] Bug Fix Account creation: registration fallback failed --- MatrixSDK/MXRestClient.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MatrixSDK/MXRestClient.m b/MatrixSDK/MXRestClient.m index a68b19899f..d3625c4b0d 100644 --- a/MatrixSDK/MXRestClient.m +++ b/MatrixSDK/MXRestClient.m @@ -192,7 +192,7 @@ - (MXHTTPOperation*)registerWithUser:(NSString*)user andPassword:(NSString*)pass - (NSString*)registerFallback; { - return [[NSURL URLWithString:@"_matrix/static/client/register" relativeToURL:[NSURL URLWithString:homeserver]] absoluteString]; + return [[NSURL URLWithString:@"_matrix/static/client/register/" relativeToURL:[NSURL URLWithString:homeserver]] absoluteString]; } #pragma mark - Login operations @@ -218,7 +218,7 @@ - (MXHTTPOperation*)loginWithUser:(NSString *)user andPassword:(NSString *)passw - (NSString*)loginFallback; { - return [[NSURL URLWithString:@"/_matrix/static/client/login" relativeToURL:[NSURL URLWithString:homeserver]] absoluteString]; + return [[NSURL URLWithString:@"/_matrix/static/client/login/" relativeToURL:[NSURL URLWithString:homeserver]] absoluteString]; } From 70d433e2d6c6a668ff52e84c6b668f2b43624da3 Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 8 Feb 2016 08:40:40 +0100 Subject: [PATCH 13/17] Email invitation: membersWithThirdPartyInviteTokenCache needs to be NSCopied too --- MatrixSDK/Data/MXRoomState.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MatrixSDK/Data/MXRoomState.m b/MatrixSDK/Data/MXRoomState.m index deafa51e20..c8435f5ae5 100644 --- a/MatrixSDK/Data/MXRoomState.m +++ b/MatrixSDK/Data/MXRoomState.m @@ -60,7 +60,7 @@ @interface MXRoomState () Cache for [self memberWithThirdPartyInviteToken]. The key is the 3pid invite token. */ - NSMutableDictionary *membersWithThirdPartyInviteTokenCache; + NSMutableDictionary *membersWithThirdPartyInviteTokenCache; } @end @@ -653,6 +653,8 @@ - (id)copyWithZone:(NSZone *)zone stateCopy->thirdPartyInvites = [[NSMutableDictionary allocWithZone:zone] initWithDictionary:thirdPartyInvites]; + stateCopy->membersWithThirdPartyInviteTokenCache= [[NSMutableDictionary allocWithZone:zone] initWithDictionary:membersWithThirdPartyInviteTokenCache]; + if (visibility) { stateCopy->visibility = [visibility copyWithZone:zone]; From 210c7989a26695a5f4866860c9577714462d726e Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 8 Feb 2016 14:02:13 +0100 Subject: [PATCH 14/17] MXFileStore: Do not log all rooms read receipts at startup --- MatrixSDK/Data/Store/MXFileStore/MXFileStore.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m index b4ec102a4d..4b5a509219 100644 --- a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m +++ b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m @@ -879,7 +879,7 @@ - (void)loadReceipts if (receiptsDict) { - NSLog(@" - %@: %@", roomId, receiptsDict); + NSLog(@" - %@: %tu", roomId, receiptsDict.count); [receiptsByRoomId setObject:receiptsDict forKey:roomId]; } From a3929dce50aeee93b9bdac342c660803e406259b Mon Sep 17 00:00:00 2001 From: giomfo Date: Tue, 9 Feb 2016 11:56:35 +0100 Subject: [PATCH 15/17] MXSession: Remove server sync v2 patch (limit 250). --- MatrixSDK/MXSession.m | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index 7ac0130b28..def90b77e3 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -1040,16 +1040,7 @@ - (void)serverSyncWithServerTimeout:(NSUInteger)serverTimeout NSDate *startDate = [NSDate date]; NSLog(@"[MXSession] Do a server sync"); - // *** PATCH SYNC V2 *** - NSString *inlineFilter; - if (_store.eventStreamToken) - { - // We increase the limit for catch-up syncs so that we get more of the v1 behaviour until v2 /sync performance improves - inlineFilter = @"{\"room\":{\"timeline\":{\"limit\":250}}}"; - } - // *** PATCH SYNC V2 *** - - eventStreamRequest = [matrixRestClient syncFromToken:_store.eventStreamToken serverTimeout:serverTimeout clientTimeout:clientTimeout setPresence:setPresence filter:inlineFilter success:^(MXSyncResponse *syncResponse) { + eventStreamRequest = [matrixRestClient syncFromToken:_store.eventStreamToken serverTimeout:serverTimeout clientTimeout:clientTimeout setPresence:setPresence filter:nil success:^(MXSyncResponse *syncResponse) { // Make sure [MXSession close] or [MXSession pause] has not been called before the server response if (!eventStreamRequest) From bc4a12d5224e36c7a50686693c63d26b7e80378a Mon Sep 17 00:00:00 2001 From: giomfo Date: Tue, 9 Feb 2016 11:59:10 +0100 Subject: [PATCH 16/17] Prepare release matrix-iso-sdk v0.6.2 --- CHANGES.rst | 11 +++++++++++ MatrixSDK.podspec | 4 ++-- MatrixSDK/MXSession.m | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index e9a198128d..c0d3387659 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,14 @@ +Changes in Matrix iOS SDK in 0.6.2 (2016-02-09) +=============================================== + +Improvements: + * MXRoom: Add an argument to limit the pagination to the messages from the store. + * MXRoom: Support email invitation. + +Bug fixes: + * App crashes on resume if a pause is pending. + * Account creation: reCaptcha is missing in registration fallback. + Changes in Matrix iOS SDK in 0.6.1 (2016-01-29) =============================================== diff --git a/MatrixSDK.podspec b/MatrixSDK.podspec index 0076d32ed5..369b2114ec 100644 --- a/MatrixSDK.podspec +++ b/MatrixSDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MatrixSDK" - s.version = "0.6.1" + s.version = "0.6.2" s.summary = "The iOS SDK to build apps compatible with Matrix (http://www.matrix.org)" s.description = <<-DESC @@ -19,7 +19,7 @@ Pod::Spec.new do |s| s.platform = :ios, "7.0" - s.source = { :git => "https://github.com/matrix-org/matrix-ios-sdk.git", :tag => "v0.6.1" } + s.source = { :git => "https://github.com/matrix-org/matrix-ios-sdk.git", :tag => "v0.6.2" } s.source_files = "MatrixSDK", "MatrixSDK/**/*.{h,m}" s.resources = "MatrixSDK/Data/Store/MXCoreDataStore/*.xcdatamodeld" diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index def90b77e3..dae6c06a2c 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -31,7 +31,7 @@ #pragma mark - Constants definitions -const NSString *MatrixSDKVersion = @"0.6.1"; +const NSString *MatrixSDKVersion = @"0.6.2"; NSString *const kMXSessionStateDidChangeNotification = @"kMXSessionStateDidChangeNotification"; NSString *const kMXSessionNewRoomNotification = @"kMXSessionNewRoomNotification"; NSString *const kMXSessionWillLeaveRoomNotification = @"kMXSessionWillLeaveRoomNotification"; From 2691f6a05249ffec69d47ac3f55e8d465ae95d13 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 9 Feb 2016 12:03:58 +0100 Subject: [PATCH 17/17] MXRestClient: Updated API url for avatarUrlForUser --- MatrixSDK/MXRestClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatrixSDK/MXRestClient.m b/MatrixSDK/MXRestClient.m index e6b4004ed6..38ee6a55da 100644 --- a/MatrixSDK/MXRestClient.m +++ b/MatrixSDK/MXRestClient.m @@ -1694,7 +1694,7 @@ - (MXHTTPOperation*)avatarUrlForUser:(NSString*)userId userId = credentials.userId; } - NSString *path = [NSString stringWithFormat:@"api/v1/profile/%@/avatarUrl", userId]; + NSString *path = [NSString stringWithFormat:@"api/v1/profile/%@/avatar_url", userId]; return [httpClient requestWithMethod:@"GET" path:path parameters:nil