Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(web): viewport reactivity, off-screen thumbhashes being rendered #15435

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

mertalev
Copy link
Contributor

@mertalev mertalev commented Jan 18, 2025

Description

Changing the viewport results in a lot of repeated work because of the viewport and safeViewport variables being $state objects and updateViewport separately triggering another update. This was exacerbated by the fact that thumbhashes were processed eagerly without checking if they're intersected, meaning that larger buckets could have hundreds of thousands of thumbhashes processed as a user changes the viewport.

This PR makes three primary changes:

  1. Only intersecting assets have their thumbhashes decoded and added to the Canvas
  2. The viewport dimensions are assigned to a regular non-reactive variable, delegating the reactivity to updateViewport.
  3. updateViewport's throttling is changed to debouncing and can be automatically shifted to a "large bucket" mode with more aggressive debouncing settings. The default trigger to enable this mode is to have more than 3000 assets in a single bucket. This effectively means that instead of having the layout react as you're dragging, it will react once you stop moving it.

The result is that both initial page load, changing viewport and moving around in the timeline is more responsive than before. There is a caveat in that the initial page load is more likely to display gray boxes initially instead of the thumbhash because of the intersection check. Scrolling displays the thumbhash as normal, though.

This was primarily tested alongside the justified layout changes (will be a separate PR), but I split it out into its own PR.

How Has This Been Tested?

Tested with average bucket sizes of 200, 600, 1000, 2000, 3500 and 30000 and confirmed that it (more or less) held up at those numbers, 30000 still being quite slow but usable.

Edit: in the current iteration of this PR, small date groups (<=100 assets) will continue to have thumbhashes eagerly processed so the thumbhashes appear in the first frame. At this scale, it does not seem to cause major issues besides high RAM usage, although it is less responsive than the original version of this PR. I think getting the best of both worlds would require deeper changes, like having a single larger canvas for the date group that gets updated instead of many small canvases, or possibly using WebGL etc.

Copy link
Contributor

@jrasm91 jrasm91 left a comment

Choose a reason for hiding this comment

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

LGTM

@alextran1502
Copy link
Contributor

With these changes, I rarely see the thumbhash rendered. Instead, it mostly transitions from the placeholder box to the thumbnail almost instantly, giving the impression of flashing in. So, we do not see a nice transition anymore. Is there a way to add it in?

@mertalev
Copy link
Contributor Author

With these changes, I rarely see the thumbhash rendered. Instead, it mostly transitions from the placeholder box to the thumbnail almost instantly, giving the impression of flashing in. So, we do not see a nice transition anymore. Is there a way to add it in?

I think it's a combination of the intersection observer adding a slight delay, and the fact that the thumbnail can load faster because of this change (less blocking JS code). Should the thumbnail have a fade-in?

@alextran1502
Copy link
Contributor

Let's try that and see how it behaves

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants