Skip to content

fix(book-card): prefer audiobook covers for square mixed-format cards#467

Merged
zachyale merged 1 commit into
developfrom
fix/square-cover-audiobook-priority
Apr 11, 2026
Merged

fix(book-card): prefer audiobook covers for square mixed-format cards#467
zachyale merged 1 commit into
developfrom
fix/square-cover-audiobook-priority

Conversation

@zachyale

@zachyale zachyale commented Apr 11, 2026

Copy link
Copy Markdown
Member

Description

Linked Issue: Fixes #465

Changes

  • update book card cover selection to prefer audiobook thumbnails when square covers are enabled and the book has an audiobook format
  • add focused test coverage for mixed-format books with square covers

Summary by CodeRabbit

  • Bug Fixes

    • Updated book cover image selection logic to display audiobook thumbnails when square covers are enabled and an audiobook format is available (whether as primary or alternative format).
  • Tests

    • Added unit test coverage for cover image URL selection with audiobook formats and square cover preferences.

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The changes add logic to prioritize audiobook thumbnail covers when displaying books in square aspect ratio contexts, such as the "Continue Listening" scroller. A new computed flag detects if a book has an audiobook format (either primary or alternative), and the cover selection now considers both audiobook availability and square cover display settings.

Changes

Cohort / File(s) Summary
Book Card Logic
frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts
Added hasAudiobookFormat computed flag to detect audiobook presence in primary file or alternative formats. Updated coverImageUrl() to select audiobook thumbnail when square covers are enabled and audiobook format is available.
Book Card Tests
frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts
Added unit test verifying coverImageUrl() returns audiobook thumbnail URL when useSquareCovers is true, and normal cover URL when false, for books with both EPUB and AUDIOBOOK formats.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

frontend, enhancement

Poem

