-
Notifications
You must be signed in to change notification settings - Fork 16
Re-implement RemoteReaderPost
in Swift - Part 1
#561
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
crazytonyli
wants to merge
9
commits into
translate-objc-to-swift
Choose a base branch
from
swift-translation-reader-post-1
base: translate-objc-to-swift
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
3affe26
Re-implement `RemoteReaderPost.readingTimeForWordCount`
crazytonyli b9794b2
Re-implement `RemoteReaderPost.authorEmailFromAuthorDictionary`
crazytonyli c1767fe
Re-implement `RemoteReaderPost.isWPComFromPostDictionary`
crazytonyli a556894
Re-implement `RemoteReaderPost.tagsFromPostDictionary`
crazytonyli 6e6b7e5
Re-implement `RemoteReaderPost.siteNameFromPostDictionary`
crazytonyli 56b6801
Re-implement `RemoteReaderPost.siteURLFromPostDictionary`
crazytonyli 2ed47f4
Re-implement RemoteReaderPost's isAtomic and isPrivate
crazytonyli 0d5e0bd
Remove semicolons
crazytonyli 22d40bc
Merge branch 'translate-objc-to-swift' into swift-translation-reader-…
crazytonyli File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Foundation | ||
|
||
struct ReaderPostsEnvelope: Decodable { | ||
var posts: [RemoteReaderPost] | ||
var nextPageHandle: String? | ||
|
||
private enum CodingKeys: String, CodingKey { | ||
case posts | ||
case nextPageHandle = "next_page_handle" | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
let postDictionary = try container.decode([String: Any].self, forKey: .posts) | ||
posts = [RemoteReaderPost(dictionary: postDictionary)] | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,6 @@ | |
NSString * const PostRESTKeyDiscoverMetadata = @"discover_metadata"; | ||
NSString * const PostRESTKeyDiscussion = @"discussion"; | ||
NSString * const PostRESTKeyEditorial = @"editorial"; | ||
NSString * const PostRESTKeyEmail = @"email"; | ||
NSString * const PostRESTKeyExcerpt = @"excerpt"; | ||
NSString * const PostRESTKeyFeaturedMedia = @"featured_media"; | ||
NSString * const PostRESTKeyFeaturedImage = @"featured_image"; | ||
|
@@ -41,10 +40,6 @@ | |
NSString * const PostRESTKeyScore = @"score"; | ||
NSString * const PostRESTKeySharingEnabled = @"sharing_enabled"; | ||
NSString * const PostRESTKeySiteID = @"site_ID"; | ||
NSString * const PostRESTKeySiteIsAtomic = @"site_is_atomic"; | ||
NSString * const PostRESTKeySiteIsPrivate = @"site_is_private"; | ||
NSString * const PostRESTKeySiteName = @"site_name"; | ||
NSString * const PostRESTKeySiteURL = @"site_URL"; | ||
NSString * const PostRESTKeySlug = @"slug"; | ||
NSString * const PostRESTKeyStatus = @"status"; | ||
NSString * const PostRESTKeyTitle = @"title"; | ||
|
@@ -74,8 +69,6 @@ | |
NSString * const CrossPostMetaXPostOrigin = @"xpost_origin"; | ||
NSString * const CrossPostMetaCommentPrefix = @"comment-"; | ||
|
||
static const NSInteger AvgWordsPerMinuteRead = 250; | ||
static const NSInteger MinutesToReadThreshold = 2; | ||
static const NSUInteger ReaderPostTitleLength = 30; | ||
|
||
@implementation RemoteReaderPost | ||
|
@@ -95,12 +88,12 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict; | |
self.author = [self stringOrEmptyString:[authorDict stringForKey:PostRESTKeyNiceName]]; // typically the author's screen name | ||
self.authorAvatarURL = [self stringOrEmptyString:[authorDict stringForKey:PostRESTKeyAvatarURL]]; | ||
self.authorDisplayName = [[self stringOrEmptyString:[authorDict stringForKey:PostRESTKeyName]] stringByDecodingXMLCharacters]; // Typically the author's given name | ||
self.authorEmail = [self authorEmailFromAuthorDictionary:authorDict]; | ||
self.authorEmail = [RemoteReaderPost authorEmailFromAuthorDictionary:authorDict]; | ||
self.authorURL = [self stringOrEmptyString:[authorDict stringForKey:PostRESTKeyURL]]; | ||
self.siteIconURL = [self stringOrEmptyString:[dict stringForKeyPath:@"meta.data.site.icon.img"]]; | ||
self.blogName = [self siteNameFromPostDictionary:dict]; | ||
self.blogName = [RemoteReaderPost siteNameFromPostDictionary:dict]; | ||
self.blogDescription = [self siteDescriptionFromPostDictionary:dict]; | ||
self.blogURL = [self siteURLFromPostDictionary:dict]; | ||
self.blogURL = [RemoteReaderPost siteURLFromPostDictionary:dict]; | ||
self.commentCount = [discussionDict numberForKey:PostRESTKeyCommentCount]; | ||
self.commentsOpen = [[discussionDict numberForKey:PostRESTKeyCommentsOpen] boolValue]; | ||
self.content = [self postContentFromPostDictionary:dict]; | ||
|
@@ -109,12 +102,12 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict; | |
self.feedID = [dict numberForKey:PostRESTKeyFeedID]; | ||
self.feedItemID = [dict numberForKey:PostRESTKeyFeedItemID]; | ||
self.globalID = [self stringOrEmptyString:[dict stringForKey:PostRESTKeyGlobalID]]; | ||
self.isBlogAtomic = [self siteIsAtomicFromPostDictionary:dict]; | ||
self.isBlogPrivate = [self siteIsPrivateFromPostDictionary:dict]; | ||
self.isBlogAtomic = [RemoteReaderPost siteIsAtomicFromPostDictionary:dict]; | ||
self.isBlogPrivate = [RemoteReaderPost siteIsPrivateFromPostDictionary:dict]; | ||
self.isFollowing = [[dict numberForKey:PostRESTKeyIsFollowing] boolValue]; | ||
self.isLiked = [[dict numberForKey:PostRESTKeyILike] boolValue]; | ||
self.isReblogged = [[dict numberForKey:PostRESTKeyIsReblogged] boolValue]; | ||
self.isWPCom = [self isWPComFromPostDictionary:dict]; | ||
self.isWPCom = [RemoteReaderPost isWPComFromPostDictionary:dict]; | ||
self.likeCount = [dict numberForKey:PostRESTKeyLikeCount]; | ||
self.permalink = [self stringOrEmptyString:[dict stringForKey:PostRESTKeyURL]]; | ||
self.postID = [dict numberForKey:PostRESTKeyID]; | ||
|
@@ -125,7 +118,7 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict; | |
self.sortRank = @(self.sortDate.timeIntervalSinceReferenceDate); | ||
self.status = [self stringOrEmptyString:[dict stringForKey:PostRESTKeyStatus]]; | ||
self.summary = [self postSummaryFromPostDictionary:dict orPostContent:self.content]; | ||
self.tags = [self tagsFromPostDictionary:dict]; | ||
self.tags = [RemoteReaderPost tagsFromPostDictionary:dict]; | ||
self.isSharingEnabled = [[dict numberForKey:PostRESTKeySharingEnabled] boolValue]; | ||
self.isLikesEnabled = [[dict numberForKey:PostRESTKeyLikesEnabled] boolValue]; | ||
self.organizationID = [dict numberForKeyPath:PostRESTKeyOrganizationID] ?: @0; | ||
|
@@ -157,7 +150,7 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict; | |
self.isExternal = [[dict numberForKey:PostRESTKeyIsExternal] boolValue]; | ||
self.isJetpack = [[dict numberForKey:PostRESTKeyIsJetpack] boolValue]; | ||
self.wordCount = [dict numberForKey:PostRESTKeyWordCount]; | ||
self.readingTime = [self readingTimeForWordCount:self.wordCount]; | ||
self.readingTime = [RemoteReaderPost readingTimeForWordCount:self.wordCount]; | ||
|
||
NSDictionary *railcar = [dict dictionaryForKey:PostRESTKeyRailcar]; | ||
if (railcar) { | ||
|
@@ -281,16 +274,6 @@ - (NSDictionary *)primaryAndSecondaryTagsFromPostDictionary:(NSDictionary *)dict | |
}; | ||
} | ||
|
||
- (NSNumber *)readingTimeForWordCount:(NSNumber *)wordCount | ||
{ | ||
NSInteger count = [wordCount integerValue]; | ||
NSInteger minutesToRead = count / AvgWordsPerMinuteRead; | ||
if (minutesToRead < MinutesToReadThreshold) { | ||
return @(0); | ||
} | ||
return @(minutesToRead); | ||
} | ||
|
||
/** | ||
Composes discover attribution if needed. | ||
|
||
|
@@ -394,55 +377,6 @@ - (NSString *)sanitizeFeaturedImageString:(NSString *)img | |
|
||
#pragma mark - Data sanitization methods | ||
|
||
/** | ||
The v1 API result is inconsistent in that it will return a 0 when there is no author email. | ||
|
||
@param dict The author dictionary. | ||
@return The author's email address or an empty string. | ||
*/ | ||
- (NSString *)authorEmailFromAuthorDictionary:(NSDictionary *)dict | ||
{ | ||
NSString *authorEmail = [dict stringForKey:PostRESTKeyEmail]; | ||
|
||
// if 0 or less than minimum email length. [email protected] | ||
if ([authorEmail isEqualToString:@"0"] || [authorEmail length] < 6) { | ||
authorEmail = @""; | ||
} | ||
|
||
return authorEmail; | ||
} | ||
|
||
/** | ||
Parse whether the post belongs to a wpcom blog. | ||
|
||
@param dict A dictionary representing a post object from the REST API | ||
@return YES if the post belongs to a wpcom blog, else NO | ||
*/ | ||
- (BOOL)isWPComFromPostDictionary:(NSDictionary *)dict | ||
{ | ||
BOOL isExternal = [[dict numberForKey:PostRESTKeyIsExternal] boolValue]; | ||
BOOL isJetpack = [[dict numberForKey:PostRESTKeyIsJetpack] boolValue]; | ||
|
||
return !isJetpack && !isExternal; | ||
} | ||
|
||
/** | ||
Get the tags assigned to a post and return them as a comma separated string. | ||
|
||
@param dict A dictionary representing a post object from the REST API. | ||
@return A comma separated list of tags, or an empty string if no tags are found. | ||
*/ | ||
- (NSString *)tagsFromPostDictionary:(NSDictionary *)dict | ||
{ | ||
NSDictionary *tagsDict = [dict dictionaryForKey:PostRESTKeyTags]; | ||
NSArray *tagsList = [NSArray arrayWithArray:[tagsDict allKeys]]; | ||
NSString *tags = [tagsList componentsJoinedByString:@", "]; | ||
if (tags == nil) { | ||
tags = @""; | ||
} | ||
return tags; | ||
} | ||
|
||
/** | ||
Get the date the post should be sorted by. | ||
|
||
|
@@ -528,32 +462,6 @@ - (NSString *)suitableImageFromPostContent:(NSDictionary *)dict { | |
return [self stringOrEmptyString:imageToDisplay]; | ||
} | ||
|
||
/** | ||
Get the name of the post's site. | ||
|
||
@param dict A dictionary representing a post object from the REST API. | ||
@return The name of the post's site or an empty string. | ||
*/ | ||
- (NSString *)siteNameFromPostDictionary:(NSDictionary *)dict | ||
{ | ||
// Blog Name | ||
NSString *siteName = [self stringOrEmptyString:[dict stringForKey:PostRESTKeySiteName]]; | ||
|
||
// For some endpoints blogname is defined in meta | ||
NSString *metaBlogName = [dict stringForKeyPath:@"meta.data.site.name"]; | ||
if (metaBlogName != nil) { | ||
siteName = metaBlogName; | ||
} | ||
|
||
// Values set in editorial trumps the rest | ||
NSString *editorialSiteName = [dict stringForKeyPath:@"editorial.blog_name"]; | ||
if (editorialSiteName != nil) { | ||
siteName = editorialSiteName; | ||
} | ||
|
||
return [self makePlainText:siteName]; | ||
} | ||
|
||
/** | ||
Get the description of the post's site. | ||
|
||
|
@@ -566,24 +474,6 @@ - (NSString *)siteDescriptionFromPostDictionary:(NSDictionary *)dict | |
return [self makePlainText:description]; | ||
} | ||
|
||
/** | ||
Retrives the post site's URL | ||
|
||
@param dict A dictionary representing a post object from the REST API. | ||
@return The URL path of the post's site. | ||
*/ | ||
- (NSString *)siteURLFromPostDictionary:(NSDictionary *)dict | ||
{ | ||
NSString *siteURL = [self stringOrEmptyString:[dict stringForKey:PostRESTKeySiteURL]]; | ||
|
||
NSString *metaSiteURL = [dict stringForKeyPath:@"meta.data.site.URL"]; | ||
if (metaSiteURL != nil) { | ||
siteURL = metaSiteURL; | ||
} | ||
|
||
return siteURL; | ||
} | ||
|
||
/** | ||
Retrives the post content from results dictionary | ||
|
||
|
@@ -623,31 +513,6 @@ - (NSString *)postSummaryFromPostDictionary:(NSDictionary *)dict orPostContent:( | |
return summary; | ||
} | ||
|
||
- (BOOL)siteIsAtomicFromPostDictionary:(NSDictionary *)dict | ||
{ | ||
NSNumber *isAtomic = [dict numberForKey:PostRESTKeySiteIsAtomic]; | ||
|
||
return [isAtomic boolValue]; | ||
} | ||
|
||
/** | ||
Retrives the privacy preference for the post's site. | ||
|
||
@param dict A dictionary representing a post object from the REST API. | ||
@return YES if the site is private. | ||
*/ | ||
- (BOOL)siteIsPrivateFromPostDictionary:(NSDictionary *)dict | ||
{ | ||
NSNumber *isPrivate = [dict numberForKey:PostRESTKeySiteIsPrivate]; | ||
|
||
NSNumber *metaIsPrivate = [dict numberForKeyPath:@"meta.data.site.is_private"]; | ||
if (metaIsPrivate != nil) { | ||
isPrivate = metaIsPrivate; | ||
} | ||
|
||
return [isPrivate boolValue]; | ||
} | ||
|
||
- (NSArray *)slugsFromDiscoverPostTaxonomies:(NSArray *)discoverPostTaxonomies | ||
{ | ||
return [discoverPostTaxonomies wp_map:^id(NSDictionary *dict) { | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import might be unnecessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's true for the current project setup. But I think it's needed for SPM support.