Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
67 changes: 35 additions & 32 deletions Sources/WordPressData/Objective-C/include/ReaderPost.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#import <CoreData/CoreData.h>
#import <WordPressData/BasePost.h>

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSUInteger, SourceAttributionStyle) {
SourceAttributionStyleNone,
SourceAttributionStylePost,
Expand All @@ -20,19 +22,19 @@ extern NSString * const ReaderPostStoredCommentTextKey;

@interface ReaderPost : BasePost

@property (nonatomic, strong) NSString *authorDisplayName;
@property (nonatomic, strong) NSString *authorEmail;
@property (nonatomic, strong) NSString *authorURL;
@property (nonatomic, strong) NSString *siteIconURL;
@property (nonatomic, strong) NSString *blogName;
@property (nonatomic, strong) NSString *blogDescription;
@property (nonatomic, strong) NSString *blogURL;
@property (nonatomic, strong) NSNumber *commentCount;
@property (nonatomic, strong, nullable) NSString *authorDisplayName;
@property (nonatomic, strong, nullable) NSString *authorEmail;
@property (nonatomic, strong, nullable) NSString *authorURL;
@property (nonatomic, strong, nullable) NSString *siteIconURL;
@property (nonatomic, strong, nullable) NSString *blogName;
@property (nonatomic, strong, nullable) NSString *blogDescription;
@property (nonatomic, strong, nullable) NSString *blogURL;
@property (nonatomic, strong, nullable) NSNumber *commentCount;
@property (nonatomic) BOOL commentsOpen;
@property (nonatomic, strong) NSString *featuredImage;
@property (nonatomic, strong) NSNumber *feedID;
@property (nonatomic, strong) NSNumber *feedItemID;
@property (nonatomic, strong) NSString *globalID;
@property (nonatomic, strong, nullable) NSString *featuredImage;
@property (nonatomic, strong, nullable) NSNumber *feedID;
@property (nonatomic, strong, nullable) NSNumber *feedItemID;
@property (nonatomic, strong, nullable) NSString *globalID;
@property (nonatomic) BOOL isBlogAtomic;
@property (nonatomic) BOOL isBlogPrivate;
@property (nonatomic) BOOL isFollowing;
Expand All @@ -42,47 +44,47 @@ extern NSString * const ReaderPostStoredCommentTextKey;
@property (nonatomic) BOOL isSavedForLater;
@property (nonatomic) BOOL isSeen;
@property (nonatomic) BOOL isSeenSupported;
@property (nonatomic, strong) NSNumber *organizationID;
@property (nonatomic, strong) NSNumber *likeCount;
@property (nonatomic, strong) NSNumber *score;
@property (nonatomic, strong) NSNumber *siteID;
@property (nonatomic) NSNumber *organizationID;
@property (nonatomic, strong, nullable) NSNumber *likeCount;
@property (nonatomic, strong, nullable) NSNumber *score;
@property (nonatomic, strong, nullable) NSNumber *siteID;
// Normalizes sorting between offset or sortDate depending on the flavor of post.
// Note that this can store a negative value.
@property (nonatomic, strong) NSNumber *sortRank;
@property (nonatomic) NSNumber *sortRank;
// Normalizes the date to sort by depending on the flavor of post.
@property (nonatomic, strong) NSDate *sortDate;
@property (nonatomic, strong) NSString *summary;
@property (nonatomic, strong) NSSet *comments;
@property (nonatomic, strong) NSString *tags;
@property (nonatomic, strong) ReaderAbstractTopic *topic;
@property (nonatomic, strong) NSSet<ReaderCard *> *card;
@property (nonatomic, strong, nullable) NSDate *sortDate;
@property (nonatomic, strong, nullable) NSString *summary;
@property (nonatomic, strong, nullable) NSSet *comments;
@property (nonatomic, strong, nullable) NSString *tags;
@property (nonatomic, strong, nullable) ReaderAbstractTopic *topic;
@property (nonatomic, strong, nullable) NSSet<ReaderCard *> *card;
@property (nonatomic) BOOL isLikesEnabled;
@property (nonatomic) BOOL isSharingEnabled;
@property (nonatomic) BOOL isSiteBlocked;
@property (nonatomic, strong) SourcePostAttribution *sourceAttribution;
@property (nonatomic, strong, nullable) SourcePostAttribution *sourceAttribution;
@property (nonatomic) BOOL isSubscribedComments;
@property (nonatomic) BOOL canSubscribeComments;
@property (nonatomic) BOOL receivesCommentNotifications;

@property (nonatomic, strong) NSString *primaryTag;
@property (nonatomic, strong) NSString *primaryTagSlug;
@property (nonatomic, strong, nullable) NSString *primaryTag;
@property (nonatomic, strong, nullable) NSString *primaryTagSlug;
@property (nonatomic) BOOL isExternal;
@property (nonatomic) BOOL isJetpack;
@property (nonatomic) NSNumber *wordCount;
@property (nonatomic) NSNumber *readingTime;
@property (nonatomic, strong) ReaderCrossPostMeta *crossPostMeta;
@property (nonatomic, strong) NSString *railcar;
@property (nonatomic, strong, nullable) NSNumber *wordCount;
@property (nonatomic, strong, nullable) NSNumber *readingTime;
@property (nonatomic, strong, nullable) ReaderCrossPostMeta *crossPostMeta;
@property (nonatomic, strong, nullable) NSString *railcar;

// Used for tracking when a post is rendered (displayed), and bumping the train tracks rendered event.
@property (nonatomic) BOOL rendered;

// When true indicates a post should not be deleted/cleaned-up as its currently being used.
@property (nonatomic) BOOL inUse;

+ (instancetype)createOrReplaceFromRemotePost:(RemoteReaderPost *)remotePost forTopic:(ReaderAbstractTopic *)topic context:(NSManagedObjectContext *) managedObjectContext;
+ (instancetype)createOrReplaceFromRemotePost:(RemoteReaderPost *)remotePost forTopic:(nullable ReaderAbstractTopic *)topic context:(NSManagedObjectContext *) managedObjectContext;

- (BOOL)contentIncludesFeaturedImage;
- (NSDictionary *)railcarDictionary;
- (nullable NSDictionary *)railcarDictionary;

@end

Expand All @@ -95,3 +97,4 @@ extern NSString * const ReaderPostStoredCommentTextKey;

@end

NS_ASSUME_NONNULL_END
7 changes: 6 additions & 1 deletion Sources/WordPressData/Swift/ReaderCard+CoreDataClass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ public class ReaderCard: NSManagedObject {

switch remoteCard.type {
case .post:
let post = ReaderPost.createOrReplace(fromRemotePost: remoteCard.post, for: nil, context: context)
let post: ReaderPost
if let remotePost = remoteCard.post {
post = ReaderPost.createOrReplace(fromRemotePost: remotePost, for: nil, context: context)
} else {
return nil
}

// Check if a card already exists with this post to prevent duplicates
if let existingCard = findExistingCard(with: post, context: context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ extension ReaderPost {
}

public var isP2Type: Bool {
guard let id = organizationID?.intValue, let type = SiteOrganizationType(rawValue: id) else { return false }
let id = organizationID.intValue
guard let type = SiteOrganizationType(rawValue: id) else { return false }
return type == .p2 || type == .automattic
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,11 @@ final class CommentService_RepliesTests: CoreDataTestCase {
}

// All comments are visible
XCTAssertEqual(post.comments.count, 24)
XCTAssertEqual(post.comments.filter({ ($0 as! Comment).visibleOnReader }).count, 24)
XCTAssertEqual(post.comments?.count, 24)
XCTAssertEqual(post.comments?.filter({ ($0 as! Comment).visibleOnReader }).count, 24)

// Mark a comment as spam
let spamComment = try XCTUnwrap(post.comments.first { ($0 as! Comment).commentID == 428668 }) as! Comment
let spamComment = try XCTUnwrap(post.comments?.first { ($0 as! Comment).commentID == 428668 }) as! Comment
spamComment.status = CommentStatusType.spam.description
contextManager.saveContextAndWait(mainContext)

Expand All @@ -282,8 +282,8 @@ final class CommentService_RepliesTests: CoreDataTestCase {
}

// The spam comment and its two replies are no longer visible
XCTAssertEqual(post.comments.count, 24)
XCTAssertEqual(post.comments.filter({ ($0 as! Comment).visibleOnReader }).count, 21)
XCTAssertEqual(post.comments?.count, 24)
XCTAssertEqual(post.comments?.filter({ ($0 as! Comment).visibleOnReader }).count, 21)
}
}

Expand Down
2 changes: 1 addition & 1 deletion WordPress/Classes/Services/NotificationSyncMediator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ private extension NotificationSyncMediator {
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [commentIDPredicate, siteIDPredicate])
if let post = try context.fetch(fetchRequest).first {
post.isLiked = isLike
post.likeCount = NSNumber(value: post.likeCount.intValue + (post.isLiked ? 1 : -1))
post.likeCount = NSNumber(value: max((post.likeCount?.intValue ?? 0) + (post.isLiked ? 1 : -1), 0))
}
}
catch {
Expand Down
2 changes: 1 addition & 1 deletion WordPress/Classes/Services/ReaderPostStreamService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ReaderPostStreamService {
posts.enumerated().forEach { index, remotePost in
let post = ReaderPost.createOrReplace(fromRemotePost: remotePost, for: readerTopic, context: context)
// To keep the API order
post?.sortRank = NSNumber(value: Date().timeIntervalSinceReferenceDate - Double(((self.pageNumber * Constants.paginationMultiplier) + index)))
post.sortRank = NSNumber(value: Date().timeIntervalSinceReferenceDate - Double(((self.pageNumber * Constants.paginationMultiplier) + index)))
}

// Clean up
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ final class CommentCreateViewModel {
wpAssert(siteID != 0, "missing required parameter siteID")
self._save = save

self.suggestionsViewModel = SuggestionsListViewModel.make(siteID: post.siteID)
self.suggestionsViewModel = SuggestionsListViewModel.make(siteID: self.siteID)
self.suggestionsViewModel?.enableProminentSuggestions(postAuthorID: post.authorID)
}

Expand Down
4 changes: 2 additions & 2 deletions WordPress/Classes/ViewRelated/Likes/LikesListController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ class LikesListController: NSObject {
///
init?(tableView: UITableView, post: ReaderPost, delegate: LikesListControllerDelegate? = nil) {

guard let postID = post.postID else {
guard let postID = post.postID, let siteID = post.siteID else {
return nil
}

content = .post(id: postID)
readerPost = post
siteID = post.siteID
self.siteID = siteID
self.tableView = tableView
self.delegate = delegate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ private final class ReaderCrossPostView: UIView {
}

private func makeHeaderString(for post: ReaderPost) -> NSAttributedString? {
guard let meta = post.crossPostMeta else {
guard let meta = post.crossPostMeta, let blogURL = post.blogURL else {
return nil
}
let template = meta.commentURL.isEmpty ? Strings.siteTemplate : Strings.commentTemplate

let authorName: NSString = (post.authorForDisplay() ?? "") as NSString
let siteName = subdomainNameFromPath(post.blogURL)
let siteName = subdomainNameFromPath(blogURL)
let originName = subdomainNameFromPath(meta.siteURL)

let subtitle = NSString(format: template as NSString, authorName, originName, siteName) as String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ final class ReaderCommentsViewController: UIViewController, WPContentSyncHelperD
return wpAssertionFailure("post missing")
}
var linkURL = url
if let components = URLComponents(string: url.absoluteString), components.host == nil {
linkURL = components.url(relativeTo: URL(string: post.blogURL)) ?? linkURL
if let components = URLComponents(string: url.absoluteString), components.host == nil, let blogURL = post.blogURL {
linkURL = components.url(relativeTo: URL(string: blogURL)) ?? linkURL
}
let configuration = WebViewControllerConfiguration(url: linkURL)
configuration.authenticateWithDefaultAccount()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class ReaderCellConfiguration {
return
}
let post = posts[indexPath.row]
cell.setSiteName(post.blogName)
cell.setSiteName(post.blogName ?? "-")
}

func configureGapMarker(_ cell: ReaderGapMarkerCell, filling: Bool) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ struct ReaderNotificationKeys {
guard
let siteID = post.siteID,
let postID = post.postID,
let host = NSURL(string: post.blogURL)?.host else {
let blogURL = post.blogURL,
let host = URL(string: blogURL)?.host() else {
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@ final class ReaderBlockSiteAction {
}

func execute(with post: ReaderPost, context: NSManagedObjectContext, completion: (() -> Void)? = nil, failure: ((Error?) -> Void)? = nil) {
guard let siteID = post.siteID else {
DispatchQueue.main.async {
failure?(nil)
}
return
}

let service = ReaderSiteService(coreDataStack: ContextManager.shared)
service.flagSite(withID: post.siteID,
service.flagSite(withID: siteID,
asBlocked: asBlocked,
success: {
WPAnalytics.trackReader(.readerBlogBlocked, properties: ["blogId": post.siteID as Any])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import WordPressData

final class ReaderHeaderAction {
func execute(post: ReaderPost, origin: UIViewController, source: ReaderStreamViewController.StatSource? = nil) {
let controller = ReaderStreamViewController.controllerWithSiteID(post.siteID, isFeed: post.isExternal)
guard let siteID = post.siteID else { return }

let controller = ReaderStreamViewController.controllerWithSiteID(siteID, isFeed: post.isExternal)
if let source {
controller.statSource = source
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,27 +115,27 @@ final class ReaderPostBlockingController {
}

@objc private func handleSiteBlockingWillBeginNotification(_ notification: Foundation.Notification) {
guard let post = notification.userInfo?[ReaderNotificationKeys.post] as? ReaderPost else {
guard let post = notification.userInfo?[ReaderNotificationKeys.post] as? ReaderPost, let siteID = post.siteID else {
return
}
self.ongoingSitesBlocking.insert(post.siteID)
self.ongoingSitesBlocking.insert(siteID)
self.delegate?.readerSiteBlockingController(self, willBeginBlockingSiteOfPost: post)
}

@objc private func handleBlockSiteNotification(_ notification: Foundation.Notification) {
guard let post = notification.userInfo?[ReaderNotificationKeys.post] as? ReaderPost else {
guard let post = notification.userInfo?[ReaderNotificationKeys.post] as? ReaderPost, let siteID = post.siteID else {
return
}
self.ongoingSitesBlocking.remove(post.siteID)
self.ongoingSitesBlocking.remove(siteID)
self.delegate?.readerSiteBlockingController(self, didBlockSiteOfPost: post, result: .success(()))
}

@objc private func handleSiteBlockingFailed(_ notification: Foundation.Notification) {
guard let post = notification.userInfo?[ReaderNotificationKeys.post] as? ReaderPost else {
guard let post = notification.userInfo?[ReaderNotificationKeys.post] as? ReaderPost, let siteID = post.siteID else {
return
}
let error = (notification.userInfo?[ReaderNotificationKeys.error] as? Error) ?? UnknownError()
self.ongoingSitesBlocking.remove(post.siteID)
self.ongoingSitesBlocking.remove(siteID)
self.delegate?.readerSiteBlockingController(self, didBlockSiteOfPost: post, result: .failure(error))
}

Expand Down
Loading