Improving handling of edge cases in conversation view.
This commit is contained in:
parent
658746093d
commit
6d4a05bbea
|
@ -62,12 +62,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (CGFloat)audioDurationSeconds
|
||||
{
|
||||
NSNumber *_Nullable audioDurationSeconds = self.viewItem.audioDurationSeconds;
|
||||
if (!audioDurationSeconds) {
|
||||
audioDurationSeconds = @([self.attachmentStream audioDurationSecondsWithoutTransaction]);
|
||||
self.viewItem.audioDurationSeconds = audioDurationSeconds;
|
||||
}
|
||||
return [audioDurationSeconds floatValue];
|
||||
OWSAssert(self.viewItem.audioDurationSeconds);
|
||||
|
||||
return [self.viewItem.audioDurationSeconds floatValue];
|
||||
}
|
||||
|
||||
- (AudioPlaybackState)audioPlaybackState
|
||||
|
|
|
@ -97,7 +97,7 @@ static const int kYapDatabasePageSize = 50;
|
|||
static const int kYapDatabaseMaxPageCount = 500;
|
||||
// Never show more than 6*50 = 300 messages in conversation view when user
|
||||
// arrives.
|
||||
static const int kYapDatabaseMaxInitialPageCount = 6;
|
||||
static const int kYapDatabaseMaxInitialPageCount = 500;
|
||||
static const int kConversationInitialMaxRangeSize = kYapDatabasePageSize * kYapDatabaseMaxInitialPageCount;
|
||||
static const int kYapDatabaseRangeMaxLength = kYapDatabasePageSize * kYapDatabaseMaxPageCount;
|
||||
static const int kYapDatabaseRangeMinLength = 0;
|
||||
|
@ -2883,8 +2883,6 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
// b) is inserting new interactions.
|
||||
__block BOOL scrollToBottom = wasAtBottom;
|
||||
|
||||
BOOL shouldAnimateUpdates = [self shouldAnimateRowUpdates:rowChanges oldViewItemCount:oldViewItemCount];
|
||||
|
||||
void (^batchUpdates)(void) = ^{
|
||||
for (YapDatabaseViewRowChange *rowChange in rowChanges) {
|
||||
switch (rowChange.type) {
|
||||
|
@ -2893,6 +2891,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
rowChange.collectionKey,
|
||||
rowChange.indexPath,
|
||||
rowChange.finalIndex);
|
||||
[DDLog flushLog];
|
||||
[self.collectionView deleteItemsAtIndexPaths:@[ rowChange.indexPath ]];
|
||||
YapCollectionKey *collectionKey = rowChange.collectionKey;
|
||||
OWSAssert(collectionKey.key.length > 0);
|
||||
|
@ -2903,6 +2902,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
rowChange.collectionKey,
|
||||
rowChange.newIndexPath,
|
||||
rowChange.finalIndex);
|
||||
[DDLog flushLog];
|
||||
[self.collectionView insertItemsAtIndexPaths:@[ rowChange.newIndexPath ]];
|
||||
// We don't want to reload a row that we just inserted.
|
||||
[rowsThatChangedSize removeObject:@(rowChange.finalIndex)];
|
||||
|
@ -2923,8 +2923,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
rowChange.indexPath,
|
||||
rowChange.newIndexPath,
|
||||
rowChange.finalIndex);
|
||||
[self.collectionView deleteItemsAtIndexPaths:@[ rowChange.indexPath ]];
|
||||
[self.collectionView insertItemsAtIndexPaths:@[ rowChange.newIndexPath ]];
|
||||
[DDLog flushLog];
|
||||
[self.collectionView moveItemAtIndexPath:rowChange.indexPath toIndexPath:rowChange.newIndexPath];
|
||||
// We don't want to reload a row that we just moved.
|
||||
[rowsThatChangedSize removeObject:@(rowChange.finalIndex)];
|
||||
break;
|
||||
|
@ -2934,6 +2934,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
rowChange.collectionKey,
|
||||
rowChange.indexPath,
|
||||
rowChange.finalIndex);
|
||||
[DDLog flushLog];
|
||||
[self.collectionView reloadItemsAtIndexPaths:@[ rowChange.indexPath ]];
|
||||
// We don't want to reload a row that we've already reloaded.
|
||||
[rowsThatChangedSize removeObject:@(rowChange.finalIndex)];
|
||||
|
@ -2946,40 +2947,151 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
// as they may affect which cells show "date" headers or "status" footers.
|
||||
NSMutableArray<NSIndexPath *> *rowsToReload = [NSMutableArray new];
|
||||
for (NSNumber *row in rowsThatChangedSize) {
|
||||
DDLogVerbose(@"rowsToReload: %@", row);
|
||||
[rowsToReload addObject:[NSIndexPath indexPathForRow:row.integerValue inSection:0]];
|
||||
}
|
||||
if (rowsToReload.count > 0) {
|
||||
[DDLog flushLog];
|
||||
[self.collectionView reloadItemsAtIndexPaths:rowsToReload];
|
||||
}
|
||||
};
|
||||
void (^batchUpdatesCompletion)(BOOL) = ^(BOOL finished) {
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
if (!finished) {
|
||||
DDLogInfo(@"%@ performBatchUpdates did not finish", self.logTag);
|
||||
}
|
||||
DDLogVerbose(@"self.viewItems.count: %zd -> %zd", oldViewItemCount, self.viewItems.count);
|
||||
[DDLog flushLog];
|
||||
|
||||
[self updateLastVisibleTimestamp];
|
||||
|
||||
if (scrollToBottom) {
|
||||
[self scrollToBottomAnimated:shouldAnimateScrollToBottom && shouldAnimateUpdates];
|
||||
}
|
||||
};
|
||||
|
||||
if (shouldAnimateUpdates) {
|
||||
[self.collectionView performBatchUpdates:batchUpdates completion:batchUpdatesCompletion];
|
||||
} else {
|
||||
BOOL shouldReloadCollection = [self shouldReloadCollection:rowChanges];
|
||||
if (shouldReloadCollection) {
|
||||
[UIView performWithoutAnimation:^{
|
||||
[self.collectionView performBatchUpdates:batchUpdates completion:batchUpdatesCompletion];
|
||||
[self.collectionView reloadData];
|
||||
}];
|
||||
[self updateLastVisibleTimestamp];
|
||||
} else {
|
||||
BOOL shouldAnimateUpdates = [self shouldAnimateRowUpdates:rowChanges oldViewItemCount:oldViewItemCount];
|
||||
void (^batchUpdatesCompletion)(BOOL) = ^(BOOL finished) {
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
if (!finished) {
|
||||
DDLogInfo(@"%@ performBatchUpdates did not finish", self.logTag);
|
||||
}
|
||||
|
||||
[self updateLastVisibleTimestamp];
|
||||
|
||||
if (scrollToBottom) {
|
||||
[self scrollToBottomAnimated:shouldAnimateScrollToBottom && shouldAnimateUpdates];
|
||||
}
|
||||
};
|
||||
if (shouldAnimateUpdates) {
|
||||
[self.collectionView performBatchUpdates:batchUpdates completion:batchUpdatesCompletion];
|
||||
} else {
|
||||
[UIView performWithoutAnimation:^{
|
||||
[self.collectionView performBatchUpdates:batchUpdates completion:batchUpdatesCompletion];
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)shouldReloadCollection:(NSArray<YapDatabaseViewRowChange *> *)rowChanges
|
||||
{
|
||||
OWSAssert(rowChanges);
|
||||
|
||||
BOOL hasDeletes = NO;
|
||||
BOOL hasInserts = NO;
|
||||
BOOL hasMoves = NO;
|
||||
BOOL hasUpdates = NO;
|
||||
for (YapDatabaseViewRowChange *rowChange in rowChanges) {
|
||||
switch (rowChange.type) {
|
||||
case YapDatabaseViewChangeDelete:
|
||||
DDLogVerbose(@"? YapDatabaseViewChangeDelete: %@, %@, %zd",
|
||||
rowChange.collectionKey,
|
||||
rowChange.indexPath,
|
||||
rowChange.finalIndex);
|
||||
[DDLog flushLog];
|
||||
hasDeletes = YES;
|
||||
break;
|
||||
case YapDatabaseViewChangeInsert:
|
||||
DDLogVerbose(@"...YapDatabaseViewChangeInsert: %@, %@, %zd",
|
||||
rowChange.collectionKey,
|
||||
rowChange.newIndexPath,
|
||||
rowChange.finalIndex);
|
||||
[DDLog flushLog];
|
||||
hasInserts = YES;
|
||||
break;
|
||||
case YapDatabaseViewChangeMove:
|
||||
DDLogVerbose(@"...YapDatabaseViewChangeMove: %@, %@, %@, %zd",
|
||||
rowChange.collectionKey,
|
||||
rowChange.indexPath,
|
||||
rowChange.newIndexPath,
|
||||
rowChange.finalIndex);
|
||||
[DDLog flushLog];
|
||||
hasMoves = YES;
|
||||
break;
|
||||
case YapDatabaseViewChangeUpdate:
|
||||
DDLogVerbose(@"...YapDatabaseViewChangeUpdate: %@, %@, %zd",
|
||||
rowChange.collectionKey,
|
||||
rowChange.indexPath,
|
||||
rowChange.finalIndex);
|
||||
[DDLog flushLog];
|
||||
hasUpdates = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasMoves) {
|
||||
// "Move" changes cannot be safely performed using
|
||||
// [UICollectionView performBatchUpdates:]. This appears to be a
|
||||
// bug in YapDatabase.
|
||||
return YES;
|
||||
}
|
||||
// if (hasDeletes && hasInserts) {
|
||||
// return YES;
|
||||
// }
|
||||
// if (hasDeletes && hasUpdates) {
|
||||
// return YES;
|
||||
// }
|
||||
// if (hasInserts && hasUpdates) {
|
||||
// return YES;
|
||||
// }
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)shouldAnimateRowUpdates:(NSArray<YapDatabaseViewRowChange *> *)rowChanges
|
||||
oldViewItemCount:(NSUInteger)oldViewItemCount
|
||||
{
|
||||
OWSAssert(rowChanges);
|
||||
|
||||
// for (YapDatabaseViewRowChange *rowChange in rowChanges) {
|
||||
// switch (rowChange.type) {
|
||||
// case YapDatabaseViewChangeDelete:
|
||||
// DDLogVerbose(@"...YapDatabaseViewChangeDelete: %@, %@, %zd",
|
||||
// rowChange.collectionKey,
|
||||
// rowChange.indexPath,
|
||||
// rowChange.finalIndex);
|
||||
// [DDLog flushLog];
|
||||
// break;
|
||||
// case YapDatabaseViewChangeInsert:
|
||||
// DDLogVerbose(@"...YapDatabaseViewChangeInsert: %@, %@, %zd",
|
||||
// rowChange.collectionKey,
|
||||
// rowChange.newIndexPath,
|
||||
// rowChange.finalIndex);
|
||||
// [DDLog flushLog];
|
||||
// break;
|
||||
// case YapDatabaseViewChangeMove:
|
||||
// DDLogVerbose(@"...YapDatabaseViewChangeMove: %@, %@, %@, %zd",
|
||||
// rowChange.collectionKey,
|
||||
// rowChange.indexPath,
|
||||
// rowChange.newIndexPath,
|
||||
// rowChange.finalIndex);
|
||||
// [DDLog flushLog];
|
||||
// break;
|
||||
// case YapDatabaseViewChangeUpdate:
|
||||
// DDLogVerbose(@"...YapDatabaseViewChangeUpdate: %@, %@, %zd",
|
||||
// rowChange.collectionKey,
|
||||
// rowChange.indexPath,
|
||||
// rowChange.finalIndex);
|
||||
// [DDLog flushLog];
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// If user sends a new outgoing message, don't animate the change.
|
||||
BOOL isOnlyInsertingNewOutgoingMessages = YES;
|
||||
BOOL isOnlyUpdatingLastOutgoingMessage = YES;
|
||||
|
@ -3325,20 +3437,23 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
|
|||
[self presentViewController:actionSheetController animated:true completion:nil];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)lastVisibleIndexPath
|
||||
- (nullable NSIndexPath *)lastVisibleIndexPath
|
||||
{
|
||||
NSIndexPath *lastVisibleIndexPath = nil;
|
||||
NSIndexPath *_Nullable lastVisibleIndexPath = nil;
|
||||
for (NSIndexPath *indexPath in [self.collectionView indexPathsForVisibleItems]) {
|
||||
if (!lastVisibleIndexPath || indexPath.row > lastVisibleIndexPath.row) {
|
||||
lastVisibleIndexPath = indexPath;
|
||||
}
|
||||
}
|
||||
if (lastVisibleIndexPath && lastVisibleIndexPath.row >= self.viewItems.count) {
|
||||
return (self.viewItems.count > 0 ? [NSIndexPath indexPathForRow:self.viewItems.count - 1 inSection:0] : nil);
|
||||
}
|
||||
return lastVisibleIndexPath;
|
||||
}
|
||||
|
||||
- (nullable ConversationViewItem *)lastVisibleViewItem
|
||||
{
|
||||
NSIndexPath *lastVisibleIndexPath = [self lastVisibleIndexPath];
|
||||
NSIndexPath *_Nullable lastVisibleIndexPath = [self lastVisibleIndexPath];
|
||||
if (!lastVisibleIndexPath) {
|
||||
return nil;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
|
|||
|
||||
@property (nonatomic, weak) OWSAudioMessageView *lastAudioMessageView;
|
||||
|
||||
@property (nonatomic, nullable) NSNumber *audioDurationSeconds;
|
||||
@property (nonatomic, readonly, nullable) NSNumber *audioDurationSeconds;
|
||||
|
||||
- (CGFloat)audioProgressSeconds;
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
|
||||
@property (nonatomic) AudioPlaybackState audioPlaybackState;
|
||||
@property (nonatomic) CGFloat audioProgressSeconds;
|
||||
@property (nonatomic, nullable) NSNumber *audioDurationSeconds;
|
||||
|
||||
#pragma mark - View State
|
||||
|
||||
|
@ -251,9 +252,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
self.audioProgressSeconds = progress;
|
||||
if (duration > 0) {
|
||||
self.audioDurationSeconds = @(duration);
|
||||
}
|
||||
|
||||
[self.lastAudioMessageView updateContents];
|
||||
}
|
||||
|
@ -390,13 +388,19 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
self.messageCellType = OWSMessageCellType_GenericAttachment;
|
||||
return;
|
||||
}
|
||||
self.contentSize = [self.attachmentStream imageSizeWithoutTransaction];
|
||||
self.contentSize = [self.attachmentStream imageSize];
|
||||
if (self.contentSize.width <= 0 || self.contentSize.height <= 0) {
|
||||
self.messageCellType = OWSMessageCellType_GenericAttachment;
|
||||
}
|
||||
return;
|
||||
} else if ([self.attachmentStream isAudio]) {
|
||||
self.messageCellType = OWSMessageCellType_Audio;
|
||||
CGFloat audioDurationSeconds = [self.attachmentStream audioDurationSeconds];
|
||||
if (audioDurationSeconds > 0) {
|
||||
self.audioDurationSeconds = @(audioDurationSeconds);
|
||||
self.messageCellType = OWSMessageCellType_Audio;
|
||||
} else {
|
||||
self.messageCellType = OWSMessageCellType_GenericAttachment;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
self.messageCellType = OWSMessageCellType_GenericAttachment;
|
||||
|
|
|
@ -40,6 +40,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSAssert(thread);
|
||||
|
||||
NSMutableArray<OWSTableItem *> *items = [@[
|
||||
[OWSTableItem itemWithTitle:@"Perform 100 random actions"
|
||||
actionBlock:^{
|
||||
[DebugUIMessages performRandomActions:100 thread:thread];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Perform 1,000 random actions"
|
||||
actionBlock:^{
|
||||
[DebugUIMessages performRandomActions:1000 thread:thread];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Send 10 messages (1/sec.)"
|
||||
actionBlock:^{
|
||||
[DebugUIMessages sendTextMessages:10 thread:thread];
|
||||
|
@ -241,14 +249,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
actionBlock:^{
|
||||
[DebugUIMessages injectFakeIncomingMessages:1000 thread:thread];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Perform 100 random actions"
|
||||
actionBlock:^{
|
||||
[DebugUIMessages performRandomActions:100 thread:thread];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Perform 1,000 random actions"
|
||||
actionBlock:^{
|
||||
[DebugUIMessages performRandomActions:1000 thread:thread];
|
||||
}],
|
||||
] mutableCopy];
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
|
@ -271,10 +271,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
+ (void)sendTextMessageInThread:(TSThread *)thread counter:(int)counter
|
||||
{
|
||||
DDLogInfo(@"%@ sendTextMessageInThread: %d", self.logTag, counter);
|
||||
[DDLog flushLog];
|
||||
|
||||
NSString *randomText = [self randomText];
|
||||
NSString *text = [[[@(counter) description] stringByAppendingString:@" "] stringByAppendingString:randomText];
|
||||
OWSMessageSender *messageSender = [Environment getCurrent].messageSender;
|
||||
[ThreadUtil sendMessageWithText:text inThread:thread messageSender:messageSender];
|
||||
TSOutgoingMessage *message = [ThreadUtil sendMessageWithText:text inThread:thread messageSender:messageSender];
|
||||
DDLogError(@"%@ sendTextMessageInThread timestamp: %llu.", self.logTag, message.timestamp);
|
||||
}
|
||||
|
||||
+ (void)sendTextMessages:(int)counter thread:(TSThread *)thread
|
||||
|
@ -939,83 +943,96 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
+ (void)sendFakeMessages:(NSUInteger)counter thread:(TSThread *)thread
|
||||
{
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (NSUInteger i = 0; i < counter; i++) {
|
||||
NSString *randomText = [self randomText];
|
||||
switch (arc4random_uniform(4)) {
|
||||
case 0: {
|
||||
TSIncomingMessage *message =
|
||||
[[TSIncomingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
authorId:@"+19174054215"
|
||||
sourceDeviceId:0
|
||||
messageBody:randomText];
|
||||
[message markAsReadWithTransaction:transaction sendReadReceipt:NO updateExpiration:NO];
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
TSOutgoingMessage *message =
|
||||
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
messageBody:randomText];
|
||||
[message saveWithTransaction:transaction];
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
UInt32 filesize = 64;
|
||||
TSAttachmentPointer *pointer =
|
||||
[[TSAttachmentPointer alloc] initWithServerId:237391539706350548
|
||||
key:[self createRandomNSDataOfSize:filesize]
|
||||
digest:nil
|
||||
byteCount:filesize
|
||||
contentType:@"audio/mp3"
|
||||
relay:@""
|
||||
sourceFilename:@"test.mp3"
|
||||
attachmentType:TSAttachmentTypeDefault];
|
||||
[pointer saveWithTransaction:transaction];
|
||||
TSIncomingMessage *message =
|
||||
[[TSIncomingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
authorId:@"+19174054215"
|
||||
sourceDeviceId:0
|
||||
messageBody:nil
|
||||
attachmentIds:@[
|
||||
pointer.uniqueId,
|
||||
]
|
||||
expiresInSeconds:0];
|
||||
[message markAsReadWithTransaction:transaction sendReadReceipt:NO updateExpiration:NO];
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
TSOutgoingMessage *message =
|
||||
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
isVoiceMessage:NO
|
||||
expiresInSeconds:0];
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self sendFakeMessages:counter thread:thread transaction:transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
NSString *filename = @"test.mp3";
|
||||
UInt32 filesize = 16;
|
||||
+ (void)sendFakeMessages:(NSUInteger)counter
|
||||
thread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
DDLogInfo(@"%@ sendFakeMessages: %zd", self.logTag, counter);
|
||||
|
||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3"
|
||||
byteCount:filesize
|
||||
sourceFilename:filename];
|
||||
for (NSUInteger i = 0; i < counter; i++) {
|
||||
NSString *randomText = [self randomText];
|
||||
switch (arc4random_uniform(4)) {
|
||||
case 0: {
|
||||
TSIncomingMessage *message =
|
||||
[[TSIncomingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
authorId:@"+19174054215"
|
||||
sourceDeviceId:0
|
||||
messageBody:randomText];
|
||||
DDLogError(@"%@ sendFakeMessages incoming timestamp: %llu.", self.logTag, message.timestamp);
|
||||
[message markAsReadWithTransaction:transaction sendReadReceipt:NO updateExpiration:NO];
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
TSOutgoingMessage *message =
|
||||
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
messageBody:randomText];
|
||||
DDLogError(@"%@ sendFakeMessages outgoing timestamp: %llu.", self.logTag, message.timestamp);
|
||||
[message saveWithTransaction:transaction];
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
UInt32 filesize = 64;
|
||||
TSAttachmentPointer *pointer =
|
||||
[[TSAttachmentPointer alloc] initWithServerId:237391539706350548
|
||||
key:[self createRandomNSDataOfSize:filesize]
|
||||
digest:nil
|
||||
byteCount:filesize
|
||||
contentType:@"audio/mp3"
|
||||
relay:@""
|
||||
sourceFilename:@"test.mp3"
|
||||
attachmentType:TSAttachmentTypeDefault];
|
||||
[pointer saveWithTransaction:transaction];
|
||||
TSIncomingMessage *message =
|
||||
[[TSIncomingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
authorId:@"+19174054215"
|
||||
sourceDeviceId:0
|
||||
messageBody:nil
|
||||
attachmentIds:@[
|
||||
pointer.uniqueId,
|
||||
]
|
||||
expiresInSeconds:0];
|
||||
DDLogError(@"%@ sendFakeMessages incoming attachment timestamp: %llu.", self.logTag, message.timestamp);
|
||||
[message markAsReadWithTransaction:transaction sendReadReceipt:NO updateExpiration:NO];
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
TSOutgoingMessage *message =
|
||||
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
isVoiceMessage:NO
|
||||
expiresInSeconds:0];
|
||||
DDLogError(@"%@ sendFakeMessages outgoing attachment timestamp: %llu.", self.logTag, message.timestamp);
|
||||
|
||||
NSError *error;
|
||||
BOOL success = [attachmentStream writeData:[self createRandomNSDataOfSize:filesize] error:&error];
|
||||
OWSAssert(success && !error);
|
||||
NSString *filename = @"test.mp3";
|
||||
UInt32 filesize = 16;
|
||||
|
||||
[attachmentStream saveWithTransaction:transaction];
|
||||
[message.attachmentIds addObject:attachmentStream.uniqueId];
|
||||
if (filename) {
|
||||
message.attachmentFilenameMap[attachmentStream.uniqueId] = filename;
|
||||
}
|
||||
[message saveWithTransaction:transaction];
|
||||
break;
|
||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3"
|
||||
byteCount:filesize
|
||||
sourceFilename:filename];
|
||||
|
||||
NSError *error;
|
||||
BOOL success = [attachmentStream writeData:[self createRandomNSDataOfSize:filesize] error:&error];
|
||||
OWSAssert(success && !error);
|
||||
|
||||
[attachmentStream saveWithTransaction:transaction];
|
||||
[message.attachmentIds addObject:attachmentStream.uniqueId];
|
||||
if (filename) {
|
||||
message.attachmentFilenameMap[attachmentStream.uniqueId] = filename;
|
||||
}
|
||||
[message saveWithTransaction:transaction];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)sendTinyAttachments:(int)counter thread:(TSThread *)thread
|
||||
|
@ -1099,6 +1116,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
{
|
||||
OWSAssert(thread);
|
||||
|
||||
DDLogInfo(@"%@ injectIncomingMessageInThread: %d", self.logTag, counter);
|
||||
|
||||
NSString *randomText = [self randomText];
|
||||
NSString *text = [[[@(counter) description] stringByAppendingString:@" "] stringByAppendingString:randomText];
|
||||
|
||||
|
@ -1154,144 +1173,151 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
+ (void)performRandomActionInThread:(TSThread *)thread
|
||||
counter:(int)counter
|
||||
{
|
||||
typedef void (^ActionBlock)(void);
|
||||
typedef void (^ActionBlock)(YapDatabaseReadWriteTransaction *transaction);
|
||||
NSArray<ActionBlock> *actionBlocks = @[
|
||||
^{
|
||||
[self injectIncomingMessageInThread:thread counter:counter];
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
// injectIncomingMessageInThread doesn't take a transaction.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self injectIncomingMessageInThread:thread counter:counter];
|
||||
});
|
||||
},
|
||||
^{
|
||||
[self sendTextMessageInThread:thread counter:counter];
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
// sendTextMessageInThread doesn't take a transaction.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self sendTextMessageInThread:thread counter:counter];
|
||||
});
|
||||
},
|
||||
^{
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
NSUInteger messageCount = (NSUInteger)(1 + arc4random_uniform(4));
|
||||
[self sendFakeMessages:messageCount thread:thread];
|
||||
[self sendFakeMessages:messageCount thread:thread transaction:transaction];
|
||||
},
|
||||
^{
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
NSUInteger messageCount = (NSUInteger)(1 + arc4random_uniform(4));
|
||||
[self deleteRandomMessages:messageCount thread:thread];
|
||||
[self deleteRandomMessages:messageCount thread:thread transaction:transaction];
|
||||
},
|
||||
^{
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
NSUInteger messageCount = (NSUInteger)(1 + arc4random_uniform(4));
|
||||
[self deleteLastMessages:messageCount thread:thread];
|
||||
[self deleteLastMessages:messageCount thread:thread transaction:transaction];
|
||||
},
|
||||
^{
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
NSUInteger messageCount = (NSUInteger)(1 + arc4random_uniform(4));
|
||||
[self deleteRandomRecentMessages:messageCount thread:thread];
|
||||
[self deleteRandomRecentMessages:messageCount thread:thread transaction:transaction];
|
||||
},
|
||||
^{
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
NSUInteger messageCount = (NSUInteger)(1 + arc4random_uniform(4));
|
||||
[self insertAndDeleteNewOutgoingMessages:messageCount thread:thread];
|
||||
[self insertAndDeleteNewOutgoingMessages:messageCount thread:thread transaction:transaction];
|
||||
},
|
||||
^{
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
NSUInteger messageCount = (NSUInteger)(1 + arc4random_uniform(4));
|
||||
[self resurrectNewOutgoingMessages1:messageCount thread:thread];
|
||||
[self resurrectNewOutgoingMessages1:messageCount thread:thread transaction:transaction];
|
||||
},
|
||||
^{
|
||||
^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
NSUInteger messageCount = (NSUInteger)(1 + arc4random_uniform(4));
|
||||
[self resurrectNewOutgoingMessages2:messageCount thread:thread];
|
||||
[self resurrectNewOutgoingMessages2:messageCount thread:thread transaction:transaction];
|
||||
},
|
||||
];
|
||||
ActionBlock actionBlock = actionBlocks[(NSUInteger) arc4random_uniform((uint32_t) actionBlocks.count)];
|
||||
actionBlock();
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
int actionCount = 1 + (int)arc4random_uniform(3);
|
||||
for (int actionIdx = 0; actionIdx < actionCount; actionIdx++) {
|
||||
ActionBlock actionBlock = actionBlocks[(NSUInteger)arc4random_uniform((uint32_t)actionBlocks.count)];
|
||||
actionBlock(transaction);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)deleteRandomMessages:(NSUInteger)count thread:(TSThread *)thread
|
||||
+ (void)deleteRandomMessages:(NSUInteger)count
|
||||
thread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
DDLogInfo(@"%@ deleteRandomMessages: %zd", self.logTag, count);
|
||||
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
NSUInteger messageCount = [interactionsByThread numberOfItemsInGroup:thread.uniqueId];
|
||||
|
||||
NSMutableArray<NSNumber *> *messageIndices = [NSMutableArray new];
|
||||
for (NSUInteger messageIdx =0; messageIdx < messageCount; messageIdx++) {
|
||||
[messageIndices addObject:@(messageIdx)];
|
||||
}
|
||||
NSMutableArray<TSInteraction *> *interactions = [NSMutableArray new];
|
||||
for (NSUInteger i =0; i < count && messageIndices.count > 0; i++) {
|
||||
NSUInteger idx = (NSUInteger) arc4random_uniform((uint32_t) messageIndices.count);
|
||||
NSNumber *messageIdx = messageIndices[idx];
|
||||
[messageIndices removeObjectAtIndex:idx];
|
||||
|
||||
TSInteraction *_Nullable interaction =
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
NSUInteger messageCount = [interactionsByThread numberOfItemsInGroup:thread.uniqueId];
|
||||
|
||||
NSMutableArray<NSNumber *> *messageIndices = [NSMutableArray new];
|
||||
for (NSUInteger messageIdx = 0; messageIdx < messageCount; messageIdx++) {
|
||||
[messageIndices addObject:@(messageIdx)];
|
||||
}
|
||||
NSMutableArray<TSInteraction *> *interactions = [NSMutableArray new];
|
||||
for (NSUInteger i = 0; i < count && messageIndices.count > 0; i++) {
|
||||
NSUInteger idx = (NSUInteger)arc4random_uniform((uint32_t)messageIndices.count);
|
||||
NSNumber *messageIdx = messageIndices[idx];
|
||||
[messageIndices removeObjectAtIndex:idx];
|
||||
|
||||
TSInteraction *_Nullable interaction =
|
||||
[interactionsByThread objectAtIndex:messageIdx.unsignedIntegerValue inGroup:thread.uniqueId];
|
||||
OWSAssert(interaction);
|
||||
[interactions addObject:interaction];
|
||||
}
|
||||
|
||||
for (TSInteraction *interaction in interactions) {
|
||||
[interaction removeWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
OWSAssert(interaction);
|
||||
[interactions addObject:interaction];
|
||||
}
|
||||
|
||||
for (TSInteraction *interaction in interactions) {
|
||||
[interaction removeWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)deleteLastMessages:(NSUInteger)count thread:(TSThread *)thread
|
||||
+ (void)deleteLastMessages:(NSUInteger)count
|
||||
thread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
DDLogInfo(@"%@ deleteLastMessages", self.logTag);
|
||||
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
NSUInteger messageCount = (NSUInteger)[interactionsByThread numberOfItemsInGroup:thread.uniqueId];
|
||||
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
NSUInteger messageCount = (NSInteger)[interactionsByThread numberOfItemsInGroup:thread.uniqueId];
|
||||
|
||||
NSMutableArray<NSNumber *> *messageIndices = [NSMutableArray new];
|
||||
for (NSUInteger i = 0; i < count && i < messageCount; i++) {
|
||||
NSUInteger messageIdx = messageCount - (1 + i);
|
||||
[messageIndices addObject:@(messageIdx)];
|
||||
}
|
||||
NSMutableArray<TSInteraction *> *interactions = [NSMutableArray new];
|
||||
for (NSNumber *messageIdx in messageIndices) {
|
||||
TSInteraction *_Nullable interaction =
|
||||
[interactionsByThread objectAtIndex:messageIdx.unsignedIntegerValue inGroup:thread.uniqueId];
|
||||
OWSAssert(interaction);
|
||||
[interactions addObject:interaction];
|
||||
}
|
||||
for (TSInteraction *interaction in interactions) {
|
||||
[interaction removeWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
NSMutableArray<NSNumber *> *messageIndices = [NSMutableArray new];
|
||||
for (NSUInteger i = 0; i < count && i < messageCount; i++) {
|
||||
NSUInteger messageIdx = messageCount - (1 + i);
|
||||
[messageIndices addObject:@(messageIdx)];
|
||||
}
|
||||
NSMutableArray<TSInteraction *> *interactions = [NSMutableArray new];
|
||||
for (NSNumber *messageIdx in messageIndices) {
|
||||
TSInteraction *_Nullable interaction =
|
||||
[interactionsByThread objectAtIndex:messageIdx.unsignedIntegerValue inGroup:thread.uniqueId];
|
||||
OWSAssert(interaction);
|
||||
[interactions addObject:interaction];
|
||||
}
|
||||
for (TSInteraction *interaction in interactions) {
|
||||
[interaction removeWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)deleteRandomRecentMessages:(NSUInteger)count thread:(TSThread *)thread
|
||||
+ (void)deleteRandomRecentMessages:(NSUInteger)count
|
||||
thread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
DDLogInfo(@"%@ deleteRandomRecentMessages: %zd", self.logTag, count);
|
||||
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
NSInteger messageCount = (NSInteger) [interactionsByThread numberOfItemsInGroup:thread.uniqueId];
|
||||
|
||||
NSMutableArray<NSNumber *> *messageIndices = [NSMutableArray new];
|
||||
const NSInteger kRecentMessageCount = 10;
|
||||
for (NSInteger i =0; i < kRecentMessageCount; i++) {
|
||||
NSInteger messageIdx = messageCount - (1 + i);
|
||||
if (messageIdx >= 0) {
|
||||
[messageIndices addObject:@(messageIdx)];
|
||||
}
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
NSInteger messageCount = (NSInteger)[interactionsByThread numberOfItemsInGroup:thread.uniqueId];
|
||||
|
||||
NSMutableArray<NSNumber *> *messageIndices = [NSMutableArray new];
|
||||
const NSInteger kRecentMessageCount = 10;
|
||||
for (NSInteger i = 0; i < kRecentMessageCount; i++) {
|
||||
NSInteger messageIdx = messageCount - (1 + i);
|
||||
if (messageIdx >= 0) {
|
||||
[messageIndices addObject:@(messageIdx)];
|
||||
}
|
||||
NSMutableArray<TSInteraction *> *interactions = [NSMutableArray new];
|
||||
for (NSUInteger i =0; i < count && messageIndices.count > 0; i++) {
|
||||
NSUInteger idx = (NSUInteger) arc4random_uniform((uint32_t) messageIndices.count);
|
||||
NSNumber *messageIdx = messageIndices[idx];
|
||||
[messageIndices removeObjectAtIndex:idx];
|
||||
|
||||
TSInteraction *_Nullable interaction =
|
||||
}
|
||||
NSMutableArray<TSInteraction *> *interactions = [NSMutableArray new];
|
||||
for (NSUInteger i = 0; i < count && messageIndices.count > 0; i++) {
|
||||
NSUInteger idx = (NSUInteger)arc4random_uniform((uint32_t)messageIndices.count);
|
||||
NSNumber *messageIdx = messageIndices[idx];
|
||||
[messageIndices removeObjectAtIndex:idx];
|
||||
|
||||
TSInteraction *_Nullable interaction =
|
||||
[interactionsByThread objectAtIndex:messageIdx.unsignedIntegerValue inGroup:thread.uniqueId];
|
||||
OWSAssert(interaction);
|
||||
[interactions addObject:interaction];
|
||||
}
|
||||
for (TSInteraction *interaction in interactions) {
|
||||
[interaction removeWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
OWSAssert(interaction);
|
||||
[interactions addObject:interaction];
|
||||
}
|
||||
for (TSInteraction *interaction in interactions) {
|
||||
[interaction removeWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)insertAndDeleteNewOutgoingMessages:(NSUInteger)count thread:(TSThread *)thread
|
||||
+ (void)insertAndDeleteNewOutgoingMessages:(NSUInteger)count
|
||||
thread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
DDLogInfo(@"%@ insertAndDeleteNewOutgoingMessages: %zd", self.logTag, count);
|
||||
|
||||
|
@ -1299,28 +1325,28 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
for (NSUInteger i =0; i < count; i++) {
|
||||
NSString *text = [self randomText];
|
||||
OWSDisappearingMessagesConfiguration *configuration =
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId transaction:transaction];
|
||||
TSOutgoingMessage *message =
|
||||
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
messageBody:text
|
||||
attachmentIds:[NSMutableArray new]
|
||||
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)];
|
||||
DDLogError(@"%@ insertAndDeleteNewOutgoingMessages timestamp: %llu.", self.logTag, message.timestamp);
|
||||
[messages addObject:message];
|
||||
}
|
||||
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (TSOutgoingMessage *message in messages) {
|
||||
[message saveWithTransaction:transaction];
|
||||
}
|
||||
for (TSOutgoingMessage *message in messages) {
|
||||
[message removeWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
|
||||
for (TSOutgoingMessage *message in messages) {
|
||||
[message saveWithTransaction:transaction];
|
||||
}
|
||||
for (TSOutgoingMessage *message in messages) {
|
||||
[message removeWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)resurrectNewOutgoingMessages1:(NSUInteger)count thread:(TSThread *)thread
|
||||
+ (void)resurrectNewOutgoingMessages1:(NSUInteger)count
|
||||
thread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *)initialTransaction
|
||||
{
|
||||
DDLogInfo(@"%@ resurrectNewOutgoingMessages1.1: %zd", self.logTag, count);
|
||||
|
||||
|
@ -1328,22 +1354,22 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
for (NSUInteger i =0; i < count; i++) {
|
||||
NSString *text = [self randomText];
|
||||
OWSDisappearingMessagesConfiguration *configuration =
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId
|
||||
transaction:initialTransaction];
|
||||
TSOutgoingMessage *message =
|
||||
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
messageBody:text
|
||||
attachmentIds:[NSMutableArray new]
|
||||
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)];
|
||||
DDLogError(@"%@ resurrectNewOutgoingMessages1 timestamp: %llu.", self.logTag, message.timestamp);
|
||||
[messages addObject:message];
|
||||
}
|
||||
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (TSOutgoingMessage *message in messages) {
|
||||
[message saveWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
|
||||
for (TSOutgoingMessage *message in messages) {
|
||||
[message saveWithTransaction:initialTransaction];
|
||||
}
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
DDLogInfo(@"%@ resurrectNewOutgoingMessages1.2: %zd", self.logTag, count);
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection
|
||||
|
@ -1358,7 +1384,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
});
|
||||
}
|
||||
|
||||
+ (void)resurrectNewOutgoingMessages2:(NSUInteger)count thread:(TSThread *)thread
|
||||
+ (void)resurrectNewOutgoingMessages2:(NSUInteger)count
|
||||
thread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadWriteTransaction *)initialTransaction
|
||||
{
|
||||
DDLogInfo(@"%@ resurrectNewOutgoingMessages2.1: %zd", self.logTag, count);
|
||||
|
||||
|
@ -1366,23 +1394,23 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
for (NSUInteger i =0; i < count; i++) {
|
||||
NSString *text = [self randomText];
|
||||
OWSDisappearingMessagesConfiguration *configuration =
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId
|
||||
transaction:initialTransaction];
|
||||
TSOutgoingMessage *message =
|
||||
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:thread
|
||||
messageBody:text
|
||||
attachmentIds:[NSMutableArray new]
|
||||
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)];
|
||||
DDLogError(@"%@ resurrectNewOutgoingMessages2 timestamp: %llu.", self.logTag, message.timestamp);
|
||||
[messages addObject:message];
|
||||
}
|
||||
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (TSOutgoingMessage *message in messages) {
|
||||
[message updateWithMessageState:TSOutgoingMessageStateAttemptingOut transaction:transaction];
|
||||
[message saveWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
|
||||
for (TSOutgoingMessage *message in messages) {
|
||||
[message updateWithMessageState:TSOutgoingMessageStateAttemptingOut transaction:initialTransaction];
|
||||
[message saveWithTransaction:initialTransaction];
|
||||
}
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
DDLogInfo(@"%@ resurrectNewOutgoingMessages2.2: %zd", self.logTag, count);
|
||||
[TSStorageManager.sharedManager.dbReadWriteConnection
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
|
||||
#import "DataSource.h"
|
||||
#import "TSAttachment.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
@ -51,11 +53,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
+ (void)deleteAttachments;
|
||||
+ (NSString *)attachmentsFolder;
|
||||
|
||||
- (CGSize)imageSizeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (CGSize)imageSizeWithoutTransaction;
|
||||
- (CGSize)imageSize;
|
||||
|
||||
- (CGFloat)audioDurationSecondsWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (CGFloat)audioDurationSecondsWithoutTransaction;
|
||||
- (CGFloat)audioDurationSeconds;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -396,7 +396,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
}
|
||||
|
||||
- (CGSize)ensureCachedImageSizeWithTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction
|
||||
- (CGSize)imageSize
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
|
@ -408,68 +408,48 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
self.cachedImageWidth = @(imageSize.width);
|
||||
self.cachedImageHeight = @(imageSize.height);
|
||||
|
||||
void (^updateDataStore)() = ^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSString *collection = [[self class] collection];
|
||||
TSAttachmentStream *latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection];
|
||||
if (latestInstance) {
|
||||
latestInstance.cachedImageWidth = @(imageSize.width);
|
||||
latestInstance.cachedImageHeight = @(imageSize.height);
|
||||
[latestInstance saveWithTransaction:transaction];
|
||||
} else {
|
||||
// This message has not yet been saved; do nothing.
|
||||
OWSFail(@"%@ Attachment not yet saved.", self.logTag);
|
||||
}
|
||||
};
|
||||
|
||||
if (transaction) {
|
||||
updateDataStore(transaction);
|
||||
} else {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
updateDataStore(transaction);
|
||||
|
||||
NSString *collection = [[self class] collection];
|
||||
TSAttachmentStream *latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection];
|
||||
if (latestInstance) {
|
||||
latestInstance.cachedImageWidth = @(imageSize.width);
|
||||
latestInstance.cachedImageHeight = @(imageSize.height);
|
||||
[latestInstance saveWithTransaction:transaction];
|
||||
} else {
|
||||
// This message has not yet been saved; do nothing.
|
||||
OWSFail(@"%@ Attachment not yet saved.", self.logTag);
|
||||
}
|
||||
}];
|
||||
}
|
||||
});
|
||||
|
||||
return imageSize;
|
||||
}
|
||||
|
||||
- (CGSize)imageSizeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
OWSAssert(transaction);
|
||||
|
||||
return [self ensureCachedImageSizeWithTransaction:transaction];
|
||||
}
|
||||
|
||||
- (CGSize)imageSizeWithoutTransaction
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
return [self ensureCachedImageSizeWithTransaction:nil];
|
||||
}
|
||||
|
||||
- (CGFloat)calculateAudioDurationSeconds
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
OWSAssert([self isAudio]);
|
||||
|
||||
NSError *error;
|
||||
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:self.mediaURL error:&error];
|
||||
if (error && [error.domain isEqualToString:NSOSStatusErrorDomain]
|
||||
&& (error.code == kAudioFileInvalidFileError || error.code == kAudioFileStreamError_InvalidFile)) {
|
||||
// Ignore "invalid audio file" errors.
|
||||
return 0.f;
|
||||
}
|
||||
if (!error) {
|
||||
return (CGFloat)[audioPlayer duration];
|
||||
} else {
|
||||
OWSFail(@"Could not find audio duration: %@", self.mediaURL);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
// NSError *error;
|
||||
// AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:self.mediaURL error:&error];
|
||||
// if (error && [error.domain isEqualToString:NSOSStatusErrorDomain]
|
||||
// && (error.code == kAudioFileInvalidFileError || error.code == kAudioFileStreamError_InvalidFile)) {
|
||||
// // Ignore "invalid audio file" errors.
|
||||
// return 0.f;
|
||||
// }
|
||||
// if (!error) {
|
||||
// return (CGFloat)[audioPlayer duration];
|
||||
// } else {
|
||||
// OWSFail(@"Could not find audio duration: %@", self.mediaURL);
|
||||
// return 0;
|
||||
// }
|
||||
}
|
||||
|
||||
- (CGFloat)ensureCachedAudioDurationSecondsWithTransaction:(YapDatabaseReadWriteTransaction *_Nullable)transaction
|
||||
- (CGFloat)audioDurationSeconds
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
|
@ -480,46 +460,25 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
CGFloat audioDurationSeconds = [self calculateAudioDurationSeconds];
|
||||
self.cachedAudioDurationSeconds = @(audioDurationSeconds);
|
||||
|
||||
void (^updateDataStore)() = ^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
OWSAssert(transaction);
|
||||
|
||||
NSString *collection = [[self class] collection];
|
||||
TSAttachmentStream *latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection];
|
||||
if (latestInstance) {
|
||||
latestInstance.cachedAudioDurationSeconds = @(audioDurationSeconds);
|
||||
[latestInstance saveWithTransaction:transaction];
|
||||
} else {
|
||||
// This message has not yet been saved; do nothing.
|
||||
OWSFail(@"%@ Attachment not yet saved.", self.logTag);
|
||||
}
|
||||
};
|
||||
|
||||
if (transaction) {
|
||||
updateDataStore(transaction);
|
||||
} else {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
updateDataStore(transaction);
|
||||
NSString *collection = [[self class] collection];
|
||||
TSAttachmentStream *latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection];
|
||||
if (latestInstance) {
|
||||
latestInstance.cachedAudioDurationSeconds = @(audioDurationSeconds);
|
||||
[latestInstance saveWithTransaction:transaction];
|
||||
} else {
|
||||
// This message has not yet been saved or has been deleted; do nothing.
|
||||
// This isn't an error per se, but these race conditions should be
|
||||
// _very_ rare.
|
||||
OWSFail(@"%@ Attachment not yet saved.", self.logTag);
|
||||
}
|
||||
}];
|
||||
}
|
||||
});
|
||||
|
||||
return audioDurationSeconds;
|
||||
}
|
||||
|
||||
- (CGFloat)audioDurationSecondsWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
OWSAssert(transaction);
|
||||
|
||||
return [self ensureCachedAudioDurationSecondsWithTransaction:transaction];
|
||||
}
|
||||
|
||||
- (CGFloat)audioDurationSecondsWithoutTransaction
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
return [self ensureCachedAudioDurationSecondsWithTransaction:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -363,7 +363,9 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
|
|||
= (NSArray<TSOutgoingMessage *> *)[TSInteraction interactionsWithTimestamp:sentTimestamp
|
||||
ofClass:[TSOutgoingMessage class]
|
||||
withTransaction:transaction];
|
||||
OWSAssert(messages.count <= 1);
|
||||
if (messages.count > 1) {
|
||||
OWSFail(@"%@ More than one matching message with timestamp: %llu.", self.logTag, sentTimestamp);
|
||||
}
|
||||
if (messages.count > 0) {
|
||||
// TODO: We might also need to "mark as read by recipient" any older messages
|
||||
// from us in that thread. Or maybe this state should hang on the thread?
|
||||
|
|
Loading…
Reference in New Issue