// // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // #import "OWSDisappearingMessagesConfiguration.h" #import "NSDate+OWS.h" NS_ASSUME_NONNULL_BEGIN // 1 day. const uint32_t OWSDisappearingMessagesConfigurationDefaultExpirationDuration = kDayInterval; @interface OWSDisappearingMessagesConfiguration () // Transient record lifecycle attributes. @property (atomic) NSDictionary *originalDictionaryValue; @property (atomic, getter=isNewRecord) BOOL newRecord; @end @implementation OWSDisappearingMessagesConfiguration - (instancetype)initDefaultWithThreadId:(NSString *)threadId { return [self initWithThreadId:threadId enabled:NO durationSeconds:OWSDisappearingMessagesConfigurationDefaultExpirationDuration]; } - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; _originalDictionaryValue = [self dictionaryValue]; _newRecord = NO; return self; } - (instancetype)initWithThreadId:(NSString *)threadId enabled:(BOOL)isEnabled durationSeconds:(uint32_t)seconds { self = [super initWithUniqueId:threadId]; if (!self) { return self; } _enabled = isEnabled; _durationSeconds = seconds; _originalDictionaryValue = [NSDictionary new]; _newRecord = YES; return self; } + (instancetype)fetchOrCreateDefaultWithThreadId:(NSString *)threadId { OWSDisappearingMessagesConfiguration *savedConfiguration = [self fetchObjectWithUniqueID:threadId]; if (savedConfiguration) { return savedConfiguration; } else { return [[self alloc] initDefaultWithThreadId:threadId]; } } + (NSString *)stringForDurationSeconds:(uint32_t)durationSeconds { NSString *amountFormat; uint32_t duration; uint32_t secondsPerMinute = 60; uint32_t secondsPerHour = secondsPerMinute * 60; uint32_t secondsPerDay = secondsPerHour * 24; uint32_t secondsPerWeek = secondsPerDay * 7; if (durationSeconds < secondsPerMinute) { // XX Seconds amountFormat = NSLocalizedString(@"TIME_AMOUNT_SECONDS", @"{{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds; } else if (durationSeconds < secondsPerMinute * 1.5) { // 1 Minute amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_MINUTE", @"{{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds / secondsPerMinute; } else if (durationSeconds < secondsPerHour) { // Multiple Minutes amountFormat = NSLocalizedString(@"TIME_AMOUNT_MINUTES", @"{{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds / secondsPerMinute; } else if (durationSeconds < secondsPerHour * 1.5) { // 1 Hour amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_HOUR", @"{{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds / secondsPerHour; } else if (durationSeconds < secondsPerDay) { // Multiple Hours amountFormat = NSLocalizedString(@"TIME_AMOUNT_HOURS", @"{{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds / secondsPerHour; } else if (durationSeconds < secondsPerDay * 1.5) { // 1 Day amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_DAY", @"{{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{1 day}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds / secondsPerDay; } else if (durationSeconds < secondsPerWeek) { // Multiple Days amountFormat = NSLocalizedString(@"TIME_AMOUNT_DAYS", @"{{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{5 days}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds / secondsPerDay; } else if (durationSeconds < secondsPerWeek * 1.5) { // 1 Week amountFormat = NSLocalizedString(@"TIME_AMOUNT_SINGLE_WEEK", @"{{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{1 week}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds / secondsPerWeek; } else { // Multiple weeks amountFormat = NSLocalizedString(@"TIME_AMOUNT_WEEKS", @"{{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages " @"expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings"); duration = durationSeconds / secondsPerWeek; } return [NSString stringWithFormat:amountFormat, [NSNumberFormatter localizedStringFromNumber:@(duration) numberStyle:NSNumberFormatterNoStyle]]; } + (NSArray *)validDurationsSeconds { return @[ @(5), @(10), @(30), @(60), @(300), @(1800), @(3600), @(21600), @(43200), @(86400), @(604800) ]; } - (NSUInteger)durationIndex { return [[self.class validDurationsSeconds] indexOfObject:@(self.durationSeconds)]; } - (NSString *)durationString { return [self.class stringForDurationSeconds:self.durationSeconds]; } #pragma mark - Dirty Tracking + (MTLPropertyStorage)storageBehaviorForPropertyWithKey:(NSString *)propertyKey { // Don't persist transient properties if ([propertyKey isEqualToString:@"originalDictionaryValue"] ||[propertyKey isEqualToString:@"newRecord"]) { return MTLPropertyStorageNone; } else { return [super storageBehaviorForPropertyWithKey:propertyKey]; } } - (BOOL)dictionaryValueDidChange { return ![self.originalDictionaryValue isEqual:[self dictionaryValue]]; } - (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction { [super saveWithTransaction:transaction]; self.originalDictionaryValue = [self dictionaryValue]; self.newRecord = NO; } @end NS_ASSUME_NONNULL_END