From 624b1d0da3c7a8be702d5167f118762b89094008 Mon Sep 17 00:00:00 2001 From: Michelle Rodriguez <29279979+lamprose@users.noreply.github.com> Date: Wed, 25 Dec 2024 19:48:28 +0800 Subject: [PATCH] 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. --- .../com/rifsxd/ksunext/ui/screen/Module.kt | 57 +++++++++++++++++++ .../ksunext/ui/viewmodel/ModuleViewModel.kt | 12 ++-- .../src/main/res/values-zh-rCN/strings.xml | 4 +- manager/app/src/main/res/values/strings.xml | 2 + 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt index d4910620..90aaa294 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt @@ -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() 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) diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt index 0ee3d56c..d9c1efaa 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt @@ -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( + { 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) } -} +} \ No newline at end of file diff --git a/manager/app/src/main/res/values-zh-rCN/strings.xml b/manager/app/src/main/res/values-zh-rCN/strings.xml index 7fae83f1..926a9a16 100644 --- a/manager/app/src/main/res/values-zh-rCN/strings.xml +++ b/manager/app/src/main/res/values-zh-rCN/strings.xml @@ -35,6 +35,8 @@ 模块 确认安装 是否要继续安装模块 %1$s ? + 可执行优先 + 已启用优先 卸载 重启 安装 @@ -156,4 +158,4 @@ 选择的 LKM: %s 保存日志 日志已保存 - + \ No newline at end of file diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml index 83634881..494f5e2d 100644 --- a/manager/app/src/main/res/values/strings.xml +++ b/manager/app/src/main/res/values/strings.xml @@ -36,6 +36,8 @@ Module Confirm Installation Do you want to continue installing module %1$s? + Sort (Action First) + Sort (Enabled First) Uninstall Restore Install