FOXA-3245 : marquer un épisode vu rouvre sa série dans « Reprendre » #297

Merged
foXaCe merged 1 commit from passe-20261018-153000-reprendre into main 2026-10-18 13:05:49 +02:00
Owner

FOXA-3245. L'écartement est une préférence : une série écartée disparaît de la rangée
« Reprendre » jusqu'à ce qu'on la rouvre. Mais markWatched(items) déléguait sans rien rouvrir :
removeDismissedNextUpKeysForContent n'était appelé que par l'enregistrement d'une progression
(WatchProgressRepository.kt:1131), jamais par WatchedRepository.

Deux corrections

  1. Le câblage manquant. markWatched(items) retire l'écartement des CONTENUS dont un épisode
    vient d'être marqué vu — avant la délégation, comme le ticket le prescrit.
  2. Un défaut de plus, que le ticket nomme. removeDismissedNextUpKeysForContent ne retirait que
    le préfixe id|… : une clé enregistrée sans coordonnées d'épisode (id seul) survivait au
    retrait, et la série restait disparue. Elle retire maintenant aussi la clé exacte.

⚠ Ce qui distingue un épisode n'est pas le type

Une marque de série et une marque d'épisode portent le même type et le même id ; seules
les coordonnées season/episode les séparent. Filtrer sur le type aurait rouvert la série en
marquant la série entière, ou jamais. Les identifiants sont rendus distincts : la préférence est
par contenu, pas par épisode.

Les preuves

Deux fonctions pures, pour que la règle soit mesurable sans réseau ni stockage :
identifiantsDeContenuDesEpisodes(items) et clesDEcarteApresRetrait(cles, contentId).

10 tests :

ce qui est mesuré comment
la clé exacte tombe avec le préfixe show, show|1|2, show|2|1 disparaissent ensemble
les autres contenus restent écartés rouvrir show laisse autre et autre|1|1
un préfixe qui ressemble ne suffit pas showcase n'est pas show
un identifiant vide ne retire rien l'ensemble est rendu inchangé
un identifiant est normalisé show vaut show
seuls les épisodes désignent un contenu une marque de série et un film ne rouvrent rien
dix épisodes ne font qu'un contenu identifiants distincts
le câblage précède la délégation sans ce verrou, retirer l'appel laisserait les autres verts
./gradlew :composeApp:testAndroidHostTest -Pnuvio.android.distribution=full \
    --tests '*LesClesDEcarteRetireesTest*' \
    --tests '*LesEpisodesMarquesVusRouvrentLeurSerieTest*'
BUILD SUCCESSFUL — 10 tests, 0 échec (+ 10 de WatchedRepositoryTest, verts)

Ce que cette PR ne fait pas

markWatchedFromPlaybackCompletion n'est pas touché. Le ticket vise le marquage depuis la fiche ;
élargir la règle à la fin de lecture est un autre geste, et il se décide — pas par effet de bord.

