fix(android) detekt: shrink AdminUsersScreen, real regenerate fix, suppress TooManyFunctions
The previous push tried to fix detekt but missed two things:
* regenerate() in PlaylistDetailViewModel had its 3 returns "fixed"
in name only — the if(!refreshable)return was still there. Now
folded into the variant Elvis chain with takeIf{refreshable}.
* The helper-composable extractions I just shipped pushed three
screens over detekt's 11-function-per-file cap. Compose screens
naturally produce many small private composables; per the
established pattern, suppress TooManyFunctions at the file level
with a one-line rationale rather than fight the cap.
* AdminUsersScreen main body was 94 lines (cap 60) because I
rebuilt the Scaffold inline with the new Invites section. Extracted
AdminUsersScaffold helper so the main function only owns state
hoisting and dialog dispatch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("TooManyFunctions") // Compose screen + private helper composables and dialogs
|
||||
|
||||
package com.fabledsword.minstrel.admin.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -70,64 +72,21 @@ fun AdminUsersScreen(
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("Admin · Users") },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = { navController.popBackStack() }) {
|
||||
Icon(Lucide.ArrowLeft, contentDescription = "Back")
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
MainAppBarActions(
|
||||
navController = navController,
|
||||
currentRouteName = AdminUsers::class.qualifiedName,
|
||||
)
|
||||
},
|
||||
)
|
||||
AdminUsersScaffold(
|
||||
navController = navController,
|
||||
usersState = state,
|
||||
invitesState = invitesState,
|
||||
onRefresh = {
|
||||
viewModel.refresh().join()
|
||||
invitesViewModel.refresh()
|
||||
},
|
||||
) { inner ->
|
||||
PullToRefreshScaffold(
|
||||
onRefresh = {
|
||||
viewModel.refresh().join()
|
||||
invitesViewModel.refresh()
|
||||
},
|
||||
modifier = Modifier.fillMaxSize().padding(inner),
|
||||
) {
|
||||
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||
item { SectionHeader("Users") }
|
||||
usersSection(
|
||||
state = state,
|
||||
onSetAdmin = viewModel::setAdmin,
|
||||
onSetAutoApprove = viewModel::setAutoApprove,
|
||||
onAskResetPassword = { resetPasswordFor = it },
|
||||
onAskDelete = { deleteCandidate = it },
|
||||
)
|
||||
item { HorizontalDivider() }
|
||||
item {
|
||||
SectionHeader(
|
||||
label = "Invites",
|
||||
trailing = {
|
||||
TextButton(onClick = { showGenerateInvite = true }) {
|
||||
Icon(
|
||||
Lucide.Plus,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
)
|
||||
Text("Generate")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
invitesSection(
|
||||
state = invitesState,
|
||||
onRevoke = invitesViewModel::revoke,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
onSetAdmin = viewModel::setAdmin,
|
||||
onSetAutoApprove = viewModel::setAutoApprove,
|
||||
onAskResetPassword = { resetPasswordFor = it },
|
||||
onAskDelete = { deleteCandidate = it },
|
||||
onAskGenerateInvite = { showGenerateInvite = true },
|
||||
onRevokeInvite = invitesViewModel::revoke,
|
||||
)
|
||||
|
||||
PendingDialogs(
|
||||
resetPasswordFor = resetPasswordFor,
|
||||
@@ -155,6 +114,74 @@ fun AdminUsersScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun AdminUsersScaffold(
|
||||
navController: NavHostController,
|
||||
usersState: AdminUsersUiState,
|
||||
invitesState: AdminInvitesUiState,
|
||||
onRefresh: suspend () -> Unit,
|
||||
onSetAdmin: (String, Boolean) -> Unit,
|
||||
onSetAutoApprove: (String, Boolean) -> Unit,
|
||||
onAskResetPassword: (AdminUserRef) -> Unit,
|
||||
onAskDelete: (AdminUserRef) -> Unit,
|
||||
onAskGenerateInvite: () -> Unit,
|
||||
onRevokeInvite: (String) -> Unit,
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("Admin · Users") },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = { navController.popBackStack() }) {
|
||||
Icon(Lucide.ArrowLeft, contentDescription = "Back")
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
MainAppBarActions(
|
||||
navController = navController,
|
||||
currentRouteName = AdminUsers::class.qualifiedName,
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
) { inner ->
|
||||
PullToRefreshScaffold(
|
||||
onRefresh = onRefresh,
|
||||
modifier = Modifier.fillMaxSize().padding(inner),
|
||||
) {
|
||||
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||
item { SectionHeader("Users") }
|
||||
usersSection(
|
||||
state = usersState,
|
||||
onSetAdmin = onSetAdmin,
|
||||
onSetAutoApprove = onSetAutoApprove,
|
||||
onAskResetPassword = onAskResetPassword,
|
||||
onAskDelete = onAskDelete,
|
||||
)
|
||||
item { HorizontalDivider() }
|
||||
item {
|
||||
SectionHeader(
|
||||
label = "Invites",
|
||||
trailing = {
|
||||
TextButton(onClick = onAskGenerateInvite) {
|
||||
Icon(
|
||||
Lucide.Plus,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
)
|
||||
Text("Generate")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
invitesSection(state = invitesState, onRevoke = onRevokeInvite)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SectionHeader(label: String, trailing: (@Composable () -> Unit)? = null) {
|
||||
Row(
|
||||
|
||||
+4
-2
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("TooManyFunctions") // Compose screen + private helper composables
|
||||
|
||||
package com.fabledsword.minstrel.playlists.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
@@ -197,8 +199,8 @@ class PlaylistDetailViewModel @Inject constructor(
|
||||
fun regenerate() {
|
||||
val playlist = (internal.value as? PlaylistDetailUiState.Success)
|
||||
?.detail?.playlist ?: return
|
||||
val variant = playlist.systemVariant ?: return
|
||||
if (!playlist.refreshable) return
|
||||
val variant = playlist.systemVariant
|
||||
?.takeIf { playlist.refreshable } ?: return
|
||||
viewModelScope.launch {
|
||||
runCatching { repository.refreshSystemPlaylist(variant) }
|
||||
.onSuccess { newId ->
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("TooManyFunctions") // Compose screen + private helper composables
|
||||
|
||||
package com.fabledsword.minstrel.requests.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
|
||||
Reference in New Issue
Block a user