diff --git a/Scripts/reverse_integration_check.py b/Scripts/reverse_integration_check.py index 01bdf6b50..f7f5967c5 100755 --- a/Scripts/reverse_integration_check.py +++ b/Scripts/reverse_integration_check.py @@ -52,6 +52,7 @@ def main(): '2.29.0.11', '2.30.0.0', '2.30.0.1', + '2.30.2.0', '3.0', '3.0.1', '3.0.2', diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index e537d2afb..75537bd8d 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -4142,6 +4142,7 @@ typedef enum : NSUInteger { [self updateLastVisibleTimestamp]; self.conversationStyle.viewWidth = self.collectionView.width; + [self.collectionView.collectionViewLayout invalidateLayout]; } #pragma mark - View Items diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index e21204abd..6058a6006 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -504,14 +504,16 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations UIImage *avatarImage = (localProfileAvatarImage ?: [[[OWSContactAvatarBuilder alloc] initForLocalUserWithDiameter:kAvatarSize] buildDefaultImage]); OWSAssertDebug(avatarImage); - AvatarImageView *avatarView = [[AvatarImageView alloc] initWithImage:avatarImage]; - [avatarView autoSetDimension:ALDimensionWidth toSize:kAvatarSize]; - [avatarView autoSetDimension:ALDimensionHeight toSize:kAvatarSize]; - avatarView.userInteractionEnabled = YES; - [avatarView - addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self - action:@selector(settingsButtonPressed:)]]; - settingsButton = [[UIBarButtonItem alloc] initWithCustomView:avatarView]; + + UIButton *avatarButton = [AvatarImageButton buttonWithType:UIButtonTypeCustom]; + [avatarButton addTarget:self + action:@selector(settingsButtonPressed:) + forControlEvents:UIControlEventTouchUpInside]; + [avatarButton setImage:avatarImage forState:UIControlStateNormal]; + [avatarButton autoSetDimension:ALDimensionWidth toSize:kAvatarSize]; + [avatarButton autoSetDimension:ALDimensionHeight toSize:kAvatarSize]; + + settingsButton = [[UIBarButtonItem alloc] initWithCustomView:avatarButton]; } else { // iOS 9 and 10 have a bug around layout of custom views in UIBarButtonItem, // so we just use a simple icon. diff --git a/SignalMessaging/Views/AvatarImageView.swift b/SignalMessaging/Views/AvatarImageView.swift index 62dd476c8..d4d4eb248 100644 --- a/SignalMessaging/Views/AvatarImageView.swift +++ b/SignalMessaging/Views/AvatarImageView.swift @@ -178,3 +178,59 @@ public class ConversationAvatarImageView: AvatarImageView { self.image = OWSAvatarBuilder.buildImage(thread: thread, diameter: diameter) } } + +@objc +public class AvatarImageButton: UIButton { + private let shadowLayer = CAShapeLayer() + + // MARK: - Button Overrides + + override public func layoutSubviews() { + super.layoutSubviews() + + layer.cornerRadius = frame.size.width / 2 + + // Inner shadow. + // This should usually not be visible; it is used to distinguish + // profile pics from the background if they are similar. + shadowLayer.frame = bounds + shadowLayer.masksToBounds = true + let shadowBounds = bounds + let shadowPath = UIBezierPath(ovalIn: shadowBounds) + // This can be any value large enough to cast a sufficiently large shadow. + let shadowInset: CGFloat = -3 + shadowPath.append(UIBezierPath(rect: shadowBounds.insetBy(dx: shadowInset, dy: shadowInset))) + // This can be any color since the fill should be clipped. + shadowLayer.fillColor = UIColor.black.cgColor + shadowLayer.path = shadowPath.cgPath + shadowLayer.fillRule = kCAFillRuleEvenOdd + shadowLayer.shadowColor = (Theme.isDarkThemeEnabled ? UIColor.white : UIColor.black).cgColor + shadowLayer.shadowRadius = 0.5 + shadowLayer.shadowOpacity = 0.15 + shadowLayer.shadowOffset = .zero + } + + override public func setImage(_ image: UIImage?, for state: UIControlState) { + ensureViewConfigured() + super.setImage(image, for: state) + } + + // MARK: Private + + var hasBeenConfigured = false + func ensureViewConfigured() { + guard !hasBeenConfigured else { + return + } + hasBeenConfigured = true + + autoPinToSquareAspectRatio() + + layer.minificationFilter = kCAFilterTrilinear + layer.magnificationFilter = kCAFilterTrilinear + layer.masksToBounds = true + layer.addSublayer(shadowLayer) + + contentMode = .scaleToFill + } +} diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m b/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m index 52f693603..e009b0894 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m @@ -189,7 +189,7 @@ typedef void (^OWSLoadedThumbnailSuccess)(OWSLoadedThumbnail *loadedThumbnail); OWSFailDebug(@"Missing path for attachment."); return NO; } - OWSLogInfo(@"Writing attachment to file: %@", filePath); + OWSLogDebug(@"Writing attachment to file: %@", filePath); return [data writeToFile:filePath options:0 error:error]; } @@ -202,7 +202,7 @@ typedef void (^OWSLoadedThumbnailSuccess)(OWSLoadedThumbnail *loadedThumbnail); OWSFailDebug(@"Missing path for attachment."); return NO; } - OWSLogInfo(@"Writing attachment to file: %@", filePath); + OWSLogDebug(@"Writing attachment to file: %@", filePath); return [dataSource writeToPath:filePath]; } diff --git a/SignalServiceKit/src/Util/TypingIndicators.swift b/SignalServiceKit/src/Util/TypingIndicators.swift index 97b721391..f148a7555 100644 --- a/SignalServiceKit/src/Util/TypingIndicators.swift +++ b/SignalServiceKit/src/Util/TypingIndicators.swift @@ -159,6 +159,10 @@ public class TypingIndicatorsImpl: NSObject, TypingIndicators { public func typingRecipientId(forThread thread: TSThread) -> String? { AssertIsOnMainThread() + guard areTypingIndicatorsEnabled() else { + return nil + } + var firstRecipientId: String? var firstTimestamp: UInt64?