Skip to content

Show a toast message (notice) when moving posts to trash #21724

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

Merged
merged 12 commits into from
Oct 27, 2023
Merged
2 changes: 1 addition & 1 deletion RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
23.6
-----

* [***] [internal][Jetpack-only] [***] Added paid domain selection, plan selection, and checkout screens in site creation flow [#21688]
* [**] When moving a post to trash, show a toast message with undo action instead of an inline undo row. [#21724]
* [*] Site Domains: Fixed an issue where the message shared while adding a domain was inaccurate. [#21827]
* [*] Fix an issue where login with site address is blocked after failing the first attempt. [#21848]
* [*] Fix an issue with an issue [#16999] with HTML not being stripped from post titles [#21846]
Expand Down
4 changes: 0 additions & 4 deletions WordPress/Classes/Models/AbstractPost.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ typedef NS_ENUM(NSUInteger, AbstractPostRemoteStatus) {
// These are primarily used as helpers sorting fetchRequests.
@property (nonatomic, assign) BOOL metaIsLocal;
@property (nonatomic, assign) BOOL metaPublishImmediately;
/**
Used to store the post's status before its sent to the trash.
*/
@property (nonatomic, strong) NSString *restorableStatus;
/**
This array will contain a list of revision IDs.
*/
Expand Down
2 changes: 0 additions & 2 deletions WordPress/Classes/Models/AbstractPost.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ @implementation AbstractPost
@dynamic autosaveModifiedDate;
@dynamic autosaveIdentifier;

@synthesize restorableStatus;

+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
Expand Down
3 changes: 3 additions & 0 deletions WordPress/Classes/Services/PostRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ final class PostRepository {
return
}

let status = try await coreDataStack.performQuery { try $0.existingObject(with: postID).status }
assert(status == .trash, "This function can only be used to delete trashed posts/pages.")

Comment on lines 83 to +86
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first I was surprised to see the assert here and not at the start of the method. But I guess the reason is that the code above recur to find the original post, and for the same reason we want to delete the original, we want to check the status on it. Am I reading this right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This status check doesn't exist in the original delete function in PostService. I added it here to catch incorrect calls to this function (which may never happen).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// First delete the post from local database.
let (remote, remotePost) = try await coreDataStack.performAndSave { [remoteFactory] context in
let post = try context.existingObject(with: postID)
Expand Down
35 changes: 0 additions & 35 deletions WordPress/Classes/Services/PostService.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,41 +125,6 @@ forceDraftIfCreating:(BOOL)forceDraftIfCreating
success:(nullable void (^)(AbstractPost *post, NSString *previewURL))success
failure:(void (^)(NSError * _Nullable error))failure;

/**
Attempts to delete the specified post outright vs moving it to the
trash folder.

@param post The post or page to delete
@param success A success block
@param failure A failure block
*/
- (void)deletePost:(AbstractPost *)post
success:(nullable void (^)(void))success
failure:(void (^)(NSError * _Nullable error))failure;

/**
Moves the specified post into the trash bin. Does not delete
the post unless it was deleted on the server.

@param post The post or page to trash
@param success A success block
@param failure A failure block
*/
- (void)trashPost:(AbstractPost *)post
success:(nullable nullable void (^)(void))success
failure:(void (^)(NSError * _Nullable error))failure;

/**
Moves the specified post out of the trash bin.

@param post The post or page to restore
@param success A success block
@param failure A failure block
*/
- (void)restorePost:(AbstractPost *)post
success:(nullable void (^)(void))success
failure:(void (^)(NSError * _Nullable error))failure;

@end

NS_ASSUME_NONNULL_END
189 changes: 0 additions & 189 deletions WordPress/Classes/Services/PostService.m
Original file line number Diff line number Diff line change
Expand Up @@ -449,195 +449,6 @@ - (void)handleAutoSaveWithRestRemote:(PostServiceRemoteREST *)restRemote

}

#pragma mark - Delete, Trashing, Restoring

- (void)deletePost:(AbstractPost *)post
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure
{
void (^privateBlock)(void) = ^void() {
NSNumber *postID = post.postID;
if ([postID longLongValue] > 0) {
RemotePost *remotePost = [PostHelper remotePostWithPost:post];
id<PostServiceRemote> remote = [self.postServiceRemoteFactory forBlog:post.blog];
[remote deletePost:remotePost success:success failure:failure];
}
[self.managedObjectContext deleteObject:post];
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];
};

if ([post isRevision]) {
[self deletePost:post.original success:privateBlock failure:failure];
} else {
privateBlock();
}
}

- (void)trashPost:(AbstractPost *)post
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure
{
if ([post.status isEqualToString:PostStatusTrash]) {
[self deletePost:post success:success failure:failure];
return;
}

void(^privateBodyBlock)(void) = ^void() {
post.restorableStatus = post.status;

NSNumber *postID = post.postID;

if ([post isRevision] || [postID longLongValue] <= 0) {
post.status = PostStatusTrash;

if (success) {
success();
}

return;
}

[self trashRemotePostWithPost:post
success:success
failure:failure];
};

if ([post isRevision]) {
[self trashPost:post.original
success:privateBodyBlock
failure:failure];
} else {
privateBodyBlock();
}
}

- (void)trashRemotePostWithPost:(AbstractPost*)post
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure
{
NSManagedObjectID *postObjectID = post.objectID;

void (^successBlock)(RemotePost *post) = ^(RemotePost *remotePost) {
NSError *err;
Post *postInContext = (Post *)[self.managedObjectContext existingObjectWithID:postObjectID error:&err];
if (err) {
DDLogError(@"%@", err);
}
if (postInContext) {
if (!remotePost || [remotePost.status isEqualToString:PostStatusDeleted]) {
[self.managedObjectContext deleteObject:post];
} else {
[PostHelper updatePost:postInContext withRemotePost:remotePost inContext:self.managedObjectContext];
postInContext.latest.statusAfterSync = postInContext.statusAfterSync;
postInContext.latest.status = postInContext.status;
}
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];
}
if (success) {
success();
}
};

void (^failureBlock)(NSError *error) = ^(NSError *error) {
NSError *err;
Post *postInContext = (Post *)[self.managedObjectContext existingObjectWithID:postObjectID error:&err];
if (err) {
DDLogError(@"%@", err);
}
if (postInContext) {
postInContext.restorableStatus = nil;
}
if (failure){
failure(error);
}
};

RemotePost *remotePost = [PostHelper remotePostWithPost:post];
id<PostServiceRemote> remote = [self.postServiceRemoteFactory forBlog:post.blog];
[remote trashPost:remotePost success:successBlock failure:failureBlock];
}

- (void)restorePost:(AbstractPost *)post
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure
{
void (^privateBodyBlock)(void) = ^void() {
post.status = post.restorableStatus;
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];

if (![post isRevision] && [post.postID longLongValue] > 0) {
[self restoreRemotePostWithPost:post success:success failure:failure];
} else {
if (success) {
success();
}
}
};

if (post.isRevision) {
[self restorePost:post.original
success:privateBodyBlock
failure:failure];

return;
} else {
privateBodyBlock();
}
}

- (void)restoreRemotePostWithPost:(AbstractPost*)post
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure
{
NSManagedObjectID *postObjectID = post.objectID;

void (^successBlock)(RemotePost *post) = ^(RemotePost *remotePost) {
NSError *err;
Post *postInContext = (Post *)[self.managedObjectContext existingObjectWithID:postObjectID error:&err];
postInContext.restorableStatus = nil;
if (err) {
DDLogError(@"%@", err);
}
if (postInContext) {
[PostHelper updatePost:postInContext withRemotePost:remotePost inContext:self.managedObjectContext];
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];
}
if (success) {
success();
}
};

void (^failureBlock)(NSError *error) = ^(NSError *error) {
NSError *err;
Post *postInContext = (Post *)[self.managedObjectContext existingObjectWithID:postObjectID error:&err];
if (err) {
DDLogError(@"%@", err);
}
if (postInContext) {
// Put the post back in the trash bin.
postInContext.status = PostStatusTrash;
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];
}
if (failure){
failure(error);
}
};

RemotePost *remotePost = [PostHelper remotePostWithPost:post];
if (post.restorableStatus) {
remotePost.status = post.restorableStatus;
} else {
// Assign a status of draft to the remote post. The WordPress.com REST API will
// ignore this and should restore the post's previous status. The XML-RPC API
// needs a status assigned to move a post out of the trash folder. Draft is the
// safest option when we don't know what the status was previously.
remotePost.status = PostStatusDraft;
}

id<PostServiceRemote> remote = [self.postServiceRemoteFactory forBlog:post.blog];
[remote restorePost:remotePost success:successBlock failure:failureBlock];
}

#pragma mark - Helpers

- (NSDictionary *)remoteSyncParametersDictionaryForRemote:(nonnull id <PostServiceRemote>)remote
Expand Down
Loading