Merge branch 'charlesmchen/newContactConversationsVsProfileWhitelist'

pull/1/head
Matthew Chen 8 years ago
commit c536f4d4b7

@ -176,7 +176,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
// we need to bump this constant. // we need to bump this constant.
// //
// We added a number of database views in v2.13.0. // We added a number of database views in v2.13.0.
NSString *kLastVersionWithDatabaseViewChange = @"2.13.0"; NSString *kLastVersionWithDatabaseViewChange = @"2.16.0";
BOOL mayNeedUpgrade = ([TSAccountManager isRegistered] && lastLaunchedAppVersion BOOL mayNeedUpgrade = ([TSAccountManager isRegistered] && lastLaunchedAppVersion
&& (!lastCompletedLaunchAppVersion || && (!lastCompletedLaunchAppVersion ||
[VersionMigrations isVersion:lastCompletedLaunchAppVersion [VersionMigrations isVersion:lastCompletedLaunchAppVersion

@ -43,6 +43,12 @@ extern const NSUInteger kOWSProfileManager_MaxAvatarDiameter;
#pragma mark - Profile Whitelist #pragma mark - Profile Whitelist
#ifdef DEBUG
// These methods are for debugging.
- (void)clearProfileWhitelist;
- (void)logProfileWhitelist;
#endif
- (void)addThreadToProfileWhitelist:(TSThread *)thread; - (void)addThreadToProfileWhitelist:(TSThread *)thread;
- (BOOL)isThreadInProfileWhitelist:(TSThread *)thread; - (BOOL)isThreadInProfileWhitelist:(TSThread *)thread;

@ -595,6 +595,53 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
#pragma mark - Profile Whitelist #pragma mark - Profile Whitelist
#ifdef DEBUG
- (void)clearProfileWhitelist
{
DDLogWarn(@"%@ Clearing the profile whitelist.", self.tag);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
[self.userProfileWhitelistCache removeAllObjects];
[self.groupProfileWhitelistCache removeAllObjects];
[self.dbConnection purgeCollection:kOWSProfileManager_UserWhitelistCollection];
[self.dbConnection purgeCollection:kOWSProfileManager_GroupWhitelistCollection];
OWSAssert(0 == [self.dbConnection numberOfKeysInCollection:kOWSProfileManager_UserWhitelistCollection]);
OWSAssert(0 == [self.dbConnection numberOfKeysInCollection:kOWSProfileManager_GroupWhitelistCollection]);
}
});
}
- (void)logProfileWhitelist
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
DDLogError(@"userProfileWhitelistCache: %zd", self.userProfileWhitelistCache.count);
DDLogError(@"groupProfileWhitelistCache: %zd", self.groupProfileWhitelistCache.count);
DDLogError(@"kOWSProfileManager_UserWhitelistCollection: %zd",
[self.dbConnection numberOfKeysInCollection:kOWSProfileManager_UserWhitelistCollection]);
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[transaction enumerateKeysInCollection:kOWSProfileManager_UserWhitelistCollection
usingBlock:^(NSString *_Nonnull key, BOOL *_Nonnull stop) {
DDLogError(@"\t profile whitelist user: %@", key);
}];
}];
DDLogError(@"kOWSProfileManager_GroupWhitelistCollection: %zd",
[self.dbConnection numberOfKeysInCollection:kOWSProfileManager_GroupWhitelistCollection]);
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[transaction enumerateKeysInCollection:kOWSProfileManager_GroupWhitelistCollection
usingBlock:^(NSString *_Nonnull key, BOOL *_Nonnull stop) {
DDLogError(@"\t profile whitelist group: %@", key);
}];
}];
}
});
}
#endif
- (void)addUserToProfileWhitelist:(NSString *)recipientId - (void)addUserToProfileWhitelist:(NSString *)recipientId
{ {
OWSAssert(recipientId.length > 0); OWSAssert(recipientId.length > 0);

@ -166,6 +166,19 @@ typedef enum : NSUInteger {
@property (nonatomic) TSThread *thread; @property (nonatomic) TSThread *thread;
@property (nonatomic) TSMessageAdapter *lastDeliveredMessage; @property (nonatomic) TSMessageAdapter *lastDeliveredMessage;
@property (nonatomic) YapDatabaseConnection *editingDatabaseConnection; @property (nonatomic) YapDatabaseConnection *editingDatabaseConnection;
// These two properties must be updated in lockstep.
//
// * The first (required) step is to update uiDatabaseConnection using beginLongLivedReadTransaction.
// * The second (required) step is to update messageMappings.
// * The third (optional) step is to update the messageMappings range using
// updateMessageMappingRangeOptions.
// * The steps must be done in strict order.
// * If we do any of the steps, we must do all of the required steps.
// * We can't use messageMappings in between the first and second steps; e.g.
// we can't do any layout, since that uses numberOfItemsInSection: and
// interactionAtIndexPath: which use the messageMappings.
// * If we do the third step, we must call resetContentAndLayout afterward.
@property (nonatomic) YapDatabaseConnection *uiDatabaseConnection; @property (nonatomic) YapDatabaseConnection *uiDatabaseConnection;
@property (nonatomic) YapDatabaseViewMappings *messageMappings; @property (nonatomic) YapDatabaseViewMappings *messageMappings;
@ -370,10 +383,10 @@ typedef enum : NSUInteger {
[[YapDatabaseViewMappings alloc] initWithGroups:@[ thread.uniqueId ] view:TSMessageDatabaseViewExtensionName]; [[YapDatabaseViewMappings alloc] initWithGroups:@[ thread.uniqueId ] view:TSMessageDatabaseViewExtensionName];
// We need to impose the range restrictions on the mappings immediately to avoid // We need to impose the range restrictions on the mappings immediately to avoid
// doing a great deal of unnecessary work and causing a perf hotspot. // doing a great deal of unnecessary work and causing a perf hotspot.
[self updateMessageMappingRangeOptions];
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[self.messageMappings updateWithTransaction:transaction]; [self.messageMappings updateWithTransaction:transaction];
}]; }];
[self updateMessageMappingRangeOptions];
[self updateShouldObserveDBModifications]; [self updateShouldObserveDBModifications];
self.page = 0; self.page = 0;
@ -1456,21 +1469,19 @@ typedef enum : NSUInteger {
// We convert large text messages to attachments // We convert large text messages to attachments
// which are presented as normal text messages. // which are presented as normal text messages.
const NSUInteger kOversizeTextMessageSizeThreshold = 16 * 1024; const NSUInteger kOversizeTextMessageSizeThreshold = 16 * 1024;
BOOL didAddToProfileWhitelist = [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
TSOutgoingMessage *message;
if ([text lengthOfBytesUsingEncoding:NSUTF8StringEncoding] >= kOversizeTextMessageSizeThreshold) { if ([text lengthOfBytesUsingEncoding:NSUTF8StringEncoding] >= kOversizeTextMessageSizeThreshold) {
SignalAttachment *attachment = SignalAttachment *attachment =
[SignalAttachment attachmentWithData:[text dataUsingEncoding:NSUTF8StringEncoding] [SignalAttachment attachmentWithData:[text dataUsingEncoding:NSUTF8StringEncoding]
dataUTI:SignalAttachment.kOversizeTextAttachmentUTI dataUTI:SignalAttachment.kOversizeTextAttachmentUTI
filename:nil]; filename:nil];
[self updateLastVisibleTimestamp:[ThreadUtil sendMessageWithAttachment:attachment message =
inThread:self.thread [ThreadUtil sendMessageWithAttachment:attachment inThread:self.thread messageSender:self.messageSender];
messageSender:self.messageSender]
.timestampForSorting];
} else { } else {
[self updateLastVisibleTimestamp:[ThreadUtil sendMessageWithText:text message = [ThreadUtil sendMessageWithText:text inThread:self.thread messageSender:self.messageSender];
inThread:self.thread
messageSender:self.messageSender]
.timestampForSorting];
} }
[self updateLastVisibleTimestamp:message.timestampForSorting];
self.lastMessageSentDate = [NSDate new]; self.lastMessageSentDate = [NSDate new];
[self clearUnreadMessagesIndicator]; [self clearUnreadMessagesIndicator];
@ -1481,6 +1492,9 @@ typedef enum : NSUInteger {
[self clearDraft]; [self clearDraft];
[self finishSendingMessage]; [self finishSendingMessage];
[((OWSMessagesToolbarContentView *)self.inputToolbar.contentView)ensureSubviews]; [((OWSMessagesToolbarContentView *)self.inputToolbar.contentView)ensureSubviews];
if (didAddToProfileWhitelist) {
[self ensureDynamicInteractions];
}
} }
} }
@ -2285,17 +2299,23 @@ typedef enum : NSUInteger {
- (void)updateMessageMappingRangeOptions - (void)updateMessageMappingRangeOptions
{ {
// The "page" length may have been increased by loading "prev" pages at the // The "old" range length may have been increased by insertions of new messages
// top of the window.
NSUInteger pageLength = kYapDatabasePageSize * (self.page + 1);
// The "old" length may have been increased by insertions of new messages
// at the bottom of the window. // at the bottom of the window.
NSUInteger oldLength = [self.messageMappings numberOfItemsInGroup:self.thread.uniqueId]; NSUInteger oldLength = [self.messageMappings numberOfItemsInGroup:self.thread.uniqueId];
NSUInteger newLength = MAX(pageLength, oldLength); // The "page-based" range length may have been increased by loading "prev" pages at the
// top of the window.
NSUInteger rangeLength;
while (YES) {
rangeLength = kYapDatabasePageSize * (self.page + 1);
if (rangeLength >= oldLength) {
break;
}
self.page = self.page + 1;
}
YapDatabaseViewRangeOptions *rangeOptions = YapDatabaseViewRangeOptions *rangeOptions =
[YapDatabaseViewRangeOptions flexibleRangeWithLength:newLength offset:0 from:YapDatabaseViewEnd]; [YapDatabaseViewRangeOptions flexibleRangeWithLength:rangeLength offset:0 from:YapDatabaseViewEnd];
rangeOptions.maxLength = MAX(newLength, kYapDatabaseRangeMaxLength); rangeOptions.maxLength = MAX(rangeLength, kYapDatabaseRangeMaxLength);
rangeOptions.minLength = kYapDatabaseRangeMinLength; rangeOptions.minLength = kYapDatabaseRangeMinLength;
[self.messageMappings setRangeOptions:rangeOptions forGroup:self.thread.uniqueId]; [self.messageMappings setRangeOptions:rangeOptions forGroup:self.thread.uniqueId];
@ -3166,12 +3186,18 @@ typedef enum : NSUInteger {
DDLogVerbose(@"Sending attachment. Size in bytes: %lu, contentType: %@", DDLogVerbose(@"Sending attachment. Size in bytes: %lu, contentType: %@",
(unsigned long)attachment.data.length, (unsigned long)attachment.data.length,
[attachment mimeType]); [attachment mimeType]);
[self updateLastVisibleTimestamp:[ThreadUtil sendMessageWithAttachment:attachment BOOL didAddToProfileWhitelist = [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
inThread:self.thread TSOutgoingMessage *message =
messageSender:self.messageSender] [ThreadUtil sendMessageWithAttachment:attachment inThread:self.thread messageSender:self.messageSender];
.timestampForSorting]; [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[message saveWithTransaction:transaction];
}];
[self updateLastVisibleTimestamp:message.timestampForSorting];
self.lastMessageSentDate = [NSDate new]; self.lastMessageSentDate = [NSDate new];
[self clearUnreadMessagesIndicator]; [self clearUnreadMessagesIndicator];
if (didAddToProfileWhitelist) {
[self ensureDynamicInteractions];
}
} }
- (NSURL *)videoTempFolder - (NSURL *)videoTempFolder
@ -4234,10 +4260,10 @@ typedef enum : NSUInteger {
// We need to `beginLongLivedReadTransaction` before we update our // We need to `beginLongLivedReadTransaction` before we update our
// mapping in order to jump to the most recent commit. // mapping in order to jump to the most recent commit.
[self.uiDatabaseConnection beginLongLivedReadTransaction]; [self.uiDatabaseConnection beginLongLivedReadTransaction];
[self updateMessageMappingRangeOptions];
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[self.messageMappings updateWithTransaction:transaction]; [self.messageMappings updateWithTransaction:transaction];
}]; }];
[self updateMessageMappingRangeOptions];
} }
self.messageAdapterCache = [[NSCache alloc] init]; self.messageAdapterCache = [[NSCache alloc] init];

@ -53,6 +53,16 @@ NS_ASSUME_NONNULL_BEGIN
actionBlock:^{ actionBlock:^{
[DebugUIMisc setManualCensorshipCircumventionEnabled:NO]; [DebugUIMisc setManualCensorshipCircumventionEnabled:NO];
}]]; }]];
#ifdef DEBUG
[items addObject:[OWSTableItem itemWithTitle:@"Clear Profile Whitelist"
actionBlock:^{
[OWSProfileManager.sharedManager clearProfileWhitelist];
}]];
[items addObject:[OWSTableItem itemWithTitle:@"Log Profile Whitelist"
actionBlock:^{
[OWSProfileManager.sharedManager logProfileWhitelist];
}]];
#endif
return [OWSTableSection sectionWithTitle:self.name items:items]; return [OWSTableSection sectionWithTitle:self.name items:items];
} }

@ -64,6 +64,7 @@ NS_ASSUME_NONNULL_BEGIN
return; return;
} }
[ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:thread];
[ThreadUtil sendMessageWithAttachment:self.attachment inThread:thread messageSender:self.messageSender]; [ThreadUtil sendMessageWithAttachment:self.attachment inThread:thread messageSender:self.messageSender];
[Environment messageThreadId:thread.uniqueId]; [Environment messageThreadId:thread.uniqueId];

