|
|
@ -18,7 +18,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
|
|
|
|
|
|
|
@implementation ThreadOffersAndIndicators
|
|
|
|
@implementation ThreadDynamicInteractions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- (void)clearUnreadIndicatorState
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
self.unreadIndicatorPosition = nil;
|
|
|
|
|
|
|
|
self.firstUnseenInteractionTimestamp = nil;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
@ -26,7 +32,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
|
|
|
|
|
|
|
@implementation ThreadUtil
|
|
|
|
@implementation ThreadUtil
|
|
|
|
|
|
|
|
|
|
|
|
+ (void)sendMessageWithText:(NSString *)text inThread:(TSThread *)thread messageSender:(OWSMessageSender *)messageSender
|
|
|
|
+ (TSOutgoingMessage *)sendMessageWithText:(NSString *)text
|
|
|
|
|
|
|
|
inThread:(TSThread *)thread
|
|
|
|
|
|
|
|
messageSender:(OWSMessageSender *)messageSender
|
|
|
|
{
|
|
|
|
{
|
|
|
|
OWSAssert([NSThread isMainThread]);
|
|
|
|
OWSAssert([NSThread isMainThread]);
|
|
|
|
OWSAssert(text.length > 0);
|
|
|
|
OWSAssert(text.length > 0);
|
|
|
@ -48,10 +56,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
failure:^(NSError *error) {
|
|
|
|
failure:^(NSError *error) {
|
|
|
|
DDLogWarn(@"%@ Failed to deliver message with error: %@", self.tag, error);
|
|
|
|
DDLogWarn(@"%@ Failed to deliver message with error: %@", self.tag, error);
|
|
|
|
}];
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ (void)sendMessageWithAttachment:(SignalAttachment *)attachment
|
|
|
|
+ (TSOutgoingMessage *)sendMessageWithAttachment:(SignalAttachment *)attachment
|
|
|
|
inThread:(TSThread *)thread
|
|
|
|
inThread:(TSThread *)thread
|
|
|
|
messageSender:(OWSMessageSender *)messageSender
|
|
|
|
messageSender:(OWSMessageSender *)messageSender
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -79,9 +89,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
failure:^(NSError *error) {
|
|
|
|
failure:^(NSError *error) {
|
|
|
|
DDLogError(@"%@ Failed to send message attachment with error: %@", self.tag, error);
|
|
|
|
DDLogError(@"%@ Failed to send message attachment with error: %@", self.tag, error);
|
|
|
|
}];
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+ (ThreadOffersAndIndicators *)ensureThreadOffersAndIndicators:(TSThread *)thread
|
|
|
|
+ (ThreadDynamicInteractions *)ensureDynamicInteractionsForThread:(TSThread *)thread
|
|
|
|
storageManager:(TSStorageManager *)storageManager
|
|
|
|
storageManager:(TSStorageManager *)storageManager
|
|
|
|
contactsManager:(OWSContactsManager *)contactsManager
|
|
|
|
contactsManager:(OWSContactsManager *)contactsManager
|
|
|
|
blockingManager:(OWSBlockingManager *)blockingManager
|
|
|
|
blockingManager:(OWSBlockingManager *)blockingManager
|
|
|
@ -96,7 +108,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
OWSAssert(blockingManager);
|
|
|
|
OWSAssert(blockingManager);
|
|
|
|
OWSAssert(maxRangeSize > 0);
|
|
|
|
OWSAssert(maxRangeSize > 0);
|
|
|
|
|
|
|
|
|
|
|
|
ThreadOffersAndIndicators *result = [ThreadOffersAndIndicators new];
|
|
|
|
ThreadDynamicInteractions *result = [ThreadDynamicInteractions new];
|
|
|
|
|
|
|
|
|
|
|
|
[storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
[storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
|
|
const int kMaxBlockOfferOutgoingMessageCount = 10;
|
|
|
|
const int kMaxBlockOfferOutgoingMessageCount = 10;
|
|
|
@ -141,7 +153,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
} else if ([object isKindOfClass:[TSErrorMessage class]]) {
|
|
|
|
} else if ([object isKindOfClass:[TSErrorMessage class]]) {
|
|
|
|
TSErrorMessage *errorMessage = (TSErrorMessage *)object;
|
|
|
|
TSErrorMessage *errorMessage = (TSErrorMessage *)object;
|
|
|
|
OWSAssert(errorMessage.errorType == TSErrorMessageNonBlockingIdentityChange);
|
|
|
|
OWSAssert(errorMessage.errorType == TSErrorMessageNonBlockingIdentityChange);
|
|
|
|
[nonBlockingSafetyNumberChanges addObject:object];
|
|
|
|
[nonBlockingSafetyNumberChanges addObject:errorMessage];
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
DDLogError(@"Unexpected interaction type: %@", [object class]);
|
|
|
|
DDLogError(@"Unexpected interaction type: %@", [object class]);
|
|
|
|
OWSAssert(0);
|
|
|
|
OWSAssert(0);
|
|
|
@ -165,6 +177,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
firstUnseenInteractionTimestamp = @(firstUnseenInteraction.timestampForSorting);
|
|
|
|
firstUnseenInteractionTimestamp = @(firstUnseenInteraction.timestampForSorting);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
result.firstUnseenInteractionTimestamp = firstUnseenInteractionTimestamp;
|
|
|
|
|
|
|
|
|
|
|
|
TSIncomingMessage *firstIncomingMessage =
|
|
|
|
TSIncomingMessage *firstIncomingMessage =
|
|
|
|
[[transaction ext:TSThreadIncomingMessageDatabaseViewExtensionName] firstObjectInGroup:thread.uniqueId];
|
|
|
|
[[transaction ext:TSThreadIncomingMessageDatabaseViewExtensionName] firstObjectInGroup:thread.uniqueId];
|
|
|
@ -183,7 +196,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
__block BOOL hasMoreUnseenMessages = NO;
|
|
|
|
__block BOOL hasMoreUnseenMessages = NO;
|
|
|
|
__block TSInteraction *interactionAfterUnreadIndicator = nil;
|
|
|
|
__block TSInteraction *interactionAfterUnreadIndicator = nil;
|
|
|
|
NSUInteger missingUnseenSafetyNumberChangeCount = 0;
|
|
|
|
NSUInteger missingUnseenSafetyNumberChangeCount = 0;
|
|
|
|
if (firstUnseenInteractionTimestamp) {
|
|
|
|
if (firstUnseenInteractionTimestamp != nil) {
|
|
|
|
[[transaction ext:TSMessageDatabaseViewExtensionName]
|
|
|
|
[[transaction ext:TSMessageDatabaseViewExtensionName]
|
|
|
|
enumerateRowsInGroup:thread.uniqueId
|
|
|
|
enumerateRowsInGroup:thread.uniqueId
|
|
|
|
withOptions:NSEnumerationReverse
|
|
|
|
withOptions:NSEnumerationReverse
|
|
|
@ -199,13 +212,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ([object isKindOfClass:[TSUnreadIndicatorInteraction class]]) {
|
|
|
|
TSInteraction *interaction = (TSInteraction *)object;
|
|
|
|
// Ignore existing unread indicator, if any.
|
|
|
|
|
|
|
|
|
|
|
|
if (interaction.isDynamicInteraction) {
|
|
|
|
|
|
|
|
// Ignore dynamic interactions, if any.
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TSInteraction *interaction = (TSInteraction *)object;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (interaction.timestampForSorting
|
|
|
|
if (interaction.timestampForSorting
|
|
|
|
< firstUnseenInteractionTimestamp.unsignedLongLongValue) {
|
|
|
|
< firstUnseenInteractionTimestamp.unsignedLongLongValue) {
|
|
|
|
// By default we want the unread indicator to appear just before
|
|
|
|
// By default we want the unread indicator to appear just before
|
|
|
@ -251,7 +264,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
|
= (missingUnseenSafetyNumberChanges.count + nonBlockingSafetyNumberChanges.count);
|
|
|
|
= (missingUnseenSafetyNumberChanges.count + nonBlockingSafetyNumberChanges.count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result.firstUnseenInteractionTimestamp = firstUnseenInteractionTimestamp;
|
|
|
|
|
|
|
|
if (hasMoreUnseenMessages) {
|
|
|
|
if (hasMoreUnseenMessages) {
|
|
|
|
// The unread indicator is _before_ the last visible unseen message.
|
|
|
|
// The unread indicator is _before_ the last visible unseen message.
|
|
|
|
result.unreadIndicatorPosition = @(visibleUnseenMessageCount);
|
|
|
|
result.unreadIndicatorPosition = @(visibleUnseenMessageCount);
|
|
|
|