feat(app): show rewatch count on the watched badge - #362
matheus-souza wants to merge 1 commit into
Conversation
The watched check on a card is binary, so a show, season, episode or movie watched three times looks exactly like one watched once. The count existed only inside movie and episode details, as "WATCHED - N", and shows and seasons had no count anywhere. The data is already local and costs no request: the watched progress cache keeps every play date per episode and per movie. A title's rewatch count is now the lowest play count across a show's non-special episodes (or the movie's play count), and it is only surfaced once the title reads as fully watched, so a partial rewatch never claims a complete one. The four near-identical private chip implementations in the media cards collapse into one CollectionChip that renders "icon + Nx" above one play and keeps its exact previous size at one.
|
Hi and thanks for the PR, If you wish to introduce something new into the app that's NOT already available in the website please open PR for the web first - or even better start with an Github issue or Featurebase request. This way tokens and time will not be wasted ;) If you spot something thats already on web but not yet in the app then PR is welcome surely. If this one contains something like this partially please extract this in a new separate smaller one. Thanks! This info should be available in the readme actually. I will be adding this now and also copy this message to other PRs. |
|
The portable part of this is now up for the web:
Worth knowing for this PR: the web already had most of the thinking done. Scope note: season posters and the episode rows inside a season stay out of the web PR. |
Closes #361
Mirrored on the web in trakt/trakt-web#3215 (issue) and trakt/trakt-web#3216 (implementation). Worth noting from that trip:
getShowWatchState.minPlaysanduseWatchCountalready implement the same "lowest play count across regular episodes, only once fully watched" rule argued for here, and the web already rendersWATCHED · Non summary posters - so the two platforms agree on the figure, and only the list cards were a real gap there. Season posters and the episode rows inside a season stay out of the web PR, sinceuseWatchCounthas no season case.The watched check is binary, so a title watched three times looks exactly like one watched once in every listing. The count existed only in movie and episode details, as
WATCHED • N; shows and seasons had none at all. This puts the count on the chip itself, so a list answers "how many times did I watch this" without a tap.What counts as "watched N times"
For a movie, the play count. For a show, the lowest play count across its non-special episodes; for a season, the same within that season. The figure is only surfaced once the title already reads as fully watched, so a partial rewatch shows nothing rather than claiming a complete one.
floor(total plays / aired episodes)was the obvious alternative and it lies: 61 episodes at three plays plus one at a single play rounds to "2x". The minimum is the only number true for every episode.The count is rendered only above one play, so a title watched once keeps the chip it has today, byte for byte.
Changes
:common— the count —ProgressItem.ShowItemgainscompletedPlays(andShowItem.Season.completedPlays), computed the same way as the existingplays/playsWithoutSpecialsgetters.CollectionStateProviderpopulates acompletedShowsPlaysmap alongside the existingwatchedShowsPlays, andwatchedMoviesgoes from aSet<TraktId>to aMap<TraktId, Int>of play counts — the field is private, soisWatchedjust moves fromcontainstocontainsKey.UserCollectionStategainsplays(traktId, type, airedEpisodes), a sibling ofisWatched/isWatchingthat returns0unless the title is fully watched.No networking change.
/users/me/watched/showsand/users/me/watched/moviesalready return every play date per episode and per movie; only the sum was being used.:app— one chip instead of four — the same pill was implemented four times: privately inVerticalMediaCardandHorizontalMediaCard, inline inPanelMediaCardandPanelHorizontalMediaCard. They collapse intoui/components/mediacards/CollectionChip.kt, which absorbs the variations that existed between them (24x16 vs 22x16, 1.5dp vs 1dp elevation, the halved "watching" state) as parameters. With no count it is the same fixed-size box as before; with a count it becomes an auto-width row of icon plusNx, and its height becomes a minimum so the counter can grow with the system font scale.:app— the count reaches the cards — the four cards gainplays: Int = 0. The default means every call site not touched here compiles and renders exactly as before. The ~27 listings that already readcollection.isWatched(...)now also passcollection.plays(...), threaded through each file's local item composable.:app— shows, seasons, episodes —ShowDetailsState.ProgressStategainscompletedPlays, soShowDetailsHeadercan stop passingplaysCount = nulland the poster chip rendersWATCHED • Nlike movies and episodes already do.ShowSeasons.markWatchedSeasonsandmarkWatchedEpisodescarry the count intoSeasonItem.playsandEpisodeItem.plays—markWatchedEpisodesswaps its set of watched ids for a map of id to play count, which is whereisWatchednow comes from too. Both the season rail and the episode rows read it, on the show details section and on the full-screen seasons view.No new strings. The show header reuses
tag_text_watched, already translated in every locale, in the same inline template movie and episode details use; the chip renders a digit and a multiplication sign, which is not translatable text.Testing
./gradlew :app:assembleInternalDebugand ktlint 1.7.1 both pass.Verified on an emulator (API 31) against a real account, using a 9-episode show marked watched a second time and a movie marked watched a second time:
VerticalMediaCard)2xPanelMediaCard)2xWATCHED • 22xHorizontalMediaCard)2xon eachPanelHorizontalMediaCard)2xon eachWATCHED • 2, unchanged behaviourTwo caveats worth stating:
Row, so it mirrors the same way the existing watched/watchlist chip pair already does, but I could not force an RTL locale on this emulator to confirm it visually.:tvmodule keeps its own copies of the media cards and is untouched. It can follow separately.