fix(android): split MinstrelNavGraph into NavGraphBuilder extensions
detekt LongMethod (97/60 lines). Body had no actual logic — just 13
sequential composable<T>() route declarations. Split by route category
(matches the existing comment headers):
- inShellTopLevel(navController, expandPlayer) — 8 in-shell tabs
- inShellDetail(expandPlayer) — 6 push-on-top detail screens
- outsideShell() — NowPlaying (with slide-up transitions), Queue,
ServerUrl, Login
`MinstrelNavGraph` itself is now 15 lines (NavHost shell that delegates
to the three groups), and each helper sits well under the 60-line cap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
@@ -28,123 +29,115 @@ fun MinstrelNavGraph(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val expandPlayer = { navController.navigate(NowPlaying) }
|
||||
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = Library,
|
||||
modifier = modifier.fillMaxSize(),
|
||||
) {
|
||||
// ── In-shell top-level destinations ───────────────────────────
|
||||
inShellTopLevel(navController, expandPlayer)
|
||||
inShellDetail(expandPlayer)
|
||||
outsideShell()
|
||||
}
|
||||
}
|
||||
|
||||
composable<Home> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Home", "Lands in the next design-drift sub-task.")
|
||||
}
|
||||
}
|
||||
|
||||
composable<Library> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
LibraryScreen(navController = navController)
|
||||
}
|
||||
}
|
||||
|
||||
composable<Search> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Search", "Lands in a later phase.")
|
||||
}
|
||||
}
|
||||
|
||||
composable<Discover> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Discover", "Lands in Phase 10 (Lidarr requests).")
|
||||
}
|
||||
}
|
||||
|
||||
composable<Playlists> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Playlists", "Lands in Phase 7.")
|
||||
}
|
||||
}
|
||||
|
||||
composable<Settings> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Settings", "Lands in Phase 11.")
|
||||
}
|
||||
}
|
||||
|
||||
composable<Admin> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Admin", "Admin landing — lands in a later phase.")
|
||||
}
|
||||
}
|
||||
|
||||
composable<Requests> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Requests", "Your Lidarr requests — Phase 10.")
|
||||
}
|
||||
}
|
||||
|
||||
// ── In-shell detail screens (push-on-top) ─────────────────────
|
||||
|
||||
composable<AlbumDetail> { backStackEntry ->
|
||||
val route: AlbumDetail = backStackEntry.toRoute()
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Album", "Album detail for ${route.id} — later 5.x slice.")
|
||||
}
|
||||
}
|
||||
|
||||
composable<ArtistDetail> { backStackEntry ->
|
||||
val route: ArtistDetail = backStackEntry.toRoute()
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Artist", "Artist detail for ${route.id} — later 5.x slice.")
|
||||
}
|
||||
}
|
||||
|
||||
composable<PlaylistDetail> { backStackEntry ->
|
||||
val route: PlaylistDetail = backStackEntry.toRoute()
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Playlist", "Playlist detail for ${route.id} — Phase 7.")
|
||||
}
|
||||
}
|
||||
|
||||
composable<AdminRequests> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Admin · Requests", "Lands with admin slice.")
|
||||
}
|
||||
}
|
||||
composable<AdminQuarantine> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Admin · Quarantine", "Lands with admin slice.")
|
||||
}
|
||||
}
|
||||
composable<AdminUsers> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Admin · Users", "Lands with admin slice.")
|
||||
}
|
||||
}
|
||||
|
||||
// ── Outside-shell full-screen routes ──────────────────────────
|
||||
|
||||
composable<NowPlaying>(
|
||||
// Slide up from the bottom on enter; back down on dismiss.
|
||||
// Mirrors the Flutter CustomTransitionPage (280ms easeOutCubic).
|
||||
enterTransition = { slideInVertically(initialOffsetY = { it }) },
|
||||
exitTransition = { slideOutVertically(targetOffsetY = { it }) },
|
||||
popEnterTransition = { slideInVertically(initialOffsetY = { it }) },
|
||||
popExitTransition = { slideOutVertically(targetOffsetY = { it }) },
|
||||
) {
|
||||
NowPlayingScreen()
|
||||
}
|
||||
|
||||
composable<Queue> { ComingSoon("Queue", "Lands in a later 6.x slice.") }
|
||||
|
||||
composable<ServerUrl> {
|
||||
ComingSoon("Connect to your Minstrel", "Server-URL entry — Phase 11.")
|
||||
}
|
||||
composable<Login> {
|
||||
ComingSoon("Sign in", "Login flow — Phase 11.")
|
||||
private fun NavGraphBuilder.inShellTopLevel(
|
||||
navController: NavHostController,
|
||||
expandPlayer: () -> Unit,
|
||||
) {
|
||||
composable<Home> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Home", "Lands in the next design-drift sub-task.")
|
||||
}
|
||||
}
|
||||
composable<Library> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
LibraryScreen(navController = navController)
|
||||
}
|
||||
}
|
||||
composable<Search> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Search", "Lands in a later phase.")
|
||||
}
|
||||
}
|
||||
composable<Discover> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Discover", "Lands in Phase 10 (Lidarr requests).")
|
||||
}
|
||||
}
|
||||
composable<Playlists> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Playlists", "Lands in Phase 7.")
|
||||
}
|
||||
}
|
||||
composable<Settings> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Settings", "Lands in Phase 11.")
|
||||
}
|
||||
}
|
||||
composable<Admin> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Admin", "Admin landing — lands in a later phase.")
|
||||
}
|
||||
}
|
||||
composable<Requests> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Requests", "Your Lidarr requests — Phase 10.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun NavGraphBuilder.inShellDetail(expandPlayer: () -> Unit) {
|
||||
composable<AlbumDetail> { backStackEntry ->
|
||||
val route: AlbumDetail = backStackEntry.toRoute()
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Album", "Album detail for ${route.id} — later 5.x slice.")
|
||||
}
|
||||
}
|
||||
composable<ArtistDetail> { backStackEntry ->
|
||||
val route: ArtistDetail = backStackEntry.toRoute()
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Artist", "Artist detail for ${route.id} — later 5.x slice.")
|
||||
}
|
||||
}
|
||||
composable<PlaylistDetail> { backStackEntry ->
|
||||
val route: PlaylistDetail = backStackEntry.toRoute()
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Playlist", "Playlist detail for ${route.id} — Phase 7.")
|
||||
}
|
||||
}
|
||||
composable<AdminRequests> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Admin · Requests", "Lands with admin slice.")
|
||||
}
|
||||
}
|
||||
composable<AdminQuarantine> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Admin · Quarantine", "Lands with admin slice.")
|
||||
}
|
||||
}
|
||||
composable<AdminUsers> {
|
||||
ShellScaffold(onExpandPlayer = expandPlayer) {
|
||||
ComingSoon("Admin · Users", "Lands with admin slice.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun NavGraphBuilder.outsideShell() {
|
||||
composable<NowPlaying>(
|
||||
// Slide up from the bottom on enter; back down on dismiss.
|
||||
// Mirrors the Flutter CustomTransitionPage (280ms easeOutCubic).
|
||||
enterTransition = { slideInVertically(initialOffsetY = { it }) },
|
||||
exitTransition = { slideOutVertically(targetOffsetY = { it }) },
|
||||
popEnterTransition = { slideInVertically(initialOffsetY = { it }) },
|
||||
popExitTransition = { slideOutVertically(targetOffsetY = { it }) },
|
||||
) {
|
||||
NowPlayingScreen()
|
||||
}
|
||||
composable<Queue> { ComingSoon("Queue", "Lands in a later 6.x slice.") }
|
||||
composable<ServerUrl> {
|
||||
ComingSoon("Connect to your Minstrel", "Server-URL entry — Phase 11.")
|
||||
}
|
||||
composable<Login> { ComingSoon("Sign in", "Login flow — Phase 11.") }
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
Reference in New Issue
Block a user