refactor(model): give ItemImage an AspectRatio method

The zero/absent guards around width/height are ItemImage's own invariant, not
the Jellyfin adapter's. Moving them onto the model keeps one definition for
every consumer, so a second one cannot quietly disagree about what an unknown
ratio means.
This commit is contained in:
Deluan 2026-07-26 11:26:57 -04:00
parent 09b647c9d0
commit ff010f8db1
3 changed files with 29 additions and 3 deletions

View File

@ -27,6 +27,15 @@ type ItemImage struct {
ImageHeight int `structs:"-" json:"imageHeight,omitempty"`
}
// AspectRatio is the image's width/height, or nil when there is no image or its dimensions are
// unknown (an unresolved item). Never guesses: a wrong ratio mis-shapes a client's placeholder.
func (i ItemImage) AspectRatio() *float64 {
if i.ImageAbsent || i.ImageWidth <= 0 || i.ImageHeight <= 0 {
return nil
}
return new(float64(i.ImageWidth) / float64(i.ImageHeight))
}
// ItemArtwork is an entity's resolved artwork state. Hash=="" means known absent.
type ItemArtwork struct {
ItemKind string `structs:"item_kind"`

View File

@ -52,6 +52,24 @@ var _ = Describe("ItemImage JSON", func() {
Expect(out).ToNot(HaveKey("imageHeight"))
})
Describe("AspectRatio", func() {
It("returns width/height", func() {
img := model.ItemImage{ImageHash: "abc", ImageWidth: 1200, ImageHeight: 800}
Expect(*img.AspectRatio()).To(BeNumerically("~", 1.5, 0.0001))
})
It("returns nil when a dimension is missing, so callers never guess a ratio", func() {
Expect(model.ItemImage{ImageHash: "abc"}.AspectRatio()).To(BeNil())
Expect(model.ItemImage{ImageHash: "abc", ImageWidth: 1200}.AspectRatio()).To(BeNil())
Expect(model.ItemImage{ImageHash: "abc", ImageHeight: 800}.AspectRatio()).To(BeNil())
})
It("returns nil for a known-absent image, whatever the dimensions say", func() {
img := model.ItemImage{ImageAbsent: true, ImageWidth: 1200, ImageHeight: 800}
Expect(img.AspectRatio()).To(BeNil())
})
})
It("exposes known-absent artwork so clients can skip the request", func() {
ar := model.Artist{ID: "ar-1", Name: "Artist"}
ar.ImageAbsent = true

View File

@ -232,9 +232,8 @@ func primaryImage(img model.ItemImage, fallback string, fields Fields) (tag stri
if img.BlurHash != "" {
blurs = map[string]map[string]string{"Primary": {tag: img.BlurHash}}
}
// Dimensions are unknown while an item is unresolved; omit rather than guess a ratio.
if fields.Has("PrimaryImageAspectRatio") && img.ImageWidth > 0 && img.ImageHeight > 0 {
ratio = new(float64(img.ImageWidth) / float64(img.ImageHeight))
if fields.Has("PrimaryImageAspectRatio") {
ratio = img.AspectRatio()
}
return tag, blurs, ratio
}