Skip to content

Commit

Permalink
Merge pull request #11661 from leandroalonso/post_list_more_action_sheet
Browse files Browse the repository at this point in the history
Replace "More" button behavior to show options in an Action Sheet
  • Loading branch information
nheagy committed May 15, 2019
2 parents ee66511 + 985439e commit bfef387
Show file tree
Hide file tree
Showing 16 changed files with 378 additions and 56 deletions.
1 change: 0 additions & 1 deletion WordPress/Classes/System/WordPress-Bridging-Header.h
Expand Up @@ -32,7 +32,6 @@
#import "HockeyManager.h"

#import "InteractivePostView.h"
#import "InteractivePostViewDelegate.h"

#import "LocalCoreDataService.h"

Expand Down
Expand Up @@ -925,6 +925,14 @@ class AbstractPostListViewController: UIViewController,
updateFilterWithPostStatus(.scheduled)
}

@objc func moveToDraft(_ apost: AbstractPost) {
WPAnalytics.track(.postListDraftAction, withProperties: propertiesForAnalytics())

apost.status = .draft
uploadPost(apost)
updateFilterWithPostStatus(.draft)
}

fileprivate func uploadPost(_ apost: AbstractPost) {
PostCoordinator.shared.save(post: apost)
}
Expand Down
1 change: 0 additions & 1 deletion WordPress/Classes/ViewRelated/Post/ConfigurablePostView.h
@@ -1,5 +1,4 @@
#import <Foundation/Foundation.h>
#import "InteractivePostViewDelegate.h"

@class Post;

Expand Down
3 changes: 2 additions & 1 deletion WordPress/Classes/ViewRelated/Post/InteractivePostView.h
@@ -1,5 +1,6 @@
#import <Foundation/Foundation.h>
#import "InteractivePostViewDelegate.h"

@protocol InteractivePostViewDelegate;

/// Protocol that any view offering post interaction can implement.
///
Expand Down
14 changes: 0 additions & 14 deletions WordPress/Classes/ViewRelated/Post/InteractivePostViewDelegate.h

This file was deleted.

@@ -0,0 +1,12 @@
import Foundation

@objc protocol InteractivePostViewDelegate {
func edit(_ post: AbstractPost)
func view(_ post: AbstractPost)
func stats(for post: AbstractPost)
func publish(_ post: AbstractPost)
func schedule(_ post: AbstractPost)
func trash(_ post: AbstractPost)
func restore(_ post: AbstractPost)
func draft(_ post: AbstractPost)
}
55 changes: 55 additions & 0 deletions WordPress/Classes/ViewRelated/Post/PostActionSheet.swift
@@ -0,0 +1,55 @@
import Foundation

@objc protocol PostActionSheetDelegate {
func showActionSheet(_ post: AbstractPost, from view: UIView)
}

class PostActionSheet {

weak var viewController: UIViewController?
weak var interactivePostViewDelegate: InteractivePostViewDelegate?

init(viewController: UIViewController, interactivePostViewDelegate: InteractivePostViewDelegate) {
self.viewController = viewController
self.interactivePostViewDelegate = interactivePostViewDelegate
}

func show(for post: Post, from view: UIView) {
let actionSheetController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

actionSheetController.addCancelActionWithTitle(Titles.cancel)

if post.status == BasePost.Status.publish || post.status == BasePost.Status.draft {
actionSheetController.addDefaultActionWithTitle(Titles.stats) { [weak self] _ in
self?.interactivePostViewDelegate?.stats(for: post)
}
}

if post.status != BasePost.Status.draft {
actionSheetController.addDefaultActionWithTitle(Titles.draft) { [weak self] _ in
self?.interactivePostViewDelegate?.draft(post)
}
}

let destructiveTitle = post.status == BasePost.Status.trash ? Titles.delete : Titles.trash
actionSheetController.addDestructiveActionWithTitle(destructiveTitle) { [weak self] _ in
self?.interactivePostViewDelegate?.trash(post)
}

if let presentationController = actionSheetController.popoverPresentationController {
presentationController.permittedArrowDirections = .any
presentationController.sourceView = view
presentationController.sourceRect = view.bounds
}

viewController?.present(actionSheetController, animated: true)
}

struct Titles {
static let cancel = NSLocalizedString("Cancel", comment: "Dismiss the post action sheet")
static let stats = NSLocalizedString("Stats", comment: "Label for post stats option. Tapping displays statistics for a post.")
static let draft = NSLocalizedString("Move to Draft", comment: "Label for an option that moves a post to the draft folder")
static let delete = NSLocalizedString("Delete Permanently", comment: "Label for the delete post option. Tapping permanently deletes a post.")
static let trash = NSLocalizedString("Move to Trash", comment: "Label for a option that moves a post to the trash folder")
}
}
3 changes: 3 additions & 0 deletions WordPress/Classes/ViewRelated/Post/PostCardActionBar.h
@@ -1,7 +1,10 @@
#import <UIKit/UIKit.h>

