manager: support search module list (#2331)

This commit is contained in:
5ec1cff 2024-12-31 16:30:58 +08:00 committed by GitHub
parent 02ad724406
commit 0a617959f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 17 deletions

View File

@ -56,7 +56,6 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberTopAppBarState
@ -67,7 +66,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -95,6 +93,7 @@ import kotlinx.coroutines.withContext
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.component.ConfirmResult
import me.weishu.kernelsu.ui.component.SearchAppBar
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
import me.weishu.kernelsu.ui.component.rememberLoadingDialog
import me.weishu.kernelsu.ui.util.DownloadListener
@ -139,8 +138,12 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
Scaffold(
topBar = {
TopAppBar(
actions = {
SearchAppBar(
title = { Text(stringResource(R.string.module)) },
searchText = viewModel.search,
onSearchTextChange = { viewModel.search = it },
onClearClick = { viewModel.search = "" },
dropdownContent = {
var showDropdown by remember { mutableStateOf(false) }
IconButton(
@ -192,8 +195,6 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
}
},
scrollBehavior = scrollBehavior,
title = { Text(stringResource(R.string.module)) },
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
)
},
floatingActionButton = {
@ -458,7 +459,6 @@ private fun ModuleList(
else -> {
items(viewModel.moduleList) { module ->
var isChecked by rememberSaveable(module) { mutableStateOf(module.enabled) }
val scope = rememberCoroutineScope()
val updatedModule by produceState(initialValue = Triple("", "", "")) {
scope.launch(Dispatchers.IO) {
@ -469,7 +469,6 @@ private fun ModuleList(
ModuleItem(
navigator = navigator,
module = module,
isChecked = isChecked,
updateUrl = updatedModule.first,
onUninstall = {
scope.launch { onModuleUninstall(module) }
@ -478,11 +477,10 @@ private fun ModuleList(
scope.launch {
val success = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
toggleModule(module.id, !isChecked)
toggleModule(module.id, !module.enabled)
}
}
if (success) {
isChecked = it
viewModel.fetchModuleList()
val result = snackBarHost.showSnackbar(
@ -494,7 +492,7 @@ private fun ModuleList(
reboot()
}
} else {
val message = if (isChecked) failedDisable else failedEnable
val message = if (module.enabled) failedDisable else failedEnable
snackBarHost.showSnackbar(message.format(module.name))
}
}
@ -530,7 +528,6 @@ private fun ModuleList(
fun ModuleItem(
navigator: DestinationsNavigator,
module: ModuleViewModel.ModuleInfo,
isChecked: Boolean,
updateUrl: String,
onUninstall: (ModuleViewModel.ModuleInfo) -> Unit,
onCheckChanged: (Boolean) -> Unit,
@ -550,7 +547,7 @@ fun ModuleItem(
.run {
if (module.hasWebUi) {
toggleable(
value = isChecked,
value = module.enabled,
interactionSource = interactionSource,
role = Role.Button,
indication = indication,
@ -606,7 +603,7 @@ fun ModuleItem(
) {
Switch(
enabled = !module.update,
checked = isChecked,
checked = module.enabled,
onCheckedChange = onCheckChanged,
interactionSource = if (!module.hasWebUi) interactionSource else null
)
@ -756,5 +753,5 @@ fun ModuleItemPreview() {
hasWebUi = false,
hasActionScript = false
)
ModuleItem(EmptyDestinationsNavigator, module, true, "", {}, {}, {}, {})
ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {})
}

View File

@ -10,10 +10,13 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import me.weishu.kernelsu.ui.util.HanziToPinyin
import me.weishu.kernelsu.ui.util.listModules
import me.weishu.kernelsu.ui.util.overlayFsAvailable
import org.json.JSONArray
import org.json.JSONObject
import java.text.Collator
import java.util.Locale
class ModuleViewModel : ViewModel() {
@ -46,6 +49,7 @@ class ModuleViewModel : ViewModel() {
var isRefreshing by mutableStateOf(false)
private set
var search by mutableStateOf("")
var isOverlayAvailable by mutableStateOf(overlayFsAvailable())
private set
@ -57,8 +61,11 @@ class ModuleViewModel : ViewModel() {
compareBy<ModuleInfo>(
{ if (sortEnabledFirst) !it.enabled else 0 },
{ if (sortActionFirst) !it.hasWebUi && !it.hasActionScript else 0 },
{ it.id })
modules.sortedWith(comparator).also {
).thenBy(Collator.getInstance(Locale.getDefault()), ModuleInfo::id)
modules.filter {
it.id.contains(search, true) || it.name.contains(search, true) || HanziToPinyin.getInstance()
.toPinyinString(it.name).contains(search, true)
}.sortedWith(comparator).also {
isRefreshing = false
}
}