mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-27 12:26:11 +00:00
ViewModel refactoring: Work profile part
close #169 Improve UI, fix #172 fix #165
This commit is contained in:
@@ -38,6 +38,7 @@
|
|||||||
<action android:name="android.app.action.PROVISION_MANAGED_PROFILE"/>
|
<action android:name="android.app.action.PROVISION_MANAGED_PROFILE"/>
|
||||||
<action android:name="android.app.action.MANAGED_PROFILE_PROVISIONED"/>
|
<action android:name="android.app.action.MANAGED_PROFILE_PROVISIONED"/>
|
||||||
<action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE"/>
|
<action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE"/>
|
||||||
|
<action android:name="android.app.action.CHECK_POLICY_COMPLIANCE"/>
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|||||||
@@ -417,11 +417,22 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
|||||||
composable<AddApnSetting> { AddApnSettingScreen(it.arguments?.getParcelable("setting"), ::navigateUp) }
|
composable<AddApnSetting> { AddApnSettingScreen(it.arguments?.getParcelable("setting"), ::navigateUp) }
|
||||||
|
|
||||||
composable<WorkProfile> { WorkProfileScreen(::navigateUp, ::navigate) }
|
composable<WorkProfile> { WorkProfileScreen(::navigateUp, ::navigate) }
|
||||||
composable<OrganizationOwnedProfile> { OrganizationOwnedProfileScreen(::navigateUp) }
|
composable<OrganizationOwnedProfile> {
|
||||||
composable<CreateWorkProfile> { CreateWorkProfileScreen(::navigateUp) }
|
OrganizationOwnedProfileScreen(vm::activateOrgProfileByShizuku, ::navigateUp)
|
||||||
composable<SuspendPersonalApp> { SuspendPersonalAppScreen(::navigateUp) }
|
}
|
||||||
composable<CrossProfileIntentFilter> { CrossProfileIntentFilterScreen(::navigateUp) }
|
composable<CreateWorkProfile> {
|
||||||
composable<DeleteWorkProfile> { DeleteWorkProfileScreen(::navigateUp) }
|
CreateWorkProfileScreen(vm::createWorkProfile, ::navigateUp)
|
||||||
|
}
|
||||||
|
composable<SuspendPersonalApp> {
|
||||||
|
SuspendPersonalAppScreen(
|
||||||
|
vm::getPersonalAppsSuspendedReason, vm::setPersonalAppsSuspended,
|
||||||
|
vm::getProfileMaxTimeOff, vm::setProfileMaxTimeOff, ::navigateUp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable<CrossProfileIntentFilter> {
|
||||||
|
CrossProfileIntentFilterScreen(vm::addCrossProfileIntentFilter, ::navigateUp)
|
||||||
|
}
|
||||||
|
composable<DeleteWorkProfile> { DeleteWorkProfileScreen(vm::wipeData, ::navigateUp) }
|
||||||
|
|
||||||
composable<ApplicationsList> {
|
composable<ApplicationsList> {
|
||||||
val canSwitchView = (it.toRoute() as ApplicationsList).canSwitchView
|
val canSwitchView = (it.toRoute() as ApplicationsList).canSwitchView
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.bintianqi.owndroid
|
package com.bintianqi.owndroid
|
||||||
|
|
||||||
|
import android.accounts.Account
|
||||||
import android.app.ActivityOptions
|
import android.app.ActivityOptions
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
@@ -35,13 +36,17 @@ import com.bintianqi.owndroid.Privilege.DPM
|
|||||||
import com.bintianqi.owndroid.dpm.ACTIVATE_DEVICE_OWNER_COMMAND
|
import com.bintianqi.owndroid.dpm.ACTIVATE_DEVICE_OWNER_COMMAND
|
||||||
import com.bintianqi.owndroid.dpm.AppStatus
|
import com.bintianqi.owndroid.dpm.AppStatus
|
||||||
import com.bintianqi.owndroid.dpm.CaCertInfo
|
import com.bintianqi.owndroid.dpm.CaCertInfo
|
||||||
|
import com.bintianqi.owndroid.dpm.CreateWorkProfileOptions
|
||||||
import com.bintianqi.owndroid.dpm.DelegatedAdmin
|
import com.bintianqi.owndroid.dpm.DelegatedAdmin
|
||||||
import com.bintianqi.owndroid.dpm.DeviceAdmin
|
import com.bintianqi.owndroid.dpm.DeviceAdmin
|
||||||
import com.bintianqi.owndroid.dpm.FrpPolicyInfo
|
import com.bintianqi.owndroid.dpm.FrpPolicyInfo
|
||||||
import com.bintianqi.owndroid.dpm.HardwareProperties
|
import com.bintianqi.owndroid.dpm.HardwareProperties
|
||||||
|
import com.bintianqi.owndroid.dpm.IntentFilterDirection
|
||||||
|
import com.bintianqi.owndroid.dpm.IntentFilterOptions
|
||||||
import com.bintianqi.owndroid.dpm.PendingSystemUpdateInfo
|
import com.bintianqi.owndroid.dpm.PendingSystemUpdateInfo
|
||||||
import com.bintianqi.owndroid.dpm.SystemOptionsStatus
|
import com.bintianqi.owndroid.dpm.SystemOptionsStatus
|
||||||
import com.bintianqi.owndroid.dpm.SystemUpdatePolicyInfo
|
import com.bintianqi.owndroid.dpm.SystemUpdatePolicyInfo
|
||||||
|
import com.bintianqi.owndroid.dpm.activateOrgProfileCommand
|
||||||
import com.bintianqi.owndroid.dpm.delegatedScopesList
|
import com.bintianqi.owndroid.dpm.delegatedScopesList
|
||||||
import com.bintianqi.owndroid.dpm.getPackageInstaller
|
import com.bintianqi.owndroid.dpm.getPackageInstaller
|
||||||
import com.bintianqi.owndroid.dpm.handlePrivilegeChange
|
import com.bintianqi.owndroid.dpm.handlePrivilegeChange
|
||||||
@@ -294,7 +299,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
}
|
}
|
||||||
fun setCmPackage(name: String, status: Boolean) {
|
fun setCmPackage(name: String, status: Boolean) {
|
||||||
cmPackages.update { list ->
|
cmPackages.update { list ->
|
||||||
if (status) list + getAppInfo(name) else list.dropWhile { it.name == name }
|
if (status) list + getAppInfo(name) else list.filter { it.name != name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@RequiresApi(34)
|
@RequiresApi(34)
|
||||||
@@ -315,7 +320,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
}
|
}
|
||||||
fun setPimPackage(name: String, status: Boolean) {
|
fun setPimPackage(name: String, status: Boolean) {
|
||||||
pimPackages.update { packages ->
|
pimPackages.update { packages ->
|
||||||
if (status) packages + getAppInfo(name) else packages.dropWhile { it.name == name }
|
if (status) packages + getAppInfo(name) else packages.filter { it.name != name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun setPimPolicy(allowAll: Boolean): Boolean {
|
fun setPimPolicy(allowAll: Boolean): Boolean {
|
||||||
@@ -335,7 +340,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
}
|
}
|
||||||
fun setPasPackage(name: String, status: Boolean) {
|
fun setPasPackage(name: String, status: Boolean) {
|
||||||
pasPackages.update { packages ->
|
pasPackages.update { packages ->
|
||||||
if (status) packages + getAppInfo(name) else packages.dropWhile { it.name == name }
|
if (status) packages + getAppInfo(name) else packages.filter { it.name != name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun setPasPolicy(allowAll: Boolean): Boolean {
|
fun setPasPolicy(allowAll: Boolean): Boolean {
|
||||||
@@ -1022,6 +1027,81 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
)
|
||||||
|
} 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(
|
||||||
|
DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION,
|
||||||
|
options.skipEncrypt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (VERSION.SDK_INT >= 33) {
|
||||||
|
intent.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_ALLOW_OFFLINE, options.offline)
|
||||||
|
}
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
fun activateOrgProfileByShizuku(callback: (Boolean) -> Unit) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
var succeed = false
|
||||||
|
useShizuku(application) { service ->
|
||||||
|
val result = IUserService.Stub.asInterface(service).execute(activateOrgProfileCommand)
|
||||||
|
succeed = result?.getInt("code", -1) == 0
|
||||||
|
callback(succeed)
|
||||||
|
}
|
||||||
|
if (succeed) Privilege.updateStatus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@RequiresApi(30)
|
||||||
|
fun getPersonalAppsSuspendedReason(): Int {
|
||||||
|
return DPM.getPersonalAppsSuspendedReasons(DAR)
|
||||||
|
}
|
||||||
|
@RequiresApi(30)
|
||||||
|
fun setPersonalAppsSuspended(suspended: Boolean) {
|
||||||
|
DPM.setPersonalAppsSuspended(DAR, suspended)
|
||||||
|
}
|
||||||
|
@RequiresApi(30)
|
||||||
|
fun getProfileMaxTimeOff(): Long {
|
||||||
|
return DPM.getManagedProfileMaximumTimeOff(DAR)
|
||||||
|
}
|
||||||
|
@RequiresApi(30)
|
||||||
|
fun setProfileMaxTimeOff(time: Long) {
|
||||||
|
DPM.setManagedProfileMaximumTimeOff(DAR, time)
|
||||||
|
}
|
||||||
|
fun addCrossProfileIntentFilter(options: IntentFilterOptions) {
|
||||||
|
val filter = IntentFilter(options.action)
|
||||||
|
if (options.category.isNotEmpty()) filter.addCategory(options.category)
|
||||||
|
if (options.mimeType.isNotEmpty()) filter.addDataType(options.mimeType)
|
||||||
|
val flags = when(options.direction) {
|
||||||
|
IntentFilterDirection.ToManaged -> DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED
|
||||||
|
IntentFilterDirection.ToParent -> DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT
|
||||||
|
IntentFilterDirection.Both -> DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED or
|
||||||
|
DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT
|
||||||
|
}
|
||||||
|
DPM.addCrossProfileIntentFilter(DAR, filter, flags)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ThemeSettings(
|
data class ThemeSettings(
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ fun useShizuku(context: Context, action: (IBinder?) -> Unit) {
|
|||||||
} else {
|
} else {
|
||||||
Sui.init(context.packageName)
|
Sui.init(context.packageName)
|
||||||
fun requestPermissionResultListener(requestCode: Int, grantResult: Int) {
|
fun requestPermissionResultListener(requestCode: Int, grantResult: Int) {
|
||||||
if(grantResult != PackageManager.PERMISSION_GRANTED) {
|
if (grantResult == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Shizuku.bindUserService(getShizukuArgs(context), connection)
|
||||||
|
} else {
|
||||||
context.popToast(R.string.permission_denied)
|
context.popToast(R.string.permission_denied)
|
||||||
}
|
}
|
||||||
Shizuku.removeRequestPermissionResultListener(::requestPermissionResultListener)
|
Shizuku.removeRequestPermissionResultListener(::requestPermissionResultListener)
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ fun ApplicationDetailsScreen(
|
|||||||
)
|
)
|
||||||
if(VERSION.SDK_INT >= 28) FunctionItem(R.string.clear_app_storage, icon = R.drawable.mop_fill0) { dialog = 1 }
|
if(VERSION.SDK_INT >= 28) FunctionItem(R.string.clear_app_storage, icon = R.drawable.mop_fill0) { dialog = 1 }
|
||||||
FunctionItem(R.string.uninstall, icon = R.drawable.delete_fill0) { dialog = 2 }
|
FunctionItem(R.string.uninstall, icon = R.drawable.delete_fill0) { dialog = 2 }
|
||||||
|
Spacer(Modifier.height(40.dp))
|
||||||
}
|
}
|
||||||
if(dialog == 1 && VERSION.SDK_INT >= 28)
|
if(dialog == 1 && VERSION.SDK_INT >= 28)
|
||||||
ClearAppStorageDialog(packageName, vm::clearAppData) { dialog = 0 }
|
ClearAppStorageDialog(packageName, vm::clearAppData) { dialog = 0 }
|
||||||
@@ -604,6 +605,7 @@ fun CredentialManagerPolicyScreen(
|
|||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.apply))
|
Text(stringResource(R.string.apply))
|
||||||
}
|
}
|
||||||
|
Spacer(Modifier.height(40.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -658,6 +660,7 @@ fun PermittedAsAndImPackages(
|
|||||||
}
|
}
|
||||||
Spacer(Modifier.height(10.dp))
|
Spacer(Modifier.height(10.dp))
|
||||||
Notes(note, HorizontalPadding)
|
Notes(note, HorizontalPadding)
|
||||||
|
Spacer(Modifier.height(40.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -767,6 +770,7 @@ fun PackageFunctionScreen(
|
|||||||
Text(stringResource(R.string.add))
|
Text(stringResource(R.string.add))
|
||||||
}
|
}
|
||||||
if (notes != null) Notes(notes, HorizontalPadding)
|
if (notes != null) Notes(notes, HorizontalPadding)
|
||||||
|
Spacer(Modifier.height(40.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1262,6 +1262,7 @@ private fun LockTaskPackages(
|
|||||||
Text(stringResource(R.string.add))
|
Text(stringResource(R.string.add))
|
||||||
}
|
}
|
||||||
Notes(R.string.info_lock_task_packages)
|
Notes(R.string.info_lock_task_packages)
|
||||||
|
Spacer(Modifier.height(40.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,9 @@
|
|||||||
package com.bintianqi.owndroid.dpm
|
package com.bintianqi.owndroid.dpm
|
||||||
|
|
||||||
import android.accounts.Account
|
import android.app.admin.DevicePolicyManager
|
||||||
import android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE
|
|
||||||
import android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE
|
|
||||||
import android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ALLOW_OFFLINE
|
|
||||||
import android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME
|
|
||||||
import android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
|
|
||||||
import android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION
|
|
||||||
import android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION
|
|
||||||
import android.app.admin.DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT
|
|
||||||
import android.app.admin.DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED
|
|
||||||
import android.app.admin.DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED
|
|
||||||
import android.app.admin.DevicePolicyManager.PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT
|
|
||||||
import android.app.admin.DevicePolicyManager.WIPE_EUICC
|
import android.app.admin.DevicePolicyManager.WIPE_EUICC
|
||||||
import android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE
|
import android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE
|
||||||
import android.content.ActivityNotFoundException
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
@@ -24,6 +11,7 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -33,8 +21,13 @@ import androidx.compose.foundation.text.selection.SelectionContainer
|
|||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.Checkbox
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
import androidx.compose.material3.MaterialTheme.typography
|
import androidx.compose.material3.MaterialTheme.typography
|
||||||
|
import androidx.compose.material3.MenuAnchorType
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
@@ -45,6 +38,7 @@ import androidx.compose.runtime.mutableIntStateOf
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
@@ -55,18 +49,19 @@ import androidx.compose.ui.text.input.ImeAction
|
|||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.bintianqi.owndroid.IUserService
|
import com.bintianqi.owndroid.HorizontalPadding
|
||||||
import com.bintianqi.owndroid.MyAdminComponent
|
|
||||||
import com.bintianqi.owndroid.Privilege
|
import com.bintianqi.owndroid.Privilege
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
import com.bintianqi.owndroid.popToast
|
|
||||||
import com.bintianqi.owndroid.showOperationResultToast
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||||
|
import com.bintianqi.owndroid.ui.CircularProgressDialog
|
||||||
|
import com.bintianqi.owndroid.ui.ExpandExposedTextFieldIcon
|
||||||
|
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
|
||||||
import com.bintianqi.owndroid.ui.FunctionItem
|
import com.bintianqi.owndroid.ui.FunctionItem
|
||||||
import com.bintianqi.owndroid.ui.MyScaffold
|
import com.bintianqi.owndroid.ui.MyScaffold
|
||||||
import com.bintianqi.owndroid.ui.Notes
|
import com.bintianqi.owndroid.ui.Notes
|
||||||
import com.bintianqi.owndroid.ui.SwitchItem
|
import com.bintianqi.owndroid.ui.SwitchItem
|
||||||
import com.bintianqi.owndroid.useShizuku
|
import com.bintianqi.owndroid.yesOrNo
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable object WorkProfile
|
@Serializable object WorkProfile
|
||||||
@@ -86,14 +81,20 @@ fun WorkProfileScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class CreateWorkProfileOptions(
|
||||||
|
val skipEncrypt: Boolean, val offline: Boolean, val migrateAccount: Boolean,
|
||||||
|
val accountName: String, val accountType: String, val keepAccount: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
@Serializable object CreateWorkProfile
|
@Serializable object CreateWorkProfile
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CreateWorkProfileScreen(onNavigateUp: () -> Unit) {
|
fun CreateWorkProfileScreen(
|
||||||
val context = LocalContext.current
|
createIntent: (CreateWorkProfileOptions) -> Intent, onNavigateUp: () -> Unit
|
||||||
|
) {
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { }
|
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { }
|
||||||
MyScaffold(R.string.create_work_profile, onNavigateUp) {
|
MyScaffold(R.string.create_work_profile, onNavigateUp, 0.dp) {
|
||||||
var skipEncrypt by remember { mutableStateOf(false) }
|
var skipEncrypt by remember { mutableStateOf(false) }
|
||||||
var offlineProvisioning by remember { mutableStateOf(true) }
|
var offlineProvisioning by remember { mutableStateOf(true) }
|
||||||
var migrateAccount by remember { mutableStateOf(false) }
|
var migrateAccount by remember { mutableStateOf(false) }
|
||||||
@@ -101,7 +102,7 @@ fun CreateWorkProfileScreen(onNavigateUp: () -> Unit) {
|
|||||||
var migrateAccountType by remember { mutableStateOf("") }
|
var migrateAccountType by remember { mutableStateOf("") }
|
||||||
var keepAccount by remember { mutableStateOf(true) }
|
var keepAccount by remember { mutableStateOf(true) }
|
||||||
if (VERSION.SDK_INT >= 22) {
|
if (VERSION.SDK_INT >= 22) {
|
||||||
CheckBoxItem(R.string.migrate_account, migrateAccount) { migrateAccount = it }
|
FullWidthCheckBoxItem(R.string.migrate_account, migrateAccount) { migrateAccount = it }
|
||||||
AnimatedVisibility(migrateAccount) {
|
AnimatedVisibility(migrateAccount) {
|
||||||
val fr = FocusRequester()
|
val fr = FocusRequester()
|
||||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||||
@@ -110,47 +111,40 @@ fun CreateWorkProfileScreen(onNavigateUp: () -> Unit) {
|
|||||||
label = { Text(stringResource(R.string.account_name)) },
|
label = { Text(stringResource(R.string.account_name)) },
|
||||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||||
keyboardActions = KeyboardActions { fr.requestFocus() },
|
keyboardActions = KeyboardActions { fr.requestFocus() },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding)
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = migrateAccountType, onValueChange = { migrateAccountType = it },
|
value = migrateAccountType, onValueChange = { migrateAccountType = it },
|
||||||
label = { Text(stringResource(R.string.account_type)) },
|
label = { Text(stringResource(R.string.account_type)) },
|
||||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||||
keyboardActions = KeyboardActions { focusMgr.clearFocus() },
|
keyboardActions = KeyboardActions { focusMgr.clearFocus() },
|
||||||
modifier = Modifier.fillMaxWidth().focusRequester(fr)
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = HorizontalPadding)
|
||||||
|
.focusRequester(fr)
|
||||||
)
|
)
|
||||||
if(VERSION.SDK_INT >= 26) {
|
if(VERSION.SDK_INT >= 26) {
|
||||||
CheckBoxItem(R.string.keep_account, keepAccount) { keepAccount = it }
|
FullWidthCheckBoxItem(R.string.keep_account, keepAccount) { keepAccount = it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(VERSION.SDK_INT >= 24) CheckBoxItem(R.string.skip_encryption, skipEncrypt) { skipEncrypt = it }
|
if (VERSION.SDK_INT >= 24) FullWidthCheckBoxItem(
|
||||||
if(VERSION.SDK_INT >= 33) CheckBoxItem(R.string.offline_provisioning, offlineProvisioning) { offlineProvisioning = it }
|
R.string.skip_encryption, skipEncrypt
|
||||||
|
) { skipEncrypt = it }
|
||||||
|
if (VERSION.SDK_INT >= 33) FullWidthCheckBoxItem(
|
||||||
|
R.string.offline_provisioning, offlineProvisioning
|
||||||
|
) { offlineProvisioning = it }
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Spacer(Modifier.padding(vertical = 5.dp))
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
try {
|
val intent = createIntent(CreateWorkProfileOptions(
|
||||||
val intent = Intent(ACTION_PROVISION_MANAGED_PROFILE)
|
skipEncrypt, offlineProvisioning, migrateAccount, migrateAccountName,
|
||||||
if(VERSION.SDK_INT >= 23) {
|
migrateAccountType, keepAccount
|
||||||
intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, MyAdminComponent)
|
))
|
||||||
} else {
|
|
||||||
intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, context.packageName)
|
|
||||||
}
|
|
||||||
if(migrateAccount && VERSION.SDK_INT >= 22) {
|
|
||||||
intent.putExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, Account(migrateAccountName, migrateAccountType))
|
|
||||||
if(VERSION.SDK_INT >= 26) {
|
|
||||||
intent.putExtra(EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION, keepAccount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(VERSION.SDK_INT >= 24) { intent.putExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION, skipEncrypt) }
|
|
||||||
if(VERSION.SDK_INT >= 33) { intent.putExtra(EXTRA_PROVISIONING_ALLOW_OFFLINE, offlineProvisioning) }
|
|
||||||
launcher.launch(intent)
|
launcher.launch(intent)
|
||||||
} catch(_: ActivityNotFoundException) {
|
|
||||||
context.popToast(R.string.unsupported)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding)
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.create))
|
Text(stringResource(R.string.create))
|
||||||
}
|
}
|
||||||
@@ -161,18 +155,19 @@ fun CreateWorkProfileScreen(onNavigateUp: () -> Unit) {
|
|||||||
|
|
||||||
@RequiresApi(30)
|
@RequiresApi(30)
|
||||||
@Composable
|
@Composable
|
||||||
fun OrganizationOwnedProfileScreen(onNavigateUp: () -> Unit) {
|
fun OrganizationOwnedProfileScreen(
|
||||||
|
onActivate: ((Boolean) -> Unit) -> Unit, onNavigateUp: () -> Unit
|
||||||
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
var activating by remember { mutableStateOf(false) }
|
||||||
var dialog by remember { mutableStateOf(false) }
|
var dialog by remember { mutableStateOf(false) }
|
||||||
MyScaffold(R.string.org_owned_work_profile, onNavigateUp) {
|
MyScaffold(R.string.org_owned_work_profile, onNavigateUp) {
|
||||||
Button({
|
Button({
|
||||||
useShizuku(context) { service ->
|
activating = true
|
||||||
val result = IUserService.Stub.asInterface(service).execute(activateOrgProfileCommand)
|
onActivate {
|
||||||
if (result?.getInt("code", -1) == 0) {
|
activating = false
|
||||||
context.showOperationResultToast(true)
|
context.showOperationResultToast(it)
|
||||||
} else {
|
if (it) onNavigateUp()
|
||||||
context.showOperationResultToast(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.shizuku))
|
Text(stringResource(R.string.shizuku))
|
||||||
@@ -189,6 +184,7 @@ fun OrganizationOwnedProfileScreen(onNavigateUp: () -> Unit) {
|
|||||||
},
|
},
|
||||||
onDismissRequest = { dialog = false }
|
onDismissRequest = { dialog = false }
|
||||||
)
|
)
|
||||||
|
if (activating) CircularProgressDialog { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,41 +195,46 @@ val activateOrgProfileCommand = "dpm mark-profile-owner-on-organization-owned-de
|
|||||||
|
|
||||||
@RequiresApi(30)
|
@RequiresApi(30)
|
||||||
@Composable
|
@Composable
|
||||||
fun SuspendPersonalAppScreen(onNavigateUp: () -> Unit) {
|
fun SuspendPersonalAppScreen(
|
||||||
|
getSuspendedReasons: () -> Int, setSuspended: (Boolean) -> Unit, getMaxTime: () -> Long,
|
||||||
|
setMaxTime: (Long) -> Unit, onNavigateUp: () -> Unit
|
||||||
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var suspend by remember { mutableStateOf(Privilege.DPM.getPersonalAppsSuspendedReasons(Privilege.DAR) != PERSONAL_APPS_NOT_SUSPENDED) }
|
var reason by remember { mutableIntStateOf(DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED) }
|
||||||
|
var time by remember { mutableStateOf("") }
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
reason = getSuspendedReasons()
|
||||||
|
time = getMaxTime().toString()
|
||||||
|
}
|
||||||
MyScaffold(R.string.suspend_personal_app, onNavigateUp) {
|
MyScaffold(R.string.suspend_personal_app, onNavigateUp) {
|
||||||
SwitchItem(R.string.suspend_personal_app, state = suspend,
|
SwitchItem(R.string.suspend_personal_app, state = reason != 0,
|
||||||
onCheckedChange = {
|
onCheckedChange = {
|
||||||
Privilege.DPM.setPersonalAppsSuspended(Privilege.DAR, it)
|
setSuspended(it)
|
||||||
suspend = Privilege.DPM.getPersonalAppsSuspendedReasons(Privilege.DAR) != PERSONAL_APPS_NOT_SUSPENDED
|
reason = if (it) DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY
|
||||||
|
else DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED
|
||||||
}, padding = false
|
}, padding = false
|
||||||
)
|
)
|
||||||
var time by remember { mutableStateOf("") }
|
|
||||||
time = Privilege.DPM.getManagedProfileMaximumTimeOff(Privilege.DAR).toString()
|
|
||||||
Spacer(Modifier.padding(vertical = 10.dp))
|
Spacer(Modifier.padding(vertical = 10.dp))
|
||||||
Text(text = stringResource(R.string.profile_max_time_off), style = typography.titleLarge)
|
Text(text = stringResource(R.string.profile_max_time_off), style = typography.titleLarge)
|
||||||
Text(text = stringResource(R.string.profile_max_time_out_desc))
|
Text(text = stringResource(R.string.profile_max_time_out_desc))
|
||||||
Text(
|
Text(stringResource(
|
||||||
text = stringResource(
|
|
||||||
R.string.personal_app_suspended_because_timeout,
|
R.string.personal_app_suspended_because_timeout,
|
||||||
Privilege.DPM.getPersonalAppsSuspendedReasons(Privilege.DAR) == PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT
|
stringResource((reason == DevicePolicyManager.PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT).yesOrNo)
|
||||||
)
|
))
|
||||||
)
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = time, onValueChange = { time=it }, modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp),
|
value = time, onValueChange = { time=it }, modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp),
|
||||||
label = { Text(stringResource(R.string.time_unit_ms)) },
|
label = { Text(stringResource(R.string.time_unit_ms)) },
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||||
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus() })
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus() })
|
||||||
)
|
)
|
||||||
Text(text = stringResource(R.string.cannot_less_than_72_hours))
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
Privilege.DPM.setManagedProfileMaximumTimeOff(Privilege.DAR, time.toLong())
|
setMaxTime(time.toLong())
|
||||||
context.showOperationResultToast(true)
|
context.showOperationResultToast(true)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
enabled = time.toLongOrNull() != null
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.apply))
|
Text(stringResource(R.string.apply))
|
||||||
}
|
}
|
||||||
@@ -241,14 +242,33 @@ fun SuspendPersonalAppScreen(onNavigateUp: () -> Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class IntentFilterOptions(
|
||||||
|
val action: String, val category: String, val mimeType: String,
|
||||||
|
val direction: IntentFilterDirection
|
||||||
|
)
|
||||||
|
enum class IntentFilterDirection(val text: Int) {
|
||||||
|
ToParent(R.string.work_to_personal), ToManaged(R.string.personal_to_work),
|
||||||
|
Both(R.string.both_direction)
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable object CrossProfileIntentFilter
|
@Serializable object CrossProfileIntentFilter
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun CrossProfileIntentFilterScreen(onNavigateUp: () -> Unit) {
|
fun CrossProfileIntentFilterScreen(
|
||||||
|
addFilter: (IntentFilterOptions) -> Unit,
|
||||||
|
onNavigateUp: () -> Unit
|
||||||
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
MyScaffold(R.string.intent_filter, onNavigateUp) {
|
|
||||||
var action by remember { mutableStateOf("") }
|
var action by remember { mutableStateOf("") }
|
||||||
|
var customCategory by remember { mutableStateOf(false) }
|
||||||
|
var category by remember { mutableStateOf("") }
|
||||||
|
var customMimeType by remember { mutableStateOf(false) }
|
||||||
|
var mimeType by remember { mutableStateOf("") }
|
||||||
|
var dropdown by remember { mutableStateOf(false) }
|
||||||
|
var direction by remember { mutableStateOf(IntentFilterDirection.Both) }
|
||||||
|
MyScaffold(R.string.intent_filter, onNavigateUp) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = action, onValueChange = { action = it },
|
value = action, onValueChange = { action = it },
|
||||||
label = { Text("Action") },
|
label = { Text("Action") },
|
||||||
@@ -256,32 +276,61 @@ fun CrossProfileIntentFilterScreen(onNavigateUp: () -> Unit) {
|
|||||||
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus() }),
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus() }),
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
Button(
|
Checkbox(customCategory, {
|
||||||
onClick = {
|
customCategory = it
|
||||||
Privilege.DPM.addCrossProfileIntentFilter(Privilege.DAR, IntentFilter(action), FLAG_PARENT_CAN_ACCESS_MANAGED)
|
category = ""
|
||||||
context.showOperationResultToast(true)
|
})
|
||||||
},
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth()
|
category, { category = it }, Modifier.fillMaxWidth(),
|
||||||
) {
|
label = { Text("Category") }, enabled = customCategory
|
||||||
Text(stringResource(R.string.add_intent_filter_work_to_personal))
|
)
|
||||||
|
}
|
||||||
|
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Checkbox(customMimeType, {
|
||||||
|
customMimeType = it
|
||||||
|
mimeType = ""
|
||||||
|
})
|
||||||
|
OutlinedTextField(
|
||||||
|
mimeType, { mimeType = it }, Modifier.fillMaxWidth(),
|
||||||
|
label = { Text("MIME type") }, enabled = customMimeType
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ExposedDropdownMenuBox(dropdown, { dropdown = it }, Modifier.padding(vertical = 5.dp)) {
|
||||||
|
OutlinedTextField(
|
||||||
|
stringResource(direction.text), {},
|
||||||
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
|
label = { Text(stringResource(R.string.direction)) }, readOnly = true,
|
||||||
|
trailingIcon = { ExpandExposedTextFieldIcon(dropdown) }
|
||||||
|
)
|
||||||
|
ExposedDropdownMenu(dropdown, { dropdown = false }) {
|
||||||
|
IntentFilterDirection.entries.forEach {
|
||||||
|
DropdownMenuItem({ Text(stringResource(it.text)) }, {
|
||||||
|
direction = it
|
||||||
|
dropdown = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
{
|
||||||
Privilege.DPM.addCrossProfileIntentFilter(Privilege.DAR, IntentFilter(action), FLAG_MANAGED_CAN_ACCESS_PARENT)
|
addFilter(IntentFilterOptions(
|
||||||
|
action, category, mimeType, direction
|
||||||
|
))
|
||||||
context.showOperationResultToast(true)
|
context.showOperationResultToast(true)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth()
|
Modifier.fillMaxWidth(),
|
||||||
|
enabled = action.isNotBlank() && (!customCategory || category.isNotBlank()) &&
|
||||||
|
(!customMimeType || mimeType.isNotBlank())
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.add_intent_filter_personal_to_work))
|
Text(stringResource(R.string.add))
|
||||||
}
|
}
|
||||||
Spacer(Modifier.padding(vertical = 2.dp))
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
Privilege.DPM.clearCrossProfileIntentFilters(Privilege.DAR)
|
Privilege.DPM.clearCrossProfileIntentFilters(Privilege.DAR)
|
||||||
context.showOperationResultToast(true)
|
context.showOperationResultToast(true)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.clear_cross_profile_filters))
|
Text(stringResource(R.string.clear_cross_profile_filters))
|
||||||
}
|
}
|
||||||
@@ -292,28 +341,34 @@ fun CrossProfileIntentFilterScreen(onNavigateUp: () -> Unit) {
|
|||||||
@Serializable object DeleteWorkProfile
|
@Serializable object DeleteWorkProfile
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DeleteWorkProfileScreen(onNavigateUp: () -> Unit) {
|
fun DeleteWorkProfileScreen(
|
||||||
|
deleteProfile: (Boolean, Int, String) -> Unit, onNavigateUp: () -> Unit
|
||||||
|
) {
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var flag by remember { mutableIntStateOf(0) }
|
var flags by remember { mutableIntStateOf(0) }
|
||||||
var warning by remember { mutableStateOf(false) }
|
var warning by remember { mutableStateOf(false) }
|
||||||
var silent by remember { mutableStateOf(false) }
|
|
||||||
var reason by remember { mutableStateOf("") }
|
var reason by remember { mutableStateOf("") }
|
||||||
MyScaffold(R.string.delete_work_profile, onNavigateUp) {
|
MyScaffold(R.string.delete_work_profile, onNavigateUp) {
|
||||||
CheckBoxItem(R.string.wipe_external_storage, flag and WIPE_EXTERNAL_STORAGE != 0) { flag = flag xor WIPE_EXTERNAL_STORAGE }
|
CheckBoxItem(R.string.wipe_external_storage, flags and WIPE_EXTERNAL_STORAGE != 0) {
|
||||||
if(VERSION.SDK_INT >= 28) CheckBoxItem(R.string.wipe_euicc, flag and WIPE_EUICC != 0) { flag = flag xor WIPE_EUICC }
|
flags = flags xor WIPE_EXTERNAL_STORAGE
|
||||||
CheckBoxItem(R.string.wipe_silently, silent) { silent = it }
|
}
|
||||||
AnimatedVisibility(!silent && VERSION.SDK_INT >= 28) {
|
if(VERSION.SDK_INT >= 28) CheckBoxItem(R.string.wipe_euicc, flags and WIPE_EUICC != 0) {
|
||||||
OutlinedTextField(
|
flags = flags xor WIPE_EUICC
|
||||||
|
}
|
||||||
|
CheckBoxItem(R.string.wipe_silently, flags and DevicePolicyManager.WIPE_SILENTLY != 0) {
|
||||||
|
flags = flags xor DevicePolicyManager.WIPE_SILENTLY
|
||||||
|
reason = ""
|
||||||
|
}
|
||||||
|
if (VERSION.SDK_INT >= 28) OutlinedTextField(
|
||||||
value = reason, onValueChange = { reason = it },
|
value = reason, onValueChange = { reason = it },
|
||||||
label = { Text(stringResource(R.string.reason)) },
|
label = { Text(stringResource(R.string.reason)) },
|
||||||
|
enabled = flags and DevicePolicyManager.WIPE_SILENTLY == 0,
|
||||||
modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp)
|
modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp)
|
||||||
)
|
)
|
||||||
}
|
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Spacer(Modifier.padding(vertical = 5.dp))
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
focusMgr.clearFocus()
|
focusMgr.clearFocus()
|
||||||
silent = reason == ""
|
|
||||||
warning = true
|
warning = true
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
||||||
@@ -323,7 +378,6 @@ fun DeleteWorkProfileScreen(onNavigateUp: () -> Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (warning) {
|
if (warning) {
|
||||||
LaunchedEffect(Unit) { silent = reason == "" }
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title = {
|
title = {
|
||||||
Text(text = stringResource(R.string.warning), color = colorScheme.error)
|
Text(text = stringResource(R.string.warning), color = colorScheme.error)
|
||||||
@@ -335,11 +389,7 @@ fun DeleteWorkProfileScreen(onNavigateUp: () -> Unit) {
|
|||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
if(VERSION.SDK_INT >= 28 && !silent) {
|
deleteProfile(false, flags, reason)
|
||||||
Privilege.DPM.wipeData(flag, reason)
|
|
||||||
} else {
|
|
||||||
Privilege.DPM.wipeData(flag)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
|
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -75,7 +75,6 @@
|
|||||||
<string name="profile_owner">Владелец профиля</string>
|
<string name="profile_owner">Владелец профиля</string>
|
||||||
<string name="device_owner">Владелец устройства</string>
|
<string name="device_owner">Владелец устройства</string>
|
||||||
<string name="delegated_admins">Делегированные администраторы</string>
|
<string name="delegated_admins">Делегированные администраторы</string>
|
||||||
<string name="delegated_scope">делегированные возможности</string>
|
|
||||||
<string name="manage_application_restrictions">Управление ограничениями для приложений</string>
|
<string name="manage_application_restrictions">Управление ограничениями для приложений</string>
|
||||||
<string name="manage_certificates">Управление сертификатами</string>
|
<string name="manage_certificates">Управление сертификатами</string>
|
||||||
<string name="select_keychain_certificates">Выберите сертификат связки ключей</string>
|
<string name="select_keychain_certificates">Выберите сертификат связки ключей</string>
|
||||||
@@ -101,7 +100,6 @@
|
|||||||
<string name="disable_account_management">Отключить управление аккаунтами</string>
|
<string name="disable_account_management">Отключить управление аккаунтами</string>
|
||||||
<string name="account_type">Тип аккаунта</string>
|
<string name="account_type">Тип аккаунта</string>
|
||||||
<string name="transfer_ownership">Передача прав владения</string>
|
<string name="transfer_ownership">Передача прав владения</string>
|
||||||
<string name="target_component_name">Имя целевого компонента</string>
|
|
||||||
<string name="lock_screen_info">Информация на экране блокировки</string>
|
<string name="lock_screen_info">Информация на экране блокировки</string>
|
||||||
<string name="support_messages">Сообщение поддержки</string>
|
<string name="support_messages">Сообщение поддержки</string>
|
||||||
<string name="short_support_msg">Краткое сообщение</string>
|
<string name="short_support_msg">Краткое сообщение</string>
|
||||||
@@ -212,8 +210,6 @@
|
|||||||
<string name="update_received_time">Время получения обновления: %1$s</string>
|
<string name="update_received_time">Время получения обновления: %1$s</string>
|
||||||
<string name="install_system_update">Установить системное обновление</string>
|
<string name="install_system_update">Установить системное обновление</string>
|
||||||
<string name="select_ota_package" tools:ignore="TypographyEllipsis">Выберите OTA-пакет...</string>
|
<string name="select_ota_package" tools:ignore="TypographyEllipsis">Выберите OTA-пакет...</string>
|
||||||
<string name="start_install_system_update">Начать установку системного обновления</string>
|
|
||||||
<string name="install_system_update_failed">Установка системного обновления не удалась: </string>
|
|
||||||
<string name="battery_low">Низкий заряд батареи</string>
|
<string name="battery_low">Низкий заряд батареи</string>
|
||||||
<string name="update_file_invalid">Файл обновления недействителен</string>
|
<string name="update_file_invalid">Файл обновления недействителен</string>
|
||||||
<string name="incorrect_os_ver">Неверная версия ОС</string>
|
<string name="incorrect_os_ver">Неверная версия ОС</string>
|
||||||
@@ -339,10 +335,7 @@
|
|||||||
<string name="profile_max_time_off">Максимальное время отключения</string>
|
<string name="profile_max_time_off">Максимальное время отключения</string>
|
||||||
<string name="profile_max_time_out_desc">Личные приложения будут приостановлены после закрытия рабочего профиля на указанное время. 0 означает отсутствие ограничения.</string>
|
<string name="profile_max_time_out_desc">Личные приложения будут приостановлены после закрытия рабочего профиля на указанное время. 0 означает отсутствие ограничения.</string>
|
||||||
<string name="personal_app_suspended_because_timeout">Личное приложение приостановлено по причине: %1$s</string>
|
<string name="personal_app_suspended_because_timeout">Личное приложение приостановлено по причине: %1$s</string>
|
||||||
<string name="cannot_less_than_72_hours">Не может быть меньше 72 часов</string>
|
|
||||||
<string name="intent_filter">Фильтр намерений</string>
|
<string name="intent_filter">Фильтр намерений</string>
|
||||||
<string name="add_intent_filter_work_to_personal">Добавить (из рабочего в личный)</string>
|
|
||||||
<string name="add_intent_filter_personal_to_work">Добавить (из личного в рабочий)</string>
|
|
||||||
<string name="clear_cross_profile_filters">Очистить все фильтры</string>
|
<string name="clear_cross_profile_filters">Очистить все фильтры</string>
|
||||||
<string name="org_id">Идентификатор организации</string>
|
<string name="org_id">Идентификатор организации</string>
|
||||||
<string name="length_6_to_64">Длина должна быть от 6 до 64 символов</string>
|
<string name="length_6_to_64">Длина должна быть от 6 до 64 символов</string>
|
||||||
|
|||||||
@@ -76,7 +76,6 @@
|
|||||||
<string name="profile_owner">Profil Sahibi</string>
|
<string name="profile_owner">Profil Sahibi</string>
|
||||||
<string name="device_owner">Cihaz Sahibi</string>
|
<string name="device_owner">Cihaz Sahibi</string>
|
||||||
<string name="delegated_admins">Yetkilendirilmiş Yöneticiler</string>
|
<string name="delegated_admins">Yetkilendirilmiş Yöneticiler</string>
|
||||||
<string name="delegated_scope">Yetkilendirilmiş Kapsam</string>
|
|
||||||
<string name="manage_application_restrictions">Uygulama Kısıtlamalarını Yönet</string>
|
<string name="manage_application_restrictions">Uygulama Kısıtlamalarını Yönet</string>
|
||||||
<string name="manage_certificates">Sertifikaları Yönet</string>
|
<string name="manage_certificates">Sertifikaları Yönet</string>
|
||||||
<string name="select_keychain_certificates">KeyChain Sertifikasını Seç</string>
|
<string name="select_keychain_certificates">KeyChain Sertifikasını Seç</string>
|
||||||
@@ -102,7 +101,6 @@
|
|||||||
<string name="disable_account_management">Hesap Yönetimini Devre Dışı Bırak</string>
|
<string name="disable_account_management">Hesap Yönetimini Devre Dışı Bırak</string>
|
||||||
<string name="account_type">Hesap Türü</string>
|
<string name="account_type">Hesap Türü</string>
|
||||||
<string name="transfer_ownership">Sahipliği Devret</string>
|
<string name="transfer_ownership">Sahipliği Devret</string>
|
||||||
<string name="target_component_name">Hedef Bileşen Adı</string>
|
|
||||||
<string name="lock_screen_info">Kilit Ekranı Bilgisi</string>
|
<string name="lock_screen_info">Kilit Ekranı Bilgisi</string>
|
||||||
<string name="support_messages">Destek Mesajları</string>
|
<string name="support_messages">Destek Mesajları</string>
|
||||||
<string name="short_support_msg">Kısa Mesaj</string>
|
<string name="short_support_msg">Kısa Mesaj</string>
|
||||||
@@ -243,8 +241,6 @@
|
|||||||
|
|
||||||
<string name="install_system_update">Sistem Güncellemesini Yükle</string>
|
<string name="install_system_update">Sistem Güncellemesini Yükle</string>
|
||||||
<string name="select_ota_package" tools:ignore="TypographyEllipsis">OTA paketini seç...</string>
|
<string name="select_ota_package" tools:ignore="TypographyEllipsis">OTA paketini seç...</string>
|
||||||
<string name="start_install_system_update">Sistem güncellemesini yüklemeye başla</string>
|
|
||||||
<string name="install_system_update_failed">"Sistem güncellemesi yüklenemedi: "</string>
|
|
||||||
<string name="battery_low">Pil seviyesi düşük</string>
|
<string name="battery_low">Pil seviyesi düşük</string>
|
||||||
<string name="update_file_invalid">Güncelleme dosyası geçersiz</string>
|
<string name="update_file_invalid">Güncelleme dosyası geçersiz</string>
|
||||||
<string name="incorrect_os_ver">Yanlış işletim sistemi sürümü</string>
|
<string name="incorrect_os_ver">Yanlış işletim sistemi sürümü</string>
|
||||||
@@ -365,10 +361,7 @@
|
|||||||
<string name="profile_max_time_off">Maksimum Kapalı Kalma Süresi</string>
|
<string name="profile_max_time_off">Maksimum Kapalı Kalma Süresi</string>
|
||||||
<string name="profile_max_time_out_desc">İş profili kapatıldıktan sonra kişisel uygulamalar bu süre boyunca askıya alınacak. 0, sınırsız anlamına gelir.</string>
|
<string name="profile_max_time_out_desc">İş profili kapatıldıktan sonra kişisel uygulamalar bu süre boyunca askıya alınacak. 0, sınırsız anlamına gelir.</string>
|
||||||
<string name="personal_app_suspended_because_timeout">Kişisel uygulama şu nedenle askıya alındı: %1$s</string>
|
<string name="personal_app_suspended_because_timeout">Kişisel uygulama şu nedenle askıya alındı: %1$s</string>
|
||||||
<string name="cannot_less_than_72_hours">72 saatten az olamaz</string>
|
|
||||||
<string name="intent_filter">Niyet Filtresi</string>
|
<string name="intent_filter">Niyet Filtresi</string>
|
||||||
<string name="add_intent_filter_work_to_personal">Ekle (işten kişisel profile)</string>
|
|
||||||
<string name="add_intent_filter_personal_to_work">Ekle (kişisel profilden işe)</string>
|
|
||||||
<string name="clear_cross_profile_filters">Tüm filtreleri temizle</string>
|
<string name="clear_cross_profile_filters">Tüm filtreleri temizle</string>
|
||||||
<string name="org_id">Kurum Kimliği</string>
|
<string name="org_id">Kurum Kimliği</string>
|
||||||
<string name="length_6_to_64">Uzunluk 6 ile 64 karakter arasında olmalıdır</string>
|
<string name="length_6_to_64">Uzunluk 6 ile 64 karakter arasında olmalıdır</string>
|
||||||
|
|||||||
@@ -74,7 +74,6 @@
|
|||||||
<string name="profile_owner">Profile owner</string>
|
<string name="profile_owner">Profile owner</string>
|
||||||
<string name="device_owner">Device owner</string>
|
<string name="device_owner">Device owner</string>
|
||||||
<string name="delegated_admins">委托管理员</string>
|
<string name="delegated_admins">委托管理员</string>
|
||||||
<string name="delegated_scope">委托作用域</string>
|
|
||||||
<string name="manage_application_restrictions">管理应用限制</string>
|
<string name="manage_application_restrictions">管理应用限制</string>
|
||||||
<string name="manage_certificates">管理证书</string>
|
<string name="manage_certificates">管理证书</string>
|
||||||
<string name="select_keychain_certificates">选择密钥链证书</string>
|
<string name="select_keychain_certificates">选择密钥链证书</string>
|
||||||
@@ -99,7 +98,6 @@
|
|||||||
<string name="disable_account_management">禁用账号管理</string>
|
<string name="disable_account_management">禁用账号管理</string>
|
||||||
<string name="account_type">账号类型</string>
|
<string name="account_type">账号类型</string>
|
||||||
<string name="transfer_ownership">转移所有权</string>
|
<string name="transfer_ownership">转移所有权</string>
|
||||||
<string name="target_component_name">目标组件名</string>
|
|
||||||
<string name="lock_screen_info">锁屏提示信息</string>
|
<string name="lock_screen_info">锁屏提示信息</string>
|
||||||
<string name="support_messages">提供支持的消息</string>
|
<string name="support_messages">提供支持的消息</string>
|
||||||
<string name="short_support_msg">提供支持的短消息</string>
|
<string name="short_support_msg">提供支持的短消息</string>
|
||||||
@@ -221,8 +219,6 @@
|
|||||||
<string name="update_received_time">系统更新接收时间: %1$s</string>
|
<string name="update_received_time">系统更新接收时间: %1$s</string>
|
||||||
<string name="install_system_update">安装系统更新</string>
|
<string name="install_system_update">安装系统更新</string>
|
||||||
<string name="select_ota_package" tools:ignore="TypographyEllipsis">选择OTA包...</string>
|
<string name="select_ota_package" tools:ignore="TypographyEllipsis">选择OTA包...</string>
|
||||||
<string name="start_install_system_update">开始安装系统更新</string>
|
|
||||||
<string name="install_system_update_failed">安装系统更新失败:</string>
|
|
||||||
<string name="battery_low">电量低</string>
|
<string name="battery_low">电量低</string>
|
||||||
<string name="update_file_invalid">OTA包无效</string>
|
<string name="update_file_invalid">OTA包无效</string>
|
||||||
<string name="incorrect_os_ver">系统版本错误</string>
|
<string name="incorrect_os_ver">系统版本错误</string>
|
||||||
@@ -343,10 +339,11 @@
|
|||||||
<string name="profile_max_time_off">资料关闭时间</string>
|
<string name="profile_max_time_off">资料关闭时间</string>
|
||||||
<string name="profile_max_time_out_desc">工作资料处于关闭状态的时间达到该限制后会挂起个人应用,0为无限制</string>
|
<string name="profile_max_time_out_desc">工作资料处于关闭状态的时间达到该限制后会挂起个人应用,0为无限制</string>
|
||||||
<string name="personal_app_suspended_because_timeout">个人应用已经因此挂起:%1$s</string>
|
<string name="personal_app_suspended_because_timeout">个人应用已经因此挂起:%1$s</string>
|
||||||
<string name="cannot_less_than_72_hours">不能少于72小时</string>
|
|
||||||
<string name="intent_filter">Intent过滤器</string>
|
<string name="intent_filter">Intent过滤器</string>
|
||||||
<string name="add_intent_filter_work_to_personal">添加(工作到个人)</string>
|
<string name="direction">方向</string>
|
||||||
<string name="add_intent_filter_personal_to_work">添加(个人到工作)</string>
|
<string name="both_direction">双向</string>
|
||||||
|
<string name="work_to_personal">工作到个人</string>
|
||||||
|
<string name="personal_to_work">个人到工作</string>
|
||||||
<string name="clear_cross_profile_filters">清除所有过滤器</string>
|
<string name="clear_cross_profile_filters">清除所有过滤器</string>
|
||||||
<string name="org_id">组织ID</string>
|
<string name="org_id">组织ID</string>
|
||||||
<string name="length_6_to_64">长度应在6~64个字符之间</string>
|
<string name="length_6_to_64">长度应在6~64个字符之间</string>
|
||||||
|
|||||||
@@ -79,7 +79,6 @@
|
|||||||
<string name="profile_owner">Profile owner</string>
|
<string name="profile_owner">Profile owner</string>
|
||||||
<string name="device_owner">Device owner</string>
|
<string name="device_owner">Device owner</string>
|
||||||
<string name="delegated_admins">Delegated admins</string>
|
<string name="delegated_admins">Delegated admins</string>
|
||||||
<string name="delegated_scope">delegated scope</string>
|
|
||||||
<string name="manage_application_restrictions">Manage application restrictions</string>
|
<string name="manage_application_restrictions">Manage application restrictions</string>
|
||||||
<string name="manage_certificates">Manage certificates</string>
|
<string name="manage_certificates">Manage certificates</string>
|
||||||
<string name="select_keychain_certificates">Select KeyChain certificate</string>
|
<string name="select_keychain_certificates">Select KeyChain certificate</string>
|
||||||
@@ -105,7 +104,6 @@
|
|||||||
<string name="disable_account_management">Disable account management</string>
|
<string name="disable_account_management">Disable account management</string>
|
||||||
<string name="account_type">Account type</string>
|
<string name="account_type">Account type</string>
|
||||||
<string name="transfer_ownership">Transfer Ownership</string>
|
<string name="transfer_ownership">Transfer Ownership</string>
|
||||||
<string name="target_component_name">Target component name</string>
|
|
||||||
<string name="lock_screen_info">Lock screen info</string>
|
<string name="lock_screen_info">Lock screen info</string>
|
||||||
<string name="support_messages">Support Messages</string>
|
<string name="support_messages">Support Messages</string>
|
||||||
<string name="short_support_msg">Short message</string>
|
<string name="short_support_msg">Short message</string>
|
||||||
@@ -249,8 +247,6 @@
|
|||||||
|
|
||||||
<string name="install_system_update">Install system update</string>
|
<string name="install_system_update">Install system update</string>
|
||||||
<string name="select_ota_package" tools:ignore="TypographyEllipsis">Select OTA package...</string>
|
<string name="select_ota_package" tools:ignore="TypographyEllipsis">Select OTA package...</string>
|
||||||
<string name="start_install_system_update">Start installing system update</string>
|
|
||||||
<string name="install_system_update_failed">"Install system update failed: "</string>
|
|
||||||
<string name="battery_low">Battery is low</string>
|
<string name="battery_low">Battery is low</string>
|
||||||
<string name="update_file_invalid">Update file is invalid</string>
|
<string name="update_file_invalid">Update file is invalid</string>
|
||||||
<string name="incorrect_os_ver">Incorrect OS version</string>
|
<string name="incorrect_os_ver">Incorrect OS version</string>
|
||||||
@@ -374,10 +370,11 @@
|
|||||||
<string name="profile_max_time_off">Max time off</string>
|
<string name="profile_max_time_off">Max time off</string>
|
||||||
<string name="profile_max_time_out_desc">Personal apps will be suspended after the work profile is closed for this amount of time. 0 means no limit. </string>
|
<string name="profile_max_time_out_desc">Personal apps will be suspended after the work profile is closed for this amount of time. 0 means no limit. </string>
|
||||||
<string name="personal_app_suspended_because_timeout">Personal app suspended because of this: %1$s</string>
|
<string name="personal_app_suspended_because_timeout">Personal app suspended because of this: %1$s</string>
|
||||||
<string name="cannot_less_than_72_hours">Cannot less than 72 hours</string>
|
|
||||||
<string name="intent_filter">Intent filter</string>
|
<string name="intent_filter">Intent filter</string>
|
||||||
<string name="add_intent_filter_work_to_personal">Add(work to personal)</string>
|
<string name="direction">Direction</string>
|
||||||
<string name="add_intent_filter_personal_to_work">Add(personal to work)</string>
|
<string name="both_direction">Both direction</string>
|
||||||
|
<string name="work_to_personal">Work to personal</string>
|
||||||
|
<string name="personal_to_work">Personal to work</string>
|
||||||
<string name="clear_cross_profile_filters">Clear all filters</string>
|
<string name="clear_cross_profile_filters">Clear all filters</string>
|
||||||
<string name="org_id">Organization ID</string>
|
<string name="org_id">Organization ID</string>
|
||||||
<string name="length_6_to_64">The length should be between 6~64 characters</string>
|
<string name="length_6_to_64">The length should be between 6~64 characters</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user