From e0f2fe6db119d1d814cca2beb8f830baa6e174bb Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Fri, 8 Oct 2021 22:07:05 +0700 Subject: [PATCH 1/4] Add delete permanently button for comment detail --- .../CommentDetailViewController.swift | 115 +++++++++++++++--- 1 file changed, 96 insertions(+), 19 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift b/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift index 52f84a8a0d7f..d00a96589da0 100644 --- a/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift +++ b/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift @@ -53,6 +53,43 @@ class CommentDetailViewController: UITableViewController { return cell }() + private lazy var deleteButton: UIButton = { + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.tintColor = .error + button.setTitle(.deleteButtonText, for: .normal) + button.setTitleColor(.error, for: .normal) + button.setTitleColor(.white, for: .highlighted) + button.setBackgroundImage(UIImage.renderBackgroundImage(fill: .clear, border: .error), for: .normal) + button.setBackgroundImage(.renderBackgroundImage(fill: .error, border: .error), for: .highlighted) + + button.titleLabel?.font = WPStyleGuide.fontForTextStyle(.body, fontWeight: .semibold) + button.titleLabel?.textAlignment = .center + button.titleLabel?.numberOfLines = 0 + + // add constraints for the title label for the button to contain the label properly in multi-line cases. + if let label = button.titleLabel { + button.pinSubviewToAllEdgeMargins(label) + } + + button.on(.touchUpInside) { [weak self] _ in + self?.deleteButtonTapped() + } + + return button + }() + + private lazy var deleteButtonCell: UITableViewCell = { + let cell = UITableViewCell() + cell.selectionStyle = .none + cell.accessibilityTraits = .button + + cell.contentView.addSubview(deleteButton) + cell.contentView.pinSubviewToAllEdges(deleteButton, insets: Constants.deleteButtonInsets) + + return cell + }() + private lazy var commentService: CommentService = { return .init(managedObjectContext: managedObjectContext) }() @@ -121,27 +158,37 @@ class CommentDetailViewController: UITableViewController { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let row = rows[indexPath.row] - switch row { - case .header: - configureHeaderCell() - return headerCell - - case .content: - guard let cell = tableView.dequeueReusableCell(withIdentifier: CommentContentTableViewCell.defaultReuseID) as? CommentContentTableViewCell else { - return .init() + let cell: UITableViewCell = { + switch row { + case .header: + configureHeaderCell() + return headerCell + + case .content: + guard let cell = tableView.dequeueReusableCell(withIdentifier: CommentContentTableViewCell.defaultReuseID) as? CommentContentTableViewCell else { + return .init() + } + + configureContentCell(cell, comment: comment) + cell.moderationBar.delegate = self + moderationBar = cell.moderationBar + return cell + + case .replyIndicator: + return replyIndicatorCell + + case .text: + return configuredTextCell(for: row) + + case .deleteComment: + return deleteButtonCell } + }() - configureContentCell(cell, comment: comment) - cell.moderationBar.delegate = self - moderationBar = cell.moderationBar - return cell + // hide cell separator if it's positioned before the delete button cell. + cell.separatorInset = shouldHideCellSeparator(for: indexPath) ? insetsForHiddenCellSeparator : tableView.separatorInset - case .replyIndicator: - return replyIndicatorCell - - case .text: - return configuredTextCell(for: row) - } + return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { @@ -176,11 +223,21 @@ private extension CommentDetailViewController { case content case replyIndicator case text(title: String, detail: String, image: UIImage? = nil) + case deleteComment } struct Constants { static let tableLeadingInset: CGFloat = 20.0 + static let tableBottomMargin: CGFloat = 40.0 static let replyIndicatorVerticalSpacing: CGFloat = 14.0 + + static let deleteButtonInsets = UIEdgeInsets(top: 4, left: 20, bottom: 4, right: 20) + } + + /// Convenience computed variable for an inset setting that hides a cell's separator by pushing it off the edge of the screen. + /// This needs to be computed because the frame size changes on orientation change. + var insetsForHiddenCellSeparator: UIEdgeInsets { + return .init(top: 0, left: tableView.frame.size.width, bottom: 0, right: 0).flippedForRightToLeftLayoutDirection() } func configureNavigationBar() { @@ -191,7 +248,7 @@ private extension CommentDetailViewController { func configureTable() { // get rid of the separator line for the last cell. - tableView.tableFooterView = UIView(frame: .init(x: 0, y: 0, width: tableView.frame.size.width, height: 1)) + tableView.tableFooterView = UIView(frame: .init(x: 0, y: 0, width: tableView.frame.size.width, height: Constants.tableBottomMargin)) // assign 20pt leading inset to the table view, as per the design. // note that by default, the system assigns 16pt inset for .phone, and 20pt for .pad idioms. @@ -222,6 +279,11 @@ private extension CommentDetailViewController { } rows.append(.text(title: .ipAddressLabelText, detail: comment.author_ip)) + + if let statusType = CommentStatusType.typeForStatus(comment.status), + (statusType == .spam || statusType == .unapproved) { + rows.append(.deleteComment) + } } self.rows = rows @@ -234,6 +296,16 @@ private extension CommentDetailViewController { tableView.reloadData() } + + /// Checks if the index path is positioned before the delete button cell. + func shouldHideCellSeparator(for indexPath: IndexPath) -> Bool { + guard let deleteCellIndex = rows.firstIndex(of: .deleteComment) else { + return false + } + + return indexPath.row == deleteCellIndex - 1 + } + // MARK: Cell configuration func configureHeaderCell() { @@ -353,6 +425,10 @@ private extension CommentDetailViewController { present(navigationControllerToPresent, animated: true) } + func deleteButtonTapped() { + // TODO: Implement delete functionality. + } + func updateComment() { // Regardless of success or failure track the user's intent to save a change. CommentAnalytics.trackCommentEdited(comment: comment) @@ -424,6 +500,7 @@ private extension String { static let webAddressLabelText = NSLocalizedString("Web address", comment: "Describes the web address section in the comment detail screen.") static let emailAddressLabelText = NSLocalizedString("Email address", comment: "Describes the email address section in the comment detail screen.") static let ipAddressLabelText = NSLocalizedString("IP address", comment: "Describes the IP address section in the comment detail screen.") + static let deleteButtonText = NSLocalizedString("Delete Permanently", comment: "Title for button on the comment details page that deletes the comment when tapped.") } From 718ac063da29c3e59b46b633c6fabb1cf234706a Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Fri, 8 Oct 2021 22:22:21 +0700 Subject: [PATCH 2/4] Fix minor comment typo --- .../ViewRelated/Comments/CommentDetailViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift b/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift index d00a96589da0..5d59f2b855ac 100644 --- a/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift +++ b/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift @@ -67,7 +67,7 @@ class CommentDetailViewController: UITableViewController { button.titleLabel?.textAlignment = .center button.titleLabel?.numberOfLines = 0 - // add constraints for the title label for the button to contain the label properly in multi-line cases. + // add constraints to the title label, so the button can contain it properly in multi-line cases. if let label = button.titleLabel { button.pinSubviewToAllEdgeMargins(label) } From 89757d37e3200fa06fd35700a46ca678971ff2aa Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Fri, 8 Oct 2021 22:28:17 +0700 Subject: [PATCH 3/4] minor: improve readability --- .../ViewRelated/Comments/CommentDetailViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift b/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift index 5d59f2b855ac..4dbc0e83f2ff 100644 --- a/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift +++ b/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift @@ -136,7 +136,7 @@ class CommentDetailViewController: UITableViewController { super.viewWillTransition(to: size, with: coordinator) // when an orientation change is triggered, recalculate the content cell's height. - guard let contentRowIndex = rows.firstIndex(where: { $0 == .content }) else { + guard let contentRowIndex = rows.firstIndex(of: .content) else { return } tableView.reloadRows(at: [.init(row: contentRowIndex, section: .zero)], with: .fade) From d9ccadc7994c5322f786eefc963f193458df9dff Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Sat, 9 Oct 2021 00:34:38 +0700 Subject: [PATCH 4/4] Adjust delete button color for dark mode --- .../Comments/CommentDetailViewController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift b/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift index 4dbc0e83f2ff..3542a52f6c41 100644 --- a/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift +++ b/WordPress/Classes/ViewRelated/Comments/CommentDetailViewController.swift @@ -55,13 +55,13 @@ class CommentDetailViewController: UITableViewController { private lazy var deleteButton: UIButton = { let button = UIButton() + let buttonColor = UIColor(light: .error, dark: .muriel(name: .red, .shade40)) button.translatesAutoresizingMaskIntoConstraints = false - button.tintColor = .error button.setTitle(.deleteButtonText, for: .normal) - button.setTitleColor(.error, for: .normal) + button.setTitleColor(buttonColor, for: .normal) button.setTitleColor(.white, for: .highlighted) - button.setBackgroundImage(UIImage.renderBackgroundImage(fill: .clear, border: .error), for: .normal) - button.setBackgroundImage(.renderBackgroundImage(fill: .error, border: .error), for: .highlighted) + button.setBackgroundImage(UIImage.renderBackgroundImage(fill: .clear, border: buttonColor), for: .normal) + button.setBackgroundImage(.renderBackgroundImage(fill: buttonColor, border: buttonColor), for: .highlighted) button.titleLabel?.font = WPStyleGuide.fontForTextStyle(.body, fontWeight: .semibold) button.titleLabel?.textAlignment = .center