diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 14db4e877..4dd53ee2b 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -140,6 +140,7 @@ 4520D8D51D417D8E00123472 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4520D8D41D417D8E00123472 /* Photos.framework */; }; 4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */; }; 4521C3C11F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */; }; + 4523149C1F7D7F81003A428C /* OWSMessagesBubbleImageFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4523149B1F7D7F81003A428C /* OWSMessagesBubbleImageFactory.swift */; }; 452C468F1E427E200087B011 /* OutboundCallInitiator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452C468E1E427E200087B011 /* OutboundCallInitiator.swift */; }; 452C46901E427E200087B011 /* OutboundCallInitiator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452C468E1E427E200087B011 /* OutboundCallInitiator.swift */; }; 452D1EE81DCA90D100A57EC4 /* MesssagesBubblesSizeCalculatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452D1EE71DCA90D100A57EC4 /* MesssagesBubblesSizeCalculatorTest.swift */; }; @@ -604,6 +605,7 @@ 452037D01EE84975004E4CDF /* DebugUISessionState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUISessionState.m; sourceTree = ""; }; 4520D8D41D417D8E00123472 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; }; 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldHelper.swift; sourceTree = ""; }; + 4523149B1F7D7F81003A428C /* OWSMessagesBubbleImageFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSMessagesBubbleImageFactory.swift; sourceTree = ""; }; 4526BD481CA61C8D00166BC8 /* OWSMessageEditing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageEditing.h; sourceTree = ""; }; 452C468E1E427E200087B011 /* OutboundCallInitiator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutboundCallInitiator.swift; sourceTree = ""; }; 452D1EE71DCA90D100A57EC4 /* MesssagesBubblesSizeCalculatorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MesssagesBubblesSizeCalculatorTest.swift; path = Models/MesssagesBubblesSizeCalculatorTest.swift; sourceTree = ""; }; @@ -1173,6 +1175,7 @@ 45E2E91F1E153B3D00457AA0 /* Strings.swift */, 34B3F8331E8DF1700035BE1A /* ViewControllers */, 76EB052B18170B33006006FC /* Views */, + 4523149B1F7D7F81003A428C /* OWSMessagesBubbleImageFactory.swift */, ); name = UserInterface; sourceTree = ""; @@ -2277,6 +2280,7 @@ 45666EC91D994C0D008FE134 /* OWSGroupAvatarBuilder.m in Sources */, 3471B1DA1EB7C63600F6AEC8 /* NewNonContactConversationViewController.m in Sources */, 34B3F87C1E8DF1700035BE1A /* FingerprintViewController.m in Sources */, + 4523149C1F7D7F81003A428C /* OWSMessagesBubbleImageFactory.swift in Sources */, 45638BDC1F3DD0D400128435 /* DebugUICalling.swift in Sources */, 76EB058218170B33006006FC /* Environment.m in Sources */, 450449391F45EE7D002D1ADA /* NSString+OWS.m in Sources */, diff --git a/Signal/src/OWSMessagesBubbleImageFactory.swift b/Signal/src/OWSMessagesBubbleImageFactory.swift new file mode 100644 index 000000000..5e7bef26e --- /dev/null +++ b/Signal/src/OWSMessagesBubbleImageFactory.swift @@ -0,0 +1,51 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +import Foundation + +@objc +class OWSMessagesBubbleImageFactory: NSObject { + + let jsqFactory = JSQMessagesBubbleImageFactory()! + + var isRTL: Bool { + return UIView().isRTL() + } + + var incoming: JSQMessagesBubbleImage { + let color = UIColor.jsq_messageBubbleLightGray()! + return incoming(color: color) + } + + var outgoing: JSQMessagesBubbleImage { + let color = UIColor.ows_materialBlue() + return outgoing(color: color) + } + + var currentlyOutgoing: JSQMessagesBubbleImage { + let color = UIColor.ows_fadedBlue() + return outgoing(color: color) + } + + var outgoingFailed: JSQMessagesBubbleImage { + let color = UIColor.gray + return outgoing(color: color) + } + + func outgoing(color: UIColor) -> JSQMessagesBubbleImage { + if isRTL { + return jsqFactory.incomingMessagesBubbleImage(with: color) + } else { + return jsqFactory.outgoingMessagesBubbleImage(with: color) + } + } + + func incoming(color: UIColor) -> JSQMessagesBubbleImage { + if isRTL { + return jsqFactory.outgoingMessagesBubbleImage(with: color) + } else { + return jsqFactory.incomingMessagesBubbleImage(with: color) + } + } +} diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index 88c2b1bf1..b4b688d3e 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -5,7 +5,6 @@ #import "AppSettingsViewController.h" #import "AttachmentSharing.h" #import "ContactTableViewCell.h" -#import "ConversationViewController.h" #import "DateUtil.h" #import "DebugUIPage.h" #import "Environment.h" @@ -44,6 +43,7 @@ #import #import #import +#import #import #import #import diff --git a/Signal/src/UIColor+OWS.h b/Signal/src/UIColor+OWS.h index 3444672bd..f4c8e9046 100644 --- a/Signal/src/UIColor+OWS.h +++ b/Signal/src/UIColor+OWS.h @@ -4,6 +4,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @interface UIColor (OWS) + (UIColor *)ows_signalBrandBlueColor; @@ -26,3 +28,5 @@ - (UIColor *)blendWithColor:(UIColor *)otherColor alpha:(CGFloat)alpha; @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/UIColor+OWS.m b/Signal/src/UIColor+OWS.m index 168005ed0..7693f3750 100644 --- a/Signal/src/UIColor+OWS.m +++ b/Signal/src/UIColor+OWS.m @@ -6,6 +6,8 @@ #import "OWSMath.h" #import "UIColor+OWS.h" +NS_ASSUME_NONNULL_BEGIN + @implementation UIColor (OWS) + (UIColor *)ows_signalBrandBlueColor @@ -154,3 +156,5 @@ } @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.h b/Signal/src/ViewControllers/ConversationView/ConversationViewController.h index 424956643..4ca34e2df 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.h +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.h @@ -5,7 +5,6 @@ #import @class TSThread; -@class JSQMessagesBubbleImage; extern NSString *const ConversationViewControllerDidAppearNotification; @@ -24,11 +23,4 @@ extern NSString *const ConversationViewControllerDidAppearNotification; - (void)peekSetup; - (void)popped; -#pragma mark shared bubble styles - -+ (JSQMessagesBubbleImage *)outgoingBubbleImageData; -+ (JSQMessagesBubbleImage *)incomingBubbleImageData; -+ (JSQMessagesBubbleImage *)currentlyOutgoingBubbleImageData; -+ (JSQMessagesBubbleImage *)outgoingMessageFailedImageData; - @end diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 377b656f9..8233fb616 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -259,6 +259,11 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { @property (nonatomic) YapDatabaseConnection *uiDatabaseConnection; @property (nonatomic) YapDatabaseViewMappings *messageMappings; +@property (nonatomic) JSQMessagesBubbleImage *outgoingBubbleImageData; +@property (nonatomic) JSQMessagesBubbleImage *incomingBubbleImageData; +@property (nonatomic) JSQMessagesBubbleImage *currentlyOutgoingBubbleImageData; +@property (nonatomic) JSQMessagesBubbleImage *outgoingMessageFailedImageData; + @property (nonatomic) MPMoviePlayerController *videoPlayer; @property (nonatomic) AVAudioRecorder *audioRecorder; @property (nonatomic) OWSAudioAttachmentPlayer *audioAttachmentPlayer; @@ -1536,75 +1541,13 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { self.collectionView.collectionViewLayout.messageBubbleLeftRightMargin = 80.0f; } + // Bubbles self.collectionView.collectionViewLayout.bubbleSizeCalculator = [OWSMessagesBubblesSizeCalculator new]; -} - -+ (JSQMessagesBubbleImageFactory *)sharedBubbleImageFactory -{ - AssertIsOnMainThread(); - - static JSQMessagesBubbleImageFactory *bubbleImageFactory; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - bubbleImageFactory = [JSQMessagesBubbleImageFactory new]; - }); - - return bubbleImageFactory; -} - -+ (JSQMessagesBubbleImage *)outgoingBubbleImageData -{ - AssertIsOnMainThread(); - - static JSQMessagesBubbleImage *bubbleImage; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - bubbleImage = - [[self sharedBubbleImageFactory] outgoingMessagesBubbleImageWithColor:[UIColor ows_materialBlueColor]]; - }); - - return bubbleImage; -} - -+ (JSQMessagesBubbleImage *)incomingBubbleImageData -{ - AssertIsOnMainThread(); - - static JSQMessagesBubbleImage *bubbleImage; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - bubbleImage = [[self sharedBubbleImageFactory] - incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]]; - }); - - return bubbleImage; -} - -+ (JSQMessagesBubbleImage *)currentlyOutgoingBubbleImageData -{ - AssertIsOnMainThread(); - - static JSQMessagesBubbleImage *bubbleImage; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - bubbleImage = - [[self sharedBubbleImageFactory] outgoingMessagesBubbleImageWithColor:[UIColor ows_fadedBlueColor]]; - }); - - return bubbleImage; -} - -+ (JSQMessagesBubbleImage *)outgoingMessageFailedImageData -{ - AssertIsOnMainThread(); - - static JSQMessagesBubbleImage *bubbleImage; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - bubbleImage = [[self sharedBubbleImageFactory] outgoingMessagesBubbleImageWithColor:[UIColor grayColor]]; - }); - - return bubbleImage; + OWSMessagesBubbleImageFactory *bubbleFactory = [OWSMessagesBubbleImageFactory new]; + self.incomingBubbleImageData = bubbleFactory.incoming; + self.outgoingBubbleImageData = bubbleFactory.outgoing; + self.currentlyOutgoingBubbleImageData = bubbleFactory.currentlyOutgoing; + self.outgoingMessageFailedImageData = bubbleFactory.outgoingFailed; } #pragma mark - Identity @@ -1886,19 +1829,19 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)message; switch (outgoingMessage.messageState) { case TSOutgoingMessageStateUnsent: - return [[self class] outgoingMessageFailedImageData]; + return self.outgoingMessageFailedImageData; case TSOutgoingMessageStateAttemptingOut: - return [[self class] currentlyOutgoingBubbleImageData]; + return self.currentlyOutgoingBubbleImageData; case TSOutgoingMessageStateSent_OBSOLETE: case TSOutgoingMessageStateDelivered_OBSOLETE: OWSFail(@"%@ Obsolete message state.", self.tag); - return [[self class] outgoingBubbleImageData]; + return self.outgoingBubbleImageData; case TSOutgoingMessageStateSentToService: - return [[self class] outgoingBubbleImageData]; + return self.outgoingBubbleImageData; } } - return [[self class] incomingBubbleImageData]; + return self.incomingBubbleImageData; } - (id)collectionView:(JSQMessagesCollectionView *)collectionView diff --git a/Signal/src/ViewControllers/MessageMetadataViewController.swift b/Signal/src/ViewControllers/MessageMetadataViewController.swift index 90e56f139..8c90b5dc0 100644 --- a/Signal/src/ViewControllers/MessageMetadataViewController.swift +++ b/Signal/src/ViewControllers/MessageMetadataViewController.swift @@ -24,6 +24,8 @@ class MessageMetadataViewController: OWSViewController { let databaseConnection: YapDatabaseConnection + let bubbleFactory = OWSMessagesBubbleImageFactory() + var message: TSMessage var mediaMessageView: MediaMessageView? @@ -280,16 +282,18 @@ class MessageMetadataViewController: OWSViewController { bodyLabel.numberOfLines = 10 bodyLabel.lineBreakMode = .byWordWrapping - let bubbleImageData = isIncoming ? ConversationViewController.incomingBubbleImageData() : ConversationViewController.outgoingBubbleImageData() + let bubbleImageData = isIncoming ? bubbleFactory.incoming : bubbleFactory.outgoing + let leadingMargin: CGFloat = isIncoming ? 15 : 10 let trailingMargin: CGFloat = isIncoming ? 10 : 15 - let bubbleView = UIImageView(image: bubbleImageData!.messageBubbleImage) + let bubbleView = UIImageView(image: bubbleImageData.messageBubbleImage) bubbleView.layer.cornerRadius = 10 bubbleView.addSubview(bodyLabel) - bodyLabel.autoPinLeadingToSuperView(withMargin: leadingMargin) - bodyLabel.autoPinTrailingToSuperView(withMargin: trailingMargin) + + bodyLabel.autoPinEdge(toSuperviewEdge: .leading, withInset: leadingMargin) + bodyLabel.autoPinEdge(toSuperviewEdge: .trailing, withInset: trailingMargin) bodyLabel.autoPinHeightToSuperview(withMargin: 10) // Try to hug content both horizontally and vertically, but *prefer* wide and short, to narrow and tall.