mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Merge branch 'mkirk/send-perf'
This commit is contained in:
commit
6764d3e754
|
@ -3887,13 +3887,14 @@ typedef enum : NSUInteger {
|
|||
inThread:self.thread
|
||||
quotedReplyModel:self.inputToolbar.quotedReply];
|
||||
} else {
|
||||
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
message = [ThreadUtil enqueueMessageWithText:text
|
||||
inThread:self.thread
|
||||
quotedReplyModel:self.inputToolbar.quotedReply
|
||||
transaction:transaction];
|
||||
}];
|
||||
}
|
||||
[self.conversationViewModel appendUnsavedOutgoingTextMessage:message];
|
||||
|
||||
[self messageWasSent:message];
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@class ConversationStyle;
|
||||
@class ConversationViewModel;
|
||||
@class OWSQuotedReplyModel;
|
||||
@class TSOutgoingMessage;
|
||||
@class TSThread;
|
||||
@class ThreadDynamicInteractions;
|
||||
|
||||
|
@ -101,6 +102,7 @@ typedef NS_ENUM(NSUInteger, ConversationUpdateItemType) {
|
|||
- (BOOL)canLoadMoreItems;
|
||||
|
||||
- (nullable NSIndexPath *)ensureLoadWindowContainsQuotedReply:(OWSQuotedReplyModel *)quotedReply;
|
||||
- (void)appendUnsavedOutgoingTextMessage:(TSOutgoingMessage *)outgoingMessage;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#import <SignalMessaging/OWSContactOffersInteraction.h>
|
||||
#import <SignalMessaging/OWSContactsManager.h>
|
||||
#import <SignalMessaging/OWSUnreadIndicator.h>
|
||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||
#import <SignalMessaging/ThreadUtil.h>
|
||||
#import <SignalServiceKit/OWSBlockingManager.h>
|
||||
#import <SignalServiceKit/OWSPrimaryStorage.h>
|
||||
|
@ -23,6 +24,7 @@
|
|||
#import <YapDatabase/YapDatabase.h>
|
||||
#import <YapDatabase/YapDatabaseAutoView.h>
|
||||
#import <YapDatabase/YapDatabaseViewChange.h>
|
||||
#import <YapDatabase/YapDatabaseViewChangePrivate.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
@ -165,6 +167,9 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
@property (nonatomic, nullable) ConversationProfileState *conversationProfileState;
|
||||
@property (nonatomic) BOOL hasTooManyOutgoingMessagesToBlockCached;
|
||||
|
||||
@property (nonatomic) NSArray<id<ConversationViewItem>> *persistedViewItems;
|
||||
@property (nonatomic) NSArray<TSOutgoingMessage *> *unsavedOutgoingMessages;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
@ -185,6 +190,8 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
|
||||
_thread = thread;
|
||||
_delegate = delegate;
|
||||
_persistedViewItems = @[];
|
||||
_unsavedOutgoingMessages = @[];
|
||||
self.focusMessageIdOnOpen = focusMessageIdOnOpen;
|
||||
|
||||
[self configure];
|
||||
|
@ -594,6 +601,40 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
return [self.delegate conversationViewModelDidUpdate:ConversationUpdate.minorUpdate];
|
||||
}
|
||||
|
||||
for (TSOutgoingMessage *unsavedOutgoingMessage in self.unsavedOutgoingMessages) {
|
||||
// unsavedOutgoingMessages should only exist for a short period (usually 30-50ms) before
|
||||
// they are saved and moved into the `persistedViewItems`
|
||||
OWSAssertDebug(
|
||||
unsavedOutgoingMessage.timestampForSorting >= ([NSDate ows_millisecondTimeStamp] - 1 * kSecondInMs));
|
||||
NSUInteger index = [rowChanges indexOfObjectPassingTest:^BOOL(
|
||||
YapDatabaseViewRowChange *_Nonnull rowChange, NSUInteger idx, BOOL *_Nonnull stop) {
|
||||
return [rowChange.collectionKey.key isEqualToString:unsavedOutgoingMessage.uniqueId];
|
||||
}];
|
||||
|
||||
if (index != NSNotFound) {
|
||||
// Replace the "Insert" RowChange to be an "Update" RowChange.
|
||||
YapDatabaseViewRowChange *rowChange = rowChanges[index];
|
||||
OWSAssertDebug(rowChange);
|
||||
|
||||
OWSLogVerbose(@"unsaved item has since been saved. collection key: %@", rowChange.collectionKey.key);
|
||||
|
||||
YapDatabaseViewRowChange *update =
|
||||
[YapDatabaseViewRowChange updateCollectionKey:rowChange.collectionKey
|
||||
inGroup:rowChange.originalGroup
|
||||
atIndex:rowChange.finalIndex
|
||||
withChanges:YapDatabaseViewChangedObject];
|
||||
|
||||
NSMutableArray<YapDatabaseViewRowChange *> *mutableRowChanges = [rowChanges mutableCopy];
|
||||
mutableRowChanges[index] = update;
|
||||
rowChanges = [mutableRowChanges copy];
|
||||
|
||||
// Remove the unsavedOutgoingViewItem since it now exists as a persistedViewItem
|
||||
NSMutableArray<TSOutgoingMessage *> *unsavedOutgoingMessages = [self.unsavedOutgoingMessages mutableCopy];
|
||||
[unsavedOutgoingMessages removeObject:unsavedOutgoingMessage];
|
||||
self.unsavedOutgoingMessages = [unsavedOutgoingMessages copy];
|
||||
}
|
||||
}
|
||||
|
||||
NSMutableArray<NSString *> *oldItemIdList = [NSMutableArray new];
|
||||
for (id<ConversationViewItem> viewItem in self.viewItems) {
|
||||
[oldItemIdList addObject:viewItem.itemId];
|
||||
|
@ -613,7 +654,7 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
[self reloadInteractionForViewItem:viewItem];
|
||||
[updatedItemSet addObject:viewItem.itemId];
|
||||
} else {
|
||||
OWSLogError(@"Update is missing view item");
|
||||
OWSFailDebug(@"Update is missing view item");
|
||||
hasMalformedRowChange = YES;
|
||||
}
|
||||
} else {
|
||||
|
@ -1165,23 +1206,25 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
[self ensureConversationProfileState];
|
||||
|
||||
__block BOOL hasError = NO;
|
||||
id<ConversationViewItem> (^tryToAddViewItem)(TSInteraction *, YapDatabaseReadTransaction *)
|
||||
= ^(TSInteraction *interaction, YapDatabaseReadTransaction *transaction) {
|
||||
OWSAssertDebug(interaction.uniqueId.length > 0);
|
||||
|
||||
id<ConversationViewItem> _Nullable viewItem = self.viewItemCache[interaction.uniqueId];
|
||||
if (!viewItem) {
|
||||
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:interaction
|
||||
isGroupThread:isGroupThread
|
||||
transaction:transaction
|
||||
conversationStyle:conversationStyle];
|
||||
}
|
||||
[viewItems addObject:viewItem];
|
||||
OWSAssertDebug(!viewItemCache[interaction.uniqueId]);
|
||||
viewItemCache[interaction.uniqueId] = viewItem;
|
||||
|
||||
return viewItem;
|
||||
};
|
||||
|
||||
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
id<ConversationViewItem> (^tryToAddViewItem)(TSInteraction *) = ^(TSInteraction *interaction) {
|
||||
OWSAssertDebug(interaction.uniqueId.length > 0);
|
||||
|
||||
id<ConversationViewItem> _Nullable viewItem = self.viewItemCache[interaction.uniqueId];
|
||||
if (!viewItem) {
|
||||
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:interaction
|
||||
isGroupThread:isGroupThread
|
||||
transaction:transaction
|
||||
conversationStyle:conversationStyle];
|
||||
}
|
||||
[viewItems addObject:viewItem];
|
||||
OWSAssertDebug(!viewItemCache[interaction.uniqueId]);
|
||||
viewItemCache[interaction.uniqueId] = viewItem;
|
||||
return viewItem;
|
||||
};
|
||||
|
||||
NSMutableArray<TSInteraction *> *interactions = [NSMutableArray new];
|
||||
NSMutableSet<NSString *> *interactionIds = [NSMutableSet new];
|
||||
|
||||
|
@ -1216,7 +1259,7 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
loadedInteractions:interactions
|
||||
canLoadMoreItems:canLoadMoreItems];
|
||||
if (offers && [interactionIds containsObject:offers.beforeInteractionId]) {
|
||||
id<ConversationViewItem> offersItem = tryToAddViewItem(offers);
|
||||
id<ConversationViewItem> offersItem = tryToAddViewItem(offers, transaction);
|
||||
if ([offersItem.interaction isKindOfClass:[OWSContactOffersInteraction class]]) {
|
||||
OWSContactOffersInteraction *oldOffers = (OWSContactOffersInteraction *)offersItem.interaction;
|
||||
BOOL didChange = (oldOffers.hasBlockOffer != offers.hasBlockOffer
|
||||
|
@ -1231,17 +1274,7 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
}
|
||||
|
||||
for (TSInteraction *interaction in interactions) {
|
||||
tryToAddViewItem(interaction);
|
||||
}
|
||||
|
||||
if (self.typingIndicatorsSender) {
|
||||
id<ConversationViewItem> _Nullable lastViewItem = viewItems.lastObject;
|
||||
uint64_t typingIndicatorTimestamp = (lastViewItem ? lastViewItem.interaction.timestamp + 1 : 1);
|
||||
TSInteraction *interaction =
|
||||
[[OWSTypingIndicatorInteraction alloc] initWithThread:self.thread
|
||||
timestamp:typingIndicatorTimestamp
|
||||
recipientId:self.typingIndicatorsSender];
|
||||
tryToAddViewItem(interaction);
|
||||
tryToAddViewItem(interaction, transaction);
|
||||
}
|
||||
}];
|
||||
|
||||
|
@ -1251,6 +1284,25 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
return [left.interaction compareForSorting:right.interaction];
|
||||
}];
|
||||
|
||||
if (self.unsavedOutgoingMessages.count > 0) {
|
||||
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
for (TSOutgoingMessage *outgoingMessage in self.unsavedOutgoingMessages) {
|
||||
tryToAddViewItem(outgoingMessage, transaction);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
if (self.typingIndicatorsSender) {
|
||||
OWSTypingIndicatorInteraction *typingIndicatorInteraction =
|
||||
[[OWSTypingIndicatorInteraction alloc] initWithThread:self.thread
|
||||
timestamp:[NSDate ows_millisecondTimeStamp]
|
||||
recipientId:self.typingIndicatorsSender];
|
||||
|
||||
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
tryToAddViewItem(typingIndicatorInteraction, transaction);
|
||||
}];
|
||||
}
|
||||
|
||||
// Flag to ensure that we only increment once per launch.
|
||||
if (hasError) {
|
||||
OWSLogWarn(@"incrementing version of: %@", TSMessageDatabaseViewExtensionName);
|
||||
|
@ -1491,6 +1543,20 @@ static const int kYapDatabaseRangeMinLength = 0;
|
|||
return !hasError;
|
||||
}
|
||||
|
||||
- (void)appendUnsavedOutgoingTextMessage:(TSOutgoingMessage *)outgoingMessage
|
||||
{
|
||||
// Because the message isn't yet saved, we don't have sufficient information to build
|
||||
// in-memory placeholder for message types more complex than plain text.
|
||||
OWSAssertDebug(outgoingMessage.attachmentIds.count == 0);
|
||||
OWSAssertDebug(outgoingMessage.contactShare == nil);
|
||||
|
||||
NSMutableArray<TSOutgoingMessage *> *unsavedOutgoingMessages = [self.unsavedOutgoingMessages mutableCopy];
|
||||
[unsavedOutgoingMessages addObject:outgoingMessage];
|
||||
self.unsavedOutgoingMessages = unsavedOutgoingMessages;
|
||||
|
||||
[self updateForTransientItems];
|
||||
}
|
||||
|
||||
// Whenever an interaction is modified, we need to reload it from the DB
|
||||
// and update the corresponding view item.
|
||||
- (void)reloadInteractionForViewItem:(id<ConversationViewItem>)viewItem
|
||||
|
|
|
@ -47,7 +47,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
+ (TSOutgoingMessage *)enqueueMessageWithText:(NSString *)text
|
||||
inThread:(TSThread *)thread
|
||||
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
transaction:(YapDatabaseReadTransaction *)transaction;
|
||||
|
||||
+ (TSOutgoingMessage *)enqueueMessageWithAttachment:(SignalAttachment *)attachment
|
||||
inThread:(TSThread *)thread
|
||||
|
|
|
@ -68,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
+ (TSOutgoingMessage *)enqueueMessageWithText:(NSString *)text
|
||||
inThread:(TSThread *)thread
|
||||
quotedReplyModel:(nullable OWSQuotedReplyModel *)quotedReplyModel
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
transaction:(YapDatabaseReadTransaction *)transaction
|
||||
{
|
||||
OWSDisappearingMessagesConfiguration *configuration =
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId transaction:transaction];
|
||||
|
@ -82,9 +82,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
expiresInSeconds:expiresInSeconds
|
||||
quotedMessage:[quotedReplyModel buildQuotedMessageForSending]];
|
||||
|
||||
[message saveWithTransaction:transaction];
|
||||
|
||||
[self.messageSenderJobQueue addMessage:message transaction:transaction];
|
||||
[BenchManager benchAsyncWithTitle:@"Saving outgoing message" block:^(void (^benchmarkCompletion)(void)) {
|
||||
// To avoid blocking the send flow, we dispatch an async write from within this read transaction
|
||||
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull writeTransaction) {
|
||||
[message saveWithTransaction:writeTransaction];
|
||||
[self.messageSenderJobQueue addMessage:message transaction:writeTransaction];
|
||||
}
|
||||
completionBlock:benchmarkCompletion];
|
||||
}];
|
||||
|
||||
return message;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue