From 8cb080da6dd811268ed4b5acf9237b18361d08ea Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Mon, 28 Oct 2019 19:52:50 -0500 Subject: [PATCH] Implement custom separator since the builtin separator is crazy when animating adds and deletes. Issue #1192 --- .../Cell/MasterFeedTableViewCell.swift | 33 ++++++++++++++++++- .../Cell/MasterFeedTableViewCellLayout.swift | 18 +++++----- iOS/MasterFeed/MasterFeedViewController.swift | 21 +++++++++--- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift b/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift index 4a90d1e92..c60badcd0 100644 --- a/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift +++ b/iOS/MasterFeed/Cell/MasterFeedTableViewCell.swift @@ -60,6 +60,18 @@ class MasterFeedTableViewCell : VibrantTableViewCell { } } + var isSeparatorShown = true { + didSet { + if isSeparatorShown != oldValue { + if isSeparatorShown { + showView(bottomSeparatorView) + } else { + hideView(bottomSeparatorView) + } + } + } + } + var unreadCount: Int { get { return unreadCountView.unreadCount @@ -101,6 +113,12 @@ class MasterFeedTableViewCell : VibrantTableViewCell { return imageView }() + private let bottomSeparatorView: UIView = { + let view = UIView() + view.backgroundColor = UIColor.separator + return view + }() + private var isDisclosureExpanded = false private var disclosureButton: UIButton? private var unreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero) @@ -173,6 +191,7 @@ private extension MasterFeedTableViewCell { addSubviewAtInit(faviconImageView) addSubviewAtInit(titleView) addDisclosureView() + addSubviewAtInit(bottomSeparatorView) } func addDisclosureView() { @@ -195,7 +214,7 @@ private extension MasterFeedTableViewCell { unreadCountView.setFrameIfNotEqual(layout.unreadCountRect) disclosureButton?.setFrameIfNotEqual(layout.disclosureButtonRect) disclosureButton?.isHidden = !isDisclosureAvailable - separatorInset = layout.separatorInsets + bottomSeparatorView.setFrameIfNotEqual(layout.separatorRect) } func updateVibrancy(animated: Bool) { @@ -210,4 +229,16 @@ private extension MasterFeedTableViewCell { } } + func hideView(_ view: UIView) { + if !view.isHidden { + view.isHidden = true + } + } + + func showView(_ view: UIView) { + if view.isHidden { + view.isHidden = false + } + } + } diff --git a/iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift b/iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift index 4066772dd..0c244bc9d 100644 --- a/iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift +++ b/iOS/MasterFeed/Cell/MasterFeedTableViewCellLayout.swift @@ -27,7 +27,7 @@ struct MasterFeedTableViewCellLayout { let titleRect: CGRect let unreadCountRect: CGRect let disclosureButtonRect: CGRect - let separatorInsets: UIEdgeInsets + let separatorRect: CGRect let height: CGFloat @@ -60,13 +60,6 @@ struct MasterFeedTableViewCellLayout { rFavicon = CGRect(x: x, y: y, width: MasterFeedTableViewCellLayout.imageSize.width, height: MasterFeedTableViewCellLayout.imageSize.height) } - // Separator Insets - if shouldShowDisclosure { - separatorInsets = UIEdgeInsets(top: 0, left: MasterFeedTableViewCellLayout.disclosureButtonSize.width, bottom: 0, right: 0) - } else { - separatorInsets = UIEdgeInsets(top: 0, left: rFavicon.maxX + MasterFeedTableViewCellLayout.imageMarginRight, bottom: 0, right: 0) - } - // Unread Count let unreadCountSize = unreadCountView.contentSize let unreadCountIsHidden = unreadCountView.unreadCount < 1 @@ -105,6 +98,15 @@ struct MasterFeedTableViewCellLayout { rDisclosure = MasterFeedTableViewCellLayout.centerVertically(rDisclosure, newBounds) } + // Separator Insets + var separatorInset = CGFloat.zero + if shouldShowDisclosure { + separatorInset = MasterFeedTableViewCellLayout.disclosureButtonSize.width + } else { + separatorInset = rFavicon.maxX + MasterFeedTableViewCellLayout.imageMarginRight + } + separatorRect = CGRect(x: separatorInset, y: cellHeight - 0.5, width: cellWidth - separatorInset, height: 0.5) + // Assign the properties self.height = cellHeight self.faviconRect = rFavicon diff --git a/iOS/MasterFeed/MasterFeedViewController.swift b/iOS/MasterFeed/MasterFeedViewController.swift index 3075e6ca1..2124499ff 100644 --- a/iOS/MasterFeed/MasterFeedViewController.swift +++ b/iOS/MasterFeed/MasterFeedViewController.swift @@ -48,7 +48,9 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { tableView.register(MasterFeedTableViewSectionHeader.self, forHeaderFooterViewReuseIdentifier: "SectionHeader") tableView.dataSource = dataSource - + resetEstimatedRowHeight() + tableView.separatorStyle = .none + NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil) @@ -59,7 +61,6 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner { refreshControl = UIRefreshControl() refreshControl!.addTarget(self, action: #selector(refreshAccounts(_:)), for: .valueChanged) - resetEstimatedRowHeight() configureToolbar() becomeFirstResponder() } @@ -628,6 +629,14 @@ private extension MasterFeedViewController { cell.unreadCount = coordinator.unreadCountFor(node) configureFavicon(cell, node) + guard let indexPath = dataSource.indexPath(for: node) else { return } + let rowsInSection = tableView.numberOfRows(inSection: indexPath.section) + if indexPath.row == rowsInSection - 1 { + cell.isSeparatorShown = false + } else { + cell.isSeparatorShown = true + } + } func configureFavicon(_ cell: MasterFeedTableViewCell, _ node: Node) { @@ -700,7 +709,9 @@ private extension MasterFeedViewController { return } coordinator.expand(node) - self.applyChanges(animate: true) + applyChanges(animate: true) { [weak self] in + self?.reloadNode(node) + } } func collapse(_ cell: MasterFeedTableViewCell) { @@ -708,7 +719,9 @@ private extension MasterFeedViewController { return } coordinator.collapse(node) - self.applyChanges(animate: true) + applyChanges(animate: true) { [weak self] in + self?.reloadNode(node) + } } func makeFeedContextMenu(indexPath: IndexPath, includeDeleteRename: Bool) -> UIContextMenuConfiguration {