`FOXA-3245`. L'écartement est une préférence : une série écartée disparaît de la rangée « Reprendre » jusqu'à ce qu'on la rouvre. Mais `markWatched(items)` déléguait **sans rien rouvrir** : `removeDismissedNextUpKeysForContent` n'était appelé que par l'enregistrement d'une progression (`WatchProgressRepository.kt:1131`), jamais par `WatchedRepository`. ## Deux corrections 1. **Le câblage manquant.** `markWatched(items)` retire l'écartement des CONTENUS dont un épisode vient d'être marqué vu — avant la délégation, comme le ticket le prescrit. 2. **Un défaut de plus, que le ticket nomme.** `removeDismissedNextUpKeysForContent` ne retirait que le préfixe `id|…` : une clé enregistrée **sans coordonnées d'épisode** (`id` seul) survivait au retrait, et la série restait disparue. Elle retire maintenant aussi la **clé exacte**. ## ⚠ Ce qui distingue un épisode n'est pas le `type` Une marque de série et une marque d'épisode portent le **même** `type` et le **même** `id` ; seules les coordonnées `season`/`episode` les séparent. Filtrer sur le type aurait rouvert la série en marquant la série entière, ou jamais. Les identifiants sont rendus **distincts** : la préférence est par contenu, pas par épisode. ## Les preuves Deux fonctions pures, pour que la règle soit mesurable sans réseau ni stockage : `identifiantsDeContenuDesEpisodes(items)` et `clesDEcarteApresRetrait(cles, contentId)`. **10 tests** : | ce qui est mesuré | comment | |---|---| | la clé exacte tombe avec le préfixe | `show`, `show\|1\|2`, `show\|2\|1` disparaissent ensemble | | les autres contenus restent écartés | rouvrir `show` laisse `autre` et `autre\|1\|1` | | un préfixe qui **ressemble** ne suffit pas | `showcase` n'est pas `show` | | un identifiant vide ne retire rien | l'ensemble est rendu inchangé | | un identifiant est normalisé | ` show ` vaut `show` | | seuls les épisodes désignent un contenu | une marque de série et un film ne rouvrent rien | | dix épisodes ne font qu'un contenu | identifiants distincts | | le câblage précède la délégation | sans ce verrou, retirer l'appel laisserait les autres verts | ``` ./gradlew :composeApp:testAndroidHostTest -Pnuvio.android.distribution=full \ --tests '*LesClesDEcarteRetireesTest*' \ --tests '*LesEpisodesMarquesVusRouvrentLeurSerieTest*' BUILD SUCCESSFUL — 10 tests, 0 échec (+ 10 de WatchedRepositoryTest, verts) ``` ## Ce que cette PR ne fait pas `markWatchedFromPlaybackCompletion` n'est pas touché. Le ticket vise le marquage **depuis la fiche** ; élargir la règle à la fin de lecture est un autre geste, et il se décide — pas par effet de bord.
FOXA-3245 : marquer un épisode vu rouvre sa série dans « Reprendre »
All checks were successful
Porte / porte (pull_request) Successful in 5m58s
a63868a5df
L'écartement est une préférence : une série écartée disparaît de la rangée « Reprendre » jusqu'à ce
qu'on la rouvre. Mais `markWatched(items)` déléguait sans rien rouvrir : `[M]`
`removeDismissedNextUpKeysForContent` n'était appelé que par l'enregistrement d'une progression
(`WatchProgressRepository.kt:1131`), jamais par `WatchedRepository`.

Deux corrections, et la seconde est un défaut de plus que le ticket nomme :

  · `markWatched(items)` retire l'écartement des CONTENUS dont un épisode vient d'être marqué vu —
    avant la délégation, comme le ticket le prescrit ;
  · `removeDismissedNextUpKeysForContent` retire aussi la **clé exacte**, pas seulement le préfixe
    `id|…` : une clé enregistrée sans coordonnées d'épisode (`id` seul) survivait au retrait, et la
    série restait disparue.

⚠ CE QUI DISTINGUE UN ÉPISODE N'EST PAS LE `type`. Une marque de série et une marque d'épisode
portent le même `type` et le même `id` ; seules les coordonnées `season`/`episode` les séparent.
Filtrer sur le type aurait rouvert la série en marquant la série entière, ou jamais. Les
identifiants sont rendus DISTINCTS : la préférence est par contenu, pas par épisode.

Deux fonctions pures, pour que la règle soit mesurable sans réseau ni stockage :
`identifiantsDeContenuDesEpisodes(items)` et `clesDEcarteApresRetrait(cles, contentId)`.

10 tests :

  · le filtre — la clé exacte tombe avec le préfixe, les autres contenus restent écartés, un
    préfixe qui RESSEMBLE (`showcase` vs `show`) ne suffit pas, un identifiant vide ne retire rien,
    un identifiant est normalisé ;
  · la sélection — seuls les épisodes désignent un contenu, dix épisodes ne font qu'un contenu, un
    identifiant vide ne désigne rien ;
  · le câblage — l'appel précède bien la délégation (sans ce verrou, retirer l'appel laisserait
    les autres verts : ils mesurent la sélection, pas le lien).

    ./gradlew :composeApp:testAndroidHostTest -Pnuvio.android.distribution=full \
        --tests '*LesClesDEcarteRetireesTest*' \
        --tests '*LesEpisodesMarquesVusRouvrentLeurSerieTest*'
    BUILD SUCCESSFUL, 10 tests, 0 échec (+ 10 de WatchedRepositoryTest, verts)

Ce que ce commit ne fait pas : `markWatchedFromPlaybackCompletion` n'est pas touché. Le ticket vise
le marquage depuis la fiche ; élargir la règle à la fin de lecture est un autre geste, et il se
décide — pas par effet de bord.
foXaCe merged commit 1a19062e4b into main 2026-10-18 13:05:49 +02:00
foXaCe deleted branch passe-20261018-153000-reprendre 2026-10-18 13:05:49 +02:00
Sign in to join this conversation.
No reviewers
No labels
montee-majeure
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
foXaCe/NuvioMobile!297
No description provided.