mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
Refactor Applications, add app list view
This commit is contained in:
@@ -74,8 +74,12 @@ import com.bintianqi.owndroid.dpm.AffiliationId
|
||||
import com.bintianqi.owndroid.dpm.AffiliationIdScreen
|
||||
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackage
|
||||
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackageScreen
|
||||
import com.bintianqi.owndroid.dpm.Applications
|
||||
import com.bintianqi.owndroid.dpm.ApplicationsScreen
|
||||
import com.bintianqi.owndroid.dpm.ApplicationDetails
|
||||
import com.bintianqi.owndroid.dpm.ApplicationDetailsScreen
|
||||
import com.bintianqi.owndroid.dpm.ApplicationsFeatures
|
||||
import com.bintianqi.owndroid.dpm.ApplicationsFeaturesScreen
|
||||
import com.bintianqi.owndroid.dpm.BlockUninstall
|
||||
import com.bintianqi.owndroid.dpm.BlockUninstallScreen
|
||||
import com.bintianqi.owndroid.dpm.CaCert
|
||||
import com.bintianqi.owndroid.dpm.CaCertScreen
|
||||
import com.bintianqi.owndroid.dpm.ChangeTime
|
||||
@@ -84,14 +88,22 @@ import com.bintianqi.owndroid.dpm.ChangeTimeZone
|
||||
import com.bintianqi.owndroid.dpm.ChangeTimeZoneScreen
|
||||
import com.bintianqi.owndroid.dpm.ChangeUsername
|
||||
import com.bintianqi.owndroid.dpm.ChangeUsernameScreen
|
||||
import com.bintianqi.owndroid.dpm.ClearAppStorage
|
||||
import com.bintianqi.owndroid.dpm.ClearAppStorageScreen
|
||||
import com.bintianqi.owndroid.dpm.ContentProtectionPolicy
|
||||
import com.bintianqi.owndroid.dpm.ContentProtectionPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.CreateUser
|
||||
import com.bintianqi.owndroid.dpm.CreateUserScreen
|
||||
import com.bintianqi.owndroid.dpm.CreateWorkProfile
|
||||
import com.bintianqi.owndroid.dpm.CreateWorkProfileScreen
|
||||
import com.bintianqi.owndroid.dpm.CredentialManagerPolicy
|
||||
import com.bintianqi.owndroid.dpm.CredentialManagerPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileIntentFilter
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileIntentFilterScreen
|
||||
import com.bintianqi.owndroid.dpm.CrossProfilePackages
|
||||
import com.bintianqi.owndroid.dpm.CrossProfilePackagesScreen
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileWidgetProviders
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileWidgetProvidersScreen
|
||||
import com.bintianqi.owndroid.dpm.DelegatedAdmins
|
||||
import com.bintianqi.owndroid.dpm.DelegatedAdminsScreen
|
||||
import com.bintianqi.owndroid.dpm.DeleteWorkProfile
|
||||
@@ -104,12 +116,24 @@ import com.bintianqi.owndroid.dpm.DeviceOwner
|
||||
import com.bintianqi.owndroid.dpm.DeviceOwnerScreen
|
||||
import com.bintianqi.owndroid.dpm.DisableAccountManagement
|
||||
import com.bintianqi.owndroid.dpm.DisableAccountManagementScreen
|
||||
import com.bintianqi.owndroid.dpm.DisableMeteredData
|
||||
import com.bintianqi.owndroid.dpm.DisableMeteredDataScreen
|
||||
import com.bintianqi.owndroid.dpm.DisableUserControl
|
||||
import com.bintianqi.owndroid.dpm.DisableUserControlScreen
|
||||
import com.bintianqi.owndroid.dpm.EnableSystemApp
|
||||
import com.bintianqi.owndroid.dpm.EnableSystemAppScreen
|
||||
import com.bintianqi.owndroid.dpm.FrpPolicy
|
||||
import com.bintianqi.owndroid.dpm.FrpPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.HardwareMonitor
|
||||
import com.bintianqi.owndroid.dpm.HardwareMonitorScreen
|
||||
import com.bintianqi.owndroid.dpm.Hide
|
||||
import com.bintianqi.owndroid.dpm.HideScreen
|
||||
import com.bintianqi.owndroid.dpm.InstallExistingApp
|
||||
import com.bintianqi.owndroid.dpm.InstallExistingAppScreen
|
||||
import com.bintianqi.owndroid.dpm.InstallSystemUpdate
|
||||
import com.bintianqi.owndroid.dpm.InstallSystemUpdateScreen
|
||||
import com.bintianqi.owndroid.dpm.KeepUninstalledPackages
|
||||
import com.bintianqi.owndroid.dpm.KeepUninstalledPackagesScreen
|
||||
import com.bintianqi.owndroid.dpm.Keyguard
|
||||
import com.bintianqi.owndroid.dpm.KeyguardDisabledFeatures
|
||||
import com.bintianqi.owndroid.dpm.KeyguardDisabledFeaturesScreen
|
||||
@@ -142,7 +166,13 @@ import com.bintianqi.owndroid.dpm.PasswordScreen
|
||||
import com.bintianqi.owndroid.dpm.PermissionPolicy
|
||||
import com.bintianqi.owndroid.dpm.PermissionPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.Permissions
|
||||
import com.bintianqi.owndroid.dpm.PermissionsManager
|
||||
import com.bintianqi.owndroid.dpm.PermissionsManagerScreen
|
||||
import com.bintianqi.owndroid.dpm.PermissionsScreen
|
||||
import com.bintianqi.owndroid.dpm.PermittedAccessibilityServices
|
||||
import com.bintianqi.owndroid.dpm.PermittedAccessibilityServicesScreen
|
||||
import com.bintianqi.owndroid.dpm.PermittedInputMethods
|
||||
import com.bintianqi.owndroid.dpm.PermittedInputMethodsScreen
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkService
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkServiceScreen
|
||||
import com.bintianqi.owndroid.dpm.PrivateDns
|
||||
@@ -163,12 +193,16 @@ import com.bintianqi.owndroid.dpm.ResetPasswordTokenScreen
|
||||
import com.bintianqi.owndroid.dpm.Restriction
|
||||
import com.bintianqi.owndroid.dpm.SecurityLogging
|
||||
import com.bintianqi.owndroid.dpm.SecurityLoggingScreen
|
||||
import com.bintianqi.owndroid.dpm.SetDefaultDialer
|
||||
import com.bintianqi.owndroid.dpm.SetDefaultDialerScreen
|
||||
import com.bintianqi.owndroid.dpm.SetSystemUpdatePolicy
|
||||
import com.bintianqi.owndroid.dpm.ShizukuScreen
|
||||
import com.bintianqi.owndroid.dpm.SupportMessage
|
||||
import com.bintianqi.owndroid.dpm.SupportMessageScreen
|
||||
import com.bintianqi.owndroid.dpm.Suspend
|
||||
import com.bintianqi.owndroid.dpm.SuspendPersonalApp
|
||||
import com.bintianqi.owndroid.dpm.SuspendPersonalAppScreen
|
||||
import com.bintianqi.owndroid.dpm.SuspendScreen
|
||||
import com.bintianqi.owndroid.dpm.SystemManager
|
||||
import com.bintianqi.owndroid.dpm.SystemManagerScreen
|
||||
import com.bintianqi.owndroid.dpm.SystemOptions
|
||||
@@ -176,6 +210,8 @@ import com.bintianqi.owndroid.dpm.SystemOptionsScreen
|
||||
import com.bintianqi.owndroid.dpm.SystemUpdatePolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.TransferOwnership
|
||||
import com.bintianqi.owndroid.dpm.TransferOwnershipScreen
|
||||
import com.bintianqi.owndroid.dpm.UninstallApp
|
||||
import com.bintianqi.owndroid.dpm.UninstallAppScreen
|
||||
import com.bintianqi.owndroid.dpm.UserInfo
|
||||
import com.bintianqi.owndroid.dpm.UserInfoScreen
|
||||
import com.bintianqi.owndroid.dpm.UserOperation
|
||||
@@ -348,7 +384,42 @@ fun Home(vm: MyViewModel) {
|
||||
composable<CrossProfileIntentFilter> { CrossProfileIntentFilterScreen(::navigateUp) }
|
||||
composable<DeleteWorkProfile> { DeleteWorkProfileScreen(::navigateUp) }
|
||||
|
||||
composable<Applications> { ApplicationsScreen(::navigateUp) }
|
||||
composable<ApplicationsList> {
|
||||
AppChooserScreen(it.toRoute(), {
|
||||
if(it == null) navigateUp() else navigate(ApplicationDetails(it))
|
||||
}, {
|
||||
SharedPrefs(context).applicationsListView = false
|
||||
navController.navigate(ApplicationsFeatures) {
|
||||
popUpTo(Home)
|
||||
}
|
||||
})
|
||||
}
|
||||
composable<ApplicationsFeatures> {
|
||||
ApplicationsFeaturesScreen(::navigateUp, ::navigate) {
|
||||
SharedPrefs(context).applicationsListView = true
|
||||
navController.navigate(ApplicationsList(true)) {
|
||||
popUpTo(Home)
|
||||
}
|
||||
}
|
||||
}
|
||||
composable<ApplicationDetails> { ApplicationDetailsScreen(it.toRoute(), ::navigateUp, ::navigate) }
|
||||
composable<Suspend> { SuspendScreen(::navigateUp) }
|
||||
composable<Hide> { HideScreen(::navigateUp) }
|
||||
composable<BlockUninstall> { BlockUninstallScreen(::navigateUp) }
|
||||
composable<DisableUserControl> { DisableUserControlScreen(::navigateUp) }
|
||||
composable<PermissionsManager> { PermissionsManagerScreen(::navigateUp, it.toRoute()) }
|
||||
composable<DisableMeteredData> { DisableMeteredDataScreen(::navigateUp) }
|
||||
composable<ClearAppStorage> { ClearAppStorageScreen(::navigateUp) }
|
||||
composable<UninstallApp> { UninstallAppScreen(::navigateUp) }
|
||||
composable<KeepUninstalledPackages> { KeepUninstalledPackagesScreen(::navigateUp) }
|
||||
composable<InstallExistingApp> { InstallExistingAppScreen(::navigateUp) }
|
||||
composable<CrossProfilePackages> { CrossProfilePackagesScreen(::navigateUp) }
|
||||
composable<CrossProfileWidgetProviders> { CrossProfileWidgetProvidersScreen(::navigateUp) }
|
||||
composable<CredentialManagerPolicy> { CredentialManagerPolicyScreen(::navigateUp) }
|
||||
composable<PermittedAccessibilityServices> { PermittedAccessibilityServicesScreen(::navigateUp) }
|
||||
composable<PermittedInputMethods> { PermittedInputMethodsScreen(::navigateUp) }
|
||||
composable<EnableSystemApp> { EnableSystemAppScreen(::navigateUp) }
|
||||
composable<SetDefaultDialer> { SetDefaultDialerScreen(::navigateUp) }
|
||||
|
||||
composable<UserRestriction> {
|
||||
LaunchedEffect(Unit) {
|
||||
@@ -493,7 +564,9 @@ private fun HomeScreen(onNavigate: (Any) -> Unit) {
|
||||
) {
|
||||
HomePageItem(R.string.work_profile, R.drawable.work_fill0) { onNavigate(WorkProfile) }
|
||||
}
|
||||
if(deviceOwner || profileOwner) HomePageItem(R.string.applications, R.drawable.apps_fill0) { onNavigate(Applications) }
|
||||
if(deviceOwner || profileOwner) HomePageItem(R.string.applications, R.drawable.apps_fill0) {
|
||||
onNavigate(if(SharedPrefs(context).applicationsListView) ApplicationsList(true) else ApplicationsFeatures)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && (profileOwner || deviceOwner)) {
|
||||
HomePageItem(R.string.user_restriction, R.drawable.person_off) { onNavigate(UserRestriction) }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
@@ -27,6 +28,7 @@ import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.List
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -41,8 +43,10 @@ import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -56,77 +60,64 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
class PackageChooserActivity: ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val vm by viewModels<MyViewModel>()
|
||||
if(getPackagesProgress.value < 1F) getPackages()
|
||||
setContent {
|
||||
val theme by vm.theme.collectAsStateWithLifecycle()
|
||||
OwnDroidTheme(theme) {
|
||||
val packages by installedPackages.collectAsStateWithLifecycle()
|
||||
val progress by getPackagesProgress.collectAsStateWithLifecycle()
|
||||
PackageChooserScreen(packages, progress, ::getPackages) {
|
||||
AppChooserScreen(ApplicationsList(false), {
|
||||
setResult(0, Intent().putExtra("package", it))
|
||||
finish()
|
||||
}
|
||||
}, {})
|
||||
}
|
||||
}
|
||||
}
|
||||
val flags = if(Build.VERSION.SDK_INT >= 24) PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.MATCH_UNINSTALLED_PACKAGES else 0
|
||||
fun getPackages() {
|
||||
installedPackages.value = emptyList()
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val pm = packageManager
|
||||
val apps = pm.getInstalledApplications(flags)
|
||||
for(pkg in apps) {
|
||||
installedPackages.update {
|
||||
it + PackageInfo(
|
||||
pkg.packageName, pkg.loadLabel(pm).toString(), pkg.loadIcon(pm),
|
||||
(pkg.flags and ApplicationInfo.FLAG_SYSTEM) != 0
|
||||
)
|
||||
}
|
||||
withContext(Dispatchers.Main) { getPackagesProgress.value = installedPackages.value.size.toFloat() / apps.size }
|
||||
}
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
val installedPackages = MutableStateFlow(emptyList<PackageInfo>())
|
||||
val getPackagesProgress = MutableStateFlow(0F)
|
||||
}
|
||||
}
|
||||
|
||||
data class PackageInfo(
|
||||
val installedApps = MutableStateFlow(emptyList<AppInfo>())
|
||||
|
||||
data class AppInfo(
|
||||
val name: String,
|
||||
val label: String,
|
||||
val icon: Drawable,
|
||||
val system: Boolean
|
||||
val flags: Int
|
||||
)
|
||||
|
||||
private fun searchInString(query: String, content: String)
|
||||
= query.split(' ').all { content.contains(it, true) }
|
||||
|
||||
@Serializable data class ApplicationsList(val canSwitchView: Boolean)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun PackageChooserScreen(
|
||||
packages: List<PackageInfo>, progress: Float, onRefresh: () -> Unit, onChoosePackage: (String?) -> Unit
|
||||
) {
|
||||
fun AppChooserScreen(params: ApplicationsList, onChoosePackage: (String?) -> Unit, onSwitchView: () -> Unit) {
|
||||
val packages by installedApps.collectAsStateWithLifecycle()
|
||||
val coroutine = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
var progress by remember { mutableFloatStateOf(1F) }
|
||||
var system by remember { mutableStateOf(false) }
|
||||
var search by remember { mutableStateOf("") }
|
||||
var query by remember { mutableStateOf("") }
|
||||
var searchMode by remember { mutableStateOf(false) }
|
||||
val filteredPackages = packages.filter {
|
||||
system == it.system &&
|
||||
(if(search.isEmpty()) true
|
||||
else it.name.contains(search, ignoreCase = true) || it.label.contains(search, ignoreCase = true))
|
||||
system == (it.flags and ApplicationInfo.FLAG_SYSTEM != 0) &&
|
||||
(query.isEmpty() || (searchInString(query, it.label) || searchInString(query, it.name)))
|
||||
}
|
||||
val focusMgr = LocalFocusManager.current
|
||||
LaunchedEffect(Unit) {
|
||||
if(packages.size <= 1) getInstalledApps(coroutine, context) { progress = it }
|
||||
}
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
@@ -141,9 +132,15 @@ private fun PackageChooserScreen(
|
||||
}) {
|
||||
Icon(painter = painterResource(R.drawable.filter_alt_fill0), contentDescription = null)
|
||||
}
|
||||
IconButton(onRefresh) {
|
||||
IconButton(
|
||||
{ getInstalledApps(coroutine, context) { progress = it } },
|
||||
enabled = progress == 1F
|
||||
) {
|
||||
Icon(painter = painterResource(R.drawable.refresh_fill0), contentDescription = null)
|
||||
}
|
||||
if(params.canSwitchView) IconButton(onSwitchView) {
|
||||
Icon(Icons.AutoMirrored.Default.List, null)
|
||||
}
|
||||
}
|
||||
},
|
||||
title = {
|
||||
@@ -151,8 +148,8 @@ private fun PackageChooserScreen(
|
||||
val fr = FocusRequester()
|
||||
LaunchedEffect(Unit) { fr.requestFocus() }
|
||||
OutlinedTextField(
|
||||
value = search,
|
||||
onValueChange = { search = it },
|
||||
value = query,
|
||||
onValueChange = { query = it },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
|
||||
keyboardActions = KeyboardActions { focusMgr.clearFocus() },
|
||||
placeholder = { Text(stringResource(R.string.search)) },
|
||||
@@ -162,7 +159,7 @@ private fun PackageChooserScreen(
|
||||
contentDescription = null,
|
||||
modifier = Modifier.clickable {
|
||||
focusMgr.clearFocus()
|
||||
search = ""
|
||||
query = ""
|
||||
searchMode = false
|
||||
}
|
||||
)
|
||||
@@ -170,8 +167,6 @@ private fun PackageChooserScreen(
|
||||
textStyle = typography.bodyLarge,
|
||||
modifier = Modifier.fillMaxWidth().focusRequester(fr)
|
||||
)
|
||||
} else {
|
||||
Text(stringResource(R.string.package_chooser))
|
||||
}
|
||||
},
|
||||
navigationIcon = {
|
||||
@@ -182,11 +177,8 @@ private fun PackageChooserScreen(
|
||||
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceContainer)
|
||||
)
|
||||
}
|
||||
) { paddingValues->
|
||||
LazyColumn(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.fillMaxSize().padding(top = paddingValues.calculateTopPadding())
|
||||
) {
|
||||
) { paddingValues ->
|
||||
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
|
||||
stickyHeader {
|
||||
AnimatedVisibility(progress < 1F) {
|
||||
LinearProgressIndicator(progress = { progress }, modifier = Modifier.fillMaxWidth())
|
||||
@@ -215,3 +207,24 @@ private fun PackageChooserScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getInstalledApps(scope: CoroutineScope, context: Context, onProgressUpdated: (Float) -> Unit) {
|
||||
installedApps.value = emptyList()
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val pm = context.packageManager
|
||||
val apps = pm.getInstalledApplications(getInstalledAppsFlags)
|
||||
for(pkg in apps) {
|
||||
val label = pkg.loadLabel(pm).toString()
|
||||
val icon = pkg.loadIcon(pm)
|
||||
withContext(Dispatchers.Main) {
|
||||
installedApps.update {
|
||||
it + AppInfo(pkg.packageName, label, icon, pkg.flags)
|
||||
}
|
||||
onProgressUpdated(installedApps.value.size.toFloat() / apps.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val getInstalledAppsFlags =
|
||||
if(Build.VERSION.SDK_INT >= 24) PackageManager.MATCH_DISABLED_COMPONENTS or PackageManager.MATCH_UNINSTALLED_PACKAGES else 0
|
||||
|
||||
@@ -20,6 +20,7 @@ class SharedPrefs(context: Context) {
|
||||
var blackTheme by BooleanSharedPref("theme.black")
|
||||
var lockPassword by StringSharedPref("lock.password")
|
||||
var biometricsUnlock by BooleanSharedPref("lock.biometrics")
|
||||
var applicationsListView by BooleanSharedPref("applications.list_view")
|
||||
}
|
||||
|
||||
private class BooleanSharedPref(val key: String, val defValue: Boolean = false): ReadWriteProperty<SharedPrefs, Boolean> {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -602,9 +602,17 @@ fun AddDelegatedAdminScreen(data: AddDelegatedAdmin, onNavigateUp: () -> Unit) {
|
||||
readOnly = updateMode,
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp, horizontal = HorizontalPadding)
|
||||
)
|
||||
DelegatedScope.entries.filter { VERSION.SDK_INT >= it.requiresApi }.forEach {scope ->
|
||||
FullWidthCheckBoxItem(scope.string, scope in scopes) {
|
||||
if(it) scopes += scope else scopes -= scope
|
||||
DelegatedScope.entries.filter { VERSION.SDK_INT >= it.requiresApi }.forEach { scope ->
|
||||
val checked = scope in scopes
|
||||
Row(
|
||||
Modifier.fillMaxWidth().clickable { if(!checked) scopes += scope else scopes -= scope }.padding(vertical = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Checkbox(checked, { if(it) scopes += scope else scopes -= scope }, modifier = Modifier.padding(horizontal = 4.dp))
|
||||
Column {
|
||||
Text(stringResource(scope.string))
|
||||
Text(scope.id, style = typography.bodyMedium, color = colorScheme.onSurfaceVariant)
|
||||
}
|
||||
}
|
||||
}
|
||||
Button(
|
||||
|
||||
@@ -9,6 +9,8 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
@@ -319,6 +321,28 @@ fun MyScaffold(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MyLazyScaffold(
|
||||
@StringRes title: Int,
|
||||
onNavIconClicked: () -> Unit,
|
||||
content: LazyListScope.() -> Unit
|
||||
) {
|
||||
val sb = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
Scaffold(
|
||||
Modifier.nestedScroll(sb.nestedScrollConnection),
|
||||
topBar = {
|
||||
LargeTopAppBar(
|
||||
{ Text(stringResource(title)) },
|
||||
navigationIcon = { NavIcon(onNavIconClicked) },
|
||||
scrollBehavior = sb
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
LazyColumn(Modifier.fillMaxSize().padding(paddingValues), content = content)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MySmallTitleScaffold(
|
||||
|
||||
9
app/src/main/res/drawable/shield_fill0.xml
Normal file
9
app/src/main/res/drawable/shield_fill0.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M480,880q-139,-35 -229.5,-159.5T160,444v-244l320,-120 320,120v244q0,152 -90.5,276.5T480,880ZM480,796q104,-33 172,-132t68,-220v-189l-240,-90 -240,90v189q0,121 68,220t172,132ZM480,480Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
@@ -377,39 +377,27 @@
|
||||
<string name="enable_lockdown">Включить блокировку</string>
|
||||
<string name="clear_current_config">Очистить текущую конфигурацию</string>
|
||||
<string name="permissions">Разрешение</string>
|
||||
<string name="scope_is_work_profile">Область действия: рабочий профиль</string>
|
||||
<string name="app_info">Информация о приложении</string>
|
||||
<string name="not_installed">Не установлено</string>
|
||||
<string name="block_uninstall">Блокировать удаление</string>
|
||||
<string name="enable_system_app">Включить системное приложение</string>
|
||||
<string name="enable_system_app_desc">Повторно включить системное приложение, отключенное по умолчанию</string>
|
||||
<!--ucd: управление пользователем отключено-->
|
||||
<string name="ucd">Отключить управление пользователем</string>
|
||||
<string name="ucd_desc">Если вы установите этот флажок, вы не сможете очистить хранилище этих приложений или принудительно остановить их.</string>
|
||||
<string name="app_list_is">Список приложений:</string>
|
||||
<string name="disable_user_control">Отключить управление пользователем</string>
|
||||
<string name="disable_metered_data">Disable metered data</string> <!--TODO-->
|
||||
<string name="cross_profile_package">Кросс-профильный пакет</string>
|
||||
<string name="cross_profile_apps">Cross profile apps</string> <!--TODO-->
|
||||
<string name="cross_profile_widget">Кросс-профильный виджет</string>
|
||||
<string name="credential_manager_policy">Credential manager policy</string> <!--TODO-->
|
||||
<string name="whitelist_and_system_app">Белый список и системные приложения</string>
|
||||
<string name="permitted_packages_is">Разрешенные пакеты: \n</string>
|
||||
<string name="permitted_accessibility_services">Разрешенные службы доступности</string>
|
||||
<string name="only_system_accessibility_allowed">Разрешены только системные службы доступности</string>
|
||||
<string name="system_accessibility_always_allowed">Системные службы доступности всегда разрешены.</string>
|
||||
<string name="only_system_ime_allowed">Разрешены только системные методы ввода</string>
|
||||
<string name="system_ime_always_allowed">Системные методы ввода всегда разрешены.</string>
|
||||
<string name="permitted_ime">Разрешенный метод ввода</string>
|
||||
<string name="keep_uninstalled_packages">Сохранять удаленные пакеты</string>
|
||||
<string name="clear_data">Очистить данные</string>
|
||||
<string name="clear_app_storage">Очистить хранилище приложения</string>
|
||||
<string name="app_storage_will_be_cleared">Хранилище этого приложения будет очищено</string>
|
||||
<string name="set_default_dialer">Установить приложение для звонков по умолчанию</string>
|
||||
<string name="app_will_be_default_dialer">Это приложение будет установлено в качестве приложения для звонков по умолчанию.</string>
|
||||
<string name="uninstall_app">Удалить приложение</string>
|
||||
<string name="install_app">Установить приложение</string>
|
||||
<!--TODO: 2 strings-->
|
||||
<string name="choose_apk_file">Choose an APK file</string>
|
||||
<string name="install_existing_app">Install existing app</string>
|
||||
<string name="install_existing_app">Install existing app</string> <!--TODO-->
|
||||
<string name="keep_after_uninstall">Keep after uninstall</string> <!--TODO-->
|
||||
<string name="search">Поиск</string>
|
||||
|
||||
<!--Ограничения пользователя-->
|
||||
@@ -699,6 +687,7 @@
|
||||
<string name="info_disable_user_control">Пользователь не сможет очищать данные приложений или принудительно останавливать пакеты.</string>
|
||||
<string name="info_keep_uninstalled_apps">Установить список приложений, которые нужно сохранить в виде APK-файлов, даже если ни у одного пользователя в данный момент они не установлены.</string>
|
||||
<!--TODO--><string name="info_install_existing_app">Install an existing package that has been installed in another user, or has been kept after uninstall.</string>
|
||||
<!--TODO--><string name="info_enable_system_app">Re-enable a system app that was disabled by default when the user was initialized.</string>
|
||||
<string name="info_headless_system_user_mode">Режим "безголового" системного пользователя означает, что системный пользователь запускает системные службы и некоторый системный интерфейс, но он не связан с каким-либо реальным человеком, и для связи с реальными людьми должны быть созданы дополнительные пользователи.</string>
|
||||
<string name="info_logout">If the current user is not switched by OwnDroid, this function cannot be used.</string> <!--TODO-->
|
||||
<string name="info_affiliation_id">Когда владелец устройства создает управляемого пользователя, управляемый пользователь не является аффилированным. Чтобы сделать управляемого пользователя аффилированным с владельцем устройства, вам следует установить одинаковые аффилированные идентификаторы в основном и управляемом пользователях.</string>
|
||||
|
||||
@@ -385,38 +385,27 @@
|
||||
<string name="enable_lockdown">Kilitlemeyi Etkinleştir</string>
|
||||
<string name="clear_current_config">Mevcut Yapılandırmayı Temizle</string>
|
||||
<string name="permissions">İzinler</string>
|
||||
<string name="scope_is_work_profile">Kapsam: İş Profili</string>
|
||||
<string name="app_info">Uygulama Bilgisi</string>
|
||||
<string name="not_installed">Yüklenmedi</string>
|
||||
<string name="block_uninstall">Kaldırmayı Engelle</string>
|
||||
<string name="enable_system_app">Sistem Uygulamasını Etkinleştir</string>
|
||||
<string name="enable_system_app_desc">Varsayılan olarak devre dışı bırakılmış bir sistem uygulamasını yeniden etkinleştir</string>
|
||||
<!--ucd: user control disabled-->
|
||||
<string name="ucd">Kullanıcı Kontrolünü Devre Dışı Bırak</string>
|
||||
<string name="ucd_desc">Bunu ayarlarsanız, bu uygulamaların depolamasını temizleyemez veya zorla durduramazsınız.</string>
|
||||
<string name="app_list_is">Uygulama listesi:</string>
|
||||
<string name="disable_user_control">Kullanıcı Kontrolünü Devre Dışı Bırak</string>
|
||||
<string name="disable_metered_data">Disable metered data</string> <!--TODO-->
|
||||
<string name="cross_profile_package">Çapraz Profil Paketi</string>
|
||||
<string name="cross_profile_apps">Cross profile apps</string> <!--TODO-->
|
||||
<string name="cross_profile_widget">Çapraz Profil Widget\'ı</string>
|
||||
<string name="credential_manager_policy">Credential manager policy</string> <!--TODO-->
|
||||
<string name="whitelist_and_system_app">Beyaz Liste ve Sistem Uygulaması</string>
|
||||
<string name="permitted_packages_is">İzin Verilen Paketler: \n</string>
|
||||
<string name="permitted_accessibility_services">İzin Verilen Erişilebilirlik Servisleri</string>
|
||||
<string name="only_system_accessibility_allowed">Yalnızca sistem erişilebilirlik servislerine izin verilir</string>
|
||||
<string name="system_accessibility_always_allowed">Sistem erişilebilirlik servisleri her zaman izinlidir.</string>
|
||||
<string name="only_system_ime_allowed">Yalnızca sistem giriş yöntemlerine izin verilir</string>
|
||||
<string name="system_ime_always_allowed">Sistem giriş yöntemleri her zaman izinlidir.</string>
|
||||
<string name="permitted_ime">İzin Verilen IME</string>
|
||||
<string name="keep_uninstalled_packages">Kaldırılmış Paketleri Koru</string>
|
||||
<string name="clear_data">Verileri Temizle</string>
|
||||
<string name="clear_app_storage">Uygulama Depolamasını Temizle</string>
|
||||
<string name="app_storage_will_be_cleared">Bu uygulamanın depolaması temizlenecek</string>
|
||||
<string name="set_default_dialer">Varsayılan Arama Uygulamasını Ayarla</string>
|
||||
<string name="app_will_be_default_dialer">Bu uygulama varsayılan arama uygulaması olarak ayarlanacak.</string>
|
||||
<string name="uninstall_app">Uygulamayı Kaldır</string>
|
||||
<string name="install_app">Uygulama Yükle</string>
|
||||
<string name="choose_apk_file">Bir APK Dosyası Seç</string>
|
||||
<string name="install_existing_app">Mevcut Uygulamayı Yükle</string>
|
||||
<string name="keep_after_uninstall">Keep after uninstall</string> <!--TODO-->
|
||||
<string name="search">Ara</string>
|
||||
|
||||
<!--UserRestriction-->
|
||||
@@ -702,6 +691,7 @@
|
||||
<string name="info_disable_user_control">Kullanıcı uygulama verilerini temizleyemez veya paketleri zorla durduramaz.</string>
|
||||
<string name="info_keep_uninstalled_apps">Hiçbir kullanıcının şu anda yüklemediği uygulamaları APK olarak saklanacak bir liste ayarlar.</string>
|
||||
<string name="info_install_existing_app">Başka bir kullanıcıda yüklenmiş veya kaldırıldıktan sonra saklanmış mevcut bir paketi yükler.</string>
|
||||
<!--TODO--><string name="info_enable_system_app">Re-enable a system app that was disabled by default when the user was initialized.</string>
|
||||
<string name="info_headless_system_user_mode">Başıboş sistem kullanıcı modu, sistem kullanıcısının sistem servislerini ve bazı sistem kullanıcı arayüzlerini çalıştırdığı, ancak herhangi bir gerçek kişiyle ilişkilendirilmediği ve gerçek kişilerle ilişkilendirilecek ek kullanıcıların oluşturulması gerektiği anlamına gelir.</string>
|
||||
<string name="info_logout">Mevcut kullanıcı OwnDroid tarafından değiştirilmediyse bu işlev kullanılamaz.</string>
|
||||
<string name="info_affiliation_id">Cihaz Sahibi bir yönetilen kullanıcı oluşturduğunda, yönetilen kullanıcı bağlı değildir. Yönetilen kullanıcının Cihaz Sahibi ile bağlı hale getirilmesi için ana kullanıcı ve yönetilen kullanıcıda aynı bağlılık kimlikleri ayarlanmalıdır.</string>
|
||||
|
||||
@@ -368,37 +368,26 @@
|
||||
<string name="enable_lockdown">启用锁定</string>
|
||||
<string name="clear_current_config">清除当前配置</string>
|
||||
<string name="permissions">权限</string>
|
||||
<string name="scope_is_work_profile">作用域: 工作资料</string>
|
||||
<string name="app_info">应用详情</string>
|
||||
<string name="not_installed">未安装</string>
|
||||
<string name="block_uninstall">阻止卸载</string>
|
||||
<string name="ucd">禁止用户控制</string>
|
||||
<string name="ucd_desc">用户将无法清除这些应用的存储空间或强制停止这些应用</string>
|
||||
<string name="app_list_is">应用列表:</string>
|
||||
<string name="disable_user_control">禁止用户控制</string>
|
||||
<string name="disable_metered_data">禁用计量数据</string>
|
||||
<string name="cross_profile_package">跨资料应用</string>
|
||||
<string name="cross_profile_apps">跨资料应用</string>
|
||||
<string name="cross_profile_widget">跨资料微件</string>
|
||||
<string name="credential_manager_policy">凭据管理器策略</string>
|
||||
<string name="whitelist_and_system_app">白名单和系统应用</string>
|
||||
<string name="permitted_packages_is">许可的应用:\n</string>
|
||||
<string name="permitted_accessibility_services">许可的无障碍服务</string>
|
||||
<string name="only_system_accessibility_allowed">只允许系统无障碍服务</string>
|
||||
<string name="system_accessibility_always_allowed">系统的无障碍服务不受影响</string>
|
||||
<string name="only_system_ime_allowed">只允许系统输入法</string>
|
||||
<string name="system_ime_always_allowed">系统输入法不受影响</string>
|
||||
<string name="permitted_ime">许可的输入法</string>
|
||||
<string name="keep_uninstalled_packages">卸载后保留的应用</string>
|
||||
<string name="clear_data">数据清除</string>
|
||||
<string name="clear_app_storage">清除应用存储</string>
|
||||
<string name="app_storage_will_be_cleared">这个应用的存储空间将被清空</string>
|
||||
<string name="set_default_dialer">设为默认拨号应用</string>
|
||||
<string name="app_will_be_default_dialer">这个应用将被设为默认拨号应用</string>
|
||||
<string name="set_default_dialer">设置默认拨号器</string>
|
||||
<string name="uninstall_app">卸载应用</string>
|
||||
<string name="install_app">安装应用</string>
|
||||
<string name="choose_apk_file">选择一个APK文件</string>
|
||||
<string name="install_existing_app">安装已存在的应用</string>
|
||||
<string name="enable_system_app">启用系统应用</string>
|
||||
<string name="enable_system_app_desc">重新启用一个默认被禁用的系统应用</string>
|
||||
<string name="keep_after_uninstall">卸载后保留</string>
|
||||
<string name="search">搜索</string>
|
||||
|
||||
<!--UserRestriction-->
|
||||
@@ -698,6 +687,7 @@
|
||||
<string name="info_disable_user_control">用户无法清除这些应用的存储空间,也无法强制停止应用</string>
|
||||
<string name="info_keep_uninstalled_apps">这个列表中的应用的APK将会一直保留,即使没有任何用户安装这个应用</string>
|
||||
<string name="info_install_existing_app">安装一个已经在其他用户中安装或在卸载后保留的app。</string>
|
||||
<string name="info_enable_system_app">重新启用一个在用户初始化时默认被禁用的系统app</string>
|
||||
<string name="info_headless_system_user_mode">无头系统用户模式意味着系统用户运行系统服务和一些系统UI,但它不与任何真实的人相关联,必须创建额外的用户才能与真实的人相关联。</string>
|
||||
<string name="info_logout">如果当前用户不是由OwnDroid切换的,无法使用此功能。</string>
|
||||
<string name="info_affiliation_id">当Device owner创建并管理用户时,新的用户不是附属用户。Device owner设置和受管理用户完全相同的附属用户ID后,受管理用户成为附属于Device owner的用户</string>
|
||||
|
||||
@@ -404,38 +404,26 @@
|
||||
<string name="enable_lockdown">Enable lockdown</string>
|
||||
<string name="clear_current_config">Clear current config</string>
|
||||
<string name="permissions">Permissions</string>
|
||||
<string name="scope_is_work_profile">Scope: work profile</string>
|
||||
<string name="app_info">App info</string>
|
||||
<string name="not_installed">Not installed</string>
|
||||
<string name="block_uninstall">Block uninstall</string>
|
||||
<string name="enable_system_app">Enable system app</string>
|
||||
<string name="enable_system_app_desc">Re-enable a system app that was disabled by default</string>
|
||||
<!--ucd: user control disabled-->
|
||||
<string name="ucd">Disable user control</string>
|
||||
<string name="ucd_desc">If you set this, you cannot clear these apps\' storage or force stop them. </string>
|
||||
<string name="app_list_is">App list:</string>
|
||||
<string name="disable_user_control">Disable user control</string>
|
||||
<string name="disable_metered_data">Disable metered data</string>
|
||||
<string name="cross_profile_package">Cross profile package</string>
|
||||
<string name="cross_profile_apps">Cross profile apps</string>
|
||||
<string name="cross_profile_widget">Cross profile widget</string>
|
||||
<string name="credential_manager_policy">Credential manager policy</string>
|
||||
<string name="whitelist_and_system_app">Whitelist and system app</string>
|
||||
<string name="permitted_packages_is">Permitted packages: \n</string>
|
||||
<string name="permitted_accessibility_services">Permitted accessibility services</string>
|
||||
<string name="only_system_accessibility_allowed">Only system accessibility services are allowed</string>
|
||||
<string name="system_accessibility_always_allowed">System accessibility services are always allowed.</string>
|
||||
<string name="only_system_ime_allowed">Only system input methods are allowed</string>
|
||||
<string name="system_ime_always_allowed">System input methods are always allowed.</string>
|
||||
<string name="permitted_ime">Permitted IME</string>
|
||||
<string name="keep_uninstalled_packages">Keep uninstalled packages</string>
|
||||
<string name="clear_data">Clear data</string>
|
||||
<string name="clear_app_storage">Clear app storage</string>
|
||||
<string name="app_storage_will_be_cleared">This app\'s storage will be cleared</string>
|
||||
<string name="set_default_dialer">Set default dialer</string>
|
||||
<string name="app_will_be_default_dialer">This app will be set as the default dialer application.</string>
|
||||
<string name="uninstall_app">Uninstall app</string>
|
||||
<string name="install_app">Install app</string>
|
||||
<string name="choose_apk_file">Choose an APK file</string>
|
||||
<string name="install_existing_app">Install existing app</string>
|
||||
<string name="keep_after_uninstall">Keep after uninstall</string>
|
||||
<string name="search">Search</string>
|
||||
|
||||
<!--UserRestriction-->
|
||||
@@ -738,6 +726,7 @@
|
||||
<string name="info_disable_user_control">User will not be able to clear app data or force-stop packages.</string>
|
||||
<string name="info_keep_uninstalled_apps">Set a list of apps to keep around as APKs even if no user has currently installed it. </string>
|
||||
<string name="info_install_existing_app">Install an existing package that has been installed in another user, or has been kept after uninstall.</string>
|
||||
<string name="info_enable_system_app">Re-enable a system app that was disabled by default when the user was initialized.</string>
|
||||
<string name="info_headless_system_user_mode">Headless system user mode means the system user runs system services and some system UI, but it is not associated with any real person and additional users must be created to be associated with real persons.</string>
|
||||
<string name="info_logout">If the current user is not switched by OwnDroid, this function cannot be used.</string>
|
||||
<string name="info_affiliation_id">When Device owner create a managed user, the managed user isn\'t affiliated. In order to make the managed user affiliated with the Device owner, you should set same affiliated IDs in main user and managed user</string>
|
||||
|
||||
Reference in New Issue
Block a user