typedef void(^MoreActionCallback)(UIView* view);

@interface PostCardActionBar : UIView

- (void)setMoreAction:(MoreActionCallback)callback;
- (void)setItems:(NSArray *)items;
- (void)reset;

Expand Down
20 changes: 17 additions & 3 deletions WordPress/Classes/ViewRelated/Post/PostCardActionBar.m
Expand Up @@ -32,6 +32,7 @@ @interface PostCardActionBar()
@property (nonatomic, assign) NSInteger currentBatch;
@property (nonatomic, assign) BOOL shouldShowMore;
@property (nonatomic, assign) BOOL needsSetupButtons;
@property (nonatomic, copy) MoreActionCallback moreActionCallback;
@end

@implementation PostCardActionBar
Expand Down Expand Up @@ -290,6 +291,10 @@ - (void)reset
[self configureButtons];
}

- (void)setMoreAction:(MoreActionCallback)callback {
self.moreActionCallback = callback;
}

#pragma mark - Accessors

- (NSInteger)indexOfItem:(PostCardActionBarItem *)item
Expand All @@ -314,7 +319,7 @@ - (NSInteger)maxButtonsToDisplay

- (BOOL)checkIfShouldShowMoreButton
{
return [self maxButtonsToDisplay] < [self.items count];
return [self maxButtonsToDisplay] < [self.items count] || _moreActionCallback;
}

- (void)setItems:(NSArray *)items
Expand Down Expand Up @@ -382,8 +387,7 @@ - (void)handleButtonTap:(id)sender
UIButton *button = (UIButton *)sender;
NSInteger index = button.tag;
if (index == ActionBarMoreButtonIndex) {
self.currentBatch++;
[self configureButtonsWithAnimation];
[self handleMoreButtonTap:sender];
return;
}
PostCardActionBarItem *item = [self.items objectAtIndex:index];
Expand All @@ -392,6 +396,16 @@ - (void)handleButtonTap:(id)sender
}
}

- (void)handleMoreButtonTap: (UIButton *)sender
{
if (_moreActionCallback) {
_moreActionCallback(sender);
} else {
self.currentBatch++;
[self configureButtonsWithAnimation];
}
}

- (void)handleDoubleTap:(UITapGestureRecognizer *)sender
{
// noop.
Expand Down
3 changes: 2 additions & 1 deletion WordPress/Classes/ViewRelated/Post/PostCardTableViewCell.h
Expand Up @@ -3,7 +3,8 @@
#import "InteractivePostView.h"

@protocol ConfigurablePostView;
@protocol PostActionSheetDelegate;

@interface PostCardTableViewCell : UITableViewCell <ConfigurablePostView, InteractivePostView>

- (void)setActionSheetDelegate:(nonnull id<PostActionSheetDelegate>)delegate;
@end
45 changes: 24 additions & 21 deletions WordPress/Classes/ViewRelated/Post/PostCardTableViewCell.m
Expand Up @@ -52,6 +52,7 @@ @interface PostCardTableViewCell()
@property (nonatomic, strong) IBOutlet NSLayoutConstraint *postCardImageViewHeightConstraint;

@property (nonatomic, weak) id<InteractivePostViewDelegate> delegate;
@property (nonatomic, weak) id<PostActionSheetDelegate> postActionSheetDelegate;
@property (nonatomic, strong) Post *post;
@property (nonatomic, strong) PostCardStatusViewModel *viewModel;
@property (nonatomic, strong) ImageLoader *imageLoader;
Expand Down Expand Up @@ -260,6 +261,16 @@ - (void)setInteractionDelegate:(id<InteractivePostViewDelegate>)delegate
self.delegate = delegate;
}

- (void)setActionSheetDelegate:(id<PostActionSheetDelegate>)delegate
{
self.postActionSheetDelegate = delegate;

__weak __typeof(self) weakSelf = self;
[self.actionBar setMoreAction:^(UIView *view) {
[weakSelf showActionSheet:view];
}];
}

#pragma mark - Configuration

- (void)configureHeader
Expand Down Expand Up @@ -685,51 +696,37 @@ - (PostCardActionBarItem *)actionBarItemWithTitle:(NSString *)title

- (void)editPostAction
{
if ([self.delegate respondsToSelector:@selector(cell:handleEditPost:)]) {
[self.delegate cell:self handleEditPost:self.post];
}
[self.delegate edit:self.post];
}

- (void)viewPostAction
{
if ([self.delegate respondsToSelector:@selector(cell:handleViewPost:)]) {
[self.delegate cell:self handleViewPost:self.post];
}
[self.delegate view:self.post];
}

- (void)publishPostAction
{
if ([self.delegate respondsToSelector:@selector(cell:handlePublishPost:)]) {
[self.delegate cell:self handlePublishPost:self.post];
}
[self.delegate publish:self.post];
}

