mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
@@ -384,7 +384,7 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
|||||||
vm:: getLockTaskFeatures, vm::setLockTaskFeatures, ::navigateUp)
|
vm:: getLockTaskFeatures, vm::setLockTaskFeatures, ::navigateUp)
|
||||||
}
|
}
|
||||||
composable<CaCert> {
|
composable<CaCert> {
|
||||||
CaCertScreen(vm.installedCaCerts, vm::getCaCerts, vm::installCaCert, vm::parseCaCert,
|
CaCertScreen(vm.installedCaCerts, vm::getCaCerts, vm.selectedCaCert, vm::selectCaCert, vm::installCaCert, vm::parseCaCert,
|
||||||
vm::exportCaCert, vm::uninstallCaCert, vm::uninstallAllCaCerts, ::navigateUp)
|
vm::exportCaCert, vm::uninstallCaCert, vm::uninstallAllCaCerts, ::navigateUp)
|
||||||
}
|
}
|
||||||
composable<SecurityLogging> {
|
composable<SecurityLogging> {
|
||||||
|
|||||||
@@ -797,17 +797,20 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val installedCaCerts = MutableStateFlow(emptyList<CaCertInfo>())
|
val installedCaCerts = MutableStateFlow(emptyList<CaCertInfo>())
|
||||||
|
val selectedCaCert = MutableStateFlow<CaCertInfo?>(null)
|
||||||
fun getCaCerts() {
|
fun getCaCerts() {
|
||||||
installedCaCerts.value = DPM.getInstalledCaCerts(DAR).mapNotNull { parseCaCert(it) }
|
installedCaCerts.value = DPM.getInstalledCaCerts(DAR).mapNotNull { parseCaCert(it) }
|
||||||
}
|
}
|
||||||
fun parseCaCert(uri: Uri): CaCertInfo? {
|
fun selectCaCert(cert: CaCertInfo) {
|
||||||
return try {
|
selectedCaCert.value = cert
|
||||||
|
}
|
||||||
|
fun parseCaCert(uri: Uri) {
|
||||||
|
try {
|
||||||
application.contentResolver.openInputStream(uri)?.use {
|
application.contentResolver.openInputStream(uri)?.use {
|
||||||
parseCaCert(it.readBytes())
|
selectedCaCert.value = parseCaCert(it.readBytes())
|
||||||
}
|
}
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun parseCaCert(bytes: ByteArray): CaCertInfo? {
|
fun parseCaCert(bytes: ByteArray): CaCertInfo? {
|
||||||
@@ -825,22 +828,22 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun installCaCert(cert: CaCertInfo): Boolean {
|
fun installCaCert(): Boolean {
|
||||||
val result = DPM.installCaCert(DAR, cert.bytes)
|
val result = DPM.installCaCert(DAR, selectedCaCert.value!!.bytes)
|
||||||
if (result) getCaCerts()
|
if (result) getCaCerts()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
fun uninstallCaCert(cert: CaCertInfo) {
|
fun uninstallCaCert() {
|
||||||
DPM.uninstallCaCert(DAR, cert.bytes)
|
DPM.uninstallCaCert(DAR, selectedCaCert.value!!.bytes)
|
||||||
getCaCerts()
|
getCaCerts()
|
||||||
}
|
}
|
||||||
fun uninstallAllCaCerts() {
|
fun uninstallAllCaCerts() {
|
||||||
DPM.uninstallAllUserCaCerts(DAR)
|
DPM.uninstallAllUserCaCerts(DAR)
|
||||||
getCaCerts()
|
getCaCerts()
|
||||||
}
|
}
|
||||||
fun exportCaCert(uri: Uri, cert: CaCertInfo) {
|
fun exportCaCert(uri: Uri) {
|
||||||
application.contentResolver.openOutputStream(uri)?.use {
|
application.contentResolver.openOutputStream(uri)?.use {
|
||||||
it.write(cert.bytes)
|
it.write(selectedCaCert.value!!.bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val mdAccountTypes = MutableStateFlow(emptyList<String>())
|
val mdAccountTypes = MutableStateFlow(emptyList<String>())
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ fun ResetPasswordTokenScreen(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var token by rememberSaveable { mutableStateOf("") }
|
var token by rememberSaveable { mutableStateOf("") }
|
||||||
var state by rememberSaveable { mutableStateOf(getState()) }
|
var state by remember { mutableStateOf(getState()) }
|
||||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
if (it.resultCode == Activity.RESULT_OK) {
|
if (it.resultCode == Activity.RESULT_OK) {
|
||||||
context.popToast(R.string.token_activated)
|
context.popToast(R.string.token_activated)
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
import androidx.compose.material3.MaterialTheme.typography
|
import androidx.compose.material3.MaterialTheme.typography
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.PrimaryTabRow
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Slider
|
import androidx.compose.material3.Slider
|
||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
@@ -75,6 +76,7 @@ import androidx.compose.material3.TabRow
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TimePicker
|
import androidx.compose.material3.TimePicker
|
||||||
|
import androidx.compose.material3.TimePickerDialog
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.rememberDatePickerState
|
import androidx.compose.material3.rememberDatePickerState
|
||||||
@@ -127,6 +129,7 @@ import com.bintianqi.owndroid.ui.SwitchItem
|
|||||||
import com.bintianqi.owndroid.yesOrNo
|
import com.bintianqi.owndroid.yesOrNo
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -562,7 +565,7 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
) {
|
) {
|
||||||
TabRow(tab) {
|
PrimaryTabRow(tab) {
|
||||||
Tab(
|
Tab(
|
||||||
tab == 0, { coroutine.launch { pagerState.animateScrollToPage(0) } },
|
tab == 0, { coroutine.launch { pagerState.animateScrollToPage(0) } },
|
||||||
text = { Text(stringResource(R.string.selector)) }
|
text = { Text(stringResource(R.string.selector)) }
|
||||||
@@ -579,6 +582,7 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
|||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
.padding(top = 8.dp)
|
.padding(top = 8.dp)
|
||||||
.padding(horizontal = HorizontalPadding)
|
.padding(horizontal = HorizontalPadding)
|
||||||
) {
|
) {
|
||||||
@@ -634,6 +638,7 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
|||||||
Text(stringResource(R.string.apply))
|
Text(stringResource(R.string.apply))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Spacer(Modifier.height(BottomPadding))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -646,17 +651,21 @@ fun ChangeTimeScreen(setTime: (Long, Boolean) -> Boolean, onNavigateUp: () -> Un
|
|||||||
},
|
},
|
||||||
onDismissRequest = { picker = 0; focusMgr.clearFocus() }
|
onDismissRequest = { picker = 0; focusMgr.clearFocus() }
|
||||||
) {
|
) {
|
||||||
|
Column(Modifier.verticalScroll(rememberScrollState())) {
|
||||||
DatePicker(datePickerState)
|
DatePicker(datePickerState)
|
||||||
}
|
}
|
||||||
if(picker == 2) AlertDialog(
|
}
|
||||||
text = { TimePicker(timePickerState) },
|
if (picker == 2) TimePickerDialog(
|
||||||
|
title = {},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(onClick = { picker = 0; focusMgr.clearFocus() } ) {
|
TextButton({ picker = 0 }) {
|
||||||
Text(stringResource(R.string.confirm))
|
Text(stringResource(R.string.confirm))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDismissRequest = { picker = 0; focusMgr.clearFocus() }
|
onDismissRequest = { picker = 0 }
|
||||||
)
|
) {
|
||||||
|
TimePicker(timePickerState)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable object ChangeTimeZone
|
@Serializable object ChangeTimeZone
|
||||||
@@ -1353,25 +1362,26 @@ data class CaCertInfo(
|
|||||||
@Composable
|
@Composable
|
||||||
fun CaCertScreen(
|
fun CaCertScreen(
|
||||||
caCertificates: StateFlow<List<CaCertInfo>>, getCerts: () -> Unit,
|
caCertificates: StateFlow<List<CaCertInfo>>, getCerts: () -> Unit,
|
||||||
installCert: (CaCertInfo) -> Boolean, parseCert: (Uri) -> CaCertInfo?,
|
selectedCaCert: MutableStateFlow<CaCertInfo?>, selectCaCert: (CaCertInfo) -> Unit,
|
||||||
exportCert: (Uri, CaCertInfo) -> Unit, uninstallCert: (CaCertInfo) -> Unit,
|
installCert: () -> Boolean, parseCert: (Uri) -> Unit,
|
||||||
|
exportCert: (Uri) -> Unit, uninstallCert: () -> Unit,
|
||||||
uninstallAllCerts: () -> Unit, onNavigateUp: () -> Unit
|
uninstallAllCerts: () -> Unit, onNavigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
/** 0:none, 1:install, 2:info, 3:uninstall all */
|
/** 0:none, 1:install, 2:info, 3:uninstall all */
|
||||||
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||||
val caCerts by caCertificates.collectAsStateWithLifecycle()
|
val caCerts by caCertificates.collectAsStateWithLifecycle()
|
||||||
var selectedCaCert by rememberSaveable { mutableStateOf<CaCertInfo?>(null) }
|
val selectedCert by selectedCaCert.collectAsStateWithLifecycle()
|
||||||
val getCertLauncher = rememberLauncherForActivityResult(
|
val getCertLauncher = rememberLauncherForActivityResult(
|
||||||
ActivityResultContracts.OpenDocument()) { uri ->
|
ActivityResultContracts.OpenDocument()) { uri ->
|
||||||
if(uri != null) {
|
if (uri != null) {
|
||||||
selectedCaCert = parseCert(uri)
|
parseCert(uri)
|
||||||
dialog = 1
|
dialog = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val exportCertLauncher = rememberLauncherForActivityResult(
|
val exportCertLauncher = rememberLauncherForActivityResult(
|
||||||
ActivityResultContracts.CreateDocument()) { uri ->
|
ActivityResultContracts.CreateDocument()) { uri ->
|
||||||
if(uri != null) exportCert(uri, selectedCaCert!!)
|
if (uri != null) exportCert(uri)
|
||||||
}
|
}
|
||||||
LaunchedEffect(Unit) { getCerts() }
|
LaunchedEffect(Unit) { getCerts() }
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -1407,7 +1417,7 @@ fun CaCertScreen(
|
|||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable {
|
.clickable {
|
||||||
selectedCaCert = cert
|
selectCaCert(cert)
|
||||||
dialog = 2
|
dialog = 2
|
||||||
}
|
}
|
||||||
.animateItem()
|
.animateItem()
|
||||||
@@ -1421,11 +1431,11 @@ fun CaCertScreen(
|
|||||||
Spacer(Modifier.height(BottomPadding))
|
Spacer(Modifier.height(BottomPadding))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selectedCaCert != null && (dialog == 1 || dialog == 2)) {
|
if (selectedCert != null && (dialog == 1 || dialog == 2)) {
|
||||||
val cert = selectedCaCert!!
|
val cert = selectedCert!!
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column(Modifier.verticalScroll(rememberScrollState())) {
|
||||||
Text("Serial number", style = typography.labelLarge)
|
Text("Serial number", style = typography.labelLarge)
|
||||||
SelectionContainer { Text(cert.serialNumber) }
|
SelectionContainer { Text(cert.serialNumber) }
|
||||||
Text("Subject", style = typography.labelLarge)
|
Text("Subject", style = typography.labelLarge)
|
||||||
@@ -1445,7 +1455,7 @@ fun CaCertScreen(
|
|||||||
) {
|
) {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
uninstallCert(cert)
|
uninstallCert()
|
||||||
dialog = 0
|
dialog = 0
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth(0.49F),
|
modifier = Modifier.fillMaxWidth(0.49F),
|
||||||
@@ -1467,7 +1477,7 @@ fun CaCertScreen(
|
|||||||
confirmButton = {
|
confirmButton = {
|
||||||
if (dialog == 1) {
|
if (dialog == 1) {
|
||||||
TextButton({
|
TextButton({
|
||||||
context.showOperationResultToast(installCert(cert))
|
context.showOperationResultToast(installCert())
|
||||||
dialog = 0
|
dialog = 0
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.install))
|
Text(stringResource(R.string.install))
|
||||||
@@ -1489,7 +1499,7 @@ fun CaCertScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDismissRequest = {}
|
onDismissRequest = { dialog = 0 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (dialog == 3) {
|
if (dialog == 3) {
|
||||||
|
|||||||
Reference in New Issue
Block a user