<commit_before>import UIKit

@objc(WMFOnThisDayCollectionViewCell)
public class OnThisDayCollectionViewCell: SideScrollingCollectionViewCell {

    public let timelineView = OnThisDayTimelineView()
        
    override public func updateFonts(with traitCollection: UITraitCollection) {
        super.updateFonts(with: traitCollection)
        let titleFont = UIFont.wmf_preferredFontForFontFamily(.system, withTextStyle: .title3, compatibleWithTraitCollection: traitCollection)
        titleLabel.font = titleFont
        bottomTitleLabel.font = titleFont
        
        let subTitleFont = UIFont.wmf_preferredFontForFontFamily(.system, withTextStyle: .subheadline, compatibleWithTraitCollection: traitCollection)
        subTitleLabel.font = subTitleFont
        descriptionLabel.font = subTitleFont
    }
    
    override public func sizeThatFits(_ size: CGSize, apply: Bool) -> CGSize {
        let timelineViewWidth:CGFloat = 66.0
        let x: CGFloat
        
        if semanticContentAttributeOverride == .forceRightToLeft {
            layoutMargins.right = timelineViewWidth
            x = size.width - timelineViewWidth - layoutMargins.right
        } else {
            x = layoutMargins.left
            layoutMargins.left = layoutMargins.left + timelineViewWidth
        }
        
        if apply {
            timelineView.frame = CGRect(x: x, y: 0, width: timelineViewWidth, height: size.height)
        }
        
        return super.sizeThatFits(size, apply: apply)
    }
    
    override open func setup() {
        super.setup()
        timelineView.isOpaque = true
        insertSubview(timelineView, belowSubview: collectionView)
    }
    
    public var pauseDotsAnimation: Bool = true {
        didSet {
            timelineView.pauseDotsAnimation = pauseDotsAnimation
        }
    }
    
    override public var isHidden: Bool {
        didSet {
            pauseDotsAnimation = isHidden
        }
    }
    
    override public func layoutSublayers(of layer: CALayer) {
        super.layoutSublayers(of: layer)
        timelineView.topDotsY = titleLabel.convert(titleLabel.bounds, to: timelineView).midY
        timelineView.bottomDotY = bottomTitleLabel.convert(bottomTitleLabel.bounds, to: timelineView).midY
    }
    
    override public func apply(theme: Theme) {
        super.apply(theme: theme)
        timelineView.backgroundColor = theme.colors.paperBackground<commit_msg>layoutMargins can't be adjusted during layout, otherwise the cell is stuck in an infinite layout loop<commit_after>import UIKit

@objc(WMFOnThisDayCollectionViewCell)
public class OnThisDayCollectionViewCell: SideScrollingCollectionViewCell {

    public let timelineView = OnThisDayTimelineView()
        
    override public func updateFonts(with traitCollection: UITraitCollection) {
        super.updateFonts(with: traitCollection)
        let titleFont = UIFont.wmf_preferredFontForFontFamily(.system, withTextStyle: .title3, compatibleWithTraitCollection: traitCollection)
        titleLabel.font = titleFont
        bottomTitleLabel.font = titleFont
        
        let subTitleFont = UIFont.wmf_preferredFontForFontFamily(.system, withTextStyle: .subheadline, compatibleWithTraitCollection: traitCollection)
        subTitleLabel.font = subTitleFont
        descriptionLabel.font = subTitleFont
    }
    
    let timelineViewWidth:CGFloat = 66.0

    func updateSuperMargins() {
        var margins = privateLayoutMargins
        if semanticContentAttributeOverride == .forceRightToLeft {
            margins.right = margins.right + timelineViewWidth
        } else {
            margins.left = margins.left + timelineViewWidth
        }
        super.layoutMargins = margins
    }

    fileprivate var privateLayoutMargins: UIEdgeInsets = ArticleCollectionViewCell.defaultMargins {
        didSet {
            updateSuperMargins()
        }
    }

    override var semanticContentAttributeOverride: UISemanticContentAttribute {
        didSet {
            updateSuperMargins()
        }
    }

    public override var layoutMargins: UIEdgeInsets {
        set {
            privateLayoutMargins = newValue
        }
        get {
            return super.layoutMargins
        }
    }

    override public func sizeThatFits(_ size: CGSize, apply: Bool) -> CGSize {
        let x: CGFloat
        if semanticContentAttributeOverride == .forceRightToLeft {
            x = size.width - timelineViewWidth - privateLayoutMargins.right
        } else {
            x = privateLayoutMargins.left
        }
        if apply {
            timelineView.frame = CGRect(x: x, y: 0, width: timelineViewWidth, height: size.height)
        }
        return super.sizeThatFits(size, apply: apply)
    }
    
    override open func setup() {
        super.setup()
        timelineView.isOpaque = true
        insertSubview(timelineView, belowSubview: collectionView)
    }
    
    public var pauseDotsAnimation: Bool = true {
        didSet {
            timelineView.pauseDotsAnimation = pauseDotsAnimation
        }
    }
    
    override public var isHidden: Bool {
        didSet {
            pauseDotsAnimation = isHidden
        }
    }
    
    override public func layoutSublayers(of layer: CALayer) {
        super.layoutSublayers(of: layer)
        timelineView.topDotsY = titleLabel.convert(titleLabel.bounds, to: timelineView).midY
        timelineView.bottomDotY = bottomTitleLabel.convert(bottomTitleLabel.bounds, to: timelineView).midY
    }
    
    override public func apply(theme: Theme) {
        super.apply(theme: theme)
        timelineView.backgroundColor = theme.colors.paperBackground
{'fraction_non_alphanumeric': 0.06660746003552398, 'fraction_numerical': 0.0017761989342806395, 'mean_word_length': 2.6119307248236048, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4325251', 'n_tokens_mistral': 1570, 'n_tokens_neox': 1501, 'n_words': 324}