mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
feat: search apps in permission manager (#229)
This commit is contained in:
@@ -74,9 +74,6 @@ data class AppInfo(
|
|||||||
val flags: Int
|
val flags: Int
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun searchInString(query: String, content: String)
|
|
||||||
= query.split(' ').all { content.contains(it, true) }
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun AppChooserScreen(
|
fun AppChooserScreen(
|
||||||
|
|||||||
@@ -183,3 +183,6 @@ fun parsePackageNames(input: String) = input.lines().filter { it.isNotEmpty() }
|
|||||||
|
|
||||||
val getInstalledAppsFlags =
|
val getInstalledAppsFlags =
|
||||||
if(Build.VERSION.SDK_INT >= 24) PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.MATCH_UNINSTALLED_PACKAGES else 0
|
if(Build.VERSION.SDK_INT >= 24) PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.MATCH_UNINSTALLED_PACKAGES else 0
|
||||||
|
|
||||||
|
fun searchInString(query: String, content: String)
|
||||||
|
= query.split(' ').all { content.contains(it, true) }
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import androidx.compose.foundation.lazy.itemsIndexed
|
|||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
@@ -41,6 +42,7 @@ import androidx.compose.material.icons.filled.Add
|
|||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.Check
|
||||||
import androidx.compose.material.icons.filled.Clear
|
import androidx.compose.material.icons.filled.Clear
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material.icons.outlined.CheckCircle
|
import androidx.compose.material.icons.outlined.CheckCircle
|
||||||
import androidx.compose.material.icons.outlined.Clear
|
import androidx.compose.material.icons.outlined.Clear
|
||||||
import androidx.compose.material.icons.outlined.Delete
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
@@ -97,6 +99,7 @@ import androidx.compose.ui.focus.focusRequester
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
@@ -116,6 +119,7 @@ import com.bintianqi.owndroid.adaptiveInsets
|
|||||||
import com.bintianqi.owndroid.dpm.PermissionItem
|
import com.bintianqi.owndroid.dpm.PermissionItem
|
||||||
import com.bintianqi.owndroid.dpm.runtimePermissions
|
import com.bintianqi.owndroid.dpm.runtimePermissions
|
||||||
import com.bintianqi.owndroid.parsePackageNames
|
import com.bintianqi.owndroid.parsePackageNames
|
||||||
|
import com.bintianqi.owndroid.searchInString
|
||||||
import com.bintianqi.owndroid.showOperationResultToast
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
||||||
import com.bintianqi.owndroid.ui.FunctionItem
|
import com.bintianqi.owndroid.ui.FunctionItem
|
||||||
@@ -128,6 +132,7 @@ import com.bintianqi.owndroid.ui.PackageNameTextField
|
|||||||
import com.bintianqi.owndroid.ui.SwitchItem
|
import com.bintianqi.owndroid.ui.SwitchItem
|
||||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
@@ -488,19 +493,54 @@ fun PermissionDetailScreen(
|
|||||||
var selectedPackage by remember { mutableStateOf<Pair<String, Int>?>(null) }
|
var selectedPackage by remember { mutableStateOf<Pair<String, Int>?>(null) }
|
||||||
var showUserApps by remember { mutableStateOf(true) }
|
var showUserApps by remember { mutableStateOf(true) }
|
||||||
var showSystemApps by remember { mutableStateOf(false) }
|
var showSystemApps by remember { mutableStateOf(false) }
|
||||||
|
var searchMode by remember { mutableStateOf(false) }
|
||||||
|
var query by remember { mutableStateOf("") }
|
||||||
val displayedPackagesList = packagesList.filter {
|
val displayedPackagesList = packagesList.filter {
|
||||||
(showUserApps && it.first.flags and ApplicationInfo.FLAG_SYSTEM == 0) ||
|
((showUserApps && it.first.flags and ApplicationInfo.FLAG_SYSTEM == 0) ||
|
||||||
(showSystemApps && it.first.flags and ApplicationInfo.FLAG_SYSTEM != 0)
|
(showSystemApps && it.first.flags and ApplicationInfo.FLAG_SYSTEM != 0)) &&
|
||||||
|
(!searchMode || query.isBlank() || searchInString(query, it.first.name) ||
|
||||||
|
searchInString(query, it.first.label))
|
||||||
}
|
}
|
||||||
|
val fm = LocalFocusManager.current
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
packagesList.addAll(getPermissionPackages(param.permission))
|
packagesList.addAll(getPermissionPackages(param.permission))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
{ Text(stringResource(permissionItem.label)) },
|
{
|
||||||
|
if (searchMode) {
|
||||||
|
val fr = remember { FocusRequester() }
|
||||||
|
LaunchedEffect(Unit) { fr.requestFocus() }
|
||||||
|
OutlinedTextField(
|
||||||
|
query, { query = it },
|
||||||
|
Modifier.fillMaxWidth().focusRequester(fr),
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
|
||||||
|
keyboardActions = KeyboardActions { fm.clearFocus() },
|
||||||
|
placeholder = { Text(stringResource(R.string.search)) },
|
||||||
|
trailingIcon = {
|
||||||
|
IconButton({
|
||||||
|
query = ""
|
||||||
|
searchMode = false
|
||||||
|
}) {
|
||||||
|
Icon(Icons.Outlined.Clear, null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
textStyle = typography.bodyLarge
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Text(stringResource(permissionItem.label))
|
||||||
|
}
|
||||||
|
},
|
||||||
navigationIcon = { NavIcon(onNavigateUp) },
|
navigationIcon = { NavIcon(onNavigateUp) },
|
||||||
actions = {
|
actions = {
|
||||||
|
if (!searchMode) {
|
||||||
|
IconButton({ searchMode = true }) {
|
||||||
|
Icon(Icons.Default.Search, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
var menu by remember { mutableStateOf(false) }
|
var menu by remember { mutableStateOf(false) }
|
||||||
Box {
|
Box {
|
||||||
IconButton({ menu = true }) {
|
IconButton({ menu = true }) {
|
||||||
@@ -533,12 +573,13 @@ fun PermissionDetailScreen(
|
|||||||
contentWindowInsets = adaptiveInsets()
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
LazyColumn(Modifier.padding(paddingValues)) {
|
LazyColumn(Modifier.padding(paddingValues)) {
|
||||||
items(displayedPackagesList) { (info, grantState) ->
|
items(displayedPackagesList, { it.first.name }) { (info, grantState) ->
|
||||||
Row(
|
Row(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable { selectedPackage = info.name to grantState }
|
.clickable { selectedPackage = info.name to grantState }
|
||||||
.padding(horizontal = 8.dp, vertical = 6.dp),
|
.padding(horizontal = 8.dp, vertical = 6.dp)
|
||||||
|
.animateItem(),
|
||||||
Arrangement.SpaceBetween, Alignment.CenterVertically
|
Arrangement.SpaceBetween, Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Row(Modifier.weight(1F), verticalAlignment = Alignment.CenterVertically) {
|
Row(Modifier.weight(1F), verticalAlignment = Alignment.CenterVertically) {
|
||||||
@@ -1216,12 +1257,11 @@ fun ManagedConfigurationScreen(
|
|||||||
val restrictions by appRestrictions.collectAsStateWithLifecycle()
|
val restrictions by appRestrictions.collectAsStateWithLifecycle()
|
||||||
var searchMode by remember { mutableStateOf(false) }
|
var searchMode by remember { mutableStateOf(false) }
|
||||||
var searchKeyword by remember { mutableStateOf("") }
|
var searchKeyword by remember { mutableStateOf("") }
|
||||||
val displayRestrictions = if (searchKeyword.isEmpty()) {
|
val displayRestrictions = if (!searchMode || searchKeyword.isBlank()) {
|
||||||
restrictions
|
restrictions
|
||||||
} else {
|
} else {
|
||||||
restrictions.filter {
|
restrictions.filter {
|
||||||
it.key.contains(searchKeyword, true) ||
|
searchInString(searchKeyword, it.key) || it.title?.contains(searchKeyword, true) ?: true
|
||||||
it.title?.contains(searchKeyword, true) ?: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var dialog by remember { mutableStateOf<AppRestriction?>(null) }
|
var dialog by remember { mutableStateOf<AppRestriction?>(null) }
|
||||||
|
|||||||
Reference in New Issue
Block a user