- (void)schedulePostAction
{
if ([self.delegate respondsToSelector:@selector(cell:handleSchedulePost:)]) {
[self.delegate cell:self handleSchedulePost:self.post];
}
[self.delegate schedule:self.post];
}

- (void)trashPostAction
{
if ([self.delegate respondsToSelector:@selector(cell:handleTrashPost:)]) {
[self.delegate cell:self handleTrashPost:self.post];
}
[self.delegate trash:self.post];
}

- (void)restorePostAction
{
if ([self.delegate respondsToSelector:@selector(cell:handleRestorePost:)]) {
[self.delegate cell:self handleRestorePost:self.post];
}
[self.delegate restore:self.post];
}

- (void)statsPostAction
{
if ([self.delegate respondsToSelector:@selector(cell:handleStatsForPost:)]) {
[self.delegate cell:self handleStatsForPost:self.post];
}
[self.delegate statsFor:self.post];
}

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
Expand All @@ -741,4 +738,10 @@ - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
}
}

#pragma mark - Post Action Sheet

- (void)showActionSheet:(UIView *)view {
[self.postActionSheetDelegate showActionSheet:self.post from: view];
}

@end
41 changes: 33 additions & 8 deletions WordPress/Classes/ViewRelated/Post/PostListViewController.swift
Expand Up @@ -49,6 +49,10 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe
@IBOutlet weak var filterTabBarBottomConstraint: NSLayoutConstraint!
@IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint!

private lazy var postActionSheet: PostActionSheet = {
return PostActionSheet(viewController: self, interactivePostViewDelegate: self)
}()

// MARK: - Convenience constructors

@objc class func controllerWithBlog(_ blog: Blog) -> PostListViewController {
Expand Down Expand Up @@ -361,6 +365,8 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe
interactivePostView.setInteractionDelegate(self)

configurablePostView.configure(with: post)

setActionSheetDelegate(cell)
}

fileprivate func cellIdentifierForPost(_ post: Post) -> String {
Expand All @@ -375,6 +381,12 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe
return identifier
}

private func setActionSheetDelegate(_ cell: UITableViewCell) {
guard let cell = cell as? PostCardTableViewCell else { return }

cell.setActionSheetDelegate(self)
}

// MARK: - Post Actions

override func createPost() {
Expand Down Expand Up @@ -481,33 +493,33 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe

// MARK: - InteractivePostViewDelegate

func cell(_ cell: UITableViewCell, handleEdit post: AbstractPost) {
func edit(_ post: AbstractPost) {
editPost(apost: post)
}

func cell(_ cell: UITableViewCell, handleViewPost post: AbstractPost) {
func view(_ post: AbstractPost) {
viewPost(post)
}

func cell(_ cell: UITableViewCell, handleStatsFor post: AbstractPost) {
func stats(for post: AbstractPost) {
ReachabilityUtils.onAvailableInternetConnectionDo {
viewStatsForPost(post)
}
}

func cell(_ cell: UITableViewCell, handlePublishPost post: AbstractPost) {
func publish(_ post: AbstractPost) {
ReachabilityUtils.onAvailableInternetConnectionDo {
publishPost(post)
}
}

func cell(_ cell: UITableViewCell, handleSchedulePost post: AbstractPost) {
func schedule(_ post: AbstractPost) {
ReachabilityUtils.onAvailableInternetConnectionDo {
schedulePost(post)
}
}

func cell(_ cell: UITableViewCell, handleTrashPost post: AbstractPost) {
func trash(_ post: AbstractPost) {
guard ReachabilityUtils.isInternetReachable() else {
let offlineMessage = NSLocalizedString("Unable to trash posts while offline. Please try again later.", comment: "Message that appears when a user tries to trash a post while their device is offline.")
ReachabilityUtils.showNoInternetConnectionNotice(message: offlineMessage)
Expand Down Expand Up @@ -538,15 +550,20 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe
self?.deletePost(post)
}
alertController.presentFromRootViewController()

}

func cell(_ cell: UITableViewCell, handleRestore post: AbstractPost) {
func restore(_ post: AbstractPost) {
ReachabilityUtils.onAvailableInternetConnectionDo {
restorePost(post)
}
}

func draft(_ post: AbstractPost) {
ReachabilityUtils.onAvailableInternetConnectionDo {
moveToDraft(post)
}
}

// MARK: - UISearchControllerDelegate

override func willPresentSearchController(_ searchController: UISearchController) {
Expand Down Expand Up @@ -671,3 +688,11 @@ private extension PostListViewController {
static let noPublishedTitle = NSLocalizedString("You haven't published any posts yet", comment: "Displayed when the user views published posts in the posts list and there are no posts")
}
}

extension PostListViewController: PostActionSheetDelegate {
func showActionSheet(_ post: AbstractPost, from view: UIView) {
guard let post = post as? Post else { return }

postActionSheet.show(for: post, from: view)
}
}

0 comments on commit bfef387

Please sign in to comment.