Skip to content

feature: adds option to prefetch all images when loading a card pool - #7838

Closed
SethMilliken wants to merge 7 commits into
Card-Forge:masterfrom
SethMilliken:images/prefetch-card-pool-images
Closed

feature: adds option to prefetch all images when loading a card pool#7838
SethMilliken wants to merge 7 commits into
Card-Forge:masterfrom
SethMilliken:images/prefetch-card-pool-images

Conversation

@SethMilliken

Copy link
Copy Markdown
Contributor

Images are currently downloaded on-demand on mouseover, which can feel sluggish. This change adds a new preference that, when enabled, will prefetch all images from a (non-infinite) card pool when opening it. Primarily for all Sanction Format modes.

Disabled by default.

Added only to desktop. Although the mobile version also loads images on-demand, it does so as soon as the cards are visible, which is less of an issue.

Note: will require adjustment when imageKey refactor (#7757) lands.

Comment thread forge-gui-desktop/src/main/java/forge/itemmanager/CardManager.java Outdated

@Jetz72 Jetz72 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe there should be an sanity cap on how many fetches can be queued? If someone opened a thousand-plus card quest inventory would this queue all of those?

Comment on lines +84 to +93
@FunctionalInterface
public interface FetchFunction {
void fetch(String imageKey);
}

public FetchFunction fetchWithoutCallbackFunc() {
return (String key) -> fetchImage(key, () -> {});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would it work to just have a fetchImageWithoutCallback(String imageKey) that forwards to fetchImage, and use it in the stream as getImageFetcher()::fetchImageWithoutCallback?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Haha. Yes. This is a vestige of a much earlier approach I had taken. Fixed.

@SethMilliken
SethMilliken force-pushed the images/prefetch-card-pool-images branch from e88696a to 1968ebd Compare June 11, 2025 21:19
@SethMilliken

Copy link
Copy Markdown
Contributor Author

Maybe there should be an sanity cap on how many fetches can be queued? If someone opened a thousand-plus card quest inventory would this queue all of those?

This would be easy enough with a .limit(MAX_FETCH_SIZE) in the prefetchAllImages stream (would 100 be a reasonable number for that constant?). Before I resort to that, though, I'm going to see if I can find a more general solution that can live in ImageFetcher, so that we address the rate-limit problem regardless of where the requests originate.

@Jetz72

Jetz72 commented Jun 11, 2025

Copy link
Copy Markdown
Contributor

If you're looking to expand the scope of this and the logic for queuing image downloads, you might consider a priority queue or similar structure. If you have a hundred images queued and the user mouses over a card with no image, it'd be good for that card to be able to skip to the front of the line.

Might also be worth considering a way to cancel pending downloads if they're no longer of interest - namely if user leaves the screen where they're requested. This may be more trouble than it's worth, though - it'd have to be hooked into all the screens that use it.

You should also be aware that we're exploring the possibility of changing up image keys from a string to an object. See #7771 and #7757.

@SethMilliken

Copy link
Copy Markdown
Contributor Author

You should also be aware that we're exploring the possibility of changing up image keys from a string to an object. See #7771 and #7757.

Yup. I made note of that in my PR description.

@SethMilliken

Copy link
Copy Markdown
Contributor Author

If you're looking to expand the scope of this and the logic for queuing image downloads, you might consider a priority queue or similar structure. If you have a hundred images queued and the user mouses over a card with no image, it'd be good for that card to be able to skip to the front of the line.

Might also be worth considering a way to cancel pending downloads if they're no longer of interest - namely if user leaves the screen where they're requested. This may be more trouble than it's worth, though - it'd have to be hooked into all the screens that use it.

I've been tinkering with some ideas for refactoring ImageFetcher that would make doing these easier. Seemed best to wait for those imageKey changes to settle first.

@SethMilliken
SethMilliken force-pushed the images/prefetch-card-pool-images branch from 1cab968 to d4201c6 Compare June 12, 2025 06:03
Images are currently downloaded on-demand on mouseover, which can feel
sluggish. This change adds a new preference that, when enabled, will
prefetch all images from a (non-infinite) card pool when opening it.
Primarily for all Sanction Format modes.

Disabled by default.

Added only to desktop. Although the mobile version also loads
images on-demand, it does so as soon as the cards are visible, which
is less of an issue.

Note: will require adjustment when `imageKey` refactor (Card-Forge#7757) lands.
…tually used

Fixes broken build since `GuiMobile` did not implment
`IGuiBase::prefetchAllImages`.
@SethMilliken
SethMilliken force-pushed the images/prefetch-card-pool-images branch from d4201c6 to 29e6a0a Compare June 12, 2025 23:46
@SethMilliken

Copy link
Copy Markdown
Contributor Author

Moved prefetch method to desktop CardManager, the only place it is actually used. Build was broken since GuiMobile did not implement IGuiBase::prefetchAllImages.

- make `WorkerThreadFactory` counter threadsafe
- 0-pad thread number in thread names
@SethMilliken

Copy link
Copy Markdown
Contributor Author

Clearly I ought to have made this a "Draft" to begin with.

Latest changes:

  • Now naming thread pools
  • Switched relevant System.* logging to use slf4j Loggers instead
  • ensure path is always removed from queue on notifyObservers

@SethMilliken
SethMilliken force-pushed the images/prefetch-card-pool-images branch from 8aecb0d to d0e7b67 Compare June 13, 2025 04:01
@Jetz72

Jetz72 commented Jun 13, 2025

Copy link
Copy Markdown
Contributor
  • Switched relevant System.* logging to use slf4j Loggers instead

I think if we want to start utilizing another logger, it's the kind of thing that should be done in a big commit that hits the whole project, not just one area. Not opposed to exploring it, but it'd be good to discuss options and benefits first.

@SethMilliken

Copy link
Copy Markdown
Contributor Author
  • Switched relevant System.* logging to use slf4j Loggers instead

I think if we want to start utilizing another logger, it's the kind of thing that should be done in a big commit that hits the whole project, not just one area. Not opposed to exploring it, but it'd be good to discuss options and benefits first.

Ah, looks like I misread the repo tea leaves. All the plumbing was already there (slf4j in the poms and logback.xml in resources directory with an originating comment "replace log4j with logback"); I thought I was just turning on the tap. But, yeah, now that I look I don't see us actually using it anywhere else.

I'll get the ball rolling on the independent conversation about logging facilities, and I'll drop that commit before this lands.

@Jetz72

Jetz72 commented Jun 13, 2025

Copy link
Copy Markdown
Contributor

Its come up before (e.g.). But I don't think the matter has gotten its own dedicated discussion, issue, or PR yet.

@github-actions

Copy link
Copy Markdown

This PR has not been updated in a while nad has been marked on stale. Stale PRs will be auto closed

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.

4 participants