mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Fix emoji message truncation on iOS10
fixes #1368 Apple switched emoji fonts from AppleColorEmoji to AppleColorEmojiUI. The new font doesn't compute it's size correctly, causing containing rectangles to be too small. This commit scrubs strings of the new emoji font, and replaces it with the old. // FREEBIE
This commit is contained in:
parent
9a9f24d8d1
commit
a28fea8384
|
@ -38,7 +38,7 @@
|
|||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.6.0.7</string>
|
||||
<string>2.6.0.9</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LOGS_EMAIL</key>
|
||||
|
|
|
@ -4,6 +4,25 @@
|
|||
#import "OWSDisplayedMessageCollectionViewCell.h"
|
||||
#import "TSMessageAdapter.h"
|
||||
#import "tgmath.h" // generic math allows fmax to handle CGFLoat correctly on 32 & 64bit.
|
||||
#import <JSQMessagesViewController/JSQMessagesCollectionViewFlowLayout.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// BEGIN HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
// superclass protected methods we need in order to compute bubble size.
|
||||
@interface OWSMessagesBubblesSizeCalculator (OWSiOS10EmojiBug)
|
||||
|
||||
@property (strong, nonatomic, readonly) NSCache *cache;
|
||||
@property (assign, nonatomic, readonly) NSUInteger minimumBubbleWidth;
|
||||
@property (assign, nonatomic, readonly) BOOL usesFixedWidthBubbles;
|
||||
@property (assign, nonatomic, readonly) NSInteger additionalInset;
|
||||
@property (assign, nonatomic) CGFloat layoutWidthForFixedWidthBubbles;
|
||||
|
||||
- (CGSize)jsq_avatarSizeForMessageData:(id<JSQMessageData>)messageData
|
||||
withLayout:(JSQMessagesCollectionViewFlowLayout *)layout;
|
||||
- (CGFloat)textBubbleWidthForLayout:(JSQMessagesCollectionViewFlowLayout *)layout;
|
||||
@end
|
||||
// END HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
|
||||
@implementation OWSMessagesBubblesSizeCalculator
|
||||
|
||||
|
@ -22,11 +41,24 @@
|
|||
atIndexPath:(NSIndexPath *)indexPath
|
||||
withLayout:(JSQMessagesCollectionViewFlowLayout *)layout
|
||||
{
|
||||
CGSize superSize = [super messageBubbleSizeForMessageData:messageData atIndexPath:indexPath withLayout:layout];
|
||||
CGSize size;
|
||||
|
||||
// BEGIN HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
BOOL isIOS10OrGreater =
|
||||
[[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 10 }];
|
||||
if (isIOS10OrGreater) {
|
||||
size = [self withiOS10EmojiFixSuperMessageBubbleSizeForMessageData:messageData
|
||||
atIndexPath:indexPath
|
||||
withLayout:layout];
|
||||
} else {
|
||||
size = [super messageBubbleSizeForMessageData:messageData atIndexPath:indexPath withLayout:layout];
|
||||
}
|
||||
// END HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
|
||||
if ([messageData isKindOfClass:[TSMessageAdapter class]]) {
|
||||
TSMessageAdapter *message = (TSMessageAdapter *)messageData;
|
||||
|
||||
|
||||
if (message.messageType == TSInfoMessageAdapter || message.messageType == TSErrorMessageAdapter) {
|
||||
// DDLogVerbose(@"[OWSMessagesBubblesSizeCalculator] superSize.height:%f, superSize.width:%f",
|
||||
// superSize.height,
|
||||
|
@ -35,11 +67,112 @@
|
|||
// header icon hangs ouside of the frame a bit.
|
||||
CGFloat headerIconProtrusion = 30.0f; // too much padding with normal font.
|
||||
// CGFloat headerIconProtrusion = 18.0f; // clips
|
||||
superSize.height = superSize.height + headerIconProtrusion;
|
||||
size.height += headerIconProtrusion;
|
||||
}
|
||||
}
|
||||
|
||||
return superSize;
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
* iOS10 bug in rendering emoji requires to fudge some things in the middle of the super method.
|
||||
* Copy/pasted the superclass method and inlined (and marked) our hacks inline.
|
||||
*/
|
||||
- (CGSize)withiOS10EmojiFixSuperMessageBubbleSizeForMessageData:(id<JSQMessageData>)messageData
|
||||
atIndexPath:(NSIndexPath *)indexPath
|
||||
withLayout:(JSQMessagesCollectionViewFlowLayout *)layout
|
||||
{
|
||||
NSValue *cachedSize = [self.cache objectForKey:@([messageData messageHash])];
|
||||
if (cachedSize != nil) {
|
||||
return [cachedSize CGSizeValue];
|
||||
}
|
||||
|
||||
CGSize finalSize = CGSizeZero;
|
||||
|
||||
if ([messageData isMediaMessage]) {
|
||||
finalSize = [[messageData media] mediaViewDisplaySize];
|
||||
} else {
|
||||
CGSize avatarSize = [self jsq_avatarSizeForMessageData:messageData withLayout:layout];
|
||||
|
||||
// from the cell xibs, there is a 2 point space between avatar and bubble
|
||||
CGFloat spacingBetweenAvatarAndBubble = 2.0f;
|
||||
CGFloat horizontalContainerInsets = layout.messageBubbleTextViewTextContainerInsets.left
|
||||
+ layout.messageBubbleTextViewTextContainerInsets.right;
|
||||
CGFloat horizontalFrameInsets
|
||||
= layout.messageBubbleTextViewFrameInsets.left + layout.messageBubbleTextViewFrameInsets.right;
|
||||
|
||||
CGFloat horizontalInsetsTotal
|
||||
= horizontalContainerInsets + horizontalFrameInsets + spacingBetweenAvatarAndBubble;
|
||||
CGFloat maximumTextWidth = [self textBubbleWidthForLayout:layout] - avatarSize.width
|
||||
- layout.messageBubbleLeftRightMargin - horizontalInsetsTotal;
|
||||
|
||||
///////////////////
|
||||
// BEGIN HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
|
||||
// //stringRect doesn't give the correct size with the new emoji font.
|
||||
// CGRect stringRect = [[messageData text] boundingRectWithSize:CGSizeMake(maximumTextWidth, CGFLOAT_MAX)
|
||||
// options:(NSStringDrawingUsesLineFragmentOrigin |
|
||||
// NSStringDrawingUsesFontLeading)
|
||||
// attributes:@{ NSFontAttributeName :
|
||||
// layout.messageBubbleFont }
|
||||
// context:nil];
|
||||
|
||||
CGRect stringRect;
|
||||
if (!messageData.text) {
|
||||
stringRect = CGRectZero;
|
||||
} else {
|
||||
NSDictionary *attributes = @{ NSFontAttributeName : layout.messageBubbleFont };
|
||||
NSMutableAttributedString *string =
|
||||
[[NSMutableAttributedString alloc] initWithString:[messageData text] attributes:attributes];
|
||||
[string fixAttributesInRange:NSMakeRange(0, string.length)];
|
||||
[string
|
||||
enumerateAttribute:NSFontAttributeName
|
||||
inRange:NSMakeRange(0, string.length)
|
||||
options:0
|
||||
usingBlock:^(id _Nullable value, NSRange range, BOOL *_Nonnull stop) {
|
||||
UIFont *font = (UIFont *)value;
|
||||
if ([font.fontName isEqualToString:@".AppleColorEmojiUI"]) {
|
||||
DDLogVerbose(@"Replacing new broken emoji font with old emoji font at location: %lu, "
|
||||
@"for length: %lu",
|
||||
(unsigned long)range.location,
|
||||
(unsigned long)range.length);
|
||||
[string addAttribute:NSFontAttributeName
|
||||
value:[UIFont fontWithName:@"AppleColorEmoji" size:font.pointSize]
|
||||
range:range];
|
||||
}
|
||||
}];
|
||||
stringRect =
|
||||
[string boundingRectWithSize:CGSizeMake(maximumTextWidth, CGFLOAT_MAX)
|
||||
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
|
||||
context:nil];
|
||||
}
|
||||
// END HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
/////////////////////////
|
||||
|
||||
CGSize stringSize = CGRectIntegral(stringRect).size;
|
||||
|
||||
CGFloat verticalContainerInsets = layout.messageBubbleTextViewTextContainerInsets.top
|
||||
+ layout.messageBubbleTextViewTextContainerInsets.bottom;
|
||||
CGFloat verticalFrameInsets
|
||||
= layout.messageBubbleTextViewFrameInsets.top + layout.messageBubbleTextViewFrameInsets.bottom;
|
||||
|
||||
// add extra 2 points of space (`self.additionalInset`), because `boundingRectWithSize:` is slightly off
|
||||
// not sure why. magix. (shrug) if you know, submit a PR
|
||||
CGFloat verticalInsets = verticalContainerInsets + verticalFrameInsets + self.additionalInset;
|
||||
|
||||
// same as above, an extra 2 points of magix
|
||||
CGFloat finalWidth
|
||||
= MAX(stringSize.width + horizontalInsetsTotal, self.minimumBubbleWidth) + self.additionalInset;
|
||||
|
||||
finalSize = CGSizeMake(finalWidth, stringSize.height + verticalInsets);
|
||||
}
|
||||
|
||||
[self.cache setObject:[NSValue valueWithCGSize:finalSize] forKey:@([messageData messageHash])];
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -741,6 +741,9 @@ typedef enum : NSUInteger {
|
|||
{
|
||||
JSQMessagesCollectionViewCell *cell =
|
||||
(JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath];
|
||||
// BEGIN HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
[self fixupiOS10EmojiBugForTextView:cell.textView];
|
||||
// END HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
if (!message.isMediaMessage) {
|
||||
cell.textView.textColor = [UIColor ows_blackColor];
|
||||
cell.textView.linkTextAttributes = @{
|
||||
|
@ -758,6 +761,11 @@ typedef enum : NSUInteger {
|
|||
OWSOutgoingMessageCollectionViewCell *cell
|
||||
= (OWSOutgoingMessageCollectionViewCell *)[super collectionView:self.collectionView
|
||||
cellForItemAtIndexPath:indexPath];
|
||||
|
||||
// BEGIN HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
[self fixupiOS10EmojiBugForTextView:cell.textView];
|
||||
// END HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
|
||||
if (!message.isMediaMessage) {
|
||||
cell.textView.textColor = [UIColor whiteColor];
|
||||
cell.textView.linkTextAttributes = @{
|
||||
|
@ -768,6 +776,28 @@ typedef enum : NSUInteger {
|
|||
return cell;
|
||||
}
|
||||
|
||||
// BEGIN HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
- (void)fixupiOS10EmojiBugForTextView:(UITextView *)textView
|
||||
{
|
||||
BOOL isIOS10OrGreater =
|
||||
[[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 10 }];
|
||||
if (isIOS10OrGreater) {
|
||||
[textView.textStorage enumerateAttribute:NSFontAttributeName
|
||||
inRange:NSMakeRange(0, textView.textStorage.length)
|
||||
options:0
|
||||
usingBlock:^(id _Nullable value, NSRange range, BOOL *_Nonnull stop) {
|
||||
UIFont *font = (UIFont *)value;
|
||||
if ([font.fontName isEqualToString:@".AppleColorEmojiUI"]) {
|
||||
[textView.textStorage addAttribute:NSFontAttributeName
|
||||
value:[UIFont fontWithName:@"AppleColorEmoji"
|
||||
size:font.pointSize]
|
||||
range:range];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
// END HACK iOS10EmojiBug see: https://github.com/WhisperSystems/Signal-iOS/issues/1368
|
||||
|
||||
- (OWSCallCollectionViewCell *)loadCallCellForCall:(OWSCall *)call atIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
OWSCallCollectionViewCell *callCell = [self.collectionView dequeueReusableCellWithReuseIdentifier:[OWSCallCollectionViewCell cellReuseIdentifier]
|
||||
|
|
Loading…
Reference in a new issue