mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
allow custom reset password token
use a dialog to confirm password before reset password hide reset password token and reset password by default
This commit is contained in:
@@ -191,7 +191,7 @@ private fun PackageItem(pkg: PkgInfo, navCtrl: NavHostController, pkgName: Mutab
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable{ pkgName.value = pkg.pkgName; navCtrl.navigateUp() }
|
.clickable{ pkgName.value = pkg.pkgName; navCtrl.navigateUp() }
|
||||||
.padding(vertical = 3.dp)
|
.padding(vertical = 6.dp)
|
||||||
) {
|
) {
|
||||||
Spacer(Modifier.padding(start = 15.dp))
|
Spacer(Modifier.padding(start = 15.dp))
|
||||||
Image(
|
Image(
|
||||||
@@ -202,7 +202,6 @@ private fun PackageItem(pkg: PkgInfo, navCtrl: NavHostController, pkgName: Mutab
|
|||||||
Column {
|
Column {
|
||||||
Text(text = pkg.label, style = typography.titleLarge)
|
Text(text = pkg.label, style = typography.titleLarge)
|
||||||
Text(text = pkg.pkgName, modifier = Modifier.alpha(0.8F))
|
Text(text = pkg.pkgName, modifier = Modifier.alpha(0.8F))
|
||||||
Spacer(Modifier.padding(top = 3.dp))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,15 +35,19 @@ import android.os.Build.VERSION
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.ScrollState
|
import androidx.compose.foundation.ScrollState
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
@@ -51,10 +55,12 @@ import androidx.compose.material3.MaterialTheme.typography
|
|||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -65,6 +71,7 @@ import androidx.compose.ui.platform.LocalFocusManager
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.content.ContextCompat.startActivity
|
import androidx.core.content.ContextCompat.startActivity
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
@@ -73,6 +80,7 @@ import androidx.navigation.compose.composable
|
|||||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
|
import com.bintianqi.owndroid.toggle
|
||||||
import com.bintianqi.owndroid.ui.Animations
|
import com.bintianqi.owndroid.ui.Animations
|
||||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||||
import com.bintianqi.owndroid.ui.Information
|
import com.bintianqi.owndroid.ui.Information
|
||||||
@@ -124,18 +132,21 @@ fun Password(navCtrl: NavHostController) {
|
|||||||
@Composable
|
@Composable
|
||||||
private fun Home(navCtrl:NavHostController,scrollState: ScrollState) {
|
private fun Home(navCtrl:NavHostController,scrollState: ScrollState) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val sharedPrefs = context.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
Column(modifier = Modifier.fillMaxSize().verticalScroll(scrollState).padding(start = 30.dp, end = 12.dp)) {
|
Column(modifier = Modifier.fillMaxSize().verticalScroll(scrollState).padding(start = 30.dp, end = 12.dp)) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.password_and_keyguard),
|
text = stringResource(R.string.password_and_keyguard),
|
||||||
style = typography.headlineLarge,
|
style = typography.headlineLarge,
|
||||||
modifier = Modifier.padding(top = 8.dp, bottom = 5.dp)
|
modifier = Modifier.padding(top = 8.dp, bottom = 5.dp).offset(x = (-8).dp)
|
||||||
)
|
)
|
||||||
SubPageItem(R.string.password_info, "", R.drawable.info_fill0) { navCtrl.navigate("PasswordInfo") }
|
SubPageItem(R.string.password_info, "", R.drawable.info_fill0) { navCtrl.navigate("PasswordInfo") }
|
||||||
if(VERSION.SDK_INT >= 26 && (context.isDeviceOwner || context.isProfileOwner)) {
|
if(sharedPrefs.getBoolean("dangerous_features", false)) {
|
||||||
SubPageItem(R.string.reset_password_token, "", R.drawable.key_vertical_fill0) { navCtrl.navigate("ResetPasswordToken") }
|
if(VERSION.SDK_INT >= 26 && (context.isDeviceOwner || context.isProfileOwner)) {
|
||||||
}
|
SubPageItem(R.string.reset_password_token, "", R.drawable.key_vertical_fill0) { navCtrl.navigate("ResetPasswordToken") }
|
||||||
if(context.isDeviceAdmin || context.isDeviceOwner || context.isProfileOwner) {
|
}
|
||||||
SubPageItem(R.string.reset_password, "", R.drawable.lock_reset_fill0) { navCtrl.navigate("ResetPassword") }
|
if(context.isDeviceAdmin || context.isDeviceOwner || context.isProfileOwner) {
|
||||||
|
SubPageItem(R.string.reset_password, "", R.drawable.lock_reset_fill0) { navCtrl.navigate("ResetPassword") }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(VERSION.SDK_INT >= 31 && (context.isDeviceOwner || context.isProfileOwner)) {
|
if(VERSION.SDK_INT >= 31 && (context.isDeviceOwner || context.isProfileOwner)) {
|
||||||
SubPageItem(R.string.required_password_complexity, "", R.drawable.password_fill0) { navCtrl.navigate("RequirePasswordComplexity") }
|
SubPageItem(R.string.required_password_complexity, "", R.drawable.password_fill0) { navCtrl.navigate("RequirePasswordComplexity") }
|
||||||
@@ -200,23 +211,25 @@ private fun ResetPasswordToken() {
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val dpm = context.getDPM()
|
val dpm = context.getDPM()
|
||||||
val receiver = context.getReceiver()
|
val receiver = context.getReceiver()
|
||||||
val tokenByteArray by remember { mutableStateOf(byteArrayOf(1,1,4,5,1,4,1,9,1,9,8,1,0,1,1,4,5,1,4,1,9,1,9,8,1,0,1,1,4,5,1,4,1,9,1,9,8,1,0)) }
|
var token by remember { mutableStateOf("") }
|
||||||
|
val tokenByteArray = token.toByteArray()
|
||||||
|
val focusMgr = LocalFocusManager.current
|
||||||
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) {
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) {
|
||||||
Spacer(Modifier.padding(vertical = 10.dp))
|
Spacer(Modifier.padding(vertical = 10.dp))
|
||||||
Text(text = stringResource(R.string.reset_password_token), style = typography.headlineLarge)
|
Text(text = stringResource(R.string.reset_password_token), style = typography.headlineLarge)
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Spacer(Modifier.padding(vertical = 5.dp))
|
||||||
Button(
|
OutlinedTextField(
|
||||||
onClick = {
|
value = token, onValueChange = { token = it },
|
||||||
Toast.makeText(
|
label = { Text(stringResource(R.string.token)) },
|
||||||
context,
|
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
||||||
if(dpm.clearResetPasswordToken(receiver)) R.string.success else R.string.failed,
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||||
Toast.LENGTH_SHORT
|
supportingText = {
|
||||||
).show()
|
AnimatedVisibility(tokenByteArray.size < 32) {
|
||||||
|
Text(stringResource(R.string.token_must_longer_than_32_byte))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
)
|
||||||
Text(stringResource(R.string.clear))
|
|
||||||
}
|
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
try {
|
try {
|
||||||
@@ -229,20 +242,38 @@ private fun ResetPasswordToken() {
|
|||||||
Toast.makeText(context, R.string.security_exception, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.security_exception, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp),
|
||||||
|
enabled = tokenByteArray.size >= 32
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.set))
|
Text(stringResource(R.string.set))
|
||||||
}
|
}
|
||||||
Button(
|
Row(
|
||||||
onClick = {
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
if(!dpm.isResetPasswordTokenActive(receiver)) {
|
|
||||||
try { activateToken(context) }
|
|
||||||
catch(e:NullPointerException) { Toast.makeText(context, R.string.please_set_a_token, Toast.LENGTH_SHORT).show() }
|
|
||||||
} else { Toast.makeText(context, R.string.token_already_activated, Toast.LENGTH_SHORT).show() }
|
|
||||||
},
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.activate))
|
Button(
|
||||||
|
onClick = {
|
||||||
|
if(!dpm.isResetPasswordTokenActive(receiver)) {
|
||||||
|
try { activateToken(context) }
|
||||||
|
catch(e:NullPointerException) { Toast.makeText(context, R.string.please_set_a_token, Toast.LENGTH_SHORT).show() }
|
||||||
|
} else { Toast.makeText(context, R.string.token_already_activated, Toast.LENGTH_SHORT).show() }
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(0.49F)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.activate))
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
if(dpm.clearResetPasswordToken(receiver)) R.string.success else R.string.failed,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(0.96F)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.clear))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Spacer(Modifier.padding(vertical = 5.dp))
|
||||||
Information{ Text(stringResource(R.string.activate_token_not_required_when_no_password)) }
|
Information{ Text(stringResource(R.string.activate_token_not_required_when_no_password)) }
|
||||||
@@ -255,84 +286,123 @@ private fun ResetPassword() {
|
|||||||
val dpm = context.getDPM()
|
val dpm = context.getDPM()
|
||||||
val receiver = context.getReceiver()
|
val receiver = context.getReceiver()
|
||||||
val focusMgr = LocalFocusManager.current
|
val focusMgr = LocalFocusManager.current
|
||||||
var newPwd by remember { mutableStateOf("") }
|
var password by remember { mutableStateOf("") }
|
||||||
val tokenByteArray by remember { mutableStateOf(byteArrayOf(1,1,4,5,1,4,1,9,1,9,8,1,0,1,1,4,5,1,4,1,9,1,9,8,1,0,1,1,4,5,1,4,1,9,1,9,8,1,0)) }
|
var useToken by remember { mutableStateOf(false) }
|
||||||
var confirmed by remember { mutableStateOf(false) }
|
var token by remember { mutableStateOf("") }
|
||||||
var resetPwdFlag by remember { mutableIntStateOf(0) }
|
val tokenByteArray = token.toByteArray()
|
||||||
|
var flags = remember { mutableStateListOf<Int>() }
|
||||||
|
var confirmDialog by remember { mutableStateOf(false) }
|
||||||
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) {
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())) {
|
||||||
Spacer(Modifier.padding(vertical = 10.dp))
|
Spacer(Modifier.padding(vertical = 10.dp))
|
||||||
Text(text = stringResource(R.string.reset_password),style = typography.headlineLarge)
|
Text(text = stringResource(R.string.reset_password),style = typography.headlineLarge)
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Spacer(Modifier.padding(vertical = 5.dp))
|
||||||
|
if(VERSION.SDK_INT >= 26) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = token, onValueChange = { token = it },
|
||||||
|
label = { Text(stringResource(R.string.token)) },
|
||||||
|
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = newPwd,
|
value = password,
|
||||||
onValueChange = { newPwd=it },
|
onValueChange = { password = it },
|
||||||
enabled = !confirmed,
|
|
||||||
label = { Text(stringResource(R.string.password)) },
|
label = { Text(stringResource(R.string.password)) },
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Done),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Done),
|
||||||
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
||||||
|
supportingText = { Text(stringResource(R.string.reset_pwd_desc)) },
|
||||||
|
visualTransformation = PasswordVisualTransformation(),
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Spacer(Modifier.padding(vertical = 3.dp))
|
|
||||||
Text(text = stringResource(R.string.reset_pwd_desc))
|
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Spacer(Modifier.padding(vertical = 5.dp))
|
||||||
if(VERSION.SDK_INT >= 23) {
|
if(VERSION.SDK_INT >= 23) {
|
||||||
RadioButtonItem(
|
CheckBoxItem(
|
||||||
R.string.do_not_ask_credentials_on_boot,
|
R.string.do_not_ask_credentials_on_boot,
|
||||||
resetPwdFlag == RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT,
|
RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT in flags,
|
||||||
{ resetPwdFlag = RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT }
|
{ flags.toggle(it, RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
RadioButtonItem(
|
CheckBoxItem(
|
||||||
R.string.reset_password_require_entry,
|
R.string.reset_password_require_entry,
|
||||||
resetPwdFlag == RESET_PASSWORD_REQUIRE_ENTRY,
|
RESET_PASSWORD_REQUIRE_ENTRY in flags,
|
||||||
{ resetPwdFlag = RESET_PASSWORD_REQUIRE_ENTRY }
|
{ flags.toggle(it, RESET_PASSWORD_REQUIRE_ENTRY) }
|
||||||
)
|
)
|
||||||
RadioButtonItem(R.string.none, resetPwdFlag == 0, { resetPwdFlag = 0 })
|
|
||||||
Spacer(Modifier.padding(vertical = 5.dp))
|
Spacer(Modifier.padding(vertical = 5.dp))
|
||||||
Button(
|
|
||||||
onClick = {
|
|
||||||
if(newPwd.length>=4 || newPwd.isEmpty()) { confirmed=!confirmed }
|
|
||||||
else { Toast.makeText(context, R.string.require_4_digit_password, Toast.LENGTH_SHORT).show() }
|
|
||||||
},
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
containerColor = if(confirmed) colorScheme.primary else colorScheme.error,
|
|
||||||
contentColor = if(confirmed) colorScheme.onPrimary else colorScheme.onError
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Text(text = stringResource(if(confirmed) R.string.cancel else R.string.confirm))
|
|
||||||
}
|
|
||||||
Spacer(Modifier.padding(vertical = 3.dp))
|
|
||||||
if(VERSION.SDK_INT >= 26) {
|
if(VERSION.SDK_INT >= 26) {
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
val resetSuccess = dpm.resetPasswordWithToken(receiver,newPwd,tokenByteArray,resetPwdFlag)
|
useToken = true
|
||||||
if(resetSuccess) { Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show(); newPwd=""}
|
confirmDialog = true
|
||||||
else{ Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show() }
|
focusMgr.clearFocus()
|
||||||
confirmed=false
|
|
||||||
},
|
},
|
||||||
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
||||||
enabled = confirmed && (context.isDeviceOwner || context.isProfileOwner),
|
enabled = tokenByteArray.size >=32 && password.length !in 1..3 && (context.isDeviceOwner || context.isProfileOwner),
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.reset_password_with_token))
|
Text(stringResource(R.string.reset_password_with_token))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button(
|
if(VERSION.SDK_INT <= 30) {
|
||||||
onClick = {
|
Button(
|
||||||
val resetSuccess = dpm.resetPassword(newPwd,resetPwdFlag)
|
onClick = {
|
||||||
if(resetSuccess) { Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show(); newPwd="" }
|
useToken = false
|
||||||
else{ Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show() }
|
confirmDialog = true
|
||||||
confirmed=false
|
focusMgr.clearFocus()
|
||||||
},
|
},
|
||||||
enabled = confirmed,
|
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
||||||
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
enabled = password.length !in 1..3,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.reset_password_deprecated))
|
Text(stringResource(R.string.reset_password))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Spacer(Modifier.padding(vertical = 30.dp))
|
Spacer(Modifier.padding(vertical = 30.dp))
|
||||||
}
|
}
|
||||||
|
if(confirmDialog) {
|
||||||
|
var confirmPassword by remember { mutableStateOf("") }
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { confirmDialog = false },
|
||||||
|
title = { Text(stringResource(R.string.reset_password)) },
|
||||||
|
text = {
|
||||||
|
val dialogFocusMgr = LocalFocusManager.current
|
||||||
|
OutlinedTextField(
|
||||||
|
value = confirmPassword,
|
||||||
|
onValueChange = { confirmPassword = it },
|
||||||
|
label = { Text(stringResource(R.string.confirm_password)) },
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Done),
|
||||||
|
keyboardActions = KeyboardActions(onDone = { dialogFocusMgr.clearFocus() }),
|
||||||
|
visualTransformation = PasswordVisualTransformation(),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
var resetFlag = 0
|
||||||
|
flags.forEach { resetFlag += it }
|
||||||
|
val success = if(VERSION.SDK_INT >= 26 && useToken) {
|
||||||
|
dpm.resetPasswordWithToken(receiver, password, tokenByteArray, resetFlag)
|
||||||
|
} else {
|
||||||
|
dpm.resetPassword(password, resetFlag)
|
||||||
|
}
|
||||||
|
Toast.makeText(context, if(success) R.string.success else R.string.failed, Toast.LENGTH_SHORT).show()
|
||||||
|
password = ""
|
||||||
|
confirmDialog = false
|
||||||
|
},
|
||||||
|
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error),
|
||||||
|
enabled = confirmPassword == password
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.confirm))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = { confirmDialog = false }) {
|
||||||
|
Text(stringResource(R.string.cancel))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
@@ -110,7 +111,7 @@ private fun Home(navCtrl: NavHostController,scrollState: ScrollState) {
|
|||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.user_manager),
|
text = stringResource(R.string.user_manager),
|
||||||
style = typography.headlineLarge,
|
style = typography.headlineLarge,
|
||||||
modifier = Modifier.padding(top = 8.dp, bottom = 5.dp)
|
modifier = Modifier.padding(top = 8.dp, bottom = 5.dp).offset(x = (-8).dp)
|
||||||
)
|
)
|
||||||
SubPageItem(R.string.user_info, "", R.drawable.person_fill0) { navCtrl.navigate("UserInfo") }
|
SubPageItem(R.string.user_info, "", R.drawable.person_fill0) { navCtrl.navigate("UserInfo") }
|
||||||
if(context.isDeviceOwner) {
|
if(context.isDeviceOwner) {
|
||||||
|
|||||||
@@ -501,17 +501,19 @@
|
|||||||
<string name="password_failed_attempts_is">Başarısız şifre denemeleri: %1$s</string>
|
<string name="password_failed_attempts_is">Başarısız şifre denemeleri: %1$s</string>
|
||||||
<string name="is_using_unified_password">Birleşik şifre: %1$s</string>
|
<string name="is_using_unified_password">Birleşik şifre: %1$s</string>
|
||||||
<string name="reset_password_token">Şifre sıfırlama jetonu</string>
|
<string name="reset_password_token">Şifre sıfırlama jetonu</string>
|
||||||
|
<string name="token">Token</string> <!--TODO-->
|
||||||
|
<string name="token_must_longer_than_32_byte">The token must be longer than 32-byte</string> <!--TODO-->
|
||||||
<string name="token_already_activated">Jeton zaten etkinleştirildi</string>
|
<string name="token_already_activated">Jeton zaten etkinleştirildi</string>
|
||||||
<string name="clear">Temizle</string>
|
<string name="clear">Temizle</string>
|
||||||
<string name="set">Ayarla</string>
|
<string name="set">Ayarla</string>
|
||||||
<string name="please_set_a_token">Lütfen bir jeton ayarlayın</string>
|
<string name="please_set_a_token">Lütfen bir jeton ayarlayın</string>
|
||||||
<string name="activate_token_not_required_when_no_password">Şifre ayarlanmadığında jeton otomatik olarak etkinleştirilecektir.</string>
|
<string name="activate_token_not_required_when_no_password">Şifre ayarlanmadığında jeton otomatik olarak etkinleştirilecektir.</string>
|
||||||
<string name="reset_password">Şifreyi sıfırla</string>
|
<string name="reset_password">Şifreyi sıfırla</string>
|
||||||
|
<string name="confirm_password">Confirm password</string> <!--TODO-->
|
||||||
<string name="do_not_ask_credentials_on_boot">Başlangıçta kimlik bilgilerini sorma</string>
|
<string name="do_not_ask_credentials_on_boot">Başlangıçta kimlik bilgilerini sorma</string>
|
||||||
<string name="reset_password_require_entry">Giriş gerektir</string>
|
<string name="reset_password_require_entry">Giriş gerektir</string>
|
||||||
<string name="require_4_digit_password">En az 4 haneli şifre gerektir</string>
|
<string name="require_4_digit_password">En az 4 haneli şifre gerektir</string>
|
||||||
<string name="reset_password_with_token">Jeton ile şifreyi sıfırla</string>
|
<string name="reset_password_with_token">Jeton ile şifreyi sıfırla</string>
|
||||||
<string name="reset_password_deprecated">Şifreyi sıfırla</string>
|
|
||||||
<string name="required_password_complexity">Gereken şifre karmaşıklığı</string>
|
<string name="required_password_complexity">Gereken şifre karmaşıklığı</string>
|
||||||
<string name="require_set_new_password">Yeni şifre ayarlanmasını iste</string>
|
<string name="require_set_new_password">Yeni şifre ayarlanmasını iste</string>
|
||||||
<string name="disable_keyguard_features">Kilit ekranı özellikleri</string>
|
<string name="disable_keyguard_features">Kilit ekranı özellikleri</string>
|
||||||
|
|||||||
@@ -473,7 +473,7 @@
|
|||||||
<!--Password&Keyguard-->
|
<!--Password&Keyguard-->
|
||||||
<string name="password_and_keyguard">密码与锁屏</string>
|
<string name="password_and_keyguard">密码与锁屏</string>
|
||||||
<string name="password_info">密码信息</string>
|
<string name="password_info">密码信息</string>
|
||||||
<string name="reset_pwd_desc">留空可以清除密码,纯数字将使用PIN码</string>
|
<string name="reset_pwd_desc">留空以清除密码</string>
|
||||||
<string name="max_pwd_fail">最大密码错误次数</string>
|
<string name="max_pwd_fail">最大密码错误次数</string>
|
||||||
<string name="max_pwd_fail_desc">达到该限制会恢复出厂设置,0为无限制</string>
|
<string name="max_pwd_fail_desc">达到该限制会恢复出厂设置,0为无限制</string>
|
||||||
<string name="max_pwd_fail_textfield">错误次数</string>
|
<string name="max_pwd_fail_textfield">错误次数</string>
|
||||||
@@ -493,17 +493,19 @@
|
|||||||
<string name="password_failed_attempts_is">密码已错误次数:%1$s</string>
|
<string name="password_failed_attempts_is">密码已错误次数:%1$s</string>
|
||||||
<string name="is_using_unified_password">个人与工作应用密码一致:%1$s</string>
|
<string name="is_using_unified_password">个人与工作应用密码一致:%1$s</string>
|
||||||
<string name="reset_password_token">密码重置令牌</string>
|
<string name="reset_password_token">密码重置令牌</string>
|
||||||
|
<string name="token">令牌</string>
|
||||||
|
<string name="token_must_longer_than_32_byte">令牌必须大于32字节</string>
|
||||||
<string name="token_already_activated">令牌已经激活</string>
|
<string name="token_already_activated">令牌已经激活</string>
|
||||||
<string name="clear">清除</string>
|
<string name="clear">清除</string>
|
||||||
<string name="set">设置</string>
|
<string name="set">设置</string>
|
||||||
<string name="please_set_a_token">请先设置令牌</string>
|
<string name="please_set_a_token">请先设置令牌</string>
|
||||||
<string name="activate_token_not_required_when_no_password">没有密码时会自动激活令牌</string>
|
<string name="activate_token_not_required_when_no_password">没有密码时会自动激活令牌</string>
|
||||||
<string name="reset_password">重置密码</string>
|
<string name="reset_password">重置密码</string>
|
||||||
|
<string name="confirm_password">确认密码</string>
|
||||||
<string name="do_not_ask_credentials_on_boot">启动(boot)时不要求密码</string>
|
<string name="do_not_ask_credentials_on_boot">启动(boot)时不要求密码</string>
|
||||||
<string name="reset_password_require_entry">不允许其他设备管理员重置密码直至用户输入一次密码</string>
|
<string name="reset_password_require_entry">不允许其他设备管理员重置密码直至用户输入一次密码</string>
|
||||||
<string name="require_4_digit_password">需要4位密码</string>
|
<string name="require_4_digit_password">需要4位密码</string>
|
||||||
<string name="reset_password_with_token">使用令牌重置密码</string>
|
<string name="reset_password_with_token">使用令牌重置密码</string>
|
||||||
<string name="reset_password_deprecated">重置密码(弃用)</string>
|
|
||||||
<string name="required_password_complexity">密码复杂度要求</string>
|
<string name="required_password_complexity">密码复杂度要求</string>
|
||||||
<string name="require_set_new_password">要求设置新密码</string>
|
<string name="require_set_new_password">要求设置新密码</string>
|
||||||
<string name="disable_keyguard_features">锁屏功能</string>
|
<string name="disable_keyguard_features">锁屏功能</string>
|
||||||
|
|||||||
@@ -507,17 +507,19 @@
|
|||||||
<string name="password_failed_attempts_is">Password failed attempts: %1$s</string>
|
<string name="password_failed_attempts_is">Password failed attempts: %1$s</string>
|
||||||
<string name="is_using_unified_password">Unified password: %1$s</string>
|
<string name="is_using_unified_password">Unified password: %1$s</string>
|
||||||
<string name="reset_password_token">Reset password token</string>
|
<string name="reset_password_token">Reset password token</string>
|
||||||
|
<string name="token">Token</string>
|
||||||
|
<string name="token_must_longer_than_32_byte">The token must be longer than 32-byte</string>
|
||||||
<string name="token_already_activated">Token already activated</string>
|
<string name="token_already_activated">Token already activated</string>
|
||||||
<string name="clear">Clear</string>
|
<string name="clear">Clear</string>
|
||||||
<string name="set">Set</string>
|
<string name="set">Set</string>
|
||||||
<string name="please_set_a_token">Please set a token</string>
|
<string name="please_set_a_token">Please set a token</string>
|
||||||
<string name="activate_token_not_required_when_no_password">Token will be automatically activated if no password is set. </string>
|
<string name="activate_token_not_required_when_no_password">Token will be automatically activated if no password is set. </string>
|
||||||
<string name="reset_password">Reset password</string>
|
<string name="reset_password">Reset password</string>
|
||||||
|
<string name="confirm_password">Confirm password</string>
|
||||||
<string name="do_not_ask_credentials_on_boot">Do not ask credentials on boot</string>
|
<string name="do_not_ask_credentials_on_boot">Do not ask credentials on boot</string>
|
||||||
<string name="reset_password_require_entry">Require entry</string>
|
<string name="reset_password_require_entry">Require entry</string>
|
||||||
<string name="require_4_digit_password">Require at least 4 digit password</string>
|
<string name="require_4_digit_password">Require at least 4 digit password</string>
|
||||||
<string name="reset_password_with_token">Reset password with token</string>
|
<string name="reset_password_with_token">Reset password with token</string>
|
||||||
<string name="reset_password_deprecated">Reset password</string>
|
|
||||||
<string name="required_password_complexity">Required password complexity</string>
|
<string name="required_password_complexity">Required password complexity</string>
|
||||||
<string name="require_set_new_password">Request to set a new password</string>
|
<string name="require_set_new_password">Request to set a new password</string>
|
||||||
<string name="disable_keyguard_features">Keyguard features</string>
|
<string name="disable_keyguard_features">Keyguard features</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user