mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 18:58:59 +03:00
BIT-711: Adding UI for AddyIo service (#456)
This commit is contained in:
parent
5ec810d4d6
commit
78461394f3
4 changed files with 367 additions and 19 deletions
|
@ -817,6 +817,7 @@ private fun UsernameOptionsItem(
|
|||
|
||||
//region ForwardedEmailAliasType Composables
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun ColumnScope.ForwardedEmailAliasTypeContent(
|
||||
usernameTypeState: GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias,
|
||||
|
@ -833,8 +834,26 @@ private fun ColumnScope.ForwardedEmailAliasTypeContent(
|
|||
|
||||
when (usernameTypeState.selectedServiceType) {
|
||||
|
||||
is ServiceType.AnonAddy -> {
|
||||
// TODO: AnonAddy Service Implementation (BIT-711)
|
||||
is ServiceType.AddyIo -> {
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = R.string.api_access_token),
|
||||
value = usernameTypeState.selectedServiceType.apiAccessToken,
|
||||
onValueChange = forwardedEmailAliasHandlers.onAddyIoAccessTokenTextChange,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.domain_name_required_parenthesis),
|
||||
value = usernameTypeState.selectedServiceType.domainName,
|
||||
onValueChange = forwardedEmailAliasHandlers.onAddyIoDomainNameTextChange,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
|
||||
is ServiceType.DuckDuckGo -> {
|
||||
|
@ -1185,10 +1204,13 @@ private class PassphraseHandlers(
|
|||
*/
|
||||
private class ForwardedEmailAliasHandlers(
|
||||
val onServiceChange: (ServiceTypeOption) -> Unit,
|
||||
val onAddyIoAccessTokenTextChange: (String) -> Unit,
|
||||
val onAddyIoDomainNameTextChange: (String) -> Unit,
|
||||
val onDuckDuckGoApiKeyTextChange: (String) -> Unit,
|
||||
val onFirefoxRelayAccessTokenTextChange: (String) -> Unit,
|
||||
) {
|
||||
companion object {
|
||||
@Suppress("LongMethod")
|
||||
fun create(viewModel: GeneratorViewModel): ForwardedEmailAliasHandlers {
|
||||
return ForwardedEmailAliasHandlers(
|
||||
onServiceChange = { newServiceTypeOption ->
|
||||
|
@ -1203,6 +1225,32 @@ private class ForwardedEmailAliasHandlers(
|
|||
),
|
||||
)
|
||||
},
|
||||
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
|
||||
|
@ -1227,7 +1275,6 @@ private class ForwardedEmailAliasHandlers(
|
|||
.AccessTokenTextChange(
|
||||
accessToken = newAccessToken,
|
||||
),
|
||||
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
@ -22,8 +22,11 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Pa
|
|||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.CatchAllEmail
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.AddyIo
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.DuckDuckGo
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.FastMail
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.FirefoxRelay
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.SimpleLogin
|
||||
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.PlusAddressedEmail
|
||||
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.RandomWord
|
||||
|
@ -115,6 +118,10 @@ class GeneratorViewModel @Inject constructor(
|
|||
handleServiceTypeOptionSelect(action)
|
||||
}
|
||||
|
||||
is GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias.AddyIo -> {
|
||||
handleAddyIoSpecificAction(action)
|
||||
}
|
||||
|
||||
is GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias.DuckDuckGo.ApiKeyTextChange -> {
|
||||
handleDuckDuckGoTextInputChange(action)
|
||||
}
|
||||
|
@ -554,15 +561,15 @@ class GeneratorViewModel @Inject constructor(
|
|||
)
|
||||
|
||||
Username.UsernameTypeOption.CATCH_ALL_EMAIL -> loadUsernameOptions(
|
||||
selectedType = Username(selectedType = Username.UsernameType.CatchAllEmail()),
|
||||
selectedType = Username(selectedType = CatchAllEmail()),
|
||||
)
|
||||
|
||||
Username.UsernameTypeOption.FORWARDED_EMAIL_ALIAS -> loadUsernameOptions(
|
||||
selectedType = Username(selectedType = Username.UsernameType.ForwardedEmailAlias()),
|
||||
selectedType = Username(selectedType = ForwardedEmailAlias()),
|
||||
)
|
||||
|
||||
Username.UsernameTypeOption.RANDOM_WORD -> loadUsernameOptions(
|
||||
selectedType = Username(selectedType = Username.UsernameType.RandomWord()),
|
||||
selectedType = Username(selectedType = RandomWord()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -580,30 +587,92 @@ class GeneratorViewModel @Inject constructor(
|
|||
.ServiceTypeOptionSelect,
|
||||
) {
|
||||
when (action.serviceTypeOption) {
|
||||
ForwardedEmailAlias.ServiceTypeOption.ANON_ADDY -> updateForwardedEmailAliasType {
|
||||
ForwardedEmailAlias(selectedServiceType = ServiceType.AnonAddy())
|
||||
ForwardedEmailAlias.ServiceTypeOption.ADDY_IO -> updateForwardedEmailAliasType {
|
||||
ForwardedEmailAlias(selectedServiceType = AddyIo())
|
||||
}
|
||||
|
||||
ForwardedEmailAlias.ServiceTypeOption.DUCK_DUCK_GO -> updateForwardedEmailAliasType {
|
||||
ForwardedEmailAlias(selectedServiceType = ServiceType.DuckDuckGo())
|
||||
ForwardedEmailAlias(selectedServiceType = DuckDuckGo())
|
||||
}
|
||||
|
||||
ForwardedEmailAlias.ServiceTypeOption.FAST_MAIL -> updateForwardedEmailAliasType {
|
||||
ForwardedEmailAlias(selectedServiceType = ServiceType.FastMail())
|
||||
ForwardedEmailAlias(selectedServiceType = FastMail())
|
||||
}
|
||||
|
||||
ForwardedEmailAlias.ServiceTypeOption.FIREFOX_RELAY -> updateForwardedEmailAliasType {
|
||||
ForwardedEmailAlias(selectedServiceType = ServiceType.FirefoxRelay())
|
||||
ForwardedEmailAlias(selectedServiceType = FirefoxRelay())
|
||||
}
|
||||
|
||||
ForwardedEmailAlias.ServiceTypeOption.SIMPLE_LOGIN -> updateForwardedEmailAliasType {
|
||||
ForwardedEmailAlias(selectedServiceType = ServiceType.SimpleLogin())
|
||||
ForwardedEmailAlias(selectedServiceType = SimpleLogin())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion Forwarded Email Alias Specific Handlers
|
||||
|
||||
//region Addy.Io Service Specific Handlers
|
||||
|
||||
private fun handleAddyIoSpecificAction(
|
||||
action: GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias.AddyIo,
|
||||
) {
|
||||
when (action) {
|
||||
is GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.AccessTokenTextChange,
|
||||
-> {
|
||||
handleAddyIoAccessTokenTextChange(action)
|
||||
}
|
||||
|
||||
is GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.DomainTextChange,
|
||||
-> {
|
||||
handleAddyIoDomainNameTextChange(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAddyIoAccessTokenTextChange(
|
||||
action: GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.AccessTokenTextChange,
|
||||
) {
|
||||
updateAddyIoServiceType { addyIoServiceType ->
|
||||
val newAccessToken = action.accessToken
|
||||
addyIoServiceType.copy(apiAccessToken = newAccessToken)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAddyIoDomainNameTextChange(
|
||||
action: GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.DomainTextChange,
|
||||
) {
|
||||
updateAddyIoServiceType { addyIoServiceType ->
|
||||
val newDomain = action.domain
|
||||
addyIoServiceType.copy(domainName = newDomain)
|
||||
}
|
||||
}
|
||||
|
||||
//endregion Addy.Io Service Specific Handlers
|
||||
|
||||
//region DuckDuckGo Service Specific Handlers
|
||||
|
||||
private fun handleDuckDuckGoTextInputChange(
|
||||
|
@ -800,6 +869,30 @@ class GeneratorViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private inline fun updateAddyIoServiceType(
|
||||
crossinline block: (AddyIo) -> AddyIo,
|
||||
) {
|
||||
updateGeneratorMainTypeUsername { currentUsernameType ->
|
||||
if (currentUsernameType.selectedType !is ForwardedEmailAlias) {
|
||||
return@updateGeneratorMainTypeUsername currentUsernameType
|
||||
}
|
||||
|
||||
val currentServiceType = (currentUsernameType.selectedType).selectedServiceType
|
||||
if (currentServiceType !is AddyIo) {
|
||||
return@updateGeneratorMainTypeUsername currentUsernameType
|
||||
}
|
||||
|
||||
val updatedServiceType = block(currentServiceType)
|
||||
|
||||
currentUsernameType.copy(
|
||||
selectedType = ForwardedEmailAlias(
|
||||
selectedServiceType = updatedServiceType,
|
||||
obfuscatedText = currentUsernameType.selectedType.obfuscatedText,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun updateDuckDuckGoServiceType(
|
||||
crossinline block: (DuckDuckGo) -> DuckDuckGo,
|
||||
) {
|
||||
|
@ -1173,7 +1266,7 @@ data class GeneratorState(
|
|||
* the label for each type.
|
||||
*/
|
||||
enum class ServiceTypeOption(val labelRes: Int) {
|
||||
ANON_ADDY(R.string.addy_io),
|
||||
ADDY_IO(R.string.addy_io),
|
||||
DUCK_DUCK_GO(R.string.duck_duck_go),
|
||||
FAST_MAIL(R.string.fastmail),
|
||||
FIREFOX_RELAY(R.string.firefox_relay),
|
||||
|
@ -1195,19 +1288,19 @@ data class GeneratorState(
|
|||
abstract val displayStringResId: Int?
|
||||
|
||||
/**
|
||||
* Represents the Anon Addy service type, with a configurable option for
|
||||
* Represents the Addy Io service type, with a configurable option for
|
||||
* service and api key.
|
||||
*
|
||||
* @property apiAccessToken The token used for generation.
|
||||
* @property domainName The domain name used for generation.
|
||||
*/
|
||||
@Parcelize
|
||||
data class AnonAddy(
|
||||
data class AddyIo(
|
||||
val apiAccessToken: String = "",
|
||||
val domainName: String = "",
|
||||
) : ServiceType(), Parcelable {
|
||||
override val displayStringResId: Int
|
||||
get() = ServiceTypeOption.ANON_ADDY.labelRes
|
||||
get() = ServiceTypeOption.ADDY_IO.labelRes
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1498,6 +1591,26 @@ sealed class GeneratorAction {
|
|||
.ServiceTypeOption,
|
||||
) : ForwardedEmailAlias()
|
||||
|
||||
/**
|
||||
* Represents actions specifically related to the AddyIo service.
|
||||
*/
|
||||
sealed class AddyIo : ForwardedEmailAlias() {
|
||||
|
||||
/**
|
||||
* Fired when the access token input text is changed.
|
||||
*
|
||||
* @property accessToken The new access token text.
|
||||
*/
|
||||
data class AccessTokenTextChange(val accessToken: String) : AddyIo()
|
||||
|
||||
/**
|
||||
* Fired when the domain text input is changed.
|
||||
*
|
||||
* @property domain The new domain text.
|
||||
*/
|
||||
data class DomainTextChange(val domain: String) : AddyIo()
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents actions specifically related to the DuckDuckGo service.
|
||||
*/
|
||||
|
|
|
@ -896,7 +896,7 @@ class GeneratorScreenTest : BaseComposeTest() {
|
|||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceTypeOption
|
||||
.ANON_ADDY
|
||||
.ADDY_IO
|
||||
|
||||
// Opens the menu
|
||||
composeTestRule
|
||||
|
@ -927,6 +927,94 @@ class GeneratorScreenTest : BaseComposeTest() {
|
|||
|
||||
//endregion Forwarded Email Alias Tests
|
||||
|
||||
//region Addy.Io Service Type Tests
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in Username_ForwardedEmailAlias_AddyIo state, updating access token text input should send AccessTokenTextChange action`() {
|
||||
updateState(
|
||||
GeneratorState(
|
||||
generatedText = "Placeholder",
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = GeneratorState
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.AddyIo(),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val newAccessToken = "accessToken"
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText("API access token")
|
||||
.performScrollTo()
|
||||
.performTextInput(newAccessToken)
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.AccessTokenTextChange(
|
||||
accessToken = newAccessToken,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in Username_ForwardedEmailAlias_AddyIo state, updating domain name text input should send DomainTextChange action`() {
|
||||
updateState(
|
||||
GeneratorState(
|
||||
generatedText = "Placeholder",
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = GeneratorState
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.AddyIo(),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val newDomainName = "domainName"
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText("Domain name (required)")
|
||||
.performScrollTo()
|
||||
.performTextInput(newDomainName)
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.DomainTextChange(
|
||||
domain = newDomainName,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//endregion Addy.Io Service Type Tests
|
||||
|
||||
//region DuckDuckGo Service Type Tests
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
|
|
|
@ -31,6 +31,9 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
|||
private val forwardedEmailAliasSavedStateHandle =
|
||||
createSavedStateHandleWithState(initialForwardedEmailAliasState)
|
||||
|
||||
private val initialAddyIoState = createAddyIoState()
|
||||
private val addyIoSavedStateHandle = createSavedStateHandleWithState(initialAddyIoState)
|
||||
|
||||
private val initialDuckDuckGoState = createDuckDuckGoState()
|
||||
private val duckDuckGoSavedStateHandle = createSavedStateHandleWithState(initialDuckDuckGoState)
|
||||
|
||||
|
@ -930,7 +933,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
|||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceTypeOption
|
||||
.ANON_ADDY,
|
||||
.ADDY_IO,
|
||||
)
|
||||
|
||||
viewModel.actionChannel.trySend(action)
|
||||
|
@ -948,7 +951,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
|||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.AnonAddy(),
|
||||
.AddyIo(),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -957,6 +960,85 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class AddyIoActions {
|
||||
private val defaultAddyIoState = createAddyIoState()
|
||||
private lateinit var viewModel: GeneratorViewModel
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
viewModel = GeneratorViewModel(addyIoSavedStateHandle, fakeGeneratorRepository)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AccessTokenTextChange should update access token text correctly`() = runTest {
|
||||
val newAccessToken = "newAccessToken"
|
||||
val action = GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.AccessTokenTextChange(
|
||||
accessToken = newAccessToken,
|
||||
)
|
||||
|
||||
viewModel.actionChannel.trySend(action)
|
||||
|
||||
val expectedState = defaultAddyIoState.copy(
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = GeneratorState
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.AddyIo(
|
||||
apiAccessToken = newAccessToken,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(expectedState, viewModel.stateFlow.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `DomainTextChange should update the domain text correctly`() = runTest {
|
||||
val newDomainName = "newDomain"
|
||||
val action = GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.AddyIo
|
||||
.DomainTextChange(
|
||||
domain = newDomainName,
|
||||
)
|
||||
|
||||
viewModel.actionChannel.trySend(action)
|
||||
|
||||
val expectedState = defaultAddyIoState.copy(
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = GeneratorState
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.AddyIo(
|
||||
domainName = newDomainName,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(expectedState, viewModel.stateFlow.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class DuckDuckGoActions {
|
||||
private val defaultDuckDuckGoState = createDuckDuckGoState()
|
||||
|
@ -1253,6 +1335,24 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
|||
),
|
||||
)
|
||||
|
||||
private fun createAddyIoState(
|
||||
generatedText: String = "defaultAddyIo",
|
||||
): GeneratorState =
|
||||
GeneratorState(
|
||||
generatedText = generatedText,
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = GeneratorState
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.AddyIo(),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private fun createDuckDuckGoState(
|
||||
generatedText: String = "defaultDuckDuckGo",
|
||||
): GeneratorState =
|
||||
|
|
Loading…
Add table
Reference in a new issue