diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index f5541c3fe..ab10eb0cd 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -25,6 +25,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, // MARK: Views + var isViewLoaded = false var hasConstraints = false var blurView: UIVisualEffectView! var dateFormatter: DateFormatter? @@ -158,7 +159,9 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, } func didBecomeActive() { - shouldRemoteVideoControlsBeHidden = false + if (self.isViewLoaded) { + shouldRemoteVideoControlsBeHidden = false + } } // MARK: View Lifecycle @@ -195,6 +198,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, call.addObserverAndSyncState(observer: self) Environment.getCurrent().callService.addObserverAndSyncState(observer: self) + self.isViewLoaded = true } // MARK: - Create Views diff --git a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m index 2c97a138c..2dd5a2faa 100644 --- a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m +++ b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m @@ -487,8 +487,17 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { _callOnOpen = callOnViewAppearing; [self.uiDatabaseConnection beginLongLivedReadTransaction]; - self.messageMappings = - [[YapDatabaseViewMappings alloc] initWithGroups:@[ thread.uniqueId ] view:TSMessageDatabaseViewExtensionName]; + + if (thread.uniqueId.length > 0) { + self.messageMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[ thread.uniqueId ] + view:TSMessageDatabaseViewExtensionName]; + } else { + OWSFail(@"uniqueId unexpectedly empty for thread: %@", thread); + self.messageMappings = + [[YapDatabaseViewMappings alloc] initWithGroups:@[] view:TSMessageDatabaseViewExtensionName]; + return; + } + // 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. [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { @@ -2202,33 +2211,38 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { if ([[messageItem media] isKindOfClass:[TSPhotoAdapter class]]) { TSPhotoAdapter *messageMedia = (TSPhotoAdapter *)[messageItem media]; - UIImage *tappedImage = ((UIImageView *)[messageMedia mediaView]).image; + UIView *mediaView = [messageMedia mediaView]; + if (![mediaView isKindOfClass:[UIImageView class]]) { + OWSFail(@"unexpected mediaView of type: %@", [mediaView class]); + return; + } + UIImageView *imageView = (UIImageView *)mediaView; + UIImage *tappedImage = imageView.image; if (tappedImage == nil) { DDLogWarn(@"tapped TSPhotoAdapter with nil image"); - } else { - UIWindow *window = [UIApplication sharedApplication].keyWindow; - JSQMessagesCollectionViewCell *cell - = (JSQMessagesCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath]; - OWSAssert([cell isKindOfClass:[JSQMessagesCollectionViewCell class]]); - CGRect convertedRect = [cell.mediaView convertRect:cell.mediaView.bounds toView:window]; + return; + } + UIWindow *window = [UIApplication sharedApplication].keyWindow; + JSQMessagesCollectionViewCell *cell + = (JSQMessagesCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath]; + OWSAssert([cell isKindOfClass:[JSQMessagesCollectionViewCell class]]); + CGRect convertedRect = [cell.mediaView convertRect:cell.mediaView.bounds toView:window]; - __block TSAttachment *attachment = nil; - [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - attachment = [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId - transaction:transaction]; - }]; + __block TSAttachment *attachment = nil; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + attachment = + [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId transaction:transaction]; + }]; - if ([attachment isKindOfClass:[TSAttachmentStream class]]) { - TSAttachmentStream *attStream = (TSAttachmentStream *)attachment; - FullImageViewController *vc = - [[FullImageViewController alloc] initWithAttachment:attStream - fromRect:convertedRect - forInteraction:interaction - messageItem:messageItem - isAnimated:NO]; + if ([attachment isKindOfClass:[TSAttachmentStream class]]) { + TSAttachmentStream *attStream = (TSAttachmentStream *)attachment; + FullImageViewController *vc = [[FullImageViewController alloc] initWithAttachment:attStream + fromRect:convertedRect + forInteraction:interaction + messageItem:messageItem + isAnimated:NO]; - [vc presentFromViewController:self]; - } + [vc presentFromViewController:self]; } } else if ([[messageItem media] isKindOfClass:[TSAnimatedAdapter class]]) { // Show animated image full-screen @@ -3956,20 +3970,30 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { TSThread *thread = self.thread; uint64_t lastVisibleTimestamp = self.lastVisibleTimestamp; + [self.editingDatabaseConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { NSMutableArray> *interactions = [NSMutableArray new]; + [[TSDatabaseView unseenDatabaseViewExtension:transaction] enumerateRowsInGroup:thread.uniqueId usingBlock:^( NSString *collection, NSString *key, id object, id metadata, NSUInteger index, BOOL *stop) { - TSInteraction *interaction = object; - if (interaction.timestampForSorting > lastVisibleTimestamp) { + if (![object conformsToProtocol:@protocol(OWSReadTracking)]) { + OWSFail(@"Expected to conform to OWSReadTracking: object with class: %@ collection: %@ " + @"key: %@", + [object class], + collection, + key); + return; + } + id possiblyRead = (id)object; + + if (possiblyRead.timestampForSorting > lastVisibleTimestamp) { *stop = YES; return; } - id possiblyRead = (id)object; OWSAssert(!possiblyRead.read); if (!possiblyRead.read) { [interactions addObject:possiblyRead]; diff --git a/Signal/src/ViewControllers/SignalsViewController.m b/Signal/src/ViewControllers/SignalsViewController.m index 86d63a7be..57f6be088 100644 --- a/Signal/src/ViewControllers/SignalsViewController.m +++ b/Signal/src/ViewControllers/SignalsViewController.m @@ -726,6 +726,11 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing callOnViewAppearing:(BOOL)callOnViewAppearing { + if (thread == nil) { + OWSFail(@"Thread unexpectedly nil"); + return; + } + // We do this synchronously if we're already on the main thread. DispatchMainThreadSafe(^{ MessagesViewController *mvc = [[MessagesViewController alloc] initWithNibName:@"MessagesViewController" diff --git a/SignalServiceKit/src/Contacts/TSThread.m b/SignalServiceKit/src/Contacts/TSThread.m index 8acc9eead..d53150622 100644 --- a/SignalServiceKit/src/Contacts/TSThread.m +++ b/SignalServiceKit/src/Contacts/TSThread.m @@ -221,7 +221,8 @@ NS_ASSUME_NONNULL_BEGIN NSString *collection, NSString *key, id object, id metadata, NSUInteger index, BOOL *stop) { if (![object conformsToProtocol:@protocol(OWSReadTracking)]) { - DDLogError(@"%@ Unexpected object in unread messages: %@", self.tag, object); + OWSFail(@"%@ Unexpected object in unread messages: %@", self.tag, object); + return; } [messages addObject:(id)object]; }]; diff --git a/SignalServiceKit/src/Messages/OWSReadTracking.h b/SignalServiceKit/src/Messages/OWSReadTracking.h index 5236753bb..ed3dd27be 100644 --- a/SignalServiceKit/src/Messages/OWSReadTracking.h +++ b/SignalServiceKit/src/Messages/OWSReadTracking.h @@ -15,6 +15,7 @@ */ @property (nonatomic, readonly, getter=wasRead) BOOL read; +@property (nonatomic, readonly) uint64_t timestampForSorting; @property (nonatomic, readonly) NSString *uniqueThreadId; - (BOOL)shouldAffectUnreadCounts;