Episodes can now be marked watched or unwatched — this one, up to here, or the whole season — and the app knows which episodes you have seen, which it never did before.
What was missing underneath
The watched history in this app was per title: the id was truncated at the : on purpose, so tt123:2:8 and tt123 were the same thing to it, and the episode record had no watched field at all. It knew which shows you had watched and could not tell you a single episode.
Both sources already had the data and were discarding it:
- The account.
sync_pull_watched_itemshas always returnedseasonandepisodeon every row, and the code has always read them — then skipped the whole row when they were non-zero. - Trakt. The history call reads the last 100 plays and skips episodes deliberately; that endpoint answers "what was watched recently", not "what is watched".
The obvious replacement did not work, and only measuring showed it. /sync/watched/shows is documented as the complete per-season map. On a real account with 75 shows it returned 25 KB with zero occurrences of "seasons", and 90 KB with ?extended=full — still zero. Just a list of shows with play counts. The numbers are written into the code so nobody retries that path without new measurements.
What does work is /shows/<id>/progress/watched, fetched for one show, when its episode list opens. It is also better data: each episode carries an explicit completed, which is what lets the list say "not watched" without lying. With a set of "what was watched", an absent episode proves nothing; with the show enumerated, a no is an answer.
The menu
Hold OK on an episode. The direction comes from the state of the focused episode — if you are looking at something watched, you want to unmark it — and the header says which of the two will happen before you choose anything.
The count goes in the label: "Up to here (4 episodes)", "Whole season (5 episodes)". Marking one and marking twenty are different decisions and you should see which you are about to make. The number comes from the same map the action will use.
One thing with its own test, because getting it wrong is silent: order is (season, number), in that order. "Up to here" on S2E1 takes all of season 1 plus the first of season 2. Comparing only the number would take S1E1 and leave S1E4 behind, and the list would end up with holes nobody can explain.
Writing back is one request per gesture, not one per episode — Trakt accepts a nested seasons/episodes payload, and the account has a matching RPC. The local effect happens first, so the list redraws in the same frame; the network call goes to its own thread, because each side can take 20 seconds to time out and that would freeze the TV.
Three of my own defects, two found by looking at the screen
- Counting for the labels returned zero, always — the loop stopped on the output-array bound, which was zero when only counting. Every label would have read "(0 episodes)".
- The footer hint was drawn over the third option, and the menu was centred on the screen while the episode sheet occupies only the right-hand 720 pixels — floating over empty space, away from the episode it refers to.
- The "released without being pressed here" guard tested the duration, and a press and release inside the same millisecond gives zero — a legitimate fast tap, swallowed.
A new headless capture test exists because this screen cannot be reached on the TV with injected keys: it opens from the player's episode button, and getting there means playing something.
Installing
Samsung Tizen 5.5+ — NuvioTV-1.0.25-tizen.wgt, unsigned; sign it with your own TV's DUID (steps in the v1.0.7 notes).
LG webOS 4.x — space.nuvio.native.legacy_1.0.25_arm.ipk.
Unofficial, and not affiliated with NuvioMedia.