mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-27 04:16:00 +00:00
@@ -25,7 +25,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -44,8 +44,8 @@ import androidx.compose.ui.window.DialogProperties
|
|||||||
fun AppLockDialog(onSucceed: () -> Unit, onDismiss: () -> Unit) = Dialog(onDismiss, DialogProperties(true, false)) {
|
fun AppLockDialog(onSucceed: () -> Unit, onDismiss: () -> Unit) = Dialog(onDismiss, DialogProperties(true, false)) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val fm = LocalFocusManager.current
|
val fm = LocalFocusManager.current
|
||||||
var input by remember { mutableStateOf("") }
|
var input by rememberSaveable { mutableStateOf("") }
|
||||||
var isError by remember { mutableStateOf(false) }
|
var isError by rememberSaveable { mutableStateOf(false) }
|
||||||
fun unlock() {
|
fun unlock() {
|
||||||
if(input.hash() == SP.lockPasswordHash) {
|
if(input.hash() == SP.lockPasswordHash) {
|
||||||
fm.clearFocus()
|
fm.clearFocus()
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -103,7 +104,7 @@ class DhizukuActivity : ComponentActivity() {
|
|||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
val theme = ThemeSettings(SP.materialYou, SP.darkTheme, SP.blackTheme)
|
val theme = ThemeSettings(SP.materialYou, SP.darkTheme, SP.blackTheme)
|
||||||
setContent {
|
setContent {
|
||||||
var appLockDialog by remember { mutableStateOf(false) }
|
var appLockDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
OwnDroidTheme(theme) {
|
OwnDroidTheme(theme) {
|
||||||
if (!appLockDialog) AlertDialog(
|
if (!appLockDialog) AlertDialog(
|
||||||
icon = {
|
icon = {
|
||||||
|
|||||||
@@ -14,10 +14,9 @@ import androidx.compose.foundation.gestures.detectTapGestures
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.ime
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
@@ -400,7 +399,7 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
|||||||
InstallSystemUpdateScreen(vm::installSystemUpdate, ::navigateUp)
|
InstallSystemUpdateScreen(vm::installSystemUpdate, ::navigateUp)
|
||||||
}
|
}
|
||||||
composable<FrpPolicy> {
|
composable<FrpPolicy> {
|
||||||
FrpPolicyScreen(vm::getFrpPolicy, vm::setFrpPolicy, ::navigateUp)
|
FrpPolicyScreen(vm.getFrpPolicy(), vm::setFrpPolicy, ::navigateUp)
|
||||||
}
|
}
|
||||||
composable<WipeData> { WipeDataScreen(vm::wipeData, ::navigateUp) }
|
composable<WipeData> { WipeDataScreen(vm::wipeData, ::navigateUp) }
|
||||||
|
|
||||||
@@ -641,13 +640,14 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
|||||||
AppearanceScreen(::navigateUp, vm.theme, vm::changeTheme)
|
AppearanceScreen(::navigateUp, vm.theme, vm::changeTheme)
|
||||||
}
|
}
|
||||||
composable<AppLockSettings> {
|
composable<AppLockSettings> {
|
||||||
AppLockSettingsScreen(vm::getAppLockConfig, vm::setAppLockConfig, ::navigateUp)
|
AppLockSettingsScreen(vm.getAppLockConfig(), vm::setAppLockConfig, ::navigateUp)
|
||||||
}
|
}
|
||||||
composable<ApiSettings> {
|
composable<ApiSettings> {
|
||||||
ApiSettings(vm::getApiEnabled, vm::setApiKey, ::navigateUp)
|
ApiSettings(vm::getApiEnabled, vm::setApiKey, ::navigateUp)
|
||||||
}
|
}
|
||||||
composable<Notifications> {
|
composable<Notifications> {
|
||||||
NotificationsScreen(vm::getEnabledNotifications, vm::setNotificationEnabled, ::navigateUp)
|
NotificationsScreen(vm.enabledNotifications, vm::getEnabledNotifications,
|
||||||
|
vm::setNotificationEnabled, ::navigateUp)
|
||||||
}
|
}
|
||||||
composable<About> { AboutScreen(::navigateUp) }
|
composable<About> { AboutScreen(::navigateUp) }
|
||||||
}
|
}
|
||||||
@@ -702,7 +702,7 @@ private fun HomeScreen(onNavigate: (Any) -> Unit) {
|
|||||||
scrollBehavior = sb
|
scrollBehavior = sb
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) {
|
) {
|
||||||
Column(Modifier
|
Column(Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -727,7 +727,7 @@ private fun HomeScreen(onNavigate: (Any) -> Unit) {
|
|||||||
HomePageItem(R.string.users,R.drawable.manage_accounts_fill0) { onNavigate(Users) }
|
HomePageItem(R.string.users,R.drawable.manage_accounts_fill0) { onNavigate(Users) }
|
||||||
HomePageItem(R.string.password_and_keyguard, R.drawable.password_fill0) { onNavigate(Password) }
|
HomePageItem(R.string.password_and_keyguard, R.drawable.password_fill0) { onNavigate(Password) }
|
||||||
}
|
}
|
||||||
Spacer(Modifier.padding(vertical = 20.dp))
|
Spacer(Modifier.height(BottomPadding))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,21 +163,16 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
fun setApiKey(key: String) {
|
fun setApiKey(key: String) {
|
||||||
SP.apiKeyHash = if (key.isEmpty()) "" else key.hash()
|
SP.apiKeyHash = if (key.isEmpty()) "" else key.hash()
|
||||||
}
|
}
|
||||||
fun getEnabledNotifications(): List<NotificationType> {
|
val enabledNotifications = MutableStateFlow(emptyList<Int>())
|
||||||
|
fun getEnabledNotifications() {
|
||||||
val list = SP.notifications?.split(',')?.mapNotNull { it.toIntOrNull() }
|
val list = SP.notifications?.split(',')?.mapNotNull { it.toIntOrNull() }
|
||||||
return if (list == null) {
|
enabledNotifications.value = list ?: NotificationType.entries.map { it.id }
|
||||||
NotificationType.entries
|
|
||||||
} else {
|
|
||||||
NotificationType.entries.filter { it.id in list }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fun setNotificationEnabled(type: NotificationType, enabled: Boolean) {
|
fun setNotificationEnabled(type: NotificationType, enabled: Boolean) {
|
||||||
val list = SP.notifications?.split(',')?.mapNotNull { it.toIntOrNull() }
|
enabledNotifications.update { list ->
|
||||||
SP.notifications = if (list == null) {
|
if (enabled) list.plus(type.id) else list.minus(type.id)
|
||||||
NotificationType.entries.minus(type).map { it.id }
|
}
|
||||||
} else {
|
SP.notifications = enabledNotifications.value.joinToString(",") { it.toString() }
|
||||||
list.run { if (enabled) plus(type.id) else minus(type.id) }
|
|
||||||
}.joinToString { it.toString() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val chosenPackage = Channel<String>(1, BufferOverflow.DROP_LATEST)
|
val chosenPackage = Channel<String>(1, BufferOverflow.DROP_LATEST)
|
||||||
@@ -267,7 +262,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
fun getPackagePermissions(name: String) {
|
fun getPackagePermissions(name: String) {
|
||||||
if (name.isValidPackageName) {
|
if (name.isValidPackageName) {
|
||||||
packagePermissions.value = runtimePermissions.associate {
|
packagePermissions.value = runtimePermissions.associate {
|
||||||
it.permission to DPM.getPermissionGrantState(DAR, name, it.permission)
|
it.id to DPM.getPermissionGrantState(DAR, name, it.id)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
packagePermissions.value = emptyMap()
|
packagePermissions.value = emptyMap()
|
||||||
@@ -1027,7 +1022,8 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
} else {
|
} else {
|
||||||
Dhizuku.requestPermission(object : DhizukuRequestPermissionListener() {
|
Dhizuku.requestPermission(object : DhizukuRequestPermissionListener() {
|
||||||
override fun onRequestPermission(grantResult: Int) {
|
override fun onRequestPermission(grantResult: Int) {
|
||||||
if(grantResult == PackageManager.PERMISSION_GRANTED) onSucceed()
|
if (grantResult == PackageManager.PERMISSION_GRANTED) onSucceed()
|
||||||
|
else callback(false, application.getString(R.string.dhizuku_permission_not_granted))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ object NotificationUtils {
|
|||||||
NotificationManagerCompat.from(context).createNotificationChannelsCompat(channels)
|
NotificationManagerCompat.from(context).createNotificationChannelsCompat(channels)
|
||||||
}
|
}
|
||||||
fun sendBasicNotification(
|
fun sendBasicNotification(
|
||||||
context: Context, type: NotificationType, channel: MyNotificationChannel, text: String
|
context: Context, type: NotificationType, text: String
|
||||||
) {
|
) {
|
||||||
val notification = NotificationCompat.Builder(context, channel.id)
|
val notification = NotificationCompat.Builder(context, type.channel.id)
|
||||||
.setSmallIcon(type.icon)
|
.setSmallIcon(type.icon)
|
||||||
.setContentTitle(context.getString(type.text))
|
.setContentTitle(context.getString(type.text))
|
||||||
.setContentText(text)
|
.setContentText(text)
|
||||||
@@ -29,7 +29,7 @@ object NotificationUtils {
|
|||||||
fun notifyEvent(context: Context, type: NotificationType, text: String) {
|
fun notifyEvent(context: Context, type: NotificationType, text: String) {
|
||||||
val enabledNotifications = SP.notifications?.split(',')?.mapNotNull { it.toIntOrNull() }
|
val enabledNotifications = SP.notifications?.split(',')?.mapNotNull { it.toIntOrNull() }
|
||||||
if (enabledNotifications == null || type.id in enabledNotifications) {
|
if (enabledNotifications == null || type.id in enabledNotifications) {
|
||||||
sendBasicNotification(context, type, MyNotificationChannel.Events, text)
|
sendBasicNotification(context, type, text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun cancel(context: Context, type: NotificationType) {
|
fun cancel(context: Context, type: NotificationType) {
|
||||||
@@ -38,19 +38,40 @@ object NotificationUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class NotificationType(val id: Int, val text: Int, val icon: Int) {
|
enum class NotificationType(
|
||||||
LockTaskMode(1, R.string.lock_task_mode, R.drawable.lock_fill0),
|
val id: Int, val text: Int, val icon: Int, val channel: MyNotificationChannel
|
||||||
PasswordChanged(2, R.string.password_changed, R.drawable.password_fill0),
|
) {
|
||||||
UserAdded(3, R.string.user_added, R.drawable.person_add_fill0),
|
LockTaskMode(
|
||||||
UserStarted(4, R.string.user_started, R.drawable.person_fill0),
|
1, R.string.lock_task_mode, R.drawable.lock_fill0, MyNotificationChannel.LockTaskMode
|
||||||
UserSwitched(5, R.string.user_switched, R.drawable.person_fill0),
|
),
|
||||||
UserStopped(6, R.string.user_stopped, R.drawable.person_off),
|
PasswordChanged(
|
||||||
UserRemoved(7, R.string.user_removed, R.drawable.person_remove_fill0),
|
2, R.string.password_changed, R.drawable.password_fill0, MyNotificationChannel.Events
|
||||||
BugReportShared(8, R.string.bug_report_shared, R.drawable.bug_report_fill0),
|
),
|
||||||
BugReportSharingDeclined(9, R.string.bug_report_sharing_declined, R.drawable.bug_report_fill0),
|
UserAdded(3, R.string.user_added, R.drawable.person_add_fill0, MyNotificationChannel.Events),
|
||||||
BugReportFailed(10, R.string.bug_report_failed, R.drawable.bug_report_fill0),
|
UserStarted(4, R.string.user_started, R.drawable.person_fill0, MyNotificationChannel.Events),
|
||||||
SystemUpdatePending(11, R.string.system_update_pending, R.drawable.system_update_fill0),
|
UserSwitched(5, R.string.user_switched, R.drawable.person_fill0, MyNotificationChannel.Events),
|
||||||
SecurityLogsCollected(12, R.string.security_logs_collected, R.drawable.description_fill0),
|
UserStopped(6, R.string.user_stopped, R.drawable.person_off, MyNotificationChannel.Events),
|
||||||
|
UserRemoved(
|
||||||
|
7, R.string.user_removed, R.drawable.person_remove_fill0, MyNotificationChannel.Events
|
||||||
|
),
|
||||||
|
BugReportShared(
|
||||||
|
8, R.string.bug_report_shared, R.drawable.bug_report_fill0, MyNotificationChannel.Events
|
||||||
|
),
|
||||||
|
BugReportSharingDeclined(
|
||||||
|
9, R.string.bug_report_sharing_declined, R.drawable.bug_report_fill0,
|
||||||
|
MyNotificationChannel.Events
|
||||||
|
),
|
||||||
|
BugReportFailed(
|
||||||
|
10, R.string.bug_report_failed, R.drawable.bug_report_fill0, MyNotificationChannel.Events
|
||||||
|
),
|
||||||
|
SystemUpdatePending(
|
||||||
|
11, R.string.system_update_pending, R.drawable.system_update_fill0,
|
||||||
|
MyNotificationChannel.Events
|
||||||
|
),
|
||||||
|
SecurityLogsCollected(
|
||||||
|
12, R.string.security_logs_collected, R.drawable.description_fill0,
|
||||||
|
MyNotificationChannel.SecurityLogging
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class MyNotificationChannel(val id: String, val text: Int, val importance: Int) {
|
enum class MyNotificationChannel(val id: String, val text: Int, val importance: Int) {
|
||||||
|
|||||||
@@ -10,10 +10,9 @@ import androidx.compose.foundation.clickable
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.ime
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
@@ -146,7 +145,7 @@ fun AppChooserScreen(
|
|||||||
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceContainer)
|
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceContainer)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
|
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
|
||||||
if (progress < 1F) stickyHeader {
|
if (progress < 1F) stickyHeader {
|
||||||
@@ -174,7 +173,7 @@ fun AppChooserScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item { Spacer(Modifier.padding(vertical = 30.dp)) }
|
item { Spacer(Modifier.height(60.dp)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,8 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.ime
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
@@ -39,9 +37,9 @@ import androidx.compose.material3.TopAppBarDefaults
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -115,7 +113,7 @@ fun SettingsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -231,22 +229,15 @@ data class AppLockConfig(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppLockSettingsScreen(
|
fun AppLockSettingsScreen(
|
||||||
getConfig: () -> AppLockConfig, setConfig: (AppLockConfig) -> Unit,
|
config: AppLockConfig, setConfig: (AppLockConfig) -> Unit,
|
||||||
onNavigateUp: () -> Unit
|
onNavigateUp: () -> Unit
|
||||||
) = MyScaffold(R.string.app_lock, onNavigateUp) {
|
) = MyScaffold(R.string.app_lock, onNavigateUp) {
|
||||||
var password by remember { mutableStateOf("") }
|
var password by rememberSaveable { mutableStateOf(config.password ?: "") }
|
||||||
var confirmPassword by remember { mutableStateOf("") }
|
var confirmPassword by rememberSaveable { mutableStateOf("") }
|
||||||
var allowBiometrics by remember { mutableStateOf(false) }
|
var allowBiometrics by rememberSaveable { mutableStateOf(config.biometrics) }
|
||||||
var lockWhenLeaving by remember { mutableStateOf(false) }
|
var lockWhenLeaving by rememberSaveable { mutableStateOf(config.whenLeaving) }
|
||||||
var alreadySet by remember { mutableStateOf(false) }
|
var alreadySet by rememberSaveable { mutableStateOf(config.password != null) }
|
||||||
val isInputLegal = password.length !in 1..3 && (alreadySet || password.isNotBlank())
|
val isInputLegal = password.length !in 1..3 && (alreadySet || password.isNotBlank())
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
val config = getConfig()
|
|
||||||
password = config.password ?: ""
|
|
||||||
allowBiometrics = config.biometrics
|
|
||||||
lockWhenLeaving = config.whenLeaving
|
|
||||||
alreadySet = config.password != null
|
|
||||||
}
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
password, { password = it }, Modifier.fillMaxWidth().padding(vertical = 4.dp),
|
password, { password = it }, Modifier.fillMaxWidth().padding(vertical = 4.dp),
|
||||||
label = { Text(stringResource(R.string.password)) },
|
label = { Text(stringResource(R.string.password)) },
|
||||||
@@ -305,7 +296,7 @@ fun ApiSettings(
|
|||||||
var alreadyEnabled by remember { mutableStateOf(getEnabled()) }
|
var alreadyEnabled by remember { mutableStateOf(getEnabled()) }
|
||||||
MyScaffold(R.string.api, onNavigateUp) {
|
MyScaffold(R.string.api, onNavigateUp) {
|
||||||
var enabled by remember { mutableStateOf(alreadyEnabled) }
|
var enabled by remember { mutableStateOf(alreadyEnabled) }
|
||||||
var key by remember { mutableStateOf("") }
|
var key by rememberSaveable { mutableStateOf("") }
|
||||||
SwitchItem(R.string.enable, state = enabled, onCheckedChange = {
|
SwitchItem(R.string.enable, state = enabled, onCheckedChange = {
|
||||||
enabled = it
|
enabled = it
|
||||||
}, padding = false)
|
}, padding = false)
|
||||||
@@ -339,15 +330,17 @@ fun ApiSettings(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NotificationsScreen(
|
fun NotificationsScreen(
|
||||||
getState: () -> List<NotificationType>, setNotification: (NotificationType, Boolean) -> Unit,
|
enabledNotifications: StateFlow<List<Int>>, getState: () -> Unit,
|
||||||
onNavigateUp: () -> Unit
|
setNotification: (NotificationType, Boolean) -> Unit, onNavigateUp: () -> Unit
|
||||||
) = MyScaffold(R.string.notifications, onNavigateUp, 0.dp) {
|
) = MyScaffold(R.string.notifications, onNavigateUp, 0.dp) {
|
||||||
val enabledNotifications = remember { mutableStateListOf(*getState().toTypedArray()) }
|
val notifications by enabledNotifications.collectAsStateWithLifecycle()
|
||||||
NotificationType.entries.forEach { type ->
|
LaunchedEffect(Unit) {
|
||||||
SwitchItem(type.text, type in enabledNotifications, {
|
getState()
|
||||||
setNotification(type, it)
|
}
|
||||||
enabledNotifications.run { if (it) plusAssign(type) else minusAssign(type) }
|
NotificationType.entries.filter {
|
||||||
})
|
it.channel == MyNotificationChannel.Events
|
||||||
|
}.forEach { type ->
|
||||||
|
SwitchItem(type.text, type.id in notifications, { setNotification(type, it) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import android.content.Intent
|
|||||||
import androidx.core.content.pm.ShortcutInfoCompat
|
import androidx.core.content.pm.ShortcutInfoCompat
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
import java.security.SecureRandom
|
|
||||||
import kotlin.io.encoding.Base64
|
|
||||||
|
|
||||||
object ShortcutUtils {
|
object ShortcutUtils {
|
||||||
fun setAllShortcuts(context: Context, enabled: Boolean) {
|
fun setAllShortcuts(context: Context, enabled: Boolean) {
|
||||||
|
|||||||
@@ -9,8 +9,22 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.compose.foundation.gestures.awaitEachGesture
|
||||||
|
import androidx.compose.foundation.gestures.awaitFirstDown
|
||||||
|
import androidx.compose.foundation.gestures.waitForUpOrCancellation
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
|
import androidx.compose.foundation.layout.displayCutout
|
||||||
|
import androidx.compose.foundation.layout.ime
|
||||||
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
|
import androidx.compose.foundation.layout.union
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.saveable.Saver
|
import androidx.compose.runtime.saveable.Saver
|
||||||
import androidx.compose.runtime.saveable.SaverScope
|
import androidx.compose.runtime.saveable.SaverScope
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.pointer.PointerEventPass
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
@@ -91,6 +105,8 @@ fun exportLogs(context: Context, uri: Uri) {
|
|||||||
|
|
||||||
val HorizontalPadding = 16.dp
|
val HorizontalPadding = 16.dp
|
||||||
|
|
||||||
|
val BottomPadding = 60.dp
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
fun String.hash(): String {
|
fun String.hash(): String {
|
||||||
val md = MessageDigest.getInstance("SHA-256")
|
val md = MessageDigest.getInstance("SHA-256")
|
||||||
@@ -129,3 +145,18 @@ fun generateBase64Key(length: Int): String {
|
|||||||
SecureRandom().nextBytes(ba)
|
SecureRandom().nextBytes(ba)
|
||||||
return Base64.withPadding(Base64.PaddingOption.ABSENT).encode(ba)
|
return Base64.withPadding(Base64.PaddingOption.ABSENT).encode(ba)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Modifier.clickableTextField(onClick: () -> Unit) =
|
||||||
|
pointerInput(Unit) {
|
||||||
|
awaitEachGesture {
|
||||||
|
awaitFirstDown(pass = PointerEventPass.Initial)
|
||||||
|
val upEvent = waitForUpOrCancellation(pass = PointerEventPass.Initial)
|
||||||
|
if (upEvent != null) onClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun adaptiveInsets(): WindowInsets {
|
||||||
|
val navbar = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
|
||||||
|
return WindowInsets.ime.union(navbar).union(WindowInsets.displayCutout)
|
||||||
|
}
|
||||||
@@ -15,15 +15,14 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.ime
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyItemScope
|
import androidx.compose.foundation.lazy.LazyItemScope
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
@@ -53,7 +52,6 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@@ -73,10 +71,12 @@ import androidx.compose.ui.window.DialogProperties
|
|||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.bintianqi.owndroid.AppInfo
|
import com.bintianqi.owndroid.AppInfo
|
||||||
import com.bintianqi.owndroid.AppInstallerActivity
|
import com.bintianqi.owndroid.AppInstallerActivity
|
||||||
|
import com.bintianqi.owndroid.BottomPadding
|
||||||
import com.bintianqi.owndroid.HorizontalPadding
|
import com.bintianqi.owndroid.HorizontalPadding
|
||||||
import com.bintianqi.owndroid.MyViewModel
|
import com.bintianqi.owndroid.MyViewModel
|
||||||
import com.bintianqi.owndroid.Privilege
|
import com.bintianqi.owndroid.Privilege
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
|
import com.bintianqi.owndroid.adaptiveInsets
|
||||||
import com.bintianqi.owndroid.showOperationResultToast
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
||||||
import com.bintianqi.owndroid.ui.FunctionItem
|
import com.bintianqi.owndroid.ui.FunctionItem
|
||||||
@@ -156,7 +156,7 @@ fun ApplicationsFeaturesScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Un
|
|||||||
scrollBehavior = sb
|
scrollBehavior = sb
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
@@ -231,7 +231,7 @@ fun ApplicationDetailsScreen(
|
|||||||
) {
|
) {
|
||||||
val packageName = param.packageName
|
val packageName = param.packageName
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var dialog by remember { mutableIntStateOf(0) } // 1: clear storage, 2: uninstall
|
var dialog by rememberSaveable { mutableIntStateOf(0) } // 1: clear storage, 2: uninstall
|
||||||
val info = vm.getAppInfo(packageName)
|
val info = vm.getAppInfo(packageName)
|
||||||
val status by vm.appStatus.collectAsStateWithLifecycle()
|
val status by vm.appStatus.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) { vm.getAppStatus(packageName) }
|
LaunchedEffect(Unit) { vm.getAppStatus(packageName) }
|
||||||
@@ -299,8 +299,8 @@ fun PermissionsManagerScreen(
|
|||||||
) {
|
) {
|
||||||
val packageNameParam = param.packageName
|
val packageNameParam = param.packageName
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var packageName by remember { mutableStateOf(packageNameParam ?: "") }
|
var packageName by rememberSaveable { mutableStateOf(packageNameParam ?: "") }
|
||||||
var selectedPermission by remember { mutableStateOf<PermissionItem?>(null) }
|
var selectedPermission by rememberSaveable { mutableIntStateOf(-1) }
|
||||||
val permissions by packagePermissions.collectAsStateWithLifecycle()
|
val permissions by packagePermissions.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
@@ -316,19 +316,19 @@ fun PermissionsManagerScreen(
|
|||||||
Spacer(Modifier.padding(vertical = 4.dp))
|
Spacer(Modifier.padding(vertical = 4.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
items(runtimePermissions, { it.permission }) {
|
itemsIndexed(runtimePermissions, { _, it -> it.id }) { index, it ->
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable(packageName.isValidPackageName) {
|
.clickable(packageName.isValidPackageName) {
|
||||||
selectedPermission = it
|
selectedPermission = index
|
||||||
}
|
}
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
) {
|
) {
|
||||||
Icon(painterResource(it.icon), null, Modifier.padding(horizontal = 12.dp))
|
Icon(painterResource(it.icon), null, Modifier.padding(horizontal = 12.dp))
|
||||||
Column {
|
Column {
|
||||||
val state = when(permissions[it.permission]) {
|
val state = when(permissions[it.id]) {
|
||||||
PERMISSION_GRANT_STATE_DEFAULT -> R.string.default_stringres
|
PERMISSION_GRANT_STATE_DEFAULT -> R.string.default_stringres
|
||||||
PERMISSION_GRANT_STATE_GRANTED -> R.string.granted
|
PERMISSION_GRANT_STATE_GRANTED -> R.string.granted
|
||||||
PERMISSION_GRANT_STATE_DENIED -> R.string.denied
|
PERMISSION_GRANT_STATE_DENIED -> R.string.denied
|
||||||
@@ -340,17 +340,18 @@ fun PermissionsManagerScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
Spacer(Modifier.padding(vertical = 30.dp))
|
Spacer(Modifier.height(BottomPadding))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(selectedPermission != null) {
|
if(selectedPermission != -1) {
|
||||||
|
val permission = runtimePermissions[selectedPermission]
|
||||||
fun changeState(state: Int) {
|
fun changeState(state: Int) {
|
||||||
val result = setPackagePermission(packageName, selectedPermission!!.permission, state)
|
val result = setPackagePermission(packageName, permission.id, state)
|
||||||
if (result) selectedPermission = null
|
if (result) selectedPermission = -1
|
||||||
}
|
}
|
||||||
@Composable
|
@Composable
|
||||||
fun GrantPermissionItem(label: Int, status: Int) {
|
fun GrantPermissionItem(label: Int, status: Int) {
|
||||||
val selected = permissions[selectedPermission!!.permission] == status
|
val selected = permissions[permission.id] == status
|
||||||
Row(
|
Row(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -365,14 +366,14 @@ fun PermissionsManagerScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = { selectedPermission = null },
|
onDismissRequest = { selectedPermission = -1 },
|
||||||
confirmButton = { TextButton({ selectedPermission = null }) { Text(stringResource(R.string.cancel)) } },
|
confirmButton = { TextButton({ selectedPermission = -1 }) { Text(stringResource(R.string.cancel)) } },
|
||||||
title = { Text(stringResource(selectedPermission!!.label)) },
|
title = { Text(stringResource(permission.label)) },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
Text(selectedPermission!!.permission)
|
Text(permission.id)
|
||||||
Spacer(Modifier.padding(vertical = 4.dp))
|
Spacer(Modifier.padding(vertical = 4.dp))
|
||||||
if(!(VERSION.SDK_INT >= 31 && selectedPermission!!.profileOwnerRestricted && privilege.profile)) {
|
if(!(VERSION.SDK_INT >= 31 && permission.profileOwnerRestricted && privilege.profile)) {
|
||||||
GrantPermissionItem(R.string.granted, PERMISSION_GRANT_STATE_GRANTED)
|
GrantPermissionItem(R.string.granted, PERMISSION_GRANT_STATE_GRANTED)
|
||||||
}
|
}
|
||||||
GrantPermissionItem(R.string.denied, PERMISSION_GRANT_STATE_DENIED)
|
GrantPermissionItem(R.string.denied, PERMISSION_GRANT_STATE_DENIED)
|
||||||
@@ -393,8 +394,8 @@ fun ClearAppStorageScreen(
|
|||||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
||||||
onClear: (String, (Boolean) -> Unit) -> Unit, onNavigateUp: () -> Unit
|
onClear: (String, (Boolean) -> Unit) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
var dialog by remember { mutableStateOf(false) }
|
var dialog by rememberSaveable { mutableStateOf(false) }
|
||||||
var packageName by remember { mutableStateOf("") }
|
var packageName by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
}
|
}
|
||||||
@@ -418,7 +419,7 @@ private fun ClearAppStorageDialog(
|
|||||||
packageName: String, onClear: (String, (Boolean) -> Unit) -> Unit, onClose: () -> Unit
|
packageName: String, onClear: (String, (Boolean) -> Unit) -> Unit, onClose: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var clearing by remember { mutableStateOf(false) }
|
var clearing by rememberSaveable { mutableStateOf(false) }
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title = { Text(stringResource(R.string.clear_app_storage)) },
|
title = { Text(stringResource(R.string.clear_app_storage)) },
|
||||||
text = {
|
text = {
|
||||||
@@ -457,8 +458,8 @@ fun UninstallAppScreen(
|
|||||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
||||||
onUninstall: (String, (String?) -> Unit) -> Unit, onNavigateUp: () -> Unit
|
onUninstall: (String, (String?) -> Unit) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
var dialog by remember { mutableStateOf(false) }
|
var dialog by rememberSaveable { mutableStateOf(false) }
|
||||||
var packageName by remember { mutableStateOf("") }
|
var packageName by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
}
|
}
|
||||||
@@ -483,8 +484,8 @@ fun UninstallAppScreen(
|
|||||||
private fun UninstallAppDialog(
|
private fun UninstallAppDialog(
|
||||||
packageName: String, onUninstall: (String, (String?) -> Unit) -> Unit, onClose: () -> Unit
|
packageName: String, onUninstall: (String, (String?) -> Unit) -> Unit, onClose: () -> Unit
|
||||||
) {
|
) {
|
||||||
var uninstalling by remember { mutableStateOf(false) }
|
var uninstalling by rememberSaveable { mutableStateOf(false) }
|
||||||
var errorMessage by remember { mutableStateOf<String?>(null) }
|
var errorMessage by rememberSaveable { mutableStateOf<String?>(null) }
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
title = { Text(stringResource(R.string.uninstall)) },
|
title = { Text(stringResource(R.string.uninstall)) },
|
||||||
text = {
|
text = {
|
||||||
@@ -525,7 +526,7 @@ fun InstallExistingAppScreen(
|
|||||||
onInstall: (String) -> Boolean, onNavigateUp: () -> Unit
|
onInstall: (String) -> Boolean, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var packageName by remember { mutableStateOf("") }
|
var packageName by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
}
|
}
|
||||||
@@ -561,7 +562,7 @@ fun CredentialManagerPolicyScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var policy by rememberSaveable { mutableIntStateOf(getCmPolicy()) }
|
var policy by rememberSaveable { mutableIntStateOf(getCmPolicy()) }
|
||||||
val packages by cmPackages.collectAsStateWithLifecycle()
|
val packages by cmPackages.collectAsStateWithLifecycle()
|
||||||
var packageName by remember { mutableStateOf("") }
|
var packageName by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
}
|
}
|
||||||
@@ -623,7 +624,7 @@ fun PermittedAsAndImPackages(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val packages by packagesState.collectAsStateWithLifecycle()
|
val packages by packagesState.collectAsStateWithLifecycle()
|
||||||
var packageName by remember { mutableStateOf("") }
|
var packageName by rememberSaveable { mutableStateOf("") }
|
||||||
var allowAll by rememberSaveable { mutableStateOf(getPackages()) }
|
var allowAll by rememberSaveable { mutableStateOf(getPackages()) }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
@@ -673,7 +674,7 @@ fun EnableSystemAppScreen(
|
|||||||
onEnable: (String) -> Unit, onNavigateUp: () -> Unit
|
onEnable: (String) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var packageName by remember { mutableStateOf("") }
|
var packageName by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
}
|
}
|
||||||
@@ -704,7 +705,7 @@ fun SetDefaultDialerScreen(
|
|||||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
chosenPackage: Channel<String>, onChoosePackage: () -> Unit,
|
||||||
onSet: (String) -> Unit, onNavigateUp: () -> Unit
|
onSet: (String) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
var packageName by remember { mutableStateOf("") }
|
var packageName by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
}
|
}
|
||||||
@@ -743,7 +744,7 @@ fun PackageFunctionScreen(
|
|||||||
chosenPackage: Channel<String>, onChoosePackage: () -> Unit, notes: Int? = null
|
chosenPackage: Channel<String>, onChoosePackage: () -> Unit, notes: Int? = null
|
||||||
) {
|
) {
|
||||||
val packages by packagesState.collectAsStateWithLifecycle()
|
val packages by packagesState.collectAsStateWithLifecycle()
|
||||||
var packageName by remember { mutableStateOf("") }
|
var packageName by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
onGet()
|
onGet()
|
||||||
packageName = chosenPackage.receive()
|
packageName = chosenPackage.receive()
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import android.os.Build.VERSION
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import com.bintianqi.owndroid.MyApplication
|
import com.bintianqi.owndroid.MyApplication
|
||||||
import com.bintianqi.owndroid.MyNotificationChannel
|
|
||||||
import com.bintianqi.owndroid.NotificationType
|
import com.bintianqi.owndroid.NotificationType
|
||||||
import com.bintianqi.owndroid.NotificationUtils
|
import com.bintianqi.owndroid.NotificationUtils
|
||||||
import com.bintianqi.owndroid.Privilege
|
import com.bintianqi.owndroid.Privilege
|
||||||
@@ -93,7 +92,7 @@ fun Context.getPackageInstaller(): PackageInstaller {
|
|||||||
val dhizukuErrorStatus = MutableStateFlow(0)
|
val dhizukuErrorStatus = MutableStateFlow(0)
|
||||||
|
|
||||||
data class PermissionItem(
|
data class PermissionItem(
|
||||||
val permission: String,
|
val id: String,
|
||||||
val label: Int,
|
val label: Int,
|
||||||
val icon: Int,
|
val icon: Int,
|
||||||
val profileOwnerRestricted: Boolean = false,
|
val profileOwnerRestricted: Boolean = false,
|
||||||
@@ -497,7 +496,7 @@ fun retrieveSecurityLogs(app: MyApplication) {
|
|||||||
val logs = Privilege.DPM.retrieveSecurityLogs(Privilege.DAR) ?: return@launch
|
val logs = Privilege.DPM.retrieveSecurityLogs(Privilege.DAR) ?: return@launch
|
||||||
app.myRepo.writeSecurityLogs(logs)
|
app.myRepo.writeSecurityLogs(logs)
|
||||||
NotificationUtils.sendBasicNotification(
|
NotificationUtils.sendBasicNotification(
|
||||||
app, NotificationType.SecurityLogsCollected, MyNotificationChannel.SecurityLogging,
|
app, NotificationType.SecurityLogsCollected,
|
||||||
app.getString(R.string.n_logs_in_total, logs.size)
|
app.getString(R.string.n_logs_in_total, logs.size)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,18 +24,14 @@ import androidx.compose.animation.animateContentSize
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.interaction.collectIsPressedAsState
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.ime
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
@@ -65,6 +61,7 @@ import androidx.compose.material3.DropdownMenu
|
|||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
|
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||||
import androidx.compose.material3.FilledTonalButton
|
import androidx.compose.material3.FilledTonalButton
|
||||||
import androidx.compose.material3.FilledTonalIconButton
|
import androidx.compose.material3.FilledTonalIconButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -113,12 +110,13 @@ import com.bintianqi.owndroid.HorizontalPadding
|
|||||||
import com.bintianqi.owndroid.MyViewModel
|
import com.bintianqi.owndroid.MyViewModel
|
||||||
import com.bintianqi.owndroid.Privilege
|
import com.bintianqi.owndroid.Privilege
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
import com.bintianqi.owndroid.formatFileSize
|
import com.bintianqi.owndroid.clickableTextField
|
||||||
import com.bintianqi.owndroid.formatDate
|
import com.bintianqi.owndroid.formatDate
|
||||||
|
import com.bintianqi.owndroid.formatFileSize
|
||||||
|
import com.bintianqi.owndroid.adaptiveInsets
|
||||||
import com.bintianqi.owndroid.popToast
|
import com.bintianqi.owndroid.popToast
|
||||||
import com.bintianqi.owndroid.showOperationResultToast
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.ErrorDialog
|
import com.bintianqi.owndroid.ui.ErrorDialog
|
||||||
import com.bintianqi.owndroid.ui.ExpandExposedTextFieldIcon
|
|
||||||
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
|
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
|
||||||
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
||||||
import com.bintianqi.owndroid.ui.FunctionItem
|
import com.bintianqi.owndroid.ui.FunctionItem
|
||||||
@@ -181,8 +179,8 @@ fun NetworkOptionsScreen(
|
|||||||
getLanEnabled: () -> Boolean, setLanEnabled: (Boolean) -> Unit, onNavigateUp: () -> Unit
|
getLanEnabled: () -> Boolean, setLanEnabled: (Boolean) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
var lanEnabled by remember { mutableStateOf(getLanEnabled()) }
|
var lanEnabled by rememberSaveable { mutableStateOf(getLanEnabled()) }
|
||||||
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
|
||||||
if(VERSION.SDK_INT >= 30 && (privilege.device || privilege.org)) {
|
if(VERSION.SDK_INT >= 30 && (privilege.device || privilege.org)) {
|
||||||
SwitchItem(R.string.lockdown_admin_configured_network, icon = R.drawable.wifi_password_fill0,
|
SwitchItem(R.string.lockdown_admin_configured_network, icon = R.drawable.wifi_password_fill0,
|
||||||
@@ -224,7 +222,7 @@ fun WifiScreen(
|
|||||||
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceContainer)
|
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceContainer)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize().padding(paddingValues)
|
modifier = Modifier.fillMaxSize().padding(paddingValues)
|
||||||
@@ -266,7 +264,7 @@ fun WifiOverviewScreen(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var macDialog by remember { mutableStateOf(false) }
|
var macDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
Column(Modifier.fillMaxSize()) {
|
Column(Modifier.fillMaxSize()) {
|
||||||
Spacer(Modifier.height(10.dp))
|
Spacer(Modifier.height(10.dp))
|
||||||
Row(
|
Row(
|
||||||
@@ -384,7 +382,7 @@ private fun SavedNetworks(
|
|||||||
removeNetwork: (Int) -> Boolean, editNetwork: (Int) -> Unit
|
removeNetwork: (Int) -> Boolean, editNetwork: (Int) -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var dialog by remember { mutableIntStateOf(-1) }
|
var dialog by rememberSaveable { mutableIntStateOf(-1) }
|
||||||
val list by configuredNetworks.collectAsStateWithLifecycle()
|
val list by configuredNetworks.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
getConfiguredNetworks()
|
getConfiguredNetworks()
|
||||||
@@ -513,7 +511,7 @@ fun UpdateNetworkScreen(info: WifiInfo, setNetwork: (WifiInfo) -> Boolean, onNav
|
|||||||
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceContainer)
|
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceContainer)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize().padding(paddingValues)
|
modifier = Modifier.fillMaxSize().padding(paddingValues)
|
||||||
@@ -537,21 +535,21 @@ private fun AddNetworkScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val fm = LocalFocusManager.current
|
val fm = LocalFocusManager.current
|
||||||
/** 0: None, 1:Status, 2:Security, 3:MAC randomization, 4:Static IP, 5:Proxy, 6:Hidden SSID */
|
/** 0: None, 1:Status, 2:Security, 3:MAC randomization, 4:Static IP, 5:Proxy, 6:Hidden SSID */
|
||||||
var menu by remember { mutableIntStateOf(0) }
|
var menu by rememberSaveable { mutableIntStateOf(0) }
|
||||||
var status by remember { mutableStateOf(WifiStatus.Enabled) }
|
var status by rememberSaveable { mutableStateOf(WifiStatus.Enabled) }
|
||||||
var ssid by remember { mutableStateOf("") }
|
var ssid by rememberSaveable { mutableStateOf("") }
|
||||||
var hiddenSsid by remember { mutableStateOf<Boolean?>(false) }
|
var hiddenSsid by rememberSaveable { mutableStateOf<Boolean?>(false) }
|
||||||
var security by remember { mutableStateOf<WifiSecurity?>(WifiSecurity.Open) }
|
var security by rememberSaveable { mutableStateOf<WifiSecurity?>(WifiSecurity.Open) }
|
||||||
var password by remember { mutableStateOf("") }
|
var password by rememberSaveable { mutableStateOf("") }
|
||||||
var macRandomization by remember { mutableStateOf<WifiMacRandomization?>(WifiMacRandomization.None) }
|
var macRandomization by rememberSaveable { mutableStateOf<WifiMacRandomization?>(WifiMacRandomization.None) }
|
||||||
var ipMode by remember { mutableStateOf<IpMode?>(IpMode.Dhcp) }
|
var ipMode by rememberSaveable { mutableStateOf<IpMode?>(IpMode.Dhcp) }
|
||||||
var ipAddress by remember { mutableStateOf("") }
|
var ipAddress by rememberSaveable { mutableStateOf("") }
|
||||||
var gatewayAddress by remember { mutableStateOf("") }
|
var gatewayAddress by rememberSaveable { mutableStateOf("") }
|
||||||
var dnsServers by remember { mutableStateOf("") }
|
var dnsServers by rememberSaveable { mutableStateOf("") }
|
||||||
var proxyMode by remember { mutableStateOf<ProxyMode?>(ProxyMode.None) }
|
var proxyMode by rememberSaveable { mutableStateOf<ProxyMode?>(ProxyMode.None) }
|
||||||
var httpProxyHost by remember { mutableStateOf("") }
|
var httpProxyHost by rememberSaveable { mutableStateOf("") }
|
||||||
var httpProxyPort by remember { mutableStateOf("") }
|
var httpProxyPort by rememberSaveable { mutableStateOf("") }
|
||||||
var httpProxyExclList by remember { mutableStateOf("") }
|
var httpProxyExclList by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
if (updating) {
|
if (updating) {
|
||||||
hiddenSsid = null
|
hiddenSsid = null
|
||||||
@@ -575,7 +573,7 @@ private fun AddNetworkScreen(
|
|||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
label = { Text(stringResource(R.string.status)) },
|
label = { Text(stringResource(R.string.status)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == 1) },
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == 1) },
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == 1, { menu = 0 }) {
|
ExposedDropdownMenu(menu == 1, { menu = 0 }) {
|
||||||
WifiStatus.entries.forEach {
|
WifiStatus.entries.forEach {
|
||||||
@@ -600,7 +598,7 @@ private fun AddNetworkScreen(
|
|||||||
stringResource(hiddenSsid?.yesOrNo ?: R.string.unchanged), {},
|
stringResource(hiddenSsid?.yesOrNo ?: R.string.unchanged), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.hidden_ssid)) },
|
readOnly = true, label = { Text(stringResource(R.string.hidden_ssid)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == 1) }
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == 1) }
|
||||||
)
|
)
|
||||||
DropdownMenu(menu == 6, { menu = 0 }) {
|
DropdownMenu(menu == 6, { menu = 0 }) {
|
||||||
if (updating) DropdownMenuItem(
|
if (updating) DropdownMenuItem(
|
||||||
@@ -633,7 +631,7 @@ private fun AddNetworkScreen(
|
|||||||
stringResource(security?.text ?: R.string.unchanged), {},
|
stringResource(security?.text ?: R.string.unchanged), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.security)) },
|
readOnly = true, label = { Text(stringResource(R.string.security)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == 1) }
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == 1) }
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == 2, { menu = 0 }) {
|
ExposedDropdownMenu(menu == 2, { menu = 0 }) {
|
||||||
if (updating) UnchangedMenuItem { security = null }
|
if (updating) UnchangedMenuItem { security = null }
|
||||||
@@ -662,7 +660,7 @@ private fun AddNetworkScreen(
|
|||||||
stringResource(macRandomization?.text ?: R.string.unchanged), {},
|
stringResource(macRandomization?.text ?: R.string.unchanged), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.mac_randomization)) },
|
readOnly = true, label = { Text(stringResource(R.string.mac_randomization)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == 3) },
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == 3) },
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == 3, { menu = 0 }) {
|
ExposedDropdownMenu(menu == 3, { menu = 0 }) {
|
||||||
if (updating) UnchangedMenuItem { macRandomization = null }
|
if (updating) UnchangedMenuItem { macRandomization = null }
|
||||||
@@ -686,7 +684,7 @@ private fun AddNetworkScreen(
|
|||||||
stringResource(ipMode?.text ?: R.string.unchanged), {},
|
stringResource(ipMode?.text ?: R.string.unchanged), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.ip_settings)) },
|
readOnly = true, label = { Text(stringResource(R.string.ip_settings)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == 4) },
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == 4) },
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == 4, { menu = 0 }) {
|
ExposedDropdownMenu(menu == 4, { menu = 0 }) {
|
||||||
if (updating) UnchangedMenuItem { ipMode = null }
|
if (updating) UnchangedMenuItem { ipMode = null }
|
||||||
@@ -737,7 +735,7 @@ private fun AddNetworkScreen(
|
|||||||
stringResource(proxyMode?.text ?: R.string.unchanged), {},
|
stringResource(proxyMode?.text ?: R.string.unchanged), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.proxy)) },
|
readOnly = true, label = { Text(stringResource(R.string.proxy)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == 5) },
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == 5) },
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == 5, { menu = 0 }) {
|
ExposedDropdownMenu(menu == 5, { menu = 0 }) {
|
||||||
if (updating) UnchangedMenuItem { proxyMode = null }
|
if (updating) UnchangedMenuItem { proxyMode = null }
|
||||||
@@ -783,19 +781,29 @@ private fun AddNetworkScreen(
|
|||||||
}
|
}
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
|
val proxyConf = if (proxyMode == ProxyMode.Http) {
|
||||||
|
ProxyConf(
|
||||||
|
httpProxyHost, httpProxyPort.toInt(),
|
||||||
|
httpProxyExclList.lines().filter { it.isNotBlank() }
|
||||||
|
)
|
||||||
|
} else null
|
||||||
|
val ipConf = if (ipMode == IpMode.Static) {
|
||||||
|
IpConf(ipAddress, gatewayAddress, dnsServers.lines().filter { it.isNotBlank() })
|
||||||
|
} else null
|
||||||
val result = setNetwork(WifiInfo(
|
val result = setNetwork(WifiInfo(
|
||||||
-1, ssid, hiddenSsid, "", macRandomization, status, security, password, ipMode,
|
-1, ssid, hiddenSsid, "", macRandomization, status, security, password, ipMode,
|
||||||
IpConf(ipAddress, gatewayAddress, dnsServers.lines().filter { it.isNotBlank() }),
|
ipConf, proxyMode, proxyConf
|
||||||
proxyMode, ProxyConf(httpProxyHost, httpProxyPort.toInt(), httpProxyExclList.lines().filter { it.isNotBlank() })
|
|
||||||
))
|
))
|
||||||
context.showOperationResultToast(result)
|
context.showOperationResultToast(result)
|
||||||
if (result) onNavigateUp()
|
if (result) onNavigateUp()
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)
|
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp),
|
||||||
|
enabled = (proxyMode != ProxyMode.Http ||
|
||||||
|
(httpProxyPort.toIntOrNull() != null && httpProxyHost.isNotBlank()))
|
||||||
) {
|
) {
|
||||||
Text(stringResource(if (updating) R.string.update else R.string.add))
|
Text(stringResource(if (updating) R.string.update else R.string.add))
|
||||||
}
|
}
|
||||||
Spacer(Modifier.height(40.dp))
|
Spacer(Modifier.height(60.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -807,7 +815,7 @@ fun WifiSecurityLevelScreen(
|
|||||||
getLevel: () -> Int, setLevel: (Int) -> Unit, onNavigateUp: () -> Unit
|
getLevel: () -> Int, setLevel: (Int) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var level by remember { mutableIntStateOf(getLevel()) }
|
var level by rememberSaveable { mutableIntStateOf(getLevel()) }
|
||||||
MyScaffold(R.string.min_wifi_security_level, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.min_wifi_security_level, onNavigateUp, 0.dp) {
|
||||||
FullWidthRadioButtonItem(R.string.wifi_security_open, level == WIFI_SECURITY_OPEN) { level = WIFI_SECURITY_OPEN }
|
FullWidthRadioButtonItem(R.string.wifi_security_open, level == WIFI_SECURITY_OPEN) { level = WIFI_SECURITY_OPEN }
|
||||||
FullWidthRadioButtonItem("WEP, WPA(2)-PSK", level == WIFI_SECURITY_PERSONAL) { level = WIFI_SECURITY_PERSONAL }
|
FullWidthRadioButtonItem("WEP, WPA(2)-PSK", level == WIFI_SECURITY_PERSONAL) { level = WIFI_SECURITY_PERSONAL }
|
||||||
@@ -845,8 +853,8 @@ fun WifiSsidPolicyScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
MyScaffold(R.string.wifi_ssid_policy, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.wifi_ssid_policy, onNavigateUp, 0.dp) {
|
||||||
var type by remember { mutableStateOf(SsidPolicyType.None) }
|
var type by rememberSaveable { mutableStateOf(SsidPolicyType.None) }
|
||||||
val list = remember { mutableStateListOf<String>() }
|
val list = rememberSaveable { mutableStateListOf<String>() }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
getPolicy().let {
|
getPolicy().let {
|
||||||
type = it.type
|
type = it.type
|
||||||
@@ -959,11 +967,7 @@ fun NetworkStatsScreen(
|
|||||||
var uid by rememberSaveable { mutableIntStateOf(NetworkStats.Bucket.UID_ALL) }
|
var uid by rememberSaveable { mutableIntStateOf(NetworkStats.Bucket.UID_ALL) }
|
||||||
var tag by rememberSaveable { mutableIntStateOf(NetworkStats.Bucket.TAG_NONE) }
|
var tag by rememberSaveable { mutableIntStateOf(NetworkStats.Bucket.TAG_NONE) }
|
||||||
var state by rememberSaveable { mutableStateOf(NetworkStatsState.All) }
|
var state by rememberSaveable { mutableStateOf(NetworkStatsState.All) }
|
||||||
val startTimeIs = remember { MutableInteractionSource() }
|
var errorMessage by rememberSaveable { mutableStateOf<String?>(null) }
|
||||||
val endTimeIs = remember { MutableInteractionSource() }
|
|
||||||
if (startTimeIs.collectIsPressedAsState().value) menu = NetworkStatsMenu.StartTime
|
|
||||||
if (endTimeIs.collectIsPressedAsState().value) menu = NetworkStatsMenu.EndTime
|
|
||||||
var errorMessage by remember { mutableStateOf<String?>(null) }
|
|
||||||
MyScaffold(R.string.network_stats, onNavigateUp) {
|
MyScaffold(R.string.network_stats, onNavigateUp) {
|
||||||
ExposedDropdownMenuBox(
|
ExposedDropdownMenuBox(
|
||||||
menu == NetworkStatsMenu.Type,
|
menu == NetworkStatsMenu.Type,
|
||||||
@@ -974,7 +978,9 @@ fun NetworkStatsScreen(
|
|||||||
stringResource(type.text), {},
|
stringResource(type.text), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.type)) },
|
readOnly = true, label = { Text(stringResource(R.string.type)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == NetworkStatsMenu.Type) }
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(menu == NetworkStatsMenu.Type)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(
|
ExposedDropdownMenu(
|
||||||
menu == NetworkStatsMenu.Type, { menu = NetworkStatsMenu.None }
|
menu == NetworkStatsMenu.Type, { menu = NetworkStatsMenu.None }
|
||||||
@@ -1001,7 +1007,9 @@ fun NetworkStatsScreen(
|
|||||||
stringResource(target.text), {},
|
stringResource(target.text), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.target)) },
|
readOnly = true, label = { Text(stringResource(R.string.target)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == NetworkStatsMenu.Target) }
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(menu == NetworkStatsMenu.Target)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(
|
ExposedDropdownMenu(
|
||||||
menu == NetworkStatsMenu.Target, { menu = NetworkStatsMenu.None }
|
menu == NetworkStatsMenu.Target, { menu = NetworkStatsMenu.None }
|
||||||
@@ -1028,7 +1036,9 @@ fun NetworkStatsScreen(
|
|||||||
stringResource(networkType.text), {},
|
stringResource(networkType.text), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.network_type)) },
|
readOnly = true, label = { Text(stringResource(R.string.network_type)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == NetworkStatsMenu.NetworkType) }
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(menu == NetworkStatsMenu.NetworkType)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(
|
ExposedDropdownMenu(
|
||||||
menu == NetworkStatsMenu.NetworkType, { menu = NetworkStatsMenu.None }
|
menu == NetworkStatsMenu.NetworkType, { menu = NetworkStatsMenu.None }
|
||||||
@@ -1045,18 +1055,22 @@ fun NetworkStatsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = startTime.let { if(it == -1L) "" else formatDate(it) }, onValueChange = {}, readOnly = true,
|
formatDate(startTime), {},
|
||||||
label = { Text(stringResource(R.string.start_time)) },
|
Modifier
|
||||||
interactionSource = startTimeIs,
|
.fillMaxWidth()
|
||||||
isError = startTime >= endTime,
|
.clickableTextField { menu = NetworkStatsMenu.StartTime }
|
||||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
.padding(bottom = 4.dp),
|
||||||
|
readOnly = true, label = { Text(stringResource(R.string.start_time)) },
|
||||||
|
isError = startTime >= endTime
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = formatDate(endTime), onValueChange = {}, readOnly = true,
|
formatDate(endTime), {},
|
||||||
label = { Text(stringResource(R.string.end_time)) },
|
Modifier
|
||||||
interactionSource = endTimeIs,
|
.fillMaxWidth()
|
||||||
isError = startTime >= endTime,
|
.clickableTextField { menu = NetworkStatsMenu.EndTime }
|
||||||
modifier = Modifier.fillMaxWidth().padding(bottom = 4.dp)
|
.padding(bottom = 4.dp),
|
||||||
|
readOnly = true, label = { Text(stringResource(R.string.end_time)) },
|
||||||
|
isError = startTime >= endTime
|
||||||
)
|
)
|
||||||
if(target == NetworkStatsTarget.Uid || target == NetworkStatsTarget.UidTag || target == NetworkStatsTarget.UidTagState)
|
if(target == NetworkStatsTarget.Uid || target == NetworkStatsTarget.UidTag || target == NetworkStatsTarget.UidTagState)
|
||||||
ExposedDropdownMenuBox(
|
ExposedDropdownMenuBox(
|
||||||
@@ -1077,7 +1091,7 @@ fun NetworkStatsScreen(
|
|||||||
it.toIntOrNull()?.let { num -> uid = num }
|
it.toIntOrNull()?.let { num -> uid = num }
|
||||||
},
|
},
|
||||||
readOnly = readOnly, label = { Text(stringResource(R.string.uid)) },
|
readOnly = readOnly, label = { Text(stringResource(R.string.uid)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == NetworkStatsMenu.Uid) },
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == NetworkStatsMenu.Uid) },
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
isError = !readOnly && uidText.toIntOrNull() == null,
|
isError = !readOnly && uidText.toIntOrNull() == null,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -1131,7 +1145,9 @@ fun NetworkStatsScreen(
|
|||||||
it.toIntOrNull()?.let { num -> tag = num }
|
it.toIntOrNull()?.let { num -> tag = num }
|
||||||
},
|
},
|
||||||
readOnly = readOnly, label = { Text(stringResource(R.string.uid)) },
|
readOnly = readOnly, label = { Text(stringResource(R.string.uid)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == NetworkStatsMenu.Tag) },
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(menu == NetworkStatsMenu.Tag)
|
||||||
|
},
|
||||||
isError = !readOnly && tagText.toIntOrNull() == null,
|
isError = !readOnly && tagText.toIntOrNull() == null,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.menuAnchor(if(readOnly) MenuAnchorType.PrimaryNotEditable else MenuAnchorType.PrimaryEditable)
|
.menuAnchor(if(readOnly) MenuAnchorType.PrimaryNotEditable else MenuAnchorType.PrimaryEditable)
|
||||||
@@ -1168,7 +1184,9 @@ fun NetworkStatsScreen(
|
|||||||
stringResource(state.text), {},
|
stringResource(state.text), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
readOnly = true, label = { Text(stringResource(R.string.uid)) },
|
readOnly = true, label = { Text(stringResource(R.string.uid)) },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == NetworkStatsMenu.State) }
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(menu == NetworkStatsMenu.State)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(
|
ExposedDropdownMenu(
|
||||||
menu == NetworkStatsMenu.State, { menu = NetworkStatsMenu.None }
|
menu == NetworkStatsMenu.State, { menu = NetworkStatsMenu.None }
|
||||||
@@ -1251,7 +1269,7 @@ data class NetworkStatsData(
|
|||||||
fun NetworkStatsViewerScreen(
|
fun NetworkStatsViewerScreen(
|
||||||
data: List<NetworkStatsData>, clearData: () -> Unit, onNavigateUp: () -> Unit
|
data: List<NetworkStatsData>, clearData: () -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
var index by remember { mutableIntStateOf(0) }
|
var index by rememberSaveable { mutableIntStateOf(0) }
|
||||||
val size = data.size
|
val size = data.size
|
||||||
val ps = rememberPagerState { size }
|
val ps = rememberPagerState { size }
|
||||||
index = ps.currentPage
|
index = ps.currentPage
|
||||||
@@ -1362,7 +1380,7 @@ fun PrivateDnsScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var mode by remember { mutableStateOf<PrivateDnsMode?>(PrivateDnsMode.Opportunistic) }
|
var mode by remember { mutableStateOf<PrivateDnsMode?>(PrivateDnsMode.Opportunistic) }
|
||||||
var inputHost by remember { mutableStateOf("") }
|
var inputHost by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
val conf = getPrivateDns()
|
val conf = getPrivateDns()
|
||||||
mode = conf.mode
|
mode = conf.mode
|
||||||
@@ -1451,12 +1469,12 @@ fun RecommendedGlobalProxyScreen(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var type by remember { mutableStateOf(ProxyType.Off) }
|
var type by rememberSaveable { mutableStateOf(ProxyType.Off) }
|
||||||
var pacUrl by remember { mutableStateOf("") }
|
var pacUrl by rememberSaveable { mutableStateOf("") }
|
||||||
var specifyPort by remember { mutableStateOf(false) }
|
var specifyPort by rememberSaveable { mutableStateOf(false) }
|
||||||
var host by remember { mutableStateOf("") }
|
var host by rememberSaveable { mutableStateOf("") }
|
||||||
var port by remember { mutableStateOf("") }
|
var port by rememberSaveable { mutableStateOf("") }
|
||||||
var exclList by remember { mutableStateOf("") }
|
var exclList by rememberSaveable { mutableStateOf("") }
|
||||||
MyScaffold(R.string.recommended_global_proxy, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.recommended_global_proxy, onNavigateUp, 0.dp) {
|
||||||
ProxyType.entries.forEach {
|
ProxyType.entries.forEach {
|
||||||
FullWidthRadioButtonItem(it.text, type == it) { type = it }
|
FullWidthRadioButtonItem(it.text, type == it) { type = it }
|
||||||
@@ -1576,7 +1594,7 @@ fun PreferentialNetworkServiceScreen(
|
|||||||
pnsConfigs: StateFlow<List<PreferentialNetworkServiceInfo>>, getConfigs: () -> Unit,
|
pnsConfigs: StateFlow<List<PreferentialNetworkServiceInfo>>, getConfigs: () -> Unit,
|
||||||
onNavigateUp: () -> Unit, onNavigate: (AddPreferentialNetworkServiceConfig) -> Unit
|
onNavigateUp: () -> Unit, onNavigate: (AddPreferentialNetworkServiceConfig) -> Unit
|
||||||
) {
|
) {
|
||||||
var masterEnabled by remember { mutableStateOf(getEnabled()) }
|
var masterEnabled by rememberSaveable { mutableStateOf(getEnabled()) }
|
||||||
val configs by pnsConfigs.collectAsStateWithLifecycle()
|
val configs by pnsConfigs.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
getConfigs()
|
getConfigs()
|
||||||
@@ -1633,12 +1651,12 @@ fun AddPreferentialNetworkServiceConfigScreen(
|
|||||||
setConfig: (PreferentialNetworkServiceInfo, Boolean) -> Unit, onNavigateUp: () -> Unit
|
setConfig: (PreferentialNetworkServiceInfo, Boolean) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val updateMode = origin.id != -1
|
val updateMode = origin.id != -1
|
||||||
var enabled by remember { mutableStateOf(origin.enabled) }
|
var enabled by rememberSaveable { mutableStateOf(origin.enabled) }
|
||||||
var id by remember { mutableIntStateOf(origin.id) }
|
var id by rememberSaveable { mutableIntStateOf(origin.id) }
|
||||||
var allowFallback by remember { mutableStateOf(origin.allowFallback) }
|
var allowFallback by rememberSaveable { mutableStateOf(origin.allowFallback) }
|
||||||
var blockNonMatching by remember { mutableStateOf(origin.blockNonMatching) }
|
var blockNonMatching by rememberSaveable { mutableStateOf(origin.blockNonMatching) }
|
||||||
var excludedUids by remember { mutableStateOf(origin.excludedUids.joinToString("\n")) }
|
var excludedUids by rememberSaveable { mutableStateOf(origin.excludedUids.joinToString("\n")) }
|
||||||
var includedUids by remember { mutableStateOf(origin.includedUids.joinToString("\n")) }
|
var includedUids by rememberSaveable { mutableStateOf(origin.includedUids.joinToString("\n")) }
|
||||||
var dropdown by remember { mutableStateOf(false) }
|
var dropdown by remember { mutableStateOf(false) }
|
||||||
MySmallTitleScaffold(R.string.preferential_network_service, onNavigateUp) {
|
MySmallTitleScaffold(R.string.preferential_network_service, onNavigateUp) {
|
||||||
SwitchItem(title = R.string.enabled, state = enabled, onCheckedChange = { enabled = it }, padding = false)
|
SwitchItem(title = R.string.enabled, state = enabled, onCheckedChange = { enabled = it }, padding = false)
|
||||||
@@ -1647,7 +1665,7 @@ fun AddPreferentialNetworkServiceConfigScreen(
|
|||||||
if (id == -1) "" else id.toString(), {},
|
if (id == -1) "" else id.toString(), {},
|
||||||
Modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryNotEditable),
|
Modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryNotEditable),
|
||||||
readOnly = true, label = { Text("id") },
|
readOnly = true, label = { Text("id") },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(dropdown) }
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(dropdown) }
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(dropdown, { dropdown = false }) {
|
ExposedDropdownMenu(dropdown, { dropdown = false }) {
|
||||||
for (i in 1..5) {
|
for (i in 1..5) {
|
||||||
@@ -1724,7 +1742,7 @@ fun OverrideApnScreen(
|
|||||||
apnConfigs: StateFlow<List<ApnConfig>>, getConfigs: () -> Unit, getEnabled: () -> Boolean,
|
apnConfigs: StateFlow<List<ApnConfig>>, getConfigs: () -> Unit, getEnabled: () -> Boolean,
|
||||||
setEnabled: (Boolean) -> Unit, onNavigateUp: () -> Unit, onNavigateToAddSetting: (Int) -> Unit
|
setEnabled: (Boolean) -> Unit, onNavigateUp: () -> Unit, onNavigateToAddSetting: (Int) -> Unit
|
||||||
) {
|
) {
|
||||||
var enabled by remember { mutableStateOf(getEnabled()) }
|
var enabled by rememberSaveable { mutableStateOf(getEnabled()) }
|
||||||
val configs by apnConfigs.collectAsStateWithLifecycle()
|
val configs by apnConfigs.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) { getConfigs() }
|
LaunchedEffect(Unit) { getConfigs() }
|
||||||
MyScaffold(R.string.override_apn, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.override_apn, onNavigateUp, 0.dp) {
|
||||||
@@ -1859,30 +1877,30 @@ fun AddApnSettingScreen(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var menu by remember { mutableStateOf(ApnMenu.None) }
|
var menu by remember { mutableStateOf(ApnMenu.None) }
|
||||||
var enabled by remember { mutableStateOf(true) }
|
var enabled by rememberSaveable { mutableStateOf(true) }
|
||||||
var entryName by remember { mutableStateOf(origin?.name ?: "") }
|
var entryName by rememberSaveable { mutableStateOf(origin?.name ?: "") }
|
||||||
var apnName by remember { mutableStateOf(origin?.apn ?: "") }
|
var apnName by rememberSaveable { mutableStateOf(origin?.apn ?: "") }
|
||||||
var apnType by remember { mutableIntStateOf(origin?.apnType ?: 0) }
|
var apnType by rememberSaveable { mutableIntStateOf(origin?.apnType ?: 0) }
|
||||||
var profileId by remember { mutableStateOf(origin?.profileId?.toString() ?: "") }
|
var profileId by rememberSaveable { mutableStateOf(origin?.profileId?.toString() ?: "") }
|
||||||
var carrierId by remember { mutableStateOf(origin?.carrierId?.toString() ?: "") }
|
var carrierId by rememberSaveable { mutableStateOf(origin?.carrierId?.toString() ?: "") }
|
||||||
var authType by remember { mutableStateOf(ApnAuthType.None) }
|
var authType by rememberSaveable { mutableStateOf(ApnAuthType.None) }
|
||||||
var user by remember { mutableStateOf(origin?.username ?: "") }
|
var user by rememberSaveable { mutableStateOf(origin?.username ?: "") }
|
||||||
var password by remember { mutableStateOf(origin?.password ?: "") }
|
var password by rememberSaveable { mutableStateOf(origin?.password ?: "") }
|
||||||
var proxy by remember { mutableStateOf(origin?.proxy ?: "") }
|
var proxy by rememberSaveable { mutableStateOf(origin?.proxy ?: "") }
|
||||||
var port by remember { mutableStateOf(origin?.port?.toString() ?: "") }
|
var port by rememberSaveable { mutableStateOf(origin?.port?.toString() ?: "") }
|
||||||
var mmsProxy by remember { mutableStateOf(origin?.mmsProxy ?: "") }
|
var mmsProxy by rememberSaveable { mutableStateOf(origin?.mmsProxy ?: "") }
|
||||||
var mmsPort by remember { mutableStateOf(origin?.mmsPort?.toString() ?: "") }
|
var mmsPort by rememberSaveable { mutableStateOf(origin?.mmsPort?.toString() ?: "") }
|
||||||
var mmsc by remember { mutableStateOf(origin?.mmsc ?: "") }
|
var mmsc by rememberSaveable { mutableStateOf(origin?.mmsc ?: "") }
|
||||||
var mtuV4 by remember { mutableStateOf(origin?.mtuV4?.toString() ?: "") }
|
var mtuV4 by rememberSaveable { mutableStateOf(origin?.mtuV4?.toString() ?: "") }
|
||||||
var mtuV6 by remember { mutableStateOf(origin?.mtuV6?.toString() ?: "") }
|
var mtuV6 by rememberSaveable { mutableStateOf(origin?.mtuV6?.toString() ?: "") }
|
||||||
var mvnoType by remember { mutableStateOf(origin?.mvno ?: ApnMvnoType.SPN) }
|
var mvnoType by rememberSaveable { mutableStateOf(origin?.mvno ?: ApnMvnoType.SPN) }
|
||||||
var networkType by remember { mutableIntStateOf(origin?.networkType ?: 0) }
|
var networkType by rememberSaveable { mutableIntStateOf(origin?.networkType ?: 0) }
|
||||||
var operatorNumeric by remember { mutableStateOf(origin?.operatorNumeric ?: "") }
|
var operatorNumeric by rememberSaveable { mutableStateOf(origin?.operatorNumeric ?: "") }
|
||||||
var protocol by remember { mutableStateOf(origin?.protocol ?: ApnProtocol.Ip) }
|
var protocol by rememberSaveable { mutableStateOf(origin?.protocol ?: ApnProtocol.Ip) }
|
||||||
var roamingProtocol by remember { mutableStateOf(origin?.roamingProtocol ?: ApnProtocol.Ip) }
|
var roamingProtocol by rememberSaveable { mutableStateOf(origin?.roamingProtocol ?: ApnProtocol.Ip) }
|
||||||
var persistent by remember { mutableStateOf(origin?.persistent == true) }
|
var persistent by rememberSaveable { mutableStateOf(origin?.persistent == true) }
|
||||||
var alwaysOn by remember { mutableStateOf(origin?.alwaysOn == true) }
|
var alwaysOn by rememberSaveable { mutableStateOf(origin?.alwaysOn == true) }
|
||||||
var errorMessage: String? by remember { mutableStateOf(null) }
|
var errorMessage: String? by rememberSaveable { mutableStateOf(null) }
|
||||||
MySmallTitleScaffold(R.string.apn_setting, onNavigateUp) {
|
MySmallTitleScaffold(R.string.apn_setting, onNavigateUp) {
|
||||||
SwitchItem(R.string.enabled, state = enabled, onCheckedChange = { enabled = it }, padding = false)
|
SwitchItem(R.string.enabled, state = enabled, onCheckedChange = { enabled = it }, padding = false)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
@@ -1950,7 +1968,7 @@ fun AddApnSettingScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
authType.text, {}, Modifier.fillMaxWidth(),
|
authType.text, {}, Modifier.fillMaxWidth(),
|
||||||
label = { Text("Authentication type") },
|
label = { Text("Authentication type") },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == ApnMenu.AuthType) }
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == ApnMenu.AuthType) }
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == ApnMenu.AuthType, { menu = ApnMenu.None }) {
|
ExposedDropdownMenu(menu == ApnMenu.AuthType, { menu = ApnMenu.None }) {
|
||||||
ApnAuthType.entries.forEach {
|
ApnAuthType.entries.forEach {
|
||||||
@@ -1970,7 +1988,7 @@ fun AddApnSettingScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
protocol.text, {}, Modifier.fillMaxWidth(),
|
protocol.text, {}, Modifier.fillMaxWidth(),
|
||||||
label = { Text("APN protocol") },
|
label = { Text("APN protocol") },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == ApnMenu.Protocol) }
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(menu == ApnMenu.Protocol) }
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == ApnMenu.Protocol, { menu = ApnMenu.None }) {
|
ExposedDropdownMenu(menu == ApnMenu.Protocol, { menu = ApnMenu.None }) {
|
||||||
ApnProtocol.entries.filter { VERSION.SDK_INT >= it.requiresApi }.forEach {
|
ApnProtocol.entries.filter { VERSION.SDK_INT >= it.requiresApi }.forEach {
|
||||||
@@ -1991,7 +2009,9 @@ fun AddApnSettingScreen(
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
roamingProtocol.text, {}, Modifier.fillMaxWidth(),
|
roamingProtocol.text, {}, Modifier.fillMaxWidth(),
|
||||||
label = { Text("APN roaming protocol") },
|
label = { Text("APN roaming protocol") },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == ApnMenu.RoamingProtocol) }
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(menu == ApnMenu.RoamingProtocol)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == ApnMenu.RoamingProtocol, { menu = ApnMenu.None }) {
|
ExposedDropdownMenu(menu == ApnMenu.RoamingProtocol, { menu = ApnMenu.None }) {
|
||||||
ApnProtocol.entries.filter { VERSION.SDK_INT >= it.requiresApi }.forEach {
|
ApnProtocol.entries.filter { VERSION.SDK_INT >= it.requiresApi }.forEach {
|
||||||
@@ -2050,7 +2070,9 @@ fun AddApnSettingScreen(
|
|||||||
mvnoType.text, {},
|
mvnoType.text, {},
|
||||||
Modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryNotEditable),
|
Modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryNotEditable),
|
||||||
readOnly = true, label = { Text("MVNO type") },
|
readOnly = true, label = { Text("MVNO type") },
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(menu == ApnMenu.RoamingProtocol) }
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(menu == ApnMenu.RoamingProtocol)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(menu == ApnMenu.MvnoType, { menu = ApnMenu.None }) {
|
ExposedDropdownMenu(menu == ApnMenu.MvnoType, { menu = ApnMenu.None }) {
|
||||||
ApnMvnoType.entries.forEach {
|
ApnMvnoType.entries.forEach {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -80,7 +81,7 @@ import kotlinx.serialization.Serializable
|
|||||||
fun PasswordScreen(vm: MyViewModel,onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
fun PasswordScreen(vm: MyViewModel,onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
MyScaffold(R.string.password_and_keyguard, onNavigateUp, 0.dp) {
|
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(PasswordInfo) }
|
||||||
if (SP.displayDangerousFeatures) {
|
if (SP.displayDangerousFeatures) {
|
||||||
@@ -210,7 +211,7 @@ fun PasswordInfoScreen(
|
|||||||
onNavigateUp: () -> Unit
|
onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var dialog by remember { mutableIntStateOf(0) } // 0:none, 1:password complexity
|
var dialog by rememberSaveable { mutableIntStateOf(0) } // 0:none, 1:password complexity
|
||||||
MyScaffold(R.string.password_info, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.password_info, onNavigateUp, 0.dp) {
|
||||||
if (VERSION.SDK_INT >= 29) {
|
if (VERSION.SDK_INT >= 29) {
|
||||||
InfoItem(R.string.current_password_complexity, getComplexity().text, true) { dialog = 1 }
|
InfoItem(R.string.current_password_complexity, getComplexity().text, true) { dialog = 1 }
|
||||||
@@ -242,8 +243,8 @@ fun ResetPasswordTokenScreen(
|
|||||||
clearToken: () -> Boolean, onNavigateUp: () -> Unit
|
clearToken: () -> Boolean, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var token by remember { mutableStateOf("") }
|
var token by rememberSaveable { mutableStateOf("") }
|
||||||
var state by remember { mutableStateOf(getState()) }
|
var state by rememberSaveable { mutableStateOf(getState()) }
|
||||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
if (it.resultCode == Activity.RESULT_OK) {
|
if (it.resultCode == Activity.RESULT_OK) {
|
||||||
context.popToast(R.string.token_activated)
|
context.popToast(R.string.token_activated)
|
||||||
@@ -305,10 +306,10 @@ fun ResetPasswordTokenScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
fun ResetPasswordScreen(resetPassword: (String, String, Int) -> Boolean, onNavigateUp: () -> Unit) {
|
fun ResetPasswordScreen(resetPassword: (String, String, Int) -> Boolean, onNavigateUp: () -> Unit) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var password by remember { mutableStateOf("") }
|
var password by rememberSaveable { mutableStateOf("") }
|
||||||
var token by remember { mutableStateOf("") }
|
var token by rememberSaveable { mutableStateOf("") }
|
||||||
var flags by remember { mutableIntStateOf(0) }
|
var flags by rememberSaveable { mutableIntStateOf(0) }
|
||||||
var confirmPassword by remember { mutableStateOf("") }
|
var confirmPassword by rememberSaveable { mutableStateOf("") }
|
||||||
MyScaffold(R.string.reset_password, onNavigateUp) {
|
MyScaffold(R.string.reset_password, onNavigateUp) {
|
||||||
if (VERSION.SDK_INT >= 26) {
|
if (VERSION.SDK_INT >= 26) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
@@ -366,7 +367,7 @@ fun RequiredPasswordComplexityScreen(
|
|||||||
onNavigateUp: () -> Unit
|
onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var complexity by remember { mutableStateOf(PasswordComplexity.None) }
|
var complexity by rememberSaveable { mutableStateOf(PasswordComplexity.None) }
|
||||||
LaunchedEffect(Unit) { complexity = getComplexity() }
|
LaunchedEffect(Unit) { complexity = getComplexity() }
|
||||||
MyScaffold(R.string.required_password_complexity, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.required_password_complexity, onNavigateUp, 0.dp) {
|
||||||
PasswordComplexity.entries.forEach {
|
PasswordComplexity.entries.forEach {
|
||||||
@@ -415,8 +416,8 @@ fun KeyguardDisabledFeaturesScreen(
|
|||||||
onNavigateUp: () -> Unit
|
onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var mode by remember { mutableStateOf(KeyguardDisableMode.None) }
|
var mode by rememberSaveable { mutableStateOf(KeyguardDisableMode.None) }
|
||||||
var flags by remember { mutableIntStateOf(0) }
|
var flags by rememberSaveable { mutableIntStateOf(0) }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
val config = getConfig()
|
val config = getConfig()
|
||||||
mode = config.mode
|
mode = config.mode
|
||||||
@@ -462,7 +463,7 @@ fun RequiredPasswordQualityScreen(onNavigateUp: () -> Unit) {
|
|||||||
PASSWORD_QUALITY_BIOMETRIC_WEAK to R.string.password_quality_biometrics_weak,
|
PASSWORD_QUALITY_BIOMETRIC_WEAK to R.string.password_quality_biometrics_weak,
|
||||||
PASSWORD_QUALITY_NUMERIC_COMPLEX to R.string.password_quality_numeric_complex
|
PASSWORD_QUALITY_NUMERIC_COMPLEX to R.string.password_quality_numeric_complex
|
||||||
)
|
)
|
||||||
var selectedItem by remember { mutableIntStateOf(PASSWORD_QUALITY_UNSPECIFIED) }
|
var selectedItem by rememberSaveable { mutableIntStateOf(PASSWORD_QUALITY_UNSPECIFIED) }
|
||||||
LaunchedEffect(Unit) { selectedItem = Privilege.DPM.getPasswordQuality(Privilege.DAR) }
|
LaunchedEffect(Unit) { selectedItem = Privilege.DPM.getPasswordQuality(Privilege.DAR) }
|
||||||
MyScaffold(R.string.required_password_quality, onNavigateUp) {
|
MyScaffold(R.string.required_password_quality, onNavigateUp) {
|
||||||
passwordQuality.forEach {
|
passwordQuality.forEach {
|
||||||
|
|||||||
@@ -16,11 +16,9 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.ime
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
@@ -90,6 +88,7 @@ import com.bintianqi.owndroid.MyViewModel
|
|||||||
import com.bintianqi.owndroid.Privilege
|
import com.bintianqi.owndroid.Privilege
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
import com.bintianqi.owndroid.Settings
|
import com.bintianqi.owndroid.Settings
|
||||||
|
import com.bintianqi.owndroid.adaptiveInsets
|
||||||
import com.bintianqi.owndroid.showOperationResultToast
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.CircularProgressDialog
|
import com.bintianqi.owndroid.ui.CircularProgressDialog
|
||||||
import com.bintianqi.owndroid.ui.InfoItem
|
import com.bintianqi.owndroid.ui.InfoItem
|
||||||
@@ -116,9 +115,9 @@ fun WorkModesScreen(
|
|||||||
) {
|
) {
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
/** 0: none, 1: device owner, 2: circular progress indicator, 3: result, 4: deactivate, 5: command */
|
/** 0: none, 1: device owner, 2: circular progress indicator, 3: result, 4: deactivate, 5: command */
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
var operationSucceed by remember { mutableStateOf(false) }
|
var operationSucceed by rememberSaveable { mutableStateOf(false) }
|
||||||
var resultText by remember { mutableStateOf("") }
|
var resultText by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(privilege) {
|
LaunchedEffect(privilege) {
|
||||||
if (!params.canNavigateUp && privilege.device) {
|
if (!params.canNavigateUp && privilege.device) {
|
||||||
delay(1000)
|
delay(1000)
|
||||||
@@ -182,7 +181,7 @@ fun WorkModesScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
fun handleResult(succeeded: Boolean, output: String?) {
|
fun handleResult(succeeded: Boolean, output: String?) {
|
||||||
operationSucceed = succeeded
|
operationSucceed = succeeded
|
||||||
@@ -367,7 +366,7 @@ fun DhizukuServerSettingsScreen(
|
|||||||
getDhizukuClients: () -> Unit, updateDhizukuClient: (DhizukuClientInfo) -> Unit,
|
getDhizukuClients: () -> Unit, updateDhizukuClient: (DhizukuClientInfo) -> Unit,
|
||||||
getServerEnabled: () -> Boolean, setServerEnabled: (Boolean) -> Unit, onNavigateUp: () -> Unit
|
getServerEnabled: () -> Boolean, setServerEnabled: (Boolean) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
var enabled by remember { mutableStateOf(getServerEnabled()) }
|
var enabled by rememberSaveable { mutableStateOf(getServerEnabled()) }
|
||||||
val clients by dhizukuClients.collectAsStateWithLifecycle()
|
val clients by dhizukuClients.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) { getDhizukuClients() }
|
LaunchedEffect(Unit) { getDhizukuClients() }
|
||||||
MyLazyScaffold(R.string.dhizuku_server, onNavigateUp) {
|
MyLazyScaffold(R.string.dhizuku_server, onNavigateUp) {
|
||||||
@@ -455,7 +454,7 @@ fun LockScreenInfoScreen(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var infoText by remember { mutableStateOf(getText()) }
|
var infoText by rememberSaveable { mutableStateOf(getText()) }
|
||||||
MyScaffold(R.string.lock_screen_info, onNavigateUp) {
|
MyScaffold(R.string.lock_screen_info, onNavigateUp) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = infoText,
|
value = infoText,
|
||||||
@@ -566,7 +565,7 @@ fun AddDelegatedAdminScreen(
|
|||||||
setDelegatedAdmin: (String, List<String>) -> Unit, onNavigateUp: () -> Unit
|
setDelegatedAdmin: (String, List<String>) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val updateMode = data.pkg.isNotEmpty()
|
val updateMode = data.pkg.isNotEmpty()
|
||||||
var input by remember { mutableStateOf(data.pkg) }
|
var input by rememberSaveable { mutableStateOf(data.pkg) }
|
||||||
val scopes = rememberSaveable { mutableStateListOf(*data.scopes.toTypedArray()) }
|
val scopes = rememberSaveable { mutableStateListOf(*data.scopes.toTypedArray()) }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
input = chosenPackage.receive()
|
input = chosenPackage.receive()
|
||||||
@@ -625,7 +624,7 @@ fun AddDelegatedAdminScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
fun DeviceInfoScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
fun DeviceInfoScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
MyScaffold(R.string.device_info, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.device_info, onNavigateUp, 0.dp) {
|
||||||
if (VERSION.SDK_INT >= 34 && (privilege.device || privilege.org)) {
|
if (VERSION.SDK_INT >= 34 && (privilege.device || privilege.org)) {
|
||||||
InfoItem(R.string.financed_device, vm.getDeviceFinanced().yesOrNo)
|
InfoItem(R.string.financed_device, vm.getDeviceFinanced().yesOrNo)
|
||||||
@@ -666,8 +665,8 @@ fun SupportMessageScreen(
|
|||||||
setLongMessage: (String?) -> Unit, onNavigateUp: () -> Unit
|
setLongMessage: (String?) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var shortMsg by remember { mutableStateOf("") }
|
var shortMsg by rememberSaveable { mutableStateOf("") }
|
||||||
var longMsg by remember { mutableStateOf("") }
|
var longMsg by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
shortMsg = getShortMessage()
|
shortMsg = getShortMessage()
|
||||||
longMsg = getLongMessage()
|
longMsg = getLongMessage()
|
||||||
@@ -750,8 +749,8 @@ fun TransferOwnershipScreen(
|
|||||||
transferOwnership: (ComponentName) -> Unit, onNavigateUp: () -> Unit, onTransferred: () -> Unit
|
transferOwnership: (ComponentName) -> Unit, onNavigateUp: () -> Unit, onTransferred: () -> Unit
|
||||||
) {
|
) {
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var selectedIndex by remember { mutableIntStateOf(-1) }
|
var selectedIndex by rememberSaveable { mutableIntStateOf(-1) }
|
||||||
var dialog by remember { mutableStateOf(false) }
|
var dialog by rememberSaveable { mutableStateOf(false) }
|
||||||
val receivers by deviceAdmins.collectAsStateWithLifecycle()
|
val receivers by deviceAdmins.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) { getDeviceAdmins() }
|
LaunchedEffect(Unit) { getDeviceAdmins() }
|
||||||
MyLazyScaffold(R.string.transfer_ownership, onNavigateUp) {
|
MyLazyScaffold(R.string.transfer_ownership, onNavigateUp) {
|
||||||
|
|||||||
@@ -31,17 +31,13 @@ import androidx.compose.animation.AnimatedVisibility
|
|||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.interaction.collectIsPressedAsState
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.ime
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
@@ -110,7 +106,9 @@ import com.bintianqi.owndroid.MyViewModel
|
|||||||
import com.bintianqi.owndroid.Privilege
|
import com.bintianqi.owndroid.Privilege
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
import com.bintianqi.owndroid.SP
|
import com.bintianqi.owndroid.SP
|
||||||
|
import com.bintianqi.owndroid.clickableTextField
|
||||||
import com.bintianqi.owndroid.formatDate
|
import com.bintianqi.owndroid.formatDate
|
||||||
|
import com.bintianqi.owndroid.adaptiveInsets
|
||||||
import com.bintianqi.owndroid.popToast
|
import com.bintianqi.owndroid.popToast
|
||||||
import com.bintianqi.owndroid.showOperationResultToast
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||||
@@ -146,7 +144,7 @@ fun SystemManagerScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
/** 1: reboot, 2: bug report, 3: org name, 4: org id, 5: enrollment specific id*/
|
/** 1: reboot, 2: bug report, 3: org name, 4: org id, 5: enrollment specific id*/
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
MyScaffold(R.string.system, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.system, onNavigateUp, 0.dp) {
|
||||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(SystemOptions) }
|
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.keyguard, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(Keyguard) }
|
||||||
@@ -242,7 +240,7 @@ fun SystemManagerScreen(
|
|||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
if(dialog in 3..5) {
|
if(dialog in 3..5) {
|
||||||
var input by remember { mutableStateOf("") }
|
var input by rememberSaveable { mutableStateOf("") }
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
text = {
|
text = {
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
@@ -323,7 +321,7 @@ data class SystemOptionsStatus(
|
|||||||
@Composable
|
@Composable
|
||||||
fun SystemOptionsScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
fun SystemOptionsScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
val status by vm.systemOptionsStatus.collectAsStateWithLifecycle()
|
val status by vm.systemOptionsStatus.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) { vm.getSystemOptionsStatus() }
|
LaunchedEffect(Unit) { vm.getSystemOptionsStatus() }
|
||||||
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
|
||||||
@@ -436,7 +434,7 @@ fun KeyguardScreen(
|
|||||||
}
|
}
|
||||||
if(VERSION.SDK_INT >= 23) Text(text = stringResource(R.string.lock_now), style = typography.headlineLarge)
|
if(VERSION.SDK_INT >= 23) Text(text = stringResource(R.string.lock_now), style = typography.headlineLarge)
|
||||||
Spacer(Modifier.padding(vertical = 2.dp))
|
Spacer(Modifier.padding(vertical = 2.dp))
|
||||||
var evictKey by remember { mutableStateOf(false) }
|
var evictKey by rememberSaveable { mutableStateOf(false) }
|
||||||
Button(
|
Button(
|
||||||
onClick = { lock(evictKey) },
|
onClick = { lock(evictKey) },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
@@ -475,7 +473,7 @@ fun HardwareMonitorScreen(
|
|||||||
onNavigateUp: () -> Unit
|
onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val properties by hardwareProperties.collectAsStateWithLifecycle()
|
val properties by hardwareProperties.collectAsStateWithLifecycle()
|
||||||
var refreshInterval by remember { mutableFloatStateOf(1F) }
|
var refreshInterval by rememberSaveable { mutableFloatStateOf(1F) }
|
||||||
val refreshIntervalMs = (refreshInterval * 1000).roundToLong()
|
val refreshIntervalMs = (refreshInterval * 1000).roundToLong()
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
getHardwareProperties()
|
getHardwareProperties()
|
||||||
@@ -540,18 +538,14 @@ fun HardwareMonitorScreen(
|
|||||||
fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Unit) {
|
fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Unit) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var tab by remember { mutableIntStateOf(0) }
|
var tab by rememberSaveable { mutableIntStateOf(0) }
|
||||||
val pagerState = rememberPagerState { 2 }
|
val pagerState = rememberPagerState { 2 }
|
||||||
tab = pagerState.currentPage
|
tab = pagerState.currentPage
|
||||||
val coroutine = rememberCoroutineScope()
|
val coroutine = rememberCoroutineScope()
|
||||||
var picker by remember { mutableIntStateOf(0) } //0:None, 1:DatePicker, 2:TimePicker
|
var picker by rememberSaveable { mutableIntStateOf(0) } //0:None, 1:DatePicker, 2:TimePicker
|
||||||
var useCurrentTz by remember { mutableStateOf(true) }
|
var useCurrentTz by rememberSaveable { mutableStateOf(true) }
|
||||||
val datePickerState = rememberDatePickerState()
|
val datePickerState = rememberDatePickerState()
|
||||||
val timePickerState = rememberTimePickerState(is24Hour = true)
|
val timePickerState = rememberTimePickerState(is24Hour = true)
|
||||||
val dateInteractionSource = remember { MutableInteractionSource() }
|
|
||||||
val timeInteractionSource = remember { MutableInteractionSource() }
|
|
||||||
if(dateInteractionSource.collectIsPressedAsState().value) picker = 1
|
|
||||||
if(timeInteractionSource.collectIsPressedAsState().value) picker = 2
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
@@ -560,7 +554,7 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
|||||||
colors = TopAppBarDefaults.topAppBarColors(colorScheme.surfaceContainer)
|
colors = TopAppBarDefaults.topAppBarColors(colorScheme.surfaceContainer)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
@@ -592,17 +586,16 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
|||||||
value = datePickerState.selectedDateMillis?.let { formatDate(it) } ?: "",
|
value = datePickerState.selectedDateMillis?.let { formatDate(it) } ?: "",
|
||||||
onValueChange = {}, readOnly = true,
|
onValueChange = {}, readOnly = true,
|
||||||
label = { Text(stringResource(R.string.date)) },
|
label = { Text(stringResource(R.string.date)) },
|
||||||
interactionSource = dateInteractionSource,
|
modifier = Modifier.fillMaxWidth().clickableTextField { picker = 1 }
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = timePickerState.hour.toString().padStart(2, '0') + ":" +
|
value = timePickerState.hour.toString().padStart(2, '0') + ":" +
|
||||||
timePickerState.minute.toString().padStart(2, '0'),
|
timePickerState.minute.toString().padStart(2, '0'),
|
||||||
onValueChange = {}, readOnly = true,
|
onValueChange = {}, readOnly = true,
|
||||||
label = { Text(stringResource(R.string.time)) },
|
label = { Text(stringResource(R.string.time)) },
|
||||||
interactionSource = timeInteractionSource,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
.clickableTextField { picker = 2 }
|
||||||
.padding(vertical = 4.dp)
|
.padding(vertical = 4.dp)
|
||||||
)
|
)
|
||||||
CheckBoxItem(R.string.use_current_timezone, useCurrentTz) {
|
CheckBoxItem(R.string.use_current_timezone, useCurrentTz) {
|
||||||
@@ -620,13 +613,12 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
|||||||
Text(stringResource(R.string.apply))
|
Text(stringResource(R.string.apply))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var inputTime by remember { mutableStateOf("") }
|
var inputTime by rememberSaveable { mutableStateOf("") }
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = inputTime,
|
value = inputTime,
|
||||||
label = { Text(stringResource(R.string.time_unit_ms)) },
|
label = { Text(stringResource(R.string.time_unit_ms)) },
|
||||||
onValueChange = { inputTime = it },
|
onValueChange = { inputTime = it },
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||||
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Button(
|
Button(
|
||||||
@@ -673,8 +665,8 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
|||||||
fun ChangeTimeZoneScreen(setTimeZone: (String) -> Boolean, onNavigateUp: () -> Unit) {
|
fun ChangeTimeZoneScreen(setTimeZone: (String) -> Boolean, onNavigateUp: () -> Unit) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var inputTimezone by remember { mutableStateOf("") }
|
var inputTimezone by rememberSaveable { mutableStateOf("") }
|
||||||
var dialog by remember { mutableStateOf(false) }
|
var dialog by rememberSaveable { mutableStateOf(false) }
|
||||||
val availableIds = TimeZone.getAvailableIDs()
|
val availableIds = TimeZone.getAvailableIDs()
|
||||||
val validInput = inputTimezone in availableIds
|
val validInput = inputTimezone in availableIds
|
||||||
MyScaffold(R.string.change_timezone, onNavigateUp) {
|
MyScaffold(R.string.change_timezone, onNavigateUp) {
|
||||||
@@ -741,7 +733,7 @@ fun AutoTimePolicyScreen(
|
|||||||
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
||||||
) = MyScaffold(R.string.auto_time_policy, onNavigateUp, 0.dp) {
|
) = MyScaffold(R.string.auto_time_policy, onNavigateUp, 0.dp) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var policy by remember { mutableIntStateOf(getPolicy()) }
|
var policy by rememberSaveable { mutableIntStateOf(getPolicy()) }
|
||||||
listOf(
|
listOf(
|
||||||
DevicePolicyManager.AUTO_TIME_ENABLED to R.string.enable,
|
DevicePolicyManager.AUTO_TIME_ENABLED to R.string.enable,
|
||||||
DevicePolicyManager.AUTO_TIME_DISABLED to R.string.disabled,
|
DevicePolicyManager.AUTO_TIME_DISABLED to R.string.disabled,
|
||||||
@@ -772,7 +764,7 @@ fun AutoTimeZonePolicyScreen(
|
|||||||
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
||||||
) = MyScaffold(R.string.auto_timezone_policy, onNavigateUp, 0.dp) {
|
) = MyScaffold(R.string.auto_timezone_policy, onNavigateUp, 0.dp) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var policy by remember { mutableIntStateOf(getPolicy()) }
|
var policy by rememberSaveable { mutableIntStateOf(getPolicy()) }
|
||||||
listOf(
|
listOf(
|
||||||
DevicePolicyManager.AUTO_TIME_ZONE_ENABLED to R.string.enable,
|
DevicePolicyManager.AUTO_TIME_ZONE_ENABLED to R.string.enable,
|
||||||
DevicePolicyManager.AUTO_TIME_ZONE_DISABLED to R.string.disabled,
|
DevicePolicyManager.AUTO_TIME_ZONE_DISABLED to R.string.disabled,
|
||||||
@@ -980,7 +972,7 @@ fun ContentProtectionPolicyScreen(
|
|||||||
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var policy by remember { mutableIntStateOf(getPolicy()) }
|
var policy by rememberSaveable { mutableIntStateOf(getPolicy()) }
|
||||||
MyScaffold(R.string.content_protection_policy, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.content_protection_policy, onNavigateUp, 0.dp) {
|
||||||
mapOf(
|
mapOf(
|
||||||
DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY to R.string.not_controlled_by_policy,
|
DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY to R.string.not_controlled_by_policy,
|
||||||
@@ -1012,7 +1004,7 @@ fun PermissionPolicyScreen(
|
|||||||
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
getPolicy: () -> Int, setPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var selectedPolicy by remember { mutableIntStateOf(getPolicy()) }
|
var selectedPolicy by rememberSaveable { mutableIntStateOf(getPolicy()) }
|
||||||
MyScaffold(R.string.permission_policy, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.permission_policy, onNavigateUp, 0.dp) {
|
||||||
FullWidthRadioButtonItem(R.string.default_stringres, selectedPolicy == PERMISSION_POLICY_PROMPT) {
|
FullWidthRadioButtonItem(R.string.default_stringres, selectedPolicy == PERMISSION_POLICY_PROMPT) {
|
||||||
selectedPolicy = PERMISSION_POLICY_PROMPT
|
selectedPolicy = PERMISSION_POLICY_PROMPT
|
||||||
@@ -1045,7 +1037,7 @@ fun PermissionPolicyScreen(
|
|||||||
fun MtePolicyScreen(
|
fun MtePolicyScreen(
|
||||||
getPolicy: () -> Int, setPolicy: (Int) -> Boolean, onNavigateUp: () -> Unit
|
getPolicy: () -> Int, setPolicy: (Int) -> Boolean, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
var policy by remember { mutableIntStateOf(getPolicy()) }
|
var policy by rememberSaveable { mutableIntStateOf(getPolicy()) }
|
||||||
MyScaffold(R.string.mte_policy, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.mte_policy, onNavigateUp, 0.dp) {
|
||||||
FullWidthRadioButtonItem(R.string.decide_by_user, policy == MTE_NOT_CONTROLLED_BY_POLICY) {
|
FullWidthRadioButtonItem(R.string.decide_by_user, policy == MTE_NOT_CONTROLLED_BY_POLICY) {
|
||||||
policy = MTE_NOT_CONTROLLED_BY_POLICY
|
policy = MTE_NOT_CONTROLLED_BY_POLICY
|
||||||
@@ -1075,7 +1067,7 @@ fun NearbyStreamingPolicyScreen(
|
|||||||
setNotificationPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
setNotificationPolicy: (Int) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var appPolicy by remember { mutableIntStateOf(getAppPolicy()) }
|
var appPolicy by rememberSaveable { mutableIntStateOf(getAppPolicy()) }
|
||||||
MySmallTitleScaffold(R.string.nearby_streaming_policy, onNavigateUp, 0.dp) {
|
MySmallTitleScaffold(R.string.nearby_streaming_policy, onNavigateUp, 0.dp) {
|
||||||
Text(
|
Text(
|
||||||
stringResource(R.string.nearby_app_streaming),
|
stringResource(R.string.nearby_app_streaming),
|
||||||
@@ -1104,7 +1096,7 @@ fun NearbyStreamingPolicyScreen(
|
|||||||
}
|
}
|
||||||
Notes(R.string.info_nearby_app_streaming_policy, HorizontalPadding)
|
Notes(R.string.info_nearby_app_streaming_policy, HorizontalPadding)
|
||||||
Spacer(Modifier.height(20.dp))
|
Spacer(Modifier.height(20.dp))
|
||||||
var notificationPolicy by remember { mutableIntStateOf(getNotificationPolicy()) }
|
var notificationPolicy by rememberSaveable { mutableIntStateOf(getNotificationPolicy()) }
|
||||||
Text(
|
Text(
|
||||||
stringResource(R.string.nearby_notification_streaming),
|
stringResource(R.string.nearby_notification_streaming),
|
||||||
Modifier.padding(start = 8.dp, top = 10.dp, bottom = 4.dp), style = typography.titleLarge
|
Modifier.padding(start = 8.dp, top = 10.dp, bottom = 4.dp), style = typography.titleLarge
|
||||||
@@ -1153,7 +1145,7 @@ fun LockTaskModeScreen(
|
|||||||
) {
|
) {
|
||||||
val coroutine = rememberCoroutineScope()
|
val coroutine = rememberCoroutineScope()
|
||||||
val pagerState = rememberPagerState { 3 }
|
val pagerState = rememberPagerState { 3 }
|
||||||
var tabIndex by remember { mutableIntStateOf(0) }
|
var tabIndex by rememberSaveable { mutableIntStateOf(0) }
|
||||||
tabIndex = pagerState.targetPage
|
tabIndex = pagerState.targetPage
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
getLockTaskPackages()
|
getLockTaskPackages()
|
||||||
@@ -1166,7 +1158,7 @@ fun LockTaskModeScreen(
|
|||||||
colors = TopAppBarDefaults.topAppBarColors(colorScheme.surfaceContainer)
|
colors = TopAppBarDefaults.topAppBarColors(colorScheme.surfaceContainer)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -1301,8 +1293,8 @@ private fun LockTaskFeatures(
|
|||||||
getLockTaskFeatures: () -> Int, setLockTaskFeature: (Int) -> String?
|
getLockTaskFeatures: () -> Int, setLockTaskFeature: (Int) -> String?
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var flags by remember { mutableIntStateOf(getLockTaskFeatures()) }
|
var flags by rememberSaveable { mutableIntStateOf(getLockTaskFeatures()) }
|
||||||
var errorMessage by remember { mutableStateOf<String?>(null) }
|
var errorMessage by rememberSaveable { mutableStateOf<String?>(null) }
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -1366,9 +1358,9 @@ fun CaCertScreen(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
/** 0:none, 1:install, 2:info, 3:uninstall all */
|
/** 0:none, 1:install, 2:info, 3:uninstall all */
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
val caCerts by caCertificates.collectAsStateWithLifecycle()
|
val caCerts by caCertificates.collectAsStateWithLifecycle()
|
||||||
var selectedCaCert by remember { mutableStateOf<CaCertInfo?>(null) }
|
var selectedCaCert by rememberSaveable { mutableStateOf<CaCertInfo?>(null) }
|
||||||
val getCertLauncher = rememberLauncherForActivityResult(
|
val getCertLauncher = rememberLauncherForActivityResult(
|
||||||
ActivityResultContracts.OpenDocument()) { uri ->
|
ActivityResultContracts.OpenDocument()) { uri ->
|
||||||
if(uri != null) {
|
if(uri != null) {
|
||||||
@@ -1400,7 +1392,8 @@ fun CaCertScreen(
|
|||||||
}) {
|
}) {
|
||||||
Icon(Icons.Default.Add, stringResource(R.string.install))
|
Icon(Icons.Default.Add, stringResource(R.string.install))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
Modifier
|
Modifier
|
||||||
@@ -1534,14 +1527,10 @@ fun SecurityLoggingScreen(
|
|||||||
exportPRLogs: (Uri, () -> Unit) -> Unit, onNavigateUp: () -> Unit
|
exportPRLogs: (Uri, () -> Unit) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var enabled by remember { mutableStateOf(false) }
|
var enabled by rememberSaveable { mutableStateOf(getEnabled()) }
|
||||||
var logsCount by remember { mutableIntStateOf(0) }
|
var logsCount by rememberSaveable { mutableIntStateOf(getCount()) }
|
||||||
var exporting by remember { mutableStateOf(false) }
|
var exporting by rememberSaveable { mutableStateOf(false) }
|
||||||
var dialog by remember { mutableStateOf(false) }
|
var dialog by rememberSaveable { mutableStateOf(false) }
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
enabled = getEnabled()
|
|
||||||
logsCount = getCount()
|
|
||||||
}
|
|
||||||
val exportLauncher = rememberLauncherForActivityResult(
|
val exportLauncher = rememberLauncherForActivityResult(
|
||||||
ActivityResultContracts.CreateDocument("application/json")
|
ActivityResultContracts.CreateDocument("application/json")
|
||||||
) {
|
) {
|
||||||
@@ -1686,24 +1675,16 @@ data class FrpPolicyInfo(
|
|||||||
@RequiresApi(30)
|
@RequiresApi(30)
|
||||||
@Composable
|
@Composable
|
||||||
fun FrpPolicyScreen(
|
fun FrpPolicyScreen(
|
||||||
getFrpPolicy: () -> FrpPolicyInfo, setFrpPolicy: (FrpPolicyInfo) -> Unit,
|
frpPolicy: FrpPolicyInfo, setFrpPolicy: (FrpPolicyInfo) -> Unit,
|
||||||
onNavigateUp: () -> Unit
|
onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var usePolicy by remember { mutableStateOf(false) }
|
var usePolicy by rememberSaveable { mutableStateOf(frpPolicy.usePolicy) }
|
||||||
var enabled by remember { mutableStateOf(false) }
|
var enabled by rememberSaveable { mutableStateOf(frpPolicy.enabled) }
|
||||||
var supported by remember { mutableStateOf(false) }
|
var supported by rememberSaveable { mutableStateOf(frpPolicy.supported) }
|
||||||
val accountList = remember { mutableStateListOf<String>() }
|
val accountList = rememberSaveable { mutableStateListOf(*frpPolicy.accounts.toTypedArray()) }
|
||||||
var inputAccount by remember { mutableStateOf("") }
|
var inputAccount by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
val info = getFrpPolicy()
|
|
||||||
supported = info.supported
|
|
||||||
if (info.supported) {
|
|
||||||
usePolicy = info.usePolicy
|
|
||||||
enabled = info.enabled
|
|
||||||
accountList.addAll(info.accounts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MyScaffold(R.string.frp_policy, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.frp_policy, onNavigateUp, 0.dp) {
|
||||||
if (!supported) {
|
if (!supported) {
|
||||||
Column(
|
Column(
|
||||||
@@ -1751,6 +1732,7 @@ fun FrpPolicyScreen(
|
|||||||
onClick = {
|
onClick = {
|
||||||
focusMgr.clearFocus()
|
focusMgr.clearFocus()
|
||||||
setFrpPolicy(FrpPolicyInfo(true, usePolicy, enabled, accountList))
|
setFrpPolicy(FrpPolicyInfo(true, usePolicy, enabled, accountList))
|
||||||
|
context.showOperationResultToast(true)
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -1774,9 +1756,9 @@ fun WipeDataScreen(
|
|||||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var flag by remember { mutableIntStateOf(WIPE_SILENTLY) }
|
var flag by rememberSaveable { mutableIntStateOf(0) }
|
||||||
var dialog by remember { mutableIntStateOf(0) } // 0: none, 1: wipe data, 2: wipe device
|
var dialog by rememberSaveable { mutableIntStateOf(0) } // 0: none, 1: wipe data, 2: wipe device
|
||||||
var reason by remember { mutableStateOf("") }
|
var reason by rememberSaveable { mutableStateOf("") }
|
||||||
MyScaffold(R.string.wipe_data, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.wipe_data, onNavigateUp, 0.dp) {
|
||||||
FullWidthCheckBoxItem(R.string.wipe_external_storage, flag and WIPE_EXTERNAL_STORAGE != 0) {
|
FullWidthCheckBoxItem(R.string.wipe_external_storage, flag and WIPE_EXTERNAL_STORAGE != 0) {
|
||||||
flag = flag xor WIPE_EXTERNAL_STORAGE
|
flag = flag xor WIPE_EXTERNAL_STORAGE
|
||||||
@@ -1978,8 +1960,8 @@ fun InstallSystemUpdateScreen(
|
|||||||
installSystemUpdate: (Uri, (String) -> Unit) -> Unit, onNavigateUp: () -> Unit
|
installSystemUpdate: (Uri, (String) -> Unit) -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
var uri by remember { mutableStateOf<Uri?>(null) }
|
var uri by remember { mutableStateOf<Uri?>(null) }
|
||||||
var installing by remember { mutableStateOf(false) }
|
var installing by rememberSaveable { mutableStateOf(false) }
|
||||||
var errorMessage by remember { mutableStateOf<String?>(null) }
|
var errorMessage by rememberSaveable { mutableStateOf<String?>(null) }
|
||||||
val getFileLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri = it }
|
val getFileLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri = it }
|
||||||
MyScaffold(R.string.install_system_update, onNavigateUp) {
|
MyScaffold(R.string.install_system_update, onNavigateUp) {
|
||||||
Button(
|
Button(
|
||||||
|
|||||||
@@ -7,11 +7,9 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.ime
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
@@ -41,7 +39,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -53,11 +51,13 @@ import androidx.compose.ui.text.input.ImeAction
|
|||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.bintianqi.owndroid.BottomPadding
|
||||||
import com.bintianqi.owndroid.HorizontalPadding
|
import com.bintianqi.owndroid.HorizontalPadding
|
||||||
import com.bintianqi.owndroid.Privilege
|
import com.bintianqi.owndroid.Privilege
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
import com.bintianqi.owndroid.UserRestrictionCategory
|
import com.bintianqi.owndroid.UserRestrictionCategory
|
||||||
import com.bintianqi.owndroid.UserRestrictionsRepository
|
import com.bintianqi.owndroid.UserRestrictionsRepository
|
||||||
|
import com.bintianqi.owndroid.adaptiveInsets
|
||||||
import com.bintianqi.owndroid.popToast
|
import com.bintianqi.owndroid.popToast
|
||||||
import com.bintianqi.owndroid.showOperationResultToast
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.FunctionItem
|
import com.bintianqi.owndroid.ui.FunctionItem
|
||||||
@@ -99,7 +99,7 @@ fun UserRestrictionScreen(
|
|||||||
scrollBehavior = sb
|
scrollBehavior = sb
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -183,7 +183,7 @@ fun UserRestrictionOptionsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
Spacer(Modifier.padding(vertical = 30.dp))
|
Spacer(Modifier.height(BottomPadding))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ fun UserRestrictionEditorScreen(
|
|||||||
navigationIcon = { NavIcon(onNavigateUp) }
|
navigationIcon = { NavIcon(onNavigateUp) }
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
|
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
|
||||||
items(list, { it }) {
|
items(list, { it }) {
|
||||||
@@ -224,7 +224,7 @@ fun UserRestrictionEditorScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
var input by remember { mutableStateOf("") }
|
var input by rememberSaveable { mutableStateOf("") }
|
||||||
fun add() {
|
fun add() {
|
||||||
if (!setRestriction(input, false)) context.showOperationResultToast(false)
|
if (!setRestriction(input, false)) context.showOperationResultToast(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
@@ -81,7 +82,7 @@ fun UsersScreen(vm: MyViewModel, onNavigateUp: () -> Unit, onNavigate: (Any) ->
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||||
/** 1: secondary users, 2: logout*/
|
/** 1: secondary users, 2: logout*/
|
||||||
var dialog by remember { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
MyScaffold(R.string.users, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.users, onNavigateUp, 0.dp) {
|
||||||
if(VERSION.SDK_INT >= 28 && privilege.profile && privilege.affiliated) {
|
if(VERSION.SDK_INT >= 28 && privilege.profile && privilege.affiliated) {
|
||||||
FunctionItem(R.string.logout, icon = R.drawable.logout_fill0) { dialog = 2 }
|
FunctionItem(R.string.logout, icon = R.drawable.logout_fill0) { dialog = 2 }
|
||||||
@@ -194,7 +195,7 @@ data class UserInformation(
|
|||||||
@Composable
|
@Composable
|
||||||
fun UserInfoScreen(getInfo: () -> UserInformation, onNavigateUp: () -> Unit) {
|
fun UserInfoScreen(getInfo: () -> UserInformation, onNavigateUp: () -> Unit) {
|
||||||
var info by remember { mutableStateOf(UserInformation()) }
|
var info by remember { mutableStateOf(UserInformation()) }
|
||||||
var infoDialog by remember { mutableIntStateOf(0) }
|
var infoDialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
info = getInfo()
|
info = getInfo()
|
||||||
}
|
}
|
||||||
@@ -234,10 +235,10 @@ fun UserOperationScreen(
|
|||||||
stopUser: (Int, Boolean) -> Int, deleteUser: (Int, Boolean) -> Boolean, onNavigateUp: () -> Unit
|
stopUser: (Int, Boolean) -> Int, deleteUser: (Int, Boolean) -> Boolean, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var input by remember { mutableStateOf("") }
|
var input by rememberSaveable { mutableStateOf("") }
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var useUserId by remember { mutableStateOf(false) }
|
var useUserId by rememberSaveable { mutableStateOf(false) }
|
||||||
var dialog by remember { mutableStateOf(false) }
|
var dialog by rememberSaveable { mutableStateOf(false) }
|
||||||
val legalInput = input.toIntOrNull() != null
|
val legalInput = input.toIntOrNull() != null
|
||||||
MyScaffold(R.string.user_operation, onNavigateUp) {
|
MyScaffold(R.string.user_operation, onNavigateUp) {
|
||||||
if(VERSION.SDK_INT >= 24) SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) {
|
if(VERSION.SDK_INT >= 24) SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) {
|
||||||
@@ -335,9 +336,9 @@ fun CreateUserScreen(
|
|||||||
) {
|
) {
|
||||||
var result by remember { mutableStateOf<CreateUserResult?>(null) }
|
var result by remember { mutableStateOf<CreateUserResult?>(null) }
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var userName by remember { mutableStateOf("") }
|
var userName by rememberSaveable { mutableStateOf("") }
|
||||||
var creating by remember { mutableStateOf(false) }
|
var creating by rememberSaveable { mutableStateOf(false) }
|
||||||
var flags by remember { mutableIntStateOf(0) }
|
var flags by rememberSaveable { mutableIntStateOf(0) }
|
||||||
MyScaffold(R.string.create_user, onNavigateUp, 0.dp) {
|
MyScaffold(R.string.create_user, onNavigateUp, 0.dp) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
userName, { userName= it }, Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding),
|
userName, { userName= it }, Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding),
|
||||||
@@ -401,7 +402,7 @@ fun AffiliationIdScreen(
|
|||||||
onNavigateUp: () -> Unit
|
onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var input by remember { mutableStateOf("") }
|
var input by rememberSaveable { mutableStateOf("") }
|
||||||
val list by affiliationIds.collectAsStateWithLifecycle()
|
val list by affiliationIds.collectAsStateWithLifecycle()
|
||||||
LaunchedEffect(Unit) { getIds() }
|
LaunchedEffect(Unit) { getIds() }
|
||||||
MyScaffold(R.string.affiliation_id, onNavigateUp) {
|
MyScaffold(R.string.affiliation_id, onNavigateUp) {
|
||||||
@@ -440,7 +441,7 @@ fun AffiliationIdScreen(
|
|||||||
fun ChangeUsernameScreen(setName: (String) -> Unit, onNavigateUp: () -> Unit) {
|
fun ChangeUsernameScreen(setName: (String) -> Unit, onNavigateUp: () -> Unit) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var inputUsername by remember { mutableStateOf("") }
|
var inputUsername by rememberSaveable { mutableStateOf("") }
|
||||||
MyScaffold(R.string.change_username, onNavigateUp) {
|
MyScaffold(R.string.change_username, onNavigateUp) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = inputUsername,
|
value = inputUsername,
|
||||||
@@ -473,8 +474,8 @@ fun UserSessionMessageScreen(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var start by remember { mutableStateOf("") }
|
var start by rememberSaveable { mutableStateOf("") }
|
||||||
var end by remember { mutableStateOf("") }
|
var end by rememberSaveable { mutableStateOf("") }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
val messages = getMessages()
|
val messages = getMessages()
|
||||||
start = messages.first
|
start = messages.first
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import androidx.compose.material3.Checkbox
|
|||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
|
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
import androidx.compose.material3.MaterialTheme.typography
|
import androidx.compose.material3.MaterialTheme.typography
|
||||||
import androidx.compose.material3.MenuAnchorType
|
import androidx.compose.material3.MenuAnchorType
|
||||||
@@ -55,7 +56,6 @@ import com.bintianqi.owndroid.R
|
|||||||
import com.bintianqi.owndroid.showOperationResultToast
|
import com.bintianqi.owndroid.showOperationResultToast
|
||||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||||
import com.bintianqi.owndroid.ui.CircularProgressDialog
|
import com.bintianqi.owndroid.ui.CircularProgressDialog
|
||||||
import com.bintianqi.owndroid.ui.ExpandExposedTextFieldIcon
|
|
||||||
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
|
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
|
||||||
import com.bintianqi.owndroid.ui.FunctionItem
|
import com.bintianqi.owndroid.ui.FunctionItem
|
||||||
import com.bintianqi.owndroid.ui.MyScaffold
|
import com.bintianqi.owndroid.ui.MyScaffold
|
||||||
@@ -301,7 +301,7 @@ fun CrossProfileIntentFilterScreen(
|
|||||||
stringResource(direction.text), {},
|
stringResource(direction.text), {},
|
||||||
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable).fillMaxWidth(),
|
||||||
label = { Text(stringResource(R.string.direction)) }, readOnly = true,
|
label = { Text(stringResource(R.string.direction)) }, readOnly = true,
|
||||||
trailingIcon = { ExpandExposedTextFieldIcon(dropdown) }
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(dropdown) }
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(dropdown, { dropdown = false }) {
|
ExposedDropdownMenu(dropdown, { dropdown = false }) {
|
||||||
IntentFilterDirection.entries.forEach {
|
IntentFilterDirection.entries.forEach {
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -102,7 +101,7 @@ fun AppInstaller(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
var tab by remember { mutableIntStateOf(0) }
|
var tab by rememberSaveable { mutableIntStateOf(0) }
|
||||||
val pagerState = rememberPagerState { 2 }
|
val pagerState = rememberPagerState { 2 }
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
tab = pagerState.targetPage
|
tab = pagerState.targetPage
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.bintianqi.owndroid.ui
|
|||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@@ -10,10 +9,8 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.ime
|
|
||||||
import androidx.compose.foundation.layout.offset
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
@@ -23,7 +20,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
|
||||||
import androidx.compose.material.icons.outlined.Info
|
import androidx.compose.material.icons.outlined.Info
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
@@ -51,7 +47,6 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.rotate
|
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -60,6 +55,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import com.bintianqi.owndroid.HorizontalPadding
|
import com.bintianqi.owndroid.HorizontalPadding
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
|
import com.bintianqi.owndroid.adaptiveInsets
|
||||||
import com.bintianqi.owndroid.zhCN
|
import com.bintianqi.owndroid.zhCN
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -313,7 +309,7 @@ fun MyScaffold(
|
|||||||
scrollBehavior = sb
|
scrollBehavior = sb
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -345,7 +341,7 @@ fun MyLazyScaffold(
|
|||||||
scrollBehavior = sb
|
scrollBehavior = sb
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
LazyColumn(Modifier.fillMaxSize().padding(paddingValues), content = content)
|
LazyColumn(Modifier.fillMaxSize().padding(paddingValues), content = content)
|
||||||
}
|
}
|
||||||
@@ -367,7 +363,7 @@ fun MySmallTitleScaffold(
|
|||||||
colors = TopAppBarDefaults.topAppBarColors(colorScheme.surfaceContainer)
|
colors = TopAppBarDefaults.topAppBarColors(colorScheme.surfaceContainer)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.ime
|
contentWindowInsets = adaptiveInsets()
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -382,15 +378,6 @@ fun MySmallTitleScaffold(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ExpandExposedTextFieldIcon(active: Boolean) {
|
|
||||||
val degrees by animateFloatAsState(if(active) 180F else 0F)
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.ArrowDropDown, contentDescription = null,
|
|
||||||
modifier = Modifier.rotate(degrees)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ErrorDialog(message: String?, onDismiss: () -> Unit) {
|
fun ErrorDialog(message: String?, onDismiss: () -> Unit) {
|
||||||
if(!message.isNullOrEmpty()) AlertDialog(
|
if(!message.isNullOrEmpty()) AlertDialog(
|
||||||
|
|||||||
Reference in New Issue
Block a user