🐰 A fuzzy-eared fix for covers so square,
When audiobooks and ebooks share the same pair,
Now the audio wins in the listening zone,
No more ebook thumbnails stealing the throne! 📚🎧

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title follows conventional commit format with 'fix' type, clear scope 'book-card', and descriptive message about the change.
Description check ✅ Passed The pull request description includes the required template sections: Description, Linked Issue, and Changes, with sufficient detail about what was changed.
Linked Issues check ✅ Passed The code changes directly address issue #465 by implementing audiobook cover prioritization for square format displays and adding test coverage for mixed-format books.
Out of Scope Changes check ✅ Passed All changes are focused on the book card component and directly support the linked issue's objective to prioritize audiobook covers in square-aspect contexts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/square-cover-audiobook-priority
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/square-cover-audiobook-priority

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts`:
- Around line 120-123: The computed coverImageUrl currently uses
urlHelper.getAudiobookThumbnailUrl(...) for audiobooks/square mixed formats but
that call can return null and cause a missing thumbnail; change the logic in the
coverImageUrl computed (the computed itself referencing isAudiobook(),
useSquareCovers(), hasAudiobookFormat()) to call
urlHelper.getAudiobookThumbnailUrl(this.book().id,
this.book().metadata?.audiobookCoverUpdatedOn) into a temporary value and if it
is null/undefined fall back to urlHelper.getThumbnailUrl(this.book().id,
this.book().metadata?.coverUpdatedOn) (e.g. using a nullish coalescing or
conditional) so a valid ebook thumbnail is used when audiobook cover metadata is
absent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c7290622-df90-40a3-bf8c-e5f89d66ac31

📥 Commits

Reviewing files that changed from the base of the PR and between 66dcc44 and 840c6ec.

📒 Files selected for processing (2)
  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts
  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Test Suite / Backend Tests
  • GitHub Check: Test Suite / Frontend Tests
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (4)
frontend/src/**/*.{ts,tsx,html,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use 2-space indentation in TypeScript, HTML, and SCSS files

Files:

  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts
  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts
frontend/src/app/**/*.component.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep Angular code on standalone components. Do not add NgModules

Files:

  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts
frontend/src/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

frontend/src/app/**/*.{ts,tsx}: Prefer inject() over constructor injection
Follow frontend/eslint.config.js: component selectors use app-*, directive selectors use app*, and any is disallowed

Files:

  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts
  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts
frontend/src/**/*.{test,spec}.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use Vitest for tests in the frontend

Files:

  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: pedronave
Repo: grimmory-tools/grimmory PR: 173
File: booklore-api/src/main/java/org/booklore/service/hardcover/HardcoverSyncService.java:188-199
Timestamp: 2026-03-24T18:46:47.249Z
Learning: In grimmory-tools/grimmory (HardcoverSyncService.java), when a `hardcoverBookId` is stored in book metadata but is malformed (non-numeric), the preferred behavior is to return null and skip the sync rather than falling back to ISBN-based lookup. The reasoning is that an explicitly set bookId represents deliberate user intent, and silently resolving via ISBN could sync progress to a different book than intended.
📚 Learning: 2026-04-04T14:03:28.295Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 372
File: frontend/src/app/features/book/service/app-books-api.service.ts:150-178
Timestamp: 2026-04-04T14:03:28.295Z
Learning: In `frontend/src/app/features/book/service/app-books-api.service.ts`, the `summaryToBook` function intentionally uses `as unknown as Book` to cast a partial object to the `Book` type. The returned object omits some required `Book` fields (e.g. `metadata.bookId`, `pdfProgress.page`) and includes an extra `bookFiles: []` property not in the `Book` interface. This is by design — consumers of `AppBooksApiService.books()` (e.g. `BookCardComponent`) only access the subset of properties that are populated from `AppBookSummary`, so no runtime issues occur. Do not flag this as a type safety error.

Applied to files:

  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts
  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts
📚 Learning: 2026-04-05T21:16:01.715Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 385
File: frontend/src/app/app.component.ts:55-56
Timestamp: 2026-04-05T21:16:01.715Z
Learning: When reviewing code in the Grimmory frontend (Angular), prefer modern Angular patterns. Specifically: (1) Prefer `DestroyRef` with `takeUntilDestroyed(destroyRef)` for teardown in Angular v16+ instead of manually tracking `Subscription` arrays and calling `unsubscribe()` in `ngOnDestroy()`. (2) Prefer `inject()` for dependency injection over constructor injection where appropriate. (3) Prefer Angular signals (e.g., `signal`, `computed`) over `BehaviorSubject`/`Observable` for state where signals/computed values fit the use case. Flag older patterns when they can be replaced with these modern equivalents without changing behavior.

Applied to files:

  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts
  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts
📚 Learning: 2026-04-07T09:28:09.587Z
Learnt from: balazs-szucs
Repo: grimmory-tools/grimmory PR: 393
File: frontend/src/app/features/readers/pdf-reader/pdf-reader.component.ts:255-263
Timestamp: 2026-04-07T09:28:09.587Z
Learning: In this Angular frontend (under frontend/src/app/), flag manual resource management/cleanup patterns when there is an Angular v16+ automatic alternative. Examples to prefer: (1) Instead of manually pairing document/window event listeners with stored cleanup functions (e.g., add/removeEventListener with mouseMoveCleanup/documentClickCleanup/keydownCleanup/touchCleanup fields), register teardown via DestroyRef.onDestroy(cleanupFn) (or equivalent Angular v16+ teardown mechanism). (2) Instead of storing Subscriptions in fields and explicitly unsubscribing in ngOnDestroy (e.g., annotationSaveSubscription/annotationCacheSubscription), use takeUntilDestroyed(destroyRef) (piped into the observable) or other Angular v16+ primitives. (3) If teardown is lifecycle-coupled and can be automated via DestroyRef/takeUntilDestroyed/signals (or other Angular v16+ mechanisms), prefer the automated approach over manual ngOnDestroy cleanup. Raise a review finding for the manual pattern and recommend the aut...

Applied to files:

  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts
  • frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts
🔇 Additional comments (2)
frontend/src/app/features/book/components/book-browser/book-card/book-card.component.ts (1)

114-118: Good mixed-format audiobook detection.

This correctly extends audiobook detection beyond primaryFile and matches the square-cover objective.

frontend/src/app/features/book/components/book-browser/book-card/book-card.component.spec.ts (1)

302-331: Targeted test coverage looks solid.

This test cleanly validates the square-cover audiobook-priority behavior for mixed-format books and the non-square fallback path.

@zachyale zachyale merged commit f64864d into develop Apr 11, 2026
14 checks passed
@zachyale zachyale deleted the fix/square-cover-audiobook-priority branch April 11, 2026 02:56
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.

[Nightly] When a book with an audiobook and ebook is in the 'Continue Listening' scroller, the ebook cover is used instead of the audiobook cover

1 participant