unread indicator uses sortId

- removed timestamp parameter. This wasn't totally obvious, previously we were tracking two pieces of state

1. `unreadIndicator.firstUnseenTimestamp`:
    the first unseen timestamp for a conversation that exists in the database
2. `unreadIndicator.timestamp`:
    the timestamp of the first interaction *after* the unread indicator that fits in the loading window

We don't actually need to track `2` because it was only used in a comparison like:

   viewItem.interaction.timestampForSorting >= unreadIndicator.timestamp

But by definition, unreadIndicator.firstUnseenTimestamp is always less than or
equal to unreadIndicator.timestamp. Put into terms of the `sortId` corallary,
the sortId of the first unseen interaction in the database is always less than
or equal to the sortId of the first unseen interaction that fits in the loading
window.

In other words, there's no situation where

   viewItem.interaction.sortId >= unreadIndicator.firstUnseenSortId
pull/1/head
Michael Kirk 7 years ago
parent 3240e0d9d0
commit 6f8eddc955

@ -4958,20 +4958,15 @@ typedef enum : NSUInteger {
&& !((id<OWSReadTracking>)viewItem.interaction).wasRead); && !((id<OWSReadTracking>)viewItem.interaction).wasRead);
if (isItemUnread && !unreadIndicator && !hasPlacedUnreadIndicator && !self.hasClearedUnreadMessagesIndicator) { if (isItemUnread && !unreadIndicator && !hasPlacedUnreadIndicator && !self.hasClearedUnreadMessagesIndicator) {
unreadIndicator = unreadIndicator = [[OWSUnreadIndicator alloc] initWithFirstUnseenSortId:viewItem.interaction.sortId
[[OWSUnreadIndicator alloc] initUnreadIndicatorWithTimestamp:viewItem.interaction.timestamp
hasMoreUnseenMessages:NO hasMoreUnseenMessages:NO
missingUnseenSafetyNumberChangeCount:0 missingUnseenSafetyNumberChangeCount:0
unreadIndicatorPosition:0 unreadIndicatorPosition:0];
firstUnseenInteractionTimestamp:viewItem.interaction.timestamp];
} }
// Place the unread indicator onto the first appropriate view item, // Place the unread indicator onto the first appropriate view item,
// if any. // if any.
// MJK FIXME - use sortId if (unreadIndicator && viewItem.interaction.sortId >= unreadIndicator.firstUnseenSortId) {
// I'm not sure why we need a comparison here, vs. an equality. Maybe if the first unread
// message is deleted, we'd need to be sure everything still works.
if (unreadIndicator && viewItem.interaction.timestampForLegacySorting >= unreadIndicator.timestamp) {
viewItem.unreadIndicator = unreadIndicator; viewItem.unreadIndicator = unreadIndicator;
unreadIndicator = nil; unreadIndicator = nil;
hasPlacedUnreadIndicator = YES; hasPlacedUnreadIndicator = YES;

@ -6,14 +6,11 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSUnreadIndicator : NSObject @interface OWSUnreadIndicator : NSObject
// MJK FIXME - do we need this timestamp column?
@property (nonatomic, readonly) uint64_t timestamp;
@property (nonatomic, readonly) BOOL hasMoreUnseenMessages; @property (nonatomic, readonly) BOOL hasMoreUnseenMessages;
@property (nonatomic, readonly) NSUInteger missingUnseenSafetyNumberChangeCount; @property (nonatomic, readonly) NSUInteger missingUnseenSafetyNumberChangeCount;
// The timestamp of the oldest unseen message. // The sortId of the oldest unseen message.
// //
// Once we enter messages view, we mark all messages read, so we need // Once we enter messages view, we mark all messages read, so we need
// a snapshot of what the first unread message was when we entered the // a snapshot of what the first unread message was when we entered the
@ -21,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
// repeatedly. The unread indicator should continue to show up until // repeatedly. The unread indicator should continue to show up until
// it has been cleared, at which point hideUnreadMessagesIndicator is // it has been cleared, at which point hideUnreadMessagesIndicator is
// YES in ensureDynamicInteractionsForThread:... // YES in ensureDynamicInteractionsForThread:...
@property (nonatomic, readonly) uint64_t firstUnseenInteractionTimestamp; @property (nonatomic, readonly) uint64_t firstUnseenSortId;
// The index of the unseen indicator, counting from the _end_ of the conversation // The index of the unseen indicator, counting from the _end_ of the conversation
// history. // history.
@ -33,11 +30,10 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
- (instancetype)initUnreadIndicatorWithTimestamp:(uint64_t)timestamp - (instancetype)initWithFirstUnseenSortId:(uint64_t)firstUnseenSortId
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:(NSInteger)unreadIndicatorPosition unreadIndicatorPosition:(NSInteger)unreadIndicatorPosition NS_DESIGNATED_INITIALIZER;
firstUnseenInteractionTimestamp:(uint64_t)firstUnseenInteractionTimestamp NS_DESIGNATED_INITIALIZER;
@end @end

@ -8,11 +8,10 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSUnreadIndicator @implementation OWSUnreadIndicator
- (instancetype)initUnreadIndicatorWithTimestamp:(uint64_t)timestamp - (instancetype)initWithFirstUnseenSortId:(uint64_t)firstUnseenSortId
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:(NSInteger)unreadIndicatorPosition unreadIndicatorPosition:(NSInteger)unreadIndicatorPosition
firstUnseenInteractionTimestamp:(uint64_t)firstUnseenInteractionTimestamp
{ {
self = [super init]; self = [super init];
@ -20,11 +19,10 @@ NS_ASSUME_NONNULL_BEGIN
return self; return self;
} }
_timestamp = timestamp; _firstUnseenSortId = firstUnseenSortId;
_hasMoreUnseenMessages = hasMoreUnseenMessages; _hasMoreUnseenMessages = hasMoreUnseenMessages;
_missingUnseenSafetyNumberChangeCount = missingUnseenSafetyNumberChangeCount; _missingUnseenSafetyNumberChangeCount = missingUnseenSafetyNumberChangeCount;
_unreadIndicatorPosition = unreadIndicatorPosition; _unreadIndicatorPosition = unreadIndicatorPosition;
_firstUnseenInteractionTimestamp = firstUnseenInteractionTimestamp;
return self; return self;
} }
@ -40,7 +38,8 @@ NS_ASSUME_NONNULL_BEGIN
} }
OWSUnreadIndicator *other = object; OWSUnreadIndicator *other = object;
return (self.timestamp == other.timestamp && self.hasMoreUnseenMessages == other.hasMoreUnseenMessages return (self.firstUnseenSortId == other.firstUnseenSortId
&& self.hasMoreUnseenMessages == other.hasMoreUnseenMessages
&& self.missingUnseenSafetyNumberChangeCount == other.missingUnseenSafetyNumberChangeCount && self.missingUnseenSafetyNumberChangeCount == other.missingUnseenSafetyNumberChangeCount
&& self.unreadIndicatorPosition == other.unreadIndicatorPosition); && self.unreadIndicatorPosition == other.unreadIndicatorPosition);
} }

