parent
31d98eb0a4
commit
f9dd6ff003
|
@ -18,6 +18,7 @@ import co.electriccoin.zcash.ui.design.util.StringResource
|
|||
import co.electriccoin.zcash.ui.design.util.getValue
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@Composable
|
||||
fun Badge(
|
||||
text: StringResource,
|
||||
|
|
|
@ -97,7 +97,7 @@ fun RadioButton(
|
|||
text = state.subtitle.getValue(),
|
||||
style = ZcashTheme.extendedTypography.radioButton,
|
||||
fontWeight = FontWeight.Normal,
|
||||
color = Color(0xFF838385),
|
||||
color = ZcashTheme.zashiColors.textTertiary,
|
||||
modifier =
|
||||
Modifier.padding(
|
||||
bottom = 6.dp,
|
||||
|
|
|
@ -27,7 +27,6 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||
import co.electriccoin.zcash.ui.design.util.getValue
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
|
@ -133,59 +132,9 @@ fun FormTextField(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun FormTextField(
|
||||
state: TextFieldState,
|
||||
modifier: Modifier = Modifier,
|
||||
textStyle: TextStyle = ZcashTheme.extendedTypography.textFieldValue,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||
colors: TextFieldColors =
|
||||
TextFieldDefaults.colors(
|
||||
cursorColor = ZcashTheme.colors.textPrimary,
|
||||
focusedContainerColor = Color.Transparent,
|
||||
unfocusedContainerColor = Color.Transparent,
|
||||
disabledContainerColor = Color.Transparent,
|
||||
errorContainerColor = Color.Transparent,
|
||||
focusedIndicatorColor = Color.Transparent,
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
disabledIndicatorColor = Color.Transparent
|
||||
),
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
shape: Shape = TextFieldDefaults.shape,
|
||||
withBorder: Boolean = true,
|
||||
bringIntoViewRequester: BringIntoViewRequester? = null,
|
||||
minHeight: Dp = ZcashTheme.dimens.textFieldDefaultHeight,
|
||||
testTag: String? = null
|
||||
) {
|
||||
FormTextField(
|
||||
value = state.value.getValue(),
|
||||
error = state.error?.getValue(),
|
||||
enabled = state.isEnabled,
|
||||
onValueChange = state.onValueChange,
|
||||
modifier = modifier,
|
||||
textStyle = textStyle,
|
||||
placeholder = placeholder,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
keyboardOptions = keyboardOptions,
|
||||
colors = colors,
|
||||
keyboardActions = keyboardActions,
|
||||
shape = shape,
|
||||
withBorder = withBorder,
|
||||
bringIntoViewRequester = bringIntoViewRequester,
|
||||
minHeight = minHeight,
|
||||
testTag = testTag,
|
||||
)
|
||||
}
|
||||
|
||||
data class TextFieldState(
|
||||
val value: StringResource,
|
||||
val isEnabled: Boolean = true,
|
||||
val error: StringResource? = null,
|
||||
val isEnabled: Boolean = true,
|
||||
val onValueChange: (String) -> Unit,
|
||||
)
|
||||
|
|
|
@ -17,6 +17,7 @@ data class ZashiColors(
|
|||
val textLightSupport: Color,
|
||||
val surfacePrimary: Color,
|
||||
val bgPrimary: Color,
|
||||
val bgSecondary: Color,
|
||||
val defaultFg: Color,
|
||||
val textTertiary: Color,
|
||||
val textPrimary: Color,
|
||||
|
@ -28,7 +29,10 @@ data class ZashiColors(
|
|||
val btnPrimaryFg: Color,
|
||||
val btnPrimaryFgDisabled: Color,
|
||||
val btnTextFg: Color,
|
||||
val exchangeRateColors: ExchangeRateColors
|
||||
val exchangeRateColors: ExchangeRateColors,
|
||||
val textSupport: Color,
|
||||
val stroke: Color,
|
||||
val divider: Color,
|
||||
)
|
||||
|
||||
internal val LightZashiColorPalette =
|
||||
|
@ -37,6 +41,7 @@ internal val LightZashiColorPalette =
|
|||
textLightSupport = Color(0xFFD9D8CF),
|
||||
surfacePrimary = Color(0xFF282622),
|
||||
bgPrimary = Color(0xFFFFFFFF),
|
||||
bgSecondary = Color(0xFFF4F4F4),
|
||||
defaultFg = Color(0xFFD9D8CF),
|
||||
textPrimary = Color(0xFF231F20),
|
||||
textTertiary = Color(0xFF716C5D),
|
||||
|
@ -48,7 +53,10 @@ internal val LightZashiColorPalette =
|
|||
btnPrimaryFg = Color(0xFFFFFFFF),
|
||||
btnPrimaryFgDisabled = Color(0xFF94907B),
|
||||
btnTextFg = Color(0xFF231F20),
|
||||
exchangeRateColors = LightExchangeRateColorPalette
|
||||
exchangeRateColors = LightExchangeRateColorPalette,
|
||||
textSupport = Color(0xFF94907B),
|
||||
stroke = Color(0xFFD9D8CF),
|
||||
divider = Color(0xFFF7F7F5)
|
||||
)
|
||||
|
||||
internal val DarkZashiColorPalette =
|
||||
|
@ -57,6 +65,7 @@ internal val DarkZashiColorPalette =
|
|||
textLightSupport = Color(0xFFBDBBBC),
|
||||
surfacePrimary = Color(0xFF454243),
|
||||
bgPrimary = Color(0xFF231F20),
|
||||
bgSecondary = Color(0xFF3B3839),
|
||||
defaultFg = Color(0xFFBDBBBC),
|
||||
textPrimary = Color(0xFFE8E8E8),
|
||||
textTertiary = Color(0xFFBDBBBC),
|
||||
|
@ -68,7 +77,10 @@ internal val DarkZashiColorPalette =
|
|||
btnPrimaryFg = Color(0xFF231F20),
|
||||
btnPrimaryFgDisabled = Color(0xFF7E7C7C),
|
||||
btnTextFg = Color(0xFFE8E8E8),
|
||||
exchangeRateColors = DarkExchangeRateColorPalette
|
||||
exchangeRateColors = DarkExchangeRateColorPalette,
|
||||
textSupport = Color(0xFF7E7C7C),
|
||||
stroke = Color(0xFFA7A5A6),
|
||||
divider = Color(0xFF343031)
|
||||
)
|
||||
|
||||
@Suppress("CompositionLocalAllowlist")
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M10,0.5L10,0.5A9.5,9.5 0,0 1,19.5 10L19.5,10A9.5,9.5 0,0 1,10 19.5L10,19.5A9.5,9.5 0,0 1,0.5 10L0.5,10A9.5,9.5 0,0 1,10 0.5z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M10,0.5L10,0.5A9.5,9.5 0,0 1,19.5 10L19.5,10A9.5,9.5 0,0 1,10 19.5L10,19.5A9.5,9.5 0,0 1,0.5 10L0.5,10A9.5,9.5 0,0 1,10 0.5z"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M14.667,6.5L8.25,12.917L5.333,10"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#292927"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
|
@ -4,9 +4,9 @@ package co.electriccoin.zcash.ui.screen.chooseserver
|
|||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
@ -54,7 +54,6 @@ import co.electriccoin.zcash.ui.design.component.Badge
|
|||
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||
import co.electriccoin.zcash.ui.design.component.FormTextField
|
||||
import co.electriccoin.zcash.ui.design.component.LottieProgress
|
||||
import co.electriccoin.zcash.ui.design.component.RadioButton
|
||||
import co.electriccoin.zcash.ui.design.component.RadioButtonCheckedContent
|
||||
|
@ -62,13 +61,14 @@ import co.electriccoin.zcash.ui.design.component.RadioButtonState
|
|||
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
||||
import co.electriccoin.zcash.ui.design.component.TextFieldState
|
||||
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
|
||||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||
import co.electriccoin.zcash.ui.design.util.getValue
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.BottomBar
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.ZashiButton
|
||||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.ZashiTextField
|
||||
|
||||
@Composable
|
||||
fun ChooseServerView(
|
||||
|
@ -145,7 +145,7 @@ private fun ServerLoading() {
|
|||
Text(
|
||||
text = stringResource(id = R.string.choose_server_loading_subtitle),
|
||||
fontSize = 14.sp,
|
||||
color = Color(0xFF646464)
|
||||
color = ZcashTheme.zashiColors.textTertiary
|
||||
)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ private fun LazyListScope.serverListItems(state: ServerListState) {
|
|||
.padding(start = 4.dp, end = 4.dp)
|
||||
.then(
|
||||
if (item.radioButtonState.isChecked) {
|
||||
Modifier.background(Color(0xFFF4F4F6), RoundedCornerShape(12.dp))
|
||||
Modifier.background(ZcashTheme.zashiColors.bgSecondary, RoundedCornerShape(12.dp))
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ private fun LazyListScope.serverListItems(state: ServerListState) {
|
|||
.padding(horizontal = 4.dp)
|
||||
.then(
|
||||
if (item.radioButtonState.isChecked && item.badge == null) {
|
||||
Modifier.background(Color(0xFFF4F4F6), RoundedCornerShape(12.dp))
|
||||
Modifier.background(ZcashTheme.zashiColors.bgSecondary, RoundedCornerShape(12.dp))
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
|
@ -271,7 +271,13 @@ private fun LazyListScope.serverListItems(state: ServerListState) {
|
|||
RadioButtonCheckedContent(item.radioButtonState)
|
||||
} else {
|
||||
Image(
|
||||
painter = painterResource(id = drawable.ic_radio_button_checked_variant),
|
||||
painter = painterResource(
|
||||
id = if (isSystemInDarkTheme()) {
|
||||
drawable.ic_radio_button_checked_variant_dark
|
||||
} else {
|
||||
drawable.ic_radio_button_checked_variant
|
||||
}
|
||||
),
|
||||
contentDescription = item.radioButtonState.text.getValue(),
|
||||
)
|
||||
}
|
||||
|
@ -287,8 +293,7 @@ private fun LazyListScope.serverListItems(state: ServerListState) {
|
|||
if (index != state.servers.lastIndex) {
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(horizontal = 24.dp),
|
||||
color = Color(0xFFF7F7F5),
|
||||
color = ZcashTheme.zashiColors.divider,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
}
|
||||
|
@ -347,7 +352,6 @@ private fun ServerHeader(text: StringResource) {
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun CustomServerRadioButton(
|
||||
state: ServerState.Custom,
|
||||
|
@ -374,7 +378,7 @@ private fun CustomServerRadioButton(
|
|||
AnimatedVisibility(visible = state.radioButtonState.isChecked) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
|
||||
FormTextField(
|
||||
ZashiTextField(
|
||||
state = state.newServerTextFieldState,
|
||||
placeholder = {
|
||||
Text(text = stringResource(R.string.choose_server_textfield_hint))
|
||||
|
|
|
@ -204,16 +204,18 @@ class ChooseServerViewModel(
|
|||
|
||||
private fun onSaveButtonClicked() =
|
||||
viewModelScope.launch {
|
||||
if (isSaveInProgress.value) return@launch
|
||||
|
||||
isSaveInProgress.update { true }
|
||||
val selection = getUserEndpointSelectionOrShowError() ?: return@launch
|
||||
try {
|
||||
persistEndpoint(selection)
|
||||
} catch (e: PersistEndpointException) {
|
||||
showValidationErrorDialog(e.message)
|
||||
if (isSaveInProgress.value) return@launch
|
||||
isSaveInProgress.update { true }
|
||||
val selection = getUserEndpointSelectionOrShowError() ?: return@launch
|
||||
try {
|
||||
persistEndpoint(selection)
|
||||
} catch (e: PersistEndpointException) {
|
||||
showValidationErrorDialog(e.message)
|
||||
}
|
||||
} finally {
|
||||
isSaveInProgress.update { false }
|
||||
}
|
||||
isSaveInProgress.update { false }
|
||||
}
|
||||
|
||||
private fun onConfirmDialogButtonClicked() {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.displayCutoutPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Button
|
||||
|
@ -10,7 +10,6 @@ import androidx.compose.material3.ButtonColors
|
|||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
@ -58,7 +57,13 @@ internal fun ZashiButton(
|
|||
@Composable
|
||||
override fun Loading() {
|
||||
if (enabled && isLoading) {
|
||||
LottieProgress(loadingRes = R.raw.lottie_loading_white)
|
||||
LottieProgress(
|
||||
loadingRes = if (isSystemInDarkTheme()) {
|
||||
R.raw.lottie_loading
|
||||
} else {
|
||||
R.raw.lottie_loading_white
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate
|
||||
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.interaction.InteractionSource
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.text.selection.LocalTextSelectionColors
|
||||
import androidx.compose.foundation.text.selection.TextSelectionColors
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.TextFieldColors
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.graphics.takeOrElse
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.design.component.TextFieldState
|
||||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.design.util.getValue
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
fun ZashiTextField(
|
||||
state: TextFieldState,
|
||||
modifier: Modifier = Modifier,
|
||||
readOnly: Boolean = false,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
label: @Composable (() -> Unit)? = null,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
prefix: @Composable (() -> Unit)? = null,
|
||||
suffix: @Composable (() -> Unit)? = null,
|
||||
supportingText: @Composable (() -> Unit)? = null,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
||||
minLines: Int = 1,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = ZashiTextFieldDefaults.shape,
|
||||
colors: TextFieldColors = ZashiTextFieldDefaults.colors()
|
||||
) {
|
||||
TextFieldInternal(
|
||||
value = state.value.getValue(),
|
||||
onValueChange = state.onValueChange,
|
||||
modifier = modifier then Modifier.border(
|
||||
width = 1.dp,
|
||||
color = ZcashTheme.zashiColors.stroke,
|
||||
shape = ZashiTextFieldDefaults.shape
|
||||
),
|
||||
enabled = state.isEnabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = textStyle,
|
||||
label = label,
|
||||
placeholder = placeholder,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
prefix = prefix,
|
||||
suffix = suffix,
|
||||
supportingText = supportingText,
|
||||
isError = state.error != null,
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
minLines = minLines,
|
||||
interactionSource = interactionSource,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TextFieldInternal(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
enabled: Boolean,
|
||||
readOnly: Boolean,
|
||||
textStyle: TextStyle,
|
||||
label: @Composable (() -> Unit)?,
|
||||
placeholder: @Composable (() -> Unit)?,
|
||||
leadingIcon: @Composable (() -> Unit)?,
|
||||
trailingIcon: @Composable (() -> Unit)?,
|
||||
prefix: @Composable (() -> Unit)?,
|
||||
suffix: @Composable (() -> Unit)?,
|
||||
supportingText: @Composable (() -> Unit)?,
|
||||
isError: Boolean,
|
||||
visualTransformation: VisualTransformation,
|
||||
keyboardOptions: KeyboardOptions,
|
||||
keyboardActions: KeyboardActions,
|
||||
singleLine: Boolean,
|
||||
maxLines: Int,
|
||||
minLines: Int,
|
||||
interactionSource: MutableInteractionSource,
|
||||
shape: Shape,
|
||||
colors: TextFieldColors,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
// If color is not provided via the text style, use content color as a default
|
||||
val textColor = textStyle.color.takeOrElse {
|
||||
colors.textColor(enabled, isError, interactionSource).value
|
||||
}
|
||||
val mergedTextStyle = textStyle.merge(TextStyle(color = textColor))
|
||||
|
||||
CompositionLocalProvider(LocalTextSelectionColors provides colors.selectionColors) {
|
||||
BasicTextField(
|
||||
value = value,
|
||||
modifier = modifier
|
||||
.defaultMinSize(minWidth = TextFieldDefaults.MinWidth),
|
||||
onValueChange = onValueChange,
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = mergedTextStyle,
|
||||
cursorBrush = SolidColor(colors.cursorColor(isError).value),
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
interactionSource = interactionSource,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
minLines = minLines,
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
// places leading icon, text field with label and placeholder, trailing icon
|
||||
TextFieldDefaults.DecorationBox(
|
||||
value = value,
|
||||
visualTransformation = visualTransformation,
|
||||
innerTextField = innerTextField,
|
||||
placeholder = placeholder,
|
||||
label = label,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
prefix = prefix,
|
||||
suffix = suffix,
|
||||
supportingText = supportingText,
|
||||
shape = shape,
|
||||
singleLine = singleLine,
|
||||
enabled = enabled,
|
||||
isError = isError,
|
||||
interactionSource = interactionSource,
|
||||
colors = colors,
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TextFieldColors.textColor(
|
||||
enabled: Boolean,
|
||||
isError: Boolean,
|
||||
interactionSource: InteractionSource
|
||||
): State<Color> {
|
||||
val focused by interactionSource.collectIsFocusedAsState()
|
||||
|
||||
val targetValue = when {
|
||||
!enabled -> disabledTextColor
|
||||
isError -> errorTextColor
|
||||
focused -> focusedTextColor
|
||||
else -> unfocusedTextColor
|
||||
}
|
||||
return rememberUpdatedState(targetValue)
|
||||
}
|
||||
|
||||
private val TextFieldColors.selectionColors: TextSelectionColors
|
||||
@Composable get() = textSelectionColors
|
||||
|
||||
@Composable
|
||||
internal fun TextFieldColors.cursorColor(isError: Boolean): State<Color> {
|
||||
return rememberUpdatedState(if (isError) errorCursorColor else cursorColor)
|
||||
}
|
||||
|
||||
object ZashiTextFieldDefaults {
|
||||
|
||||
val shape: Shape
|
||||
get() = RoundedCornerShape(8.dp)
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
fun colors(
|
||||
focusedTextColor: Color = ZcashTheme.zashiColors.textPrimary,
|
||||
unfocusedTextColor: Color = ZcashTheme.zashiColors.textPrimary,
|
||||
disabledTextColor: Color = ZcashTheme.zashiColors.textPrimary,
|
||||
errorTextColor: Color = Color.Unspecified,
|
||||
focusedContainerColor: Color = if (isSystemInDarkTheme()) {
|
||||
ZcashTheme.zashiColors.bgSecondary
|
||||
} else {
|
||||
ZcashTheme.zashiColors.bgPrimary
|
||||
},
|
||||
unfocusedContainerColor: Color = if (isSystemInDarkTheme()) {
|
||||
ZcashTheme.zashiColors.bgSecondary
|
||||
} else {
|
||||
ZcashTheme.zashiColors.bgPrimary
|
||||
},
|
||||
disabledContainerColor: Color = if (isSystemInDarkTheme()) {
|
||||
ZcashTheme.zashiColors.bgSecondary
|
||||
} else {
|
||||
ZcashTheme.zashiColors.bgPrimary
|
||||
},
|
||||
errorContainerColor: Color = Color.Unspecified,
|
||||
cursorColor: Color = Color.Unspecified,
|
||||
errorCursorColor: Color = Color.Unspecified,
|
||||
selectionColors: TextSelectionColors? = null,
|
||||
focusedIndicatorColor: Color = Color.Transparent,
|
||||
unfocusedIndicatorColor: Color = Color.Transparent,
|
||||
disabledIndicatorColor: Color = Color.Transparent,
|
||||
errorIndicatorColor: Color = Color.Unspecified,
|
||||
focusedLeadingIconColor: Color = Color.Unspecified,
|
||||
unfocusedLeadingIconColor: Color = Color.Unspecified,
|
||||
disabledLeadingIconColor: Color = Color.Unspecified,
|
||||
errorLeadingIconColor: Color = Color.Unspecified,
|
||||
focusedTrailingIconColor: Color = Color.Unspecified,
|
||||
unfocusedTrailingIconColor: Color = Color.Unspecified,
|
||||
disabledTrailingIconColor: Color = Color.Unspecified,
|
||||
errorTrailingIconColor: Color = Color.Unspecified,
|
||||
focusedLabelColor: Color = Color.Unspecified,
|
||||
unfocusedLabelColor: Color = Color.Unspecified,
|
||||
disabledLabelColor: Color = Color.Unspecified,
|
||||
errorLabelColor: Color = Color.Unspecified,
|
||||
focusedPlaceholderColor: Color = ZcashTheme.zashiColors.textSupport,
|
||||
unfocusedPlaceholderColor: Color = ZcashTheme.zashiColors.textSupport,
|
||||
disabledPlaceholderColor: Color = ZcashTheme.zashiColors.textSupport,
|
||||
errorPlaceholderColor: Color = Color.Unspecified,
|
||||
focusedSupportingTextColor: Color = ZcashTheme.zashiColors.textSupport,
|
||||
unfocusedSupportingTextColor: Color = ZcashTheme.zashiColors.textSupport,
|
||||
disabledSupportingTextColor: Color = ZcashTheme.zashiColors.textSupport,
|
||||
errorSupportingTextColor: Color = Color.Unspecified,
|
||||
focusedPrefixColor: Color = Color.Unspecified,
|
||||
unfocusedPrefixColor: Color = Color.Unspecified,
|
||||
disabledPrefixColor: Color = Color.Unspecified,
|
||||
errorPrefixColor: Color = Color.Unspecified,
|
||||
focusedSuffixColor: Color = Color.Unspecified,
|
||||
unfocusedSuffixColor: Color = Color.Unspecified,
|
||||
disabledSuffixColor: Color = Color.Unspecified,
|
||||
errorSuffixColor: Color = Color.Unspecified,
|
||||
): TextFieldColors = TextFieldDefaults.colors(
|
||||
focusedTextColor = focusedTextColor,
|
||||
unfocusedTextColor = unfocusedTextColor,
|
||||
disabledTextColor = disabledTextColor,
|
||||
errorTextColor = errorTextColor,
|
||||
focusedContainerColor = focusedContainerColor,
|
||||
unfocusedContainerColor = unfocusedContainerColor,
|
||||
disabledContainerColor = disabledContainerColor,
|
||||
errorContainerColor = errorContainerColor,
|
||||
cursorColor = cursorColor,
|
||||
errorCursorColor = errorCursorColor,
|
||||
selectionColors = selectionColors,
|
||||
focusedIndicatorColor = focusedIndicatorColor,
|
||||
unfocusedIndicatorColor = unfocusedIndicatorColor,
|
||||
disabledIndicatorColor = disabledIndicatorColor,
|
||||
errorIndicatorColor = errorIndicatorColor,
|
||||
focusedLeadingIconColor = focusedLeadingIconColor,
|
||||
unfocusedLeadingIconColor = unfocusedLeadingIconColor,
|
||||
disabledLeadingIconColor = disabledLeadingIconColor,
|
||||
errorLeadingIconColor = errorLeadingIconColor,
|
||||
focusedTrailingIconColor = focusedTrailingIconColor,
|
||||
unfocusedTrailingIconColor = unfocusedTrailingIconColor,
|
||||
disabledTrailingIconColor = disabledTrailingIconColor,
|
||||
errorTrailingIconColor = errorTrailingIconColor,
|
||||
focusedLabelColor = focusedLabelColor,
|
||||
unfocusedLabelColor = unfocusedLabelColor,
|
||||
disabledLabelColor = disabledLabelColor,
|
||||
errorLabelColor = errorLabelColor,
|
||||
focusedPlaceholderColor = focusedPlaceholderColor,
|
||||
unfocusedPlaceholderColor = unfocusedPlaceholderColor,
|
||||
disabledPlaceholderColor = disabledPlaceholderColor,
|
||||
errorPlaceholderColor = errorPlaceholderColor,
|
||||
focusedSupportingTextColor = focusedSupportingTextColor,
|
||||
unfocusedSupportingTextColor = unfocusedSupportingTextColor,
|
||||
disabledSupportingTextColor = disabledSupportingTextColor,
|
||||
errorSupportingTextColor = errorSupportingTextColor,
|
||||
focusedPrefixColor = focusedPrefixColor,
|
||||
unfocusedPrefixColor = unfocusedPrefixColor,
|
||||
disabledPrefixColor = disabledPrefixColor,
|
||||
errorPrefixColor = errorPrefixColor,
|
||||
focusedSuffixColor = focusedSuffixColor,
|
||||
unfocusedSuffixColor = unfocusedSuffixColor,
|
||||
disabledSuffixColor = disabledSuffixColor,
|
||||
errorSuffixColor = errorSuffixColor,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
@PreviewScreens
|
||||
@Composable
|
||||
private fun ZashiTextFieldPreview() = ZcashTheme {
|
||||
ZashiTextField(
|
||||
state = TextFieldState(
|
||||
value = stringRes("Text")
|
||||
) {}
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue