mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 02:56:01 +00:00
feat: a snackbar to undo removal in PackageFunctionScreen (#216)
Remove redundant SDK version check
This commit is contained in:
@@ -16,6 +16,7 @@ class AppInstallerActivity:FragmentActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
val vm by viewModels<AppInstallerViewModel>()
|
||||
vm.initialize(intent)
|
||||
vm.registerInstallerReceiver(this)
|
||||
val theme = ThemeSettings(SP.materialYou, SP.darkTheme, SP.blackTheme)
|
||||
setContent {
|
||||
OwnDroidTheme(theme) {
|
||||
|
||||
@@ -36,13 +36,19 @@ class AppInstallerViewModel(application: Application): AndroidViewModel(applicat
|
||||
intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)?.let { list += it }
|
||||
intent.getParcelableArrayExtra(Intent.EXTRA_STREAM)?.forEach { list += it as Uri }
|
||||
intent.clipData?.let { clipData ->
|
||||
for(i in 0..clipData.itemCount - 1) {
|
||||
for(i in 0..<clipData.itemCount) {
|
||||
list += clipData.getItemAt(i).uri
|
||||
}
|
||||
}
|
||||
uiState.update { it.copy(it.packages + list.distinct()) }
|
||||
}
|
||||
|
||||
fun registerInstallerReceiver(context: Context) {
|
||||
ContextCompat.registerReceiver(
|
||||
context, Receiver(), IntentFilter(ACTION), ContextCompat.RECEIVER_NOT_EXPORTED
|
||||
)
|
||||
}
|
||||
|
||||
fun onPackagesAdd(packages: List<Uri>) {
|
||||
uiState.update {
|
||||
it.copy(packages = it.packages.plus(packages).distinct())
|
||||
@@ -93,17 +99,14 @@ class AppInstallerViewModel(application: Application): AndroidViewModel(applicat
|
||||
uiState.update { it.copy(installing = false, packageWriting = -1) }
|
||||
return
|
||||
}
|
||||
ContextCompat.registerReceiver(
|
||||
application, Receiver(), IntentFilter(ACTION), null,
|
||||
null, ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
val intent = Intent(ACTION).setPackage(application.packageName)
|
||||
val pi = if(Build.VERSION.SDK_INT >= 34) {
|
||||
PendingIntent.getBroadcast(
|
||||
application, sessionId, Intent(ACTION),
|
||||
application, sessionId, intent,
|
||||
PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT or PendingIntent.FLAG_MUTABLE
|
||||
).intentSender
|
||||
} else {
|
||||
PendingIntent.getBroadcast(application, sessionId, Intent(ACTION), PendingIntent.FLAG_MUTABLE).intentSender
|
||||
PendingIntent.getBroadcast(application, sessionId, intent, PendingIntent.FLAG_MUTABLE).intentSender
|
||||
}
|
||||
session.commit(pi)
|
||||
}
|
||||
@@ -119,7 +122,6 @@ class AppInstallerViewModel(application: Application): AndroidViewModel(applicat
|
||||
)
|
||||
} else {
|
||||
uiState.update { it.copy(result = intent) }
|
||||
context.unregisterReceiver(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,10 +269,6 @@ class MainActivity : FragmentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ExperimentalMaterial3Api
|
||||
|
||||
@@ -276,7 +276,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
|
||||
val packagePermissions = MutableStateFlow(emptyMap<String, Int>())
|
||||
@RequiresApi(23)
|
||||
fun getPackagePermissions(name: String) {
|
||||
if (name.isValidPackageName) {
|
||||
packagePermissions.value = runtimePermissions.associate {
|
||||
@@ -286,7 +285,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
packagePermissions.value = emptyMap()
|
||||
}
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun setPackagePermission(name: String, permission: String, status: Int): Boolean {
|
||||
val result = DPM.setPermissionGrantState(DAR, name, permission, status)
|
||||
getPackagePermissions(name)
|
||||
@@ -366,6 +364,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
|
||||
fun uninstallPackage(packageName: String, onComplete: (String?) -> Unit) {
|
||||
val action = "com.bintianqi.owndroid.action.PACKAGE_UNINSTALLED"
|
||||
val receiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val statusExtra = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, 999)
|
||||
@@ -383,16 +382,17 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
}
|
||||
ContextCompat.registerReceiver(
|
||||
application, receiver, IntentFilter(AppInstallerViewModel.ACTION), null,
|
||||
null, ContextCompat.RECEIVER_EXPORTED
|
||||
application, receiver, IntentFilter(action), null,
|
||||
null, ContextCompat.RECEIVER_NOT_EXPORTED
|
||||
)
|
||||
val intent = Intent(action).setPackage(application.packageName)
|
||||
val pi = if(VERSION.SDK_INT >= 34) {
|
||||
PendingIntent.getBroadcast(
|
||||
application, 0, Intent(AppInstallerViewModel.ACTION),
|
||||
application, 0, intent,
|
||||
PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT or PendingIntent.FLAG_MUTABLE
|
||||
).intentSender
|
||||
} else {
|
||||
PendingIntent.getBroadcast(application, 0, Intent(AppInstallerViewModel.ACTION), PendingIntent.FLAG_MUTABLE).intentSender
|
||||
PendingIntent.getBroadcast(application, 0, intent, PendingIntent.FLAG_MUTABLE).intentSender
|
||||
}
|
||||
application.getPackageInstaller().uninstall(packageName, pi)
|
||||
}
|
||||
@@ -545,7 +545,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
|
||||
val appRestrictions = MutableStateFlow(emptyList<AppRestriction>())
|
||||
|
||||
@RequiresApi(23)
|
||||
fun getAppRestrictions(name: String) {
|
||||
val rm = application.getSystemService(RestrictionsManager::class.java)
|
||||
try {
|
||||
@@ -569,7 +568,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(23)
|
||||
fun setAppRestrictions(name: String, item: AppRestriction) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val bundle = transformAppRestriction(
|
||||
@@ -580,7 +578,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(23)
|
||||
fun clearAppRestrictions(name: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
DPM.setApplicationRestrictions(DAR, name, Bundle())
|
||||
@@ -699,7 +696,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
autoTimeRequired = if (VERSION.SDK_INT < 30) DPM.autoTimeRequired else false,
|
||||
masterVolumeMuted = DPM.isMasterVolumeMuted(DAR),
|
||||
backupServiceEnabled = if (VERSION.SDK_INT >= 26) DPM.isBackupServiceEnabled(DAR) else false,
|
||||
btContactSharingDisabled = if (VERSION.SDK_INT >= 23 && privilege.work)
|
||||
btContactSharingDisabled = if (privilege.work)
|
||||
DPM.getBluetoothContactSharingDisabled(DAR) else false,
|
||||
commonCriteriaMode = if (VERSION.SDK_INT >= 30 && privilege.run { device || org })
|
||||
DPM.isCommonCriteriaModeEnabled(DAR) else false,
|
||||
@@ -718,7 +715,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
it.copy(screenCaptureDisabled = DPM.getScreenCaptureDisabled(null))
|
||||
}
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun setStatusBarDisabled(disabled: Boolean) {
|
||||
val result = DPM.setStatusBarDisabled(DAR, disabled)
|
||||
if (result) systemOptionsStatus.update { it.copy(statusBarDisabled = disabled) }
|
||||
@@ -752,7 +748,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
it.copy(backupServiceEnabled = DPM.isBackupServiceEnabled(DAR))
|
||||
}
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun setBtContactSharingDisabled(disabled: Boolean) {
|
||||
DPM.setBluetoothContactSharingDisabled(DAR, disabled)
|
||||
systemOptionsStatus.update {
|
||||
@@ -771,7 +766,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
DPM.isUsbDataSignalingEnabled = enabled
|
||||
systemOptionsStatus.update { it.copy(usbSignalEnabled = DPM.isUsbDataSignalingEnabled) }
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun setKeyguardDisabled(disabled: Boolean): Boolean {
|
||||
return DPM.setKeyguardDisabled(DAR, disabled)
|
||||
}
|
||||
@@ -841,11 +835,9 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
fun setContentProtectionPolicy(policy: Int) {
|
||||
DPM.setContentProtectionPolicy(DAR, policy)
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun getPermissionPolicy(): Int {
|
||||
return DPM.getPermissionPolicy(DAR)
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun setPermissionPolicy(policy: Int) {
|
||||
DPM.setPermissionPolicy(DAR, policy)
|
||||
}
|
||||
@@ -1031,14 +1023,12 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun getSystemUpdatePolicy(): SystemUpdatePolicyInfo {
|
||||
val policy = DPM.systemUpdatePolicy
|
||||
return SystemUpdatePolicyInfo(
|
||||
policy?.policyType ?: -1, policy?.installWindowStart ?: 0, policy?.installWindowEnd ?: 0
|
||||
)
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun setSystemUpdatePolicy(info: SystemUpdatePolicyInfo) {
|
||||
val policy = when (info.type) {
|
||||
SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC -> SystemUpdatePolicy.createAutomaticInstallPolicy()
|
||||
@@ -1352,28 +1342,19 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
fun createWorkProfile(options: CreateWorkProfileOptions): Intent {
|
||||
val intent = Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE)
|
||||
if (VERSION.SDK_INT >= 23) {
|
||||
intent.putExtra(
|
||||
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
|
||||
MyAdminComponent
|
||||
)
|
||||
intent.putExtra(
|
||||
DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE,
|
||||
Account(options.accountName, options.accountType)
|
||||
)
|
||||
if (VERSION.SDK_INT >= 26) {
|
||||
intent.putExtra(
|
||||
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
|
||||
MyAdminComponent
|
||||
DevicePolicyManager.EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION,
|
||||
options.keepAccount
|
||||
)
|
||||
} else {
|
||||
intent.putExtra(
|
||||
DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
|
||||
application.packageName
|
||||
)
|
||||
}
|
||||
if (options.migrateAccount && VERSION.SDK_INT >= 22) {
|
||||
intent.putExtra(
|
||||
DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE,
|
||||
Account(options.accountName, options.accountType)
|
||||
)
|
||||
if (VERSION.SDK_INT >= 26) {
|
||||
intent.putExtra(
|
||||
DevicePolicyManager.EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION,
|
||||
options.keepAccount
|
||||
)
|
||||
}
|
||||
}
|
||||
if (VERSION.SDK_INT >= 24) {
|
||||
intent.putExtra(
|
||||
@@ -1440,10 +1421,10 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
return UserInformation(
|
||||
if (VERSION.SDK_INT >= 24) UserManager.supportsMultipleUsers() else false,
|
||||
if (VERSION.SDK_INT >= 31) UserManager.isHeadlessSystemUserMode() else false,
|
||||
if (VERSION.SDK_INT >= 23) UM.isSystemUser else false,
|
||||
UM.isSystemUser,
|
||||
if (VERSION.SDK_INT >= 34) UM.isAdminUser else false,
|
||||
if (VERSION.SDK_INT >= 25) UM.isDemoUser else false,
|
||||
if (VERSION.SDK_INT >= 23) UM.getUserCreationTime(uh) else 0,
|
||||
UM.getUserCreationTime(uh),
|
||||
if (VERSION.SDK_INT >= 28) DPM.isLogoutEnabled else false,
|
||||
if (VERSION.SDK_INT >= 28) DPM.isEphemeralUser(DAR) else false,
|
||||
if (VERSION.SDK_INT >= 28) DPM.isAffiliatedUser else false,
|
||||
@@ -1518,7 +1499,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
fun setProfileName(name: String) {
|
||||
DPM.setProfileName(DAR, name)
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun setUserIcon(bitmap: Bitmap) {
|
||||
DPM.setUserIcon(DAR, bitmap)
|
||||
}
|
||||
@@ -1656,7 +1636,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
return PM.getPackageUid(name, 0)
|
||||
}
|
||||
var networkStatsData = emptyList<NetworkStatsData>()
|
||||
@RequiresApi(23)
|
||||
fun readNetworkStats(stats: NetworkStats): List<NetworkStatsData> {
|
||||
val list = mutableListOf<NetworkStatsData>()
|
||||
while (stats.hasNextBucket()) {
|
||||
@@ -1667,7 +1646,6 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
stats.close()
|
||||
return list
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun readNetworkStatsBucket(bucket: NetworkStats.Bucket): NetworkStatsData {
|
||||
return NetworkStatsData(
|
||||
bucket.rxBytes, bucket.rxPackets, bucket.txBytes, bucket.txPackets,
|
||||
|
||||
@@ -65,6 +65,10 @@ import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SegmentedButton
|
||||
import androidx.compose.material3.SegmentedButtonDefaults
|
||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
@@ -78,6 +82,7 @@ import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -121,6 +126,7 @@ import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.Serializable
|
||||
import sh.calvin.reorderable.ReorderableItem
|
||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||
@@ -213,9 +219,7 @@ fun ApplicationsFeaturesScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Un
|
||||
if(VERSION.SDK_INT >= 30 && (privilege.device || (VERSION.SDK_INT >= 33 && privilege.profile))) {
|
||||
FunctionItem(R.string.disable_user_control, icon = R.drawable.do_not_touch_fill0) { onNavigate(DisableUserControl) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 23) {
|
||||
FunctionItem(R.string.permissions, icon = R.drawable.shield_fill0) { onNavigate(PermissionsManager()) }
|
||||
}
|
||||
FunctionItem(R.string.permissions, icon = R.drawable.shield_fill0) { onNavigate(PermissionsManager()) }
|
||||
if(VERSION.SDK_INT >= 28) {
|
||||
FunctionItem(R.string.disable_metered_data, icon = R.drawable.money_off_fill0) { onNavigate(DisableMeteredData) }
|
||||
}
|
||||
@@ -278,7 +282,7 @@ fun ApplicationDetailsScreen(
|
||||
val appRestrictions by vm.appRestrictions.collectAsStateWithLifecycle()
|
||||
LaunchedEffect(Unit) {
|
||||
vm.getAppStatus(packageName)
|
||||
if (VERSION.SDK_INT >= 23) vm.getAppRestrictions(packageName)
|
||||
vm.getAppRestrictions(packageName)
|
||||
}
|
||||
MySmallTitleScaffold(R.string.place_holder, onNavigateUp, 0.dp) {
|
||||
Column(Modifier
|
||||
@@ -320,7 +324,7 @@ fun ApplicationDetailsScreen(
|
||||
state = status.keepUninstalled,
|
||||
onCheckedChange = { vm.adSetPackageKu(packageName, it) }
|
||||
)
|
||||
if (VERSION.SDK_INT >= 23 && appRestrictions.isNotEmpty()) {
|
||||
if (appRestrictions.isNotEmpty()) {
|
||||
FunctionItem(R.string.managed_configuration, icon = R.drawable.description_fill0) {
|
||||
onNavigate(ManagedConfiguration(packageName))
|
||||
}
|
||||
@@ -347,7 +351,6 @@ fun ApplicationDetailsScreen(
|
||||
|
||||
@Serializable data class PermissionsManager(val packageName: String? = null)
|
||||
|
||||
@RequiresApi(23)
|
||||
@Composable
|
||||
fun PermissionsManagerScreen(
|
||||
packagePermissions: MutableStateFlow<Map<String, Int>>, getPackagePermissions: (String) -> Unit,
|
||||
@@ -806,12 +809,15 @@ fun PackageFunctionScreen(
|
||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
||||
navigateToGroups: () -> Unit, appGroups: StateFlow<List<AppGroup>>, notes: Int? = null
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val groups by appGroups.collectAsStateWithLifecycle()
|
||||
val packages by packagesState.collectAsStateWithLifecycle()
|
||||
var input by rememberSaveable { mutableStateOf("") }
|
||||
val inputPackages = parsePackageNames(input)
|
||||
var dialog by remember { mutableStateOf(false) }
|
||||
var selectedGroup by remember { mutableStateOf<AppGroup?>(null) }
|
||||
val snackbar = remember { SnackbarHostState() }
|
||||
val coroutine = rememberCoroutineScope()
|
||||
LaunchedEffect(Unit) {
|
||||
onGet()
|
||||
input = chosenPackage.receive()
|
||||
@@ -852,12 +858,25 @@ fun PackageFunctionScreen(
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
snackbarHost = {
|
||||
SnackbarHost(snackbar)
|
||||
}
|
||||
) { paddingValues ->
|
||||
LazyColumn(Modifier.padding(paddingValues)) {
|
||||
items(packages, { it.name }) {
|
||||
ApplicationItem(it) {
|
||||
onSet(listOf(it.name), false)
|
||||
coroutine.launch {
|
||||
val result = snackbar.showSnackbar(
|
||||
context.getString(R.string.package_removed, it.name),
|
||||
context.getString(R.string.undo),
|
||||
true, SnackbarDuration.Short
|
||||
)
|
||||
if (result == SnackbarResult.ActionPerformed) {
|
||||
onSet(listOf(it.name), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
|
||||
@@ -152,7 +152,7 @@ fun NetworkScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
if(VERSION.SDK_INT >= 30) {
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(NetworkOptions) }
|
||||
}
|
||||
if (VERSION.SDK_INT >= 23 && !privilege.dhizuku)
|
||||
if (!privilege.dhizuku)
|
||||
FunctionItem(R.string.network_stats, icon = R.drawable.query_stats_fill0) { onNavigate(QueryNetworkStats) }
|
||||
if(VERSION.SDK_INT >= 29 && privilege.device) {
|
||||
FunctionItem(R.string.private_dns, icon = R.drawable.dns_fill0) { onNavigate(PrivateDns) }
|
||||
@@ -937,7 +937,6 @@ enum class NetworkStatsState(val id: Int, val text: Int) {
|
||||
Default(NetworkStats.Bucket.STATE_DEFAULT, R.string.default_str),
|
||||
Foreground(NetworkStats.Bucket.STATE_FOREGROUND, R.string.foreground)
|
||||
}
|
||||
@RequiresApi(23)
|
||||
enum class NetworkStatsUID(val uid: Int, val text: Int) {
|
||||
All(NetworkStats.Bucket.UID_ALL, R.string.all),
|
||||
Removed(NetworkStats.Bucket.UID_REMOVED, R.string.uninstalled),
|
||||
@@ -952,7 +951,6 @@ data class QueryNetworkStatsParams(
|
||||
@Serializable object QueryNetworkStats
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(23)
|
||||
@Composable
|
||||
fun NetworkStatsScreen(
|
||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit, getUid: (String) -> Int,
|
||||
@@ -1270,7 +1268,6 @@ data class NetworkStatsData(
|
||||
|
||||
@Serializable object NetworkStatsViewer
|
||||
|
||||
@RequiresApi(23)
|
||||
@Composable
|
||||
fun NetworkStatsViewerScreen(
|
||||
data: List<NetworkStatsData>, clearData: () -> Unit, onNavigateUp: () -> Unit
|
||||
|
||||
@@ -333,12 +333,10 @@ fun ResetPasswordScreen(resetPassword: (String, String, Int) -> Boolean, onNavig
|
||||
visualTransformation = PasswordVisualTransformation()
|
||||
)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
if(VERSION.SDK_INT >= 23) {
|
||||
CheckBoxItem(
|
||||
R.string.do_not_ask_credentials_on_boot,
|
||||
flags and RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT != 0
|
||||
) { flags = flags xor RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT }
|
||||
}
|
||||
CheckBoxItem(
|
||||
R.string.do_not_ask_credentials_on_boot,
|
||||
flags and RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT != 0
|
||||
) { flags = flags xor RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT }
|
||||
CheckBoxItem(
|
||||
R.string.reset_password_require_entry,
|
||||
flags and RESET_PASSWORD_REQUIRE_ENTRY != 0
|
||||
|
||||
@@ -171,9 +171,7 @@ fun SystemManagerScreen(
|
||||
FunctionItem(R.string.key_pairs, icon = R.drawable.key_vertical_fill0) { navCtrl.navigate("KeyPairs") }*/
|
||||
if(VERSION.SDK_INT >= 35 && (privilege.device || (privilege.profile && privilege.affiliated)))
|
||||
FunctionItem(R.string.content_protection_policy, icon = R.drawable.search_fill0) { onNavigate(ContentProtectionPolicy) }
|
||||
if(VERSION.SDK_INT >= 23) {
|
||||
FunctionItem(R.string.permission_policy, icon = R.drawable.key_fill0) { onNavigate(PermissionPolicy) }
|
||||
}
|
||||
FunctionItem(R.string.permission_policy, icon = R.drawable.key_fill0) { onNavigate(PermissionPolicy) }
|
||||
if(VERSION.SDK_INT >= 34 && privilege.device) {
|
||||
FunctionItem(R.string.mte_policy, icon = R.drawable.memory_fill0) { onNavigate(MtePolicy) }
|
||||
}
|
||||
@@ -204,7 +202,7 @@ fun SystemManagerScreen(
|
||||
FunctionItem(R.string.support_messages, icon = R.drawable.chat_fill0) { onNavigate(SupportMessage) }
|
||||
}
|
||||
FunctionItem(R.string.disable_account_management, icon = R.drawable.account_circle_fill0) { onNavigate(DisableAccountManagement) }
|
||||
if(VERSION.SDK_INT >= 23 && (privilege.device || privilege.org)) {
|
||||
if (privilege.device || privilege.org) {
|
||||
FunctionItem(R.string.system_update_policy, icon = R.drawable.system_update_fill0) { onNavigate(SetSystemUpdatePolicy) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 29 && (privilege.device || privilege.org)) {
|
||||
@@ -368,7 +366,7 @@ fun SystemOptionsScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
||||
SwitchItem(R.string.enable_usb_signal, status.usbSignalEnabled,
|
||||
vm::setUsbSignalEnabled, R.drawable.usb_fill0)
|
||||
}
|
||||
if (VERSION.SDK_INT >= 23 && VERSION.SDK_INT < 34) {
|
||||
if (VERSION.SDK_INT < 34) {
|
||||
Row(
|
||||
Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
@@ -413,8 +411,8 @@ fun KeyguardScreen(
|
||||
val context = LocalContext.current
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
MyScaffold(R.string.keyguard, onNavigateUp) {
|
||||
if (VERSION.SDK_INT >= 23 && (privilege.device ||
|
||||
(VERSION.SDK_INT >= 28 && privilege.profile && privilege.affiliated))) {
|
||||
if (privilege.device ||
|
||||
(VERSION.SDK_INT >= 28 && privilege.profile && privilege.affiliated)) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
@@ -435,7 +433,7 @@ fun KeyguardScreen(
|
||||
Notes(R.string.info_disable_keyguard)
|
||||
Spacer(Modifier.padding(vertical = 12.dp))
|
||||
}
|
||||
if(VERSION.SDK_INT >= 23) Text(text = stringResource(R.string.lock_now), style = typography.headlineLarge)
|
||||
Text(text = stringResource(R.string.lock_now), style = typography.headlineLarge)
|
||||
Spacer(Modifier.padding(vertical = 2.dp))
|
||||
var evictKey by rememberSaveable { mutableStateOf(false) }
|
||||
Button(
|
||||
@@ -1007,7 +1005,6 @@ fun ContentProtectionPolicyScreen(
|
||||
|
||||
@Serializable object PermissionPolicy
|
||||
|
||||
@RequiresApi(23)
|
||||
@Composable
|
||||
fun PermissionPolicyScreen(
|
||||
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -1215,7 +1212,7 @@ private fun StartLockTaskMode(
|
||||
var activity by rememberSaveable { mutableStateOf("") }
|
||||
var specifyActivity by rememberSaveable { mutableStateOf(false) }
|
||||
var clearTask by rememberSaveable { mutableStateOf(true) }
|
||||
var showNotification by rememberSaveable() { mutableStateOf(true) }
|
||||
var showNotification by rememberSaveable { mutableStateOf(true) }
|
||||
LaunchedEffect(Unit) {
|
||||
packageName = chosenPackage.receive()
|
||||
}
|
||||
@@ -1785,7 +1782,7 @@ fun WipeDataScreen(
|
||||
FullWidthCheckBoxItem(R.string.wipe_external_storage, flag and WIPE_EXTERNAL_STORAGE != 0) {
|
||||
flag = flag xor WIPE_EXTERNAL_STORAGE
|
||||
}
|
||||
if(VERSION.SDK_INT >= 22 && privilege.device) FullWidthCheckBoxItem(
|
||||
if (privilege.device) FullWidthCheckBoxItem(
|
||||
R.string.wipe_reset_protection_data, flag and WIPE_RESET_PROTECTION_DATA != 0) {
|
||||
flag = flag xor WIPE_RESET_PROTECTION_DATA
|
||||
}
|
||||
@@ -1839,7 +1836,7 @@ fun WipeDataScreen(
|
||||
text = {
|
||||
Text(
|
||||
text = stringResource(
|
||||
if(VERSION.SDK_INT >= 23 && userManager.isSystemUser) R.string.wipe_data_warning
|
||||
if (userManager.isSystemUser) R.string.wipe_data_warning
|
||||
else R.string.info_wipe_data_in_managed_user
|
||||
),
|
||||
color = colorScheme.error
|
||||
@@ -1880,7 +1877,6 @@ data class PendingSystemUpdateInfo(val exists: Boolean, val time: Long, val secu
|
||||
|
||||
@Serializable object SetSystemUpdatePolicy
|
||||
|
||||
@RequiresApi(23)
|
||||
@Composable
|
||||
fun SystemUpdatePolicyScreen(
|
||||
getPolicy: () -> SystemUpdatePolicyInfo, setPolicy: (SystemUpdatePolicyInfo) -> Unit,
|
||||
|
||||
@@ -30,12 +30,12 @@ import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExposedDropdownMenuAnchorType
|
||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||
import androidx.compose.material3.FilledTonalIconButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MenuAnchorType
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.SegmentedButton
|
||||
import androidx.compose.material3.SegmentedButtonDefaults
|
||||
@@ -105,25 +105,23 @@ fun UsersScreen(vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) ->
|
||||
FunctionItem(R.string.create_user, icon = R.drawable.person_add_fill0) { onNavigate(CreateUser) }
|
||||
}
|
||||
FunctionItem(R.string.change_username, icon = R.drawable.edit_fill0) { onNavigate(ChangeUsername) }
|
||||
if(VERSION.SDK_INT >= 23) {
|
||||
var changeUserIconDialog by remember { mutableStateOf(false) }
|
||||
var bitmap: Bitmap? by remember { mutableStateOf(null) }
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
|
||||
if(it != null) uriToStream(context, it) { stream ->
|
||||
bitmap = BitmapFactory.decodeStream(stream)
|
||||
if(bitmap != null) changeUserIconDialog = true
|
||||
}
|
||||
var changeUserIconDialog by remember { mutableStateOf(false) }
|
||||
var bitmap: Bitmap? by remember { mutableStateOf(null) }
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
|
||||
if(it != null) uriToStream(context, it) { stream ->
|
||||
bitmap = BitmapFactory.decodeStream(stream)
|
||||
if(bitmap != null) changeUserIconDialog = true
|
||||
}
|
||||
FunctionItem(R.string.change_user_icon, icon = R.drawable.account_circle_fill0) {
|
||||
context.popToast(R.string.select_an_image)
|
||||
launcher.launch("image/*")
|
||||
}
|
||||
if (changeUserIconDialog) ChangeUserIconDialog(
|
||||
bitmap!!, {
|
||||
vm.setUserIcon(bitmap!!)
|
||||
changeUserIconDialog = false
|
||||
}) { changeUserIconDialog = false }
|
||||
}
|
||||
FunctionItem(R.string.change_user_icon, icon = R.drawable.account_circle_fill0) {
|
||||
context.popToast(R.string.select_an_image)
|
||||
launcher.launch("image/*")
|
||||
}
|
||||
if (changeUserIconDialog) ChangeUserIconDialog(
|
||||
bitmap!!, {
|
||||
vm.setUserIcon(bitmap!!)
|
||||
changeUserIconDialog = false
|
||||
}) { changeUserIconDialog = false }
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.user_session_msg, icon = R.drawable.notifications_fill0) { onNavigate(UserSessionMessage) }
|
||||
}
|
||||
@@ -191,7 +189,7 @@ fun UserInfoScreen(getInfo: () -> UserInformation, onNavigateUp: () -> Unit) {
|
||||
if (VERSION.SDK_INT >= 24) InfoItem(R.string.support_multiuser, info.multiUser.yesOrNo)
|
||||
if (VERSION.SDK_INT >= 31) InfoItem(R.string.headless_system_user_mode, info.headless.yesOrNo, true) { infoDialog = 1 }
|
||||
Spacer(Modifier.height(8.dp))
|
||||
if (VERSION.SDK_INT >= 23) InfoItem(R.string.system_user, info.system.yesOrNo)
|
||||
InfoItem(R.string.system_user, info.system.yesOrNo)
|
||||
if (VERSION.SDK_INT >= 34) InfoItem(R.string.admin_user, info.admin.yesOrNo)
|
||||
if (VERSION.SDK_INT >= 25) InfoItem(R.string.demo_user, info.demo.yesOrNo)
|
||||
if (info.time != 0L) InfoItem(R.string.creation_time, formatDate(info.time))
|
||||
@@ -264,7 +262,7 @@ fun UserOperationScreen(
|
||||
input, { input = it },
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.menuAnchor(MenuAnchorType.PrimaryEditable)
|
||||
.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable)
|
||||
.padding(top = 4.dp, bottom = 8.dp),
|
||||
label = {
|
||||
Text(stringResource(if(useUserId) R.string.user_id else R.string.serial_number))
|
||||
@@ -586,7 +584,6 @@ fun UserSessionMessageScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(23)
|
||||
@Composable
|
||||
private fun ChangeUserIconDialog(bitmap: Bitmap, onSet: () -> Unit, onClose: () -> Unit) {
|
||||
AlertDialog(
|
||||
|
||||
@@ -101,31 +101,29 @@ fun CreateWorkProfileScreen(
|
||||
var migrateAccountName by remember { mutableStateOf("") }
|
||||
var migrateAccountType by remember { mutableStateOf("") }
|
||||
var keepAccount by remember { mutableStateOf(true) }
|
||||
if (VERSION.SDK_INT >= 22) {
|
||||
FullWidthCheckBoxItem(R.string.migrate_account, migrateAccount) { migrateAccount = it }
|
||||
AnimatedVisibility(migrateAccount) {
|
||||
val fr = FocusRequester()
|
||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||
OutlinedTextField(
|
||||
value = migrateAccountName, onValueChange = { migrateAccountName = it },
|
||||
label = { Text(stringResource(R.string.account_name)) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||
keyboardActions = KeyboardActions { fr.requestFocus() },
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = migrateAccountType, onValueChange = { migrateAccountType = it },
|
||||
label = { Text(stringResource(R.string.account_type)) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions { focusMgr.clearFocus() },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = HorizontalPadding)
|
||||
.focusRequester(fr)
|
||||
)
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
FullWidthCheckBoxItem(R.string.keep_account, keepAccount) { keepAccount = it }
|
||||
}
|
||||
FullWidthCheckBoxItem(R.string.migrate_account, migrateAccount) { migrateAccount = it }
|
||||
AnimatedVisibility(migrateAccount) {
|
||||
val fr = FocusRequester()
|
||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||
OutlinedTextField(
|
||||
value = migrateAccountName, onValueChange = { migrateAccountName = it },
|
||||
label = { Text(stringResource(R.string.account_name)) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||
keyboardActions = KeyboardActions { fr.requestFocus() },
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding)
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = migrateAccountType, onValueChange = { migrateAccountType = it },
|
||||
label = { Text(stringResource(R.string.account_type)) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions { focusMgr.clearFocus() },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = HorizontalPadding)
|
||||
.focusRequester(fr)
|
||||
)
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
FullWidthCheckBoxItem(R.string.keep_account, keepAccount) { keepAccount = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
<string name="timeout">超时</string>
|
||||
<string name="continue_str">继续</string>
|
||||
<string name="exit">退出</string>
|
||||
<string name="undo">撤销</string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="profile_owner">Profile owner</string>
|
||||
@@ -381,6 +382,7 @@
|
||||
<string name="managed_configuration">托管配置</string>
|
||||
<string name="clear_configurations">清除配置</string>
|
||||
<string name="specify_value">指定值</string>
|
||||
<string name="package_removed">移除了 %1$s</string>
|
||||
|
||||
<!--UserRestriction-->
|
||||
<string name="user_restriction">用户限制</string>
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
<string name="timeout">Timeout</string>
|
||||
<string name="continue_str">Continue</string>
|
||||
<string name="exit">Exit</string>
|
||||
<string name="undo">Undo</string>
|
||||
|
||||
<!--Permissions-->
|
||||
<string name="profile_owner">Profile owner</string>
|
||||
@@ -415,6 +416,7 @@
|
||||
<string name="managed_configuration">Managed configuration</string>
|
||||
<string name="clear_configurations">Clear configurations</string>
|
||||
<string name="specify_value">Specify value</string>
|
||||
<string name="package_removed">Removed %1$s</string>
|
||||
|
||||
<!--UserRestriction-->
|
||||
<string name="user_restriction">User restriction</string>
|
||||
|
||||
Reference in New Issue
Block a user