manager: fully polish and refactor module card ui

This commit is contained in:
Rifat Azad
2025-06-12 23:40:14 +06:00
parent d218346613
commit ad290a51a0

View File

@@ -9,6 +9,11 @@ import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@@ -443,6 +448,8 @@ private fun ModuleList(
val loadingDialog = rememberLoadingDialog() val loadingDialog = rememberLoadingDialog()
val confirmDialog = rememberConfirmDialog() val confirmDialog = rememberConfirmDialog()
var expandedModuleId by rememberSaveable { mutableStateOf<String?>(null) }
suspend fun onModuleUpdate( suspend fun onModuleUpdate(
module: ModuleViewModel.ModuleInfo, module: ModuleViewModel.ModuleInfo,
changelogUrl: String, changelogUrl: String,
@@ -665,6 +672,10 @@ private fun ModuleList(
}, },
onClick = { onClick = {
onClickModule(it.dirId, it.name, it.hasWebUi) onClickModule(it.dirId, it.name, it.hasWebUi)
},
expanded = expandedModuleId == module.id,
onExpandToggle = {
expandedModuleId = if (expandedModuleId == module.id) null else module.id
} }
) )
@@ -690,6 +701,8 @@ fun ModuleItem(
onCheckChanged: (Boolean) -> Unit, onCheckChanged: (Boolean) -> Unit,
onUpdate: (ModuleViewModel.ModuleInfo) -> Unit, onUpdate: (ModuleViewModel.ModuleInfo) -> Unit,
onClick: (ModuleViewModel.ModuleInfo) -> Unit, onClick: (ModuleViewModel.ModuleInfo) -> Unit,
expanded: Boolean,
onExpandToggle: () -> Unit,
) { ) {
val viewModel = viewModel<ModuleViewModel>() val viewModel = viewModel<ModuleViewModel>()
@@ -698,12 +711,7 @@ fun ModuleItem(
.fillMaxWidth() .fillMaxWidth()
.clip(MaterialTheme.shapes.medium) .clip(MaterialTheme.shapes.medium)
.clickable( .clickable(
enabled = (module.enabled && !module.remove && (module.hasWebUi)), onClick = onExpandToggle
onClick = {
if (module.hasWebUi) {
onClick(module)
}
}
) )
) { ) {
Box( Box(
@@ -866,6 +874,15 @@ fun ModuleItem(
) )
) )
} }
if (module.hasActionScript) {
LabelItem(
text = stringResource(R.string.action),
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
)
)
}
} }
} }
@@ -945,76 +962,142 @@ fun ModuleItem(
maxLines = 4 maxLines = 4
) )
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(2.dp))
Row( if (expanded) {
horizontalArrangement = Arrangement.SpaceBetween, Spacer(modifier = Modifier.height(10.dp))
verticalAlignment = Alignment.CenterVertically }
AnimatedVisibility(
visible = expanded,
enter = fadeIn() + expandVertically(),
exit = shrinkVertically() + fadeOut()
) { ) {
if (module.hasActionScript) { Row(
FilledTonalButton( horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.defaultMinSize(52.dp, 32.dp), verticalAlignment = Alignment.CenterVertically
enabled = !module.remove && module.enabled, ) {
onClick = { if (module.hasActionScript) {
navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId)) FilledTonalButton(
viewModel.markNeedRefresh() modifier = Modifier.defaultMinSize(52.dp, 32.dp),
}, enabled = !module.remove && module.enabled,
contentPadding = ButtonDefaults.TextButtonContentPadding onClick = {
) { navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId))
Icon( viewModel.markNeedRefresh()
modifier = Modifier.size(20.dp), },
imageVector = Icons.Outlined.Terminal, contentPadding = ButtonDefaults.TextButtonContentPadding
contentDescription = null ) {
) Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Terminal,
contentDescription = null
)
if (!module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
text = stringResource(R.string.action),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize
)
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
} }
Spacer(modifier = Modifier.weight(0.1f, true)) if (module.hasWebUi) {
} FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
Spacer(modifier = Modifier.weight(1f, true)) enabled = !module.remove && module.enabled,
onClick = { onClick(module) },
if (updateUrl.isNotEmpty()) { interactionSource = interactionSource,
Button( contentPadding = ButtonDefaults.TextButtonContentPadding
modifier = Modifier.defaultMinSize(52.dp, 32.dp), ) {
enabled = !module.remove, Icon(
onClick = { onUpdate(module) }, modifier = Modifier.size(20.dp),
shape = ButtonDefaults.textShape, imageVector = Icons.AutoMirrored.Outlined.Wysiwyg,
contentPadding = ButtonDefaults.TextButtonContentPadding contentDescription = null
) { )
Icon( if (!module.hasActionScript && updateUrl.isEmpty()) {
modifier = Modifier.size(20.dp), Text(
imageVector = Icons.Outlined.Download, modifier = Modifier.padding(start = 7.dp),
contentDescription = null fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
) fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.open)
)
}
}
} }
Spacer(modifier = Modifier.weight(0.1f, true)) Spacer(modifier = Modifier.weight(1f, true))
}
if (module.remove) { if (updateUrl.isNotEmpty()) {
FilledTonalButton( Button(
modifier = Modifier.defaultMinSize(52.dp, 32.dp), modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = { onRestore(module) }, enabled = !module.remove,
contentPadding = ButtonDefaults.TextButtonContentPadding onClick = { onUpdate(module) },
) { shape = ButtonDefaults.textShape,
Icon( contentPadding = ButtonDefaults.TextButtonContentPadding
modifier = Modifier.size(20.dp), ) {
imageVector = Icons.Outlined.Restore, Icon(
contentDescription = null modifier = Modifier.size(20.dp),
) imageVector = Icons.Outlined.Download,
contentDescription = null
)
if (!module.hasActionScript || !module.hasWebUi) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.module_update)
)
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
} }
} else {
FilledTonalButton( if (module.remove) {
modifier = Modifier.defaultMinSize(52.dp, 32.dp), FilledTonalButton(
enabled = true, modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = { onUninstall(module) }, onClick = { onRestore(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding contentPadding = ButtonDefaults.TextButtonContentPadding
) { ) {
Icon( Icon(
modifier = Modifier.size(20.dp), modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Delete, imageVector = Icons.Outlined.Restore,
contentDescription = null contentDescription = null
) )
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.restore)
)
}
}
} else {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = true,
onClick = { onUninstall(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.uninstall)
)
}
}
} }
} }
} }
@@ -1056,5 +1139,5 @@ fun ModuleItemPreview() {
size = 12345678L, size = 12345678L,
banner = "" banner = ""
) )
ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {}, {}) ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {}, {}, false, {})
} }