manager: support search module list (#2331)
This commit is contained in:
@@ -56,7 +56,6 @@ import androidx.compose.material3.SnackbarHostState
|
|||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
@@ -67,7 +66,6 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -95,6 +93,7 @@ import kotlinx.coroutines.withContext
|
|||||||
import me.weishu.kernelsu.Natives
|
import me.weishu.kernelsu.Natives
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
import me.weishu.kernelsu.ui.component.ConfirmResult
|
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.rememberConfirmDialog
|
||||||
import me.weishu.kernelsu.ui.component.rememberLoadingDialog
|
import me.weishu.kernelsu.ui.component.rememberLoadingDialog
|
||||||
import me.weishu.kernelsu.ui.util.DownloadListener
|
import me.weishu.kernelsu.ui.util.DownloadListener
|
||||||
@@ -139,8 +138,12 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
|||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
SearchAppBar(
|
||||||
actions = {
|
title = { Text(stringResource(R.string.module)) },
|
||||||
|
searchText = viewModel.search,
|
||||||
|
onSearchTextChange = { viewModel.search = it },
|
||||||
|
onClearClick = { viewModel.search = "" },
|
||||||
|
dropdownContent = {
|
||||||
var showDropdown by remember { mutableStateOf(false) }
|
var showDropdown by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
@@ -192,8 +195,6 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
title = { Text(stringResource(R.string.module)) },
|
|
||||||
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
@@ -458,7 +459,6 @@ private fun ModuleList(
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
items(viewModel.moduleList) { module ->
|
items(viewModel.moduleList) { module ->
|
||||||
var isChecked by rememberSaveable(module) { mutableStateOf(module.enabled) }
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val updatedModule by produceState(initialValue = Triple("", "", "")) {
|
val updatedModule by produceState(initialValue = Triple("", "", "")) {
|
||||||
scope.launch(Dispatchers.IO) {
|
scope.launch(Dispatchers.IO) {
|
||||||
@@ -469,7 +469,6 @@ private fun ModuleList(
|
|||||||
ModuleItem(
|
ModuleItem(
|
||||||
navigator = navigator,
|
navigator = navigator,
|
||||||
module = module,
|
module = module,
|
||||||
isChecked = isChecked,
|
|
||||||
updateUrl = updatedModule.first,
|
updateUrl = updatedModule.first,
|
||||||
onUninstall = {
|
onUninstall = {
|
||||||
scope.launch { onModuleUninstall(module) }
|
scope.launch { onModuleUninstall(module) }
|
||||||
@@ -478,11 +477,10 @@ private fun ModuleList(
|
|||||||
scope.launch {
|
scope.launch {
|
||||||
val success = loadingDialog.withLoading {
|
val success = loadingDialog.withLoading {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
toggleModule(module.id, !isChecked)
|
toggleModule(module.id, !module.enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
isChecked = it
|
|
||||||
viewModel.fetchModuleList()
|
viewModel.fetchModuleList()
|
||||||
|
|
||||||
val result = snackBarHost.showSnackbar(
|
val result = snackBarHost.showSnackbar(
|
||||||
@@ -494,7 +492,7 @@ private fun ModuleList(
|
|||||||
reboot()
|
reboot()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val message = if (isChecked) failedDisable else failedEnable
|
val message = if (module.enabled) failedDisable else failedEnable
|
||||||
snackBarHost.showSnackbar(message.format(module.name))
|
snackBarHost.showSnackbar(message.format(module.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -530,7 +528,6 @@ private fun ModuleList(
|
|||||||
fun ModuleItem(
|
fun ModuleItem(
|
||||||
navigator: DestinationsNavigator,
|
navigator: DestinationsNavigator,
|
||||||
module: ModuleViewModel.ModuleInfo,
|
module: ModuleViewModel.ModuleInfo,
|
||||||
isChecked: Boolean,
|
|
||||||
updateUrl: String,
|
updateUrl: String,
|
||||||
onUninstall: (ModuleViewModel.ModuleInfo) -> Unit,
|
onUninstall: (ModuleViewModel.ModuleInfo) -> Unit,
|
||||||
onCheckChanged: (Boolean) -> Unit,
|
onCheckChanged: (Boolean) -> Unit,
|
||||||
@@ -550,7 +547,7 @@ fun ModuleItem(
|
|||||||
.run {
|
.run {
|
||||||
if (module.hasWebUi) {
|
if (module.hasWebUi) {
|
||||||
toggleable(
|
toggleable(
|
||||||
value = isChecked,
|
value = module.enabled,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
role = Role.Button,
|
role = Role.Button,
|
||||||
indication = indication,
|
indication = indication,
|
||||||
@@ -606,7 +603,7 @@ fun ModuleItem(
|
|||||||
) {
|
) {
|
||||||
Switch(
|
Switch(
|
||||||
enabled = !module.update,
|
enabled = !module.update,
|
||||||
checked = isChecked,
|
checked = module.enabled,
|
||||||
onCheckedChange = onCheckChanged,
|
onCheckedChange = onCheckChanged,
|
||||||
interactionSource = if (!module.hasWebUi) interactionSource else null
|
interactionSource = if (!module.hasWebUi) interactionSource else null
|
||||||
)
|
)
|
||||||
@@ -756,5 +753,5 @@ fun ModuleItemPreview() {
|
|||||||
hasWebUi = false,
|
hasWebUi = false,
|
||||||
hasActionScript = false
|
hasActionScript = false
|
||||||
)
|
)
|
||||||
ModuleItem(EmptyDestinationsNavigator, module, true, "", {}, {}, {}, {})
|
ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import me.weishu.kernelsu.ui.util.HanziToPinyin
|
||||||
import me.weishu.kernelsu.ui.util.listModules
|
import me.weishu.kernelsu.ui.util.listModules
|
||||||
import me.weishu.kernelsu.ui.util.overlayFsAvailable
|
import me.weishu.kernelsu.ui.util.overlayFsAvailable
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import java.text.Collator
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class ModuleViewModel : ViewModel() {
|
class ModuleViewModel : ViewModel() {
|
||||||
|
|
||||||
@@ -46,6 +49,7 @@ class ModuleViewModel : ViewModel() {
|
|||||||
|
|
||||||
var isRefreshing by mutableStateOf(false)
|
var isRefreshing by mutableStateOf(false)
|
||||||
private set
|
private set
|
||||||
|
var search by mutableStateOf("")
|
||||||
|
|
||||||
var isOverlayAvailable by mutableStateOf(overlayFsAvailable())
|
var isOverlayAvailable by mutableStateOf(overlayFsAvailable())
|
||||||
private set
|
private set
|
||||||
@@ -57,8 +61,11 @@ class ModuleViewModel : ViewModel() {
|
|||||||
compareBy<ModuleInfo>(
|
compareBy<ModuleInfo>(
|
||||||
{ if (sortEnabledFirst) !it.enabled else 0 },
|
{ if (sortEnabledFirst) !it.enabled else 0 },
|
||||||
{ if (sortActionFirst) !it.hasWebUi && !it.hasActionScript else 0 },
|
{ if (sortActionFirst) !it.hasWebUi && !it.hasActionScript else 0 },
|
||||||
{ it.id })
|
).thenBy(Collator.getInstance(Locale.getDefault()), ModuleInfo::id)
|
||||||
modules.sortedWith(comparator).also {
|
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
|
isRefreshing = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user