Fix RTL bubbles in conversation and message detail view

// FREEBIE
pull/1/head
Michael Kirk 8 years ago
parent b2a38323b1
commit e2445e6ed2

@ -140,6 +140,7 @@
4520D8D51D417D8E00123472 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4520D8D41D417D8E00123472 /* Photos.framework */; }; 4520D8D51D417D8E00123472 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4520D8D41D417D8E00123472 /* Photos.framework */; };
4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */; }; 4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */; };
4521C3C11F59F3BA00B4C582 /* 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 */; }; 452C468F1E427E200087B011 /* OutboundCallInitiator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452C468E1E427E200087B011 /* OutboundCallInitiator.swift */; };
452C46901E427E200087B011 /* 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 */; }; 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 = "<group>"; }; 452037D01EE84975004E4CDF /* DebugUISessionState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUISessionState.m; sourceTree = "<group>"; };
4520D8D41D417D8E00123472 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; }; 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 = "<group>"; }; 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldHelper.swift; sourceTree = "<group>"; };
4523149B1F7D7F81003A428C /* OWSMessagesBubbleImageFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSMessagesBubbleImageFactory.swift; sourceTree = "<group>"; };
4526BD481CA61C8D00166BC8 /* OWSMessageEditing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageEditing.h; sourceTree = "<group>"; }; 4526BD481CA61C8D00166BC8 /* OWSMessageEditing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageEditing.h; sourceTree = "<group>"; };
452C468E1E427E200087B011 /* OutboundCallInitiator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutboundCallInitiator.swift; sourceTree = "<group>"; }; 452C468E1E427E200087B011 /* OutboundCallInitiator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutboundCallInitiator.swift; sourceTree = "<group>"; };
452D1EE71DCA90D100A57EC4 /* MesssagesBubblesSizeCalculatorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MesssagesBubblesSizeCalculatorTest.swift; path = Models/MesssagesBubblesSizeCalculatorTest.swift; sourceTree = "<group>"; }; 452D1EE71DCA90D100A57EC4 /* MesssagesBubblesSizeCalculatorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MesssagesBubblesSizeCalculatorTest.swift; path = Models/MesssagesBubblesSizeCalculatorTest.swift; sourceTree = "<group>"; };
@ -1173,6 +1175,7 @@
45E2E91F1E153B3D00457AA0 /* Strings.swift */, 45E2E91F1E153B3D00457AA0 /* Strings.swift */,
34B3F8331E8DF1700035BE1A /* ViewControllers */, 34B3F8331E8DF1700035BE1A /* ViewControllers */,
76EB052B18170B33006006FC /* Views */, 76EB052B18170B33006006FC /* Views */,
4523149B1F7D7F81003A428C /* OWSMessagesBubbleImageFactory.swift */,
); );
name = UserInterface; name = UserInterface;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2277,6 +2280,7 @@
45666EC91D994C0D008FE134 /* OWSGroupAvatarBuilder.m in Sources */, 45666EC91D994C0D008FE134 /* OWSGroupAvatarBuilder.m in Sources */,
3471B1DA1EB7C63600F6AEC8 /* NewNonContactConversationViewController.m in Sources */, 3471B1DA1EB7C63600F6AEC8 /* NewNonContactConversationViewController.m in Sources */,
34B3F87C1E8DF1700035BE1A /* FingerprintViewController.m in Sources */, 34B3F87C1E8DF1700035BE1A /* FingerprintViewController.m in Sources */,
4523149C1F7D7F81003A428C /* OWSMessagesBubbleImageFactory.swift in Sources */,
45638BDC1F3DD0D400128435 /* DebugUICalling.swift in Sources */, 45638BDC1F3DD0D400128435 /* DebugUICalling.swift in Sources */,
76EB058218170B33006006FC /* Environment.m in Sources */, 76EB058218170B33006006FC /* Environment.m in Sources */,
450449391F45EE7D002D1ADA /* NSString+OWS.m in Sources */, 450449391F45EE7D002D1ADA /* NSString+OWS.m in Sources */,

@ -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)
}
}
}

