manager: Add sort options on module's appbar (#2308)

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.
This commit is contained in:
Michelle Rodriguez
2024-12-25 19:48:28 +08:00
committed by Rifat Azad
parent 156b369862
commit 02f08f7971
4 changed files with 70 additions and 5 deletions

View File

@@ -36,12 +36,16 @@ import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.AlertDialog
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
@@ -111,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()
}
}
@@ -135,6 +143,55 @@ 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)

View File

@@ -14,8 +14,6 @@ import com.rifsxd.ksunext.ui.util.listModules
import com.rifsxd.ksunext.ui.util.overlayFsAvailable
import org.json.JSONArray
import org.json.JSONObject
import java.text.Collator
import java.util.Locale
class ModuleViewModel : ViewModel() {
@@ -52,8 +50,14 @@ class ModuleViewModel : ViewModel() {
var isRefreshing by mutableStateOf(false)
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
}
@@ -159,4 +163,4 @@ class ModuleViewModel : ViewModel() {
return Triple(zipUrl, version, changelog)
}
}
}

View File

@@ -35,6 +35,8 @@
<string name="module">模块</string>
<string name="confirm_module_installation">确认安装</string>
<string name="module_install_prompt_with_name">是否要继续安装模块 %1$s </string>
<string name="module_sort_action_first">可执行优先</string>
<string name="module_sort_enabled_first">已启用优先</string>
<string name="uninstall">卸载</string>
<string name="restore">重启</string>
<string name="module_install">安装</string>
@@ -156,4 +158,4 @@
<string name="selected_lkm">选择的 LKM: %s</string>
<string name="save_log">保存日志</string>
<string name="log_saved">日志已保存</string>
</resources>
</resources>

View File

@@ -36,6 +36,8 @@
<string name="module">Module</string>
<string name="confirm_module_installation">Confirm Installation</string>
<string name="module_install_prompt_with_name">Do you want to continue installing module %1$s?</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="restore">Restore</string>
<string name="module_install">Install</string>