mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 02:56:01 +00:00
feat: refactor navigation, use navigation3 library
Fix global settings crash (#237)
This commit is contained in:
@@ -89,12 +89,13 @@ gradle.taskGraph.whenReady {
|
||||
dependencies {
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.nav3.runtime)
|
||||
implementation(libs.androidx.nav3.ui)
|
||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||
implementation(libs.accompanist.drawablepainter)
|
||||
implementation(libs.accompanist.permissions)
|
||||
implementation(libs.androidx.material3)
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
implementation(libs.material.icons.core)
|
||||
implementation(libs.shizuku.provider)
|
||||
implementation(libs.shizuku.api)
|
||||
|
||||
@@ -9,30 +9,13 @@ import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -41,207 +24,21 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.toRoute
|
||||
import com.bintianqi.owndroid.dpm.AddApnSetting
|
||||
import com.bintianqi.owndroid.dpm.AddApnSettingScreen
|
||||
import com.bintianqi.owndroid.dpm.AddDelegatedAdmin
|
||||
import com.bintianqi.owndroid.dpm.AddDelegatedAdminScreen
|
||||
import com.bintianqi.owndroid.dpm.AddPreferentialNetworkServiceConfig
|
||||
import com.bintianqi.owndroid.dpm.AddPreferentialNetworkServiceConfigScreen
|
||||
import com.bintianqi.owndroid.dpm.AffiliationId
|
||||
import com.bintianqi.owndroid.dpm.AffiliationIdScreen
|
||||
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackage
|
||||
import com.bintianqi.owndroid.dpm.AlwaysOnVpnPackageScreen
|
||||
import com.bintianqi.owndroid.dpm.ApplicationDetails
|
||||
import com.bintianqi.owndroid.dpm.ApplicationDetailsScreen
|
||||
import com.bintianqi.owndroid.dpm.ApplicationsFeatures
|
||||
import com.bintianqi.owndroid.dpm.ApplicationsFeaturesScreen
|
||||
import com.bintianqi.owndroid.dpm.AutoTimePolicy
|
||||
import com.bintianqi.owndroid.dpm.AutoTimePolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.AutoTimeZonePolicy
|
||||
import com.bintianqi.owndroid.dpm.AutoTimeZonePolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.BlockUninstall
|
||||
import com.bintianqi.owndroid.dpm.CaCert
|
||||
import com.bintianqi.owndroid.dpm.CaCertScreen
|
||||
import com.bintianqi.owndroid.dpm.ChangeTime
|
||||
import com.bintianqi.owndroid.dpm.ChangeTimeScreen
|
||||
import com.bintianqi.owndroid.dpm.ChangeTimeZone
|
||||
import com.bintianqi.owndroid.dpm.ChangeTimeZoneScreen
|
||||
import com.bintianqi.owndroid.dpm.ChangeUsername
|
||||
import com.bintianqi.owndroid.dpm.ChangeUsernameScreen
|
||||
import com.bintianqi.owndroid.dpm.ClearAppStorage
|
||||
import com.bintianqi.owndroid.dpm.ClearAppStorageScreen
|
||||
import com.bintianqi.owndroid.dpm.ContentProtectionPolicy
|
||||
import com.bintianqi.owndroid.dpm.ContentProtectionPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.CreateUser
|
||||
import com.bintianqi.owndroid.dpm.CreateUserScreen
|
||||
import com.bintianqi.owndroid.dpm.CreateWorkProfile
|
||||
import com.bintianqi.owndroid.dpm.CreateWorkProfileScreen
|
||||
import com.bintianqi.owndroid.dpm.CredentialManagerPolicy
|
||||
import com.bintianqi.owndroid.dpm.CredentialManagerPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileIntentFilter
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileIntentFilterScreen
|
||||
import com.bintianqi.owndroid.dpm.CrossProfilePackages
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileWidgetProviders
|
||||
import com.bintianqi.owndroid.dpm.DefaultInputMethod
|
||||
import com.bintianqi.owndroid.dpm.DefaultInputMethodScreen
|
||||
import com.bintianqi.owndroid.dpm.DelegatedAdmins
|
||||
import com.bintianqi.owndroid.dpm.DelegatedAdminsScreen
|
||||
import com.bintianqi.owndroid.dpm.DeleteWorkProfile
|
||||
import com.bintianqi.owndroid.dpm.DeleteWorkProfileScreen
|
||||
import com.bintianqi.owndroid.dpm.DeviceInfo
|
||||
import com.bintianqi.owndroid.dpm.DeviceInfoScreen
|
||||
import com.bintianqi.owndroid.dpm.DhizukuServerSettings
|
||||
import com.bintianqi.owndroid.dpm.DhizukuServerSettingsScreen
|
||||
import com.bintianqi.owndroid.dpm.DisableAccountManagement
|
||||
import com.bintianqi.owndroid.dpm.DisableAccountManagementScreen
|
||||
import com.bintianqi.owndroid.dpm.DisableMeteredData
|
||||
import com.bintianqi.owndroid.dpm.DisableUserControl
|
||||
import com.bintianqi.owndroid.dpm.EditAppGroup
|
||||
import com.bintianqi.owndroid.dpm.EditAppGroupScreen
|
||||
import com.bintianqi.owndroid.dpm.EnableSystemApp
|
||||
import com.bintianqi.owndroid.dpm.EnableSystemAppScreen
|
||||
import com.bintianqi.owndroid.dpm.FrpPolicy
|
||||
import com.bintianqi.owndroid.dpm.FrpPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.HardwareMonitor
|
||||
import com.bintianqi.owndroid.dpm.HardwareMonitorScreen
|
||||
import com.bintianqi.owndroid.dpm.Hide
|
||||
import com.bintianqi.owndroid.dpm.InstallExistingApp
|
||||
import com.bintianqi.owndroid.dpm.InstallExistingAppScreen
|
||||
import com.bintianqi.owndroid.dpm.InstallSystemUpdate
|
||||
import com.bintianqi.owndroid.dpm.InstallSystemUpdateScreen
|
||||
import com.bintianqi.owndroid.dpm.KeepUninstalledPackages
|
||||
import com.bintianqi.owndroid.dpm.Keyguard
|
||||
import com.bintianqi.owndroid.dpm.KeyguardDisabledFeatures
|
||||
import com.bintianqi.owndroid.dpm.KeyguardDisabledFeaturesScreen
|
||||
import com.bintianqi.owndroid.dpm.KeyguardScreen
|
||||
import com.bintianqi.owndroid.dpm.LockScreenInfo
|
||||
import com.bintianqi.owndroid.dpm.LockScreenInfoScreen
|
||||
import com.bintianqi.owndroid.dpm.LockTaskMode
|
||||
import com.bintianqi.owndroid.dpm.LockTaskModeScreen
|
||||
import com.bintianqi.owndroid.dpm.ManageAppGroups
|
||||
import com.bintianqi.owndroid.dpm.ManageAppGroupsScreen
|
||||
import com.bintianqi.owndroid.dpm.ManagedConfiguration
|
||||
import com.bintianqi.owndroid.dpm.ManagedConfigurationScreen
|
||||
import com.bintianqi.owndroid.dpm.MtePolicy
|
||||
import com.bintianqi.owndroid.dpm.MtePolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.NearbyStreamingPolicy
|
||||
import com.bintianqi.owndroid.dpm.NearbyStreamingPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.Network
|
||||
import com.bintianqi.owndroid.dpm.NetworkLogging
|
||||
import com.bintianqi.owndroid.dpm.NetworkLoggingScreen
|
||||
import com.bintianqi.owndroid.dpm.NetworkOptions
|
||||
import com.bintianqi.owndroid.dpm.NetworkOptionsScreen
|
||||
import com.bintianqi.owndroid.dpm.NetworkScreen
|
||||
import com.bintianqi.owndroid.dpm.NetworkStatsScreen
|
||||
import com.bintianqi.owndroid.dpm.NetworkStatsViewer
|
||||
import com.bintianqi.owndroid.dpm.NetworkStatsViewerScreen
|
||||
import com.bintianqi.owndroid.dpm.OrganizationOwnedProfile
|
||||
import com.bintianqi.owndroid.dpm.OrganizationOwnedProfileScreen
|
||||
import com.bintianqi.owndroid.dpm.OverrideApn
|
||||
import com.bintianqi.owndroid.dpm.OverrideApnScreen
|
||||
import com.bintianqi.owndroid.dpm.PackageFunctionScreen
|
||||
import com.bintianqi.owndroid.dpm.Password
|
||||
import com.bintianqi.owndroid.dpm.PasswordInfo
|
||||
import com.bintianqi.owndroid.dpm.PasswordInfoScreen
|
||||
import com.bintianqi.owndroid.dpm.PasswordScreen
|
||||
import com.bintianqi.owndroid.dpm.PermissionPolicy
|
||||
import com.bintianqi.owndroid.dpm.PermissionPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.AppPermissionsManager
|
||||
import com.bintianqi.owndroid.dpm.AppPermissionsManagerScreen
|
||||
import com.bintianqi.owndroid.dpm.PermissionDetail
|
||||
import com.bintianqi.owndroid.dpm.PermissionDetailScreen
|
||||
import com.bintianqi.owndroid.dpm.PermissionManager
|
||||
import com.bintianqi.owndroid.dpm.PermissionManagerScreen
|
||||
import com.bintianqi.owndroid.dpm.PermittedAccessibilityServices
|
||||
import com.bintianqi.owndroid.dpm.PermittedAsAndImPackages
|
||||
import com.bintianqi.owndroid.dpm.PermittedInputMethods
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkService
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkServiceInfo
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkServiceScreen
|
||||
import com.bintianqi.owndroid.dpm.PrivateDns
|
||||
import com.bintianqi.owndroid.dpm.PrivateDnsScreen
|
||||
import com.bintianqi.owndroid.dpm.QueryNetworkStats
|
||||
import com.bintianqi.owndroid.dpm.RecommendedGlobalProxy
|
||||
import com.bintianqi.owndroid.dpm.RecommendedGlobalProxyScreen
|
||||
import com.bintianqi.owndroid.dpm.RequiredPasswordComplexity
|
||||
import com.bintianqi.owndroid.dpm.RequiredPasswordComplexityScreen
|
||||
import com.bintianqi.owndroid.dpm.RequiredPasswordQuality
|
||||
import com.bintianqi.owndroid.dpm.RequiredPasswordQualityScreen
|
||||
import com.bintianqi.owndroid.dpm.ResetPassword
|
||||
import com.bintianqi.owndroid.dpm.ResetPasswordScreen
|
||||
import com.bintianqi.owndroid.dpm.ResetPasswordToken
|
||||
import com.bintianqi.owndroid.dpm.ResetPasswordTokenScreen
|
||||
import com.bintianqi.owndroid.dpm.SecurityLogging
|
||||
import com.bintianqi.owndroid.dpm.SecurityLoggingScreen
|
||||
import com.bintianqi.owndroid.dpm.SetDefaultDialer
|
||||
import com.bintianqi.owndroid.dpm.SetDefaultDialerScreen
|
||||
import com.bintianqi.owndroid.dpm.SetSystemUpdatePolicy
|
||||
import com.bintianqi.owndroid.dpm.SupportMessage
|
||||
import com.bintianqi.owndroid.dpm.SupportMessageScreen
|
||||
import com.bintianqi.owndroid.dpm.Suspend
|
||||
import com.bintianqi.owndroid.dpm.SuspendPersonalApp
|
||||
import com.bintianqi.owndroid.dpm.SuspendPersonalAppScreen
|
||||
import com.bintianqi.owndroid.dpm.SystemManager
|
||||
import com.bintianqi.owndroid.dpm.SystemManagerScreen
|
||||
import com.bintianqi.owndroid.dpm.SystemOptions
|
||||
import com.bintianqi.owndroid.dpm.SystemOptionsScreen
|
||||
import com.bintianqi.owndroid.dpm.SystemUpdatePolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.TransferOwnership
|
||||
import com.bintianqi.owndroid.dpm.TransferOwnershipScreen
|
||||
import com.bintianqi.owndroid.dpm.UninstallApp
|
||||
import com.bintianqi.owndroid.dpm.UninstallAppScreen
|
||||
import com.bintianqi.owndroid.dpm.UpdateNetwork
|
||||
import com.bintianqi.owndroid.dpm.UpdateNetworkScreen
|
||||
import com.bintianqi.owndroid.dpm.UserInfo
|
||||
import com.bintianqi.owndroid.dpm.UserInfoScreen
|
||||
import com.bintianqi.owndroid.dpm.UserOperation
|
||||
import com.bintianqi.owndroid.dpm.UserOperationScreen
|
||||
import com.bintianqi.owndroid.dpm.UserRestriction
|
||||
import com.bintianqi.owndroid.dpm.UserRestrictionEditor
|
||||
import com.bintianqi.owndroid.dpm.UserRestrictionEditorScreen
|
||||
import com.bintianqi.owndroid.dpm.UserRestrictionOptions
|
||||
import com.bintianqi.owndroid.dpm.UserRestrictionOptionsScreen
|
||||
import com.bintianqi.owndroid.dpm.UserRestrictionScreen
|
||||
import com.bintianqi.owndroid.dpm.UserSessionMessage
|
||||
import com.bintianqi.owndroid.dpm.UserSessionMessageScreen
|
||||
import com.bintianqi.owndroid.dpm.Users
|
||||
import com.bintianqi.owndroid.dpm.UsersOptions
|
||||
import com.bintianqi.owndroid.dpm.UsersOptionsScreen
|
||||
import com.bintianqi.owndroid.dpm.UsersScreen
|
||||
import com.bintianqi.owndroid.dpm.WiFi
|
||||
import com.bintianqi.owndroid.dpm.WifiScreen
|
||||
import com.bintianqi.owndroid.dpm.WifiSecurityLevel
|
||||
import com.bintianqi.owndroid.dpm.WifiSecurityLevelScreen
|
||||
import com.bintianqi.owndroid.dpm.WifiSsidPolicyScreen
|
||||
import com.bintianqi.owndroid.dpm.WipeData
|
||||
import com.bintianqi.owndroid.dpm.WipeDataScreen
|
||||
import com.bintianqi.owndroid.dpm.WorkModes
|
||||
import com.bintianqi.owndroid.dpm.WorkModesScreen
|
||||
import com.bintianqi.owndroid.dpm.WorkProfile
|
||||
import com.bintianqi.owndroid.dpm.WorkProfileScreen
|
||||
import androidx.navigation3.runtime.rememberNavBackStack
|
||||
import androidx.navigation3.ui.NavDisplay
|
||||
import com.bintianqi.owndroid.dpm.dhizukuErrorStatus
|
||||
import com.bintianqi.owndroid.ui.NavTransition
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.bintianqi.owndroid.ui.navigation.myEntryProvider
|
||||
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.Locale
|
||||
|
||||
@ExperimentalMaterial3Api
|
||||
@@ -267,589 +64,61 @@ class MainActivity : FragmentActivity() {
|
||||
var appLockDialog by rememberSaveable { mutableStateOf(false) }
|
||||
val theme by vm.theme.collectAsStateWithLifecycle()
|
||||
OwnDroidTheme(theme) {
|
||||
Home(vm) { appLockDialog = true }
|
||||
Box(Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background))
|
||||
val backstack = rememberNavBackStack(Destination.Home)
|
||||
NavDisplay(
|
||||
backstack,
|
||||
onBack = {
|
||||
backstack.removeLastOrNull()
|
||||
},
|
||||
transitionSpec = {
|
||||
NavTransition.transition
|
||||
},
|
||||
popTransitionSpec = {
|
||||
NavTransition.popTransition
|
||||
},
|
||||
predictivePopTransitionSpec = {
|
||||
NavTransition.popTransition
|
||||
}
|
||||
) {
|
||||
myEntryProvider(it as Destination, backstack, vm)
|
||||
}
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
if (appLockDialog) {
|
||||
AppLockDialog({ appLockDialog = false }) { moveTaskToBack(true) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ExperimentalMaterial3Api
|
||||
@Composable
|
||||
fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
||||
val navController = rememberNavController()
|
||||
val context = LocalContext.current
|
||||
val focusMgr = LocalFocusManager.current
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
fun navigateUp() { navController.navigateUp() }
|
||||
fun navigate(destination: Any) {
|
||||
navController.navigate(destination) {
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
fun choosePackage() {
|
||||
navController.navigate(ApplicationsList(false, true))
|
||||
}
|
||||
fun chooseSinglePackage() {
|
||||
navController.navigate(ApplicationsList(false, false))
|
||||
}
|
||||
fun navigateToAppGroups() {
|
||||
navController.navigate(ManageAppGroups)
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
if(!Privilege.status.value.activated) {
|
||||
navController.navigate(WorkModes(false)) {
|
||||
popUpTo<Home> { inclusive = true }
|
||||
}
|
||||
}
|
||||
}
|
||||
@Suppress("NewApi") NavHost(
|
||||
navController = navController,
|
||||
startDestination = Home,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(colorScheme.background)
|
||||
.pointerInput(Unit) { detectTapGestures(onTap = { focusMgr.clearFocus() }) },
|
||||
enterTransition = { NavTransition.enterTransition },
|
||||
exitTransition = { NavTransition.exitTransition },
|
||||
popEnterTransition = { NavTransition.popEnterTransition },
|
||||
popExitTransition = { NavTransition.popExitTransition }
|
||||
) {
|
||||
composable<Home> { HomeScreen(::navigate) }
|
||||
composable<WorkModes> {
|
||||
WorkModesScreen(vm, it.toRoute(), ::navigateUp, {
|
||||
navController.navigate(Home) {
|
||||
popUpTo<WorkModes> { inclusive = true }
|
||||
}
|
||||
}, {
|
||||
navController.navigate(WorkModes(false)) {
|
||||
popUpTo(Home) { inclusive = true }
|
||||
}
|
||||
}, ::navigate)
|
||||
}
|
||||
composable<DhizukuServerSettings> {
|
||||
DhizukuServerSettingsScreen(vm.dhizukuClients, vm::getDhizukuClients,
|
||||
vm::updateDhizukuClient, vm::getDhizukuServerEnabled, vm::setDhizukuServerEnabled,
|
||||
::navigateUp)
|
||||
}
|
||||
|
||||
composable<DelegatedAdmins> {
|
||||
DelegatedAdminsScreen(vm.delegatedAdmins, vm::getDelegatedAdmins, ::navigateUp, ::navigate)
|
||||
}
|
||||
composable<AddDelegatedAdmin>{
|
||||
AddDelegatedAdminScreen(vm.chosenPackage, ::chooseSinglePackage, it.toRoute(),
|
||||
vm::setDelegatedAdmin, ::navigateUp)
|
||||
}
|
||||
composable<DeviceInfo> { DeviceInfoScreen(vm, ::navigateUp) }
|
||||
composable<LockScreenInfo> {
|
||||
LockScreenInfoScreen(vm::getLockScreenInfo, vm::setLockScreenInfo, ::navigateUp)
|
||||
}
|
||||
composable<SupportMessage> {
|
||||
SupportMessageScreen(vm::getShortSupportMessage, vm::getLongSupportMessage,
|
||||
vm::setShortSupportMessage, vm::setLongSupportMessage, ::navigateUp)
|
||||
}
|
||||
composable<TransferOwnership> {
|
||||
TransferOwnershipScreen(vm.deviceAdminReceivers, vm::getDeviceAdminReceivers,
|
||||
vm::transferOwnership, ::navigateUp) {
|
||||
navController.navigate(WorkModes(false)) {
|
||||
popUpTo(Home) { inclusive = true }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
composable<SystemManager> { SystemManagerScreen(vm, ::navigateUp, ::navigate) }
|
||||
composable<SystemOptions> { SystemOptionsScreen(vm, ::navigateUp) }
|
||||
composable<Keyguard> {
|
||||
KeyguardScreen(vm::setKeyguardDisabled, vm::lockScreen, ::navigateUp)
|
||||
}
|
||||
composable<HardwareMonitor> {
|
||||
HardwareMonitorScreen(vm.hardwareProperties, vm::getHardwareProperties,
|
||||
vm::setHpRefreshInterval, ::navigateUp)
|
||||
}
|
||||
composable<DefaultInputMethod> {
|
||||
DefaultInputMethodScreen(vm::getCurrentInputMethod, vm.inputMethodList,
|
||||
vm::getInputMethods, vm::setDefaultInputMethod, ::navigateUp)
|
||||
}
|
||||
composable<ChangeTime> { ChangeTimeScreen(vm::setTime, ::navigateUp) }
|
||||
composable<ChangeTimeZone> { ChangeTimeZoneScreen(vm::setTimeZone, ::navigateUp) }
|
||||
composable<AutoTimePolicy> {
|
||||
AutoTimePolicyScreen(vm::getAutoTimePolicy, vm::setAutoTimePolicy, ::navigateUp)
|
||||
}
|
||||
composable<AutoTimeZonePolicy> {
|
||||
AutoTimeZonePolicyScreen(vm::getAutoTimeZonePolicy, vm::setAutoTimeZonePolicy,
|
||||
::navigateUp)
|
||||
}
|
||||
//composable<> { KeyPairs(::navigateUp) }
|
||||
composable<ContentProtectionPolicy> {
|
||||
ContentProtectionPolicyScreen(vm::getContentProtectionPolicy,
|
||||
vm::setContentProtectionPolicy, ::navigateUp)
|
||||
}
|
||||
composable<PermissionPolicy> {
|
||||
PermissionPolicyScreen(vm::getPermissionPolicy, vm::setPermissionPolicy, ::navigateUp)
|
||||
}
|
||||
composable<MtePolicy> {
|
||||
MtePolicyScreen(vm::getMtePolicy, vm::setMtePolicy, ::navigateUp)
|
||||
}
|
||||
composable<NearbyStreamingPolicy> {
|
||||
NearbyStreamingPolicyScreen(vm::getNsAppPolicy, vm::setNsAppPolicy,
|
||||
vm::getNsNotificationPolicy, vm::setNsNotificationPolicy, ::navigateUp)
|
||||
}
|
||||
composable<LockTaskMode> {
|
||||
LockTaskModeScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, ::choosePackage, vm.lockTaskPackages,
|
||||
vm::getLockTaskPackages, vm::setLockTaskPackage, vm::startLockTaskMode,
|
||||
vm:: getLockTaskFeatures, vm::setLockTaskFeatures, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<CaCert> {
|
||||
CaCertScreen(vm.installedCaCerts, vm::getCaCerts, vm.selectedCaCert, vm::selectCaCert, vm::installCaCert, vm::parseCaCert,
|
||||
vm::exportCaCert, vm::uninstallCaCert, vm::uninstallAllCaCerts, ::navigateUp)
|
||||
}
|
||||
composable<SecurityLogging> {
|
||||
SecurityLoggingScreen(vm::getSecurityLoggingEnabled, vm::setSecurityLoggingEnabled,
|
||||
vm::exportSecurityLogs, vm::getSecurityLogsCount, vm::deleteSecurityLogs,
|
||||
vm::getPreRebootSecurityLogs, vm::exportPreRebootSecurityLogs, ::navigateUp)
|
||||
}
|
||||
composable<DisableAccountManagement> {
|
||||
DisableAccountManagementScreen(vm.mdAccountTypes, vm::getMdAccountTypes,
|
||||
vm::setMdAccountType, ::navigateUp)
|
||||
}
|
||||
composable<SetSystemUpdatePolicy> {
|
||||
SystemUpdatePolicyScreen(vm::getSystemUpdatePolicy, vm::setSystemUpdatePolicy,
|
||||
vm::getPendingSystemUpdate, ::navigateUp)
|
||||
}
|
||||
composable<InstallSystemUpdate> {
|
||||
InstallSystemUpdateScreen(vm::installSystemUpdate, ::navigateUp)
|
||||
}
|
||||
composable<FrpPolicy> {
|
||||
FrpPolicyScreen(vm.getFrpPolicy(), vm::setFrpPolicy, ::navigateUp)
|
||||
}
|
||||
composable<WipeData> { WipeDataScreen(vm::wipeData, ::navigateUp) }
|
||||
|
||||
composable<Network> { NetworkScreen(::navigateUp, ::navigate) }
|
||||
composable<WiFi> {
|
||||
WifiScreen(vm, ::navigateUp, ::navigate) { navController.navigate(UpdateNetwork(it)) }
|
||||
}
|
||||
composable<NetworkOptions> {
|
||||
NetworkOptionsScreen(vm::getLanEnabled, vm::setLanEnabled, ::navigateUp)
|
||||
}
|
||||
composable<UpdateNetwork> {
|
||||
val info = vm.configuredNetworks.collectAsStateWithLifecycle().value[
|
||||
(it.toRoute() as UpdateNetwork).index
|
||||
]
|
||||
UpdateNetworkScreen(info, vm::setWifi, ::navigateUp)
|
||||
}
|
||||
composable<WifiSecurityLevel> {
|
||||
WifiSecurityLevelScreen(vm::getMinimumWifiSecurityLevel,
|
||||
vm::setMinimumWifiSecurityLevel, ::navigateUp)
|
||||
}
|
||||
composable<WifiSsidPolicyScreen> {
|
||||
WifiSsidPolicyScreen(vm::getSsidPolicy, vm::setSsidPolicy, ::navigateUp)
|
||||
}
|
||||
composable<QueryNetworkStats> {
|
||||
NetworkStatsScreen(vm.chosenPackage, ::chooseSinglePackage, vm::getPackageUid,
|
||||
vm::queryNetworkStats, ::navigateUp) { navController.navigate(NetworkStatsViewer) }
|
||||
}
|
||||
composable<NetworkStatsViewer> {
|
||||
NetworkStatsViewerScreen(vm.networkStatsData, vm::clearNetworkStats, ::navigateUp)
|
||||
}
|
||||
composable<PrivateDns> {
|
||||
PrivateDnsScreen(vm::getPrivateDns, vm::setPrivateDns, ::navigateUp)
|
||||
}
|
||||
composable<AlwaysOnVpnPackage> {
|
||||
AlwaysOnVpnPackageScreen(vm::getAlwaysOnVpnPackage, vm::getAlwaysOnVpnLockdown,
|
||||
vm::setAlwaysOnVpn, vm.chosenPackage, ::chooseSinglePackage, ::navigateUp)
|
||||
}
|
||||
composable<RecommendedGlobalProxy> {
|
||||
RecommendedGlobalProxyScreen(vm::setRecommendedGlobalProxy, ::navigateUp)
|
||||
}
|
||||
composable<NetworkLogging> {
|
||||
NetworkLoggingScreen(vm::getNetworkLoggingEnabled, vm::setNetworkLoggingEnabled,
|
||||
vm::getNetworkLogsCount, vm::exportNetworkLogs, vm::deleteNetworkLogs, ::navigateUp)
|
||||
}
|
||||
//composable<WifiAuthKeypair> { WifiAuthKeypairScreen(::navigateUp) }
|
||||
composable<PreferentialNetworkService> {
|
||||
PreferentialNetworkServiceScreen(vm::getPnsEnabled, vm::setPnsEnabled, vm.pnsConfigs,
|
||||
vm::getPnsConfigs, ::navigateUp, ::navigate)
|
||||
}
|
||||
composable<AddPreferentialNetworkServiceConfig> {
|
||||
val info = vm.pnsConfigs.collectAsStateWithLifecycle().value.getOrNull(
|
||||
it.toRoute<AddPreferentialNetworkServiceConfig>().index
|
||||
) ?: PreferentialNetworkServiceInfo()
|
||||
AddPreferentialNetworkServiceConfigScreen(info, vm::setPnsConfig, ::navigateUp)
|
||||
}
|
||||
composable<OverrideApn> {
|
||||
OverrideApnScreen(vm.apnConfigs, vm::getApnConfigs, vm::getApnEnabled,
|
||||
vm::setApnEnabled, ::navigateUp) { navController.navigate(AddApnSetting(it)) }
|
||||
}
|
||||
composable<AddApnSetting> {
|
||||
val origin = vm.apnConfigs.collectAsStateWithLifecycle().value.getOrNull((it.toRoute() as AddApnSetting).index)
|
||||
AddApnSettingScreen(vm::setApnConfig, vm::removeApnConfig, origin, ::navigateUp)
|
||||
}
|
||||
|
||||
composable<WorkProfile> { WorkProfileScreen(::navigateUp, ::navigate) }
|
||||
composable<OrganizationOwnedProfile> {
|
||||
OrganizationOwnedProfileScreen(vm::activateOrgProfileByShizuku, ::navigateUp)
|
||||
}
|
||||
composable<CreateWorkProfile> {
|
||||
CreateWorkProfileScreen(vm::createWorkProfile, ::navigateUp)
|
||||
}
|
||||
composable<SuspendPersonalApp> {
|
||||
SuspendPersonalAppScreen(
|
||||
vm::getPersonalAppsSuspendedReason, vm::setPersonalAppsSuspended,
|
||||
vm::getProfileMaxTimeOff, vm::setProfileMaxTimeOff, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<CrossProfileIntentFilter> {
|
||||
CrossProfileIntentFilterScreen(
|
||||
vm::addCrossProfileIntentFilter, vm::clearCrossProfileIntentFilters,
|
||||
vm::importCrossProfileIntentFilters, vm::exportCrossProfileIntentFilters,
|
||||
::navigateUp
|
||||
)
|
||||
}
|
||||
composable<DeleteWorkProfile> { DeleteWorkProfileScreen(vm::wipeData, ::navigateUp) }
|
||||
|
||||
composable<ApplicationsList> {
|
||||
val params = it.toRoute<ApplicationsList>()
|
||||
AppChooserScreen(
|
||||
params, vm.installedPackages, vm.refreshPackagesProgress, { name ->
|
||||
if (params.canSwitchView) {
|
||||
if (name == null) {
|
||||
navigateUp()
|
||||
} else {
|
||||
navigate(ApplicationDetails(name))
|
||||
DisposableEffect(lifecycleOwner) {
|
||||
val observer = LifecycleEventObserver { _, event ->
|
||||
if (
|
||||
(event == Lifecycle.Event.ON_CREATE && !SP.lockPasswordHash.isNullOrEmpty()) ||
|
||||
(event == Lifecycle.Event.ON_RESUME && SP.lockWhenLeaving)
|
||||
) {
|
||||
appLockDialog = true
|
||||
}
|
||||
}
|
||||
lifecycleOwner.lifecycle.addObserver(observer)
|
||||
onDispose {
|
||||
lifecycleOwner.lifecycle.removeObserver(observer)
|
||||
}
|
||||
} else {
|
||||
if (name != null) vm.chosenPackage.trySend(name)
|
||||
navigateUp()
|
||||
}
|
||||
}, {
|
||||
SP.applicationsListView = false
|
||||
navController.navigate(ApplicationsFeatures) {
|
||||
popUpTo(Home)
|
||||
LaunchedEffect(Unit) {
|
||||
val profileNotActivated = !SP.managedProfileActivated && Privilege.status.value.work
|
||||
if(profileNotActivated) {
|
||||
Privilege.DPM.setProfileEnabled(Privilege.DAR)
|
||||
SP.managedProfileActivated = true
|
||||
context.popToast(R.string.work_profile_activated)
|
||||
}
|
||||
}
|
||||
}, vm::refreshPackageList, vm::setPackageSuspended, vm::setPackageHidden)
|
||||
}
|
||||
composable<ApplicationsFeatures> {
|
||||
ApplicationsFeaturesScreen(::navigateUp, ::navigate) {
|
||||
SP.applicationsListView = true
|
||||
navController.navigate(ApplicationsList(true, true)) {
|
||||
popUpTo(Home)
|
||||
DhizukuErrorDialog {
|
||||
dhizukuErrorStatus.value = 0
|
||||
Privilege.updateStatus()
|
||||
backstack += Destination.WorkingModes(false)
|
||||
repeat(backstack.size - 1) {
|
||||
backstack.removeFirstOrNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
composable<ApplicationDetails> {
|
||||
ApplicationDetailsScreen(it.toRoute(), vm, ::navigateUp, ::navigate)
|
||||
}
|
||||
composable<Suspend> {
|
||||
PackageFunctionScreen(
|
||||
R.string.suspend, vm.suspendedPackages, vm::getSuspendedPackaged,
|
||||
vm::setPackageSuspended, ::navigateUp, vm.chosenPackage, ::choosePackage,
|
||||
::navigateToAppGroups, vm.appGroups, R.string.info_suspend_app
|
||||
)
|
||||
}
|
||||
composable<Hide> {
|
||||
PackageFunctionScreen(
|
||||
R.string.hide, vm.hiddenPackages, vm::getHiddenPackages, vm::setPackageHidden,
|
||||
::navigateUp, vm.chosenPackage, ::choosePackage, ::navigateToAppGroups, vm.appGroups
|
||||
)
|
||||
}
|
||||
composable<BlockUninstall> {
|
||||
PackageFunctionScreen(
|
||||
R.string.block_uninstall, vm.ubPackages, vm::getUbPackages, vm::setPackageUb,
|
||||
::navigateUp, vm.chosenPackage, ::choosePackage, ::navigateToAppGroups, vm.appGroups
|
||||
)
|
||||
}
|
||||
composable<DisableUserControl> {
|
||||
PackageFunctionScreen(
|
||||
R.string.disable_user_control, vm.ucdPackages, vm::getUcdPackages,
|
||||
vm::setPackageUcd, ::navigateUp, vm.chosenPackage, ::choosePackage,
|
||||
::navigateToAppGroups, vm.appGroups, R.string.info_disable_user_control
|
||||
)
|
||||
}
|
||||
composable<AppPermissionsManager> {
|
||||
AppPermissionsManagerScreen(
|
||||
vm::getPackagePermissions, vm::setPackagePermission, ::navigateUp, it.toRoute()
|
||||
)
|
||||
}
|
||||
composable<PermissionManager> {
|
||||
PermissionManagerScreen(::navigate, ::navigateUp)
|
||||
}
|
||||
composable<PermissionDetail> {
|
||||
PermissionDetailScreen(
|
||||
it.toRoute(), vm::getPermissionPackages, vm::setPackagePermission, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<DisableMeteredData> {
|
||||
PackageFunctionScreen(
|
||||
R.string.disable_metered_data, vm.mddPackages, vm::getMddPackages,
|
||||
vm::setPackageMdd, ::navigateUp, vm.chosenPackage, ::choosePackage,
|
||||
::navigateToAppGroups, vm.appGroups
|
||||
)
|
||||
}
|
||||
composable<ClearAppStorage> {
|
||||
ClearAppStorageScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::clearAppData, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<UninstallApp> {
|
||||
UninstallAppScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::uninstallPackage, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<KeepUninstalledPackages> {
|
||||
PackageFunctionScreen(
|
||||
R.string.keep_uninstalled_packages, vm.kuPackages, vm::getKuPackages,
|
||||
vm::setPackageKu, ::navigateUp, vm.chosenPackage, ::choosePackage,
|
||||
::navigateToAppGroups, vm.appGroups, R.string.info_keep_uninstalled_apps
|
||||
)
|
||||
}
|
||||
composable<InstallExistingApp> {
|
||||
InstallExistingAppScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::installExistingApp, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<CrossProfilePackages> {
|
||||
PackageFunctionScreen(
|
||||
R.string.cross_profile_apps, vm.cpPackages,
|
||||
vm::getCpPackages, vm::setPackageCp, ::navigateUp, vm.chosenPackage,
|
||||
::choosePackage, ::navigateToAppGroups, vm.appGroups
|
||||
)
|
||||
}
|
||||
composable<CrossProfileWidgetProviders> {
|
||||
PackageFunctionScreen(R.string.cross_profile_widget, vm.cpwProviders,
|
||||
vm::getCpwProviders, vm::setCpwProvider, ::navigateUp, vm.chosenPackage,
|
||||
::choosePackage, ::navigateToAppGroups, vm.appGroups)
|
||||
}
|
||||
composable<CredentialManagerPolicy> {
|
||||
CredentialManagerPolicyScreen(
|
||||
vm.chosenPackage, ::choosePackage, vm.cmPackages, vm::getCmPolicy,
|
||||
vm::setCmPackage, vm::setCmPolicy, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<PermittedAccessibilityServices> {
|
||||
PermittedAsAndImPackages(
|
||||
R.string.permitted_accessibility_services,
|
||||
R.string.system_accessibility_always_allowed, vm.chosenPackage, ::choosePackage,
|
||||
vm.pasPackages, vm::getPasPackages, vm::setPasPackage, vm::setPasPolicy,
|
||||
::navigateUp
|
||||
)
|
||||
}
|
||||
composable<PermittedInputMethods> {
|
||||
PermittedAsAndImPackages(
|
||||
R.string.permitted_ime, R.string.system_ime_always_allowed,
|
||||
vm.chosenPackage, ::choosePackage, vm.pimPackages, vm::getPimPackages,
|
||||
vm::setPimPackage, vm::setPimPolicy, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<EnableSystemApp> {
|
||||
EnableSystemAppScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::enableSystemApp, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<SetDefaultDialer> {
|
||||
SetDefaultDialerScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::setDefaultDialer, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<ManagedConfiguration> {
|
||||
ManagedConfigurationScreen(
|
||||
it.toRoute(), vm.appRestrictions, vm::setAppRestrictions,
|
||||
vm::clearAppRestrictions, ::navigateUp
|
||||
)
|
||||
}
|
||||
composable<ManageAppGroups> {
|
||||
ManageAppGroupsScreen(
|
||||
vm.appGroups, vm::exportAppGroups, vm::importAppGroups,
|
||||
{ id, name, apps -> navController.navigate(EditAppGroup(id, name, apps)) },
|
||||
::navigateUp
|
||||
)
|
||||
}
|
||||
composable<EditAppGroup> {
|
||||
EditAppGroupScreen(
|
||||
it.toRoute(), vm::getAppInfo, ::navigateUp, vm::setAppGroup,
|
||||
vm::deleteAppGroup, ::choosePackage, vm.chosenPackage
|
||||
)
|
||||
}
|
||||
|
||||
composable<UserRestriction> {
|
||||
UserRestrictionScreen(vm::getUserRestrictions, ::navigateUp, ::navigate)
|
||||
}
|
||||
composable<UserRestrictionEditor> {
|
||||
UserRestrictionEditorScreen(vm.userRestrictions, vm::setUserRestriction, ::navigateUp)
|
||||
}
|
||||
composable<UserRestrictionOptions> {
|
||||
UserRestrictionOptionsScreen(it.toRoute(), vm.userRestrictions,
|
||||
vm::setUserRestriction, vm::createUserRestrictionShortcut, ::navigateUp)
|
||||
}
|
||||
|
||||
composable<Users> { UsersScreen(vm, ::navigateUp, ::navigate) }
|
||||
composable<UserInfo> { UserInfoScreen(vm::getUserInformation, ::navigateUp) }
|
||||
composable<UsersOptions> {
|
||||
UsersOptionsScreen(vm::getLogoutEnabled, vm::setLogoutEnabled, ::navigateUp)
|
||||
}
|
||||
composable<UserOperation> {
|
||||
UserOperationScreen(vm::getUserIdentifiers, vm::doUserOperation,
|
||||
vm::createUserOperationShortcut, ::navigateUp)
|
||||
}
|
||||
composable<CreateUser> { CreateUserScreen(vm::createUser, ::navigateUp) }
|
||||
composable<ChangeUsername> { ChangeUsernameScreen(vm::setProfileName, ::navigateUp) }
|
||||
composable<UserSessionMessage> {
|
||||
UserSessionMessageScreen(vm::getUserSessionMessages, vm::setStartUserSessionMessage,
|
||||
vm::setEndUserSessionMessage, ::navigateUp)
|
||||
}
|
||||
composable<AffiliationId> {
|
||||
AffiliationIdScreen(vm.affiliationIds, vm::getAffiliationIds, vm::setAffiliationId,
|
||||
::navigateUp)
|
||||
}
|
||||
|
||||
composable<Password> { PasswordScreen(vm, ::navigateUp, ::navigate) }
|
||||
composable<PasswordInfo> {
|
||||
PasswordInfoScreen(vm::getPasswordComplexity, vm::isPasswordComplexitySufficient,
|
||||
vm::isUsingUnifiedPassword, ::navigateUp)
|
||||
}
|
||||
composable<ResetPasswordToken> {
|
||||
ResetPasswordTokenScreen(vm::getRpTokenState, vm::setRpToken,
|
||||
vm::createActivateRpTokenIntent, vm::clearRpToken, ::navigateUp)
|
||||
}
|
||||
composable<ResetPassword> { ResetPasswordScreen(vm::resetPassword, ::navigateUp) }
|
||||
composable<RequiredPasswordComplexity> {
|
||||
RequiredPasswordComplexityScreen(vm::getRequiredPasswordComplexity,
|
||||
vm::setRequiredPasswordComplexity, ::navigateUp)
|
||||
}
|
||||
composable<KeyguardDisabledFeatures> {
|
||||
KeyguardDisabledFeaturesScreen(vm::getKeyguardDisableConfig,
|
||||
vm::setKeyguardDisableConfig, ::navigateUp)
|
||||
}
|
||||
composable<RequiredPasswordQuality> { RequiredPasswordQualityScreen(::navigateUp) }
|
||||
|
||||
composable<Settings> { SettingsScreen(::navigateUp, ::navigate) }
|
||||
composable<SettingsOptions> {
|
||||
SettingsOptionsScreen(vm::getDisplayDangerousFeatures, vm::getShortcutsEnabled,
|
||||
vm::setDisplayDangerousFeatures, vm::setShortcutsEnabled, ::navigateUp)
|
||||
}
|
||||
composable<Appearance> {
|
||||
AppearanceScreen(::navigateUp, vm.theme, vm::changeTheme)
|
||||
}
|
||||
composable<AppLockSettings> {
|
||||
AppLockSettingsScreen(vm.getAppLockConfig(), vm::setAppLockConfig, ::navigateUp)
|
||||
}
|
||||
composable<ApiSettings> {
|
||||
ApiSettings(vm::getApiEnabled, vm::setApiKey, ::navigateUp)
|
||||
}
|
||||
composable<Notifications> {
|
||||
NotificationsScreen(vm.enabledNotifications, vm::getEnabledNotifications,
|
||||
vm::setNotificationEnabled, ::navigateUp)
|
||||
}
|
||||
composable<About> { AboutScreen(::navigateUp) }
|
||||
}
|
||||
DisposableEffect(lifecycleOwner) {
|
||||
val observer = LifecycleEventObserver { _, event ->
|
||||
if (
|
||||
(event == Lifecycle.Event.ON_CREATE && !SP.lockPasswordHash.isNullOrEmpty()) ||
|
||||
(event == Lifecycle.Event.ON_RESUME && SP.lockWhenLeaving)
|
||||
) {
|
||||
onLock()
|
||||
}
|
||||
}
|
||||
lifecycleOwner.lifecycle.addObserver(observer)
|
||||
onDispose {
|
||||
lifecycleOwner.lifecycle.removeObserver(observer)
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
val profileNotActivated = !SP.managedProfileActivated && Privilege.status.value.work
|
||||
if(profileNotActivated) {
|
||||
Privilege.DPM.setProfileEnabled(Privilege.DAR)
|
||||
SP.managedProfileActivated = true
|
||||
context.popToast(R.string.work_profile_activated)
|
||||
}
|
||||
}
|
||||
DhizukuErrorDialog {
|
||||
dhizukuErrorStatus.value = 0
|
||||
Privilege.updateStatus()
|
||||
navController.navigate(WorkModes(false)) {
|
||||
popUpTo<Home> { inclusive = true }
|
||||
launchSingleTop = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable private object Home
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun HomeScreen(onNavigate: (Any) -> Unit) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
val sb = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
Scaffold(
|
||||
Modifier.nestedScroll(sb.nestedScrollConnection),
|
||||
topBar = {
|
||||
LargeTopAppBar(
|
||||
{ Text(stringResource(R.string.app_name)) },
|
||||
actions = {
|
||||
IconButton({ onNavigate(WorkModes(true)) }) { Icon(painterResource(R.drawable.security_fill0), null) }
|
||||
IconButton({ onNavigate(Settings) }) { Icon(Icons.Default.Settings, null) }
|
||||
},
|
||||
scrollBehavior = sb
|
||||
)
|
||||
},
|
||||
contentWindowInsets = adaptiveInsets()
|
||||
) {
|
||||
Column(Modifier
|
||||
.fillMaxSize()
|
||||
.padding(it)
|
||||
.verticalScroll(rememberScrollState())) {
|
||||
if(privilege.device || privilege.profile) {
|
||||
HomePageItem(R.string.system, R.drawable.android_fill0) { onNavigate(SystemManager) }
|
||||
HomePageItem(R.string.network, R.drawable.wifi_fill0) { onNavigate(Network) }
|
||||
}
|
||||
if(privilege.work) {
|
||||
HomePageItem(R.string.work_profile, R.drawable.work_fill0) {
|
||||
onNavigate(WorkProfile)
|
||||
}
|
||||
}
|
||||
if(privilege.device || privilege.profile) {
|
||||
HomePageItem(R.string.applications, R.drawable.apps_fill0) {
|
||||
onNavigate(
|
||||
if (SP.applicationsListView) ApplicationsList(true, true)
|
||||
else ApplicationsFeatures
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24) {
|
||||
HomePageItem(R.string.user_restriction, R.drawable.person_off) { onNavigate(UserRestriction) }
|
||||
}
|
||||
HomePageItem(R.string.users,R.drawable.manage_accounts_fill0) { onNavigate(Users) }
|
||||
HomePageItem(R.string.password_and_keyguard, R.drawable.password_fill0) { onNavigate(Password) }
|
||||
}
|
||||
Spacer(Modifier.height(BottomPadding))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HomePageItem(name: Int, imgVector: Int, onClick: () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick)
|
||||
.padding(vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Spacer(Modifier.padding(start = 30.dp))
|
||||
Icon(
|
||||
painter = painterResource(imgVector),
|
||||
contentDescription = null
|
||||
)
|
||||
Spacer(Modifier.padding(start = 15.dp))
|
||||
Text(
|
||||
text = stringResource(name),
|
||||
style = typography.headlineSmall,
|
||||
modifier = Modifier.padding(bottom = if(zhCN) { 2 } else { 0 }.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import androidx.annotation.RequiresApi
|
||||
import androidx.core.database.getIntOrNull
|
||||
import androidx.core.database.getLongOrNull
|
||||
import androidx.core.database.getStringOrNull
|
||||
import com.bintianqi.owndroid.dpm.AppGroup
|
||||
import com.bintianqi.owndroid.dpm.IntentFilterOptions
|
||||
import com.bintianqi.owndroid.ui.screen.AppGroup
|
||||
import com.bintianqi.owndroid.ui.screen.IntentFilterOptions
|
||||
import com.bintianqi.owndroid.dpm.NetworkLog
|
||||
import com.bintianqi.owndroid.dpm.SecurityEvent
|
||||
import com.bintianqi.owndroid.dpm.SecurityEventWithData
|
||||
|
||||
@@ -60,57 +60,58 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.bintianqi.owndroid.Privilege.DAR
|
||||
import com.bintianqi.owndroid.Privilege.DPM
|
||||
import com.bintianqi.owndroid.dpm.ACTIVATE_DEVICE_OWNER_COMMAND
|
||||
import com.bintianqi.owndroid.dpm.ApnAuthType
|
||||
import com.bintianqi.owndroid.dpm.ApnConfig
|
||||
import com.bintianqi.owndroid.dpm.ApnMvnoType
|
||||
import com.bintianqi.owndroid.dpm.ApnProtocol
|
||||
import com.bintianqi.owndroid.dpm.AppGroup
|
||||
import com.bintianqi.owndroid.dpm.AppRestriction
|
||||
import com.bintianqi.owndroid.dpm.AppStatus
|
||||
import com.bintianqi.owndroid.dpm.BasicAppGroup
|
||||
import com.bintianqi.owndroid.dpm.CaCertInfo
|
||||
import com.bintianqi.owndroid.dpm.CreateUserResult
|
||||
import com.bintianqi.owndroid.dpm.CreateWorkProfileOptions
|
||||
import com.bintianqi.owndroid.dpm.DelegatedAdmin
|
||||
import com.bintianqi.owndroid.dpm.DeviceAdmin
|
||||
import com.bintianqi.owndroid.dpm.FrpPolicyInfo
|
||||
import com.bintianqi.owndroid.dpm.HardwareProperties
|
||||
import com.bintianqi.owndroid.dpm.IntentFilterOptions
|
||||
import com.bintianqi.owndroid.dpm.IpMode
|
||||
import com.bintianqi.owndroid.dpm.KeyguardDisableConfig
|
||||
import com.bintianqi.owndroid.dpm.KeyguardDisableMode
|
||||
import com.bintianqi.owndroid.dpm.NetworkStatsData
|
||||
import com.bintianqi.owndroid.dpm.NetworkStatsTarget
|
||||
import com.bintianqi.owndroid.dpm.PasswordComplexity
|
||||
import com.bintianqi.owndroid.dpm.PendingSystemUpdateInfo
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkServiceInfo
|
||||
import com.bintianqi.owndroid.dpm.PrivateDnsConfiguration
|
||||
import com.bintianqi.owndroid.dpm.PrivateDnsMode
|
||||
import com.bintianqi.owndroid.dpm.ProxyMode
|
||||
import com.bintianqi.owndroid.dpm.ProxyType
|
||||
import com.bintianqi.owndroid.dpm.QueryNetworkStatsParams
|
||||
import com.bintianqi.owndroid.dpm.RecommendedProxyConf
|
||||
import com.bintianqi.owndroid.dpm.RpTokenState
|
||||
import com.bintianqi.owndroid.dpm.SsidPolicy
|
||||
import com.bintianqi.owndroid.dpm.SsidPolicyType
|
||||
import com.bintianqi.owndroid.dpm.SystemOptionsStatus
|
||||
import com.bintianqi.owndroid.dpm.SystemUpdatePolicyInfo
|
||||
import com.bintianqi.owndroid.dpm.UserIdentifier
|
||||
import com.bintianqi.owndroid.dpm.UserInformation
|
||||
import com.bintianqi.owndroid.dpm.UserOperationType
|
||||
import com.bintianqi.owndroid.dpm.WifiInfo
|
||||
import com.bintianqi.owndroid.dpm.WifiSecurity
|
||||
import com.bintianqi.owndroid.dpm.WifiStatus
|
||||
import com.bintianqi.owndroid.dpm.activateOrgProfileCommand
|
||||
import com.bintianqi.owndroid.dpm.delegatedScopesList
|
||||
import com.bintianqi.owndroid.dpm.doUserOperationWithContext
|
||||
import com.bintianqi.owndroid.dpm.getPackageInstaller
|
||||
import com.bintianqi.owndroid.dpm.globalSettings
|
||||
import com.bintianqi.owndroid.dpm.handlePrivilegeChange
|
||||
import com.bintianqi.owndroid.dpm.parsePackageInstallerMessage
|
||||
import com.bintianqi.owndroid.dpm.runtimePermissions
|
||||
import com.bintianqi.owndroid.dpm.secureSettings
|
||||
import com.bintianqi.owndroid.dpm.temperatureTypes
|
||||
import com.bintianqi.owndroid.ui.screen.ApnAuthType
|
||||
import com.bintianqi.owndroid.ui.screen.ApnConfig
|
||||
import com.bintianqi.owndroid.ui.screen.ApnMvnoType
|
||||
import com.bintianqi.owndroid.ui.screen.ApnProtocol
|
||||
import com.bintianqi.owndroid.ui.screen.AppGroup
|
||||
import com.bintianqi.owndroid.ui.screen.AppLockConfig
|
||||
import com.bintianqi.owndroid.ui.screen.AppRestriction
|
||||
import com.bintianqi.owndroid.ui.screen.AppStatus
|
||||
import com.bintianqi.owndroid.ui.screen.BasicAppGroup
|
||||
import com.bintianqi.owndroid.ui.screen.CaCertInfo
|
||||
import com.bintianqi.owndroid.ui.screen.CreateUserResult
|
||||
import com.bintianqi.owndroid.ui.screen.CreateWorkProfileOptions
|
||||
import com.bintianqi.owndroid.ui.screen.FrpPolicyInfo
|
||||
import com.bintianqi.owndroid.ui.screen.HardwareProperties
|
||||
import com.bintianqi.owndroid.ui.screen.IntentFilterOptions
|
||||
import com.bintianqi.owndroid.ui.screen.IpMode
|
||||
import com.bintianqi.owndroid.ui.screen.KeyguardDisableConfig
|
||||
import com.bintianqi.owndroid.ui.screen.KeyguardDisableMode
|
||||
import com.bintianqi.owndroid.ui.screen.NetworkStatsData
|
||||
import com.bintianqi.owndroid.ui.screen.NetworkStatsTarget
|
||||
import com.bintianqi.owndroid.ui.screen.PasswordComplexity
|
||||
import com.bintianqi.owndroid.ui.screen.PendingSystemUpdateInfo
|
||||
import com.bintianqi.owndroid.ui.screen.PreferentialNetworkServiceInfo
|
||||
import com.bintianqi.owndroid.ui.screen.PrivateDnsConfiguration
|
||||
import com.bintianqi.owndroid.ui.screen.PrivateDnsMode
|
||||
import com.bintianqi.owndroid.ui.screen.ProxyMode
|
||||
import com.bintianqi.owndroid.ui.screen.ProxyType
|
||||
import com.bintianqi.owndroid.ui.screen.QueryNetworkStatsParams
|
||||
import com.bintianqi.owndroid.ui.screen.RecommendedProxyConf
|
||||
import com.bintianqi.owndroid.ui.screen.RpTokenState
|
||||
import com.bintianqi.owndroid.ui.screen.SsidPolicy
|
||||
import com.bintianqi.owndroid.ui.screen.SsidPolicyType
|
||||
import com.bintianqi.owndroid.ui.screen.SystemOptionsStatus
|
||||
import com.bintianqi.owndroid.ui.screen.SystemUpdatePolicyInfo
|
||||
import com.bintianqi.owndroid.ui.screen.UserIdentifier
|
||||
import com.bintianqi.owndroid.ui.screen.UserInformation
|
||||
import com.bintianqi.owndroid.ui.screen.UserOperationType
|
||||
import com.bintianqi.owndroid.ui.screen.WifiInfo
|
||||
import com.bintianqi.owndroid.ui.screen.WifiSecurity
|
||||
import com.bintianqi.owndroid.ui.screen.WifiStatus
|
||||
import com.bintianqi.owndroid.ui.screen.activateOrgProfileCommand
|
||||
import com.bintianqi.owndroid.ui.screen.delegatedScopesList
|
||||
import com.bintianqi.owndroid.ui.screen.globalSettings
|
||||
import com.bintianqi.owndroid.ui.screen.secureSettings
|
||||
import com.bintianqi.owndroid.ui.screen.temperatureTypes
|
||||
import com.rosan.dhizuku.api.Dhizuku
|
||||
import com.rosan.dhizuku.api.DhizukuRequestPermissionListener
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -159,7 +160,9 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
fun getAppLockConfig(): AppLockConfig {
|
||||
val passwordHash = SP.lockPasswordHash
|
||||
return AppLockConfig(passwordHash?.ifEmpty { null }, SP.biometricsUnlock, SP.lockWhenLeaving)
|
||||
return AppLockConfig(
|
||||
passwordHash?.ifEmpty { null }, SP.biometricsUnlock, SP.lockWhenLeaving
|
||||
)
|
||||
}
|
||||
fun setAppLockConfig(config: AppLockConfig) {
|
||||
if (config.password == null) {
|
||||
|
||||
@@ -63,9 +63,9 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
data class AppInfo(
|
||||
val name: String,
|
||||
@@ -77,12 +77,10 @@ data class AppInfo(
|
||||
private fun searchInString(query: String, content: String)
|
||||
= query.split(' ').all { content.contains(it, true) }
|
||||
|
||||
@Serializable data class ApplicationsList(val canSwitchView: Boolean, val multiSelect: Boolean)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun AppChooserScreen(
|
||||
params: ApplicationsList, packageList: MutableStateFlow<List<AppInfo>>,
|
||||
params: Destination.ApplicationsList, packageList: MutableStateFlow<List<AppInfo>>,
|
||||
refreshProgress: MutableStateFlow<Float>, onChoosePackage: (String?) -> Unit,
|
||||
onSwitchView: () -> Unit, onRefresh: () -> Unit,
|
||||
setPackagesSuspend: (List<String>, Boolean) -> Unit,
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.content.Intent
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import com.bintianqi.owndroid.dpm.UserOperationType
|
||||
import com.bintianqi.owndroid.ui.screen.UserOperationType
|
||||
|
||||
object ShortcutUtils {
|
||||
fun setAllShortcuts(context: Context, enabled: Boolean) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.bintianqi.owndroid
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import com.bintianqi.owndroid.dpm.UserOperationType
|
||||
import com.bintianqi.owndroid.ui.screen.UserOperationType
|
||||
import com.bintianqi.owndroid.dpm.doUserOperationWithContext
|
||||
|
||||
class ShortcutsReceiverActivity : Activity() {
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.bintianqi.owndroid
|
||||
|
||||
import android.os.Build
|
||||
import android.os.UserManager
|
||||
import com.bintianqi.owndroid.dpm.Restriction
|
||||
import com.bintianqi.owndroid.ui.screen.Restriction
|
||||
|
||||
@Suppress("InlinedApi")
|
||||
object UserRestrictionsRepository {
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.app.admin.DevicePolicyManager
|
||||
import android.app.admin.DnsEvent
|
||||
import android.app.admin.IDevicePolicyManager
|
||||
import android.app.admin.SecurityLog
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.IPackageInstaller
|
||||
@@ -16,6 +17,7 @@ import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.bintianqi.owndroid.AppInfo
|
||||
import com.bintianqi.owndroid.MyApplication
|
||||
import com.bintianqi.owndroid.NotificationType
|
||||
import com.bintianqi.owndroid.NotificationUtils
|
||||
@@ -25,6 +27,7 @@ import com.bintianqi.owndroid.Privilege.DPM
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.SP
|
||||
import com.bintianqi.owndroid.ShortcutUtils
|
||||
import com.bintianqi.owndroid.ui.screen.UserOperationType
|
||||
import com.rosan.dhizuku.api.Dhizuku
|
||||
import com.rosan.dhizuku.api.DhizukuBinderWrapper
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -589,3 +592,9 @@ fun doUserOperationWithContext(
|
||||
UserOperationType.Delete -> DPM.removeUser(DAR, handle)
|
||||
}
|
||||
}
|
||||
|
||||
const val ACTIVATE_DEVICE_OWNER_COMMAND = "dpm set-device-owner com.bintianqi.owndroid/.Receiver"
|
||||
|
||||
data class DelegatedAdmin(val app: AppInfo, val scopes: List<String>)
|
||||
|
||||
data class DeviceAdmin(val app: AppInfo, val admin: ComponentName)
|
||||
|
||||
@@ -17,9 +17,12 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.List
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Card
|
||||
@@ -31,6 +34,7 @@ import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Switch
|
||||
@@ -48,14 +52,18 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import com.bintianqi.owndroid.HorizontalPadding
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.adaptiveInsets
|
||||
import com.bintianqi.owndroid.ui.screen.isValidPackageName
|
||||
import com.bintianqi.owndroid.zhCN
|
||||
|
||||
@Composable
|
||||
@@ -398,3 +406,25 @@ fun CircularProgressDialog(onDismiss: () -> Unit) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PackageNameTextField(
|
||||
value: String, onChoosePackage: () -> Unit,
|
||||
modifier: Modifier = Modifier, onValueChange: (String) -> Unit
|
||||
) {
|
||||
val fm = LocalFocusManager.current
|
||||
OutlinedTextField(
|
||||
value, onValueChange, Modifier
|
||||
.fillMaxWidth()
|
||||
.then(modifier),
|
||||
label = { Text(stringResource(R.string.package_name)) },
|
||||
trailingIcon = {
|
||||
IconButton(onChoosePackage) {
|
||||
Icon(Icons.AutoMirrored.Default.List, null)
|
||||
}
|
||||
},
|
||||
isError = value.isNotEmpty() && !value.isValidPackageName,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions { fm.clearFocus() }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.animation.togetherWith
|
||||
|
||||
/**
|
||||
* Learned from AOSP's Activity animation
|
||||
@@ -42,4 +43,7 @@ object NavTransition {
|
||||
) + fadeOut(
|
||||
tween(83, 35, LinearEasing)
|
||||
)
|
||||
|
||||
val transition = enterTransition togetherWith exitTransition
|
||||
val popTransition = popEnterTransition togetherWith popExitTransition
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
package com.bintianqi.owndroid.ui.navigation
|
||||
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
sealed class Destination : NavKey {
|
||||
@Serializable object Home : Destination()
|
||||
|
||||
@Serializable class WorkingModes(val canNavigateUp: Boolean) : Destination()
|
||||
@Serializable object DhizukuServerSettings : Destination()
|
||||
@Serializable object DelegatedAdmins : Destination()
|
||||
@Serializable class DelegatedAdminDetails(
|
||||
val pkg: String, val scopes: List<String>
|
||||
) : Destination()
|
||||
|
||||
@Serializable object TransferOwnership : Destination()
|
||||
|
||||
@Serializable object System : Destination()
|
||||
@Serializable object SystemOptions : Destination()
|
||||
@Serializable object Keyguard : Destination()
|
||||
@Serializable object HardwareMonitor : Destination()
|
||||
@Serializable object DefaultInputMethod : Destination()
|
||||
@Serializable object ChangeTime : Destination()
|
||||
@Serializable object ChangeTimezone : Destination()
|
||||
@Serializable object AutoTimePolicy : Destination()
|
||||
@Serializable object AutoTimezonePolicy : Destination()
|
||||
@Serializable object ContentProtectionPolicy : Destination()
|
||||
@Serializable object PermissionPolicy : Destination()
|
||||
@Serializable object MtePolicy : Destination()
|
||||
@Serializable object NearbyStreamingPolicy : Destination()
|
||||
@Serializable object LockTaskMode : Destination()
|
||||
@Serializable object CaCert : Destination()
|
||||
@Serializable object SecurityLogging : Destination()
|
||||
@Serializable object DeviceInfo : Destination()
|
||||
@Serializable object LockScreenInfo : Destination()
|
||||
@Serializable object SupportMessage : Destination()
|
||||
@Serializable object DisableAccountManagement : Destination()
|
||||
@Serializable object FrpPolicy : Destination()
|
||||
@Serializable object WipeData : Destination()
|
||||
@Serializable object SystemUpdatePolicy : Destination()
|
||||
@Serializable object InstallSystemUpdate : Destination()
|
||||
|
||||
@Serializable object Network : Destination()
|
||||
@Serializable object NetworkOptions : Destination()
|
||||
@Serializable object WiFi : Destination()
|
||||
@Serializable class UpdateNetwork(val index: Int) : Destination()
|
||||
@Serializable object WifiSecurityLevel : Destination()
|
||||
@Serializable object WifiSsidPolicy : Destination()
|
||||
@Serializable object NetworkStats : Destination()
|
||||
@Serializable object NetworkStatsViewer : Destination()
|
||||
@Serializable object PrivateDns : Destination()
|
||||
@Serializable object AlwaysOnVpnPackage : Destination()
|
||||
@Serializable object RecommendedGlobalProxy : Destination()
|
||||
@Serializable object NetworkLogging : Destination()
|
||||
@Serializable object PreferentialNetworkService : Destination()
|
||||
@Serializable class AddPreferentialNetworkServiceConfig(val index: Int) : Destination()
|
||||
@Serializable object OverrideApn : Destination()
|
||||
@Serializable data class AddApnSetting(val index: Int) : Destination()
|
||||
|
||||
@Serializable object WorkProfile : Destination()
|
||||
@Serializable object CreateWorkProfile : Destination()
|
||||
@Serializable object OrganizationOwnedProfile : Destination()
|
||||
@Serializable object SuspendPersonalApp : Destination()
|
||||
@Serializable object CrossProfileIntentFilter : Destination()
|
||||
@Serializable object DeleteWorkProfile : Destination()
|
||||
|
||||
@Serializable object ApplicationFunctions : Destination()
|
||||
@Serializable object Suspend : Destination()
|
||||
@Serializable object Hide : Destination()
|
||||
@Serializable object BlockUninstall : Destination()
|
||||
@Serializable object DisableUserControl : Destination()
|
||||
@Serializable object PermissionManager : Destination()
|
||||
@Serializable class PermissionDetail(val permission: String) : Destination()
|
||||
@Serializable object DisableMeteredData : Destination()
|
||||
@Serializable object ClearAppStorage : Destination()
|
||||
@Serializable object UninstallApp : Destination()
|
||||
@Serializable object KeepUninstalledPackages : Destination()
|
||||
@Serializable object InstallExistingApp : Destination()
|
||||
@Serializable object CrossProfilePackages : Destination()
|
||||
@Serializable object CrossProfileWidgetProviders : Destination()
|
||||
@Serializable object CredentialManagerPolicy : Destination()
|
||||
@Serializable object PermittedAccessibilityServices : Destination()
|
||||
@Serializable object PermittedInputMethods : Destination()
|
||||
@Serializable object EnableSystemApp : Destination()
|
||||
@Serializable object SetDefaultDialer : Destination()
|
||||
@Serializable object ManageAppGroups : Destination()
|
||||
@Serializable class EditAppGroup(
|
||||
val id: Int?, val name: String, val apps: List<String>
|
||||
) : Destination()
|
||||
|
||||
@Serializable class ApplicationDetails(val packageName: String) : Destination()
|
||||
@Serializable class AppPermissionsManager(val packageName: String) : Destination()
|
||||
@Serializable class ManagedConfiguration(val packageName: String) : Destination()
|
||||
|
||||
@Serializable data class ApplicationsList(
|
||||
val canSwitchView: Boolean, val multiSelect: Boolean
|
||||
) : Destination()
|
||||
|
||||
@Serializable object UserRestriction : Destination()
|
||||
@Serializable data class UserRestrictionOptions(val id: String) : Destination()
|
||||
@Serializable object UserRestrictionEditor : Destination()
|
||||
|
||||
@Serializable object Users : Destination()
|
||||
@Serializable object UsersOptions : Destination()
|
||||
@Serializable object UserInfo : Destination()
|
||||
@Serializable object UserOperation : Destination()
|
||||
@Serializable object CreateUser : Destination()
|
||||
@Serializable object AffiliationId : Destination()
|
||||
@Serializable object ChangeUsername : Destination()
|
||||
@Serializable object UserSessionMessage : Destination()
|
||||
|
||||
@Serializable object Password : Destination()
|
||||
@Serializable object PasswordInfo : Destination()
|
||||
@Serializable object ResetPasswordToken : Destination()
|
||||
@Serializable object ResetPassword : Destination()
|
||||
@Serializable object RequiredPasswordComplexity : Destination()
|
||||
@Serializable object KeyguardDisabledFeatures : Destination()
|
||||
@Serializable object RequiredPasswordQuality : Destination()
|
||||
|
||||
@Serializable object Settings : Destination()
|
||||
@Serializable object SettingsOptions : Destination()
|
||||
@Serializable object AppearanceSettings : Destination()
|
||||
@Serializable object AppLockSettings : Destination()
|
||||
@Serializable object ApiSettings : Destination()
|
||||
@Serializable object NotificationSettings : Destination()
|
||||
@Serializable object About : Destination()
|
||||
}
|
||||
@@ -0,0 +1,557 @@
|
||||
package com.bintianqi.owndroid.ui.navigation
|
||||
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavEntry
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import com.bintianqi.owndroid.AppChooserScreen
|
||||
import com.bintianqi.owndroid.MyViewModel
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.SP
|
||||
import com.bintianqi.owndroid.ui.screen.AboutScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AddApnSettingScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AddDelegatedAdminScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AddPreferentialNetworkServiceConfigScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AffiliationIdScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AlwaysOnVpnPackageScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ApiSettings
|
||||
import com.bintianqi.owndroid.ui.screen.AppLockSettingsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AppPermissionsManagerScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AppearanceScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ApplicationDetailsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ApplicationsFeaturesScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AutoTimePolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.AutoTimeZonePolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.CaCertScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ChangeTimeScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ChangeTimeZoneScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ChangeUsernameScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ClearAppStorageScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ContentProtectionPolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.CreateUserScreen
|
||||
import com.bintianqi.owndroid.ui.screen.CreateWorkProfileScreen
|
||||
import com.bintianqi.owndroid.ui.screen.CredentialManagerPolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.CrossProfileIntentFilterScreen
|
||||
import com.bintianqi.owndroid.ui.screen.DefaultInputMethodScreen
|
||||
import com.bintianqi.owndroid.ui.screen.DelegatedAdminsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.DeleteWorkProfileScreen
|
||||
import com.bintianqi.owndroid.ui.screen.DeviceInfoScreen
|
||||
import com.bintianqi.owndroid.ui.screen.DhizukuServerSettingsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.DisableAccountManagementScreen
|
||||
import com.bintianqi.owndroid.ui.screen.EditAppGroupScreen
|
||||
import com.bintianqi.owndroid.ui.screen.EnableSystemAppScreen
|
||||
import com.bintianqi.owndroid.ui.screen.FrpPolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.HardwareMonitorScreen
|
||||
import com.bintianqi.owndroid.ui.screen.HomeScreen
|
||||
import com.bintianqi.owndroid.ui.screen.InstallExistingAppScreen
|
||||
import com.bintianqi.owndroid.ui.screen.InstallSystemUpdateScreen
|
||||
import com.bintianqi.owndroid.ui.screen.KeyguardDisabledFeaturesScreen
|
||||
import com.bintianqi.owndroid.ui.screen.KeyguardScreen
|
||||
import com.bintianqi.owndroid.ui.screen.LockScreenInfoScreen
|
||||
import com.bintianqi.owndroid.ui.screen.LockTaskModeScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ManageAppGroupsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ManagedConfigurationScreen
|
||||
import com.bintianqi.owndroid.ui.screen.MtePolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.NearbyStreamingPolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.NetworkLoggingScreen
|
||||
import com.bintianqi.owndroid.ui.screen.NetworkOptionsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.NetworkScreen
|
||||
import com.bintianqi.owndroid.ui.screen.NetworkStatsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.NetworkStatsViewerScreen
|
||||
import com.bintianqi.owndroid.ui.screen.NotificationsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.OrganizationOwnedProfileScreen
|
||||
import com.bintianqi.owndroid.ui.screen.OverrideApnScreen
|
||||
import com.bintianqi.owndroid.ui.screen.PackageFunctionScreen
|
||||
import com.bintianqi.owndroid.ui.screen.PasswordInfoScreen
|
||||
import com.bintianqi.owndroid.ui.screen.PasswordScreen
|
||||
import com.bintianqi.owndroid.ui.screen.PermissionDetailScreen
|
||||
import com.bintianqi.owndroid.ui.screen.PermissionManagerScreen
|
||||
import com.bintianqi.owndroid.ui.screen.PermissionPolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.PermittedAsAndImPackages
|
||||
import com.bintianqi.owndroid.ui.screen.PreferentialNetworkServiceInfo
|
||||
import com.bintianqi.owndroid.ui.screen.PreferentialNetworkServiceScreen
|
||||
import com.bintianqi.owndroid.ui.screen.PrivateDnsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.RecommendedGlobalProxyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.RequiredPasswordComplexityScreen
|
||||
import com.bintianqi.owndroid.ui.screen.RequiredPasswordQualityScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ResetPasswordScreen
|
||||
import com.bintianqi.owndroid.ui.screen.ResetPasswordTokenScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SecurityLoggingScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SetDefaultDialerScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SettingsOptionsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SettingsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SupportMessageScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SuspendPersonalAppScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SystemManagerScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SystemOptionsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.SystemUpdatePolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.TransferOwnershipScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UninstallAppScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UpdateNetworkScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UserInfoScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UserOperationScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UserRestrictionEditorScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UserRestrictionOptionsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UserRestrictionScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UserSessionMessageScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UsersOptionsScreen
|
||||
import com.bintianqi.owndroid.ui.screen.UsersScreen
|
||||
import com.bintianqi.owndroid.ui.screen.WifiScreen
|
||||
import com.bintianqi.owndroid.ui.screen.WifiSecurityLevelScreen
|
||||
import com.bintianqi.owndroid.ui.screen.WifiSsidPolicyScreen
|
||||
import com.bintianqi.owndroid.ui.screen.WipeDataScreen
|
||||
import com.bintianqi.owndroid.ui.screen.WorkModesScreen
|
||||
import com.bintianqi.owndroid.ui.screen.WorkProfileScreen
|
||||
|
||||
fun myEntryProvider(
|
||||
destination: Destination, backstack: NavBackStack<NavKey>, vm: MyViewModel
|
||||
) = entryProvider {
|
||||
fun navigate(dest: Destination) {
|
||||
backstack += dest
|
||||
}
|
||||
fun navigateUp() {
|
||||
backstack.removeLastOrNull()
|
||||
}
|
||||
fun navigateToAppGroups() {
|
||||
navigate(Destination.ManageAppGroups)
|
||||
}
|
||||
fun navigateAndPopAll(dest: Destination) {
|
||||
navigate(dest)
|
||||
repeat(backstack.size - 1) {
|
||||
backstack.removeFirst()
|
||||
}
|
||||
}
|
||||
fun choosePackage() {
|
||||
navigate(Destination.ApplicationsList(false, true))
|
||||
}
|
||||
fun chooseSinglePackage() {
|
||||
navigate(Destination.ApplicationsList(false, false))
|
||||
}
|
||||
|
||||
entry<Destination.Home> {
|
||||
HomeScreen(::navigate)
|
||||
}
|
||||
entry<Destination.WorkingModes> {
|
||||
WorkModesScreen(vm, it, ::navigateUp, {
|
||||
navigateAndPopAll(Destination.Home)
|
||||
}, {
|
||||
navigateAndPopAll(Destination.WorkingModes(false))
|
||||
}, ::navigate)
|
||||
}
|
||||
entry<Destination.DhizukuServerSettings> {
|
||||
DhizukuServerSettingsScreen(vm.dhizukuClients, vm::getDhizukuClients,
|
||||
vm::updateDhizukuClient, vm::getDhizukuServerEnabled, vm::setDhizukuServerEnabled,
|
||||
::navigateUp)
|
||||
}
|
||||
|
||||
entry<Destination.DelegatedAdmins> {
|
||||
DelegatedAdminsScreen(vm.delegatedAdmins, vm::getDelegatedAdmins, ::navigateUp, ::navigate)
|
||||
}
|
||||
entry<Destination.DelegatedAdminDetails>{
|
||||
AddDelegatedAdminScreen(vm.chosenPackage, ::chooseSinglePackage, it,
|
||||
vm::setDelegatedAdmin, ::navigateUp)
|
||||
}
|
||||
entry<Destination.DeviceInfo> { DeviceInfoScreen(vm, ::navigateUp) }
|
||||
entry<Destination.LockScreenInfo> {
|
||||
LockScreenInfoScreen(vm::getLockScreenInfo, vm::setLockScreenInfo, ::navigateUp)
|
||||
}
|
||||
entry<Destination.SupportMessage> {
|
||||
SupportMessageScreen(vm::getShortSupportMessage, vm::getLongSupportMessage,
|
||||
vm::setShortSupportMessage, vm::setLongSupportMessage, ::navigateUp)
|
||||
}
|
||||
entry<Destination.TransferOwnership> {
|
||||
TransferOwnershipScreen(vm.deviceAdminReceivers, vm::getDeviceAdminReceivers,
|
||||
vm::transferOwnership, ::navigateUp
|
||||
) {
|
||||
navigate(Destination.WorkingModes(false))
|
||||
}
|
||||
}
|
||||
|
||||
entry<Destination.System> { SystemManagerScreen(vm, ::navigateUp, ::navigate) }
|
||||
entry<Destination.SystemOptions> { SystemOptionsScreen(vm, ::navigateUp) }
|
||||
entry<Destination.Keyguard> {
|
||||
KeyguardScreen(vm::setKeyguardDisabled, vm::lockScreen, ::navigateUp)
|
||||
}
|
||||
entry<Destination.HardwareMonitor> {
|
||||
HardwareMonitorScreen(vm.hardwareProperties, vm::getHardwareProperties,
|
||||
vm::setHpRefreshInterval, ::navigateUp)
|
||||
}
|
||||
entry<Destination.DefaultInputMethod> {
|
||||
DefaultInputMethodScreen(vm::getCurrentInputMethod, vm.inputMethodList,
|
||||
vm::getInputMethods, vm::setDefaultInputMethod, ::navigateUp)
|
||||
}
|
||||
entry<Destination.ChangeTime> { ChangeTimeScreen(vm::setTime, ::navigateUp) }
|
||||
entry<Destination.ChangeTimezone> { ChangeTimeZoneScreen(vm::setTimeZone, ::navigateUp) }
|
||||
entry<Destination.AutoTimePolicy> {
|
||||
AutoTimePolicyScreen(vm::getAutoTimePolicy, vm::setAutoTimePolicy, ::navigateUp)
|
||||
}
|
||||
entry<Destination.AutoTimezonePolicy> {
|
||||
AutoTimeZonePolicyScreen(vm::getAutoTimeZonePolicy, vm::setAutoTimeZonePolicy,
|
||||
::navigateUp)
|
||||
}
|
||||
//entry<Destination.> { KeyPairs(::navigateUp) }
|
||||
entry<Destination.ContentProtectionPolicy> {
|
||||
ContentProtectionPolicyScreen(vm::getContentProtectionPolicy,
|
||||
vm::setContentProtectionPolicy, ::navigateUp)
|
||||
}
|
||||
entry<Destination.PermissionPolicy> {
|
||||
PermissionPolicyScreen(vm::getPermissionPolicy, vm::setPermissionPolicy, ::navigateUp)
|
||||
}
|
||||
entry<Destination.MtePolicy> {
|
||||
MtePolicyScreen(vm::getMtePolicy, vm::setMtePolicy, ::navigateUp)
|
||||
}
|
||||
entry<Destination.NearbyStreamingPolicy> {
|
||||
NearbyStreamingPolicyScreen(vm::getNsAppPolicy, vm::setNsAppPolicy,
|
||||
vm::getNsNotificationPolicy, vm::setNsNotificationPolicy, ::navigateUp)
|
||||
}
|
||||
entry<Destination.LockTaskMode> {
|
||||
LockTaskModeScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, ::choosePackage, vm.lockTaskPackages,
|
||||
vm::getLockTaskPackages, vm::setLockTaskPackage, vm::startLockTaskMode,
|
||||
vm:: getLockTaskFeatures, vm::setLockTaskFeatures, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.CaCert> {
|
||||
CaCertScreen(vm.installedCaCerts, vm::getCaCerts, vm.selectedCaCert, vm::selectCaCert, vm::installCaCert, vm::parseCaCert,
|
||||
vm::exportCaCert, vm::uninstallCaCert, vm::uninstallAllCaCerts, ::navigateUp)
|
||||
}
|
||||
entry<Destination.SecurityLogging> {
|
||||
SecurityLoggingScreen(vm::getSecurityLoggingEnabled, vm::setSecurityLoggingEnabled,
|
||||
vm::exportSecurityLogs, vm::getSecurityLogsCount, vm::deleteSecurityLogs,
|
||||
vm::getPreRebootSecurityLogs, vm::exportPreRebootSecurityLogs, ::navigateUp)
|
||||
}
|
||||
entry<Destination.DisableAccountManagement> {
|
||||
DisableAccountManagementScreen(vm.mdAccountTypes, vm::getMdAccountTypes,
|
||||
vm::setMdAccountType, ::navigateUp)
|
||||
}
|
||||
entry<Destination.SystemUpdatePolicy> {
|
||||
SystemUpdatePolicyScreen(vm::getSystemUpdatePolicy, vm::setSystemUpdatePolicy,
|
||||
vm::getPendingSystemUpdate, ::navigateUp)
|
||||
}
|
||||
entry<Destination.InstallSystemUpdate> {
|
||||
InstallSystemUpdateScreen(vm::installSystemUpdate, ::navigateUp)
|
||||
}
|
||||
entry<Destination.FrpPolicy> {
|
||||
FrpPolicyScreen(vm.getFrpPolicy(), vm::setFrpPolicy, ::navigateUp)
|
||||
}
|
||||
entry<Destination.WipeData> { WipeDataScreen(vm::wipeData, ::navigateUp) }
|
||||
|
||||
entry<Destination.Network> { NetworkScreen(::navigateUp, ::navigate) }
|
||||
entry<Destination.WiFi> {
|
||||
WifiScreen(vm, ::navigateUp, ::navigate) { navigate(Destination.UpdateNetwork(it)) }
|
||||
}
|
||||
entry<Destination.NetworkOptions> {
|
||||
NetworkOptionsScreen(vm::getLanEnabled, vm::setLanEnabled, ::navigateUp)
|
||||
}
|
||||
entry<Destination.UpdateNetwork> {
|
||||
val info = vm.configuredNetworks.collectAsStateWithLifecycle().value[
|
||||
it.index
|
||||
]
|
||||
UpdateNetworkScreen(info, vm::setWifi, ::navigateUp)
|
||||
}
|
||||
entry<Destination.WifiSecurityLevel> {
|
||||
WifiSecurityLevelScreen(vm::getMinimumWifiSecurityLevel,
|
||||
vm::setMinimumWifiSecurityLevel, ::navigateUp)
|
||||
}
|
||||
entry<Destination.WifiSsidPolicy> {
|
||||
WifiSsidPolicyScreen(vm::getSsidPolicy, vm::setSsidPolicy, ::navigateUp)
|
||||
}
|
||||
entry<Destination.NetworkStats> {
|
||||
NetworkStatsScreen(vm.chosenPackage, ::chooseSinglePackage, vm::getPackageUid,
|
||||
vm::queryNetworkStats, ::navigateUp) { navigate(Destination.NetworkStatsViewer) }
|
||||
}
|
||||
entry<Destination.NetworkStatsViewer> {
|
||||
NetworkStatsViewerScreen(vm.networkStatsData, vm::clearNetworkStats, ::navigateUp)
|
||||
}
|
||||
entry<Destination.PrivateDns> {
|
||||
PrivateDnsScreen(vm::getPrivateDns, vm::setPrivateDns, ::navigateUp)
|
||||
}
|
||||
entry<Destination.AlwaysOnVpnPackage> {
|
||||
AlwaysOnVpnPackageScreen(vm::getAlwaysOnVpnPackage, vm::getAlwaysOnVpnLockdown,
|
||||
vm::setAlwaysOnVpn, vm.chosenPackage, ::chooseSinglePackage, ::navigateUp)
|
||||
}
|
||||
entry<Destination.RecommendedGlobalProxy> {
|
||||
RecommendedGlobalProxyScreen(vm::setRecommendedGlobalProxy, ::navigateUp)
|
||||
}
|
||||
entry<Destination.NetworkLogging> {
|
||||
NetworkLoggingScreen(vm::getNetworkLoggingEnabled, vm::setNetworkLoggingEnabled,
|
||||
vm::getNetworkLogsCount, vm::exportNetworkLogs, vm::deleteNetworkLogs, ::navigateUp)
|
||||
}
|
||||
//entry<Destination.WifiAuthKeypair> { WifiAuthKeypairScreen(::navigateUp) }
|
||||
entry<Destination.PreferentialNetworkService> {
|
||||
PreferentialNetworkServiceScreen(vm::getPnsEnabled, vm::setPnsEnabled, vm.pnsConfigs,
|
||||
vm::getPnsConfigs, ::navigateUp, ::navigate)
|
||||
}
|
||||
entry<Destination.AddPreferentialNetworkServiceConfig> {
|
||||
val info = vm.pnsConfigs.collectAsStateWithLifecycle().value.getOrNull(
|
||||
it.index
|
||||
) ?: PreferentialNetworkServiceInfo()
|
||||
AddPreferentialNetworkServiceConfigScreen(info, vm::setPnsConfig, ::navigateUp)
|
||||
}
|
||||
entry<Destination.OverrideApn> {
|
||||
OverrideApnScreen(vm.apnConfigs, vm::getApnConfigs, vm::getApnEnabled,
|
||||
vm::setApnEnabled, ::navigateUp) { navigate(Destination.AddApnSetting(it)) }
|
||||
}
|
||||
entry<Destination.AddApnSetting> {
|
||||
val origin = vm.apnConfigs.collectAsStateWithLifecycle().value.getOrNull(it.index)
|
||||
AddApnSettingScreen(vm::setApnConfig, vm::removeApnConfig, origin, ::navigateUp)
|
||||
}
|
||||
|
||||
entry<Destination.WorkProfile> { WorkProfileScreen(::navigateUp, ::navigate) }
|
||||
entry<Destination.OrganizationOwnedProfile> {
|
||||
OrganizationOwnedProfileScreen(vm::activateOrgProfileByShizuku, ::navigateUp)
|
||||
}
|
||||
entry<Destination.CreateWorkProfile> {
|
||||
CreateWorkProfileScreen(vm::createWorkProfile, ::navigateUp)
|
||||
}
|
||||
entry<Destination.SuspendPersonalApp> {
|
||||
SuspendPersonalAppScreen(
|
||||
vm::getPersonalAppsSuspendedReason, vm::setPersonalAppsSuspended,
|
||||
vm::getProfileMaxTimeOff, vm::setProfileMaxTimeOff, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.CrossProfileIntentFilter> {
|
||||
CrossProfileIntentFilterScreen(
|
||||
vm::addCrossProfileIntentFilter, vm::clearCrossProfileIntentFilters,
|
||||
vm::importCrossProfileIntentFilters, vm::exportCrossProfileIntentFilters,
|
||||
::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.DeleteWorkProfile> { DeleteWorkProfileScreen(vm::wipeData, ::navigateUp) }
|
||||
|
||||
entry<Destination.ApplicationsList> { params ->
|
||||
AppChooserScreen(
|
||||
params, vm.installedPackages, vm.refreshPackagesProgress, { name ->
|
||||
if (params.canSwitchView) {
|
||||
if (name == null) {
|
||||
navigateUp()
|
||||
} else {
|
||||
navigate(Destination.ApplicationDetails(name))
|
||||
}
|
||||
} else {
|
||||
if (name != null) vm.chosenPackage.trySend(name)
|
||||
navigateUp()
|
||||
}
|
||||
}, {
|
||||
SP.applicationsListView = false
|
||||
navigate(Destination.ApplicationFunctions)
|
||||
backstack.removeAt(backstack.size - 2)
|
||||
}, vm::refreshPackageList, vm::setPackageSuspended, vm::setPackageHidden)
|
||||
}
|
||||
entry<Destination.ApplicationFunctions> {
|
||||
ApplicationsFeaturesScreen(::navigateUp, ::navigate) {
|
||||
SP.applicationsListView = true
|
||||
navigate(Destination.ApplicationsList(true, true))
|
||||
backstack.removeAt(backstack.size - 2)
|
||||
}
|
||||
}
|
||||
entry<Destination.ApplicationDetails> {
|
||||
ApplicationDetailsScreen(it, vm, ::navigateUp, ::navigate)
|
||||
}
|
||||
entry<Destination.Suspend> {
|
||||
PackageFunctionScreen(
|
||||
R.string.suspend, vm.suspendedPackages, vm::getSuspendedPackaged,
|
||||
vm::setPackageSuspended, ::navigateUp, vm.chosenPackage, ::choosePackage,
|
||||
::navigateToAppGroups, vm.appGroups, R.string.info_suspend_app
|
||||
)
|
||||
}
|
||||
entry<Destination.Hide> {
|
||||
PackageFunctionScreen(
|
||||
R.string.hide, vm.hiddenPackages, vm::getHiddenPackages, vm::setPackageHidden,
|
||||
::navigateUp, vm.chosenPackage, ::choosePackage, ::navigateToAppGroups, vm.appGroups
|
||||
)
|
||||
}
|
||||
entry<Destination.BlockUninstall> {
|
||||
PackageFunctionScreen(
|
||||
R.string.block_uninstall, vm.ubPackages, vm::getUbPackages, vm::setPackageUb,
|
||||
::navigateUp, vm.chosenPackage, ::choosePackage, ::navigateToAppGroups, vm.appGroups
|
||||
)
|
||||
}
|
||||
entry<Destination.DisableUserControl> {
|
||||
PackageFunctionScreen(
|
||||
R.string.disable_user_control, vm.ucdPackages, vm::getUcdPackages,
|
||||
vm::setPackageUcd, ::navigateUp, vm.chosenPackage, ::choosePackage,
|
||||
::navigateToAppGroups, vm.appGroups, R.string.info_disable_user_control
|
||||
)
|
||||
}
|
||||
entry<Destination.AppPermissionsManager> {
|
||||
AppPermissionsManagerScreen(
|
||||
vm::getPackagePermissions, vm::setPackagePermission, ::navigateUp, it
|
||||
)
|
||||
}
|
||||
entry<Destination.PermissionManager> {
|
||||
PermissionManagerScreen(::navigate, ::navigateUp)
|
||||
}
|
||||
entry<Destination.PermissionDetail> {
|
||||
PermissionDetailScreen(
|
||||
it, vm::getPermissionPackages, vm::setPackagePermission, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.DisableMeteredData> {
|
||||
PackageFunctionScreen(
|
||||
R.string.disable_metered_data, vm.mddPackages, vm::getMddPackages,
|
||||
vm::setPackageMdd, ::navigateUp, vm.chosenPackage, ::choosePackage,
|
||||
::navigateToAppGroups, vm.appGroups
|
||||
)
|
||||
}
|
||||
entry<Destination.ClearAppStorage> {
|
||||
ClearAppStorageScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::clearAppData, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.UninstallApp> {
|
||||
UninstallAppScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::uninstallPackage, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.KeepUninstalledPackages> {
|
||||
PackageFunctionScreen(
|
||||
R.string.keep_uninstalled_packages, vm.kuPackages, vm::getKuPackages,
|
||||
vm::setPackageKu, ::navigateUp, vm.chosenPackage, ::choosePackage,
|
||||
::navigateToAppGroups, vm.appGroups, R.string.info_keep_uninstalled_apps
|
||||
)
|
||||
}
|
||||
entry<Destination.InstallExistingApp> {
|
||||
InstallExistingAppScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::installExistingApp, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.CrossProfilePackages> {
|
||||
PackageFunctionScreen(
|
||||
R.string.cross_profile_apps, vm.cpPackages,
|
||||
vm::getCpPackages, vm::setPackageCp, ::navigateUp, vm.chosenPackage,
|
||||
::choosePackage, ::navigateToAppGroups, vm.appGroups
|
||||
)
|
||||
}
|
||||
entry<Destination.CrossProfileWidgetProviders> {
|
||||
PackageFunctionScreen(R.string.cross_profile_widget, vm.cpwProviders,
|
||||
vm::getCpwProviders, vm::setCpwProvider, ::navigateUp, vm.chosenPackage,
|
||||
::choosePackage, ::navigateToAppGroups, vm.appGroups)
|
||||
}
|
||||
entry<Destination.CredentialManagerPolicy> {
|
||||
CredentialManagerPolicyScreen(
|
||||
vm.chosenPackage, ::choosePackage, vm.cmPackages, vm::getCmPolicy,
|
||||
vm::setCmPackage, vm::setCmPolicy, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.PermittedAccessibilityServices> {
|
||||
PermittedAsAndImPackages(
|
||||
R.string.permitted_accessibility_services,
|
||||
R.string.system_accessibility_always_allowed, vm.chosenPackage, ::choosePackage,
|
||||
vm.pasPackages, vm::getPasPackages, vm::setPasPackage, vm::setPasPolicy,
|
||||
::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.PermittedInputMethods> {
|
||||
PermittedAsAndImPackages(
|
||||
R.string.permitted_ime, R.string.system_ime_always_allowed,
|
||||
vm.chosenPackage, ::choosePackage, vm.pimPackages, vm::getPimPackages,
|
||||
vm::setPimPackage, vm::setPimPolicy, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.EnableSystemApp> {
|
||||
EnableSystemAppScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::enableSystemApp, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.SetDefaultDialer> {
|
||||
SetDefaultDialerScreen(
|
||||
vm.chosenPackage, ::chooseSinglePackage, vm::setDefaultDialer, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.ManagedConfiguration> {
|
||||
ManagedConfigurationScreen(
|
||||
it, vm.appRestrictions, vm::setAppRestrictions,
|
||||
vm::clearAppRestrictions, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.ManageAppGroups> {
|
||||
ManageAppGroupsScreen(
|
||||
vm.appGroups, vm::exportAppGroups, vm::importAppGroups,
|
||||
{ id, name, apps -> navigate(Destination.EditAppGroup(id, name, apps)) },
|
||||
::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.EditAppGroup> {
|
||||
EditAppGroupScreen(
|
||||
it, vm::getAppInfo, ::navigateUp, vm::setAppGroup,
|
||||
vm::deleteAppGroup, ::choosePackage, vm.chosenPackage
|
||||
)
|
||||
}
|
||||
|
||||
entry<Destination.UserRestriction> {
|
||||
UserRestrictionScreen(vm::getUserRestrictions, ::navigateUp, ::navigate)
|
||||
}
|
||||
entry<Destination.UserRestrictionEditor> {
|
||||
UserRestrictionEditorScreen(vm.userRestrictions, vm::setUserRestriction, ::navigateUp)
|
||||
}
|
||||
entry<Destination.UserRestrictionOptions> {
|
||||
UserRestrictionOptionsScreen(it, vm.userRestrictions,
|
||||
vm::setUserRestriction, vm::createUserRestrictionShortcut, ::navigateUp)
|
||||
}
|
||||
|
||||
entry<Destination.Users> { UsersScreen(vm, ::navigateUp, ::navigate) }
|
||||
entry<Destination.UserInfo> { UserInfoScreen(vm::getUserInformation, ::navigateUp) }
|
||||
entry<Destination.UsersOptions> {
|
||||
UsersOptionsScreen(vm::getLogoutEnabled, vm::setLogoutEnabled, ::navigateUp)
|
||||
}
|
||||
entry<Destination.UserOperation> {
|
||||
UserOperationScreen(vm::getUserIdentifiers, vm::doUserOperation,
|
||||
vm::createUserOperationShortcut, ::navigateUp)
|
||||
}
|
||||
entry<Destination.CreateUser> { CreateUserScreen(vm::createUser, ::navigateUp) }
|
||||
entry<Destination.ChangeUsername> { ChangeUsernameScreen(vm::setProfileName, ::navigateUp) }
|
||||
entry<Destination.UserSessionMessage> {
|
||||
UserSessionMessageScreen(vm::getUserSessionMessages, vm::setStartUserSessionMessage,
|
||||
vm::setEndUserSessionMessage, ::navigateUp)
|
||||
}
|
||||
entry<Destination.AffiliationId> {
|
||||
AffiliationIdScreen(vm.affiliationIds, vm::getAffiliationIds, vm::setAffiliationId,
|
||||
::navigateUp)
|
||||
}
|
||||
|
||||
entry<Destination.Password> { PasswordScreen(vm, ::navigateUp, ::navigate) }
|
||||
entry<Destination.PasswordInfo> {
|
||||
PasswordInfoScreen(vm::getPasswordComplexity, vm::isPasswordComplexitySufficient,
|
||||
vm::isUsingUnifiedPassword, ::navigateUp)
|
||||
}
|
||||
entry<Destination.ResetPasswordToken> {
|
||||
ResetPasswordTokenScreen(vm::getRpTokenState, vm::setRpToken,
|
||||
vm::createActivateRpTokenIntent, vm::clearRpToken, ::navigateUp)
|
||||
}
|
||||
entry<Destination.ResetPassword> { ResetPasswordScreen(vm::resetPassword, ::navigateUp) }
|
||||
entry<Destination.RequiredPasswordComplexity> {
|
||||
RequiredPasswordComplexityScreen(vm::getRequiredPasswordComplexity,
|
||||
vm::setRequiredPasswordComplexity, ::navigateUp)
|
||||
}
|
||||
entry<Destination.KeyguardDisabledFeatures> {
|
||||
KeyguardDisabledFeaturesScreen(vm::getKeyguardDisableConfig,
|
||||
vm::setKeyguardDisableConfig, ::navigateUp)
|
||||
}
|
||||
entry<Destination.RequiredPasswordQuality> { RequiredPasswordQualityScreen(::navigateUp) }
|
||||
|
||||
entry<Destination.Settings> { SettingsScreen(::navigate, ::navigateUp) }
|
||||
entry<Destination.SettingsOptions> {
|
||||
SettingsOptionsScreen(
|
||||
vm::getDisplayDangerousFeatures, vm::getShortcutsEnabled,
|
||||
vm::setDisplayDangerousFeatures, vm::setShortcutsEnabled, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.AppearanceSettings> {
|
||||
AppearanceScreen(::navigateUp, vm.theme, vm::changeTheme)
|
||||
}
|
||||
entry<Destination.AppLockSettings> {
|
||||
AppLockSettingsScreen(vm.getAppLockConfig(), vm::setAppLockConfig, ::navigateUp)
|
||||
}
|
||||
entry<Destination.ApiSettings> {
|
||||
ApiSettings(vm::getApiEnabled, vm::setApiKey, ::navigateUp)
|
||||
}
|
||||
entry<Destination.NotificationSettings> {
|
||||
NotificationsScreen(
|
||||
vm.enabledNotifications, vm::getEnabledNotifications,
|
||||
vm::setNotificationEnabled, ::navigateUp
|
||||
)
|
||||
}
|
||||
entry<Destination.About> { AboutScreen(::navigateUp) }
|
||||
}(destination) as NavEntry<NavKey>
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT
|
||||
import android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
|
||||
@@ -33,12 +33,10 @@ import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.List
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
@@ -99,12 +97,10 @@ import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
@@ -117,6 +113,8 @@ import com.bintianqi.owndroid.MyViewModel
|
||||
import com.bintianqi.owndroid.Privilege
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.adaptiveInsets
|
||||
import com.bintianqi.owndroid.dpm.PermissionItem
|
||||
import com.bintianqi.owndroid.dpm.runtimePermissions
|
||||
import com.bintianqi.owndroid.parsePackageNames
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
||||
@@ -126,7 +124,9 @@ import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.MySmallTitleScaffold
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.PackageNameTextField
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -166,33 +166,11 @@ fun LazyItemScope.ApplicationItem(info: AppInfo, onClear: () -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PackageNameTextField(
|
||||
value: String, onChoosePackage: () -> Unit,
|
||||
modifier: Modifier = Modifier, onValueChange: (String) -> Unit
|
||||
) {
|
||||
val fm = LocalFocusManager.current
|
||||
OutlinedTextField(
|
||||
value, onValueChange, Modifier
|
||||
.fillMaxWidth()
|
||||
.then(modifier),
|
||||
label = { Text(stringResource(R.string.package_name)) },
|
||||
trailingIcon = {
|
||||
IconButton(onChoosePackage) {
|
||||
Icon(Icons.AutoMirrored.Default.List, null)
|
||||
}
|
||||
},
|
||||
isError = value.isNotEmpty() && !value.isValidPackageName,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions { fm.clearFocus() }
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object ApplicationsFeatures
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ApplicationsFeaturesScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onSwitchView: () -> Unit) {
|
||||
fun ApplicationsFeaturesScreen(
|
||||
onNavigateUp: () -> Unit, onNavigate: (Destination) -> Unit, onSwitchView: () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val sb = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
Scaffold(
|
||||
@@ -219,56 +197,82 @@ fun ApplicationsFeaturesScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Un
|
||||
.padding(bottom = 80.dp)
|
||||
) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
if(VERSION.SDK_INT >= 24) FunctionItem(R.string.suspend, icon = R.drawable.block_fill0) { onNavigate(Suspend) }
|
||||
FunctionItem(R.string.hide, icon = R.drawable.visibility_off_fill0) { onNavigate(Hide) }
|
||||
FunctionItem(R.string.block_uninstall, icon = R.drawable.delete_forever_fill0) { onNavigate(BlockUninstall) }
|
||||
if(VERSION.SDK_INT >= 24) FunctionItem(R.string.suspend, icon = R.drawable.block_fill0) {
|
||||
onNavigate(Destination.Suspend)
|
||||
}
|
||||
FunctionItem(R.string.hide, icon = R.drawable.visibility_off_fill0) {
|
||||
onNavigate(Destination.Hide)
|
||||
}
|
||||
FunctionItem(R.string.block_uninstall, icon = R.drawable.delete_forever_fill0) {
|
||||
onNavigate(Destination.BlockUninstall)
|
||||
}
|
||||
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) }
|
||||
FunctionItem(R.string.disable_user_control, icon = R.drawable.do_not_touch_fill0) {
|
||||
onNavigate(Destination.DisableUserControl)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.permissions, icon = R.drawable.shield_fill0) {
|
||||
onNavigate(PermissionManager)
|
||||
onNavigate(Destination.PermissionManager)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28) {
|
||||
FunctionItem(R.string.disable_metered_data, icon = R.drawable.money_off_fill0) { onNavigate(DisableMeteredData) }
|
||||
FunctionItem(R.string.disable_metered_data, icon = R.drawable.money_off_fill0) {
|
||||
onNavigate(Destination.DisableMeteredData)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28) {
|
||||
FunctionItem(R.string.clear_app_storage, icon = R.drawable.mop_fill0) { onNavigate(ClearAppStorage) }
|
||||
FunctionItem(R.string.clear_app_storage, icon = R.drawable.mop_fill0) {
|
||||
onNavigate(Destination.ClearAppStorage)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.install_app, icon = R.drawable.install_mobile_fill0) {
|
||||
context.startActivity(Intent(context, AppInstallerActivity::class.java))
|
||||
}
|
||||
FunctionItem(R.string.uninstall_app, icon = R.drawable.delete_fill0) { onNavigate(UninstallApp) }
|
||||
FunctionItem(R.string.uninstall_app, icon = R.drawable.delete_fill0) {
|
||||
onNavigate(Destination.UninstallApp)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.keep_uninstalled_packages, icon = R.drawable.delete_fill0) { onNavigate(KeepUninstalledPackages) }
|
||||
FunctionItem(R.string.keep_uninstalled_packages, icon = R.drawable.delete_fill0) {
|
||||
onNavigate(Destination.KeepUninstalledPackages)
|
||||
}
|
||||
}
|
||||
if (VERSION.SDK_INT >= 28 && (privilege.device || (privilege.profile && privilege.affiliated))) {
|
||||
FunctionItem(R.string.install_existing_app, icon = R.drawable.install_mobile_fill0) {
|
||||
onNavigate(InstallExistingApp)
|
||||
onNavigate(Destination.InstallExistingApp)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 30 && privilege.work) {
|
||||
FunctionItem(R.string.cross_profile_apps, icon = R.drawable.work_fill0) { onNavigate(CrossProfilePackages) }
|
||||
FunctionItem(R.string.cross_profile_apps, icon = R.drawable.work_fill0) {
|
||||
onNavigate(Destination.CrossProfilePackages)
|
||||
}
|
||||
}
|
||||
if(privilege.work) {
|
||||
FunctionItem(R.string.cross_profile_widget, icon = R.drawable.widgets_fill0) { onNavigate(CrossProfileWidgetProviders) }
|
||||
FunctionItem(R.string.cross_profile_widget, icon = R.drawable.widgets_fill0) {
|
||||
onNavigate(Destination.CrossProfileWidgetProviders)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 34 && privilege.device) {
|
||||
FunctionItem(R.string.credential_manager_policy, icon = R.drawable.license_fill0) { onNavigate(CredentialManagerPolicy) }
|
||||
FunctionItem(R.string.credential_manager_policy, icon = R.drawable.license_fill0) {
|
||||
onNavigate(Destination.CredentialManagerPolicy)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.permitted_accessibility_services, icon = R.drawable.settings_accessibility_fill0) {
|
||||
onNavigate(PermittedAccessibilityServices)
|
||||
onNavigate(Destination.PermittedAccessibilityServices)
|
||||
}
|
||||
FunctionItem(R.string.permitted_ime, icon = R.drawable.keyboard_fill0) {
|
||||
onNavigate(Destination.PermittedInputMethods)
|
||||
}
|
||||
FunctionItem(R.string.enable_system_app, icon = R.drawable.enable_fill0) {
|
||||
onNavigate(Destination.EnableSystemApp)
|
||||
}
|
||||
FunctionItem(R.string.permitted_ime, icon = R.drawable.keyboard_fill0) { onNavigate(PermittedInputMethods) }
|
||||
FunctionItem(R.string.enable_system_app, icon = R.drawable.enable_fill0) { onNavigate(EnableSystemApp) }
|
||||
if(VERSION.SDK_INT >= 34 && (privilege.device || privilege.work)) {
|
||||
FunctionItem(R.string.set_default_dialer, icon = R.drawable.call_fill0) { onNavigate(SetDefaultDialer) }
|
||||
FunctionItem(R.string.set_default_dialer, icon = R.drawable.call_fill0) {
|
||||
onNavigate(Destination.SetDefaultDialer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable data class ApplicationDetails(val packageName: String)
|
||||
|
||||
data class AppStatus(
|
||||
val suspend: Boolean,
|
||||
val hide: Boolean,
|
||||
@@ -280,7 +284,8 @@ data class AppStatus(
|
||||
|
||||
@Composable
|
||||
fun ApplicationDetailsScreen(
|
||||
param: ApplicationDetails, vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit
|
||||
param: Destination.ApplicationDetails, vm: MyViewModel, onNavigateUp: () -> Unit,
|
||||
onNavigate: (Destination) -> Unit
|
||||
) {
|
||||
val packageName = param.packageName
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
@@ -302,7 +307,9 @@ fun ApplicationDetailsScreen(
|
||||
.alpha(0.7F)
|
||||
.padding(bottom = 8.dp), style = typography.bodyMedium)
|
||||
}
|
||||
FunctionItem(R.string.permissions, icon = R.drawable.shield_fill0) { onNavigate(AppPermissionsManager(packageName)) }
|
||||
FunctionItem(R.string.permissions, icon = R.drawable.shield_fill0) {
|
||||
onNavigate(Destination.AppPermissionsManager(packageName))
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24) SwitchItem(
|
||||
R.string.suspend, icon = R.drawable.block_fill0, state = status.suspend,
|
||||
onCheckedChange = { vm.adSetPackageSuspended(packageName, it) }
|
||||
@@ -334,7 +341,7 @@ fun ApplicationDetailsScreen(
|
||||
)
|
||||
if (appRestrictions.isNotEmpty()) {
|
||||
FunctionItem(R.string.managed_configuration, icon = R.drawable.description_fill0) {
|
||||
onNavigate(ManagedConfiguration(packageName))
|
||||
onNavigate(Destination.ManagedConfiguration(packageName))
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28) FunctionItem(R.string.clear_app_storage, icon = R.drawable.mop_fill0) { dialog = 1 }
|
||||
@@ -349,21 +356,11 @@ fun ApplicationDetailsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object Suspend
|
||||
|
||||
@Serializable object Hide
|
||||
|
||||
@Serializable object BlockUninstall
|
||||
|
||||
@Serializable object DisableUserControl
|
||||
|
||||
@Serializable data class AppPermissionsManager(val packageName: String)
|
||||
|
||||
@Composable
|
||||
fun AppPermissionsManagerScreen(
|
||||
getPackagePermissions: (String) -> Map<String, Int>,
|
||||
setPackagePermission: (String, String, Int) -> Boolean, onNavigateUp: () -> Unit,
|
||||
param: AppPermissionsManager
|
||||
param: Destination.AppPermissionsManager
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
@@ -453,10 +450,10 @@ fun PackagePermissionDialog(
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object PermissionManager
|
||||
|
||||
@Composable
|
||||
fun PermissionManagerScreen(onNavigate: (PermissionDetail) -> Unit, onNavigateUp: () -> Unit) {
|
||||
fun PermissionManagerScreen(
|
||||
onNavigate: (Destination.PermissionDetail) -> Unit, onNavigateUp: () -> Unit
|
||||
) {
|
||||
MyLazyScaffold(R.string.permissions, onNavigateUp) {
|
||||
items(runtimePermissions) {
|
||||
Row(
|
||||
@@ -464,7 +461,7 @@ fun PermissionManagerScreen(onNavigate: (PermissionDetail) -> Unit, onNavigateUp
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
onNavigate(PermissionDetail(it.id))
|
||||
onNavigate(Destination.PermissionDetail(it.id))
|
||||
}
|
||||
.padding(8.dp, 12.dp)
|
||||
) {
|
||||
@@ -478,12 +475,10 @@ fun PermissionManagerScreen(onNavigate: (PermissionDetail) -> Unit, onNavigateUp
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable class PermissionDetail(val permission: String)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun PermissionDetailScreen(
|
||||
param: PermissionDetail, getPermissionPackages: (String) -> List<Pair<AppInfo, Int>>,
|
||||
param: Destination.PermissionDetail, getPermissionPackages: (String) -> List<Pair<AppInfo, Int>>,
|
||||
setPackagePermission: (String, String, Int) -> Boolean, onNavigateUp: () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
@@ -586,10 +581,6 @@ fun PermissionDetailScreen(
|
||||
) { selectedPackage = null }
|
||||
}
|
||||
|
||||
@Serializable object DisableMeteredData
|
||||
|
||||
@Serializable object ClearAppStorage
|
||||
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
fun ClearAppStorageScreen(
|
||||
@@ -653,8 +644,6 @@ private fun ClearAppStorageDialog(
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object UninstallApp
|
||||
|
||||
@Composable
|
||||
fun UninstallAppScreen(
|
||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
||||
@@ -722,10 +711,6 @@ private fun UninstallAppDialog(
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object KeepUninstalledPackages
|
||||
|
||||
@Serializable object InstallExistingApp
|
||||
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
fun InstallExistingAppScreen(
|
||||
@@ -752,12 +737,6 @@ fun InstallExistingAppScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object CrossProfilePackages
|
||||
|
||||
@Serializable object CrossProfileWidgetProviders
|
||||
|
||||
@Serializable object CredentialManagerPolicy
|
||||
|
||||
@RequiresApi(34)
|
||||
@Composable
|
||||
fun CredentialManagerPolicyScreen(
|
||||
@@ -819,10 +798,6 @@ fun CredentialManagerPolicyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object PermittedAccessibilityServices
|
||||
|
||||
@Serializable object PermittedInputMethods
|
||||
|
||||
@Composable
|
||||
fun PermittedAsAndImPackages(
|
||||
title: Int, note: Int, chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
||||
@@ -879,8 +854,6 @@ fun PermittedAsAndImPackages(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object EnableSystemApp
|
||||
|
||||
@Composable
|
||||
fun EnableSystemAppScreen(
|
||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
||||
@@ -910,8 +883,6 @@ fun EnableSystemAppScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object SetDefaultDialer
|
||||
|
||||
@RequiresApi(34)
|
||||
@Composable
|
||||
fun SetDefaultDialerScreen(
|
||||
@@ -1072,8 +1043,6 @@ class AppGroup(
|
||||
val id: Int, override val name: String, override val apps: List<String>
|
||||
) : BasicAppGroup(name, apps)
|
||||
|
||||
@Serializable object ManageAppGroups
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ManageAppGroupsScreen(
|
||||
@@ -1158,12 +1127,10 @@ fun ManageAppGroupsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable class EditAppGroup(val id: Int?, val name: String, val apps: List<String>)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun EditAppGroupScreen(
|
||||
params: EditAppGroup, getAppInfo: (String) -> AppInfo, navigateUp: () -> Unit,
|
||||
params: Destination.EditAppGroup, getAppInfo: (String) -> AppInfo, navigateUp: () -> Unit,
|
||||
setGroup: (Int?, String, List<String>) -> Unit, deleteGroup: (Int) -> Unit,
|
||||
onChoosePackage: () -> Unit, chosenPackage: Channel<String>
|
||||
) {
|
||||
@@ -1239,12 +1206,10 @@ fun EditAppGroupScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable class ManagedConfiguration(val packageName: String)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ManagedConfigurationScreen(
|
||||
params: ManagedConfiguration, appRestrictions: StateFlow<List<AppRestriction>>,
|
||||
params: Destination.ManagedConfiguration, appRestrictions: StateFlow<List<AppRestriction>>,
|
||||
setRestriction: (String, AppRestriction) -> Unit, clearRestriction: (String) -> Unit,
|
||||
navigateUp: () -> Unit
|
||||
) {
|
||||
120
app/src/main/java/com/bintianqi/owndroid/ui/screen/Home.kt
Normal file
120
app/src/main/java/com/bintianqi/owndroid/ui/screen/Home.kt
Normal file
@@ -0,0 +1,120 @@
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.os.Build.VERSION
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.BottomPadding
|
||||
import com.bintianqi.owndroid.Privilege
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.SP
|
||||
import com.bintianqi.owndroid.adaptiveInsets
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun HomeScreen(onNavigate: (Destination) -> Unit) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
val sb = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
Scaffold(
|
||||
Modifier.nestedScroll(sb.nestedScrollConnection),
|
||||
topBar = {
|
||||
LargeTopAppBar(
|
||||
{ Text(stringResource(R.string.app_name)) },
|
||||
actions = {
|
||||
IconButton({ onNavigate(Destination.WorkingModes(true)) }) {
|
||||
Icon(
|
||||
painterResource(R.drawable.security_fill0), null
|
||||
)
|
||||
}
|
||||
IconButton({ onNavigate(Destination.Settings) }) {
|
||||
Icon(Icons.Default.Settings, null)
|
||||
}
|
||||
},
|
||||
scrollBehavior = sb
|
||||
)
|
||||
},
|
||||
contentWindowInsets = adaptiveInsets()
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(it)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
if (privilege.device || privilege.profile) {
|
||||
HomePageItem(R.string.system, R.drawable.android_fill0) {
|
||||
onNavigate(Destination.System)
|
||||
}
|
||||
HomePageItem(R.string.network, R.drawable.wifi_fill0) { onNavigate(Destination.Network) }
|
||||
}
|
||||
if (privilege.work) {
|
||||
HomePageItem(R.string.work_profile, R.drawable.work_fill0) {
|
||||
onNavigate(Destination.WorkProfile)
|
||||
}
|
||||
}
|
||||
if (privilege.device || privilege.profile) {
|
||||
HomePageItem(R.string.applications, R.drawable.apps_fill0) {
|
||||
onNavigate(
|
||||
if (SP.applicationsListView) Destination.ApplicationsList(true, true)
|
||||
else Destination.ApplicationFunctions
|
||||
)
|
||||
}
|
||||
if (VERSION.SDK_INT >= 24) {
|
||||
HomePageItem(R.string.user_restriction, R.drawable.person_off) {
|
||||
onNavigate(Destination.UserRestriction)
|
||||
}
|
||||
}
|
||||
HomePageItem(R.string.users, R.drawable.manage_accounts_fill0) {
|
||||
onNavigate(Destination.Users)
|
||||
}
|
||||
HomePageItem(
|
||||
R.string.password_and_keyguard, R.drawable.password_fill0
|
||||
) { onNavigate(Destination.Password) }
|
||||
}
|
||||
Spacer(Modifier.height(BottomPadding))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HomePageItem(name: Int, icon: Int, onClick: () -> Unit) {
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick)
|
||||
.padding(vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Spacer(Modifier.padding(start = 30.dp))
|
||||
Icon(painterResource(icon), null)
|
||||
Spacer(Modifier.padding(start = 15.dp))
|
||||
Text(stringResource(name), style = typography.headlineSmall)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
@@ -128,7 +128,9 @@ import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.MySmallTitleScaffold
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.PackageNameTextField
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.bintianqi.owndroid.writeClipBoard
|
||||
import com.bintianqi.owndroid.yesOrNo
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
@@ -142,44 +144,58 @@ import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
@Serializable object Network
|
||||
|
||||
@Composable
|
||||
fun NetworkScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
fun NetworkScreen(onNavigateUp: () -> Unit, onNavigate: (Destination) -> Unit) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
MyScaffold(R.string.network, onNavigateUp, 0.dp) {
|
||||
if(!privilege.dhizuku) FunctionItem(R.string.wifi, icon = R.drawable.wifi_fill0) { onNavigate(WiFi) }
|
||||
if(!privilege.dhizuku) FunctionItem(R.string.wifi, icon = R.drawable.wifi_fill0) {
|
||||
onNavigate(Destination.WiFi)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 30) {
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(NetworkOptions) }
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) {
|
||||
onNavigate(Destination.NetworkOptions)
|
||||
}
|
||||
}
|
||||
if (!privilege.dhizuku)
|
||||
FunctionItem(R.string.network_stats, icon = R.drawable.query_stats_fill0) { onNavigate(QueryNetworkStats) }
|
||||
FunctionItem(R.string.network_stats, icon = R.drawable.query_stats_fill0) {
|
||||
onNavigate(Destination.NetworkStats)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 29 && privilege.device) {
|
||||
FunctionItem(R.string.private_dns, icon = R.drawable.dns_fill0) { onNavigate(PrivateDns) }
|
||||
FunctionItem(R.string.private_dns, icon = R.drawable.dns_fill0) {
|
||||
onNavigate(Destination.PrivateDns)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24) {
|
||||
FunctionItem(R.string.always_on_vpn, icon = R.drawable.vpn_key_fill0) { onNavigate(AlwaysOnVpnPackage) }
|
||||
FunctionItem(R.string.always_on_vpn, icon = R.drawable.vpn_key_fill0) {
|
||||
onNavigate(Destination.AlwaysOnVpnPackage)
|
||||
}
|
||||
}
|
||||
if(privilege.device) {
|
||||
FunctionItem(R.string.recommended_global_proxy, icon = R.drawable.vpn_key_fill0) { onNavigate(RecommendedGlobalProxy) }
|
||||
FunctionItem(R.string.recommended_global_proxy, icon = R.drawable.vpn_key_fill0) {
|
||||
onNavigate(Destination.RecommendedGlobalProxy)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && !privilege.dhizuku && (privilege.device || privilege.work)) {
|
||||
FunctionItem(R.string.network_logging, icon = R.drawable.description_fill0) { onNavigate(NetworkLogging) }
|
||||
FunctionItem(R.string.network_logging, icon = R.drawable.description_fill0) {
|
||||
onNavigate(Destination.NetworkLogging)
|
||||
}
|
||||
}
|
||||
/*if(VERSION.SDK_INT >= 31) {
|
||||
FunctionItem(R.string.wifi_auth_keypair, icon = R.drawable.key_fill0) { onNavigate(WifiAuthKeypair) }
|
||||
FunctionItem(R.string.wifi_auth_keypair, icon = R.drawable.key_fill0) { onNavigate(Destination.WifiAuthKeypair) }
|
||||
}*/
|
||||
if (VERSION.SDK_INT >= 33 && (privilege.work || privilege.device)) {
|
||||
FunctionItem(R.string.preferential_network_service, icon = R.drawable.globe_fill0) { onNavigate(PreferentialNetworkService) }
|
||||
FunctionItem(R.string.preferential_network_service, icon = R.drawable.globe_fill0) {
|
||||
onNavigate(Destination.PreferentialNetworkService)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.override_apn, icon = R.drawable.cell_tower_fill0) { onNavigate(OverrideApn) }
|
||||
FunctionItem(R.string.override_apn, icon = R.drawable.cell_tower_fill0) {
|
||||
onNavigate(Destination.OverrideApn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object NetworkOptions
|
||||
|
||||
@Composable
|
||||
fun NetworkOptionsScreen(
|
||||
getLanEnabled: () -> Boolean, setLanEnabled: (Boolean) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -208,12 +224,10 @@ fun NetworkOptionsScreen(
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object WiFi
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WifiScreen(
|
||||
vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit,
|
||||
vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Destination) -> Unit,
|
||||
editNetwork: (Int) -> Unit
|
||||
) {
|
||||
val coroutine = rememberCoroutineScope()
|
||||
@@ -266,7 +280,7 @@ fun WifiScreen(
|
||||
@Composable
|
||||
fun WifiOverviewScreen(
|
||||
setWifiEnabled: (Boolean) -> Boolean, disconnect: () -> Boolean, reconnect: () -> Boolean,
|
||||
getMac: () -> String?, navigate: (Any) -> Unit
|
||||
getMac: () -> String?, navigate: (Destination) -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
@@ -305,8 +319,12 @@ fun WifiOverviewScreen(
|
||||
FunctionItem(R.string.wifi_mac_address) { macDialog = true }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 33 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.min_wifi_security_level) { navigate(WifiSecurityLevel) }
|
||||
FunctionItem(R.string.wifi_ssid_policy) { navigate(WifiSsidPolicyScreen) }
|
||||
FunctionItem(R.string.min_wifi_security_level) {
|
||||
navigate(Destination.WifiSecurityLevel)
|
||||
}
|
||||
FunctionItem(R.string.wifi_ssid_policy) {
|
||||
navigate(Destination.WifiSsidPolicy)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (macDialog && VERSION.SDK_INT >= 24) {
|
||||
@@ -503,9 +521,6 @@ private fun SavedNetworks(
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class UpdateNetwork(val index: Int)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun UpdateNetworkScreen(info: WifiInfo, setNetwork: (WifiInfo) -> Boolean, onNavigateUp: () -> Unit) {
|
||||
@@ -813,8 +828,6 @@ private fun AddNetworkScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object WifiSecurityLevel
|
||||
|
||||
@RequiresApi(33)
|
||||
@Composable
|
||||
fun WifiSecurityLevelScreen(
|
||||
@@ -849,8 +862,6 @@ enum class SsidPolicyType(val id: Int, val text: Int) {
|
||||
Blacklist(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST, R.string.blacklist)
|
||||
}
|
||||
|
||||
@Serializable object WifiSsidPolicyScreen
|
||||
|
||||
@RequiresApi(33)
|
||||
@Composable
|
||||
fun WifiSsidPolicyScreen(
|
||||
@@ -948,8 +959,6 @@ data class QueryNetworkStatsParams(
|
||||
val startTime: Long, val endTime: Long, val uid: Int, val tag: Int, val state: NetworkStatsState
|
||||
)
|
||||
|
||||
@Serializable object QueryNetworkStats
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun NetworkStatsScreen(
|
||||
@@ -1266,8 +1275,6 @@ data class NetworkStatsData(
|
||||
val metered: Int?
|
||||
)
|
||||
|
||||
@Serializable object NetworkStatsViewer
|
||||
|
||||
@Composable
|
||||
fun NetworkStatsViewerScreen(
|
||||
data: List<NetworkStatsData>, clearData: () -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -1372,8 +1379,6 @@ enum class PrivateDnsMode(val id: Int, val text: Int) {
|
||||
|
||||
data class PrivateDnsConfiguration(val mode: PrivateDnsMode?, val host: String)
|
||||
|
||||
@Serializable object PrivateDns
|
||||
|
||||
@RequiresApi(29)
|
||||
@Composable
|
||||
fun PrivateDnsScreen(
|
||||
@@ -1413,8 +1418,6 @@ fun PrivateDnsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object AlwaysOnVpnPackage
|
||||
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun AlwaysOnVpnPackageScreen(
|
||||
@@ -1464,8 +1467,6 @@ data class RecommendedProxyConf(
|
||||
val port: Int, val exclude: List<String>
|
||||
)
|
||||
|
||||
@Serializable object RecommendedGlobalProxy
|
||||
|
||||
@Composable
|
||||
fun RecommendedGlobalProxyScreen(
|
||||
setProxy: (RecommendedProxyConf) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -1538,8 +1539,6 @@ fun RecommendedGlobalProxyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object NetworkLogging
|
||||
|
||||
@RequiresApi(26)
|
||||
@Composable
|
||||
fun NetworkLoggingScreen(
|
||||
@@ -1620,14 +1619,12 @@ fun NetworkLoggingScreen(
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object PreferentialNetworkService
|
||||
|
||||
@RequiresApi(33)
|
||||
@Composable
|
||||
fun PreferentialNetworkServiceScreen(
|
||||
getEnabled: () -> Boolean, setEnabled: (Boolean) -> Unit,
|
||||
pnsConfigs: StateFlow<List<PreferentialNetworkServiceInfo>>, getConfigs: () -> Unit,
|
||||
onNavigateUp: () -> Unit, onNavigate: (AddPreferentialNetworkServiceConfig) -> Unit
|
||||
onNavigateUp: () -> Unit, onNavigate: (Destination.AddPreferentialNetworkServiceConfig) -> Unit
|
||||
) {
|
||||
var masterEnabled by rememberSaveable { mutableStateOf(getEnabled()) }
|
||||
val configs by pnsConfigs.collectAsStateWithLifecycle()
|
||||
@@ -1647,7 +1644,7 @@ fun PreferentialNetworkServiceScreen(
|
||||
) {
|
||||
Text(config.id.toString())
|
||||
IconButton({
|
||||
onNavigate(AddPreferentialNetworkServiceConfig(index))
|
||||
onNavigate(Destination.AddPreferentialNetworkServiceConfig(index))
|
||||
}) {
|
||||
Icon(Icons.Default.Edit, stringResource(R.string.edit))
|
||||
}
|
||||
@@ -1656,7 +1653,7 @@ fun PreferentialNetworkServiceScreen(
|
||||
Row(
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(top = 4.dp)
|
||||
.clickable { onNavigate(AddPreferentialNetworkServiceConfig(-1)) }
|
||||
.clickable { onNavigate(Destination.AddPreferentialNetworkServiceConfig(-1)) }
|
||||
.padding(horizontal = 8.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
@@ -1675,9 +1672,6 @@ data class PreferentialNetworkServiceInfo(
|
||||
val includedUids: List<Int> = emptyList()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class AddPreferentialNetworkServiceConfig(val index: Int)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(33)
|
||||
@Composable
|
||||
@@ -1769,8 +1763,6 @@ fun AddPreferentialNetworkServiceConfigScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object OverrideApn
|
||||
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
fun OverrideApnScreen(
|
||||
@@ -1901,8 +1893,6 @@ data class ApnConfig(
|
||||
val persistent: Boolean, val alwaysOn: Boolean, val id: Int = -1
|
||||
)
|
||||
|
||||
@Serializable data class AddApnSetting(val index: Int)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
@@ -71,29 +71,37 @@ import com.bintianqi.owndroid.ui.InfoItem
|
||||
import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.RadioButtonItem
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.bintianqi.owndroid.yesOrNo
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable object Password
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Composable
|
||||
fun PasswordScreen(vm: MyViewModel,onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
fun PasswordScreen(vm: MyViewModel,onNavigateUp: () -> Unit, onNavigate: (Destination) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||
MyScaffold(R.string.password_and_keyguard, onNavigateUp, 0.dp) {
|
||||
FunctionItem(R.string.password_info, icon = R.drawable.info_fill0) { onNavigate(PasswordInfo) }
|
||||
FunctionItem(R.string.password_info, icon = R.drawable.info_fill0) {
|
||||
onNavigate(Destination.PasswordInfo)
|
||||
}
|
||||
if (SP.displayDangerousFeatures) {
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
FunctionItem(R.string.reset_password_token, icon = R.drawable.key_vertical_fill0) { onNavigate(ResetPasswordToken) }
|
||||
FunctionItem(R.string.reset_password_token, icon = R.drawable.key_vertical_fill0) {
|
||||
onNavigate(Destination.ResetPasswordToken)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.reset_password, icon = R.drawable.lock_reset_fill0) {
|
||||
onNavigate(Destination.ResetPassword)
|
||||
}
|
||||
FunctionItem(R.string.reset_password, icon = R.drawable.lock_reset_fill0) { onNavigate(ResetPassword) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 31) {
|
||||
FunctionItem(R.string.required_password_complexity, icon = R.drawable.password_fill0) { onNavigate(RequiredPasswordComplexity) }
|
||||
FunctionItem(R.string.required_password_complexity, icon = R.drawable.password_fill0) {
|
||||
onNavigate(Destination.RequiredPasswordComplexity)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.disable_keyguard_features, icon = R.drawable.screen_lock_portrait_fill0) {
|
||||
onNavigate(Destination.KeyguardDisabledFeatures)
|
||||
}
|
||||
FunctionItem(R.string.disable_keyguard_features, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(KeyguardDisabledFeatures) }
|
||||
if(privilege.device) {
|
||||
FunctionItem(R.string.max_time_to_lock, icon = R.drawable.schedule_fill0) { dialog = 1 }
|
||||
FunctionItem(R.string.pwd_expiration_timeout, icon = R.drawable.lock_clock_fill0) { dialog = 3 }
|
||||
@@ -106,7 +114,9 @@ fun PasswordScreen(vm: MyViewModel,onNavigateUp: () -> Unit, onNavigate: (Any) -
|
||||
}
|
||||
FunctionItem(R.string.pwd_history, icon = R.drawable.history_fill0) { dialog = 5 }
|
||||
if(VERSION.SDK_INT < 31) {
|
||||
FunctionItem(R.string.required_password_quality, icon = R.drawable.password_fill0) { onNavigate(RequiredPasswordQuality) }
|
||||
FunctionItem(R.string.required_password_quality, icon = R.drawable.password_fill0) {
|
||||
onNavigate(Destination.RequiredPasswordQuality)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(dialog != 0) {
|
||||
@@ -205,8 +215,6 @@ enum class PasswordComplexity(val id: Int, val text: Int) {
|
||||
High(DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH, R.string.high)
|
||||
}
|
||||
|
||||
@Serializable object PasswordInfo
|
||||
|
||||
@Composable
|
||||
fun PasswordInfoScreen(
|
||||
getComplexity: () -> PasswordComplexity, isSufficient: () -> Boolean, isUnified: () -> Boolean,
|
||||
@@ -236,8 +244,6 @@ fun PasswordInfoScreen(
|
||||
|
||||
data class RpTokenState(val set: Boolean, val active: Boolean)
|
||||
|
||||
@Serializable object ResetPasswordToken
|
||||
|
||||
@RequiresApi(26)
|
||||
@Composable
|
||||
fun ResetPasswordTokenScreen(
|
||||
@@ -303,8 +309,6 @@ fun ResetPasswordTokenScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object ResetPassword
|
||||
|
||||
@Composable
|
||||
fun ResetPasswordScreen(resetPassword: (String, String, Int) -> Boolean, onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
@@ -358,8 +362,6 @@ fun ResetPasswordScreen(resetPassword: (String, String, Int) -> Boolean, onNavig
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object RequiredPasswordComplexity
|
||||
|
||||
@RequiresApi(31)
|
||||
@Composable
|
||||
fun RequiredPasswordComplexityScreen(
|
||||
@@ -408,8 +410,6 @@ enum class KeyguardDisableMode(val text: Int) {
|
||||
data class KeyguardDisableConfig(val mode: KeyguardDisableMode, val flags: Int)
|
||||
|
||||
|
||||
@Serializable object KeyguardDisabledFeatures
|
||||
|
||||
@Composable
|
||||
fun KeyguardDisabledFeaturesScreen(
|
||||
getConfig: () -> KeyguardDisableConfig, setConfig: (KeyguardDisableConfig) -> Unit,
|
||||
@@ -449,8 +449,6 @@ fun KeyguardDisabledFeaturesScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object RequiredPasswordQuality
|
||||
|
||||
@Composable
|
||||
fun RequiredPasswordQualityScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
@@ -54,23 +55,31 @@ import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.BottomPadding
|
||||
import com.bintianqi.owndroid.MyNotificationChannel
|
||||
import com.bintianqi.owndroid.NotificationType
|
||||
import com.bintianqi.owndroid.Privilege
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.ThemeSettings
|
||||
import com.bintianqi.owndroid.adaptiveInsets
|
||||
import com.bintianqi.owndroid.exportLogs
|
||||
import com.bintianqi.owndroid.generateBase64Key
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.FunctionItem
|
||||
import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@Serializable object Settings
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SettingsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
fun SettingsScreen(onNavigate: (Destination) -> Unit, onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
val exportLogsLauncher = rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) {
|
||||
@@ -120,22 +129,34 @@ fun SettingsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(bottom = 80.dp)
|
||||
) {
|
||||
FunctionItem(title = R.string.options, icon = R.drawable.tune_fill0) { onNavigate(SettingsOptions) }
|
||||
FunctionItem(title = R.string.appearance, icon = R.drawable.format_paint_fill0) { onNavigate(Appearance) }
|
||||
FunctionItem(R.string.app_lock, icon = R.drawable.lock_fill0) { onNavigate(AppLockSettings) }
|
||||
if (privilege.device || privilege.profile)
|
||||
FunctionItem(title = R.string.api, icon = R.drawable.code_fill0) { onNavigate(ApiSettings) }
|
||||
if (privilege.device && !privilege.dhizuku)
|
||||
FunctionItem(R.string.notifications, icon = R.drawable.notifications_fill0) { onNavigate(Notifications) }
|
||||
FunctionItem(title = R.string.about, icon = R.drawable.info_fill0) { onNavigate(About) }
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) {
|
||||
onNavigate(Destination.SettingsOptions)
|
||||
}
|
||||
FunctionItem(R.string.appearance, icon = R.drawable.format_paint_fill0) {
|
||||
onNavigate(Destination.AppearanceSettings)
|
||||
}
|
||||
FunctionItem(R.string.app_lock, icon = R.drawable.lock_fill0) {
|
||||
onNavigate(Destination.AppLockSettings)
|
||||
}
|
||||
if (privilege.device || privilege.profile) {
|
||||
FunctionItem(R.string.api, icon = R.drawable.code_fill0) {
|
||||
onNavigate(Destination.ApiSettings)
|
||||
}
|
||||
}
|
||||
if (privilege.device && !privilege.dhizuku) {
|
||||
FunctionItem(R.string.notifications, icon = R.drawable.notifications_fill0) {
|
||||
onNavigate(Destination.NotificationSettings)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.about, icon = R.drawable.info_fill0) {
|
||||
onNavigate(Destination.About)
|
||||
}
|
||||
Spacer(Modifier.height(BottomPadding))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object SettingsOptions
|
||||
|
||||
@Composable
|
||||
fun SettingsOptionsScreen(
|
||||
getDisplayDangerousFeatures: () -> Boolean, getShortcutsEnabled: () -> Boolean,
|
||||
@@ -160,8 +181,6 @@ fun SettingsOptionsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object Appearance
|
||||
|
||||
@Composable
|
||||
fun AppearanceScreen(
|
||||
onNavigateUp: () -> Unit, currentTheme: StateFlow<ThemeSettings>,
|
||||
@@ -225,8 +244,6 @@ data class AppLockConfig(
|
||||
val password: String?, val biometrics: Boolean, val whenLeaving: Boolean
|
||||
)
|
||||
|
||||
@Serializable object AppLockSettings
|
||||
|
||||
@Composable
|
||||
fun AppLockSettingsScreen(
|
||||
config: AppLockConfig, setConfig: (AppLockConfig) -> Unit,
|
||||
@@ -286,8 +303,6 @@ fun AppLockSettingsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object ApiSettings
|
||||
|
||||
@Composable
|
||||
fun ApiSettings(
|
||||
getEnabled: () -> Boolean, setKey: (String) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -326,8 +341,6 @@ fun ApiSettings(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object Notifications
|
||||
|
||||
@Composable
|
||||
fun NotificationsScreen(
|
||||
enabledNotifications: StateFlow<List<Int>>, getState: () -> Unit,
|
||||
@@ -344,8 +357,6 @@ fun NotificationsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object About
|
||||
|
||||
@Composable
|
||||
fun AboutScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.admin.DevicePolicyManager
|
||||
@@ -131,7 +131,9 @@ import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.MySmallTitleScaffold
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.PackageNameTextField
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.bintianqi.owndroid.yesOrNo
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
@@ -139,30 +141,33 @@ import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import kotlin.math.roundToLong
|
||||
|
||||
@Serializable object SystemManager
|
||||
|
||||
@Composable
|
||||
fun SystemManagerScreen(
|
||||
vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit
|
||||
vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Destination) -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
/** 1: reboot, 2: bug report, 3: org name, 4: org id, 5: enrollment specific id*/
|
||||
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||
MyScaffold(R.string.system, onNavigateUp, 0.dp) {
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(SystemOptions) }
|
||||
FunctionItem(R.string.keyguard, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(Keyguard) }
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) {
|
||||
onNavigate(Destination.SystemOptions)
|
||||
}
|
||||
FunctionItem(R.string.keyguard, icon = R.drawable.screen_lock_portrait_fill0) {
|
||||
onNavigate(Destination.Keyguard)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device && !privilege.dhizuku)
|
||||
FunctionItem(R.string.hardware_monitor, icon = R.drawable.memory_fill0) { onNavigate(HardwareMonitor) }
|
||||
FunctionItem(R.string.hardware_monitor, icon = R.drawable.memory_fill0) {
|
||||
onNavigate(Destination.HardwareMonitor)
|
||||
}
|
||||
FunctionItem(R.string.default_input_method, icon = R.drawable.keyboard_fill0) {
|
||||
onNavigate(DefaultInputMethod)
|
||||
onNavigate(Destination.DefaultInputMethod)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device) {
|
||||
FunctionItem(R.string.reboot, icon = R.drawable.restart_alt_fill0) { dialog = 1 }
|
||||
@@ -171,32 +176,56 @@ fun SystemManagerScreen(
|
||||
FunctionItem(R.string.bug_report, icon = R.drawable.bug_report_fill0) { dialog = 2 }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.change_time, icon = R.drawable.schedule_fill0) { onNavigate(ChangeTime) }
|
||||
FunctionItem(R.string.change_timezone, icon = R.drawable.globe_fill0) { onNavigate(ChangeTimeZone) }
|
||||
FunctionItem(R.string.change_time, icon = R.drawable.schedule_fill0) {
|
||||
onNavigate(Destination.ChangeTime)
|
||||
}
|
||||
FunctionItem(R.string.change_timezone, icon = R.drawable.globe_fill0) {
|
||||
onNavigate(Destination.ChangeTimezone)
|
||||
}
|
||||
}
|
||||
if (VERSION.SDK_INT >= 36 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.auto_time_policy, icon = R.drawable.schedule_fill0) { onNavigate(AutoTimePolicy) }
|
||||
FunctionItem(R.string.auto_timezone_policy, icon = R.drawable.globe_fill0) { onNavigate(AutoTimeZonePolicy) }
|
||||
FunctionItem(R.string.auto_time_policy, icon = R.drawable.schedule_fill0) {
|
||||
onNavigate(Destination.AutoTimePolicy)
|
||||
}
|
||||
FunctionItem(R.string.auto_timezone_policy, icon = R.drawable.globe_fill0) {
|
||||
onNavigate(Destination.AutoTimezonePolicy)
|
||||
}
|
||||
}
|
||||
/*if(VERSION.SDK_INT >= 28 && (deviceOwner || profileOwner))
|
||||
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) }
|
||||
FunctionItem(R.string.permission_policy, icon = R.drawable.key_fill0) { onNavigate(PermissionPolicy) }
|
||||
FunctionItem(R.string.content_protection_policy, icon = R.drawable.search_fill0) {
|
||||
onNavigate(Destination.ContentProtectionPolicy)
|
||||
}
|
||||
FunctionItem(R.string.permission_policy, icon = R.drawable.key_fill0) {
|
||||
onNavigate(Destination.PermissionPolicy)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 34 && privilege.device) {
|
||||
FunctionItem(R.string.mte_policy, icon = R.drawable.memory_fill0) { onNavigate(MtePolicy) }
|
||||
FunctionItem(R.string.mte_policy, icon = R.drawable.memory_fill0) {
|
||||
onNavigate(Destination.MtePolicy)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 31) {
|
||||
FunctionItem(R.string.nearby_streaming_policy, icon = R.drawable.share_fill0) { onNavigate(NearbyStreamingPolicy) }
|
||||
FunctionItem(R.string.nearby_streaming_policy, icon = R.drawable.share_fill0) {
|
||||
onNavigate(Destination.NearbyStreamingPolicy)
|
||||
}
|
||||
}
|
||||
if (VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.lock_task_mode, icon = R.drawable.lock_fill0) { onNavigate(LockTaskMode) }
|
||||
FunctionItem(R.string.lock_task_mode, icon = R.drawable.lock_fill0) {
|
||||
onNavigate(Destination.LockTaskMode)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.ca_cert, icon = R.drawable.license_fill0) {
|
||||
onNavigate(Destination.CaCert)
|
||||
}
|
||||
FunctionItem(R.string.ca_cert, icon = R.drawable.license_fill0) { onNavigate(CaCert) }
|
||||
if(VERSION.SDK_INT >= 26 && !privilege.dhizuku && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.security_logging, icon = R.drawable.description_fill0) { onNavigate(SecurityLogging) }
|
||||
FunctionItem(R.string.security_logging, icon = R.drawable.description_fill0) {
|
||||
onNavigate(Destination.SecurityLogging)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.device_info, icon = R.drawable.perm_device_information_fill0) {
|
||||
onNavigate(Destination.DeviceInfo)
|
||||
}
|
||||
FunctionItem(R.string.device_info, icon = R.drawable.perm_device_information_fill0) { onNavigate(DeviceInfo) }
|
||||
if(VERSION.SDK_INT >= 24 && (privilege.profile || (VERSION.SDK_INT >= 26 && privilege.device))) {
|
||||
FunctionItem(R.string.org_name, icon = R.drawable.corporate_fare_fill0) { dialog = 3 }
|
||||
}
|
||||
@@ -207,23 +236,37 @@ fun SystemManagerScreen(
|
||||
FunctionItem(R.string.enrollment_specific_id, icon = R.drawable.id_card_fill0) { dialog = 5 }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.lock_screen_info, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(LockScreenInfo) }
|
||||
FunctionItem(R.string.lock_screen_info, icon = R.drawable.screen_lock_portrait_fill0) {
|
||||
onNavigate(Destination.LockScreenInfo)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24) {
|
||||
FunctionItem(R.string.support_messages, icon = R.drawable.chat_fill0) { onNavigate(SupportMessage) }
|
||||
FunctionItem(R.string.support_messages, icon = R.drawable.chat_fill0) {
|
||||
onNavigate(Destination.SupportMessage)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.disable_account_management, icon = R.drawable.account_circle_fill0) {
|
||||
onNavigate(Destination.DisableAccountManagement)
|
||||
}
|
||||
FunctionItem(R.string.disable_account_management, icon = R.drawable.account_circle_fill0) { onNavigate(DisableAccountManagement) }
|
||||
if (privilege.device || privilege.org) {
|
||||
FunctionItem(R.string.system_update_policy, icon = R.drawable.system_update_fill0) { onNavigate(SetSystemUpdatePolicy) }
|
||||
FunctionItem(R.string.system_update_policy, icon = R.drawable.system_update_fill0) {
|
||||
onNavigate(Destination.SystemUpdatePolicy)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 29 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.install_system_update, icon = R.drawable.system_update_fill0) { onNavigate(InstallSystemUpdate) }
|
||||
FunctionItem(R.string.install_system_update, icon = R.drawable.system_update_fill0) {
|
||||
onNavigate(Destination.InstallSystemUpdate)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 30 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.frp_policy, icon = R.drawable.device_reset_fill0) { onNavigate(FrpPolicy) }
|
||||
FunctionItem(R.string.frp_policy, icon = R.drawable.device_reset_fill0) {
|
||||
onNavigate(Destination.FrpPolicy)
|
||||
}
|
||||
}
|
||||
if(SP.displayDangerousFeatures && !privilege.work) {
|
||||
FunctionItem(R.string.wipe_data, icon = R.drawable.device_reset_fill0) { onNavigate(WipeData) }
|
||||
FunctionItem(R.string.wipe_data, icon = R.drawable.device_reset_fill0) {
|
||||
onNavigate(Destination.WipeData)
|
||||
}
|
||||
}
|
||||
}
|
||||
if((dialog == 1 || dialog == 2) && VERSION.SDK_INT >= 24) AlertDialog(
|
||||
@@ -329,13 +372,11 @@ data class SystemOptionsStatus(
|
||||
val stayOnWhilePluggedIn: Boolean = false
|
||||
)
|
||||
|
||||
@Serializable object SystemOptions
|
||||
|
||||
class GlobalSetting(val icon: Int, val name: Int, val setting: String) // also for secure settings
|
||||
|
||||
// STAY_ON_WHILE_PLUGGED_IN is set separately
|
||||
val globalSettings = listOf(
|
||||
GlobalSetting(R.drawable.cell_tower_fill0, R.string.data_roaming, Settings.Global.DATA_ROAMING),
|
||||
//GlobalSetting(R.drawable.cell_tower_fill0, R.string.data_roaming, Settings.Global.DATA_ROAMING),
|
||||
GlobalSetting(R.drawable.adb_fill0, R.string.enable_adb, Settings.Global.ADB_ENABLED),
|
||||
GlobalSetting(R.drawable.usb_fill0, R.string.enable_usb_mass_storage,
|
||||
Settings.Global.USB_MASS_STORAGE_ENABLED),
|
||||
@@ -457,8 +498,6 @@ fun SystemOptionsScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object Keyguard
|
||||
|
||||
@Composable
|
||||
fun KeyguardScreen(
|
||||
setKeyguardDisabled: (Boolean) -> Boolean, lock: (Boolean) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -519,8 +558,6 @@ val temperatureTypes = mapOf(
|
||||
HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN to R.string.skin_temp
|
||||
)
|
||||
|
||||
@Serializable object HardwareMonitor
|
||||
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun HardwareMonitorScreen(
|
||||
@@ -586,8 +623,6 @@ fun HardwareMonitorScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object DefaultInputMethod
|
||||
|
||||
@Composable
|
||||
fun DefaultInputMethodScreen(
|
||||
getCurrentIm: () -> String, imListState: StateFlow<List<Pair<String, AppInfo>>>,
|
||||
@@ -632,8 +667,6 @@ fun DefaultInputMethodScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object ChangeTime
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
@@ -768,8 +801,6 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object ChangeTimeZone
|
||||
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
fun ChangeTimeZoneScreen(setTimeZone: (String) -> Boolean, onNavigateUp: () -> Unit) {
|
||||
@@ -835,8 +866,6 @@ fun ChangeTimeZoneScreen(setTimeZone: (String) -> Boolean, onNavigateUp: () -> U
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object AutoTimePolicy
|
||||
|
||||
@RequiresApi(36)
|
||||
@Composable
|
||||
fun AutoTimePolicyScreen(
|
||||
@@ -866,8 +895,6 @@ fun AutoTimePolicyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object AutoTimeZonePolicy
|
||||
|
||||
@RequiresApi(36)
|
||||
@Composable
|
||||
fun AutoTimeZonePolicyScreen(
|
||||
@@ -1074,8 +1101,6 @@ fun KeyPairs(navCtrl: NavHostController) {
|
||||
}
|
||||
}*/
|
||||
|
||||
@Serializable object ContentProtectionPolicy
|
||||
|
||||
@RequiresApi(35)
|
||||
@Composable
|
||||
fun ContentProtectionPolicyScreen(
|
||||
@@ -1106,8 +1131,6 @@ fun ContentProtectionPolicyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object PermissionPolicy
|
||||
|
||||
@Composable
|
||||
fun PermissionPolicyScreen(
|
||||
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -1139,8 +1162,6 @@ fun PermissionPolicyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object MtePolicy
|
||||
|
||||
@RequiresApi(34)
|
||||
@Composable
|
||||
fun MtePolicyScreen(
|
||||
@@ -1167,8 +1188,6 @@ fun MtePolicyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object NearbyStreamingPolicy
|
||||
|
||||
@RequiresApi(31)
|
||||
@Composable
|
||||
fun NearbyStreamingPolicyScreen(
|
||||
@@ -1241,8 +1260,6 @@ fun NearbyStreamingPolicyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object LockTaskMode
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
@@ -1467,8 +1484,6 @@ data class CaCertInfo(
|
||||
val bytes: ByteArray
|
||||
)
|
||||
|
||||
@Serializable object CaCert
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalStdlibApi::class)
|
||||
@Composable
|
||||
fun CaCertScreen(
|
||||
@@ -1639,8 +1654,6 @@ fun CaCertScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object SecurityLogging
|
||||
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun SecurityLoggingScreen(
|
||||
@@ -1745,8 +1758,6 @@ fun SecurityLoggingScreen(
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object DisableAccountManagement
|
||||
|
||||
@Composable
|
||||
fun DisableAccountManagementScreen(
|
||||
mdAccounts: StateFlow<List<String>>, getMdAccounts: () -> Unit,
|
||||
@@ -1798,8 +1809,6 @@ data class FrpPolicyInfo(
|
||||
val accounts: List<String>
|
||||
)
|
||||
|
||||
@Serializable object FrpPolicy
|
||||
|
||||
@RequiresApi(30)
|
||||
@Composable
|
||||
fun FrpPolicyScreen(
|
||||
@@ -1874,8 +1883,6 @@ fun FrpPolicyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object WipeData
|
||||
|
||||
@Composable
|
||||
fun WipeDataScreen(
|
||||
wipeData: (Boolean, Int, String) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -1988,8 +1995,6 @@ fun WipeDataScreen(
|
||||
data class SystemUpdatePolicyInfo(val type: Int, val start: Int, val end: Int)
|
||||
data class PendingSystemUpdateInfo(val exists: Boolean, val time: Long, val securityPatch: Boolean)
|
||||
|
||||
@Serializable object SetSystemUpdatePolicy
|
||||
|
||||
@Composable
|
||||
fun SystemUpdatePolicyScreen(
|
||||
getPolicy: () -> SystemUpdatePolicyInfo, setPolicy: (SystemUpdatePolicyInfo) -> Unit,
|
||||
@@ -2083,8 +2088,6 @@ fun SystemUpdatePolicyScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object InstallSystemUpdate
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Composable
|
||||
fun InstallSystemUpdateScreen(
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.background
|
||||
@@ -63,6 +63,7 @@ import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.FunctionItem
|
||||
import com.bintianqi.owndroid.ui.MyLazyScaffold
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@@ -74,13 +75,11 @@ data class Restriction(
|
||||
val requiresApi: Int = 0
|
||||
)
|
||||
|
||||
@Serializable object UserRestriction
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun UserRestrictionScreen(
|
||||
getRestrictions: () -> Unit,onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit
|
||||
getRestrictions: () -> Unit,onNavigateUp: () -> Unit, onNavigate: (Destination) -> Unit
|
||||
) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
val sb = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
@@ -92,7 +91,7 @@ fun UserRestrictionScreen(
|
||||
{ Text(stringResource(R.string.user_restriction)) },
|
||||
navigationIcon = { NavIcon(onNavigateUp) },
|
||||
actions = {
|
||||
IconButton({ onNavigate(UserRestrictionEditor) }) {
|
||||
IconButton({ onNavigate(Destination.UserRestrictionEditor) }) {
|
||||
Icon(Icons.Default.Edit, null)
|
||||
}
|
||||
},
|
||||
@@ -119,7 +118,7 @@ fun UserRestrictionScreen(
|
||||
Spacer(Modifier.padding(vertical = 2.dp))
|
||||
UserRestrictionCategory.entries.forEach {
|
||||
FunctionItem(it.title, icon = it.icon) {
|
||||
onNavigate(UserRestrictionOptions(it.name))
|
||||
onNavigate(Destination.UserRestrictionOptions(it.name))
|
||||
}
|
||||
}
|
||||
Row(
|
||||
@@ -137,13 +136,10 @@ fun UserRestrictionScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class UserRestrictionOptions(val id: String)
|
||||
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun UserRestrictionOptionsScreen(
|
||||
args: UserRestrictionOptions, userRestrictions: StateFlow<Map<String, Boolean>>,
|
||||
args: Destination.UserRestrictionOptions, userRestrictions: StateFlow<Map<String, Boolean>>,
|
||||
setRestriction: (String, Boolean) -> Boolean, setShortcut: (String) -> Boolean,
|
||||
onNavigateUp: () -> Unit
|
||||
) {
|
||||
@@ -188,8 +184,6 @@ fun UserRestrictionOptionsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object UserRestrictionEditor
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.graphics.Bitmap
|
||||
@@ -77,15 +77,13 @@ import com.bintianqi.owndroid.ui.ListItem
|
||||
import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.bintianqi.owndroid.uriToStream
|
||||
import com.bintianqi.owndroid.yesOrNo
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable object Users
|
||||
|
||||
@Composable
|
||||
fun UsersScreen(vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
fun UsersScreen(vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Destination) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
/** 1: logout */
|
||||
@@ -94,17 +92,27 @@ fun UsersScreen(vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) ->
|
||||
if(VERSION.SDK_INT >= 28 && privilege.profile && privilege.affiliated) {
|
||||
FunctionItem(R.string.logout, icon = R.drawable.logout_fill0) { dialog = 1 }
|
||||
}
|
||||
FunctionItem(R.string.user_info, icon = R.drawable.person_fill0) { onNavigate(UserInfo) }
|
||||
FunctionItem(R.string.user_info, icon = R.drawable.person_fill0) {
|
||||
onNavigate(Destination.UserInfo)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(UsersOptions) }
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) {
|
||||
onNavigate(Destination.UsersOptions)
|
||||
}
|
||||
}
|
||||
if(privilege.device) {
|
||||
FunctionItem(R.string.user_operation, icon = R.drawable.sync_alt_fill0) { onNavigate(UserOperation) }
|
||||
FunctionItem(R.string.user_operation, icon = R.drawable.sync_alt_fill0) {
|
||||
onNavigate(Destination.UserOperation)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device) {
|
||||
FunctionItem(R.string.create_user, icon = R.drawable.person_add_fill0) { onNavigate(CreateUser) }
|
||||
FunctionItem(R.string.create_user, icon = R.drawable.person_add_fill0) {
|
||||
onNavigate(Destination.CreateUser)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.change_username, icon = R.drawable.edit_fill0) {
|
||||
onNavigate(Destination.ChangeUsername)
|
||||
}
|
||||
FunctionItem(R.string.change_username, icon = R.drawable.edit_fill0) { onNavigate(ChangeUsername) }
|
||||
var changeUserIconDialog by remember { mutableStateOf(false) }
|
||||
var bitmap: Bitmap? by remember { mutableStateOf(null) }
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
|
||||
@@ -123,10 +131,14 @@ fun UsersScreen(vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) ->
|
||||
changeUserIconDialog = false
|
||||
}) { changeUserIconDialog = false }
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.user_session_msg, icon = R.drawable.notifications_fill0) { onNavigate(UserSessionMessage) }
|
||||
FunctionItem(R.string.user_session_msg, icon = R.drawable.notifications_fill0) {
|
||||
onNavigate(Destination.UserSessionMessage)
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
FunctionItem(R.string.affiliation_id, icon = R.drawable.id_card_fill0) { onNavigate(AffiliationId) }
|
||||
FunctionItem(R.string.affiliation_id, icon = R.drawable.id_card_fill0) {
|
||||
onNavigate(Destination.AffiliationId)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (VERSION.SDK_INT >= 28 && dialog == 1) AlertDialog(
|
||||
@@ -151,8 +163,6 @@ fun UsersScreen(vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) ->
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object UsersOptions
|
||||
|
||||
@Composable
|
||||
fun UsersOptionsScreen(
|
||||
getLogoutEnabled: () -> Boolean, setLogoutEnabled: (Boolean) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -176,8 +186,6 @@ data class UserInformation(
|
||||
val serial: Long = 0
|
||||
)
|
||||
|
||||
@Serializable object UserInfo
|
||||
|
||||
@Composable
|
||||
fun UserInfoScreen(getInfo: () -> UserInformation, onNavigateUp: () -> Unit) {
|
||||
var info by remember { mutableStateOf(UserInformation()) }
|
||||
@@ -219,8 +227,6 @@ enum class UserOperationType {
|
||||
Start, Switch, Stop, Delete
|
||||
}
|
||||
|
||||
@Serializable object UserOperation
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun UserOperationScreen(
|
||||
@@ -370,8 +376,6 @@ fun UserOperationScreen(
|
||||
|
||||
data class CreateUserResult(val message: Int, val serial: Long = -1)
|
||||
|
||||
@Serializable object CreateUser
|
||||
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun CreateUserScreen(
|
||||
@@ -436,8 +440,6 @@ fun CreateUserScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object AffiliationId
|
||||
|
||||
@RequiresApi(26)
|
||||
@Composable
|
||||
fun AffiliationIdScreen(
|
||||
@@ -478,8 +480,6 @@ fun AffiliationIdScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object ChangeUsername
|
||||
|
||||
@Composable
|
||||
fun ChangeUsernameScreen(setName: (String) -> Unit, onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
@@ -507,8 +507,6 @@ fun ChangeUsernameScreen(setName: (String) -> Unit, onNavigateUp: () -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object UserSessionMessage
|
||||
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
fun UserSessionMessageScreen(
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.app.admin.DevicePolicyManager.WIPE_EUICC
|
||||
@@ -77,23 +77,30 @@ import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.bintianqi.owndroid.yesOrNo
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable object WorkProfile
|
||||
|
||||
@Composable
|
||||
fun WorkProfileScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
fun WorkProfileScreen(onNavigateUp: () -> Unit, onNavigate: (Destination) -> Unit) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
MyScaffold(R.string.work_profile, onNavigateUp, 0.dp) {
|
||||
if(VERSION.SDK_INT >= 30 && !privilege.org) {
|
||||
FunctionItem(R.string.org_owned_work_profile, icon = R.drawable.corporate_fare_fill0) { onNavigate(OrganizationOwnedProfile) }
|
||||
FunctionItem(R.string.org_owned_work_profile, icon = R.drawable.corporate_fare_fill0) {
|
||||
onNavigate(Destination.OrganizationOwnedProfile)
|
||||
}
|
||||
}
|
||||
if(privilege.org) {
|
||||
FunctionItem(R.string.suspend_personal_app, icon = R.drawable.block_fill0) { onNavigate(SuspendPersonalApp) }
|
||||
FunctionItem(R.string.suspend_personal_app, icon = R.drawable.block_fill0) {
|
||||
onNavigate(Destination.SuspendPersonalApp)
|
||||
}
|
||||
}
|
||||
FunctionItem(R.string.intent_filter, icon = R.drawable.filter_alt_fill0) {
|
||||
onNavigate(Destination.CrossProfileIntentFilter)
|
||||
}
|
||||
FunctionItem(R.string.delete_work_profile, icon = R.drawable.delete_forever_fill0) {
|
||||
onNavigate(Destination.DeleteWorkProfile)
|
||||
}
|
||||
FunctionItem(R.string.intent_filter, icon = R.drawable.filter_alt_fill0) { onNavigate(CrossProfileIntentFilter) }
|
||||
FunctionItem(R.string.delete_work_profile, icon = R.drawable.delete_forever_fill0) { onNavigate(DeleteWorkProfile) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +109,6 @@ data class CreateWorkProfileOptions(
|
||||
val accountName: String, val accountType: String, val keepAccount: Boolean
|
||||
)
|
||||
|
||||
@Serializable object CreateWorkProfile
|
||||
|
||||
@Composable
|
||||
fun CreateWorkProfileScreen(
|
||||
createIntent: (CreateWorkProfileOptions) -> Intent, onNavigateUp: () -> Unit
|
||||
@@ -165,8 +170,6 @@ fun CreateWorkProfileScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object OrganizationOwnedProfile
|
||||
|
||||
@RequiresApi(30)
|
||||
@Composable
|
||||
fun OrganizationOwnedProfileScreen(
|
||||
@@ -205,8 +208,6 @@ fun OrganizationOwnedProfileScreen(
|
||||
val activateOrgProfileCommand = "dpm mark-profile-owner-on-organization-owned-device --user " +
|
||||
"${Binder.getCallingUid()/100000} com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver"
|
||||
|
||||
@Serializable object SuspendPersonalApp
|
||||
|
||||
@RequiresApi(30)
|
||||
@Composable
|
||||
fun SuspendPersonalAppScreen(
|
||||
@@ -267,8 +268,6 @@ val crossProfileIntentFilterPresets = mapOf(
|
||||
IntentFilterOptions(Intent.ACTION_SEND, Intent.CATEGORY_DEFAULT, "*/*", 3)
|
||||
)
|
||||
|
||||
@Serializable object CrossProfileIntentFilter
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CrossProfileIntentFilterScreen(
|
||||
@@ -452,8 +451,6 @@ fun CrossProfileIntentFilterScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object DeleteWorkProfile
|
||||
|
||||
@Composable
|
||||
fun DeleteWorkProfileScreen(
|
||||
deleteProfile: (Boolean, Int, String) -> Unit, onNavigateUp: () -> Unit
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
package com.bintianqi.owndroid.ui.screen
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.ComponentName
|
||||
@@ -88,8 +88,10 @@ import com.bintianqi.owndroid.HorizontalPadding
|
||||
import com.bintianqi.owndroid.MyViewModel
|
||||
import com.bintianqi.owndroid.Privilege
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.Settings
|
||||
import com.bintianqi.owndroid.adaptiveInsets
|
||||
import com.bintianqi.owndroid.dpm.ACTIVATE_DEVICE_OWNER_COMMAND
|
||||
import com.bintianqi.owndroid.dpm.DelegatedAdmin
|
||||
import com.bintianqi.owndroid.dpm.DeviceAdmin
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.CircularProgressDialog
|
||||
import com.bintianqi.owndroid.ui.InfoItem
|
||||
@@ -98,21 +100,20 @@ import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.MySmallTitleScaffold
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.PackageNameTextField
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.ui.navigation.Destination
|
||||
import com.bintianqi.owndroid.yesOrNo
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable data class WorkModes(val canNavigateUp: Boolean)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun WorkModesScreen(
|
||||
vm: MyViewModel, params: WorkModes, onNavigateUp: () -> Unit, onActivate: () -> Unit,
|
||||
onDeactivate: () -> Unit, onNavigate: (Any) -> Unit
|
||||
vm: MyViewModel, params: Destination.WorkingModes, onNavigateUp: () -> Unit,
|
||||
onActivate: () -> Unit, onDeactivate: () -> Unit, onNavigate: (Destination) -> Unit
|
||||
) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
/** 0: none, 1: device owner, 2: circular progress indicator, 3: result, 4: deactivate, 5: command */
|
||||
@@ -162,7 +163,7 @@ fun WorkModesScreen(
|
||||
{ Text(stringResource(R.string.delegated_admins)) },
|
||||
{
|
||||
expanded = false
|
||||
onNavigate(DelegatedAdmins)
|
||||
onNavigate(Destination.DelegatedAdmins)
|
||||
},
|
||||
leadingIcon = { Icon(painterResource(R.drawable.admin_panel_settings_fill0), null) }
|
||||
)
|
||||
@@ -170,13 +171,13 @@ fun WorkModesScreen(
|
||||
{ Text(stringResource(R.string.transfer_ownership)) },
|
||||
{
|
||||
expanded = false
|
||||
onNavigate(TransferOwnership)
|
||||
onNavigate(Destination.TransferOwnership)
|
||||
},
|
||||
leadingIcon = { Icon(painterResource(R.drawable.swap_horiz_fill0), null) }
|
||||
)
|
||||
}
|
||||
}
|
||||
if(!params.canNavigateUp) IconButton({ onNavigate(Settings) }) {
|
||||
if(!params.canNavigateUp) IconButton({ onNavigate(Destination.Settings) }) {
|
||||
Icon(Icons.Default.Settings, null)
|
||||
}
|
||||
}
|
||||
@@ -210,14 +211,14 @@ fun WorkModesScreen(
|
||||
privilege.work || (VERSION.SDK_INT < 24 || vm.isCreatingWorkProfileAllowed())
|
||||
) {
|
||||
WorkingModeItem(R.string.work_profile, privilege.work) {
|
||||
if (!privilege.work) onNavigate(CreateWorkProfile)
|
||||
if (!privilege.work) onNavigate(Destination.CreateWorkProfile)
|
||||
}
|
||||
}
|
||||
if (privilege.activated && !privilege.dhizuku) Row(
|
||||
Modifier
|
||||
.padding(top = 20.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable { onNavigate(DhizukuServerSettings) }
|
||||
.clickable { onNavigate(Destination.DhizukuServerSettings) }
|
||||
.padding(vertical = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
@@ -357,10 +358,6 @@ fun WorkingModeItem(text: Int, active: Boolean, onClick: () -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
const val ACTIVATE_DEVICE_OWNER_COMMAND = "dpm set-device-owner com.bintianqi.owndroid/.Receiver"
|
||||
|
||||
@Serializable object DhizukuServerSettings
|
||||
|
||||
@Composable
|
||||
fun DhizukuServerSettingsScreen(
|
||||
dhizukuClients: StateFlow<List<Pair<DhizukuClientInfo, AppInfo>>>,
|
||||
@@ -446,8 +443,6 @@ fun DhizukuServerSettingsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object LockScreenInfo
|
||||
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun LockScreenInfoScreen(
|
||||
@@ -509,15 +504,11 @@ val delegatedScopesList = listOf(
|
||||
DelegatedScope(DevicePolicyManager.DELEGATION_SECURITY_LOGGING, R.string.security_logging, 31)
|
||||
).filter { VERSION.SDK_INT >= it.requiresApi }
|
||||
|
||||
data class DelegatedAdmin(val app: AppInfo, val scopes: List<String>)
|
||||
|
||||
@Serializable object DelegatedAdmins
|
||||
|
||||
@RequiresApi(26)
|
||||
@Composable
|
||||
fun DelegatedAdminsScreen(
|
||||
delegatedAdmins: StateFlow<List<DelegatedAdmin>>, getDelegatedAdmins: () -> Unit,
|
||||
onNavigateUp: () -> Unit, onNavigate: (AddDelegatedAdmin) -> Unit
|
||||
onNavigateUp: () -> Unit, onNavigate: (Destination.DelegatedAdminDetails) -> Unit
|
||||
) {
|
||||
val admins by delegatedAdmins.collectAsStateWithLifecycle()
|
||||
LaunchedEffect(Unit) { getDelegatedAdmins() }
|
||||
@@ -537,7 +528,7 @@ fun DelegatedAdminsScreen(
|
||||
Text(app.name, Modifier.alpha(0.8F), style = typography.bodyMedium)
|
||||
}
|
||||
}
|
||||
IconButton({ onNavigate(AddDelegatedAdmin(app.name, scopes)) }) {
|
||||
IconButton({ onNavigate(Destination.DelegatedAdminDetails(app.name, scopes)) }) {
|
||||
Icon(Icons.Outlined.Edit, null)
|
||||
}
|
||||
}
|
||||
@@ -546,7 +537,7 @@ fun DelegatedAdminsScreen(
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onNavigate(AddDelegatedAdmin()) }
|
||||
.clickable { onNavigate(Destination.DelegatedAdminDetails("", emptyList())) }
|
||||
.padding(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
@@ -557,12 +548,10 @@ fun DelegatedAdminsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable data class AddDelegatedAdmin(val pkg: String = "", val scopes: List<String> = emptyList())
|
||||
|
||||
@RequiresApi(26)
|
||||
@Composable
|
||||
fun AddDelegatedAdminScreen(
|
||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit, data: AddDelegatedAdmin,
|
||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit, data: Destination.DelegatedAdminDetails,
|
||||
setDelegatedAdmin: (String, List<String>) -> Unit, onNavigateUp: () -> Unit
|
||||
) {
|
||||
val updateMode = data.pkg.isNotEmpty()
|
||||
@@ -620,8 +609,6 @@ fun AddDelegatedAdminScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object DeviceInfo
|
||||
|
||||
@Composable
|
||||
fun DeviceInfoScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
@@ -657,8 +644,6 @@ fun DeviceInfoScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable object SupportMessage
|
||||
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun SupportMessageScreen(
|
||||
@@ -739,10 +724,6 @@ fun SupportMessageScreen(
|
||||
}
|
||||
}
|
||||
|
||||
data class DeviceAdmin(val app: AppInfo, val admin: ComponentName)
|
||||
|
||||
@Serializable object TransferOwnership
|
||||
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
fun TransferOwnershipScreen(
|
||||
@@ -2,7 +2,7 @@
|
||||
agp = "9.0.1"
|
||||
kotlin = "2.3.10"
|
||||
|
||||
navigation-compose = "2.9.7"
|
||||
nav3 = "1.0.1"
|
||||
composeBom = "2026.02.00"
|
||||
accompanist-drawablepainter = "0.37.3"
|
||||
accompanist-permissions = "0.37.3"
|
||||
@@ -21,10 +21,12 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u
|
||||
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||
androidx-activity-compose = { module = "androidx.activity:activity-compose" }
|
||||
androidx-material3 = { module = "androidx.compose.material3:material3" }
|
||||
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" }
|
||||
androidx-fragment = { group = "androidx.fragment", name = "fragment", version.ref = "fragment" }
|
||||
material-icons-core = { group = "androidx.compose.material", name = "material-icons-core" }
|
||||
|
||||
androidx-nav3-runtime = { group = "androidx.navigation3", name = "navigation3-runtime", version.ref = "nav3" }
|
||||
androidx-nav3-ui = { group = "androidx.navigation3", name = "navigation3-ui", version.ref = "nav3" }
|
||||
|
||||
accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist-drawablepainter" }
|
||||
accompanist-permissions = { group = "com.google.accompanist", name = "accompanist-permissions", version.ref = "accompanist-permissions" }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user