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