Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
bd695a7
Implements NSAttributedString Extension
jleandroperez Oct 31, 2014
00b49a7
Implements UITextView Extension
jleandroperez Oct 31, 2014
e898a13
Implements RichTextView
jleandroperez Oct 31, 2014
53b35ef
Updates project
jleandroperez Oct 31, 2014
8857fd2
NotificationDetailsViewController Cleanup
jleandroperez Oct 31, 2014
c467f68
Splits ReplyTextView and Mentions code
jleandroperez Oct 31, 2014
71f4c64
Code Cleanup
jleandroperez Oct 31, 2014
ccd94b3
RichTextView: Switching over to Autolayout
jleandroperez Nov 3, 2014
bbb9de5
RichTextView: Wrapping up extra UITextView properties
jleandroperez Nov 3, 2014
e0b74de
CommentTableViewCell: Switching over to RichTextView
jleandroperez Nov 3, 2014
14a097a
Nukes WPDynamicHeightTextView
jleandroperez Nov 3, 2014
d34e7a3
Notifications: Switching over to RichTextView
jleandroperez Nov 3, 2014
26e7793
NotificationBlock: Nukes range failsafe. Fixed backend side
jleandroperez Nov 3, 2014
daaceaa
NotificationBlock: Code cleanup
jleandroperez Nov 3, 2014
ed33360
NotificationBlock: Extension code cleanup
jleandroperez Nov 3, 2014
617ffcf
Updates Notifications WPStyleGuide Extension
jleandroperez Nov 3, 2014
151e0e2
NoteBlockText: Selectable by default
jleandroperez Nov 3, 2014
e0387f7
NoteBlockText: Code Cleanup
jleandroperez Nov 3, 2014
b45d81e
Notification: Wires badge derived property
jleandroperez Nov 3, 2014
69554fd
Updates Notifications WPStyleGuide Extension
jleandroperez Nov 3, 2014
ea0ced4
NotificationBlock: Extension code cleanup. Part II
jleandroperez Nov 3, 2014
9ae2bc0
Fixes CommentTableViewCell
jleandroperez Nov 3, 2014
d40ac38
NoteBlockTableViewCell: Nukes TODO
jleandroperez Nov 3, 2014
c5fe21b
Code Cleanup
jleandroperez Nov 3, 2014
39b9070
Merge remote-tracking branch 'origin/develop' into issue/2661-notific…
jleandroperez Nov 3, 2014
d0292ca
RichTextView: Implements Link-Press Helper
jleandroperez Nov 4, 2014
e5656a3
Updates RichTextView protocols
jleandroperez Nov 4, 2014
287f84d
Workaround to fix DTCoreText mess
jleandroperez Nov 4, 2014
bbbdc9f
Implements TextImageAttachment
jleandroperez Nov 4, 2014
1bc0033
NotificationBlock: Implements richAttributedText Helper
jleandroperez Nov 4, 2014
c295279
Merge remote-tracking branch 'origin/develop' into issue/2661-notific…
jleandroperez Nov 5, 2014
3280e53
Nukes TextImageAttachment
jleandroperez Nov 5, 2014
d836900
NoteBlockTextTableViewCell: Nukes RichTextView Helper
jleandroperez Nov 5, 2014
2f33d6c
NotificationDetails: Fixes alignments
jleandroperez Nov 5, 2014
7c9ef2f
Notification: Implements helper method
jleandroperez Nov 5, 2014
2d8417e
Updates ReplyTextView Location
jleandroperez Nov 5, 2014
3bb4d3c
Updates NotificationBlock richText Helper
jleandroperez Nov 5, 2014
e0354de
Notification: Updates helper methods
jleandroperez Nov 5, 2014
ed679a1
Updates Bridging Header
jleandroperez Nov 5, 2014
c96c403
Implements NotificationMediaDownloader
jleandroperez Nov 5, 2014
240fe0e
Wires NotificationMediaDownloader
jleandroperez Nov 5, 2014
c54c6d3
Nukes dead nib
jleandroperez Nov 5, 2014
745acd4
Merge branch 'develop' into issue/2661-notification-comments-rich-tex…
jleandroperez Nov 6, 2014
6e1f8c7
Merge branch 'develop' into issue/2661-notification-comments-rich-tex…
jleandroperez Nov 7, 2014
1c388df
Updating nibs: switching over to RichTextView
jleandroperez Nov 7, 2014
ffa9a1e
Notification Downloader: Updates signature
jleandroperez Nov 7, 2014
1188f4c
Notification Downloader: Updates callback sequence
jleandroperez Nov 7, 2014
32fdf71
RichTextView: Nukes redundant setters
jleandroperez Nov 7, 2014
f10796e
NotificationBlock: Compensates for Attachment Lengths
jleandroperez Nov 7, 2014
abe6c33
WPStyleGuide: Nukes unused method
jleandroperez Nov 7, 2014
236b45b
Notifications: Fixes line height clipping glitch
jleandroperez Nov 7, 2014
043f620
Notifications Storyboard: Updates constraints
jleandroperez Nov 7, 2014
b868541
NotificationMediaDownloader: Prevents dupe urls
jleandroperez Nov 7, 2014
b2db8fe
RichTextView: Updates autolayout settings
jleandroperez Nov 7, 2014
4e55ba0
Notification: Nukes titleOrUrl getter
jleandroperez Nov 7, 2014
6f833bd
Decouples Image Embed Helpers
jleandroperez Nov 7, 2014
65f395c
Notifications: Caps Media Embeds size. If needed
jleandroperez Nov 7, 2014
11ef5aa
Notifications: Fixes Site flickering
jleandroperez Nov 10, 2014
3de2170
Fixes autolayout warning
jleandroperez Nov 10, 2014
2f160c4
Merge remote-tracking branch 'origin/develop' into issue/2661-notific…
jleandroperez Nov 11, 2014
aaa7319
Updates storyboard constraints
jleandroperez Nov 11, 2014
ea25548
NoteBlockText: Nukes attachment resize
jleandroperez Nov 11, 2014
20e7850
Updates Swift Bridging Header
jleandroperez Nov 11, 2014
82dbfb2
Notifications Media Downloader: Implements async resize
jleandroperez Nov 11, 2014
add3507
Wires Notification Downloader Resizer
jleandroperez Nov 11, 2014
585273a
Notification Media Downloader: Wires Max retry Count
jleandroperez Nov 11, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions WordPress/Classes/Extensions/NSAttributedString+Helpers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Foundation