@ -363,15 +363,14 @@ NS_ASSUME_NONNULL_BEGIN
// have been marked as read. // have been marked as read.
// //
// IFF this variable is non-null, there are unseen messages in the thread. // IFF this variable is non-null, there are unseen messages in the thread.
NSNumber *_Nullable firstUnseenInteractionTimestamp = nil; NSNumber *_Nullable firstUnseenSortId = nil;
if (lastUnreadIndicator) { if (lastUnreadIndicator) {
firstUnseenInteractionTimestamp = @(lastUnreadIndicator.firstUnseenInteractionTimestamp); firstUnseenSortId = @(lastUnreadIndicator.firstUnseenSortId);
} else { } else {
TSInteraction *_Nullable firstUnseenInteraction = TSInteraction *_Nullable firstUnseenInteraction =
[[TSDatabaseView unseenDatabaseViewExtension:transaction] firstObjectInGroup:thread.uniqueId]; [[TSDatabaseView unseenDatabaseViewExtension:transaction] firstObjectInGroup:thread.uniqueId];
if (firstUnseenInteraction) { if (firstUnseenInteraction) {
// MJK FIXME - use sortId firstUnseenSortId = @(firstUnseenInteraction.sortId);
firstUnseenInteractionTimestamp = @(firstUnseenInteraction.timestampForLegacySorting);
} }
} }
@ -532,7 +531,7 @@ NS_ASSUME_NONNULL_BEGIN
blockingSafetyNumberChanges:blockingSafetyNumberChanges blockingSafetyNumberChanges:blockingSafetyNumberChanges
nonBlockingSafetyNumberChanges:nonBlockingSafetyNumberChanges nonBlockingSafetyNumberChanges:nonBlockingSafetyNumberChanges
hideUnreadMessagesIndicator:hideUnreadMessagesIndicator hideUnreadMessagesIndicator:hideUnreadMessagesIndicator
firstUnseenInteractionTimestamp:firstUnseenInteractionTimestamp]; firstUnseenSortId:firstUnseenSortId];
// Determine the position of the focus message _after_ performing any mutations // Determine the position of the focus message _after_ performing any mutations
// around dynamic interactions. // around dynamic interactions.
@ -553,7 +552,7 @@ NS_ASSUME_NONNULL_BEGIN
blockingSafetyNumberChanges:(NSArray<TSInvalidIdentityKeyErrorMessage *> *)blockingSafetyNumberChanges blockingSafetyNumberChanges:(NSArray<TSInvalidIdentityKeyErrorMessage *> *)blockingSafetyNumberChanges
nonBlockingSafetyNumberChanges:(NSArray<TSInteraction *> *)nonBlockingSafetyNumberChanges nonBlockingSafetyNumberChanges:(NSArray<TSInteraction *> *)nonBlockingSafetyNumberChanges
hideUnreadMessagesIndicator:(BOOL)hideUnreadMessagesIndicator hideUnreadMessagesIndicator:(BOOL)hideUnreadMessagesIndicator
firstUnseenInteractionTimestamp:(nullable NSNumber *)firstUnseenInteractionTimestamp firstUnseenSortId:(nullable NSNumber *)firstUnseenSortId
{ {
OWSAssertDebug(dynamicInteractions); OWSAssertDebug(dynamicInteractions);
OWSAssertDebug(thread); OWSAssertDebug(thread);
@ -564,7 +563,7 @@ NS_ASSUME_NONNULL_BEGIN
if (hideUnreadMessagesIndicator) { if (hideUnreadMessagesIndicator) {
return; return;
} }
if (!firstUnseenInteractionTimestamp) { if (!firstUnseenSortId) {
// If there are no unseen interactions, don't show an unread indicator. // If there are no unseen interactions, don't show an unread indicator.
return; return;
} }
@ -600,9 +599,7 @@ NS_ASSUME_NONNULL_BEGIN
return; return;
} }
// MJK FIXME - use sortId if (interaction.sortId < firstUnseenSortId.unsignedLongLongValue) {
if (interaction.timestampForLegacySorting
< firstUnseenInteractionTimestamp.unsignedLongLongValue) {
// By default we want the unread indicator to appear just before // By default we want the unread indicator to appear just before
// the first unread message. // the first unread message.
*stop = YES; *stop = YES;
@ -634,15 +631,12 @@ NS_ASSUME_NONNULL_BEGIN
if (hasMoreUnseenMessages) { if (hasMoreUnseenMessages) {
NSMutableSet<NSData *> *missingUnseenSafetyNumberChanges = [NSMutableSet set]; NSMutableSet<NSData *> *missingUnseenSafetyNumberChanges = [NSMutableSet set];
for (TSInvalidIdentityKeyErrorMessage *safetyNumberChange in blockingSafetyNumberChanges) { for (TSInvalidIdentityKeyErrorMessage *safetyNumberChange in blockingSafetyNumberChanges) {
// MJK FIXME - use sortId BOOL isUnseen = safetyNumberChange.sortId >= firstUnseenSortId.unsignedLongLongValue;
BOOL isUnseen
= safetyNumberChange.timestampForLegacySorting >= firstUnseenInteractionTimestamp.unsignedLongLongValue;
if (!isUnseen) { if (!isUnseen) {
continue; continue;
} }
// MJK FIXME - use sortId
BOOL isMissing = safetyNumberChange.timestampForLegacySorting BOOL isMissing = safetyNumberChange.sortId < interactionAfterUnreadIndicator.sortId;
< interactionAfterUnreadIndicator.timestampForLegacySorting;
if (!isMissing) { if (!isMissing) {
continue; continue;
} }
@ -667,14 +661,12 @@ NS_ASSUME_NONNULL_BEGIN
unreadIndicatorPosition++; unreadIndicatorPosition++;
} }
// MJK FIXME - use sortId, or maybe just timestamp, do we even need timestamp? dynamicInteractions.unreadIndicator =
dynamicInteractions.unreadIndicator = [[OWSUnreadIndicator alloc] [[OWSUnreadIndicator alloc] initWithFirstUnseenSortId:firstUnseenSortId.unsignedLongLongValue
initUnreadIndicatorWithTimestamp:interactionAfterUnreadIndicator.timestampForLegacySorting
hasMoreUnseenMessages:hasMoreUnseenMessages hasMoreUnseenMessages:hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:missingUnseenSafetyNumberChangeCount missingUnseenSafetyNumberChangeCount:missingUnseenSafetyNumberChangeCount
unreadIndicatorPosition:unreadIndicatorPosition unreadIndicatorPosition:unreadIndicatorPosition];
firstUnseenInteractionTimestamp:firstUnseenInteractionTimestamp.unsignedLongLongValue]; OWSLogInfo(@"Creating Unread Indicator: %llu", dynamicInteractions.unreadIndicator.firstUnseenSortId);
OWSLogInfo(@"Creating Unread Indicator: %llu", dynamicInteractions.unreadIndicator.timestamp);
} }
+ (nullable NSNumber *)focusMessagePositionForThread:(TSThread *)thread + (nullable NSNumber *)focusMessagePositionForThread:(TSThread *)thread

Loading…
Cancel
Save