@ -5,7 +5,6 @@
#import "AppSettingsViewController.h" #import "AppSettingsViewController.h"
#import "AttachmentSharing.h" #import "AttachmentSharing.h"
#import "ContactTableViewCell.h" #import "ContactTableViewCell.h"
#import "ConversationViewController.h"
#import "DateUtil.h" #import "DateUtil.h"
#import "DebugUIPage.h" #import "DebugUIPage.h"
#import "Environment.h" #import "Environment.h"
@ -44,6 +43,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <JSQMessagesViewController/JSQMediaItem.h> #import <JSQMessagesViewController/JSQMediaItem.h>
#import <JSQMessagesViewController/JSQMessagesBubbleImage.h> #import <JSQMessagesViewController/JSQMessagesBubbleImage.h>
#import <JSQMessagesViewController/JSQMessagesBubbleImageFactory.h>
#import <JSQMessagesViewController/JSQMessagesMediaViewBubbleImageMasker.h> #import <JSQMessagesViewController/JSQMessagesMediaViewBubbleImageMasker.h>
#import <JSQMessagesViewController/UIColor+JSQMessages.h> #import <JSQMessagesViewController/UIColor+JSQMessages.h>
#import <JSQSystemSoundPlayer.h> #import <JSQSystemSoundPlayer.h>

@ -4,6 +4,8 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIColor (OWS) @interface UIColor (OWS)
+ (UIColor *)ows_signalBrandBlueColor; + (UIColor *)ows_signalBrandBlueColor;
@ -26,3 +28,5 @@
- (UIColor *)blendWithColor:(UIColor *)otherColor alpha:(CGFloat)alpha; - (UIColor *)blendWithColor:(UIColor *)otherColor alpha:(CGFloat)alpha;
@end @end
NS_ASSUME_NONNULL_END

@ -6,6 +6,8 @@
#import "OWSMath.h" #import "OWSMath.h"
#import "UIColor+OWS.h" #import "UIColor+OWS.h"
NS_ASSUME_NONNULL_BEGIN
@implementation UIColor (OWS) @implementation UIColor (OWS)
+ (UIColor *)ows_signalBrandBlueColor + (UIColor *)ows_signalBrandBlueColor
@ -154,3 +156,5 @@
} }
@end @end
NS_ASSUME_NONNULL_END

@ -5,7 +5,6 @@
#import <JSQMessagesViewController/JSQMessagesViewController.h> #import <JSQMessagesViewController/JSQMessagesViewController.h>
@class TSThread; @class TSThread;
@class JSQMessagesBubbleImage;
extern NSString *const ConversationViewControllerDidAppearNotification; extern NSString *const ConversationViewControllerDidAppearNotification;
@ -24,11 +23,4 @@ extern NSString *const ConversationViewControllerDidAppearNotification;
- (void)peekSetup; - (void)peekSetup;
- (void)popped; - (void)popped;
#pragma mark shared bubble styles
+ (JSQMessagesBubbleImage *)outgoingBubbleImageData;
+ (JSQMessagesBubbleImage *)incomingBubbleImageData;
+ (JSQMessagesBubbleImage *)currentlyOutgoingBubbleImageData;
+ (JSQMessagesBubbleImage *)outgoingMessageFailedImageData;
@end @end

