Skip to content

Show large covers in the Library widgets - #1650

Merged
GianniCarlo merged 1 commit into
developfrom
fix/widget-artwork-thumbnails
Oct 16, 2026
Merged

GianniCarlo merged 1 commit into
developfrom
fix/widget-artwork-thumbnails

Conversation

@GianniCarlo

Copy link
Copy Markdown
Collaborator

Problem

Large covers break the Library widgets:

  • Recently Played checks each cover against WidgetKit's limit of 718,080 pixels and shows the exclamation-mark placeholder for any cover over it. A 1000×1000 cover is already over, so most real covers never show.
  • Last Played loads the original file and redraws it under that limit, but the redraw decodes the whole cover first. A 4000×4000 cover is about 64 MB decoded, more than a widget extension may use, so the widget fails to render.

Changes

  • WidgetUtils.getArtworkImage(for:length:scale:theme:) decodes the cached cover straight to the size the widget draws it, with ImageIO's thumbnail API (CGImageSourceCreateThumbnailAtIndex). The full cover is never decoded: memory follows the widget's size, not the original's, and every result is far under WidgetKit's pixel limit. It still falls back to the default artwork.
  • Last Played asks for its 90 pt cover, and Recently Played for its 60 pt covers, both at the screen's scale.
  • isValidSize and resizedForWidget are gone: nothing is over the limit anymore.

Testing

  • iPhone (device): the four most recently played books given covers from 3000×3000 to 6000×6000 (JPEG and PNG). On develop, Recently Played showed the placeholder for each and Last Played didn't render; with this change both show every cover.
  • iPhone 17 Pro simulator (iOS 27.0): the widget gallery's Last Played and Recently Played previews with four 3000–4000 px covers (one PNG).
  • App and widget extension build with no new warnings.

Recently Played showed a placeholder for any cover over WidgetKit's
718,080-pixel limit, and Last Played decoded the whole cover before
shrinking it, which runs a widget extension out of memory on a large one.
Both now build an ImageIO thumbnail straight from the cached file at the
size they draw it, so the full cover is never decoded and every image is
far under the limit.
@github-actions

Copy link
Copy Markdown

✅ Claude PR Review — PASS

This PR changes WidgetUtils.getArtworkImage to use ImageIO's thumbnail API (CGImageSourceCreateThumbnailAtIndex). The cached cover is decoded straight to the size the widget draws it (length * displayScale), so it is never decoded at full size. It drops isValidSize/resizedForWidget, and both Last Played (90 pt) and Recently Played (60 pt) now call the same helper. The only callers are those two phone views, and the helper sits inside the #if os(iOS) block where ImageIO is imported, so the watch build is unaffected. Results stay well under WidgetKit's 718,080-pixel limit and memory follows the widget's size. The default-artwork fallback (50×50 pt) still works, and ImageIO doesn't upscale smaller covers. Nothing here touches concurrency, the player, CoreData/SwiftData, or accounts and entitlements: the work is synchronous image decoding in a widget view body, the same as before. One small point: a non-square cover is still stretched into the square frame, exactly as before, so that is not a regression.

Findings: no findings

Converged: nothing new this round, and no earlier finding is open.

Model claude-opus-5-5 · run log · 0 new · 0 carried over · 0 resolved · advisory (a human should still review). Findings are de-duplicated across pushes; an earlier finding closes only when the verification pass judges it against the current code — fixed, no longer applicable, accepted by a maintainer, or a duplicate of a finding reported on this push.

@GianniCarlo
GianniCarlo merged commit 4c7b1c8 into develop Oct 16, 2026
3 checks passed
@GianniCarlo
GianniCarlo deleted the fix/widget-artwork-thumbnails branch October 16, 2026 22:52

This branch was successfully deployed

1 active deployment
reviewer — ee6ec73d Deployed Oct 16, 2026 by GianniCarlo via review #276
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant