mirror of
https://github.com/bitwarden/android.git
synced 2024-11-21 17:05:44 +03:00
Clean up the generator screen and handlers (#4270)
This commit is contained in:
parent
6dd783051f
commit
16cc70f344
8 changed files with 535 additions and 484 deletions
|
@ -67,6 +67,20 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Pa
|
|||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Passphrase.Companion.PASSPHRASE_MIN_NUMBER_OF_WORDS
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceTypeOption
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.CatchAllEmailHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.ForwardedEmailAliasHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.PassphraseHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.PasswordHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.PlusAddressedEmailHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.RandomWordHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.UsernameTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.rememberCatchAllEmailHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.rememberForwardedEmailAliasHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.rememberPassphraseHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.rememberPasswordHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.rememberPlusAddressedEmailHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.rememberRandomWordHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.handlers.rememberUsernameTypeHandlers
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.model.GeneratorMode
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
@ -135,47 +149,26 @@ fun GeneratorScreen(
|
|||
remember(viewModel) {
|
||||
{
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Username.UsernameTypeOptionSelect(
|
||||
it,
|
||||
),
|
||||
GeneratorAction.MainType.Username.UsernameTypeOptionSelect(it),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val passwordHandlers = remember(viewModel) {
|
||||
PasswordHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val passphraseHandlers = remember(viewModel) {
|
||||
PassphraseHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val usernameTypeHandlers = remember(viewModel) {
|
||||
UsernameTypeHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val forwardedEmailAliasHandlers = remember(viewModel) {
|
||||
ForwardedEmailAliasHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val plusAddressedEmailHandlers = remember(viewModel) {
|
||||
PlusAddressedEmailHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val catchAllEmailHandlers = remember(viewModel) {
|
||||
CatchAllEmailHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
|
||||
val randomWordHandlers = remember(viewModel) {
|
||||
RandomWordHandlers.create(viewModel = viewModel)
|
||||
}
|
||||
val passwordHandlers = rememberPasswordHandlers(viewModel)
|
||||
val passphraseHandlers = rememberPassphraseHandlers(viewModel)
|
||||
val usernameTypeHandlers = rememberUsernameTypeHandlers(viewModel)
|
||||
val forwardedEmailAliasHandlers = rememberForwardedEmailAliasHandlers(viewModel)
|
||||
val plusAddressedEmailHandlers = rememberPlusAddressedEmailHandlers(viewModel)
|
||||
val catchAllEmailHandlers = rememberCatchAllEmailHandlers(viewModel)
|
||||
val randomWordHandlers = rememberRandomWordHandlers(viewModel)
|
||||
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
BitwardenScaffold(
|
||||
topBar = {
|
||||
when (state.generatorMode) {
|
||||
when (val generatorMode = state.generatorMode) {
|
||||
is GeneratorMode.Modal -> {
|
||||
ModalAppBar(
|
||||
generatorMode = generatorMode,
|
||||
scrollBehavior = scrollBehavior,
|
||||
onCloseClick = remember(viewModel) {
|
||||
{ viewModel.trySendAction(GeneratorAction.CloseClick) }
|
||||
|
@ -234,6 +227,7 @@ fun GeneratorScreen(
|
|||
private fun DefaultAppBar(
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
onPasswordHistoryClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenMediumTopAppBar(
|
||||
title = stringResource(id = R.string.generator),
|
||||
|
@ -249,15 +243,18 @@ private fun DefaultAppBar(
|
|||
),
|
||||
)
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ModalAppBar(
|
||||
generatorMode: GeneratorMode.Modal,
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
onCloseClick: () -> Unit,
|
||||
onSelectClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenTopAppBar(
|
||||
title = stringResource(id = R.string.generator),
|
||||
|
@ -265,6 +262,10 @@ private fun ModalAppBar(
|
|||
navigationIconContentDescription = stringResource(id = R.string.close),
|
||||
onNavigationIconClick = onCloseClick,
|
||||
scrollBehavior = scrollBehavior,
|
||||
dividerStyle = when (generatorMode) {
|
||||
GeneratorMode.Modal.Password -> TopAppBarDividerStyle.NONE
|
||||
is GeneratorMode.Modal.Username -> TopAppBarDividerStyle.ON_SCROLL
|
||||
},
|
||||
actions = {
|
||||
BitwardenTextButton(
|
||||
label = stringResource(id = R.string.select),
|
||||
|
@ -272,6 +273,7 @@ private fun ModalAppBar(
|
|||
modifier = Modifier.testTag("SelectButton"),
|
||||
)
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -365,6 +367,7 @@ private fun GeneratedStringItem(
|
|||
generatedText: String,
|
||||
onCopyClick: () -> Unit,
|
||||
onRegenerateClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenTextFieldWithActions(
|
||||
label = "",
|
||||
|
@ -390,7 +393,7 @@ private fun GeneratedStringItem(
|
|||
textStyle = BitwardenTheme.typography.sensitiveInfoSmall,
|
||||
shouldAddCustomLineBreaks = true,
|
||||
visualTransformation = nonLetterColorVisualTransformation(),
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
modifier = modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -469,26 +472,25 @@ private fun ColumnScope.PasswordTypeContent(
|
|||
|
||||
PasswordCapitalLettersToggleItem(
|
||||
useCapitals = passwordTypeState.useCapitals,
|
||||
onPasswordToggleCapitalLettersChange =
|
||||
passwordHandlers.onPasswordToggleCapitalLettersChange,
|
||||
onPasswordToggleCapitalLettersChange = passwordHandlers
|
||||
.onPasswordToggleCapitalLettersChange,
|
||||
enabled = passwordTypeState.capitalsEnabled,
|
||||
)
|
||||
PasswordLowercaseLettersToggleItem(
|
||||
useLowercase = passwordTypeState.useLowercase,
|
||||
onPasswordToggleLowercaseLettersChange =
|
||||
passwordHandlers.onPasswordToggleLowercaseLettersChange,
|
||||
onPasswordToggleLowercaseLettersChange = passwordHandlers
|
||||
.onPasswordToggleLowercaseLettersChange,
|
||||
enabled = passwordTypeState.lowercaseEnabled,
|
||||
)
|
||||
PasswordNumbersToggleItem(
|
||||
useNumbers = passwordTypeState.useNumbers,
|
||||
onPasswordToggleNumbersChange =
|
||||
passwordHandlers.onPasswordToggleNumbersChange,
|
||||
onPasswordToggleNumbersChange = passwordHandlers.onPasswordToggleNumbersChange,
|
||||
enabled = passwordTypeState.numbersEnabled,
|
||||
)
|
||||
PasswordSpecialCharactersToggleItem(
|
||||
useSpecialChars = passwordTypeState.useSpecialChars,
|
||||
onPasswordToggleSpecialCharactersChange =
|
||||
passwordHandlers.onPasswordToggleSpecialCharactersChange,
|
||||
onPasswordToggleSpecialCharactersChange = passwordHandlers
|
||||
.onPasswordToggleSpecialCharactersChange,
|
||||
enabled = passwordTypeState.specialCharsEnabled,
|
||||
)
|
||||
}
|
||||
|
@ -497,8 +499,7 @@ private fun ColumnScope.PasswordTypeContent(
|
|||
|
||||
PasswordMinNumbersCounterItem(
|
||||
minNumbers = passwordTypeState.minNumbers,
|
||||
onPasswordMinNumbersCounterChange =
|
||||
passwordHandlers.onPasswordMinNumbersCounterChange,
|
||||
onPasswordMinNumbersCounterChange = passwordHandlers.onPasswordMinNumbersCounterChange,
|
||||
maxValue = max(passwordTypeState.maxNumbersAllowed, passwordTypeState.minNumbersAllowed),
|
||||
minValue = passwordTypeState.minNumbersAllowed,
|
||||
)
|
||||
|
@ -507,8 +508,8 @@ private fun ColumnScope.PasswordTypeContent(
|
|||
|
||||
PasswordMinSpecialCharactersCounterItem(
|
||||
minSpecial = passwordTypeState.minSpecial,
|
||||
onPasswordMinSpecialCharactersChange =
|
||||
passwordHandlers.onPasswordMinSpecialCharactersChange,
|
||||
onPasswordMinSpecialCharactersChange = passwordHandlers
|
||||
.onPasswordMinSpecialCharactersChange,
|
||||
maxValue = max(passwordTypeState.maxSpecialAllowed, passwordTypeState.minSpecialAllowed),
|
||||
minValue = passwordTypeState.minSpecialAllowed,
|
||||
)
|
||||
|
@ -517,8 +518,8 @@ private fun ColumnScope.PasswordTypeContent(
|
|||
|
||||
PasswordAvoidAmbiguousCharsToggleItem(
|
||||
avoidAmbiguousChars = passwordTypeState.avoidAmbiguousChars,
|
||||
onPasswordToggleAvoidAmbiguousCharsChange =
|
||||
passwordHandlers.onPasswordToggleAvoidAmbiguousCharsChange,
|
||||
onPasswordToggleAvoidAmbiguousCharsChange = passwordHandlers
|
||||
.onPasswordToggleAvoidAmbiguousCharsChange,
|
||||
enabled = passwordTypeState.ambiguousCharsEnabled,
|
||||
)
|
||||
}
|
||||
|
@ -527,18 +528,19 @@ private fun ColumnScope.PasswordTypeContent(
|
|||
private fun PasswordCapitalLettersToggleItem(
|
||||
useCapitals: Boolean,
|
||||
onPasswordToggleCapitalLettersChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
label = "A—Z",
|
||||
contentDescription = stringResource(id = R.string.uppercase_ato_z),
|
||||
isChecked = useCapitals,
|
||||
onCheckedChange = onPasswordToggleCapitalLettersChange,
|
||||
enabled = enabled,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("UppercaseAtoZToggle")
|
||||
.padding(horizontal = 16.dp),
|
||||
contentDescription = stringResource(id = R.string.uppercase_ato_z),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -546,18 +548,19 @@ private fun PasswordCapitalLettersToggleItem(
|
|||
private fun PasswordLowercaseLettersToggleItem(
|
||||
useLowercase: Boolean,
|
||||
onPasswordToggleLowercaseLettersChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
label = "a—z",
|
||||
contentDescription = stringResource(id = R.string.lowercase_ato_z),
|
||||
isChecked = useLowercase,
|
||||
onCheckedChange = onPasswordToggleLowercaseLettersChange,
|
||||
enabled = enabled,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("LowercaseAtoZToggle")
|
||||
.padding(horizontal = 16.dp),
|
||||
contentDescription = stringResource(id = R.string.lowercase_ato_z),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -565,18 +568,19 @@ private fun PasswordLowercaseLettersToggleItem(
|
|||
private fun PasswordNumbersToggleItem(
|
||||
useNumbers: Boolean,
|
||||
onPasswordToggleNumbersChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
label = "0-9",
|
||||
contentDescription = stringResource(id = R.string.numbers_zero_to_nine),
|
||||
isChecked = useNumbers,
|
||||
onCheckedChange = onPasswordToggleNumbersChange,
|
||||
enabled = enabled,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("NumbersZeroToNineToggle")
|
||||
.padding(horizontal = 16.dp),
|
||||
contentDescription = stringResource(id = R.string.numbers_zero_to_nine),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -584,18 +588,19 @@ private fun PasswordNumbersToggleItem(
|
|||
private fun PasswordSpecialCharactersToggleItem(
|
||||
useSpecialChars: Boolean,
|
||||
onPasswordToggleSpecialCharactersChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
label = "!@#$%^&*",
|
||||
contentDescription = stringResource(id = R.string.special_characters),
|
||||
isChecked = useSpecialChars,
|
||||
onCheckedChange = onPasswordToggleSpecialCharactersChange,
|
||||
enabled = enabled,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("SpecialCharactersToggle")
|
||||
.padding(horizontal = 16.dp),
|
||||
contentDescription = stringResource(id = R.string.special_characters),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -605,13 +610,14 @@ private fun PasswordMinNumbersCounterItem(
|
|||
onPasswordMinNumbersCounterChange: (Int) -> Unit,
|
||||
minValue: Int,
|
||||
maxValue: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenStepper(
|
||||
label = stringResource(id = R.string.min_numbers),
|
||||
value = minNumbers.coerceIn(minValue, maxValue),
|
||||
range = minValue..maxValue,
|
||||
onValueChange = onPasswordMinNumbersCounterChange,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.testTag("MinNumberValueLabel")
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
|
@ -623,13 +629,14 @@ private fun PasswordMinSpecialCharactersCounterItem(
|
|||
onPasswordMinSpecialCharactersChange: (Int) -> Unit,
|
||||
minValue: Int,
|
||||
maxValue: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenStepper(
|
||||
label = stringResource(id = R.string.min_special),
|
||||
value = minSpecial.coerceIn(minValue, maxValue),
|
||||
range = minValue..maxValue,
|
||||
onValueChange = onPasswordMinSpecialCharactersChange,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.testTag("MinSpecialValueLabel")
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
|
@ -639,6 +646,7 @@ private fun PasswordMinSpecialCharactersCounterItem(
|
|||
private fun PasswordAvoidAmbiguousCharsToggleItem(
|
||||
avoidAmbiguousChars: Boolean,
|
||||
onPasswordToggleAvoidAmbiguousCharsChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
|
@ -646,7 +654,7 @@ private fun PasswordAvoidAmbiguousCharsToggleItem(
|
|||
isChecked = avoidAmbiguousChars,
|
||||
enabled = enabled,
|
||||
onCheckedChange = onPasswordToggleAvoidAmbiguousCharsChange,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("AvoidAmbiguousCharsToggle")
|
||||
.padding(horizontal = 16.dp),
|
||||
|
@ -666,8 +674,7 @@ private fun ColumnScope.PassphraseTypeContent(
|
|||
|
||||
PassphraseNumWordsCounterItem(
|
||||
numWords = passphraseTypeState.numWords,
|
||||
onPassphraseNumWordsCounterChange =
|
||||
passphraseHandlers.onPassphraseNumWordsCounterChange,
|
||||
onPassphraseNumWordsCounterChange = passphraseHandlers.onPassphraseNumWordsCounterChange,
|
||||
minValue = passphraseTypeState.minNumWords,
|
||||
maxValue = passphraseTypeState.maxNumWords,
|
||||
)
|
||||
|
@ -686,14 +693,14 @@ private fun ColumnScope.PassphraseTypeContent(
|
|||
) {
|
||||
PassphraseCapitalizeToggleItem(
|
||||
capitalize = passphraseTypeState.capitalize,
|
||||
onPassphraseCapitalizeToggleChange =
|
||||
passphraseHandlers.onPassphraseCapitalizeToggleChange,
|
||||
onPassphraseCapitalizeToggleChange = passphraseHandlers
|
||||
.onPassphraseCapitalizeToggleChange,
|
||||
enabled = passphraseTypeState.capitalizeEnabled,
|
||||
)
|
||||
PassphraseIncludeNumberToggleItem(
|
||||
includeNumber = passphraseTypeState.includeNumber,
|
||||
onPassphraseIncludeNumberToggleChange =
|
||||
passphraseHandlers.onPassphraseIncludeNumberToggleChange,
|
||||
onPassphraseIncludeNumberToggleChange = passphraseHandlers
|
||||
.onPassphraseIncludeNumberToggleChange,
|
||||
enabled = passphraseTypeState.includeNumberEnabled,
|
||||
)
|
||||
}
|
||||
|
@ -703,6 +710,7 @@ private fun ColumnScope.PassphraseTypeContent(
|
|||
private fun PassphraseNumWordsCounterItem(
|
||||
numWords: Int,
|
||||
onPassphraseNumWordsCounterChange: (Int) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
minValue: Int = PASSPHRASE_MIN_NUMBER_OF_WORDS,
|
||||
maxValue: Int = PASSPHRASE_MAX_NUMBER_OF_WORDS,
|
||||
) {
|
||||
|
@ -714,7 +722,7 @@ private fun PassphraseNumWordsCounterItem(
|
|||
range = minValue..maxValue,
|
||||
onValueChange = onPassphraseNumWordsCounterChange,
|
||||
stepperActionsTestTag = "NumberOfWordsStepper",
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.testTag("NumberOfWordsLabel")
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
|
@ -724,6 +732,7 @@ private fun PassphraseNumWordsCounterItem(
|
|||
private fun PassphraseWordSeparatorInputItem(
|
||||
wordSeparator: Char?,
|
||||
onPassphraseWordSeparatorChange: (wordSeparator: Char?) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.word_separator),
|
||||
|
@ -737,7 +746,7 @@ private fun PassphraseWordSeparatorInputItem(
|
|||
onPassphraseWordSeparatorChange(char)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.testTag("WordSeparatorEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
|
@ -748,6 +757,7 @@ private fun PassphraseWordSeparatorInputItem(
|
|||
private fun PassphraseCapitalizeToggleItem(
|
||||
capitalize: Boolean,
|
||||
onPassphraseCapitalizeToggleChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
|
@ -755,7 +765,7 @@ private fun PassphraseCapitalizeToggleItem(
|
|||
isChecked = capitalize,
|
||||
onCheckedChange = onPassphraseCapitalizeToggleChange,
|
||||
enabled = enabled,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.testTag("CapitalizePassphraseToggle")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
|
@ -767,13 +777,14 @@ private fun PassphraseIncludeNumberToggleItem(
|
|||
includeNumber: Boolean,
|
||||
onPassphraseIncludeNumberToggleChange: (Boolean) -> Unit,
|
||||
enabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
label = stringResource(id = R.string.include_number),
|
||||
isChecked = includeNumber,
|
||||
enabled = enabled,
|
||||
onCheckedChange = onPassphraseIncludeNumberToggleChange,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.testTag("IncludeNumbersToggle")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
|
@ -832,6 +843,7 @@ private fun UsernameOptionsItem(
|
|||
currentSubState: GeneratorState.MainType.Username,
|
||||
onSubStateOptionClicked: (GeneratorState.MainType.Username.UsernameTypeOption) -> Unit,
|
||||
usernameTypeHandlers: UsernameTypeHandlers,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val possibleSubStates = GeneratorState.MainType.Username.UsernameTypeOption.entries
|
||||
val optionsWithStrings = possibleSubStates.associateWith { stringResource(id = it.labelRes) }
|
||||
|
@ -845,10 +857,6 @@ private fun UsernameOptionsItem(
|
|||
optionsWithStrings.entries.first { it.value == selectedOption }.key
|
||||
onSubStateOptionClicked(selectedOptionId)
|
||||
},
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth()
|
||||
.testTag("UsernameTypePicker"),
|
||||
supportingText = currentSubState.selectedType.supportingStringResId?.let {
|
||||
stringResource(id = it)
|
||||
},
|
||||
|
@ -856,6 +864,10 @@ private fun UsernameOptionsItem(
|
|||
onClick = usernameTypeHandlers.onUsernameTooltipClicked,
|
||||
contentDescription = stringResource(id = R.string.learn_more),
|
||||
),
|
||||
modifier = modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth()
|
||||
.testTag("UsernameTypePicker"),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1002,6 +1014,7 @@ private fun ColumnScope.ForwardedEmailAliasTypeContent(
|
|||
private fun ServiceTypeOptionsItem(
|
||||
currentSubState: GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias,
|
||||
onSubStateOptionClicked: (ServiceTypeOption) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val possibleSubStates = ServiceTypeOption.entries
|
||||
val optionsWithStrings = possibleSubStates.associateWith { stringResource(id = it.labelRes) }
|
||||
|
@ -1017,7 +1030,7 @@ private fun ServiceTypeOptionsItem(
|
|||
optionsWithStrings.entries.first { it.value == selectedOption }.key
|
||||
onSubStateOptionClicked(selectedOptionId)
|
||||
},
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.testTag("ServiceTypePicker")
|
||||
.fillMaxWidth(),
|
||||
|
@ -1043,14 +1056,13 @@ private fun ColumnScope.PlusAddressedEmailTypeContent(
|
|||
private fun PlusAddressedEmailTextInputItem(
|
||||
email: String,
|
||||
onPlusAddressedEmailTextChange: (email: String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.email_required_parenthesis),
|
||||
value = email,
|
||||
onValueChange = {
|
||||
onPlusAddressedEmailTextChange(it)
|
||||
},
|
||||
modifier = Modifier
|
||||
onValueChange = onPlusAddressedEmailTextChange,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("PlusAddressedEmailEntry")
|
||||
.padding(horizontal = 16.dp),
|
||||
|
@ -1078,14 +1090,13 @@ private fun ColumnScope.CatchAllEmailTypeContent(
|
|||
private fun CatchAllEmailTextInputItem(
|
||||
domain: String,
|
||||
onDomainTextChange: (domain: String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.domain_name_required_parenthesis),
|
||||
value = domain,
|
||||
onValueChange = {
|
||||
onDomainTextChange(it)
|
||||
},
|
||||
modifier = Modifier
|
||||
onValueChange = onDomainTextChange,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("CatchAllEmailDomainEntry")
|
||||
.padding(horizontal = 16.dp),
|
||||
|
@ -1118,12 +1129,13 @@ private fun ColumnScope.RandomWordTypeContent(
|
|||
private fun RandomWordCapitalizeToggleItem(
|
||||
capitalize: Boolean,
|
||||
onRandomWordCapitalizeToggleChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
label = stringResource(id = R.string.capitalize),
|
||||
isChecked = capitalize,
|
||||
onCheckedChange = onRandomWordCapitalizeToggleChange,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("CapitalizeRandomWordUsernameToggle")
|
||||
.padding(horizontal = 16.dp),
|
||||
|
@ -1134,12 +1146,13 @@ private fun RandomWordCapitalizeToggleItem(
|
|||
private fun RandomWordIncludeNumberToggleItem(
|
||||
includeNumber: Boolean,
|
||||
onRandomWordIncludeNumberToggleChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
BitwardenSwitch(
|
||||
label = stringResource(id = R.string.include_number),
|
||||
isChecked = includeNumber,
|
||||
onCheckedChange = onRandomWordIncludeNumberToggleChange,
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.testTag("IncludeNumberRandomWordUsernameToggle")
|
||||
.padding(horizontal = 16.dp),
|
||||
|
@ -1150,7 +1163,7 @@ private fun RandomWordIncludeNumberToggleItem(
|
|||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun GeneratorPreview() {
|
||||
private fun Generator_preview() {
|
||||
BitwardenTheme {
|
||||
GeneratorScreen(
|
||||
onNavigateToPasswordHistory = {},
|
||||
|
@ -1158,404 +1171,3 @@ private fun GeneratorPreview() {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to password configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
private data class PasswordHandlers(
|
||||
val onPasswordSliderLengthChange: (Int, Boolean) -> Unit,
|
||||
val onPasswordToggleCapitalLettersChange: (Boolean) -> Unit,
|
||||
val onPasswordToggleLowercaseLettersChange: (Boolean) -> Unit,
|
||||
val onPasswordToggleNumbersChange: (Boolean) -> Unit,
|
||||
val onPasswordToggleSpecialCharactersChange: (Boolean) -> Unit,
|
||||
val onPasswordMinNumbersCounterChange: (Int) -> Unit,
|
||||
val onPasswordMinSpecialCharactersChange: (Int) -> Unit,
|
||||
val onPasswordToggleAvoidAmbiguousCharsChange: (Boolean) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
@Suppress("LongMethod")
|
||||
fun create(viewModel: GeneratorViewModel): PasswordHandlers {
|
||||
return PasswordHandlers(
|
||||
onPasswordSliderLengthChange = { newLength, isUserInteracting ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.SliderLengthChange(
|
||||
length = newLength,
|
||||
isUserInteracting = isUserInteracting,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleCapitalLettersChange = { shouldUseCapitals ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleCapitalLettersChange(
|
||||
useCapitals = shouldUseCapitals,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleLowercaseLettersChange = { shouldUseLowercase ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleLowercaseLettersChange(
|
||||
useLowercase = shouldUseLowercase,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleNumbersChange = { shouldUseNumbers ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleNumbersChange(
|
||||
useNumbers = shouldUseNumbers,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleSpecialCharactersChange = { shouldUseSpecialChars ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleSpecialCharactersChange(
|
||||
useSpecialChars = shouldUseSpecialChars,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordMinNumbersCounterChange = { newMinNumbers ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.MinNumbersCounterChange(
|
||||
minNumbers = newMinNumbers,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordMinSpecialCharactersChange = { newMinSpecial ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.MinSpecialCharactersChange(
|
||||
minSpecial = newMinSpecial,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleAvoidAmbiguousCharsChange = { shouldAvoidAmbiguousChars ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleAvoidAmbigousCharactersChange(
|
||||
avoidAmbiguousChars = shouldAvoidAmbiguousChars,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to passphrase configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
private data class PassphraseHandlers(
|
||||
val onPassphraseNumWordsCounterChange: (Int) -> Unit,
|
||||
val onPassphraseWordSeparatorChange: (Char?) -> Unit,
|
||||
val onPassphraseCapitalizeToggleChange: (Boolean) -> Unit,
|
||||
val onPassphraseIncludeNumberToggleChange: (Boolean) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
fun create(viewModel: GeneratorViewModel): PassphraseHandlers {
|
||||
return PassphraseHandlers(
|
||||
onPassphraseNumWordsCounterChange = { changeInCounter ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Passphrase.NumWordsCounterChange(
|
||||
numWords = changeInCounter,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPassphraseWordSeparatorChange = { newSeparator ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Passphrase.WordSeparatorTextChange(
|
||||
wordSeparator = newSeparator,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPassphraseCapitalizeToggleChange = { shouldCapitalize ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Passphrase.ToggleCapitalizeChange(
|
||||
capitalize = shouldCapitalize,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPassphraseIncludeNumberToggleChange = { shouldIncludeNumber ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Passphrase.ToggleIncludeNumberChange(
|
||||
includeNumber = shouldIncludeNumber,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to all username configurations.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
private data class UsernameTypeHandlers(
|
||||
val onUsernameTooltipClicked: () -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
fun create(viewModel: GeneratorViewModel): UsernameTypeHandlers {
|
||||
return UsernameTypeHandlers(
|
||||
onUsernameTooltipClicked = {
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Username.UsernameType.TooltipClick,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to forwarded email alias
|
||||
* configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
private data class ForwardedEmailAliasHandlers(
|
||||
val onServiceChange: (ServiceTypeOption) -> Unit,
|
||||
val onAddyIoAccessTokenTextChange: (String) -> Unit,
|
||||
val onAddyIoDomainNameTextChange: (String) -> Unit,
|
||||
val onDuckDuckGoApiKeyTextChange: (String) -> Unit,
|
||||
val onFastMailApiKeyTextChange: (String) -> Unit,
|
||||
val onFirefoxRelayAccessTokenTextChange: (String) -> Unit,
|
||||
val onForwardEmailApiKeyTextChange: (String) -> Unit,
|
||||
val onForwardEmailDomainNameTextChange: (String) -> Unit,
|
||||
val onSimpleLoginApiKeyTextChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
@Suppress("LongMethod")
|
||||
fun create(viewModel: GeneratorViewModel): ForwardedEmailAliasHandlers {
|
||||
return ForwardedEmailAliasHandlers(
|
||||
onServiceChange = { newServiceTypeOption ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceTypeOptionSelect(
|
||||
serviceTypeOption = newServiceTypeOption,
|
||||
),
|
||||
)
|
||||
},
|
||||
onAddyIoAccessTokenTextChange = { newAccessToken ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.AccessTokenTextChange(
|
||||
accessToken = newAccessToken,
|
||||
),
|
||||
)
|
||||
},
|
||||
onAddyIoDomainNameTextChange = { newDomainName ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.DomainTextChange(
|
||||
domain = newDomainName,
|
||||
),
|
||||
)
|
||||
},
|
||||
onDuckDuckGoApiKeyTextChange = { newApiKey ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.DuckDuckGo
|
||||
.ApiKeyTextChange(
|
||||
apiKey = newApiKey,
|
||||
),
|
||||
)
|
||||
},
|
||||
onFastMailApiKeyTextChange = { newApiKey ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.FastMail
|
||||
.ApiKeyTextChange(
|
||||
apiKey = newApiKey,
|
||||
),
|
||||
)
|
||||
},
|
||||
onFirefoxRelayAccessTokenTextChange = { newAccessToken ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.FirefoxRelay
|
||||
.AccessTokenTextChange(
|
||||
accessToken = newAccessToken,
|
||||
),
|
||||
)
|
||||
},
|
||||
onForwardEmailApiKeyTextChange = { newApiKey ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ForwardEmail
|
||||
.ApiKeyTextChange(
|
||||
apiKey = newApiKey,
|
||||
),
|
||||
)
|
||||
},
|
||||
onForwardEmailDomainNameTextChange = { newDomainName ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ForwardEmail
|
||||
.DomainNameTextChange(
|
||||
domainName = newDomainName,
|
||||
),
|
||||
)
|
||||
},
|
||||
onSimpleLoginApiKeyTextChange = { newApiKey ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.SimpleLogin
|
||||
.ApiKeyTextChange(
|
||||
apiKey = newApiKey,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to plus addressed email
|
||||
* configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
private data class PlusAddressedEmailHandlers(
|
||||
val onEmailChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
fun create(viewModel: GeneratorViewModel): PlusAddressedEmailHandlers {
|
||||
return PlusAddressedEmailHandlers(
|
||||
onEmailChange = { newEmail ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.PlusAddressedEmail
|
||||
.EmailTextChange(
|
||||
email = newEmail,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to plus addressed email
|
||||
* configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
private data class CatchAllEmailHandlers(
|
||||
val onDomainChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
fun create(viewModel: GeneratorViewModel): CatchAllEmailHandlers {
|
||||
return CatchAllEmailHandlers(
|
||||
onDomainChange = { newDomain ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.CatchAllEmail
|
||||
.DomainTextChange(
|
||||
domain = newDomain,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to Random Word
|
||||
* configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
private data class RandomWordHandlers(
|
||||
val onCapitalizeChange: (Boolean) -> Unit,
|
||||
val onIncludeNumberChange: (Boolean) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
fun create(viewModel: GeneratorViewModel): RandomWordHandlers {
|
||||
return RandomWordHandlers(
|
||||
onCapitalizeChange = { shouldCapitalize ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.RandomWord
|
||||
.ToggleCapitalizeChange(
|
||||
capitalize = shouldCapitalize,
|
||||
),
|
||||
)
|
||||
},
|
||||
onIncludeNumberChange = { shouldIncludeNumber ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.RandomWord
|
||||
.ToggleIncludeNumberChange(
|
||||
includeNumber = shouldIncludeNumber,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package com.x8bit.bitwarden.ui.tools.feature.generator.handlers
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorViewModel
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorAction.MainType.Username.UsernameType.CatchAllEmail as CatchAllEmailAction
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to plus addressed email
|
||||
* configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
data class CatchAllEmailHandlers(
|
||||
val onDomainChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Creates an instance of [CatchAllEmailHandlers] by binding actions to the provided
|
||||
* [GeneratorViewModel].
|
||||
*/
|
||||
fun create(
|
||||
viewModel: GeneratorViewModel,
|
||||
): CatchAllEmailHandlers = CatchAllEmailHandlers(
|
||||
onDomainChange = { newDomain ->
|
||||
viewModel.trySendAction(CatchAllEmailAction.DomainTextChange(domain = newDomain))
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remember a [CatchAllEmailHandlers] instance in a [Composable] scope.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberCatchAllEmailHandlers(viewModel: GeneratorViewModel): CatchAllEmailHandlers =
|
||||
remember(viewModel) {
|
||||
CatchAllEmailHandlers.create(viewModel = viewModel)
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package com.x8bit.bitwarden.ui.tools.feature.generator.handlers
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorViewModel
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias as ForwardedEmailAliasAction
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to forwarded email alias
|
||||
* configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
data class ForwardedEmailAliasHandlers(
|
||||
val onServiceChange: (ForwardedEmailAlias.ServiceTypeOption) -> Unit,
|
||||
val onAddyIoAccessTokenTextChange: (String) -> Unit,
|
||||
val onAddyIoDomainNameTextChange: (String) -> Unit,
|
||||
val onDuckDuckGoApiKeyTextChange: (String) -> Unit,
|
||||
val onFastMailApiKeyTextChange: (String) -> Unit,
|
||||
val onFirefoxRelayAccessTokenTextChange: (String) -> Unit,
|
||||
val onForwardEmailApiKeyTextChange: (String) -> Unit,
|
||||
val onForwardEmailDomainNameTextChange: (String) -> Unit,
|
||||
val onSimpleLoginApiKeyTextChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Creates an instance of [ForwardedEmailAliasHandlers] by binding actions to the provided
|
||||
* [GeneratorViewModel].
|
||||
*/
|
||||
fun create(
|
||||
viewModel: GeneratorViewModel,
|
||||
): ForwardedEmailAliasHandlers = ForwardedEmailAliasHandlers(
|
||||
onServiceChange = { newServiceTypeOption ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.ServiceTypeOptionSelect(
|
||||
serviceTypeOption = newServiceTypeOption,
|
||||
),
|
||||
)
|
||||
},
|
||||
onAddyIoAccessTokenTextChange = { newAccessToken ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.AddyIo.AccessTokenTextChange(
|
||||
accessToken = newAccessToken,
|
||||
),
|
||||
)
|
||||
},
|
||||
onAddyIoDomainNameTextChange = { newDomainName ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.AddyIo.DomainTextChange(domain = newDomainName),
|
||||
)
|
||||
},
|
||||
onDuckDuckGoApiKeyTextChange = { newApiKey ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.DuckDuckGo.ApiKeyTextChange(apiKey = newApiKey),
|
||||
)
|
||||
},
|
||||
onFastMailApiKeyTextChange = { newApiKey ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.FastMail.ApiKeyTextChange(apiKey = newApiKey),
|
||||
)
|
||||
},
|
||||
onFirefoxRelayAccessTokenTextChange = { newAccessToken ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.FirefoxRelay.AccessTokenTextChange(
|
||||
accessToken = newAccessToken,
|
||||
),
|
||||
)
|
||||
},
|
||||
onForwardEmailApiKeyTextChange = { newApiKey ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.ForwardEmail.ApiKeyTextChange(apiKey = newApiKey),
|
||||
)
|
||||
},
|
||||
onForwardEmailDomainNameTextChange = { newDomainName ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.ForwardEmail.DomainNameTextChange(
|
||||
domainName = newDomainName,
|
||||
),
|
||||
)
|
||||
},
|
||||
onSimpleLoginApiKeyTextChange = { newApiKey ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.SimpleLogin.ApiKeyTextChange(apiKey = newApiKey),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remember a [ForwardedEmailAliasHandlers] instance in a [Composable] scope.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberForwardedEmailAliasHandlers(
|
||||
viewModel: GeneratorViewModel,
|
||||
): ForwardedEmailAliasHandlers =
|
||||
remember(viewModel) {
|
||||
ForwardedEmailAliasHandlers.create(viewModel = viewModel)
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.x8bit.bitwarden.ui.tools.feature.generator.handlers
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorAction
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorViewModel
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to passphrase configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
data class PassphraseHandlers(
|
||||
val onPassphraseNumWordsCounterChange: (Int) -> Unit,
|
||||
val onPassphraseWordSeparatorChange: (Char?) -> Unit,
|
||||
val onPassphraseCapitalizeToggleChange: (Boolean) -> Unit,
|
||||
val onPassphraseIncludeNumberToggleChange: (Boolean) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Creates an instance of [PassphraseHandlers] by binding actions to the provided
|
||||
* [GeneratorViewModel].
|
||||
*/
|
||||
fun create(
|
||||
viewModel: GeneratorViewModel,
|
||||
): PassphraseHandlers = PassphraseHandlers(
|
||||
onPassphraseNumWordsCounterChange = { changeInCounter ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Passphrase.NumWordsCounterChange(
|
||||
numWords = changeInCounter,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPassphraseWordSeparatorChange = { newSeparator ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Passphrase.WordSeparatorTextChange(
|
||||
wordSeparator = newSeparator,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPassphraseCapitalizeToggleChange = { shouldCapitalize ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Passphrase.ToggleCapitalizeChange(
|
||||
capitalize = shouldCapitalize,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPassphraseIncludeNumberToggleChange = { shouldIncludeNumber ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Passphrase.ToggleIncludeNumberChange(
|
||||
includeNumber = shouldIncludeNumber,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remember a [PassphraseHandlers] instance in a [Composable] scope.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberPassphraseHandlers(viewModel: GeneratorViewModel): PassphraseHandlers =
|
||||
remember(viewModel) {
|
||||
PassphraseHandlers.create(viewModel = viewModel)
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package com.x8bit.bitwarden.ui.tools.feature.generator.handlers
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorAction
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorViewModel
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to password configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
data class PasswordHandlers(
|
||||
val onPasswordSliderLengthChange: (Int, Boolean) -> Unit,
|
||||
val onPasswordToggleCapitalLettersChange: (Boolean) -> Unit,
|
||||
val onPasswordToggleLowercaseLettersChange: (Boolean) -> Unit,
|
||||
val onPasswordToggleNumbersChange: (Boolean) -> Unit,
|
||||
val onPasswordToggleSpecialCharactersChange: (Boolean) -> Unit,
|
||||
val onPasswordMinNumbersCounterChange: (Int) -> Unit,
|
||||
val onPasswordMinSpecialCharactersChange: (Int) -> Unit,
|
||||
val onPasswordToggleAvoidAmbiguousCharsChange: (Boolean) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Creates an instance of [PasswordHandlers] by binding actions to the provided
|
||||
* [GeneratorViewModel].
|
||||
*/
|
||||
fun create(
|
||||
viewModel: GeneratorViewModel,
|
||||
): PasswordHandlers = PasswordHandlers(
|
||||
onPasswordSliderLengthChange = { newLength, isUserInteracting ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.SliderLengthChange(
|
||||
length = newLength,
|
||||
isUserInteracting = isUserInteracting,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleCapitalLettersChange = { shouldUseCapitals ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleCapitalLettersChange(
|
||||
useCapitals = shouldUseCapitals,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleLowercaseLettersChange = { shouldUseLowercase ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleLowercaseLettersChange(
|
||||
useLowercase = shouldUseLowercase,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleNumbersChange = { shouldUseNumbers ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleNumbersChange(
|
||||
useNumbers = shouldUseNumbers,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleSpecialCharactersChange = { shouldUseSpecialChars ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleSpecialCharactersChange(
|
||||
useSpecialChars = shouldUseSpecialChars,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordMinNumbersCounterChange = { newMinNumbers ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.MinNumbersCounterChange(
|
||||
minNumbers = newMinNumbers,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordMinSpecialCharactersChange = { newMinSpecial ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.MinSpecialCharactersChange(
|
||||
minSpecial = newMinSpecial,
|
||||
),
|
||||
)
|
||||
},
|
||||
onPasswordToggleAvoidAmbiguousCharsChange = { shouldAvoidAmbiguousChars ->
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction.MainType.Password.ToggleAvoidAmbigousCharactersChange(
|
||||
avoidAmbiguousChars = shouldAvoidAmbiguousChars,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remember a [PasswordHandlers] instance in a [Composable] scope.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberPasswordHandlers(viewModel: GeneratorViewModel): PasswordHandlers =
|
||||
remember(viewModel) {
|
||||
PasswordHandlers.create(viewModel = viewModel)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.x8bit.bitwarden.ui.tools.feature.generator.handlers
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorViewModel
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorAction.MainType.Username.UsernameType.PlusAddressedEmail as PlusAddressedEmailAction
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to plus addressed email
|
||||
* configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
data class PlusAddressedEmailHandlers(
|
||||
val onEmailChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Creates an instance of [PlusAddressedEmailHandlers] by binding actions to the provided
|
||||
* [GeneratorViewModel].
|
||||
*/
|
||||
fun create(viewModel: GeneratorViewModel): PlusAddressedEmailHandlers =
|
||||
PlusAddressedEmailHandlers(
|
||||
onEmailChange = { newEmail ->
|
||||
viewModel.trySendAction(
|
||||
PlusAddressedEmailAction.EmailTextChange(email = newEmail),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remember a [PlusAddressedEmailHandlers] instance in a [Composable] scope.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberPlusAddressedEmailHandlers(viewModel: GeneratorViewModel): PlusAddressedEmailHandlers =
|
||||
remember(viewModel) {
|
||||
PlusAddressedEmailHandlers.create(viewModel = viewModel)
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.x8bit.bitwarden.ui.tools.feature.generator.handlers
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorViewModel
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorAction.MainType.Username.UsernameType.RandomWord as RandomWordAction
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to Random Word
|
||||
* configuration.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
data class RandomWordHandlers(
|
||||
val onCapitalizeChange: (Boolean) -> Unit,
|
||||
val onIncludeNumberChange: (Boolean) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Creates an instance of [RandomWordHandlers] by binding actions to the provided
|
||||
* [GeneratorViewModel].
|
||||
*/
|
||||
fun create(
|
||||
viewModel: GeneratorViewModel,
|
||||
): RandomWordHandlers = RandomWordHandlers(
|
||||
onCapitalizeChange = { shouldCapitalize ->
|
||||
viewModel.trySendAction(
|
||||
RandomWordAction.ToggleCapitalizeChange(capitalize = shouldCapitalize),
|
||||
)
|
||||
},
|
||||
onIncludeNumberChange = { shouldIncludeNumber ->
|
||||
viewModel.trySendAction(
|
||||
RandomWordAction.ToggleIncludeNumberChange(includeNumber = shouldIncludeNumber),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remember a [RandomWordHandlers] instance in a [Composable] scope.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberRandomWordHandlers(viewModel: GeneratorViewModel): RandomWordHandlers =
|
||||
remember(viewModel) {
|
||||
RandomWordHandlers.create(viewModel = viewModel)
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.x8bit.bitwarden.ui.tools.feature.generator.handlers
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorAction
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorViewModel
|
||||
|
||||
/**
|
||||
* A class dedicated to handling user interactions related to all username configurations.
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
data class UsernameTypeHandlers(
|
||||
val onUsernameTooltipClicked: () -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Creates an instance of [UsernameTypeHandlers] by binding actions to the provided
|
||||
* [GeneratorViewModel].
|
||||
*/
|
||||
fun create(
|
||||
viewModel: GeneratorViewModel,
|
||||
): UsernameTypeHandlers = UsernameTypeHandlers(
|
||||
onUsernameTooltipClicked = {
|
||||
viewModel.trySendAction(GeneratorAction.MainType.Username.UsernameType.TooltipClick)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to remember a [UsernameTypeHandlers] instance in a [Composable] scope.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberUsernameTypeHandlers(viewModel: GeneratorViewModel): UsernameTypeHandlers =
|
||||
remember(viewModel) {
|
||||
UsernameTypeHandlers.create(viewModel = viewModel)
|
||||
}
|
Loading…
Reference in a new issue