Skip to content

Commit

Permalink
manager: Add sort options on module's appbar (tiann#2308)
Browse files Browse the repository at this point in the history
module list will be sorted by options when these are enabled:

![83d5cd3d23b8f6c36b52e731f5e21a97](https://github.com/user-attachments/assets/eaadc1a3-21c6-4b73-a55f-206b6faa7d2d)
It will be very friendly and convenient  when manager has many modules.
  • Loading branch information
lamprose authored and backslashxx committed Jan 29, 2025
1 parent 6dd33a9 commit ddda6cb
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 34 deletions.
120 changes: 90 additions & 30 deletions manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,22 @@ import androidx.compose.foundation.selection.toggleable
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Wysiwyg
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.PlayArrow
import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarDuration
Expand Down Expand Up @@ -110,9 +115,13 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
val viewModel = viewModel<ModuleViewModel>()
val context = LocalContext.current
val snackBarHost = LocalSnackbarHost.current
val scope = rememberCoroutineScope()
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)

LaunchedEffect(Unit) {
if (viewModel.moduleList.isEmpty() || viewModel.isNeedRefresh) {
viewModel.sortEnabledFirst = prefs.getBoolean("module_sort_enabled_first", false)
viewModel.sortActionFirst = prefs.getBoolean("module_sort_action_first", false)
viewModel.fetchModuleList()
}
}
Expand All @@ -127,6 +136,57 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
Scaffold(
topBar = {
TopAppBar(
actions = {
var showDropdown by remember { mutableStateOf(false) }

IconButton(
onClick = { showDropdown = true },
) {
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = stringResource(id = R.string.settings)
)

DropdownMenu(expanded = showDropdown, onDismissRequest = {
showDropdown = false
}) {
DropdownMenuItem(text = {
Text(stringResource(R.string.module_sort_action_first))
}, trailingIcon = {
Checkbox(viewModel.sortActionFirst, null)
}, onClick = {
viewModel.sortActionFirst =
!viewModel.sortActionFirst
prefs.edit()
.putBoolean(
"module_sort_action_first",
viewModel.sortActionFirst
)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
})
DropdownMenuItem(text = {
Text(stringResource(R.string.module_sort_enabled_first))
}, trailingIcon = {
Checkbox(viewModel.sortEnabledFirst, null)
}, onClick = {
viewModel.sortEnabledFirst =
!viewModel.sortEnabledFirst
prefs.edit()
.putBoolean(
"module_sort_enabled_first",
viewModel.sortEnabledFirst
)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
})
}
}
},
scrollBehavior = scrollBehavior,
title = { Text(stringResource(R.string.module)) },
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
Expand Down Expand Up @@ -493,8 +553,8 @@ fun ModuleItem(
onValueChange = { onClick(module) }
)
} else {
this
}
this
}
}
.padding(22.dp, 18.dp, 22.dp, 12.dp)
) {
Expand Down Expand Up @@ -577,24 +637,24 @@ fun ModuleItem(
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = {
navigator.navigate(ExecuteModuleActionScreenDestination(module.id))
viewModel.markNeedRefresh()
navigator.navigate(ExecuteModuleActionScreenDestination(module.id))
viewModel.markNeedRefresh()
},
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.PlayArrow,
contentDescription = null
)
if (!module.hasWebUi && updateUrl.isEmpty()) {
if (!module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
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))
Expand All @@ -608,16 +668,16 @@ fun ModuleItem(
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
modifier = Modifier.size(20.dp),
imageVector = Icons.AutoMirrored.Outlined.Wysiwyg,
contentDescription = null
)
if (!module.hasActionScript && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.open)
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.open)
)
}
}
Expand All @@ -632,19 +692,19 @@ fun ModuleItem(
shape = ButtonDefaults.textShape,
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Download,
contentDescription = null
)
if (!module.hasActionScript || !module.hasWebUi) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Download,
contentDescription = null
)
if (!module.hasActionScript || !module.hasWebUi) {
Text(
modifier = Modifier.padding(start = 7.dp),
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))
Expand All @@ -656,19 +716,19 @@ fun ModuleItem(
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),
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)
)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ 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() {

Expand Down Expand Up @@ -52,8 +50,14 @@ class ModuleViewModel : ViewModel() {
var isOverlayAvailable by mutableStateOf(overlayFsAvailable())
private set

var sortEnabledFirst by mutableStateOf(false)
var sortActionFirst by mutableStateOf(false)
val moduleList by derivedStateOf {
val comparator = compareBy(Collator.getInstance(Locale.getDefault()), ModuleInfo::id)
val comparator =
compareBy<ModuleInfo>(
{ if (sortEnabledFirst) !it.enabled else 0 },
{ if (sortActionFirst) !it.hasWebUi && !it.hasActionScript else 0 },
{ it.id })
modules.sortedWith(comparator).also {
isRefreshing = false
}
Expand Down Expand Up @@ -159,4 +163,4 @@ class ModuleViewModel : ViewModel() {

return Triple(zipUrl, version, changelog)
}
}
}
2 changes: 2 additions & 0 deletions manager/app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
<string name="module_failed_to_disable">无法禁用模块: %s</string>
<string name="module_empty">没有安装模块</string>
<string name="module">模块</string>
<string name="module_sort_action_first">可执行优先</string>
<string name="module_sort_enabled_first">已启用优先</string>
<string name="uninstall">卸载</string>
<string name="module_install">安装</string>
<string name="install">安装</string>
Expand Down
2 changes: 2 additions & 0 deletions manager/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
<string name="module_failed_to_disable">Failed to disable module: %s</string>
<string name="module_empty">No module installed</string>
<string name="module">Module</string>
<string name="module_sort_action_first">Sort (Action First)</string>
<string name="module_sort_enabled_first">Sort (Enabled First)</string>
<string name="uninstall">Uninstall</string>
<string name="module_install">Install</string>
<string name="install">Install</string>
Expand Down

0 comments on commit ddda6cb

Please sign in to comment.