Rename GroupManager methods.

This commit is contained in:
Matthew Chen 2020-02-13 13:49:11 -03:00
parent 2f9ee1e0f8
commit 9ce3a42f74
12 changed files with 509 additions and 489 deletions

View File

@ -121,7 +121,7 @@ NS_ASSUME_NONNULL_BEGIN
TSAccountManager.localAddress,
] mutableCopy];
[GroupManager createNewGroupObjcWithMembers:recipientAddresses
[GroupManager localCreateNewGroupObjcWithMembers:recipientAddresses
groupId:nil
name:groupName
avatarData:nil

View File

@ -80,7 +80,7 @@ public extension DebugUIMessages {
let members = uuidMembers + [TSAccountManager.localAddress!]
let groupName = "UUID Group"
GroupManager.createNewGroup(members: members, name: groupName, shouldSendMessage: true).retainUntilComplete()
GroupManager.localCreateNewGroup(members: members, name: groupName, shouldSendMessage: true).retainUntilComplete()
}
}

View File

@ -233,18 +233,17 @@ NS_ASSUME_NONNULL_BEGIN
thread:thread];
}];
}],
[OWSTableItem
itemWithTitle:@"Request Bogus group info"
actionBlock:^{
OWSLogInfo(@"Requesting bogus group info for thread: %@", thread);
OWSGroupInfoRequestMessage *groupInfoRequestMessage =
[[OWSGroupInfoRequestMessage alloc] initWithThread:thread
groupId:[TSGroupModel generateRandomV1GroupId]];
[self writeWithBlock:^(SDSAnyWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:groupInfoRequestMessage.asPreparer
transaction:transaction];
}];
}],
[OWSTableItem itemWithTitle:@"Request Bogus group info"
actionBlock:^{
OWSLogInfo(@"Requesting bogus group info for thread: %@", thread);
OWSGroupInfoRequestMessage *groupInfoRequestMessage = [[OWSGroupInfoRequestMessage alloc]
initWithThread:thread
groupId:[TSGroupModel generateRandomV1GroupId]];
[self writeWithBlock:^(SDSAnyWriteTransaction *_Nonnull transaction) {
[self.messageSenderJobQueue addMessage:groupInfoRequestMessage.asPreparer
transaction:transaction];
}];
}],
[OWSTableItem itemWithTitle:@"Message with stalled timer"
actionBlock:^{
[DebugUIMessages createDisappearingMessagesWhichFailedToStartInThread:thread];
@ -419,8 +418,9 @@ NS_ASSUME_NONNULL_BEGIN
}
[dataSource setSourceFilename:filename];
SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType imageQuality:TSImageQualityOriginal];
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource
dataUTI:utiType
imageQuality:TSImageQualityOriginal];
NSString *messageBody = nil;
if (hasCaption) {
@ -568,23 +568,22 @@ NS_ASSUME_NONNULL_BEGIN
label = [label stringByAppendingString:@" 🔤"];
}
return [DebugUIMessagesSingleAction
actionWithLabel:label
staggeredActionBlock:^(NSUInteger index,
SDSAnyWriteTransaction *transaction,
ActionSuccessBlock success,
ActionFailureBlock failure) {
dispatch_async(dispatch_get_main_queue(), ^{
OWSAssertDebug(fakeAssetLoader.filePath.length > 0);
[self sendAttachmentWithFilePath:fakeAssetLoader.filePath
thread:thread
label:label
hasCaption:hasCaption
success:success
failure:failure];
});
}
prepareBlock:fakeAssetLoader.prepareBlock];
return [DebugUIMessagesSingleAction actionWithLabel:label
staggeredActionBlock:^(NSUInteger index,
SDSAnyWriteTransaction *transaction,
ActionSuccessBlock success,
ActionFailureBlock failure) {
dispatch_async(dispatch_get_main_queue(), ^{
OWSAssertDebug(fakeAssetLoader.filePath.length > 0);
[self sendAttachmentWithFilePath:fakeAssetLoader.filePath
thread:thread
label:label
hasCaption:hasCaption
success:success
failure:failure];
});
}
prepareBlock:fakeAssetLoader.prepareBlock];
}
+ (DebugUIMessagesAction *)sendAllMediaAction:(TSThread *)thread
@ -856,18 +855,17 @@ NS_ASSUME_NONNULL_BEGIN
isDelivered:NO
isRead:NO]];
return
[DebugUIMessagesSingleAction actionWithLabel:label
unstaggeredActionBlock:^(NSUInteger index, SDSAnyWriteTransaction *transaction) {
OWSAssertDebug(fakeAssetLoader.filePath.length > 0);
[self createFakeOutgoingMedia:index
messageState:messageState
hasCaption:hasCaption
fakeAssetLoader:fakeAssetLoader
thread:thread
transaction:transaction];
}
prepareBlock:fakeAssetLoader.prepareBlock];
return [DebugUIMessagesSingleAction actionWithLabel:label
unstaggeredActionBlock:^(NSUInteger index, SDSAnyWriteTransaction *transaction) {
OWSAssertDebug(fakeAssetLoader.filePath.length > 0);
[self createFakeOutgoingMedia:index
messageState:messageState
hasCaption:hasCaption
fakeAssetLoader:fakeAssetLoader
thread:thread
transaction:transaction];
}
prepareBlock:fakeAssetLoader.prepareBlock];
}
+ (void)createFakeOutgoingMedia:(NSUInteger)index
@ -1168,18 +1166,17 @@ NS_ASSUME_NONNULL_BEGIN
label = [label stringByAppendingString:@" 👍"];
}
return
[DebugUIMessagesSingleAction actionWithLabel:label
unstaggeredActionBlock:^(NSUInteger index, SDSAnyWriteTransaction *transaction) {
OWSAssertDebug(fakeAssetLoader.filePath.length > 0);
[self createFakeIncomingMedia:index
isAttachmentDownloaded:isAttachmentDownloaded
hasCaption:hasCaption
fakeAssetLoader:fakeAssetLoader
thread:thread
transaction:transaction];
}
prepareBlock:fakeAssetLoader.prepareBlock];
return [DebugUIMessagesSingleAction actionWithLabel:label
unstaggeredActionBlock:^(NSUInteger index, SDSAnyWriteTransaction *transaction) {
OWSAssertDebug(fakeAssetLoader.filePath.length > 0);
[self createFakeIncomingMedia:index
isAttachmentDownloaded:isAttachmentDownloaded
hasCaption:hasCaption
fakeAssetLoader:fakeAssetLoader
thread:thread
transaction:transaction];
}
prepareBlock:fakeAssetLoader.prepareBlock];
}
+ (TSIncomingMessage *)createFakeIncomingMedia:(NSUInteger)index
@ -1509,8 +1506,8 @@ NS_ASSUME_NONNULL_BEGIN
[self fakeIncomingMp4Action:thread isAttachmentDownloaded:YES hasCaption:YES],
]];
if (includeLabels) {
[actions
addObject:[self fakeIncomingTextMessageAction:thread text:@"⚠️ Incoming Compact Landscape Png ⚠️"]];
[actions addObject:[self fakeIncomingTextMessageAction:thread
text:@"⚠️ Incoming Compact Landscape Png ⚠️"]];
}
[actions addObjectsFromArray:@[
[self fakeIncomingCompactLandscapePngAction:thread isAttachmentDownloaded:NO hasCaption:NO],
@ -1519,8 +1516,8 @@ NS_ASSUME_NONNULL_BEGIN
[self fakeIncomingCompactLandscapePngAction:thread isAttachmentDownloaded:YES hasCaption:YES],
]];
if (includeLabels) {
[actions
addObject:[self fakeIncomingTextMessageAction:thread text:@"⚠️ Incoming Compact Portrait Png ⚠️"]];
[actions addObject:[self fakeIncomingTextMessageAction:thread
text:@"⚠️ Incoming Compact Portrait Png ⚠️"]];
}
[actions addObjectsFromArray:@[
[self fakeIncomingCompactPortraitPngAction:thread isAttachmentDownloaded:NO hasCaption:NO],
@ -1529,8 +1526,8 @@ NS_ASSUME_NONNULL_BEGIN
[self fakeIncomingCompactPortraitPngAction:thread isAttachmentDownloaded:YES hasCaption:YES],
]];
if (includeLabels) {
[actions
addObject:[self fakeIncomingTextMessageAction:thread text:@"⚠️ Incoming Wide Landscape Png ⚠️"]];
[actions addObject:[self fakeIncomingTextMessageAction:thread
text:@"⚠️ Incoming Wide Landscape Png ⚠️"]];
}
[actions addObjectsFromArray:@[
[self fakeIncomingWideLandscapePngAction:thread isAttachmentDownloaded:NO hasCaption:NO],
@ -1539,8 +1536,8 @@ NS_ASSUME_NONNULL_BEGIN
[self fakeIncomingWideLandscapePngAction:thread isAttachmentDownloaded:YES hasCaption:YES],
]];
if (includeLabels) {
[actions
addObject:[self fakeIncomingTextMessageAction:thread text:@"⚠️ Incoming Tall Portrait Png ⚠️"]];
[actions addObject:[self fakeIncomingTextMessageAction:thread
text:@"⚠️ Incoming Tall Portrait Png ⚠️"]];
}
[actions addObjectsFromArray:@[
[self fakeIncomingTallPortraitPngAction:thread isAttachmentDownloaded:NO hasCaption:NO],
@ -1563,8 +1560,8 @@ NS_ASSUME_NONNULL_BEGIN
[self fakeIncomingTinyPngAction:thread isAttachmentDownloaded:YES hasCaption:YES],
]];
if (includeLabels) {
[actions
addObject:[self fakeIncomingTextMessageAction:thread text:@"⚠️ Incoming Reserved Color Png ⚠️"]];
[actions addObject:[self fakeIncomingTextMessageAction:thread
text:@"⚠️ Incoming Reserved Color Png ⚠️"]];
}
[actions addObjectsFromArray:@[
[self fakeIncomingPngAction:thread
@ -1721,18 +1718,17 @@ NS_ASSUME_NONNULL_BEGIN
{
OWSAssertDebug(thread);
return [DebugUIMessagesSingleAction
actionWithLabel:@"Fake Short Incoming Text Message"
unstaggeredActionBlock:^(NSUInteger index, SDSAnyWriteTransaction *transaction) {
NSString *messageBody =
[[@(index).stringValue stringByAppendingString:@" "] stringByAppendingString:[self randomText]];
[self createFakeIncomingMessage:thread
messageBody:messageBody
fakeAssetLoader:nil
isAttachmentDownloaded:NO
quotedMessage:nil
transaction:transaction];
}];
return [DebugUIMessagesSingleAction actionWithLabel:@"Fake Short Incoming Text Message"
unstaggeredActionBlock:^(NSUInteger index, SDSAnyWriteTransaction *transaction) {
NSString *messageBody = [[@(index).stringValue stringByAppendingString:@" "]
stringByAppendingString:[self randomText]];
[self createFakeIncomingMessage:thread
messageBody:messageBody
fakeAssetLoader:nil
isAttachmentDownloaded:NO
quotedMessage:nil
transaction:transaction];
}];
}
+ (SignalAttachment *)signalAttachmentForFilePath:(NSString *)filePath
@ -1747,8 +1743,9 @@ NS_ASSUME_NONNULL_BEGIN
error:&error];
OWSAssertDebug(dataSource != nil);
[dataSource setSourceFilename:filename];
SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType imageQuality:TSImageQualityOriginal];
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource
dataUTI:utiType
imageQuality:TSImageQualityOriginal];
if (arc4random_uniform(100) > 50) {
attachment.captionText = [self randomCaptionText];
}
@ -1946,19 +1943,19 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Fake Quoted Replies
+ (DebugUIMessagesAction *)
fakeQuotedReplyAction:(TSThread *)thread
quotedMessageLabel:(NSString *)quotedMessageLabel
isQuotedMessageIncoming:(BOOL)isQuotedMessageIncoming
// Optional. At least one of quotedMessageBody and quotedMessageAssetLoader should be non-nil.
quotedMessageBody:(nullable NSString *)quotedMessageBody
fakeQuotedReplyAction:(TSThread *)thread
quotedMessageLabel:(NSString *)quotedMessageLabel
isQuotedMessageIncoming:(BOOL)isQuotedMessageIncoming
// Optional. At least one of quotedMessageBody and quotedMessageAssetLoader should be non-nil.
quotedMessageAssetLoader:(nullable DebugUIMessagesAssetLoader *)quotedMessageAssetLoader
replyLabel:(NSString *)replyLabel
isReplyIncoming:(BOOL)isReplyIncoming
replyMessageBody:(nullable NSString *)replyMessageBody
replyAssetLoader:(nullable DebugUIMessagesAssetLoader *)replyAssetLoader
// Only applies if !isReplyIncoming.
replyMessageState:(TSOutgoingMessageState)replyMessageState
quotedMessageBody:(nullable NSString *)quotedMessageBody
// Optional. At least one of quotedMessageBody and quotedMessageAssetLoader should be non-nil.
quotedMessageAssetLoader:(nullable DebugUIMessagesAssetLoader *)quotedMessageAssetLoader
replyLabel:(NSString *)replyLabel
isReplyIncoming:(BOOL)isReplyIncoming
replyMessageBody:(nullable NSString *)replyMessageBody
replyAssetLoader:(nullable DebugUIMessagesAssetLoader *)replyAssetLoader
// Only applies if !isReplyIncoming.
replyMessageState:(TSOutgoingMessageState)replyMessageState
{
OWSAssertDebug(thread);
@ -2039,8 +2036,8 @@ NS_ASSUME_NONNULL_BEGIN
thread:thread
transaction:transaction
conversationStyle:conversationStyle];
quotedMessage = [
[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem transaction:transaction]
quotedMessage = [[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem
transaction:transaction]
buildQuotedMessageForSending];
} else {
TSOutgoingMessage *_Nullable messageToQuote = [self createFakeOutgoingMessage:thread
@ -2061,8 +2058,8 @@ NS_ASSUME_NONNULL_BEGIN
thread:thread
transaction:transaction
conversationStyle:conversationStyle];
quotedMessage = [
[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem transaction:transaction]
quotedMessage = [[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem
transaction:transaction]
buildQuotedMessageForSending];
}
OWSAssertDebug(quotedMessage);
@ -2710,9 +2707,9 @@ NS_ASSUME_NONNULL_BEGIN
{
OWSAssertDebug(thread);
return
[DebugUIMessagesGroupAction allGroupActionWithLabel:@"All Quoted Reply"
subactions:[self allFakeQuotedReplyActions:thread includeLabels:YES]];
return [DebugUIMessagesGroupAction allGroupActionWithLabel:@"All Quoted Reply"
subactions:[self allFakeQuotedReplyActions:thread
includeLabels:YES]];
}
+ (void)selectQuotedReplyAction:(TSThread *)thread
@ -2727,9 +2724,9 @@ NS_ASSUME_NONNULL_BEGIN
{
OWSAssertDebug(thread);
return [DebugUIMessagesGroupAction
randomGroupActionWithLabel:@"Random Quoted Reply"
subactions:[self allFakeQuotedReplyActions:thread includeLabels:NO]];
return [DebugUIMessagesGroupAction randomGroupActionWithLabel:@"Random Quoted Reply"
subactions:[self allFakeQuotedReplyActions:thread
includeLabels:NO]];
}
#pragma mark - Exemplary
@ -2797,8 +2794,9 @@ NS_ASSUME_NONNULL_BEGIN
}
[actions addObject:[self fakeIncomingTextMessageAction:thread text:@"Incoming"]];
[actions
addObject:[self fakeOutgoingTextMessageAction:thread messageState:TSOutgoingMessageStateSent text:@"Outgoing"]];
[actions addObject:[self fakeOutgoingTextMessageAction:thread
messageState:TSOutgoingMessageStateSent
text:@"Outgoing"]];
[actions addObject:[self fakeIncomingTextMessageAction:thread text:@"Incoming 1"]];
[actions addObject:[self fakeIncomingTextMessageAction:thread text:@"Incoming 2"]];
[actions addObject:[self fakeIncomingTextMessageAction:thread text:@"Incoming 3"]];
@ -2855,12 +2853,12 @@ NS_ASSUME_NONNULL_BEGIN
[actions addObject:[self fakeOutgoingTextMessageAction:thread
messageState:TSOutgoingMessageStateSent
text:[@"Outgoing" stringByAppendingString:longText]]];
[actions
addObject:[self fakeIncomingTextMessageAction:thread text:[@"Incoming 1" stringByAppendingString:longText]]];
[actions
addObject:[self fakeIncomingTextMessageAction:thread text:[@"Incoming 2" stringByAppendingString:longText]]];
[actions
addObject:[self fakeIncomingTextMessageAction:thread text:[@"Incoming 3" stringByAppendingString:longText]]];
[actions addObject:[self fakeIncomingTextMessageAction:thread
text:[@"Incoming 1" stringByAppendingString:longText]]];
[actions addObject:[self fakeIncomingTextMessageAction:thread
text:[@"Incoming 2" stringByAppendingString:longText]]];
[actions addObject:[self fakeIncomingTextMessageAction:thread
text:[@"Incoming 3" stringByAppendingString:longText]]];
[actions addObject:[self fakeOutgoingTextMessageAction:thread
messageState:TSOutgoingMessageStateFailed
text:[@"Outgoing Unsent 1" stringByAppendingString:longText]]];
@ -2955,16 +2953,20 @@ NS_ASSUME_NONNULL_BEGIN
text:@"⚠️ Back-Dated ⚠️"]];
}
[actions
addObject:[self fakeBackDatedMessageAction:thread label:@"One Minute Ago" dateOffset:-(int64_t)kMinuteInMs]];
[actions addObject:[self fakeBackDatedMessageAction:thread
label:@"One Minute Ago"
dateOffset:-(int64_t)kMinuteInMs]];
[actions addObject:[self fakeBackDatedMessageAction:thread label:@"One Hour Ago" dateOffset:-(int64_t)kHourInMs]];
[actions addObject:[self fakeBackDatedMessageAction:thread label:@"One Day Ago" dateOffset:-(int64_t)kDayInMs]];
[actions
addObject:[self fakeBackDatedMessageAction:thread label:@"Two Days Ago" dateOffset:-(int64_t)kDayInMs * 2]];
[actions
addObject:[self fakeBackDatedMessageAction:thread label:@"Ten Days Ago" dateOffset:-(int64_t)kDayInMs * 10]];
[actions
addObject:[self fakeBackDatedMessageAction:thread label:@"400 Days Ago" dateOffset:-(int64_t)kDayInMs * 400]];
[actions addObject:[self fakeBackDatedMessageAction:thread
label:@"Two Days Ago"
dateOffset:-(int64_t)kDayInMs * 2]];
[actions addObject:[self fakeBackDatedMessageAction:thread
label:@"Ten Days Ago"
dateOffset:-(int64_t)kDayInMs * 10]];
[actions addObject:[self fakeBackDatedMessageAction:thread
label:@"400 Days Ago"
dateOffset:-(int64_t)kDayInMs * 400]];
return actions;
}
@ -2995,11 +2997,11 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
{
OWSAssertDebug(thread);
return [DebugUIMessagesSingleAction
actionWithLabel:[NSString stringWithFormat:@"Fake Contact Share (%@)", label]
unstaggeredActionBlock:^(NSUInteger index, SDSAnyWriteTransaction *transaction) {
OWSContact *contact = contactBlock(transaction);
TSOutgoingMessage *message = [self createFakeOutgoingMessage:thread
return [DebugUIMessagesSingleAction actionWithLabel:[NSString stringWithFormat:@"Fake Contact Share (%@)", label]
unstaggeredActionBlock:^(NSUInteger index, SDSAnyWriteTransaction *transaction) {
OWSContact *contact = contactBlock(transaction);
TSOutgoingMessage *message =
[self createFakeOutgoingMessage:thread
messageBody:nil
fakeAssetLoader:nil
messageState:TSOutgoingMessageStateSent
@ -3010,8 +3012,8 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
linkPreview:nil
messageSticker:nil
transaction:transaction];
[message anyInsertWithTransaction:transaction];
}];
[message anyInsertWithTransaction:transaction];
}];
}
+ (NSArray<DebugUIMessagesAction *> *)allFakeContactShareActions:(TSThread *)thread includeLabels:(BOOL)includeLabels
@ -3172,9 +3174,9 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
{
OWSAssertDebug(thread);
return
[DebugUIMessagesGroupAction allGroupActionWithLabel:@"All Fake Contact Shares"
subactions:[self allFakeContactShareActions:thread includeLabels:YES]];
return [DebugUIMessagesGroupAction allGroupActionWithLabel:@"All Fake Contact Shares"
subactions:[self allFakeContactShareActions:thread
includeLabels:YES]];
}
@ -3354,8 +3356,8 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
+ (void)sendAllContacts:(TSThread *)thread
{
NSArray<DebugUIMessagesAction *> *subactions = [self allSendContactShareActions:thread includeLabels:NO];
DebugUIMessagesAction *action =
[DebugUIMessagesGroupAction allGroupActionWithLabel:@"Send All Contact Shares" subactions:subactions];
DebugUIMessagesAction *action = [DebugUIMessagesGroupAction allGroupActionWithLabel:@"Send All Contact Shares"
subactions:subactions];
[action prepareAndPerformNTimes:subactions.count];
}
@ -3405,10 +3407,11 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
+ (void)sendRandomAttachment:(TSThread *)thread uti:(NSString *)uti length:(NSUInteger)length
{
_Nullable id<DataSource> dataSource =
[DataSourceValue dataSourceWithData:[self createRandomNSDataOfSize:length] utiType:uti];
SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:uti imageQuality:TSImageQualityOriginal];
_Nullable id<DataSource> dataSource = [DataSourceValue dataSourceWithData:[self createRandomNSDataOfSize:length]
utiType:uti];
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource
dataUTI:uti
imageQuality:TSImageQualityOriginal];
if (arc4random_uniform(100) > 50) {
// give 1/2 our attachments captions, and add a hint that it's a caption since we
@ -3694,15 +3697,16 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
@"one that comes after it."),
@"War against a foreign country only happens when the moneyed classes think they are going to profit from it.",
@"People have only as much liberty as they have the intelligence to want and the courage to take.",
(@"You cannot buy the revolution. You cannot make the revolution. You can only be the revolution. It is in your "
@"spirit, or it is nowhere."),
(@"You cannot buy the revolution. You cannot make the revolution. You can only be the revolution. It is in "
@"your "
@"spirit, or it is nowhere."),
(@"That is what I have always understood to be the essence of anarchism: the conviction that the burden of "
@"proof has to be placed on authority, and that it should be dismantled if that burden cannot be met."),
@"proof has to be placed on authority, and that it should be dismantled if that burden cannot be met."),
(@"Ask for work. If they don't give you work, ask for bread. If they do not give you work or bread, then take "
@"bread."),
@"bread."),
@"Every society has the criminals it deserves.",
(@"Anarchism is founded on the observation that since few men are wise enough to rule themselves, even fewer "
@"are wise enough to rule others."),
@"are wise enough to rule others."),
@"If you would know who controls you see who you may not criticise.",
@"At one time in the world there were woods that no one owned."
];
@ -3878,8 +3882,8 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
ConversationFactory *conversationFactory = [ConversationFactory new];
// We want to produce a variety of album sizes, but favoring smaller albums
conversationFactory.attachmentCount = MAX(0,
MIN(SignalAttachment.maxAttachmentsAllowed,
((NSInteger)((double)UINT32_MAX/(double)arc4random()) - 1)));
MIN(SignalAttachment.maxAttachmentsAllowed,
((NSInteger)((double)UINT32_MAX / (double)arc4random()) - 1)));
conversationFactory.threadCreator = ^(SDSAnyWriteTransaction *_transaction){
return thread;
};
@ -3992,14 +3996,12 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
+ (void)performRandomActions:(NSUInteger)counter thread:(TSThread *)thread
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.f * NSEC_PER_SEC)),
dispatch_get_main_queue(),
^{
[self performRandomActionInThread:thread counter:counter];
if (counter > 0) {
[self performRandomActions:counter - 1 thread:thread];
}
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self performRandomActionInThread:thread counter:counter];
if (counter > 0) {
[self performRandomActions:counter - 1 thread:thread];
}
});
}
+ (void)performRandomActionInThread:(TSThread *)thread counter:(NSUInteger)counter
@ -4075,8 +4077,8 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
OWSFailDebug(@"error: %@", error);
}
for (NSString *interactionId in interactionIds) {
TSInteraction *_Nullable interaction =
[TSInteraction anyFetchWithUniqueId:interactionId transaction:transaction];
TSInteraction *_Nullable interaction = [TSInteraction anyFetchWithUniqueId:interactionId
transaction:transaction];
if (interaction == nil) {
OWSFailDebug(@"Couldn't load interaction.");
continue;
@ -4112,8 +4114,8 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
NSString *interactionId = interactionIds[idx];
[interactionIds removeObjectAtIndex:idx];
TSInteraction *_Nullable interaction =
[TSInteraction anyFetchWithUniqueId:interactionId transaction:transaction];
TSInteraction *_Nullable interaction = [TSInteraction anyFetchWithUniqueId:interactionId
transaction:transaction];
if (interaction == nil) {
OWSFailDebug(@"Couldn't load interaction.");
continue;
@ -4373,7 +4375,7 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
member,
TSAccountManager.localAddress,
];
[GroupManager createNewGroupObjcWithMembers:members
[GroupManager localCreateNewGroupObjcWithMembers:members
groupId:nil
name:groupName
avatarData:nil
@ -4424,27 +4426,26 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
@"This is some normal text",
];
[self
writeWithBlock:^(SDSAnyWriteTransaction *transaction) {
for (NSString *string in strings) {
OWSLogInfo(@"sending zalgo");
[self writeWithBlock:^(SDSAnyWriteTransaction *transaction) {
for (NSString *string in strings) {
OWSLogInfo(@"sending zalgo");
[self createFakeIncomingMessage:thread
messageBody:string
fakeAssetLoader:nil
isAttachmentDownloaded:NO
quotedMessage:nil
transaction:transaction];
[self createFakeIncomingMessage:thread
messageBody:string
fakeAssetLoader:nil
isAttachmentDownloaded:NO
quotedMessage:nil
transaction:transaction];
SignalServiceAddress *member = [[SignalServiceAddress alloc] initWithPhoneNumber:@"+1323555555"];
[self createRandomGroupWithName:string
member:member
success:^(TSGroupThread *thread) {
// Do nothing.
}];
}
}];
SignalServiceAddress *member = [[SignalServiceAddress alloc] initWithPhoneNumber:@"+1323555555"];
[self createRandomGroupWithName:string
member:member
success:^(TSGroupThread *thread) {
// Do nothing.
}];
}
}];
}
+ (void)testDirectionalFilenamesInThread:(TSThread *)thread
@ -4466,8 +4467,9 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
_Nullable id<DataSource> dataSource =
[DataSourceValue dataSourceWithData:[self createRandomNSDataOfSize:kDataLength] utiType:utiType];
[dataSource setSourceFilename:filename];
SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:utiType imageQuality:TSImageQualityOriginal];
SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource
dataUTI:utiType
imageQuality:TSImageQualityOriginal];
OWSAssertDebug(attachment);
if ([attachment hasError]) {
@ -4704,10 +4706,9 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
if (isAttachmentDownloaded) {
NSError *error;
id<DataSource>dataSource =
[DataSourcePath dataSourceWithFilePath:fakeAssetLoader.filePath
shouldDeleteOnDeallocation:NO
error:&error];
id<DataSource> dataSource = [DataSourcePath dataSourceWithFilePath:fakeAssetLoader.filePath
shouldDeleteOnDeallocation:NO
error:&error];
OWSAssertDebug(error == nil);
NSString *filename = dataSource.sourceFilename;
// To support "fake missing" attachments, we sometimes lie about the
@ -4786,10 +4787,9 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
= fakeAssetLoaders[arc4random_uniform((uint32_t)fakeAssetLoaders.count)];
OWSAssertDebug([NSFileManager.defaultManager fileExistsAtPath:fakeAssetLoader.filePath]);
NSError *error;
id<DataSource>dataSource =
[DataSourcePath dataSourceWithFilePath:fakeAssetLoader.filePath
shouldDeleteOnDeallocation:NO
error:&error];
id<DataSource> dataSource = [DataSourcePath dataSourceWithFilePath:fakeAssetLoader.filePath
shouldDeleteOnDeallocation:NO
error:&error];
OWSAssertDebug(error == nil);
SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource

View File

@ -60,9 +60,10 @@ NS_ASSUME_NONNULL_BEGIN
[items addObject:[OWSTableItem itemWithTitle:@"Send empty message"
actionBlock:^{
[DebugUIStress sendStressMessage:thread block:^(SignalRecipient *recipient) {
return [NSData new];
}];
[DebugUIStress sendStressMessage:thread
block:^(SignalRecipient *recipient) {
return [NSData new];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send random noise message"
actionBlock:^{
@ -147,88 +148,82 @@ NS_ASSUME_NONNULL_BEGIN
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send whitespace text data message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContent builder];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessage builder];
dataBuilder.body = @" ";
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder
thread:thread];
contentBuilder.dataMessage =
[dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem
itemWithTitle:@"Send whitespace text data message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContent builder];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessage builder];
dataBuilder.body = @" ";
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem
itemWithTitle:@"Send bad attachment data message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContent builder];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessage builder];
SSKProtoAttachmentPointerBuilder *attachmentPointer =
[SSKProtoAttachmentPointer
builderWithId:arc4random_uniform(32) + 1];
[attachmentPointer setContentType:@"1"];
[attachmentPointer setSize:arc4random_uniform(32) + 1];
[attachmentPointer setDigest:[Cryptography generateRandomBytes:1]];
[attachmentPointer setFileName:@" "];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem
itemWithTitle:@"Send normal text data message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContent builder];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessage builder];
dataBuilder.body = @"alice";
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items
addObject:[OWSTableItem
itemWithTitle:@"Send bad attachment data message"
itemWithTitle:@"Send N text messages with same timestamp"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContent builder];
SSKProtoDataMessageBuilder *dataBuilder = [SSKProtoDataMessage builder];
SSKProtoAttachmentPointerBuilder *attachmentPointer =
[SSKProtoAttachmentPointer
builderWithId:arc4random_uniform(32) + 1];
[attachmentPointer setContentType:@"1"];
[attachmentPointer setSize:arc4random_uniform(32) + 1];
[attachmentPointer setDigest:[Cryptography generateRandomBytes:1]];
[attachmentPointer setFileName:@" "];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return
[[contentBuilder buildIgnoringErrors] serializedDataIgnoringErrors];
}];
uint64_t timestamp = [NSDate ows_millisecondTimeStamp];
for (int i = 0; i < 3; i++) {
[DebugUIStress
sendStressMessage:thread
timestamp:timestamp
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder = [SSKProtoContent builder];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessage builder];
dataBuilder.body = [NSString
stringWithFormat:@"%@ %d", [NSUUID UUID].UUIDString, i];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder thread:thread];
contentBuilder.dataMessage = [dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send normal text data message"
actionBlock:^{
[DebugUIStress
sendStressMessage:thread
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContent builder];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessage builder];
dataBuilder.body = @"alice";
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder
thread:thread];
contentBuilder.dataMessage =
[dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Send N text messages with same timestamp"
actionBlock:^{
uint64_t timestamp = [NSDate ows_millisecondTimeStamp];
for (int i = 0; i < 3; i++) {
[DebugUIStress
sendStressMessage:thread
timestamp:timestamp
block:^(SignalRecipient *recipient) {
SSKProtoContentBuilder *contentBuilder =
[SSKProtoContent builder];
SSKProtoDataMessageBuilder *dataBuilder =
[SSKProtoDataMessage builder];
dataBuilder.body = [NSString stringWithFormat:@"%@ %d",
[NSUUID UUID].UUIDString,
i];
[DebugUIStress ensureGroupOfDataBuilder:dataBuilder
thread:thread];
contentBuilder.dataMessage =
[dataBuilder buildIgnoringErrors];
return [[contentBuilder buildIgnoringErrors]
serializedDataIgnoringErrors];
}];
}
}]];
[items addObject:[OWSTableItem
itemWithTitle:@"Send text message with current timestamp"
actionBlock:^{
@ -496,8 +491,8 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssertDebug(thread);
OWSAssertDebug(block);
OWSDynamicOutgoingMessage *message =
[[OWSDynamicOutgoingMessage alloc] initWithPlainTextDataBlock:block thread:thread];
OWSDynamicOutgoingMessage *message = [[OWSDynamicOutgoingMessage alloc] initWithPlainTextDataBlock:block
thread:thread];
[self sendStressMessage:message];
}
@ -507,8 +502,9 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssertDebug(thread);
OWSAssertDebug(block);
OWSDynamicOutgoingMessage *message =
[[OWSDynamicOutgoingMessage alloc] initWithPlainTextDataBlock:block timestamp:timestamp thread:thread];
OWSDynamicOutgoingMessage *message = [[OWSDynamicOutgoingMessage alloc] initWithPlainTextDataBlock:block
timestamp:timestamp
thread:thread];
[self sendStressMessage:message];
}
@ -518,7 +514,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)hallucinateTwinGroup:(TSGroupThread *)groupThread
{
NSString *groupName = [groupThread.groupModel.groupName stringByAppendingString:@" Copy"];
[GroupManager createNewGroupObjcWithMembers:groupThread.groupModel.groupMembers
[GroupManager localCreateNewGroupObjcWithMembers:groupThread.groupModel.groupMembers
groupId:nil
name:groupName
avatarData:groupThread.groupModel.groupAvatarData
@ -552,7 +548,7 @@ NS_ASSUME_NONNULL_BEGIN
}
}
[GroupManager createNewGroupObjcWithMembers:recipientAddresses
[GroupManager localCreateNewGroupObjcWithMembers:recipientAddresses
groupId:nil
name:NSUUID.UUID.UUIDString
avatarData:nil

View File

@ -300,7 +300,7 @@ NS_ASSUME_NONNULL_BEGIN
presentFromViewController:self
canCancel:NO
backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) {
[GroupManager createNewGroupObjcWithMembers:members
[GroupManager localCreateNewGroupObjcWithMembers:members
groupId:nil
name:groupName
avatarImage:self.groupAvatar

View File

@ -3,6 +3,7 @@
//
import Foundation
import PromiseKit
@objc
public extension UpdateGroupViewController {
@ -66,15 +67,16 @@ public extension UpdateGroupViewController {
// GroupsV2 TODO: Skip change where the user didn't change anything.
// dmConfiguration: nil means don't change disappearing messages configuration.
GroupManager.updateExistingGroup(groupId: groupId,
name: newTitle,
avatarData: newAvatarData,
groupMembership: groupMembership,
groupAccess: groupAccess,
groupsVersion: groupsVersion,
dmConfiguration: nil,
groupUpdateSourceAddress: localAddress)
.done(on: .global()) { groupThread in
firstly {
GroupManager.localUpdateExistingGroup(groupId: groupId,
name: newTitle,
avatarData: newAvatarData,
groupMembership: groupMembership,
groupAccess: groupAccess,
groupsVersion: groupsVersion,
dmConfiguration: nil,
groupUpdateSourceAddress: localAddress)
}.done(on: .global()) { groupThread in
success(groupThread)
}.catch(on: .global()) { (error) in
switch error {

View File

@ -201,12 +201,12 @@ public class IncomingGroupSyncOperation: OWSOperation, DurableOperation {
// who made any changes.
let groupUpdateSourceAddress: SignalServiceAddress? = nil
// We only sync v1 groups via group sync messages.
let result = try GroupManager.upsertExistingGroupV1(groupId: groupId,
name: groupDetails.name,
avatarData: groupDetails.avatarData,
members: groupDetails.memberAddresses,
groupUpdateSourceAddress: groupUpdateSourceAddress,
transaction: transaction)
let result = try GroupManager.remoteUpsertExistingGroupV1(groupId: groupId,
name: groupDetails.name,
avatarData: groupDetails.avatarData,
members: groupDetails.memberAddresses,
groupUpdateSourceAddress: groupUpdateSourceAddress,
transaction: transaction)
let groupThread = result.groupThread
let groupModel = groupThread.groupModel

View File

@ -32,11 +32,7 @@ class GroupsV2ProfileKeyUpdater {
return OWSProfileManager.shared()
}
private var groupsV2: GroupsV2 {
return SSKEnvironment.shared.groupsV2
}
private var groupsV2Swift: GroupsV2Swift {
private var groupsV2: GroupsV2Swift {
return SSKEnvironment.shared.groupsV2 as! GroupsV2Swift
}
@ -223,7 +219,7 @@ class GroupsV2ProfileKeyUpdater {
}.then(on: .global()) { (groupThread: TSGroupThread) throws -> Promise<TSGroupThread> in
// Get latest group state from service and verify that this update is still necessary.
return firstly {
self.groupsV2Swift.fetchCurrentGroupV2Snapshot(groupModel: groupThread.groupModel)
self.groupsV2.fetchCurrentGroupV2Snapshot(groupModel: groupThread.groupModel)
}.map(on: .global()) { (groupV2Snapshot: GroupV2Snapshot) throws -> TSGroupThread in
guard groupV2Snapshot.groupMembership.isNonPendingMember(localAddress) else {
// We're not a full member, no need to update profile key.
@ -249,7 +245,7 @@ class GroupsV2ProfileKeyUpdater {
changeSet.setShouldUpdateLocalProfileKey()
return changeSet
}.then(on: DispatchQueue.global()) { (changeSet: GroupsV2ChangeSet) -> Promise<TSGroupThread> in
return self.groupsV2Swift.updateExistingGroupOnService(changeSet: changeSet)
return self.groupsV2.updateExistingGroupOnService(changeSet: changeSet)
}.asVoid()
}
}

View File

@ -18,12 +18,8 @@ public class GroupsV2Test: NSObject {
return TSAccountManager.sharedInstance()
}
private class var groupsV2: GroupsV2 {
return SSKEnvironment.shared.groupsV2
}
private class var groupsV2Swift: GroupsV2Swift {
return self.groupsV2 as! GroupsV2Swift
private class var groupsV2: GroupsV2Swift {
return SSKEnvironment.shared.groupsV2 as! GroupsV2Swift
}
private class var databaseStorage: SDSDatabaseStorage {
@ -65,7 +61,7 @@ public class GroupsV2Test: NSObject {
let localAddressSet = Set([SignalServiceAddress(uuid: localUuid)])
Logger.verbose("otherAddresses: \(otherAddresses)")
firstly {
GroupManager.createNewGroup(members: members,
GroupManager.localCreateNewGroup(members: members,
name: title0,
shouldSendMessage: true)
}.then(on: .global()) { (groupThread: TSGroupThread) -> Promise<(Data, GroupV2Snapshot)> in
@ -73,12 +69,11 @@ public class GroupsV2Test: NSObject {
guard groupModel.groupsVersion == .V2 else {
throw OWSAssertionError("Not a V2 group.")
}
return self.groupsV2Swift.fetchCurrentGroupV2Snapshot(groupModel: groupModel)
return self.groupsV2.fetchCurrentGroupV2Snapshot(groupModel: groupModel)
.map(on: .global()) { (groupV2Snapshot: GroupV2Snapshot) -> (Data, GroupV2Snapshot) in
return (groupThread.groupModel.groupId, groupV2Snapshot)
}
}.map(on: .global()) { (groupId: Data, groupV2Snapshot: GroupV2Snapshot) throws -> Data in
let groupModel = try self.databaseStorage.read { transaction in
return try GroupManager.buildGroupModel(groupV2Snapshot: groupV2Snapshot, transaction: transaction)
}
@ -134,22 +129,21 @@ public class GroupsV2Test: NSObject {
let groupAccess = groupModel.groupAccess
// GroupsV2 TODO: Add and remove members, change avatar, etc.
return GroupManager.updateExistingGroup(groupId: groupId,
name: title1,
avatarData: nil,
groupMembership: groupMembership,
groupAccess: groupAccess,
groupsVersion: groupModel.groupsVersion,
dmConfiguration: dmConfiguration,
groupUpdateSourceAddress: localAddress)
return GroupManager.localUpdateExistingGroup(groupId: groupId,
name: title1,
avatarData: nil,
groupMembership: groupMembership,
groupAccess: groupAccess,
groupsVersion: groupModel.groupsVersion,
dmConfiguration: dmConfiguration,
groupUpdateSourceAddress: localAddress)
.then(on: .global()) { (groupThread) -> Promise<GroupV2Snapshot> in
// GroupsV2 TODO: This should reflect the new group.
return groupsV2Swift.fetchCurrentGroupV2Snapshot(groupModel: groupThread.groupModel)
return groupsV2.fetchCurrentGroupV2Snapshot(groupModel: groupThread.groupModel)
}.map(on: .global()) { (groupV2Snapshot: GroupV2Snapshot) -> (Data, GroupV2Snapshot) in
return (groupId, groupV2Snapshot)
}
}.map(on: .global()) { (groupId: Data, groupV2Snapshot: GroupV2Snapshot) throws -> Data in
let groupModel = try self.databaseStorage.read { transaction in
return try GroupManager.buildGroupModel(groupV2Snapshot: groupV2Snapshot, transaction: transaction)
}
@ -205,22 +199,21 @@ public class GroupsV2Test: NSObject {
let groupAccess = groupModel.groupAccess
// GroupsV2 TODO: Add and remove members, change avatar, etc.
return GroupManager.updateExistingGroup(groupId: groupId,
name: title1,
avatarData: nil,
groupMembership: groupMembership,
groupAccess: groupAccess,
groupsVersion: groupModel.groupsVersion,
dmConfiguration: dmConfiguration,
groupUpdateSourceAddress: localAddress)
return GroupManager.localUpdateExistingGroup(groupId: groupId,
name: title1,
avatarData: nil,
groupMembership: groupMembership,
groupAccess: groupAccess,
groupsVersion: groupModel.groupsVersion,
dmConfiguration: dmConfiguration,
groupUpdateSourceAddress: localAddress)
.then(on: .global()) { (_) -> Promise<GroupV2Snapshot> in
// GroupsV2 TODO: This should reflect the new group.
return groupsV2Swift.fetchCurrentGroupV2Snapshot(groupModel: groupModel)
return groupsV2.fetchCurrentGroupV2Snapshot(groupModel: groupModel)
}.map(on: .global()) { (groupV2Snapshot: GroupV2Snapshot) -> (Data, GroupV2Snapshot) in
return (groupId, groupV2Snapshot)
}
}.map(on: .global()) { (groupId: Data, groupV2Snapshot: GroupV2Snapshot) throws -> Data in
let groupModel = try self.databaseStorage.read { transaction in
return try GroupManager.buildGroupModel(groupV2Snapshot: groupV2Snapshot, transaction: transaction)
}

View File

@ -148,13 +148,13 @@ NS_ASSUME_NONNULL_BEGIN
}
NSArray<SignalServiceAddress *> *members = @[ localAddress ];
NSError *_Nullable groupError;
_thread = [GroupManager upsertExistingGroupV1WithGroupId:_groupId
name:groupContextV1.name
avatarData:nil
members:members
groupUpdateSourceAddress:localAddress
transaction:transaction
error:&groupError]
_thread = [GroupManager remoteUpsertExistingGroupV1WithGroupId:_groupId
name:groupContextV1.name
avatarData:nil
members:members
groupUpdateSourceAddress:localAddress
transaction:transaction
error:&groupError]
.groupThread;
if (groupError != nil || _thread == nil) {
OWSFailDebug(@"Could not create group: %@", groupError);
@ -192,8 +192,9 @@ NS_ASSUME_NONNULL_BEGIN
_thread = [TSContactThread getOrCreateThreadWithContactAddress:_recipientAddress transaction:transaction];
}
_quotedMessage =
[TSQuotedMessage quotedMessageForDataMessage:_dataMessage thread:_thread transaction:transaction];
_quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:_dataMessage
thread:_thread
transaction:transaction];
_contact = [OWSContacts contactForDataMessage:_dataMessage transaction:transaction];
NSError *linkPreviewError;

View File

@ -1049,13 +1049,13 @@ NS_ASSUME_NONNULL_BEGIN
// Ensures that the thread exists but doesn't update it.
NSError *_Nullable error;
UpsertGroupResult *_Nullable result =
[GroupManager upsertExistingGroupV1WithGroupId:groupId
name:groupContext.name
avatarData:oldGroupThread.groupModel.groupAvatarData
members:newMembers.allObjects
groupUpdateSourceAddress:groupUpdateSourceAddress
transaction:transaction
error:&error];
[GroupManager remoteUpsertExistingGroupV1WithGroupId:groupId
name:groupContext.name
avatarData:oldGroupThread.groupModel.groupAvatarData
members:newMembers.allObjects
groupUpdateSourceAddress:groupUpdateSourceAddress
transaction:transaction
error:&error];
if (error != nil || result == nil) {
OWSFailDebug(@"Error: %@", error);
return;
@ -1086,13 +1086,13 @@ NS_ASSUME_NONNULL_BEGIN
NSError *_Nullable error;
UpsertGroupResult *_Nullable result =
[GroupManager upsertExistingGroupV1WithGroupId:groupId
name:oldGroupThread.groupModel.groupName
avatarData:oldGroupThread.groupModel.groupAvatarData
members:newMembers.allObjects
groupUpdateSourceAddress:groupUpdateSourceAddress
transaction:transaction
error:&error];
[GroupManager remoteUpsertExistingGroupV1WithGroupId:groupId
name:oldGroupThread.groupModel.groupName
avatarData:oldGroupThread.groupModel.groupAvatarData
members:newMembers.allObjects
groupUpdateSourceAddress:groupUpdateSourceAddress
transaction:transaction
error:&error];
if (error != nil || result == nil) {
OWSFailDebug(@"Error: %@", error);
return;

View File

@ -28,6 +28,9 @@ public class UpsertGroupResult: NSObject {
// MARK: -
// * The "local" methods are used in response to the local user's interactions.
// * The "remote" methods are used in response to remote activity (incoming messages,
// sync transcripts, group syncs, etc.).
@objc
public class GroupManager: NSObject {
@ -49,12 +52,8 @@ public class GroupManager: NSObject {
return SSKEnvironment.shared.messageSender
}
private class var groupsV2: GroupsV2 {
return SSKEnvironment.shared.groupsV2
}
private class var groupsV2Swift: GroupsV2Swift {
return self.groupsV2 as! GroupsV2Swift
private class var groupsV2: GroupsV2Swift {
return SSKEnvironment.shared.groupsV2 as! GroupsV2Swift
}
private class var contactsManager: ContactsManagerProtocol {
@ -265,7 +264,7 @@ public class GroupManager: NSObject {
return false
}
guard doesUserHaveGroupsV2Capability(address: address,
transaction: transaction) else {
transaction: transaction) else {
Logger.warn("Member without Groups v2 capability.")
return false
}
@ -290,31 +289,31 @@ public class GroupManager: NSObject {
//
// "New" groups are being created for the first time; they might need to be created on the service.
public static func createNewGroup(members: [SignalServiceAddress],
groupId: Data? = nil,
name: String? = nil,
avatarImage: UIImage?,
newGroupSeed: NewGroupSeed? = nil,
shouldSendMessage: Bool) -> Promise<TSGroupThread> {
public static func localCreateNewGroup(members: [SignalServiceAddress],
groupId: Data? = nil,
name: String? = nil,
avatarImage: UIImage?,
newGroupSeed: NewGroupSeed? = nil,
shouldSendMessage: Bool) -> Promise<TSGroupThread> {
return DispatchQueue.global().async(.promise) {
return TSGroupModel.data(forGroupAvatar: avatarImage)
}.then(on: .global()) { avatarData in
return createNewGroup(members: members,
groupId: groupId,
name: name,
avatarData: avatarData,
newGroupSeed: newGroupSeed,
shouldSendMessage: shouldSendMessage)
return localCreateNewGroup(members: members,
groupId: groupId,
name: name,
avatarData: avatarData,
newGroupSeed: newGroupSeed,
shouldSendMessage: shouldSendMessage)
}
}
public static func createNewGroup(members membersParam: [SignalServiceAddress],
groupId: Data? = nil,
name: String? = nil,
avatarData: Data? = nil,
newGroupSeed: NewGroupSeed? = nil,
shouldSendMessage: Bool) -> Promise<TSGroupThread> {
public static func localCreateNewGroup(members membersParam: [SignalServiceAddress],
groupId: Data? = nil,
name: String? = nil,
avatarData: Data? = nil,
newGroupSeed: NewGroupSeed? = nil,
shouldSendMessage: Bool) -> Promise<TSGroupThread> {
guard let localAddress = tsAccountManager.localAddress else {
return Promise(error: OWSAssertionError("Missing localAddress."))
@ -338,9 +337,9 @@ public class GroupManager: NSObject {
return Promise.value(groupMembership)
}
return firstly {
self.groupsV2Swift.tryToEnsureProfileKeyCredentials(for: Array(groupMembership.allUsers))
self.groupsV2.tryToEnsureProfileKeyCredentials(for: Array(groupMembership.allUsers))
}.map(on: .global()) { (_) -> GroupMembership in
return groupMembership
return groupMembership
}
}.map(on: .global()) { (proposedGroupMembership: GroupMembership) throws -> TSGroupModel in
// GroupsV2 TODO: Let users specify access levels in the "new group" view.
@ -373,9 +372,9 @@ public class GroupManager: NSObject {
return Promise.value(proposedGroupModel)
}
return firstly {
self.groupsV2Swift.createNewGroupOnService(groupModel: proposedGroupModel)
self.groupsV2.createNewGroupOnService(groupModel: proposedGroupModel)
}.then(on: .global()) { _ in
self.groupsV2Swift.fetchCurrentGroupV2Snapshot(groupModel: proposedGroupModel)
self.groupsV2.fetchCurrentGroupV2Snapshot(groupModel: proposedGroupModel)
}.map(on: .global()) { (groupV2Snapshot: GroupV2Snapshot) -> TSGroupModel in
let createdGroupModel = try self.databaseStorage.read { transaction in
return try GroupManager.buildGroupModel(groupV2Snapshot: groupV2Snapshot, transaction: transaction)
@ -493,21 +492,21 @@ public class GroupManager: NSObject {
// success and failure are invoked on the main thread.
@objc
public static func createNewGroupObjc(members: [SignalServiceAddress],
groupId: Data?,
name: String,
avatarImage: UIImage?,
newGroupSeed: NewGroupSeed?,
shouldSendMessage: Bool,
success: @escaping (TSGroupThread) -> Void,
failure: @escaping (Error) -> Void) {
createNewGroup(members: members,
groupId: groupId,
name: name,
avatarImage: avatarImage,
newGroupSeed: newGroupSeed,
shouldSendMessage: shouldSendMessage).done { thread in
success(thread)
public static func localCreateNewGroupObjc(members: [SignalServiceAddress],
groupId: Data?,
name: String,
avatarImage: UIImage?,
newGroupSeed: NewGroupSeed?,
shouldSendMessage: Bool,
success: @escaping (TSGroupThread) -> Void,
failure: @escaping (Error) -> Void) {
localCreateNewGroup(members: members,
groupId: groupId,
name: name,
avatarImage: avatarImage,
newGroupSeed: newGroupSeed,
shouldSendMessage: shouldSendMessage).done { thread in
success(thread)
}.catch { error in
failure(error)
}.retainUntilComplete()
@ -515,21 +514,21 @@ public class GroupManager: NSObject {
// success and failure are invoked on the main thread.
@objc
public static func createNewGroupObjc(members: [SignalServiceAddress],
groupId: Data?,
name: String,
avatarData: Data?,
newGroupSeed: NewGroupSeed?,
shouldSendMessage: Bool,
success: @escaping (TSGroupThread) -> Void,
failure: @escaping (Error) -> Void) {
createNewGroup(members: members,
groupId: groupId,
name: name,
avatarData: avatarData,
newGroupSeed: newGroupSeed,
shouldSendMessage: shouldSendMessage).done { thread in
success(thread)
public static func localCreateNewGroupObjc(members: [SignalServiceAddress],
groupId: Data?,
name: String,
avatarData: Data?,
newGroupSeed: NewGroupSeed?,
shouldSendMessage: Bool,
success: @escaping (TSGroupThread) -> Void,
failure: @escaping (Error) -> Void) {
localCreateNewGroup(members: members,
groupId: groupId,
name: name,
avatarData: avatarData,
newGroupSeed: newGroupSeed,
shouldSendMessage: shouldSendMessage).done { thread in
success(thread)
}.catch { error in
failure(error)
}.retainUntilComplete()
@ -597,9 +596,9 @@ public class GroupManager: NSObject {
// Just create it in the database, don't create it on the service.
//
// GroupsV2 TODO: Update method to handle admins, pending members, etc.
return try upsertExistingGroup(groupModel: groupModel,
groupUpdateSourceAddress: localAddress,
transaction: transaction).groupThread
return try remoteUpsertExistingGroup(groupModel: groupModel,
groupUpdateSourceAddress: localAddress,
transaction: transaction).groupThread
}
#endif
@ -608,38 +607,38 @@ public class GroupManager: NSObject {
//
// "Existing" groups have already been created, we just need to make sure they're in the database.
@objc(upsertExistingGroupV1WithGroupId:name:avatarData:members:groupUpdateSourceAddress:transaction:error:)
public static func upsertExistingGroupV1(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
members: [SignalServiceAddress],
groupUpdateSourceAddress: SignalServiceAddress?,
transaction: SDSAnyWriteTransaction) throws -> UpsertGroupResult {
@objc(remoteUpsertExistingGroupV1WithGroupId:name:avatarData:members:groupUpdateSourceAddress:transaction:error:)
public static func remoteUpsertExistingGroupV1(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
members: [SignalServiceAddress],
groupUpdateSourceAddress: SignalServiceAddress?,
transaction: SDSAnyWriteTransaction) throws -> UpsertGroupResult {
let groupMembership = GroupMembership(v1Members: Set(members))
let groupAccess = GroupAccess.forV1
return try upsertExistingGroup(groupId: groupId,
name: name,
avatarData: avatarData,
groupMembership: groupMembership,
groupAccess: groupAccess,
groupsVersion: .V1,
groupV2Revision: 0,
groupSecretParamsData: nil,
groupUpdateSourceAddress: groupUpdateSourceAddress,
transaction: transaction)
return try remoteUpsertExistingGroup(groupId: groupId,
name: name,
avatarData: avatarData,
groupMembership: groupMembership,
groupAccess: groupAccess,
groupsVersion: .V1,
groupV2Revision: 0,
groupSecretParamsData: nil,
groupUpdateSourceAddress: groupUpdateSourceAddress,
transaction: transaction)
}
public static func upsertExistingGroup(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupAccess: GroupAccess,
groupsVersion: GroupsVersion,
groupV2Revision: UInt32,
groupSecretParamsData: Data? = nil,
groupUpdateSourceAddress: SignalServiceAddress?,
transaction: SDSAnyWriteTransaction) throws -> UpsertGroupResult {
public static func remoteUpsertExistingGroup(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupAccess: GroupAccess,
groupsVersion: GroupsVersion,
groupV2Revision: UInt32,
groupSecretParamsData: Data? = nil,
groupUpdateSourceAddress: SignalServiceAddress?,
transaction: SDSAnyWriteTransaction) throws -> UpsertGroupResult {
let groupModel = try buildGroupModel(groupId: groupId,
name: name,
@ -651,14 +650,14 @@ public class GroupManager: NSObject {
groupSecretParamsData: groupSecretParamsData,
transaction: transaction)
return try upsertExistingGroup(groupModel: groupModel,
groupUpdateSourceAddress: groupUpdateSourceAddress,
transaction: transaction)
return try remoteUpsertExistingGroup(groupModel: groupModel,
groupUpdateSourceAddress: groupUpdateSourceAddress,
transaction: transaction)
}
public static func upsertExistingGroup(groupModel: TSGroupModel,
groupUpdateSourceAddress: SignalServiceAddress?,
transaction: SDSAnyWriteTransaction) throws -> UpsertGroupResult {
public static func remoteUpsertExistingGroup(groupModel: TSGroupModel,
groupUpdateSourceAddress: SignalServiceAddress?,
transaction: SDSAnyWriteTransaction) throws -> UpsertGroupResult {
return try self.tryToUpsertExistingGroupThreadInDatabaseAndCreateInfoMessage(newGroupModel: groupModel,
groupUpdateSourceAddress: groupUpdateSourceAddress,
@ -668,6 +667,39 @@ public class GroupManager: NSObject {
// MARK: - Update Existing Group
// Unlike remoteUpsertExistingGroupV1(), this method never inserts.
@objc
public static func remoteUpdateToExistingGroupV1(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupUpdateSourceAddress: SignalServiceAddress?,
transaction: SDSAnyWriteTransaction) throws -> UpsertGroupResult {
let updateInfo: UpdateInfo
do {
updateInfo = try self.updateInfo(groupId: groupId,
name: name,
avatarData: avatarData,
groupMembership: groupMembership,
groupAccess: GroupAccess.forV1,
newDMConfiguration: nil,
transaction: transaction)
} catch GroupsV2Error.redundantChange {
guard let groupThread = TSGroupThread.fetch(groupId: groupId, transaction: transaction) else {
throw OWSAssertionError("Missing groupThread.")
}
return UpsertGroupResult(action: .unchanged, groupThread: groupThread)
}
let newGroupModel = updateInfo.newGroupModel
return try self.tryToUpsertExistingGroupThreadInDatabaseAndCreateInfoMessage(newGroupModel: newGroupModel,
groupUpdateSourceAddress: groupUpdateSourceAddress,
canInsert: false,
transaction: transaction)
}
// MARK: - Update Existing Group
private struct UpdateInfo {
let groupId: Data
let oldGroupModel: TSGroupModel
@ -677,44 +709,44 @@ public class GroupManager: NSObject {
}
// If dmConfiguration is nil, don't change the disappearing messages configuration.
public static func updateExistingGroup(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupAccess: GroupAccess,
groupsVersion: GroupsVersion,
dmConfiguration: OWSDisappearingMessagesConfiguration?,
groupUpdateSourceAddress: SignalServiceAddress?) -> Promise<TSGroupThread> {
public static func localUpdateExistingGroup(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupAccess: GroupAccess,
groupsVersion: GroupsVersion,
dmConfiguration: OWSDisappearingMessagesConfiguration?,
groupUpdateSourceAddress: SignalServiceAddress?) -> Promise<TSGroupThread> {
switch groupsVersion {
case .V1:
return updateExistingGroupV1(groupId: groupId,
name: name,
avatarData: avatarData,
groupMembership: groupMembership,
groupAccess: groupAccess,
dmConfiguration: dmConfiguration,
groupUpdateSourceAddress: groupUpdateSourceAddress)
return localUpdateExistingGroupV1(groupId: groupId,
name: name,
avatarData: avatarData,
groupMembership: groupMembership,
groupAccess: groupAccess,
dmConfiguration: dmConfiguration,
groupUpdateSourceAddress: groupUpdateSourceAddress)
case .V2:
return updateExistingGroupV2(groupId: groupId,
name: name,
avatarData: avatarData,
groupMembership: groupMembership,
groupAccess: groupAccess,
dmConfiguration: dmConfiguration,
groupUpdateSourceAddress: groupUpdateSourceAddress)
return localUpdateExistingGroupV2(groupId: groupId,
name: name,
avatarData: avatarData,
groupMembership: groupMembership,
groupAccess: groupAccess,
dmConfiguration: dmConfiguration,
groupUpdateSourceAddress: groupUpdateSourceAddress)
}
}
// If dmConfiguration is nil, don't change the disappearing messages configuration.
private static func updateExistingGroupV1(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupAccess: GroupAccess,
dmConfiguration: OWSDisappearingMessagesConfiguration?,
groupUpdateSourceAddress: SignalServiceAddress?) -> Promise<TSGroupThread> {
private static func localUpdateExistingGroupV1(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupAccess: GroupAccess,
dmConfiguration: OWSDisappearingMessagesConfiguration?,
groupUpdateSourceAddress: SignalServiceAddress?) -> Promise<TSGroupThread> {
return self.databaseStorage.write(.promise) { (transaction) throws -> UpsertGroupResult in
let updateInfo = try self.updateInfo(groupId: groupId,
@ -754,13 +786,13 @@ public class GroupManager: NSObject {
// If dmConfiguration is nil, don't change the disappearing messages configuration.
//
// GroupsV2 TODO: This should block on message processing.
private static func updateExistingGroupV2(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupAccess: GroupAccess,
dmConfiguration: OWSDisappearingMessagesConfiguration?,
groupUpdateSourceAddress: SignalServiceAddress?) -> Promise<TSGroupThread> {
private static func localUpdateExistingGroupV2(groupId: Data,
name: String? = nil,
avatarData: Data? = nil,
groupMembership: GroupMembership,
groupAccess: GroupAccess,
dmConfiguration: OWSDisappearingMessagesConfiguration?,
groupUpdateSourceAddress: SignalServiceAddress?) -> Promise<TSGroupThread> {
return firstly {
return self.ensureLocalProfileHasCommitmentIfNecessary()
@ -773,15 +805,15 @@ public class GroupManager: NSObject {
groupAccess: groupAccess,
newDMConfiguration: dmConfiguration,
transaction: transaction)
let changeSet = try groupsV2Swift.buildChangeSet(oldGroupModel: updateInfo.oldGroupModel,
newGroupModel: updateInfo.newGroupModel,
oldDMConfiguration: updateInfo.oldDMConfiguration,
newDMConfiguration: updateInfo.newDMConfiguration,
transaction: transaction)
let changeSet = try groupsV2.buildChangeSet(oldGroupModel: updateInfo.oldGroupModel,
newGroupModel: updateInfo.newGroupModel,
oldDMConfiguration: updateInfo.oldDMConfiguration,
newDMConfiguration: updateInfo.newDMConfiguration,
transaction: transaction)
return (updateInfo, changeSet)
}
}.then(on: .global()) { (_: UpdateInfo, changeSet: GroupsV2ChangeSet) throws -> Promise<TSGroupThread> in
return groupsV2Swift.updateExistingGroupOnService(changeSet: changeSet)
return groupsV2.updateExistingGroupOnService(changeSet: changeSet)
}
// GroupsV2 TODO: Handle redundant change error.
}
@ -882,8 +914,8 @@ public class GroupManager: NSObject {
return firstly {
return self.ensureLocalProfileHasCommitmentIfNecessary()
}.then(on: .global()) { () throws -> Promise<TSGroupThread> in
return groupsV2Swift.updateDisappearingMessageStateOnService(groupThread: groupThread,
disappearingMessageToken: disappearingMessageToken)
return groupsV2.updateDisappearingMessageStateOnService(groupThread: groupThread,
disappearingMessageToken: disappearingMessageToken)
}.asVoid()
}
@ -932,7 +964,7 @@ public class GroupManager: NSObject {
return firstly {
return self.ensureLocalProfileHasCommitmentIfNecessary()
}.then(on: .global()) { () throws -> Promise<TSGroupThread> in
return self.groupsV2Swift.acceptInviteToGroupV2(groupThread: groupThread)
return self.groupsV2.acceptInviteToGroupV2(groupThread: groupThread)
}
}
@ -997,7 +1029,7 @@ public class GroupManager: NSObject {
return firstly {
return self.ensureLocalProfileHasCommitmentIfNecessary()
}.then(on: .global()) { () throws -> Promise<TSGroupThread> in
return self.groupsV2Swift.leaveGroupV2OrDeclineInvite(groupThread: groupThread)
return self.groupsV2.leaveGroupV2OrDeclineInvite(groupThread: groupThread)
}
}
@ -1089,7 +1121,7 @@ public class GroupManager: NSObject {
assert(messageBuilder.additionalRecipients == nil)
let additionalRecipients = groupThread.groupModel.pendingMembers.filter { address in
return doesUserSupportGroupsV2(address: address,
transaction: transaction)
transaction: transaction)
}
messageBuilder.additionalRecipients = Array(additionalRecipients)
}
@ -1216,7 +1248,7 @@ public class GroupManager: NSObject {
@objc
public static func doesUserHaveGroupsV2Capability(address: SignalServiceAddress,
transaction: SDSAnyReadTransaction) -> Bool {
transaction: SDSAnyReadTransaction) -> Bool {
if FeatureFlags.groupsV2IgnoreCapability {
return true
}
@ -1307,7 +1339,7 @@ public class GroupManager: NSObject {
// for the local user (which should last forever) we'll abort above.
// Group v2 actions will use tryToEnsureProfileKeyCredentials()
// and we want to set them up to succeed.
return self.groupsV2Swift.reuploadLocalProfilePromise()
return self.groupsV2.reuploadLocalProfilePromise()
}
}
}