@ -259,6 +259,11 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
@property (nonatomic) YapDatabaseConnection *uiDatabaseConnection; @property (nonatomic) YapDatabaseConnection *uiDatabaseConnection;
@property (nonatomic) YapDatabaseViewMappings *messageMappings; @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) MPMoviePlayerController *videoPlayer;
@property (nonatomic) AVAudioRecorder *audioRecorder; @property (nonatomic) AVAudioRecorder *audioRecorder;
@property (nonatomic) OWSAudioAttachmentPlayer *audioAttachmentPlayer; @property (nonatomic) OWSAudioAttachmentPlayer *audioAttachmentPlayer;
@ -1536,75 +1541,13 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
self.collectionView.collectionViewLayout.messageBubbleLeftRightMargin = 80.0f; self.collectionView.collectionViewLayout.messageBubbleLeftRightMargin = 80.0f;
} }
// Bubbles
self.collectionView.collectionViewLayout.bubbleSizeCalculator = [OWSMessagesBubblesSizeCalculator new]; self.collectionView.collectionViewLayout.bubbleSizeCalculator = [OWSMessagesBubblesSizeCalculator new];
} OWSMessagesBubbleImageFactory *bubbleFactory = [OWSMessagesBubbleImageFactory new];
self.incomingBubbleImageData = bubbleFactory.incoming;
+ (JSQMessagesBubbleImageFactory *)sharedBubbleImageFactory self.outgoingBubbleImageData = bubbleFactory.outgoing;
{ self.currentlyOutgoingBubbleImageData = bubbleFactory.currentlyOutgoing;
AssertIsOnMainThread(); self.outgoingMessageFailedImageData = bubbleFactory.outgoingFailed;
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;
} }
#pragma mark - Identity #pragma mark - Identity
@ -1886,19 +1829,19 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) {
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)message; TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)message;
switch (outgoingMessage.messageState) { switch (outgoingMessage.messageState) {
case TSOutgoingMessageStateUnsent: case TSOutgoingMessageStateUnsent:
return [[self class] outgoingMessageFailedImageData]; return self.outgoingMessageFailedImageData;
case TSOutgoingMessageStateAttemptingOut: case TSOutgoingMessageStateAttemptingOut:
return [[self class] currentlyOutgoingBubbleImageData]; return self.currentlyOutgoingBubbleImageData;
case TSOutgoingMessageStateSent_OBSOLETE: case TSOutgoingMessageStateSent_OBSOLETE:
case TSOutgoingMessageStateDelivered_OBSOLETE: case TSOutgoingMessageStateDelivered_OBSOLETE:
OWSFail(@"%@ Obsolete message state.", self.tag); OWSFail(@"%@ Obsolete message state.", self.tag);
return [[self class] outgoingBubbleImageData]; return self.outgoingBubbleImageData;
case TSOutgoingMessageStateSentToService: case TSOutgoingMessageStateSentToService:
return [[self class] outgoingBubbleImageData]; return self.outgoingBubbleImageData;
} }
} }
return [[self class] incomingBubbleImageData]; return self.incomingBubbleImageData;
} }
- (id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView - (id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView

@ -24,6 +24,8 @@ class MessageMetadataViewController: OWSViewController {
let databaseConnection: YapDatabaseConnection let databaseConnection: YapDatabaseConnection
let bubbleFactory = OWSMessagesBubbleImageFactory()
var message: TSMessage var message: TSMessage
var mediaMessageView: MediaMessageView? var mediaMessageView: MediaMessageView?
@ -280,16 +282,18 @@ class MessageMetadataViewController: OWSViewController {
bodyLabel.numberOfLines = 10 bodyLabel.numberOfLines = 10
bodyLabel.lineBreakMode = .byWordWrapping bodyLabel.lineBreakMode = .byWordWrapping
let bubbleImageData = isIncoming ? ConversationViewController.incomingBubbleImageData() : ConversationViewController.outgoingBubbleImageData() let bubbleImageData = isIncoming ? bubbleFactory.incoming : bubbleFactory.outgoing
let leadingMargin: CGFloat = isIncoming ? 15 : 10 let leadingMargin: CGFloat = isIncoming ? 15 : 10
let trailingMargin: CGFloat = isIncoming ? 10 : 15 let trailingMargin: CGFloat = isIncoming ? 10 : 15
let bubbleView = UIImageView(image: bubbleImageData!.messageBubbleImage) let bubbleView = UIImageView(image: bubbleImageData.messageBubbleImage)
bubbleView.layer.cornerRadius = 10 bubbleView.layer.cornerRadius = 10
bubbleView.addSubview(bodyLabel) 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) bodyLabel.autoPinHeightToSuperview(withMargin: 10)
// Try to hug content both horizontally and vertically, but *prefer* wide and short, to narrow and tall. // Try to hug content both horizontally and vertically, but *prefer* wide and short, to narrow and tall.

Loading…
Cancel
Save