Skip to content

Commit

Permalink
Stats Traffic: Optimize table view updates by integrating diffable da…
Browse files Browse the repository at this point in the history
…ta source (#22542)
  • Loading branch information
staskus committed Feb 22, 2024
2 parents 3ddebf7 + d130c3a commit 4e97126
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 158 deletions.
61 changes: 61 additions & 0 deletions WordPress/Classes/Utility/ImmuTable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -483,3 +483,64 @@ extension UITableView: CellRegistrar {
}

extension UITableViewController: TableViewContainer {}

// MARK: - Diffable

typealias ImmuTableDiffableDataSourceSnapshot = NSDiffableDataSourceSnapshot<AnyHashable, AnyHashableImmuTableRow>
typealias ImmuTableDiffableDataSource = UITableViewDiffableDataSource<AnyHashable, AnyHashableImmuTableRow>

struct AnyHashableImmuTableRow: Hashable {
let immuTableRow: any (ImmuTableRow & Hashable)

static func == (lhs: AnyHashableImmuTableRow, rhs: AnyHashableImmuTableRow) -> Bool {
return AnyHashable(lhs.immuTableRow) == AnyHashable(rhs.immuTableRow)
}

func hash(into hasher: inout Hasher) {
hasher.combine(AnyHashable(immuTableRow))
}
}

class ImmuTableDiffableViewHandler: ImmuTableViewHandler {
lazy var diffableDataSource: ImmuTableDiffableDataSource = {
return ImmuTableDiffableDataSource(tableView: target.tableView) { tableView, indexPath, item in
let row = item.immuTableRow
let cell = tableView.dequeueReusableCell(withIdentifier: row.reusableIdentifier, for: indexPath)
row.configureCell(cell)
return cell
}
}()

override init(takeOver target: ImmuTableViewHandler.UIViewControllerWithTableView, with passthroughScrollViewDelegate: UIScrollViewDelegate? = nil) {
super.init(takeOver: target, with: passthroughScrollViewDelegate)

self.target.tableView.dataSource = diffableDataSource
self.automaticallyReloadTableView = false
}

func item(for indexPath: IndexPath) -> ImmuTableRow? {
guard let diffableDataSource = target.tableView.dataSource as? UITableViewDiffableDataSource<AnyHashable, AnyHashableImmuTableRow> else {
return nil
}

return diffableDataSource.itemIdentifier(for: indexPath)?.immuTableRow
}

open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if target.responds(to: #selector(UITableViewDelegate.tableView(_:didSelectRowAt:))) {
target.tableView?(tableView, didSelectRowAt: indexPath)
} else if let item = item(for: indexPath) {
item.action?(item)
}
if automaticallyDeselectCells {
tableView.deselectRow(at: indexPath, animated: true)
}
}

open override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if let item = item(for: indexPath), let customHeight = type(of: item).customHeight {
return CGFloat(customHeight)
}
return tableView.rowHeight
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

struct CountriesMap {
struct CountriesMap: Hashable {
let minViewsCount: Int
let maxViewsCount: Int
let data: [String: NSNumber]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import UIKit

struct OverviewTabData: FilterTabBarItem {
struct OverviewTabData: FilterTabBarItem, Hashable {
var tabTitle: String
var tabData: Int
var tabDataStub: String?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ final class SiteStatsPeriodTableViewController: SiteStatsBaseTableViewController
private var changeReceipt: Receipt?

private var viewModel: SiteStatsPeriodViewModel?
private var tableHeaderView: SiteStatsTableHeaderView?
private weak var tableHeaderView: SiteStatsTableHeaderView?

private let analyticsTracker = BottomScrollAnalyticsTracker()

private lazy var tableHandler: ImmuTableViewHandler = {
return ImmuTableViewHandler(takeOver: self, with: analyticsTracker)
private lazy var tableHandler: ImmuTableDiffableViewHandler = {
return ImmuTableDiffableViewHandler(takeOver: self, with: analyticsTracker)
}()

init() {
Expand Down Expand Up @@ -173,9 +173,10 @@ private extension SiteStatsPeriodTableViewController {
return
}

tableHandler.viewModel = viewModel.tableViewModel()
tableHandler.diffableDataSource.apply(viewModel.tableViewSnapshot(), animatingDifferences: false)

refreshControl.endRefreshing()
tableHeaderView?.animateGhostLayers(viewModel.isFetchingChart() == true)

if viewModel.fetchingFailed() {
displayFailureViewIfNecessary()
Expand Down Expand Up @@ -217,7 +218,7 @@ private extension SiteStatsPeriodTableViewController {

extension SiteStatsPeriodTableViewController: NoResultsViewHost {
private func displayFailureViewIfNecessary() {
guard tableHandler.viewModel.sections.isEmpty else {
guard tableHandler.diffableDataSource.snapshot().numberOfSections == 0 else {
return
}

Expand Down
Loading

0 comments on commit 4e97126

Please sign in to comment.