feat: MyAnimeList community score on anime details (#45) - #136
Merged
Conversation
added 2 commits
April 5, 2026 16:00
Adds a MAL score badge next to the IMDb badge on anime details pages.
The flow is:
IMDB id -> ARM API (imdb -> mal_id) -> Jikan v4 (mal_id -> score)
ARVIO already used the ARM API in SkipIntroRepository for the AniSkip
intro-marker feature, so the IMDB->MAL hop is a known working path.
Jikan v4 is the unofficial MyAnimeList REST API and is widely used by
anime apps for community score display.
Changes:
- New JikanApi interface (GET /anime/{malId}) with JikanAnimeResponse
and JikanAnimeData models that deserialize the `score` field.
- New AnimeScoreRepository (@singleton) that wraps the IMDB->MAL->score
resolution chain with in-memory LRU caching (up to 256 entries each
for imdbId->malId and malId->score, including negative caching to
avoid re-hitting ARM for titles that aren't in its database). Uses
withTimeoutOrNull(2s) on each hop so slow responses don't stall the
details load. All exceptions are swallowed to null \u2014 the caller hides
the badge on null.
- AppModule provides a new Retrofit instance for Jikan and binds
JikanApi via Hilt, matching the existing ArmApi provider pattern.
- DetailsUiState gains `malScore: Double?` (nullable, default null).
- DetailsViewModel now takes AnimeScoreRepository and fetches the MAL
score in a detached launch off the existing external-IDs resolver.
Gated on AnimeMapper.isAnimeContentStatic(tmdbId, genreIds,
originalLanguage) so we don't hit Jikan for live-action content.
Runs in parallel with the main details load; never blocks rendering.
- DetailsScreen shows a cyan/blue MAL badge in the metadata row after
the IMDb badge, only when `uiState.malScore > 0.0`. Rendered in both
the mobile layout (~line 1100) and the TV layout (~line 1530), using
the MAL brand color `#2E51A2` to distinguish it from IMDB yellow.
Jikan rate limit (~3 req/s, 60 req/min unofficial) is handled by the
LRU cache \u2014 a typical session performs at most one Jikan call per
unique anime visited, and results persist until the app process dies.
Closes #45
ProdigyV21
force-pushed
the
feat/mal-score-anime
branch
from
April 5, 2026 14:01
5e69cd6 to
eb48ccc
Compare
Closed
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.
Closes #45.
Displays a MAL community score badge next to the IMDb badge on anime details pages. Only renders for anime content and only when Jikan returns a score — non-anime and unscored entries see no visual change.
Flow
ARVIO already uses the ARM API in
SkipIntroRepositoryfor the AniSkip intro-marker feature, so the IMDB to MAL hop is a known working path. Jikan v4 is the unofficial MyAnimeList REST API and is widely used by anime apps for community score display.Changes
JikanApi.kt(new) — Retrofit interface withGET /anime/{malId}and response models that deserialize thescorefield.AnimeScoreRepository.kt(new, @singleton) — wraps IMDB to MAL to score with in-memory LRU caching (256 entries each forimdbId -> malIdandmalId -> score, including negative caching to avoid re-hitting ARM for titles that aren't in its database). UseswithTimeoutOrNull(2_000L)on each hop so slow responses don't stall details load. All exceptions swallowed to null — caller hides the badge.AppModule.kt— new Retrofit instance forhttps://api.jikan.moe/v4/and@Providesbinding forJikanApi, matching the existingArmApiprovider pattern.DetailsUiState— newmalScore: Double?field (nullable, default null).DetailsViewModel— now takesAnimeScoreRepository. Fetches the MAL score in a detachedlaunchoff the existing external-IDs resolver, gated onAnimeMapper.isAnimeContentStatic(tmdbId, genreIds, originalLanguage)so we don't hit Jikan for live-action content. Runs in parallel with the main details load — never blocks rendering.DetailsScreen— renders a MAL badge in the metadata row after IMDb, only whenuiState.malScore > 0.0. Added to both the mobile layout and the TV layout. Uses the MAL brand color#2E51A2so it's visually distinct from the yellow IMDb badge.Rate limits
Jikan unofficial rate limit is about 3 req/s, 60 req/min. The LRU cache handles this — a typical session performs at most one Jikan call per unique anime visited, and results persist for the lifetime of the process. Rebrowsing a catalog of anime costs zero network.
Risk
Low. Three entirely new files plus minor additive changes to three existing files. No existing flow is touched; the MAL badge renders only for anime AND only when Jikan returns a score. Jikan being down = no badge; ARM being down = no badge; 2s timeout on each hop means worst case is 4 seconds of background work that never surfaces to the UI.
Test
isAnimeContentStaticgate).