replace thread.lastMessageDate/archivalDate -> thread.lastSortId, thread.archivedAsOfSortId

Update migration accordingly

Date shown on home view cell is message.receivedAt
This commit is contained in:
Michael Kirk 2018-09-23 14:48:44 -06:00
parent c27d35f8f2
commit b281b37637
9 changed files with 96 additions and 98 deletions

View File

@ -2778,7 +2778,6 @@ typedef enum : NSUInteger {
OWSAssertIsOnMainThread();
OWSAssertDebug(message);
[self updateLastVisibleSortId:message.sortId];
self.lastMessageSentDate = [NSDate new];
[self clearUnreadMessagesIndicator];
self.inputToolbar.quotedReply = nil;
@ -3902,15 +3901,6 @@ typedef enum : NSUInteger {
self.hasUnreadMessages = numberOfUnreadMessages > 0;
}
- (void)updateLastVisibleSortId:(uint64_t)sortId
{
OWSAssertDebug(sortId > 0);
self.lastVisibleSortId = MAX(self.lastVisibleSortId, sortId);
[self ensureScrollDownButton];
}
- (void)markVisibleMessagesAsRead
{
if (self.presentedViewController) {

View File

@ -25,12 +25,14 @@ public class ThreadViewModel: NSObject {
@objc
public init(thread: TSThread, transaction: YapDatabaseReadTransaction) {
self.threadRecord = thread
self.lastMessageDate = thread.lastMessageDate()
self.isGroupThread = thread.isGroupThread()
self.name = thread.name()
self.isMuted = thread.isMuted
self.lastMessageText = thread.lastMessageText(transaction: transaction)
self.lastMessageForInbox = thread.lastInteractionForInbox(transaction: transaction)
let lastInteraction = thread.lastInteractionForInbox(transaction: transaction)
self.lastMessageForInbox = lastInteraction
self.lastMessageDate = lastInteraction?.receivedAtDate() ?? thread.creationDate
if let contactThread = thread as? TSContactThread {
self.contactIdentifier = contactThread.contactIdentifier()

View File

@ -16,6 +16,21 @@ class OWS110SortIdMigration: OWSDatabaseMigration {
// TODO batch this?
self.dbReadWriteConnection().readWrite { transaction in
var archivedThreads: [TSThread] = []
// get archived threads before migration
TSThread.enumerateCollectionObjects({ (object, _) in
guard let thread = object as? TSThread else {
owsFailDebug("unexpected object: \(type(of: object))")
return
}
if thread.isArchivedByLegacyTimestampForSorting {
archivedThreads.append(thread)
}
})
guard let legacySorting: YapDatabaseAutoViewTransaction = transaction.extension(TSMessageDatabaseViewExtensionName_Legacy) as? YapDatabaseAutoViewTransaction else {
owsFailDebug("legacySorting was unexpectedly nil")
return
@ -33,6 +48,14 @@ class OWS110SortIdMigration: OWSDatabaseMigration {
Logger.debug("thread: \(interaction.uniqueThreadId), timestampForLegacySorting:\(interaction.timestampForLegacySorting()), sortId: \(interaction.sortId)")
}
}
Logger.info("re-archiving \(archivedThreads.count) threads which were previously archived")
for archivedThread in archivedThreads {
// latestMessageSortId will have been modified by saving all
// the interactions above, make sure we get the latest value.
archivedThread.reload(with: transaction)
archivedThread.archiveThread(with: transaction)
}
}
completion()

View File

@ -18,6 +18,8 @@ NS_ASSUME_NONNULL_BEGIN
// YES IFF this thread has ever had a message.
@property (nonatomic) BOOL hasEverHadMessage;
@property (nonatomic, readonly) NSDate *creationDate;
@property (nonatomic, readonly) BOOL isArchivedByLegacyTimestampForSorting;
/**
* Whether the object is a group thread or not.
@ -71,12 +73,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
/**
* Returns the latest date of a message in the thread or the thread creation date if there are no messages in that
*thread.
*
* @return The date of the last message or thread creation date.
* @return the latest sortId of a message in the thread or 0 if there are no messages in that
* thread.
*/
- (NSDate *)lastMessageDate;
@property (nonatomic, readonly) uint64_t latestMessageSortId;
/**
* Returns the string that will be displayed typically in a conversations view as a preview of the last message
@ -101,31 +101,19 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark Archival
/**
* Returns the last date at which a string was archived or nil if the thread was never archived or brought back to the
*inbox.
*
* @return Last archival date.
* @return YES if no new messages have been sent or received since the thread was last archived.
*/
- (nullable NSDate *)archivalDate;
- (BOOL)isArchived;
/**
* Archives a thread with the current date.
* Archives a thread
*
* @param transaction Database transaction.
*/
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
/**
* Archives a thread with the reference date. This is currently only used for migrating older data that has already
* been archived.
*
* @param transaction Database transaction.
* @param date Date at which the thread was archived.
*/
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction referenceDate:(NSDate *)date;
/**
* Unarchives a thread that was archived previously.
* Unarchives a thread
*
* @param transaction Database transaction.
*/

View File

@ -22,9 +22,11 @@ NS_ASSUME_NONNULL_BEGIN
@interface TSThread ()
@property (nonatomic) NSDate *creationDate;
@property (nonatomic, copy, nullable) NSDate *archivalDate;
@property (nonatomic, nullable) NSString *conversationColorName;
@property (nonatomic, nullable) NSDate *lastMessageDate;
@property (nonatomic) uint64_t latestMessageSortId;
@property (nonatomic) uint64_t archivedAsOfMessageSortId;
@property (nonatomic, copy, nullable) NSString *messageDraft;
@property (atomic, nullable) NSDate *mutedUntilDate;
@ -43,8 +45,6 @@ NS_ASSUME_NONNULL_BEGIN
self = [super initWithUniqueId:uniqueId];
if (self) {
_archivalDate = nil;
_lastMessageDate = nil;
_creationDate = [NSDate date];
_messageDraft = nil;
@ -76,7 +76,12 @@ NS_ASSUME_NONNULL_BEGIN
_conversationColorName = [self.class stableConversationColorNameForString:self.uniqueId];
}
}
NSDate *_Nullable lastMessageDate = [coder decodeObjectOfClass:NSDate.class forKey:@"lastMessageDate"];
NSDate *_Nullable archivalDate = [coder decodeObjectOfClass:NSDate.class forKey:@"archivalDate"];
_isArchivedByLegacyTimestampForSorting =
[self.class legacyIsArchivedWithLastMessageDate:lastMessageDate archivalDate:archivalDate];
return self;
}
@ -300,14 +305,6 @@ NS_ASSUME_NONNULL_BEGIN
return last;
}
- (NSDate *)lastMessageDate {
if (_lastMessageDate) {
return _lastMessageDate;
} else {
return _creationDate;
}
}
- (NSString *)lastMessageTextWithTransaction:(YapDatabaseReadTransaction *)transaction
{
TSInteraction *interaction = [self lastInteractionForInboxWithTransaction:transaction];
@ -354,12 +351,8 @@ NS_ASSUME_NONNULL_BEGIN
}
self.hasEverHadMessage = YES;
// MJK FIXME - this needs to use sortId
NSDate *lastMessageDate = lastMessage.dateForLegacySorting;
if (!_lastMessageDate || [lastMessageDate timeIntervalSinceDate:self.lastMessageDate] > 0) {
_lastMessageDate = lastMessageDate;
if (lastMessage.sortId > self.latestMessageSortId) {
self.latestMessageSortId = lastMessage.sortId;
[self saveWithTransaction:transaction];
}
}
@ -384,30 +377,46 @@ NS_ASSUME_NONNULL_BEGIN
}
}
#pragma mark Archival
#pragma mark - Archival
- (nullable NSDate *)archivalDate
- (BOOL)isArchived
{
return _archivalDate;
return self.archivedAsOfMessageSortId >= self.latestMessageSortId;
}
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction {
[self archiveThreadWithTransaction:transaction referenceDate:[NSDate date]];
+ (BOOL)legacyIsArchivedWithLastMessageDate:(nullable NSDate *)lastMessageDate
archivalDate:(nullable NSDate *)archivalDate
{
if (!archivalDate) {
return NO;
}
if (!lastMessageDate) {
return YES;
}
return [archivalDate compare:lastMessageDate] != NSOrderedAscending;
}
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction referenceDate:(NSDate *)date {
- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(TSThread *thread) {
thread.archivedAsOfMessageSortId = self.latestMessageSortId;
}];
[self markAllAsReadWithTransaction:transaction];
_archivalDate = date;
[self saveWithTransaction:transaction];
}
- (void)unarchiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction {
_archivalDate = nil;
[self saveWithTransaction:transaction];
- (void)unarchiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(TSThread *thread) {
thread.archivedAsOfMessageSortId = 0;
}];
}
#pragma mark Drafts
#pragma mark - Drafts
- (NSString *)currentDraftWithTransaction:(YapDatabaseReadTransaction *)transaction {
TSThread *thread = [TSThread fetchObjectWithUniqueID:self.uniqueId transaction:transaction];

View File

@ -170,7 +170,7 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value)
[super saveWithTransaction:transaction];
TSThread *fetchedThread = [TSThread fetchObjectWithUniqueID:self.uniqueThreadId transaction:transaction];
TSThread *fetchedThread = [self threadWithTransaction:transaction];
[fetchedThread updateWithLastMessage:self transaction:transaction];
}

