Skip to content

feat(home): show watched ticks without a Trakt sign-in - #758

Merged
ProdigyV21 merged 6 commits into
ProdigyV21:mainfrom
ReichiMD:claude/serene-allen-x8974y
Sep 26, 2026
Merged

ProdigyV21 merged 6 commits into
ProdigyV21:mainfrom
ReichiMD:claude/serene-allen-x8974y

Conversation

@ReichiMD

Copy link
Copy Markdown
Contributor

Summary

Home showed the watched tick on its cards only when the profile had a Trakt token. Search and Discover mark their cards for every profile since #751, and Details never checked Trakt either — so a profile on local history, Cloud, MDBList or SIMKL saw ticks everywhere except on Home.

Changes

  • No Trakt gate in refreshWatchedBadges. isAuthenticated only means "a Trakt token is stored", but initializeWatchedCache() already fills the cache from local, Cloud, MDBList and SIMKL history. Home now marks from that cache like the other screens.
  • Series history indexed once, off the network pool on Dispatchers.Default: the episode history becomes a set of started show ids instead of one hasWatchedEpisodes(id) scan per show — the same pattern as SearchViewModel.watchedMatcher after cfded3c.
  • Ticks applied to the latest state. The old code wrote back a snapshot of the rows taken before the reads, so a row published in between (a catalog page, Continue Watching) could be rolled back. It now uses _uiState.update { … }, as Search does.
  • The hero keeps its details. The tick pass used to replace the hero with the plain row card, which dropped the runtime, ratings, budget and network logo that are hydrated into the hero only (until focus moved). It now copies just the tick. This was already the case for Trakt profiles; without the gate every profile with history would have hit it.
  • Every new set of rows gets its ticks. On a phone without Trakt no tick ever showed once the gate was gone: the startup cache rows were marked and started the 90 s throttle, then the catalog load published fresh, unmarked rows and its pass was throttled away — and nothing asked again. The throttle now only skips a pass when the rows are the very ones the last pass marked (watchedBadgesPassIsRedundant). A small collector on categories (identity, not equality) triggers the debounced pass for every newly published set of rows — startup cache, catalog load, next page, cloud reload — instead of relying on the three call sites. Home resuming (back from Details) forces a pass, as Search does with refreshWatchedMarks(). That resume pass only debounces 300 ms once a pass has run (watchedBadgesPassDelayMs): with the startup pause it took 3 s on a phone (memoryClass <= 256 counts as low-RAM) although the pass itself takes milliseconds. The first pass after launch or a profile switch keeps the startup pause. Once a pass has run, re-published rows take over what it found at once (HomeUiState.withWatchedBadges), so the ticks no longer blink off for ~3 s when the catalog load lands after the startup cache.
  • Tick throttle reset on profile switch. resetProfileRuntimeState reset everything except lastWatchedBadgesRefreshMs, so the next profile could wait up to 90 s for its ticks.
  • The marking lives in three small internal functions (startedShowIds, applyWatchedBadges, heroWithWatchedBadge) so it is unit-tested without building the whole HomeViewModel. Continue Watching is still skipped (it has its own progress bars), and unchanged rows keep their instances, so a refresh that finds nothing new recomposes nothing.

Note: the KDoc on TraktRepository.initializeWatchedCache still says the cache stays empty without Trakt auth. That is no longer true (it loads local, Cloud, MDBList and SIMKL history) and may make the removed gate look intentional. I left the comment alone to keep this PR to Home.

Not in this PR

The long-press "mark watched" on a Home card still does not set the tick right away (so the menu keeps offering "mark watched" until the next pass). Same for Trakt profiles today; happy to send it as a small follow-up.

Offer

Search and Home now read "watched" the same way (film in the watched list, series started) in two places. If you prefer, a follow-up can let Search call startedShowIds or move both into one shared helper. I kept them separate so this PR stays small.

Testing

  • New HomeWatchedBadgesTest (8 tests): history indexing with 20,000 episode keys (Trakt-only and malformed keys skipped), films and started shows marked, Continue Watching untouched, ticks removed when the title leaves the history, unchanged rows keep their instances, the hero keeps runtime/ratings/logo and takes over only the tick, fresh rows are never throttled while the rows a pass already marked are, the resume pass is quick while the first pass keeps the startup pause, re-published rows and the hero take over the known ticks.
  • testSideloadDebugUnitTest: 1826 tests, 0 failures.
  • Test APK on a phone, profile without Trakt: tick on Home after marking a film and an episode in Details and going back, still there after restarting the app, no ticks on a second profile (checked with a temporary logcat line on the test build only).
Screenshot_20260925-223131

created by Claude (Anthropic) on behalf of @ReichiMD

Home marked its cards only when a Trakt token was present, while Search,
Discover and Details already mark from the same watched cache for every
profile (local, Cloud, MDBList, SIMKL). Drop the Trakt gate, index the
episode history once into started show ids instead of scanning it per
show, and mark the latest UI state instead of writing back a snapshot
taken before the reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RvQSEcH38SjW7hjUY8TvSs
The tick pass replaced the hero with the plain row card, dropping the
runtime, ratings, budget and network logo that are hydrated into the
hero only; it now takes over just the tick. A profile switch reset
every runtime state except the tick throttle, so the next profile could
wait up to 90 s for its ticks. The history index and the state update
run on Dispatchers.Default, as in Search, instead of the network pool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RvQSEcH38SjW7hjUY8TvSs
On a device no tick ever showed: the startup cache rows were marked and
started the 90 s throttle, then the catalog load published fresh,
unmarked rows and its tick pass was throttled away; nothing asked again.
The throttle now only skips a pass when the rows are the very ones the
last pass marked. Every new set of rows (startup cache, catalog load,
next page, cloud reload) triggers a debounced pass, and Home resuming
(back from Details) forces one, as Search does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RvQSEcH38SjW7hjUY8TvSs
The pass Home asks for on resume waited the full startup pause (3 s on
most phones, memoryClass <= 256) although the cache is loaded and the
pass takes milliseconds. Once a pass has run, a resume pass now only
debounces for 300 ms; the first pass after launch or a profile switch
keeps the startup pause.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RvQSEcH38SjW7hjUY8TvSs
On a phone the ticks showed after the startup pass, vanished when the
catalog load re-published the rows (unmarked) and came back 3 s later.
New rows now take over what the last pass found at once; a full pass
still runs when no pass has run yet or on resume. The marking of rows
and hero moved into HomeUiState.withWatchedBadges, shared by both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RvQSEcH38SjW7hjUY8TvSs
@ProdigyV21
ProdigyV21 merged commit 08979a2 into ProdigyV21:main Sep 26, 2026
5 checks passed
@ProdigyV21

Copy link
Copy Markdown
Owner

Merged, thanks for making Home's watched badges work without a Trakt login!

Added a small follow-up (1663726): the hero badge now updates even when the rows already have correct badges, and history is indexed in the background before publishing on Main with a profile check and updated lookup bookkeeping. No layout/backdrop changes. Your original commits and PR authorship are preserved.

Both new regression tests failed before the fix and pass afterward. All 56 Home tests passed locally, both Android variants compiled, and GitHub's full Sideload unit suite plus backend/web checks passed. The local full suite encountered seven DataStore temporary-file rename failures in StreamIntegrationRepositoryTest; these passed in Linux CI. No physical-device testing was performed for this patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: android Changes to the Android app or Gradle build

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants