Skip to content

Conversation

luc-lisi
Copy link
Collaborator

@luc-lisi luc-lisi commented Oct 8, 2025

DO NOT MERGE: This is a draft PR and is still a work in progress.

The goal of this PR is to include a new impression observer class that handles its own view state using a custom UICollectionViewCell base class.

This draft has been opened for comments on the approach. Any release of this code must be done behind a feature flag.

📝 Checklist

  • I filled in the ticket numbers and a description of my work
  • I updated the PR name to follow our PR naming guidelines
  • I ensured unit tests pass and wrote tests for new code
  • If working on UI, I checked and implemented accessibility (Dynamic Text and VoiceOver)
  • If adding telemetry, I read the data stewardship requirements and will request a data review
  • If adding or modifying strings, I read the guidelines and will request a string review from l10n
  • If needed, I updated documentation and added comments to complex code

private var observedScrollViews: Set<UIScrollView> = []

private var visibleAreaFraction: CGFloat {
guard let window = window, !isHidden, alpha > 0.01, !bounds.isEmpty else { return 0 }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I got this logic right... but I would love a sanity check here as I think I've stared at this code for too long

@mobiletest-ci-bot
Copy link

mobiletest-ci-bot commented Oct 8, 2025

Messages
📖 Project coverage: 37.7%

🧹 Tidy commit

Just 3 file(s) touched. Thanks for keeping it clean and review-friendly!

❌ Per-file test coverage gate

The following changed file(s) are below 35.0% coverage:

File Coverage Required
firefox-ios/Client/Frontend/Home/TopSites/Cell/ObservableCollectionViewCell.swift 0.0% 35.0%
firefox-ios/Client/Frontend/Home/Homepage Rebuild/TopSites/TopSiteCell.swift 0.0% 35.0%

Client.app: Coverage: 37.18

File Coverage
ObservableCollectionViewCell.swift 0.0% ⚠️
TopSiteCell.swift 0.0% ⚠️

Generated by 🚫 Danger Swift against c64800e

fixed formatting

formatting

formatting
private var inViewAreaFraction: CGFloat {
guard let window = window, !isHidden, alpha > 0.01, !bounds.isEmpty else { return 0 }
var rect = convert(bounds, to: window).intersection(window.bounds)
if rect.isNull { return 0 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably also be a guard !rect.isNull else { return 0 } (usually guard is used for this type of early-returning)

var rect = convert(bounds, to: window).intersection(window.bounds)
if rect.isNull { return 0 }
var a = superview
while let s = a, s !== window {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this code would be clearer if broken out into a separate function with more well-defined variable names

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's a good call. Let me clean this up! I was very fast and loose with this one.

// MARK: Visibility timer
private func startVisibilityTimerIfNeeded() {
guard visibilityTimer == nil, !wasVisibleForThisLifetime else { return }
let t = Timer(timeInterval: visibleTimeThresholdSeconds, repeats: false) { [weak self] _ in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you can use Timer's built-in initializer instead of instantiating it with its constructor directly so you don't need to manually add it to the run loop like:

visibilityTimer = Timer.scheduledTimer(withTimeInterval: visibleTimeThresholdSeconds, repeats: false) { [weak self] _ in
  // do stuff...
}

}
self.stopVisibilityTimer()
}
t.tolerance = visibleTimeThresholdSeconds * 0.1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should add this tolerance. In practice, this will just ensure that it almost always fires later than you intend.

@adudenamedruby adudenamedruby added the Do Not Merge ⛔️ This issue is a work in progress and is not ready to land label Oct 14, 2025
@adudenamedruby adudenamedruby self-requested a review October 15, 2025 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Do Not Merge ⛔️ This issue is a work in progress and is not ready to land

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants