|
@@ -1,9 +1,8 @@
|
|
|
package com.fastest.pass.account.presentation.ui.components
|
|
|
|
|
|
-import android.os.Handler
|
|
|
-import android.os.Looper
|
|
|
import android.util.Log
|
|
|
import androidx.compose.foundation.BorderStroke
|
|
|
+import androidx.compose.foundation.ExperimentalFoundationApi
|
|
|
import androidx.compose.foundation.Image
|
|
|
import androidx.compose.foundation.background
|
|
|
import androidx.compose.foundation.border
|
|
@@ -18,44 +17,61 @@ import androidx.compose.foundation.layout.Spacer
|
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
+import androidx.compose.foundation.layout.navigationBarsPadding
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
import androidx.compose.foundation.layout.size
|
|
|
import androidx.compose.foundation.layout.statusBarsPadding
|
|
|
+import androidx.compose.foundation.rememberScrollState
|
|
|
+import androidx.compose.foundation.selection.selectable
|
|
|
+import androidx.compose.foundation.shape.CircleShape
|
|
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
|
+import androidx.compose.foundation.verticalScroll
|
|
|
import androidx.compose.material3.AlertDialog
|
|
|
import androidx.compose.material3.Button
|
|
|
import androidx.compose.material3.ButtonDefaults
|
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
+import androidx.compose.material3.ModalBottomSheet
|
|
|
+import androidx.compose.material3.RadioButton
|
|
|
+import androidx.compose.material3.RadioButtonDefaults
|
|
|
+import androidx.compose.material3.Slider
|
|
|
+import androidx.compose.material3.SliderDefaults
|
|
|
import androidx.compose.material3.Surface
|
|
|
+import androidx.compose.material3.Switch
|
|
|
+import androidx.compose.material3.SwitchDefaults
|
|
|
import androidx.compose.material3.Text
|
|
|
+import androidx.compose.material3.TextButton
|
|
|
+import androidx.compose.material3.rememberModalBottomSheetState
|
|
|
import androidx.compose.runtime.Composable
|
|
|
import androidx.compose.runtime.getValue
|
|
|
+import androidx.compose.runtime.mutableFloatStateOf
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
import androidx.compose.runtime.remember
|
|
|
-import androidx.compose.runtime.rememberCoroutineScope
|
|
|
import androidx.compose.runtime.setValue
|
|
|
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.focus.FocusRequester
|
|
|
-import androidx.compose.ui.focus.onFocusChanged
|
|
|
+import androidx.compose.ui.draw.scale
|
|
|
import androidx.compose.ui.graphics.Color
|
|
|
import androidx.compose.ui.graphics.ColorFilter
|
|
|
-import androidx.compose.ui.platform.LocalContext
|
|
|
import androidx.compose.ui.platform.LocalFocusManager
|
|
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
|
import androidx.compose.ui.res.colorResource
|
|
|
import androidx.compose.ui.res.painterResource
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
+import androidx.compose.ui.text.TextStyle
|
|
|
+import androidx.compose.ui.text.font.FontWeight
|
|
|
+import androidx.compose.ui.text.style.TextAlign
|
|
|
+import androidx.compose.ui.text.style.TextOverflow
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
+import androidx.compose.ui.unit.sp
|
|
|
import androidx.compose.ui.window.DialogProperties
|
|
|
-import androidx.lifecycle.viewmodel.compose.viewModel
|
|
|
-import androidx.navigation.NavHostController
|
|
|
import com.fastest.pass.R
|
|
|
-import com.fastest.pass.home.presentation.ui.components.GapLine
|
|
|
-import com.fastest.pass.security.presentation.ui.components.AddFeaturesRow
|
|
|
+import com.fastest.pass.account.domain.model.SliderPasswordType
|
|
|
+import com.fastest.pass.account.domain.model.sliderPasswordTypeList
|
|
|
+import kotlin.math.roundToInt
|
|
|
+import kotlin.random.Random
|
|
|
|
|
|
enum class ClickType {
|
|
|
OPEN_LOGIN_SCREEN
|
|
@@ -74,33 +90,39 @@ fun AccountScreen(clickType: (ClickType) -> Unit) {
|
|
|
.fillMaxSize()
|
|
|
.statusBarsPadding()
|
|
|
) {
|
|
|
- Column(
|
|
|
+ Box(
|
|
|
modifier = Modifier
|
|
|
.fillMaxSize()
|
|
|
- .padding(top = 0.dp)
|
|
|
+ .padding(top = 150.dp)
|
|
|
.statusBarsPadding()
|
|
|
) {
|
|
|
Column(
|
|
|
modifier = Modifier
|
|
|
.fillMaxSize()
|
|
|
- .padding(top = 25.dp)
|
|
|
+ .padding(top = 0.dp)
|
|
|
.clip(RoundedCornerShape(topStart = 0.dp, topEnd = 0.dp))
|
|
|
- .background(colorResource(id = R.color.home_background_color),)
|
|
|
+ .background(colorResource(id = R.color.home_background_color))
|
|
|
+ .verticalScroll(rememberScrollState())
|
|
|
) {
|
|
|
- Spacer(modifier = Modifier.height(20.dp))
|
|
|
- AddRowAccount(title = stringResource(id = R.string.username), subTitle = "KP")
|
|
|
- Spacer(modifier = Modifier.height(10.dp))
|
|
|
- AddRowAccount(title = stringResource(id = R.string.product), subTitle = "Free Plan")
|
|
|
- Spacer(modifier = Modifier.height(20.dp))
|
|
|
- GapLine()
|
|
|
+// Spacer(modifier = Modifier.height(20.dp))
|
|
|
+// AddRowAccount(title = stringResource(id = R.string.username), subTitle = "KP")
|
|
|
+// Spacer(modifier = Modifier.height(10.dp))
|
|
|
+// AddRowAccount(title = stringResource(id = R.string.product), subTitle = "Free Plan")
|
|
|
+// Spacer(modifier = Modifier.height(20.dp))
|
|
|
+// GapLine()
|
|
|
|
|
|
Column(
|
|
|
modifier = Modifier
|
|
|
.padding(horizontal = 30.dp)
|
|
|
- .padding(bottom = 20.dp)
|
|
|
+ .padding(bottom = 20.dp),
|
|
|
+ horizontalAlignment = Alignment.CenterHorizontally
|
|
|
) {
|
|
|
+ Spacer(modifier = Modifier.height(90.dp))
|
|
|
+ ShowUserAccountText(text = "kp@yopmail.com", MaterialTheme.typography.headlineLarge)
|
|
|
+ Spacer(modifier = Modifier.height(3.dp))
|
|
|
+ ShowUserAccountText(text = "Free Plan", MaterialTheme.typography.headlineSmall)
|
|
|
Spacer(modifier = Modifier.height(50.dp))
|
|
|
- AddFeaturesRow(R.drawable.generate_password, R.string.generate_password, R.string.generate_robust)
|
|
|
+ AddFeaturesRowAS(R.drawable.generate_password, R.string.generate_password, R.string.generate_robust)
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
AddFeaturesRowAS(icon = R.drawable.about, title = R.string.about) {}
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
@@ -113,6 +135,22 @@ fun AccountScreen(clickType: (ClickType) -> Unit) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ Box(
|
|
|
+ modifier = Modifier
|
|
|
+ .padding(top = 75.dp)
|
|
|
+ .size(150.dp)
|
|
|
+ .clip(CircleShape)
|
|
|
+ .background(colorResource(id = R.color.light_gray_login))
|
|
|
+ .align(Alignment.TopCenter),
|
|
|
+ contentAlignment = Alignment.Center
|
|
|
+ ) {
|
|
|
+ Text(text = "K",
|
|
|
+ style = MaterialTheme.typography.titleLarge.copy(
|
|
|
+ color = colorResource(id = R.color.blue_login)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
if (isLoggedOut) {
|
|
|
AlertDialog(
|
|
|
onDismissRequest = { isLoggedOut = false },
|
|
@@ -333,6 +371,8 @@ fun BoxScope.LogoutDialog(
|
|
|
|
|
|
@Composable
|
|
|
fun ColumnScope.AddFeaturesRowAS(icon: Int, title: Int, desc: Int) {
|
|
|
+ var isSheetOpened by remember { mutableStateOf(false) }
|
|
|
+
|
|
|
Row(
|
|
|
modifier = Modifier
|
|
|
.border(
|
|
@@ -341,8 +381,10 @@ fun ColumnScope.AddFeaturesRowAS(icon: Int, title: Int, desc: Int) {
|
|
|
)
|
|
|
.clip(RoundedCornerShape(15.dp))
|
|
|
.background(colorResource(id = R.color.white))
|
|
|
- .padding(vertical = 15.dp)
|
|
|
- .fillMaxWidth(),
|
|
|
+ .fillMaxWidth()
|
|
|
+ .clickable {
|
|
|
+ isSheetOpened = true
|
|
|
+ },
|
|
|
horizontalArrangement = Arrangement.Start,
|
|
|
verticalAlignment = Alignment.CenterVertically
|
|
|
) {
|
|
@@ -355,6 +397,7 @@ fun ColumnScope.AddFeaturesRowAS(icon: Int, title: Int, desc: Int) {
|
|
|
contentDescription = "Icon",
|
|
|
modifier = Modifier
|
|
|
.padding(start = 0.dp)
|
|
|
+ .padding(vertical = 15.dp)
|
|
|
.size(34.dp)
|
|
|
.weight(1f),
|
|
|
colorFilter = ColorFilter.tint(colorResource(id = R.color.gray_splash)),
|
|
@@ -385,22 +428,444 @@ fun ColumnScope.AddFeaturesRowAS(icon: Int, title: Int, desc: Int) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Spacer(modifier = Modifier.weight(1f))
|
|
|
+// Spacer(modifier = Modifier.weight(1f))
|
|
|
+//
|
|
|
+// Surface(
|
|
|
+// modifier = Modifier
|
|
|
+// .padding(end = 15.dp)
|
|
|
+// .align(Alignment.CenterVertically),
|
|
|
+// color = Color.Transparent
|
|
|
+// ) {
|
|
|
+// Image(
|
|
|
+// painter = painterResource(id = R.drawable.crown_premium),
|
|
|
+// contentDescription = "Front_Arrow",
|
|
|
+// modifier = Modifier
|
|
|
+// .padding(start = 0.dp, end = 0.dp)
|
|
|
+// .size(24.dp)
|
|
|
+// .weight(1f),
|
|
|
+// )
|
|
|
+// }
|
|
|
+ }
|
|
|
|
|
|
- Surface(
|
|
|
+ if (isSheetOpened) {
|
|
|
+ OpenModalBottomSheetAS(
|
|
|
+ isSheetOpened = { isSheetOpened = false }
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@Composable
|
|
|
+fun ColumnScope.ShowUserAccountText(text: String, style: TextStyle) {
|
|
|
+ Text(text = text,
|
|
|
+ style = style.copy(
|
|
|
+ color = colorResource(id = R.color.blue_login)
|
|
|
+ )
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
|
|
+@Composable
|
|
|
+fun ColumnScope.OpenModalBottomSheetAS(
|
|
|
+ isSheetOpened: () -> Unit
|
|
|
+) {
|
|
|
+ val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
|
|
+ var isSheetOpen by remember { mutableStateOf(true) }
|
|
|
+ var passwordStrength by remember { mutableStateOf("Average") }
|
|
|
+ var selectedSliderType by remember { mutableStateOf(sliderPasswordTypeList[0]) }
|
|
|
+ var sliderPosition by remember { mutableFloatStateOf(8F) }
|
|
|
+ var updatedColor by remember { mutableStateOf((R.color.light_yellow)) }
|
|
|
+ var updatedTextColor by remember { mutableStateOf((R.color.brown_text)) }
|
|
|
+
|
|
|
+ var isLowerCaseEnabled by remember { mutableStateOf(true) }
|
|
|
+ var isUpperCaseEnabled by remember { mutableStateOf(false) }
|
|
|
+ var isNumberEnabled by remember { mutableStateOf(false) }
|
|
|
+ var isRandomSymbolsEnabled by remember { mutableStateOf(false) }
|
|
|
+ val pass = generatePassword(selectedSliderType, isLowerCaseEnabled, isUpperCaseEnabled, isNumberEnabled, isRandomSymbolsEnabled, sliderPosition.roundToInt())
|
|
|
+ var generatedPassword by remember { mutableStateOf(pass) }
|
|
|
+
|
|
|
+ if (isSheetOpen) {
|
|
|
+ ModalBottomSheet(
|
|
|
+ onDismissRequest = {
|
|
|
+ isSheetOpen = false
|
|
|
+ isSheetOpened.invoke()
|
|
|
+ },
|
|
|
+ sheetState = sheetState,
|
|
|
+ containerColor = colorResource(id = R.color.white),
|
|
|
+ dragHandle = {
|
|
|
+// BottomSheetDefaults.DragHandle(
|
|
|
+// color = colorResource(id = R.color.gray_splash),
|
|
|
+// )
|
|
|
+ },
|
|
|
modifier = Modifier
|
|
|
- .padding(end = 15.dp)
|
|
|
- .align(Alignment.CenterVertically),
|
|
|
- color = Color.Transparent
|
|
|
+ .padding(top = 50.dp)
|
|
|
+ .fillMaxSize()
|
|
|
+// .statusBarsPadding()
|
|
|
+// .navigationBarsPadding()
|
|
|
) {
|
|
|
- Image(
|
|
|
- painter = painterResource(id = R.drawable.crown_premium),
|
|
|
- contentDescription = "Front_Arrow",
|
|
|
+ Column(
|
|
|
modifier = Modifier
|
|
|
- .padding(start = 0.dp, end = 0.dp)
|
|
|
- .size(24.dp)
|
|
|
- .weight(1f),
|
|
|
- )
|
|
|
+ .fillMaxSize()
|
|
|
+ .background(Color.Transparent)
|
|
|
+ .padding(start = 0.dp, top = 0.dp)
|
|
|
+ ) {
|
|
|
+ Box(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .height(150.dp)
|
|
|
+ .background(colorResource(id = updatedColor))
|
|
|
+ ) {
|
|
|
+ Column(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxSize()
|
|
|
+ .padding(horizontal = 30.dp, vertical = 15.dp),
|
|
|
+ horizontalAlignment = Alignment.Start,
|
|
|
+ verticalArrangement = Arrangement.SpaceAround
|
|
|
+ ) {
|
|
|
+ Text(
|
|
|
+ generatedPassword,
|
|
|
+ style = MaterialTheme.typography.displayLarge.copy(
|
|
|
+ color = colorResource(id = R.color.gray_splash)
|
|
|
+ ),
|
|
|
+ maxLines = 2,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ )
|
|
|
+ Spacer(modifier = Modifier.height(15.dp))
|
|
|
+ Text(
|
|
|
+ passwordStrength,
|
|
|
+ style = MaterialTheme.typography.displayMedium.copy(
|
|
|
+ color = colorResource(id = updatedTextColor),
|
|
|
+ fontWeight = FontWeight.SemiBold
|
|
|
+ ),
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Box(
|
|
|
+ modifier = Modifier
|
|
|
+ .padding(horizontal = 30.dp, vertical = 10.dp)
|
|
|
+ .padding(bottom = 0.dp)
|
|
|
+ .fillMaxSize()
|
|
|
+ .background(Color.Transparent)
|
|
|
+
|
|
|
+ ) {
|
|
|
+ Column(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxSize()
|
|
|
+ ) {
|
|
|
+ Text(
|
|
|
+ "Password length: ${sliderPosition.roundToInt()} characters",
|
|
|
+ style = MaterialTheme.typography.displayMedium.copy(
|
|
|
+ color = colorResource(id = R.color.gray_splash)
|
|
|
+ ),
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .verticalScroll(rememberScrollState())
|
|
|
+ )
|
|
|
+ Spacer(modifier = Modifier.height(8.dp))
|
|
|
+ Slider(
|
|
|
+ value = sliderPosition,
|
|
|
+ onValueChange = {
|
|
|
+ sliderPosition = it.roundToInt().toFloat()
|
|
|
+ },
|
|
|
+ onValueChangeFinished = {
|
|
|
+ Log.d("slider", "Finish => ${sliderPosition.roundToInt()}")
|
|
|
+ if (sliderPosition.roundToInt() == 8) {
|
|
|
+ passwordStrength = "Average"
|
|
|
+ updatedColor = R.color.light_yellow
|
|
|
+ updatedTextColor = R.color.brown_text
|
|
|
+ }
|
|
|
+ else if (sliderPosition.roundToInt() == 9 || sliderPosition.roundToInt() == 10) {
|
|
|
+ passwordStrength = "Strong"
|
|
|
+ updatedColor = R.color.light_green
|
|
|
+ updatedTextColor = R.color.green_text
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ passwordStrength = "Very strong"
|
|
|
+ updatedColor = R.color.light_green
|
|
|
+ updatedTextColor = R.color.green_text
|
|
|
+ }
|
|
|
+
|
|
|
+ generatedPassword = generatePassword(selectedSliderType, isLowerCaseEnabled, isUpperCaseEnabled, isNumberEnabled, isRandomSymbolsEnabled, sliderPosition.roundToInt())
|
|
|
+ },
|
|
|
+ valueRange = 8f..128f,
|
|
|
+ colors = SliderDefaults.colors(
|
|
|
+ thumbColor = colorResource(id = R.color.sky_green),
|
|
|
+ activeTrackColor = colorResource(id = R.color.sky_green),
|
|
|
+ inactiveTrackColor = colorResource(id = R.color.home_background_color)
|
|
|
+ ),
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ )
|
|
|
+ Spacer(modifier = Modifier.height(10.dp))
|
|
|
+ Text(
|
|
|
+ "Choose a password type",
|
|
|
+ style = MaterialTheme.typography.labelMedium.copy(
|
|
|
+ color = colorResource(id = R.color.gray_splash),
|
|
|
+ ),
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ )
|
|
|
+ Spacer(modifier = Modifier.height(15.dp))
|
|
|
+
|
|
|
+ sliderPasswordTypeList.forEachIndexed { index, sliderPasswordType ->
|
|
|
+ Row(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .background(Color.Transparent)
|
|
|
+ .selectable(
|
|
|
+ sliderPasswordType == selectedSliderType,
|
|
|
+ onClick = {
|
|
|
+ selectedSliderType = sliderPasswordType
|
|
|
+ if (selectedSliderType == sliderPasswordTypeList[2]) {
|
|
|
+ isNumberEnabled = false
|
|
|
+ isRandomSymbolsEnabled = false
|
|
|
+ }
|
|
|
+
|
|
|
+ val passGen = generatePassword(selectedSliderType, isLowerCaseEnabled, isUpperCaseEnabled, isNumberEnabled, isRandomSymbolsEnabled, sliderPosition.roundToInt())
|
|
|
+ generatedPassword = passGen
|
|
|
+ }
|
|
|
+ ),
|
|
|
+ verticalAlignment = Alignment.CenterVertically,
|
|
|
+ ) {
|
|
|
+ Column(
|
|
|
+ modifier = Modifier
|
|
|
+ .weight(1F),
|
|
|
+ verticalArrangement = Arrangement.Center,
|
|
|
+ horizontalAlignment = Alignment.Start
|
|
|
+ ) {
|
|
|
+ Text(
|
|
|
+ sliderPasswordType.title,
|
|
|
+ style = MaterialTheme.typography.titleMedium.copy(
|
|
|
+ color = colorResource(id = R.color.gray_splash),
|
|
|
+ ),
|
|
|
+ modifier = Modifier
|
|
|
+
|
|
|
+ )
|
|
|
+ Spacer(modifier = Modifier.height(2.dp))
|
|
|
+ Text(
|
|
|
+ sliderPasswordType.desc,
|
|
|
+ style = MaterialTheme.typography.displaySmall.copy(
|
|
|
+ color = colorResource(id = R.color.gray_splash),
|
|
|
+ ),
|
|
|
+ modifier = Modifier
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ RadioButton(
|
|
|
+ selected = sliderPasswordType == selectedSliderType,
|
|
|
+ onClick = {
|
|
|
+ selectedSliderType = sliderPasswordType
|
|
|
+ if (selectedSliderType == sliderPasswordTypeList[2]) {
|
|
|
+ isNumberEnabled = false
|
|
|
+ isRandomSymbolsEnabled = false
|
|
|
+ }
|
|
|
+
|
|
|
+ val passGen = generatePassword(selectedSliderType, isLowerCaseEnabled, isUpperCaseEnabled, isNumberEnabled, isRandomSymbolsEnabled, sliderPosition.roundToInt())
|
|
|
+ generatedPassword = passGen
|
|
|
+ },
|
|
|
+ colors = RadioButtonDefaults.colors(
|
|
|
+ selectedColor = colorResource(id = R.color.radio_button_blue),
|
|
|
+ unselectedColor = colorResource(id = R.color.gray_icon),
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ }
|
|
|
+ Spacer(modifier = Modifier.height(15.dp))
|
|
|
+ }
|
|
|
+
|
|
|
+ Spacer(modifier = Modifier.height(10.dp))
|
|
|
+ Text(
|
|
|
+ stringResource(id = R.string.more_options),
|
|
|
+ style = MaterialTheme.typography.labelMedium.copy(
|
|
|
+ color = colorResource(id = R.color.gray_splash),
|
|
|
+ ),
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ )
|
|
|
+ Spacer(modifier = Modifier.height(10.dp))
|
|
|
+ SwitchPasswordGenerator(title = R.string.lowercase_abc, onSwitchClick = {
|
|
|
+ isLowerCaseEnabled = it
|
|
|
+ }, isLowerCaseEnabled,
|
|
|
+ onSwitchGeneratePassword = {
|
|
|
+ val passGen = generatePassword(selectedSliderType, isLowerCaseEnabled, isUpperCaseEnabled, isNumberEnabled, isRandomSymbolsEnabled, sliderPosition.roundToInt())
|
|
|
+ generatedPassword = passGen
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ Spacer(modifier = Modifier.height(5.dp))
|
|
|
+ SwitchPasswordGenerator(title = R.string.uppercase_abc, onSwitchClick = {
|
|
|
+ isUpperCaseEnabled = it
|
|
|
+ }, isUpperCaseEnabled,
|
|
|
+ onSwitchGeneratePassword = {
|
|
|
+ val passGen = generatePassword(selectedSliderType, isLowerCaseEnabled, isUpperCaseEnabled, isNumberEnabled, isRandomSymbolsEnabled, sliderPosition.roundToInt())
|
|
|
+ generatedPassword = passGen
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ Spacer(modifier = Modifier.height(5.dp))
|
|
|
+ SwitchPasswordGenerator(
|
|
|
+ title = R.string.numbers_123,
|
|
|
+ onSwitchClick = {
|
|
|
+ isNumberEnabled = it
|
|
|
+ },
|
|
|
+ isSwitchEnabled = isNumberEnabled,
|
|
|
+ toBeEnabled = selectedSliderType != sliderPasswordTypeList[2],
|
|
|
+ onSwitchGeneratePassword = {
|
|
|
+ val passGen = generatePassword(selectedSliderType, isLowerCaseEnabled, isUpperCaseEnabled, isNumberEnabled, isRandomSymbolsEnabled, sliderPosition.roundToInt())
|
|
|
+ generatedPassword = passGen
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ Spacer(modifier = Modifier.height(5.dp))
|
|
|
+ SwitchPasswordGenerator(
|
|
|
+ title = R.string.randomized_symbols,
|
|
|
+ onSwitchClick = {
|
|
|
+ isRandomSymbolsEnabled = it
|
|
|
+ },
|
|
|
+ isSwitchEnabled = isRandomSymbolsEnabled,
|
|
|
+ toBeEnabled = selectedSliderType != sliderPasswordTypeList[2],
|
|
|
+ onSwitchGeneratePassword = {
|
|
|
+ val passGen = generatePassword(selectedSliderType, isLowerCaseEnabled, isUpperCaseEnabled, isNumberEnabled, isRandomSymbolsEnabled, sliderPosition.roundToInt())
|
|
|
+ generatedPassword = passGen
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ Spacer(modifier = Modifier.height(5.dp))
|
|
|
+ Row(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .background(Color.Transparent),
|
|
|
+ horizontalArrangement = Arrangement.End
|
|
|
+ ) {
|
|
|
+ TextButton(onClick = {
|
|
|
+ isSheetOpen = false
|
|
|
+ isSheetOpened.invoke()
|
|
|
+ }) {
|
|
|
+ Text(
|
|
|
+ text = "CANCEL",
|
|
|
+ style = MaterialTheme.typography.bodyMedium.copy(
|
|
|
+ textAlign = TextAlign.End
|
|
|
+ ),
|
|
|
+ color = colorResource(id = R.color.blue_text),
|
|
|
+ modifier = Modifier
|
|
|
+ )
|
|
|
+ }
|
|
|
+ TextButton(onClick = {
|
|
|
+ isSheetOpen = false
|
|
|
+ isSheetOpened.invoke()
|
|
|
+ }) {
|
|
|
+ Text(
|
|
|
+ text = "USE",
|
|
|
+ style = MaterialTheme.typography.bodyMedium.copy(
|
|
|
+ textAlign = TextAlign.End
|
|
|
+ ),
|
|
|
+ color = colorResource(id = R.color.blue_text),
|
|
|
+ modifier = Modifier
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+// Box(
|
|
|
+// modifier = Modifier
|
|
|
+// .fillMaxWidth()
|
|
|
+// .height(150.dp)
|
|
|
+// .background(colorResource(id = R.color.white))
|
|
|
+// .align(Alignment.BottomCenter)
|
|
|
+// ) {
|
|
|
+//
|
|
|
+// }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+@Composable
|
|
|
+fun ColumnScope.SwitchPasswordGenerator(
|
|
|
+ title: Int,
|
|
|
+ onSwitchClick: (Boolean) -> Unit,
|
|
|
+ isSwitchEnabled: Boolean,
|
|
|
+ toBeEnabled: Boolean = true,
|
|
|
+ onSwitchGeneratePassword: () -> Unit
|
|
|
+) {
|
|
|
+ var isSwitch by remember { mutableStateOf(isSwitchEnabled) }
|
|
|
+ isSwitch = isSwitchEnabled
|
|
|
+
|
|
|
+ Row(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+// .height(30.dp)
|
|
|
+ .background(Color.Transparent),
|
|
|
+ verticalAlignment = Alignment.CenterVertically
|
|
|
+ ) {
|
|
|
+ Text(
|
|
|
+ text = stringResource(id = title).plus(isSwitchEnabled).plus(isSwitch),
|
|
|
+ color = colorResource(id = R.color.gray_splash),
|
|
|
+ style = MaterialTheme.typography.titleMedium,
|
|
|
+ lineHeight = 20.sp,
|
|
|
+ modifier = Modifier
|
|
|
+ )
|
|
|
+ Spacer(modifier = Modifier.weight(1F))
|
|
|
+ Switch(
|
|
|
+ checked = isSwitch,
|
|
|
+ onCheckedChange = {
|
|
|
+ isSwitch = it
|
|
|
+ onSwitchClick.invoke(isSwitch)
|
|
|
+ onSwitchGeneratePassword.invoke()
|
|
|
+ },
|
|
|
+ enabled = toBeEnabled,
|
|
|
+ modifier = Modifier
|
|
|
+ .scale(0.8F),
|
|
|
+ colors = SwitchDefaults.colors(
|
|
|
+ checkedThumbColor = colorResource(id = R.color.white),
|
|
|
+ checkedTrackColor = colorResource(id = R.color.sky_green),
|
|
|
+ uncheckedThumbColor = colorResource(id = R.color.white),
|
|
|
+ uncheckedTrackColor = colorResource(id = R.color.gray_text),
|
|
|
+ uncheckedBorderColor = colorResource(id = R.color.gray_text),
|
|
|
+ ),
|
|
|
+ thumbContent = {}
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+fun generatePassword(
|
|
|
+ selectedSliderType: SliderPasswordType,
|
|
|
+ isLowercaseEnabled: Boolean,
|
|
|
+ isUppercaseEnabled: Boolean,
|
|
|
+ isNumbersEnabled: Boolean,
|
|
|
+ isRandomSymbolsEnabled: Boolean,
|
|
|
+ passwordLength: Int
|
|
|
+) : String {
|
|
|
+ val uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
+ val lowercase = "abcdefghijklmnopqrstuvwxyz"
|
|
|
+ val numbers = "0123456789"
|
|
|
+ val specialCharacters = "!@#$%^&*()-_=+<>?/{}[]|"
|
|
|
+
|
|
|
+ val easyToRead = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789"
|
|
|
+
|
|
|
+ var charPool = ""
|
|
|
+ if (isLowercaseEnabled) charPool += lowercase
|
|
|
+ if (isUppercaseEnabled) charPool += uppercase
|
|
|
+ if (isNumbersEnabled) charPool += numbers
|
|
|
+ if (isRandomSymbolsEnabled) charPool += specialCharacters
|
|
|
+
|
|
|
+ val password = if (charPool.isNotEmpty()) {
|
|
|
+ (1..passwordLength)
|
|
|
+ .map { Random.nextInt(0, charPool.length) }
|
|
|
+ .map { charPool[it] }
|
|
|
+ .shuffled()
|
|
|
+ .joinToString("")
|
|
|
+ } else {
|
|
|
+ ""
|
|
|
+ }
|
|
|
+
|
|
|
+ Log.d("test_generate_pass", "$isLowercaseEnabled $isUppercaseEnabled $isNumbersEnabled $isRandomSymbolsEnabled")
|
|
|
+ Log.d("test_generate_pass", "charPool = $charPool")
|
|
|
+ Log.d("test_generate_pass", "password = $password")
|
|
|
+
|
|
|
+ return password
|
|
|
+}
|