extension NSAttributedString
{
/**
Note:
This method will embed a collection of assets, in the specified NSRange's. Since NSRange is an ObjC struct,
you'll need to wrap it up into a NSValue instance!
*/
public func stringByEmbeddingImageAttachments(embeds: [NSValue: UIImage]?) -> NSAttributedString {
// Allow nil embeds: behave as a simple NO-OP
if embeds == nil {
return self
}

// Proceed embedding!
let unwrappedEmbeds = embeds!
let theString = self.mutableCopy() as NSMutableAttributedString
var rangeDelta = 0

for (value, image) in unwrappedEmbeds {
let imageAttachment = NSTextAttachment()
imageAttachment.bounds = CGRect(origin: CGPointZero, size: image.size)
imageAttachment.image = image

// Each embed is expected to add 1 char to the string. Compensate for that
let attachmentString = NSAttributedString(attachment: imageAttachment)
var correctedRange = value.rangeValue
correctedRange.location += rangeDelta

// Bounds Safety
let lastPosition = correctedRange.location + correctedRange.length
if lastPosition <= theString.length {
theString.replaceCharactersInRange(correctedRange, withAttributedString: attachmentString)
}

rangeDelta += attachmentString.length

}

return theString
}
}
8 changes: 6 additions & 2 deletions WordPress/Classes/Extensions/NSParagraphStyle+Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import Foundation