@ -94,6 +94,13 @@ NS_ASSUME_NONNULL_BEGIN
firstUnseenInteractionTimestamp:(nullable NSNumber *)firstUnseenInteractionTimestamp firstUnseenInteractionTimestamp:(nullable NSNumber *)firstUnseenInteractionTimestamp
maxRangeSize:(int)maxRangeSize; maxRangeSize:(int)maxRangeSize;
// This method should be called right _before_ we send a message to a thread,
// since we want to auto-add contact threads to the profile whitelist if the
// conversation was initiated by the local user.
//
// Returns YES IFF the thread was just added to the profile whitelist.
+ (BOOL)addThreadToProfileWhitelistIfEmptyContactThread:(TSThread *)thread;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -4,6 +4,7 @@
#import "ThreadUtil.h" #import "ThreadUtil.h"
#import "OWSContactsManager.h" #import "OWSContactsManager.h"
#import "OWSProfileManager.h"
#import "Signal-Swift.h" #import "Signal-Swift.h"
#import "TSUnreadIndicatorInteraction.h" #import "TSUnreadIndicatorInteraction.h"
#import <SignalServiceKit/NSDate+millisecondTimeStamp.h> #import <SignalServiceKit/NSDate+millisecondTimeStamp.h>
@ -397,6 +398,13 @@ NS_ASSUME_NONNULL_BEGIN
const int kAddToContactsOfferOffset = -2; const int kAddToContactsOfferOffset = -2;
const int kUnreadIndicatorOfferOffset = -1; const int kUnreadIndicatorOfferOffset = -1;
// We want the offers to be the first interactions in their
// conversation's timeline, so we back-date them to slightly before
// the first message - or at an aribtrary old timestamp if the
// conversation has no messages.
long long startOfConversationTimestamp
= (long long)(firstMessage ? firstMessage.timestampForSorting : 1000);
if (existingBlockOffer && !shouldHaveBlockOffer) { if (existingBlockOffer && !shouldHaveBlockOffer) {
DDLogInfo(@"%@ Removing block offer: %@ (%llu)", DDLogInfo(@"%@ Removing block offer: %@ (%llu)",
self.tag, self.tag,
@ -406,10 +414,7 @@ NS_ASSUME_NONNULL_BEGIN
} else if (!existingBlockOffer && shouldHaveBlockOffer) { } else if (!existingBlockOffer && shouldHaveBlockOffer) {
DDLogInfo(@"Creating block offer for unknown contact"); DDLogInfo(@"Creating block offer for unknown contact");
// We want the block offer to be the first interaction in their uint64_t blockOfferTimestamp = (uint64_t)(startOfConversationTimestamp + kBlockOfferOffset);
// conversation's timeline, so we back-date it to slightly before
// the first incoming message (which we know is the first message).
uint64_t blockOfferTimestamp = (uint64_t)((long long)firstMessage.timestampForSorting + kBlockOfferOffset);
NSString *recipientId = ((TSContactThread *)thread).contactIdentifier; NSString *recipientId = ((TSContactThread *)thread).contactIdentifier;
TSMessage *offerMessage = TSMessage *offerMessage =
@ -434,11 +439,7 @@ NS_ASSUME_NONNULL_BEGIN
DDLogInfo(@"%@ Creating 'add to contacts' offer for unknown contact", self.tag); DDLogInfo(@"%@ Creating 'add to contacts' offer for unknown contact", self.tag);
// We want the offer to be the first interaction in their uint64_t offerTimestamp = (uint64_t)(startOfConversationTimestamp + kAddToContactsOfferOffset);
// conversation's timeline, so we back-date it to slightly before
// the first incoming message (which we know is the first message).
uint64_t offerTimestamp
= (uint64_t)((long long)firstMessage.timestampForSorting + kAddToContactsOfferOffset);
NSString *recipientId = ((TSContactThread *)thread).contactIdentifier; NSString *recipientId = ((TSContactThread *)thread).contactIdentifier;
TSMessage *offerMessage = [OWSAddToContactsOfferMessage addToContactsOfferMessage:offerTimestamp TSMessage *offerMessage = [OWSAddToContactsOfferMessage addToContactsOfferMessage:offerTimestamp
@ -462,11 +463,7 @@ NS_ASSUME_NONNULL_BEGIN
DDLogInfo(@"%@ Creating 'add to profile whitelist' offer", self.tag); DDLogInfo(@"%@ Creating 'add to profile whitelist' offer", self.tag);
// We want the offer to be the first interaction in their uint64_t offerTimestamp = (uint64_t)(startOfConversationTimestamp + kAddToProfileWhitelistOfferOffset);
// conversation's timeline, so we back-date it to slightly before
// the first incoming message (which we know is the first message).
uint64_t offerTimestamp
= (uint64_t)((long long)firstMessage.timestampForSorting + kAddToProfileWhitelistOfferOffset);
TSMessage *offerMessage = TSMessage *offerMessage =
[OWSAddToProfileWhitelistOfferMessage addToProfileWhitelistOfferMessage:offerTimestamp thread:thread]; [OWSAddToProfileWhitelistOfferMessage addToProfileWhitelistOfferMessage:offerTimestamp thread:thread];
@ -523,6 +520,24 @@ NS_ASSUME_NONNULL_BEGIN
return result; return result;
} }
+ (BOOL)addThreadToProfileWhitelistIfEmptyContactThread:(TSThread *)thread
{
OWSAssert(thread);
if (thread.isGroupThread) {
return NO;
}
if ([OWSProfileManager.sharedManager isThreadInProfileWhitelist:thread]) {
return NO;
}
if (!thread.hasEverHadMessage) {
[OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread];
return YES;
} else {
return NO;
}
}
#pragma mark - Logging #pragma mark - Logging
+ (NSString *)tag + (NSString *)tag

@ -40,6 +40,10 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
_errorMessageSchemaVersion = TSErrorMessageSchemaVersion; _errorMessageSchemaVersion = TSErrorMessageSchemaVersion;
if (self.isDynamicInteraction) {
self.read = YES;
}
return self; return self;
} }
@ -70,6 +74,10 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
_recipientId = recipientId; _recipientId = recipientId;
_errorMessageSchemaVersion = TSErrorMessageSchemaVersion; _errorMessageSchemaVersion = TSErrorMessageSchemaVersion;
if (self.isDynamicInteraction) {
self.read = YES;
}
return self; return self;
} }

