Skip to content

Commit

Permalink
[#459] Improve code implementation for text fields
Browse files Browse the repository at this point in the history
  • Loading branch information
paulinea committed Apr 11, 2023
1 parent 95c8769 commit 3ac108a
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import com.orange.ods.app.ui.utilities.composable.CodeImplementationColumn
import com.orange.ods.app.ui.utilities.composable.CodeParameter
import com.orange.ods.app.ui.utilities.composable.ComponentCode
import com.orange.ods.app.ui.utilities.composable.ListParameter
import com.orange.ods.app.ui.utilities.composable.ListParameterValue
import com.orange.ods.app.ui.utilities.composable.ObjectInstance
import com.orange.ods.app.ui.utilities.composable.TextValueParameter
import com.orange.ods.compose.component.OdsComponent
import com.orange.ods.compose.component.list.OdsListItem
Expand Down Expand Up @@ -116,10 +116,10 @@ fun MenuExposedDropdown() {
enabled = isEnabled
)

val itemsValues = mutableListOf<ListParameterValue>()
val itemsValues = mutableListOf<ObjectInstance>()
items.forEach { item ->
itemsValues.add(
ListParameterValue(
ObjectInstance(
"OdsExposedDropdownMenuItem",
mutableListOf<CodeParameter>(TextValueParameter.BetweenQuotesParameter("label", item.label)).apply {
if (hasIcons) add(TextValueParameter.Icon)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,22 @@ package com.orange.ods.app.ui.components.textfields
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardCapitalization
import com.orange.ods.app.R
import com.orange.ods.app.ui.components.textfields.TextFieldCustomizationState.Companion.TextFieldMaxChars
import com.orange.ods.app.ui.components.utilities.clickOnElement
import com.orange.ods.app.ui.utilities.composable.CodeImplementationColumn
import com.orange.ods.app.ui.utilities.composable.CodeParameter
import com.orange.ods.app.ui.utilities.composable.ComponentCode
import com.orange.ods.app.ui.utilities.composable.ObjectInstance
import com.orange.ods.app.ui.utilities.composable.ObjectParameter
import com.orange.ods.app.ui.utilities.composable.TextValueParameter
import com.orange.ods.compose.component.OdsComponent
import com.orange.ods.compose.component.textfield.OdsIconTrailing
Expand All @@ -39,89 +44,128 @@ fun TextField(customizationState: TextFieldCustomizationState) {
val modifier = Modifier
.fillMaxWidth()
.padding(top = dimensionResource(id = R.dimen.spacing_s))
val leadingIcon = if (customizationState.hasLeadingIcon) painterResource(id = R.drawable.ic_heart) else null
val enabled = customizationState.isEnabled
val isError = customizationState.isError
val errorMessage = if (customizationState.isError) stringResource(id = R.string.component_text_field_error_message) else null
val value = customizationState.displayedText
val onValueChange: (String) -> Unit = { customizationState.updateText(it) }
val label = stringResource(id = R.string.component_element_label)
val placeholder = stringResource(id = R.string.component_text_field_placeholder)
val singleLine = customizationState.isSingleLine
val keyboardOptions = customizationState.keyboardOptions
val characterCounter: (@Composable () -> Unit)? = if (customizationState.hasCharacterCounter) {
{ TextFieldCharacterCounter(valueLength = customizationState.displayedText.length, enabled = customizationState.isEnabled) }
} else null
val hasTrailing = customizationState.hasTrailingText || customizationState.hasTrailingIcon

Column {
if (hasTrailing) {
OdsTextField(
modifier = modifier,
leadingIcon = leadingIcon,
enabled = enabled,
isError = isError,
errorMessage = errorMessage,
value = value,
onValueChange = onValueChange,
with(customizationState) {
val leadingIcon = if (hasLeadingIcon) painterResource(id = R.drawable.ic_heart) else null
val errorMessage = if (isError) stringResource(id = R.string.component_text_field_error_message) else null
val onValueChange: (String) -> Unit = { updateText(it) }
val label = stringResource(id = R.string.component_element_label)
val placeholder = stringResource(id = R.string.component_text_field_placeholder)
val characterCounter: (@Composable () -> Unit)? = if (hasCharacterCounter) {
{ TextFieldCharacterCounter(valueLength = displayedText.length, enabled = isEnabled) }
} else null
val hasTrailing = hasTrailingText || hasTrailingIcon

Column {
if (hasTrailing) {
OdsTextField(
modifier = modifier,
leadingIcon = leadingIcon,
enabled = isEnabled,
isError = isError,
errorMessage = errorMessage,
value = displayedText,
onValueChange = onValueChange,
label = label,
placeholder = placeholder,
trailing = if (customizationState.hasTrailingIcon) {
OdsIconTrailing(
painter = painterResource(id = R.drawable.ic_eye),
onClick = { clickOnElement(context = context, trailingIconName) })
} else {
OdsTextTrailing(text = "units")
},
singleLine = isSingleLine,
keyboardOptions = keyboardOptions,
characterCounter = characterCounter
)
} else {
OdsTextField(
modifier = modifier,
leadingIcon = leadingIcon,
enabled = isEnabled,
isError = isError,
errorMessage = errorMessage,
value = displayedText,
onValueChange = onValueChange,
label = label,
placeholder = placeholder,
singleLine = isSingleLine,
keyboardOptions = keyboardOptions,
characterCounter = characterCounter
)
}

TextFieldCodeImplementationColumn(
componentName = OdsComponent.OdsTextField.name,
customizationState = customizationState,
label = label,
placeholder = placeholder,
trailing = if (customizationState.hasTrailingIcon) {
OdsIconTrailing(
painter = painterResource(id = R.drawable.ic_eye),
onClick = { clickOnElement(context = context, trailingIconName) })
} else {
OdsTextTrailing(text = "units")
},
singleLine = singleLine,
keyboardOptions = keyboardOptions,
characterCounter = characterCounter
)
} else {
OdsTextField(
modifier = modifier,
leadingIcon = leadingIcon,
enabled = enabled,
isError = isError,
errorMessage = errorMessage,
value = value,
onValueChange = onValueChange,
label = label,
placeholder = placeholder,
singleLine = singleLine,
keyboardOptions = keyboardOptions,
characterCounter = characterCounter
hasTrailing = hasTrailing
)
}
}
}

@Composable
fun TextFieldCharacterCounter(valueLength: Int, enabled: Boolean) {
OdsTextFieldCharacterCounter(
valueLength = valueLength,
maxChars = TextFieldMaxChars,
enabled = enabled
)
}

@Composable
fun TextFieldCodeImplementationColumn(
componentName: String,
customizationState: TextFieldCustomizationState,
label: String,
placeholder: String,
errorMessage: String?,
hasTrailing: Boolean
) {
with(customizationState) {
val capitalizationValue = if (softKeyboardCapitalization.value) KeyboardCapitalization.Characters.toString() else KeyboardCapitalization.None.toString()
CodeImplementationColumn {
ComponentCode(name = OdsComponent.OdsTextField.name, parameters = mutableListOf(
TextValueParameter.BetweenQuotesParameter("value", value),
ComponentCode(name = componentName, parameters = mutableListOf(
TextValueParameter.BetweenQuotesParameter("value", displayedText),
TextValueParameter.LambdaParameter("onValueChange"),
TextValueParameter.Label(label),
TextValueParameter.Placeholder(placeholder),
TextValueParameter.ValueOnlyParameter("keyboardOptions", "<KeyboardOptions>") // TODO
ObjectParameter(
"keyboardOptions", ObjectInstance(
KeyboardOptions::class.java.simpleName, listOf<CodeParameter>(
TextValueParameter.ValueOnlyParameter("capitalization", capitalizationValue),
TextValueParameter.ValueOnlyParameter("keyboardType", softKeyboardType.value.keyboardType.toString()),
TextValueParameter.ValueOnlyParameter("imeAction", softKeyboardAction.value.imeAction.toString())
)
)
)
).apply {
if (leadingIcon != null) add(TextValueParameter.Icon)
if (!enabled) add(TextValueParameter.Enabled(false))
if (hasLeadingIcon) add(TextValueParameter.Icon)
if (!hasVisualisationIcon) add(TextValueParameter.StringRepresentationParameter("visualisationIcon", false))
if (!isEnabled) add(TextValueParameter.Enabled(false))
if (isError) {
add(TextValueParameter.StringRepresentationParameter("isError", true))
errorMessage?.let { add(TextValueParameter.BetweenQuotesParameter("errorMessage", it)) }
}
if (singleLine) add(TextValueParameter.StringRepresentationParameter("singleLine", true))
if (isSingleLine) add(TextValueParameter.StringRepresentationParameter("singleLine", true))
if (hasTrailing) add(TextValueParameter.ValueOnlyParameter("trailing", "<trailing composable>"))
if (characterCounter != null) add(TextValueParameter.ValueOnlyParameter("characterCounter", "<OdsTextFieldCharacterCounter>")) // TODO
if (hasCharacterCounter) {
add(
ObjectParameter(
"characterCounter", ObjectInstance(
OdsComponent.OdsTextFieldCharacterCounter.name, listOf<CodeParameter>(
TextValueParameter.StringRepresentationParameter("valueLength", displayedText.length),
TextValueParameter.Enabled(isEnabled)
)
)
)
)
}
})
}
}
}

@Composable
fun TextFieldCharacterCounter(valueLength: Int, enabled: Boolean) {
OdsTextFieldCharacterCounter(
valueLength = valueLength,
maxChars = TextFieldMaxChars,
enabled = enabled
)
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ package com.orange.ods.app.ui.components.textfields
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardCapitalization
import com.orange.ods.app.R
import com.orange.ods.app.ui.utilities.composable.CodeImplementationColumn
import com.orange.ods.app.ui.utilities.composable.CodeParameter
import com.orange.ods.app.ui.utilities.composable.ComponentCode
import com.orange.ods.app.ui.utilities.composable.ObjectInstance
import com.orange.ods.app.ui.utilities.composable.ObjectParameter
import com.orange.ods.app.ui.utilities.composable.TextValueParameter
import com.orange.ods.compose.component.OdsComponent
import com.orange.ods.compose.component.textfield.password.OdsPasswordTextField
Expand Down Expand Up @@ -52,28 +57,14 @@ fun TextFieldPassword(customizationState: TextFieldCustomizationState) {
} else null
)

CodeImplementationColumn {
ComponentCode(name = OdsComponent.OdsPasswordTextField.name, parameters = mutableListOf(
TextValueParameter.BetweenQuotesParameter("value", displayedText),
TextValueParameter.LambdaParameter("onValueChange"),
TextValueParameter.Label(label),
TextValueParameter.Placeholder(placeholder),
TextValueParameter.ValueOnlyParameter("keyboardOptions", "<KeyboardOptions>") // TODO
).apply {
if (!hasVisualisationIcon) add(TextValueParameter.StringRepresentationParameter("visualisationIcon", false))
if (!isEnabled) add(TextValueParameter.Enabled(false))
if (isError) {
add(TextValueParameter.StringRepresentationParameter("isError", true))
add(TextValueParameter.BetweenQuotesParameter("errorMessage", errorMessage))
}
if (hasCharacterCounter) add(
TextValueParameter.ValueOnlyParameter(
"characterCounter",
"<OdsTextFieldCharacterCounter>"
)
) // TODO
})
}
TextFieldCodeImplementationColumn(
componentName = OdsComponent.OdsPasswordTextField.name,
customizationState = customizationState,
label = label,
placeholder = placeholder,
errorMessage = errorMessage,
hasTrailing = false
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ sealed class TextValueParameter(name: String, val value: String) : CodeParameter
}

class ComposableParameter(name: String, val value: @Composable () -> Unit) : CodeParameter(name)
class ObjectParameter(name: String, val objectInstance: ObjectInstance) : CodeParameter(name)
class ListParameter(name: String, val value: List<ObjectInstance>) : CodeParameter(name)

class ListParameter(name: String, val value: List<ListParameterValue>) : CodeParameter(name)
data class ListParameterValue(val className: String, val parameters: List<CodeParameter>)
data class ObjectInstance(val className: String, val parameters: List<CodeParameter>)


@Composable
Expand Down Expand Up @@ -102,30 +103,7 @@ fun ComponentCode(
ComponentWithContentOnlyCode(name) { content() }
} else {
TechnicalText(text = "$name(")
IndentCodeColumn {
parameters.forEach { parameter ->
when (parameter) {
is TextValueParameter -> TechnicalText(text = "${parameter.name} = ${parameter.value},")
is ComposableParameter -> {
TechnicalText(text = "${parameter.name} = {")
Column(modifier = Modifier.padding(start = dimensionResource(id = R.dimen.spacing_s))) {
parameter.value.invoke()
}
TechnicalText(text = "},")
}
is ListParameter -> {
TechnicalText(text = "${parameter.name} = listOf(")
Column(modifier = Modifier.padding(start = dimensionResource(id = R.dimen.spacing_s))) {
parameter.value.forEach { item ->
ComponentCode(name = item.className, parameters = item.parameters)
}
}
TechnicalText(text = "),")
}
}
}
TechnicalText(text = "//...")
}
ComponentParametersCode(parameters = parameters)

if (content != null) {
TechnicalText(text = ") {")
Expand All @@ -140,6 +118,39 @@ fun ComponentCode(
}
}

@Composable
private fun ComponentParametersCode(parameters: List<CodeParameter>) {
IndentCodeColumn {
parameters.forEach { parameter ->
when (parameter) {
is TextValueParameter -> TechnicalText(text = "${parameter.name} = ${parameter.value},")
is ComposableParameter -> {
TechnicalText(text = "${parameter.name} = {")
IndentCodeColumn {
parameter.value.invoke()
}
TechnicalText(text = "},")
}
is ListParameter -> {
TechnicalText(text = "${parameter.name} = listOf(")
IndentCodeColumn {
parameter.value.forEach { item ->
ComponentCode(name = item.className, parameters = item.parameters)
}
}
TechnicalText(text = "),")
}
is ObjectParameter -> {
TechnicalText(text = "${parameter.name} = ${parameter.objectInstance.className}(")
ComponentParametersCode(parameters = parameter.objectInstance.parameters)
TechnicalText(text = "),")
}
}
}
TechnicalText(text = "//...")
}
}

@Composable
private fun ComponentWithContentOnlyCode(name: String, content: @Composable () -> Unit) {
TechnicalText(text = "$name {")
Expand Down

0 comments on commit 3ac108a

Please sign in to comment.