// // HomeCollectionViewCell.swift // Reader // // Created by Shadowfacts on 1/9/22. // import UIKit import Fervor import Persistence import OSLog private let signposter = OSSignposter(subsystem: "net.shadowfacts.Reader", category: "HomeCollectionViewCell") class HomeCollectionViewCell: UICollectionViewListCell { private var currentItemCountTask: Task? private var itemCount: Int? #if !targetEnvironment(macCatalyst) override func updateConfiguration(using state: UICellConfigurationState) { var backgroundConfig = UIBackgroundConfiguration.listGroupedCell().updated(for: state) if state.isHighlighted || state.isSelected { backgroundConfig.backgroundColor = .appCellHighlightBackground } else { backgroundConfig.backgroundColor = .appBackground } self.backgroundConfiguration = backgroundConfig } #endif override func prepareForReuse() { super.prepareForReuse() currentItemCountTask?.cancel() itemCount = nil } func updateUI(item: ItemListType, persistentContainer: PersistentContainer) { var config = UIListContentConfiguration.valueCell() config.text = item.title if let itemCount { config.secondaryText = itemCount.formatted(.number) } config.secondaryTextProperties.color = .tintColor self.contentConfiguration = config currentItemCountTask = Task(priority: .userInitiated) { let state = signposter.beginInterval("fetch count", id: signposter.makeSignpostID(), "\(String(item.hashValue, radix: 16), privacy: .public)") if let count = await fetchCount(item: item, in: persistentContainer), !Task.isCancelled { self.itemCount = count config.secondaryText = count.formatted(.number) self.contentConfiguration = config } signposter.endInterval("fetch count", state) } } private func fetchCount(item: ItemListType, in persistentContainer: PersistentContainer) async -> Int? { guard let request = item.countFetchRequest else { return nil } return await withCheckedContinuation({ continuation in let state = signposter.beginInterval("waiting to perform", id: signposter.makeSignpostID(), "\(String(item.hashValue, radix: 16), privacy: .public)") persistentContainer.performBackgroundTask { context in signposter.endInterval("waiting to perform", state) let state = signposter.beginInterval("count", id: signposter.makeSignpostID(), "\(String(item.hashValue, radix: 16), privacy: .public)") let count = try? context.count(for: request) signposter.endInterval("count", state) continuation.resume(returning: count) } }) } }