extension NSMutableParagraphStyle
{
convenience init(minLineHeight: CGFloat, maxLineHeight: CGFloat, lineBreakMode: NSLineBreakMode, alignment: NSTextAlignment) {
convenience init(minLineHeight: CGFloat, lineBreakMode: NSLineBreakMode, alignment: NSTextAlignment) {
self.init()
self.minimumLineHeight = minLineHeight
self.maximumLineHeight = maxLineHeight
self.lineBreakMode = lineBreakMode
self.alignment = alignment
}

convenience init(minLineHeight: CGFloat, maxLineHeight: CGFloat, lineBreakMode: NSLineBreakMode, alignment: NSTextAlignment) {
self.init(minLineHeight: minLineHeight, lineBreakMode: lineBreakMode, alignment: alignment)
self.maximumLineHeight = maxLineHeight
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,71 +4,85 @@ import Foundation
extension NotificationBlock
{
public func subjectAttributedText() -> NSAttributedString {
if text == nil {
return NSAttributedString()
}

let theString = NSMutableAttributedString(string: text, attributes: WPStyleGuide.Notifications.subjectRegularStyle)

theString.applyAttributesToQuotes(WPStyleGuide.Notifications.subjectItalicsStyle)

for notificationRange in ranges as [NotificationRange] {

// Make sure this range is not of bounds!
let range = notificationRange.range
if range.location + range.length > theString.length {
continue
}

if notificationRange.isUser {
theString.addAttributes(WPStyleGuide.Notifications.subjectBoldStyle, range: range)
} else if notificationRange.isPost || notificationRange.isComment {
theString.addAttributes(WPStyleGuide.Notifications.subjectItalicsStyle, range: range)
}
}

return theString;
return textWithRangeStyles(isSubject: true)
}

public func snippetAttributedText() -> NSAttributedString {
if text == nil {
return NSAttributedString()
}

return NSMutableAttributedString(string: text, attributes: WPStyleGuide.Notifications.snippetRegularStyle)
return NSAttributedString(string: text, attributes: Styles.snippetRegularStyle)
}

public func regularAttributedText() -> NSAttributedString {
public func richAttributedText() -> NSAttributedString {
// Operations such as editing a comment cause a lag between the REST and Simperium update.
// TextOverride is a transient property meant to store, temporarily, the edited text
if textOverride != nil {
return NSAttributedString(string: textOverride, attributes: Styles.blockRegularStyle)
}

return textWithRangeStyles(isSubject: false)
}

public func buildRangesToImagesMap(mediaMap: [NSURL: UIImage]?) -> [NSValue: UIImage]? {
// If we've got a text override: Ranges may not match, and the new text may not even contain ranges!
if mediaMap == nil || textOverride != nil {
return nil
}

var ranges = [NSValue: UIImage]()

for theMedia in media as [NotificationMedia] {
if let image = mediaMap![theMedia.mediaURL] {
let rangeValue = NSValue(range: theMedia.range)
ranges[rangeValue] = image
}
}

return ranges
}


// MARK: - Private Helpers
private func textWithRangeStyles(#isSubject: Bool) -> NSAttributedString {
if text == nil {
return NSAttributedString()
}

let theString = NSMutableAttributedString(string: text, attributes: WPStyleGuide.Notifications.blockRegularStyle)
// Setup the styles
let regularStyle = isSubject ? Styles.subjectRegularStyle : (isBadge ? Styles.blockBadgeStyle : Styles.blockRegularStyle)
let quotesStyle = isSubject ? Styles.subjectItalicsStyle : Styles.blockBoldStyle
let userStyle = isSubject ? Styles.subjectBoldStyle : Styles.blockBoldStyle
let postStyle = isSubject ? Styles.subjectItalicsStyle : Styles.blockItalicsStyle
let commentStyle = postStyle
let blockStyle = Styles.blockQuotedStyle

theString.applyAttributesToQuotes(WPStyleGuide.Notifications.blockBoldStyle)
// Format the String
let theString = NSMutableAttributedString(string: text, attributes: regularStyle)
theString.applyAttributesToQuotes(quotesStyle)

for range in ranges as [NotificationRange] {
if range.isPost {
theString.addAttributes(WPStyleGuide.Notifications.blockItalicsStyle, range: range.range)
if range.isUser {
theString.addAttributes(userStyle, range: range.range)
} else if range.isPost {
theString.addAttributes(postStyle, range: range.range)
} else if range.isComment {
theString.addAttributes(commentStyle, range: range.range)
} else if range.isBlockquote {
theString.addAttributes(WPStyleGuide.Notifications.blockQuotedStyle, range: range.range)
theString.addAttributes(blockStyle, range: range.range)
}

if range.url != nil {
// Don't Highlight Links in the subject
if isSubject == false && range.url != nil {
theString.addAttribute(NSLinkAttributeName, value: range.url, range: range.range)
theString.addAttribute(NSForegroundColorAttributeName, value: WPStyleGuide.Notifications.blockLinkColor, range: range.range)
theString.addAttribute(NSForegroundColorAttributeName, value: Styles.blockLinkColor, range: range.range)
}
}

return theString
}

public func regularAttributedTextOverride() -> NSAttributedString? {
// Operations such as editing a comment cause a lag between the REST and Simperium update.
// TextOverride is a transient property meant to store, temporarily, the edited text
if textOverride != nil {
return NSAttributedString(string: textOverride, attributes: WPStyleGuide.Notifications.blockRegularStyle)
}
return nil
}

private typealias Styles = WPStyleGuide.Notifications
}

16 changes: 10 additions & 6 deletions WordPress/Classes/Models/Notifications/Notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ extern NSString * NoteActionReplyKey;
extern NSString * NoteActionApproveKey;
extern NSString * NoteActionEditKey;

extern NSString * NoteMediaTypeImage;

typedef NS_ENUM(NSInteger, NoteBlockType)
{
NoteBlockTypeText,
NoteBlockTypeImage, // BlockTypesImage: Includes Badges and Images
NoteBlockTypeImage, // BlockTypesImage: Includes Badges and Images
NoteBlockTypeUser,
NoteBlockTypeComment
};
Expand All @@ -32,9 +34,9 @@ typedef NS_ENUM(NSInteger, NoteBlockGroupType)
NoteBlockGroupTypeText = NoteBlockTypeText,
NoteBlockGroupTypeImage = NoteBlockTypeImage,
NoteBlockGroupTypeUser = NoteBlockTypeUser,
NoteBlockGroupTypeComment = NoteBlockTypeComment, // Contains a User + Comment Block
NoteBlockGroupTypeSubject = 20, // Contains a User + Text Block
NoteBlockGroupTypeHeader = 30 // Contains a User + Text Block
NoteBlockGroupTypeComment = NoteBlockTypeComment, // Contains a User + Comment Block
NoteBlockGroupTypeSubject = 20, // Contains a User + Text Block
NoteBlockGroupTypeHeader = 30 // Contains a User + Text Block
};


Expand Down Expand Up @@ -94,6 +96,7 @@ typedef NS_ENUM(NSInteger, NoteBlockGroupType)
@property (nonatomic, assign, readonly) NoteBlockGroupType type;

- (NotificationBlock *)blockOfType:(NoteBlockType)type;
- (NSSet *)imageUrlsForBlocksOfTypes:(NSSet *)types;

@end

Expand All @@ -111,17 +114,18 @@ typedef NS_ENUM(NSInteger, NoteBlockGroupType)
@property (nonatomic, strong, readonly) NSDictionary *actions;

// Derived Properties
@property (nonatomic, assign, readonly) NoteBlockType type;
@property (nonatomic, assign, readonly) NoteBlockType type;
@property (nonatomic, assign, readonly) BOOL isBadge;
@property (nonatomic, strong, readonly) NSNumber *metaSiteID;
@property (nonatomic, strong, readonly) NSNumber *metaCommentID;
@property (nonatomic, strong, readonly) NSString *metaLinksHome;
@property (nonatomic, strong, readonly) NSString *metaTitlesHome;
@property (nonatomic, strong, readonly) NSString *metaTitleOrUrl;

// Overrides
@property (nonatomic, strong, readwrite) NSString *textOverride;

- (NotificationRange *)notificationRangeWithUrl:(NSURL *)url;
- (NSArray *)imageUrls;

- (void)setActionOverrideValue:(NSNumber *)obj forKey:(NSString *)key;
- (void)removeActionOverrideForKey:(NSString *)key;
Expand Down
69 changes: 52 additions & 17 deletions WordPress/Classes/Models/Notifications/Notification.m
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ + (NSArray *)mediaFromArray:(NSArray *)rawMedia

@interface NotificationBlock ()
@property (nonatomic, strong, readwrite) NSMutableDictionary *actionsOverride;
@property (nonatomic, assign, readwrite) NoteBlockType type;
@property (nonatomic, assign, readwrite) NoteBlockType type;
@property (nonatomic, assign, readwrite) BOOL isBadge;
@end


Expand Down Expand Up @@ -245,15 +246,6 @@ - (NSString *)metaTitlesHome
return [[self.meta dictionaryForKey:NoteTitlesKey] stringForKey:NoteHomeKey];
}

- (NSString *)metaTitleOrUrl
{
if ([self metaTitlesHome]) {
return [self metaTitlesHome];
}

return self.metaLinksHome.hostname;
}

- (NotificationRange *)notificationRangeWithUrl:(NSURL *)url
{
for (NotificationRange *range in self.ranges) {
Expand All @@ -265,6 +257,19 @@ - (NotificationRange *)notificationRangeWithUrl:(NSURL *)url
return nil;
}

- (NSArray *)imageUrls
{
NSMutableArray *urls = [NSMutableArray array];

for (NotificationMedia *media in self.media) {
if (media.isImage && media.mediaURL != nil) {
[urls addObject:media.mediaURL];
}
}

return urls;
}

- (void)setActionOverrideValue:(NSNumber *)value forKey:(NSString *)key
{
if (!_actionsOverride) {
Expand Down Expand Up @@ -301,6 +306,7 @@ + (NSArray *)blocksFromArray:(NSArray *)rawBlocks notification:(Notification *)n
}

NSMutableArray *parsed = [NSMutableArray array];
BOOL isBadge = false;

for (NSDictionary *rawDict in rawBlocks) {
if (![rawDict isKindOfClass:[NSDictionary class]]) {
Expand Down Expand Up @@ -330,11 +336,24 @@ + (NSArray *)blocksFromArray:(NSArray *)rawBlocks notification:(Notification *)n
} else {
block.type = NoteBlockTypeText;
}


// Figure out if this is a badge
for (NotificationMedia *media in block.media) {
if (media.isBadge) {
isBadge = true;
}
}

[parsed addObject:block];
}

// Note: Seriously. Duck typing should be abolished.
if (isBadge) {
for (NotificationBlock *block in parsed) {
block.isBadge = true;
}
}

return parsed;
}

Expand All @@ -346,8 +365,8 @@ + (NSArray *)blocksFromArray:(NSArray *)rawBlocks notification:(Notification *)n
#pragma mark ====================================================================================

@interface NotificationBlockGroup ()
@property (nonatomic, strong) NSArray *blocks;
@property (nonatomic, assign) NoteBlockGroupType type;
@property (nonatomic, strong) NSArray *blocks;
@property (nonatomic, assign) NoteBlockGroupType type;
@end

@implementation NotificationBlockGroup
Expand All @@ -362,6 +381,24 @@ - (NotificationBlock *)blockOfType:(NoteBlockType)type
return nil;
}

- (NSSet *)imageUrlsForBlocksOfTypes:(NSSet *)types
{
NSMutableSet *urls = [NSMutableSet set];

for (NotificationBlock *block in self.blocks) {
if ([types containsObject:@(block.type)] == false) {
continue;
}

NSArray *imageUrls = [block imageUrls];
if (imageUrls) {
[urls addObjectsFromArray:imageUrls];
}
}

return urls;
}

+ (NotificationBlockGroup *)groupWithBlocks:(NSArray *)blocks type:(NoteBlockGroupType)type
{
NotificationBlockGroup *group = [self new];
Expand Down Expand Up @@ -549,10 +586,8 @@ - (BOOL)isBadge
//
for (NotificationBlockGroup *group in self.bodyBlockGroups) {
for (NotificationBlock *block in group.blocks) {
for (NotificationMedia *media in block.media) {
if (media.isBadge) {
return true;
}
if (block.isBadge) {
return true;
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions WordPress/Classes/System/WordPress-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#import <AFNetworking/AFNetworking.h>
#import <AFNetworking/UIKit+AFNetworking.h>

#import <MGImageUtilities/UIImage+ProportionalFill.h>

#import "Notification.h"

#import "DDLogSwift.h"
Expand Down
Loading