View File

@ -293,13 +293,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
}
}
if (thread.archivalDate) {
return ([self threadShouldBeInInbox:thread]) ? TSInboxGroup : TSArchiveGroup;
} else if (thread.archivalDate) {
return TSArchiveGroup;
} else {
return TSInboxGroup;
}
return thread.isArchived ? TSArchiveGroup : TSInboxGroup;
}];
YapDatabaseViewSorting *viewSorting = [self threadSorting];
@ -315,29 +309,6 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
[storage asyncRegisterExtension:databaseView withName:TSThreadDatabaseViewExtensionName];
}
/**
* Determines whether a thread belongs to the archive or inbox
*
* @param thread TSThread
*
* @return Inbox if true, Archive if false
*/
+ (BOOL)threadShouldBeInInbox:(TSThread *)thread {
NSDate *lastMessageDate = thread.lastMessageDate;
NSDate *archivalDate = thread.archivalDate;
if (lastMessageDate && archivalDate) { // this is what is called
return ([lastMessageDate timeIntervalSinceDate:archivalDate] > 0)
? YES
: NO; // if there hasn't been a new message since the archive date, it's in the archive. an issue is
// that empty threads are always given with a lastmessage date of the present on every launch
} else if (archivalDate) {
return NO;
}
return YES;
}
+ (YapDatabaseViewSorting *)threadSorting {
return [YapDatabaseViewSorting withObjectBlock:^NSComparisonResult(YapDatabaseReadTransaction *transaction,
NSString *group,
@ -358,7 +329,11 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
TSThread *thread1 = (TSThread *)object1;
TSThread *thread2 = (TSThread *)object2;
if ([group isEqualToString:TSArchiveGroup] || [group isEqualToString:TSInboxGroup]) {
return [thread1.lastMessageDate compare:thread2.lastMessageDate];
if (thread1.latestMessageSortId == 0 && thread2.latestMessageSortId == 0) {
return [thread1.creationDate compare:thread2.creationDate];
}
return [@(thread1.latestMessageSortId) compare:@(thread2.latestMessageSortId)];
}
return NSOrderedSame;

View File

@ -95,6 +95,7 @@ NS_ASSUME_NONNULL_BEGIN
* Assign the latest persisted values from the database.
*/
- (void)reload;
- (void)reloadWithTransaction:(YapDatabaseReadTransaction *)transaction;
/**
* Saves the object with the shared readWrite connection - does not block.

View File

@ -218,9 +218,19 @@ NS_ASSUME_NONNULL_BEGIN
}
}
#pragma mark Reload
- (void)reload
{
TSYapDatabaseObject *latest = [[self class] fetchObjectWithUniqueID:self.uniqueId];
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[self reloadWithTransaction:transaction];
}];
}
- (void)reloadWithTransaction:(YapDatabaseReadTransaction *)transaction
{
TSYapDatabaseObject *latest = [[self class] fetchObjectWithUniqueID:self.uniqueId transaction:transaction];
if (!latest) {
OWSFailDebug(@"`latest` was unexpectedly nil");
return;