Repository navigation
refactor(webapp): split main.tsx into app/ and player.tsx along the provider's seams - #362
Conversation
….tsx into app/ Signed-off-by: InstaZDLL <github.105mh@8shield.net>
…g it as the player's face Signed-off-by: InstaZDLL <github.105mh@8shield.net>
Signed-off-by: InstaZDLL <github.105mh@8shield.net>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Routes racine et coque authentifiée webapp/src/app/routes/root.tsx, webapp/src/app/shell.tsx |
Les routes racine distinguent les accès publics et authentifiés. La coque compose les fournisseurs et les éléments d’interface, puis affiche un état d’attente lorsque le périmètre de bibliothèque n’est pas prêt. |
Routes par domaine et assemblage webapp/src/app/routes/library.tsx, webapp/src/app/routes/listen.tsx, webapp/src/app/routes/maintenance.tsx, webapp/src/app/routes/settings.tsx, webapp/src/app/route-tree.ts, webapp/src/main.tsx, CLAUDE.md |
Les routes sont réparties par domaine, avec validation de paramètres et redirections d’anciennes adresses. route-tree.ts les assemble; main.tsx importe cet arbre. |
Navigation responsive et préchargement webapp/src/app/navigation-entries.ts, webapp/src/app/navigation.tsx, webapp/src/app/more-sheet.tsx |
Les entrées sont groupées et filtrées selon les autorisations. Les changements d’onglet peuvent attendre le préchargement des données, jusqu’à 1 500 ms. Sur mobile, les entrées secondaires apparaissent dans la feuille « More ». |
Lecteur audio
| Layer / File(s) | Summary |
|---|---|
État du lecteur et ordre de lecture webapp/src/player/context.ts, webapp/src/player/order.ts, webapp/src/player/volume.ts, webapp/src/player/player.tsx |
Les contextes exposent l’état et la progression. Les fonctions d’ordre gèrent le mélange, la répétition et le suivi des entrées de la file. La lecture du volume enregistré accepte les valeurs finies comprises entre 0 et 1. |
Gestion des éléments audio webapp/src/player/aside-playback.ts, webapp/src/player/queue-element.ts, webapp/src/player/replay-gain-graph.ts, webapp/src/player/player.tsx |
Des hooks distincts gèrent la file, la lecture radio et podcast, les signets d’épisodes et ReplayGain. player.tsx appelle ces hooks à la place des implémentations locales précédentes. |
Commandes système et barres de lecture webapp/src/player/system-controls.ts, webapp/src/player/bar.tsx, webapp/src/player/player.tsx |
Les commandes Media Session et les raccourcis clavier ciblent la source affichée. La barre présente les commandes de la file ou de l’aside, selon l’état du lecteur. |
Priority:
Estimated code review effort: 4 (Complex) | ~60 minutes
Change: Refactor
Sequence Diagram(s)
sequenceDiagram
actor Utilisateur
participant Navigation
participant prepareTab
participant Routeur
Utilisateur->>Navigation: clic sur un lien
Navigation->>prepareTab: préparer les données de destination
prepareTab-->>Navigation: résultat ou échec du préchargement
Navigation->>Routeur: naviguer après préparation ou délai maximal
sequenceDiagram
actor Utilisateur
participant useAsidePlayback
participant AudioAside
participant AudioFile
participant PlayerBar
Utilisateur->>useAsidePlayback: demander la lecture d’un épisode
useAsidePlayback->>AudioAside: charger le flux et la position de reprise
AudioAside-->>useAsidePlayback: événement de lecture
useAsidePlayback->>AudioFile: mettre en pause la file
useAsidePlayback->>PlayerBar: fournir l’état de l’aside
Suggested labels: scope: web, size: xl
Merge Risk: 
Minimal · up to 9d7f7
-
This is a structural refactor of the web client's routing and player code that is meant to leave behavior unchanged. I found no concrete defect introduced by the change. Merge once the Playwright suite passes in CI.
Security architecture risk: 
Minimal · up to 9d7f7
-
The split preserves existing route protections, public access, playback ownership and cleanup behavior. No material security risk introduced or worsened by this PR was identified.
Retained concerns
No architecture-level concerns identified.Security review details
-
Security Blast Radius
- inferred — The reviewed extraction preserves the existing browser-session and playback authority scope. High-fanout player consumers continue through the same provider and compatible exports, and protected listen destinations retain their session-gated parentage.
Trust Boundaries and Controls
- observed — Login, token-based sharing and offline access remain direct root-route children outside the authenticated group, as at the merge base. These public exceptions are not newly introduced exposure.
Resilience and Maintainability Implications
- observed — Existing attempt-token and cancellation checks continue to prevent superseded stream requests from changing active playback. Bookmark writes remain serialized, with completion deletion and interruption persistence preserved. These controls retain failure containment across replacement, stopping and unmount.
-
Pre-merge checks: 
5
-
Full details: Title check
-
Explanation
Le titre décrit bien le changement principal : découpage de main.tsx en app/ et de player.tsx en modules frères, un refactoring sans changement de comportement. Il est précis et correspond au résumé des fichiers modifiés.
Full details: Description check
-
Explanation
La description suit le modèle : résumé, tableaux de changements, plan de test (commandes listées avec résultats locaux, Playwright laissé à la CI) et notes. Les cases de la section Test plan ne sont pas cochées, et la ligne de confirmation DCO/AGPL du modèle est absente. Le contenu est substantiel et couvre les points essentiels.
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 33 functions across 20 files. (1 skipped: 1 unsupported.)
-
Finishing Touches
-
📝 Generate docstrings
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Warning
Some tools did not complete. Review the errors below.
🔧 Biome (2.5.15)
-
webapp/src/app/more-sheet.tsx
-
Biome could not lint this file: nested root configuration. Check the repository's Biome configuration and plugins.
webapp/src/app/navigation-entries.ts
-
Biome could not lint this file: nested root configuration. Check the repository's Biome configuration and plugins.
webapp/src/app/navigation.tsx
-
Biome could not lint this file: nested root configuration. Check the repository's Biome configuration and plugins.
- 17 others
-
Usage-based review receipt
- Mode: Continue automatically
- Reviewed files: 21
- Charged: $5.25
- View usage details
Note
This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.
Comment @coderabbitai help to get the list of available commands.
Phase A of the webapp restructuring, for the two root-level giants:
main.tsx(1,267 lines) andplayer/player.tsx(1,759 lines). Moves only; no import specifier changes —"./main"is the entry and"../player/player"still answers every name it exported.Old → new
src/main.tsx(1,267) → bootstrap +src/app/main.tsxcreateRouter, thedeclare module … Register/StaticDataRouteOptionblock, the query client, the service worker and the renderapp/navigation-entries.tsNAVIGATION_GROUPS,GROUP_LABELS,navigation,NavigationTargetapp/navigation.tsxTAB_WAIT_MS,prepareTab,Brand,permitted,Navigationapp/more-sheet.tsxMoreSheetapp/shell.tsxSplashGate,ScopedOutlet,Shell,RootFrameapp/routes/root.tsxrootRoute,loginRoute,shareRoute,offlineRoute,authedRoute,authorizeRouteapp/routes/library.tsxapp/routes/listen.tsxapp/routes/settings.tsxapp/routes/maintenance.tsxapp/route-tree.tsrouteTree, with the children in exactly the old orderRoute paths, ids,
beforeLoadguards,validateSearch,staticDataand the order in the tree are untouched; the only edit to a route definition is theexportin front of it. Type registration still works: a scratch<Link to="/no-such-route" />failstscwith the full list of registered paths.src/player/player.tsx(1,759) →player.tsxas provider and face + siblingsplayer.tsxPlayerProvider, and explicit re-exports of every name the file used to exportvolume.tsVOLUME_KEY(now exported for the provider),readStoredVolumeorder.tsRepeatMode,shuffledOrder,advance,continuationOf,followQueue,orderForQueue,retreatcontext.tsPlayerState,PlayerProgress, the three contexts,usePlayer,usePlayerProgress,useAsideProgressreplay-gain-graph.tsuseReplayGainGraph: the provider's lines fromuseReplayGainPreference()toprepareGraph(graph refs, the unmount teardown,wakeGraph,prepareGraph)aside-playback.tsuseAsidePlayback: the whole "aside" section (station / episode element, bookmarks,playLive,playEpisode,toggleAside,seekAside,stopAside)queue-element.tsuseQueueElement: the queue element's event effect, the ticketed source effect, the preload and the half-way scrobblesystem-controls.tsuseSystemControls: the Media Session handlers and metadata effects and the keyboard effectbar.tsxScrubber,QueueScrubber,AsideScrubber,LevelControls,AsideBar,PlayerBarEach extracted hook is a contiguous run of the provider's body, called from the provider exactly where that run used to be, so React sees the same hooks in the same order. Tests (
order.test.ts,player.test.ts,volume.test.ts) are unchanged and still import from./player.CLAUDE.md's layout sentence now describesmain.tsxas the bootstrap and namesapp/.Proofs
bunx playwright test --list, listing only): 508 tests in 5 files before and after.use…(call in the oldPlayerProvider, and in the new one with each extracted hook expanded in place): 88 calls before, 88 after, identical order.exportprefixes ignored):main.tsx: 1,089 old lines, 0 missing. The only new lines are the one-line headers.player.tsx: 1,642 old lines; the 10 missing lines are all dependency arrays, listed below. Everything else in the new files is the wrappers (hook signatures, parameter types, the destructured returns and call sites) and the headers.The one edit inside moved code: dependency arrays
Biome's
useExhaustiveDependenciestreats auseRefresult or auseStatesetter as stable only when it is declared in the same function. Once a run of the provider becomes a hook that receivesaudio,positionRef,setPlaying… as arguments, the rule can no longer see that they are stable, and it raised 50 new warnings. The fix applied: the ref objects and setters were added to the dependency arrays that use them — neverx.current. Each one is auseRefor auseStatesetter in the provider (orside, auseRefinsideuseAsidePlayback). Their identity never changes, so no effect or callback runs more often than before. Affected arrays (11):replay-gain-graph.ts: the unmount effect[]→[audio, preloader];prepareGraph+ audioaside-playback.ts:pauseQueue[]→[audio]; the element effect+ audioqueue-element.ts: the event effect, the source effect, the preload (+ preloader) and the scrobble (+ submitted)system-controls.ts: the handlers effect+ audio, side; the keyboard effect+ asideRef, asidePositionRef, positionRefplayer.tsx: the volume effect+ sideThe other way out was a
biome-ignoreper hook. It was not chosen because it would turn the rule off for those hooks from now on, where the extra entries keep the rule checking them.Checks run (in
webapp/)bunx biome check .: the same 10 warningsmainhas, all CSSnoDescendingSpecificity; none new.bun run typecheck: clean.bun run test: 323 passed.bun run build: passes.--listwas run locally.Noticed, not changed
PlayerProviderkeeps aqueueLengthref that is written on every render (queueLength.current = queue.length) and never read. Its comment says the ended handler reads it, butonEndnow goes throughorderRef/indexRef.continuationOf's own doc says it compares by entry identity and that the prefix test was dropped.onEnd's "stop on the last track rather than stepping past it" explanation appears twice: once above the handler and again inside it.Summary by CodeRabbit