@ -35,6 +35,10 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
_infoMessageSchemaVersion = TSInfoMessageSchemaVersion; _infoMessageSchemaVersion = TSInfoMessageSchemaVersion;
if (self.isDynamicInteraction) {
self.read = YES;
}
return self; return self;
} }
@ -56,6 +60,10 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
_messageType = infoMessage; _messageType = infoMessage;
_infoMessageSchemaVersion = TSInfoMessageSchemaVersion; _infoMessageSchemaVersion = TSInfoMessageSchemaVersion;
if (self.isDynamicInteraction) {
self.read = YES;
}
return self; return self;
} }

@ -1141,9 +1141,9 @@ NS_ASSUME_NONNULL_BEGIN
- (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread { - (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread {
__block NSUInteger numberOfItems; __block NSUInteger numberOfItems;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
numberOfItems = [[transaction ext:TSUnreadDatabaseViewExtensionName] numberOfItemsInAllGroups]; id databaseView = [transaction ext:TSUnreadDatabaseViewExtensionName];
numberOfItems = OWSAssert(databaseView);
numberOfItems - [[transaction ext:TSUnreadDatabaseViewExtensionName] numberOfItemsInGroup:thread.uniqueId]; numberOfItems = ([databaseView numberOfItemsInAllGroups] - [databaseView numberOfItemsInGroup:thread.uniqueId]);
}]; }];
return numberOfItems; return numberOfItems;

@ -144,7 +144,7 @@ NSString *const TSSecondaryDevicesDatabaseViewExtensionName = @"TSSecondaryDevic
[self registerMessageDatabaseViewWithName:TSUnseenDatabaseViewExtensionName [self registerMessageDatabaseViewWithName:TSUnseenDatabaseViewExtensionName
viewGrouping:viewGrouping viewGrouping:viewGrouping
version:@"1" version:@"2"
async:YES]; async:YES];
} }

@ -391,9 +391,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
#pragma mark - convenience methods #pragma mark - convenience methods
- (void)purgeCollection:(NSString *)collection { - (void)purgeCollection:(NSString *)collection {
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [self.dbReadWriteConnection purgeCollection:collection];
[transaction removeAllObjectsInCollection:collection];
}];
} }
- (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection { - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection {

@ -24,6 +24,8 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable PreKeyRecord *)preKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection; - (nullable PreKeyRecord *)preKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection;
- (nullable SignedPreKeyRecord *)signedPreKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection; - (nullable SignedPreKeyRecord *)signedPreKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection;
- (NSUInteger)numberOfKeysInCollection:(NSString *)collection;
#pragma mark - #pragma mark -
- (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection; - (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection;
@ -31,9 +33,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)removeObjectForKey:(NSString *)string inCollection:(NSString *)collection; - (void)removeObjectForKey:(NSString *)string inCollection:(NSString *)collection;
- (void)setInt:(int)integer forKey:(NSString *)key inCollection:(NSString *)collection; - (void)setInt:(int)integer forKey:(NSString *)key inCollection:(NSString *)collection;
- (void)setDate:(NSDate *)value forKey:(NSString *)key inCollection:(NSString *)collection; - (void)setDate:(NSDate *)value forKey:(NSString *)key inCollection:(NSString *)collection;
- (void)purgeCollection:(NSString *)collection;
- (int)incrementIntForKey:(NSString *)key inCollection:(NSString *)collection; - (int)incrementIntForKey:(NSString *)key inCollection:(NSString *)collection;
- (void)purgeCollection:(NSString *)collection;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -94,6 +94,15 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - #pragma mark -
- (NSUInteger)numberOfKeysInCollection:(NSString *)collection
{
__block NSUInteger result;
[self readWithBlock:^(YapDatabaseReadTransaction *transaction) {
result = [transaction numberOfKeysInCollection:collection];
}];
return result;
}
- (void)purgeCollection:(NSString *)collection - (void)purgeCollection:(NSString *)collection
{ {
[self readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [self readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {

Loading…
Cancel
Save