perf: lazy-render episode lists and tighten Kingfisher caching#12
Merged
Conversation
Addresses the SIMALYTICS-IOS-3 N+1 image-burst Sentry issue by cutting the per-screen request count and fixing settings that were defeating Kingfisher's own caches. - ShowDetailView, AnimeDetailView: switch the episodes container from VStack to LazyVStack so off-screen thumbnails don't fetch up front - CustomKFImage: remove .fromMemoryCacheOrRefresh(true), which was skipping the disk cache on every memory miss; remove .serialize(as: .JPEG), which stripped alpha from PNG sources (TMDB streaming logos); add DownsamplingImageProcessor sized to the view frame to reduce decoded-image memory - SimalyticsApp: cap ImageCache disk storage at 500 MB so it LRU-evicts instead of growing unbounded Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Targets a Sentry-reported image-loading burst on episode lists and tightens Kingfisher cache configuration so disk caching, PNG transparency, and decoded-image memory all behave correctly.
Changes:
- Switch the episode list
VStacktoLazyVStackinShowDetailViewandAnimeDetailViewso off-screen episode thumbnails are no longer fetched up front. - Replace
.serialize(as: .JPEG)and.fromMemoryCacheOrRefresh(true)inCustomKFImagewith aDownsamplingImageProcessorsized to the view frame. - Cap
ImageCache.default.diskStorageat 500 MB duringSimalyticsApp.init().
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| simalytics/Views/Explore/ShowDetailView.swift | Lazy-renders the episodes list to avoid fetching all thumbnails on appear. |
| simalytics/Views/Explore/AnimeDetailView.swift | Same lazy-render fix for the anime episode list. |
| simalytics/SimalyticsApp.swift | Imports Kingfisher and sets a 500 MB disk-cache size limit at startup. |
| simalytics/Components/CustomKFImage.swift | Drops JPEG re-serialization and forced refresh, adds size-based downsampling processor. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| .resizable() | ||
| .serialize(as: .JPEG) | ||
| .setProcessor(DownsamplingImageProcessor(size: CGSize(width: width, height: height))) |
| } | ||
| .resizable() | ||
| .serialize(as: .JPEG) | ||
| .setProcessor(DownsamplingImageProcessor(size: CGSize(width: width, height: height))) |
| }() | ||
|
|
||
| init() { | ||
| ImageCache.default.diskStorage.config.sizeLimit = 500 * 1024 * 1024 |
NickReisenauer
added a commit
that referenced
this pull request
May 15, 2026
Three follow-ups from PR #12: 1. CustomKFImage now caches the original (un-downsampled) image to disk so the same poster URL shared by lists (80x118, 100x147) and details (150x220.59, 150x225) hits a single disk entry. The processor still runs to bound memory, but cache-key fragmentation across view sizes is gone. 2. Clamp the processor size to at least 1pt in each dimension. Guards against any caller that passes a zero-sized frame, which would otherwise produce a zero bitmap, silently fall back to the original, and pollute the cache key with the zero size. 3. Pull the 500 MB disk-cache size limit out to a named constant with an explaining comment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Addressed all three Copilot points in 9786734 on main. The original-image disk caching is the main fix — same poster URL across list and detail views now shares one entry, restoring the snappy-on-return goal. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
__backButtonAction) by switching the episodes list inShowDetailView/AnimeDetailViewfromVStacktoLazyVStack— off-screen episode thumbnails no longer fetch up front.CustomKFImageso Kingfisher's caches actually work as intended: removes.fromMemoryCacheOrRefresh(true)(was skipping the disk cache on every memory miss) and.serialize(as: .JPEG)(was stripping alpha from PNG sources like TMDB streaming-service logos). Adds aDownsamplingImageProcessorsized to the view frame to lower decoded-image memory.ImageCache.default.diskStorageat 500 MB inSimalyticsApp.init()so the disk cache LRU-evicts instead of growing unbounded.Test plan
JustWatchView, force-quit, reopen — streaming-service logos should keep PNG transparency on cache hit (previously re-encoded to JPEG on disk).memoryCacheOnly: falsecallers).TVListView,MovieListView,AnimeListView) or detail screen posters.🤖 Generated with Claude Code