mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-15 07:28:30 +00:00
Move clearable text field to core module.
This commit is contained in:
committed by
Greyson Parrelli
parent
d9dba89781
commit
155b59d71f
@@ -10,7 +10,6 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.result.contract.ActivityResultContract
|
import androidx.activity.result.contract.ActivityResultContract
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@@ -20,12 +19,9 @@ import androidx.compose.foundation.layout.size
|
|||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TextFieldDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -36,21 +32,19 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.focus.onFocusChanged
|
|
||||||
import androidx.compose.ui.res.dimensionResource
|
import androidx.compose.ui.res.dimensionResource
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import org.signal.core.ui.compose.Buttons
|
import org.signal.core.ui.compose.Buttons
|
||||||
|
import org.signal.core.ui.compose.ClearableTextField
|
||||||
import org.signal.core.ui.compose.DayNightPreviews
|
import org.signal.core.ui.compose.DayNightPreviews
|
||||||
import org.signal.core.ui.compose.Dialogs
|
import org.signal.core.ui.compose.Dialogs
|
||||||
import org.signal.core.ui.compose.Previews
|
import org.signal.core.ui.compose.Previews
|
||||||
import org.signal.core.ui.compose.Scaffolds
|
import org.signal.core.ui.compose.Scaffolds
|
||||||
import org.signal.core.ui.compose.SignalIcons
|
import org.signal.core.ui.compose.SignalIcons
|
||||||
import org.signal.core.ui.compose.TextFields
|
|
||||||
import org.signal.core.util.getParcelableCompat
|
import org.signal.core.util.getParcelableCompat
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActivity
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
@@ -292,7 +286,8 @@ private fun NicknameContent(
|
|||||||
onValueChange = callback::onNoteChanged,
|
onValueChange = callback::onNoteChanged,
|
||||||
keyboardActions = KeyboardActions.Default,
|
keyboardActions = KeyboardActions.Default,
|
||||||
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
|
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
|
||||||
charactersRemaining = state.noteCharactersRemaining,
|
charactersRemainingBeforeLimit = state.noteCharactersRemaining,
|
||||||
|
countdownConfig = ClearableTextField.CountdownConfig(displayThreshold = 100, warnThreshold = 5),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.focusRequester(noteFocusRequester)
|
.focusRequester(noteFocusRequester)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -357,132 +352,3 @@ private fun NicknameContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DayNightPreviews
|
|
||||||
@Composable
|
|
||||||
private fun ClearableTextFieldPreview() {
|
|
||||||
Previews.Preview {
|
|
||||||
val focusRequester = remember { FocusRequester() }
|
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
|
||||||
ClearableTextField(
|
|
||||||
value = "",
|
|
||||||
hint = "Without content",
|
|
||||||
enabled = true,
|
|
||||||
onValueChange = {},
|
|
||||||
clearContentDescription = ""
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
|
||||||
ClearableTextField(
|
|
||||||
value = "Test",
|
|
||||||
hint = "With Content",
|
|
||||||
enabled = true,
|
|
||||||
onValueChange = {},
|
|
||||||
clearContentDescription = ""
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
|
||||||
ClearableTextField(
|
|
||||||
value = "",
|
|
||||||
hint = "Disabled",
|
|
||||||
enabled = false,
|
|
||||||
onValueChange = {},
|
|
||||||
clearContentDescription = ""
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.size(16.dp))
|
|
||||||
ClearableTextField(
|
|
||||||
value = "",
|
|
||||||
hint = "Focused",
|
|
||||||
enabled = true,
|
|
||||||
onValueChange = {},
|
|
||||||
modifier = Modifier.focusRequester(focusRequester),
|
|
||||||
clearContentDescription = ""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
focusRequester.requestFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun ClearableTextField(
|
|
||||||
value: String,
|
|
||||||
hint: String,
|
|
||||||
clearContentDescription: String,
|
|
||||||
enabled: Boolean,
|
|
||||||
onValueChange: (String) -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
singleLine: Boolean = false,
|
|
||||||
clearable: Boolean = true,
|
|
||||||
charactersRemaining: Int = Int.MAX_VALUE,
|
|
||||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
|
||||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default
|
|
||||||
) {
|
|
||||||
var focused by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
val displayCountdown = charactersRemaining <= 100
|
|
||||||
|
|
||||||
val clearButton: @Composable () -> Unit = {
|
|
||||||
ClearButton(
|
|
||||||
visible = focused,
|
|
||||||
onClick = { onValueChange("") },
|
|
||||||
contentDescription = clearContentDescription
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(modifier = modifier) {
|
|
||||||
TextFields.TextField(
|
|
||||||
value = value,
|
|
||||||
onValueChange = onValueChange,
|
|
||||||
label = {
|
|
||||||
Text(text = hint)
|
|
||||||
},
|
|
||||||
enabled = enabled,
|
|
||||||
singleLine = singleLine,
|
|
||||||
keyboardActions = keyboardActions,
|
|
||||||
keyboardOptions = keyboardOptions,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.onFocusChanged { focused = it.hasFocus && clearable },
|
|
||||||
colors = TextFieldDefaults.colors(
|
|
||||||
unfocusedLabelColor = MaterialTheme.colorScheme.outline,
|
|
||||||
unfocusedIndicatorColor = MaterialTheme.colorScheme.outline
|
|
||||||
),
|
|
||||||
trailingIcon = if (clearable) clearButton else null,
|
|
||||||
contentPadding = TextFieldDefaults.contentPaddingWithLabel(end = if (displayCountdown) 48.dp else 16.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = displayCountdown,
|
|
||||||
modifier = Modifier
|
|
||||||
.align(Alignment.BottomEnd)
|
|
||||||
.padding(bottom = 10.dp, end = 12.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "$charactersRemaining",
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = if (charactersRemaining <= 5) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.outline
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun ClearButton(
|
|
||||||
visible: Boolean,
|
|
||||||
onClick: () -> Unit,
|
|
||||||
contentDescription: String
|
|
||||||
) {
|
|
||||||
AnimatedVisibility(visible = visible) {
|
|
||||||
IconButton(
|
|
||||||
onClick = onClick
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = R.drawable.symbol_x_circle_fill_24),
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
tint = MaterialTheme.colorScheme.outline
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.signal.core.ui.compose
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.LocalTextStyle
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextFieldColors
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusRequester
|
||||||
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
object ClearableTextField {
|
||||||
|
/**
|
||||||
|
* Configures how the "characters remaining" countdown is displayed.
|
||||||
|
*/
|
||||||
|
data class CountdownConfig(
|
||||||
|
/** The number of characters remaining before the countdown is displayed. */
|
||||||
|
val displayThreshold: Int,
|
||||||
|
|
||||||
|
/** The number of characters remaining before the countdown is displayed as warning. */
|
||||||
|
val warnThreshold: Int
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A text field with an optional clear button that appears when focused and [clearable] is true.
|
||||||
|
*
|
||||||
|
* Also supports displaying a character countdown when the character count is approaching a limit.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun ClearableTextField(
|
||||||
|
value: String,
|
||||||
|
onValueChange: (String) -> Unit,
|
||||||
|
hint: String,
|
||||||
|
clearContentDescription: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
textStyle: TextStyle = LocalTextStyle.current,
|
||||||
|
leadingIcon: @Composable (() -> Unit)? = null,
|
||||||
|
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||||
|
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||||
|
singleLine: Boolean = false,
|
||||||
|
clearable: Boolean = true,
|
||||||
|
charactersRemainingBeforeLimit: Int = Int.MAX_VALUE,
|
||||||
|
countdownConfig: ClearableTextField.CountdownConfig? = null,
|
||||||
|
colors: TextFieldColors = defaultTextFieldColors()
|
||||||
|
) {
|
||||||
|
ClearableTextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onValueChange,
|
||||||
|
clearContentDescription = clearContentDescription,
|
||||||
|
modifier = modifier,
|
||||||
|
enabled = enabled,
|
||||||
|
textStyle = textStyle,
|
||||||
|
label = { Text(hint) },
|
||||||
|
leadingIcon = leadingIcon,
|
||||||
|
keyboardOptions = keyboardOptions,
|
||||||
|
keyboardActions = keyboardActions,
|
||||||
|
singleLine = singleLine,
|
||||||
|
clearable = clearable,
|
||||||
|
charactersRemaining = charactersRemainingBeforeLimit,
|
||||||
|
countdownConfig = countdownConfig,
|
||||||
|
colors = colors
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A text field with an optional clear button that appears when focused and [clearable] is true.
|
||||||
|
*
|
||||||
|
* Also supports displaying a character countdown when the character count is approaching a limit.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun ClearableTextField(
|
||||||
|
value: String,
|
||||||
|
onValueChange: (String) -> Unit,
|
||||||
|
clearContentDescription: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
textStyle: TextStyle = LocalTextStyle.current,
|
||||||
|
label: @Composable (() -> Unit)? = null,
|
||||||
|
leadingIcon: @Composable (() -> Unit)? = null,
|
||||||
|
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||||
|
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||||
|
singleLine: Boolean = false,
|
||||||
|
clearable: Boolean = true,
|
||||||
|
charactersRemaining: Int = Int.MAX_VALUE,
|
||||||
|
countdownConfig: ClearableTextField.CountdownConfig? = null,
|
||||||
|
colors: TextFieldColors = defaultTextFieldColors()
|
||||||
|
) {
|
||||||
|
var focused by remember { mutableStateOf(false) }
|
||||||
|
val displayCountdown = countdownConfig != null && charactersRemaining <= countdownConfig.displayThreshold
|
||||||
|
|
||||||
|
val clearButton: @Composable () -> Unit = {
|
||||||
|
ClearButton(
|
||||||
|
visible = focused,
|
||||||
|
onClick = { onValueChange("") },
|
||||||
|
contentDescription = clearContentDescription
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(modifier = modifier) {
|
||||||
|
TextFields.TextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = onValueChange,
|
||||||
|
textStyle = textStyle,
|
||||||
|
label = label,
|
||||||
|
enabled = enabled,
|
||||||
|
singleLine = singleLine,
|
||||||
|
keyboardActions = keyboardActions,
|
||||||
|
keyboardOptions = keyboardOptions,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.onFocusChanged { focused = it.hasFocus && clearable },
|
||||||
|
colors = colors,
|
||||||
|
leadingIcon = leadingIcon,
|
||||||
|
trailingIcon = if (clearable) clearButton else null,
|
||||||
|
contentPadding = TextFieldDefaults.contentPaddingWithLabel(end = if (displayCountdown) 48.dp else 16.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = displayCountdown,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomEnd)
|
||||||
|
.padding(bottom = 10.dp, end = 12.dp)
|
||||||
|
) {
|
||||||
|
val errorThresholdExceeded = countdownConfig != null && charactersRemaining <= countdownConfig.warnThreshold
|
||||||
|
Text(
|
||||||
|
text = "$charactersRemaining",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = if (errorThresholdExceeded) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.outline
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ClearButton(
|
||||||
|
visible: Boolean,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
contentDescription: String
|
||||||
|
) {
|
||||||
|
AnimatedVisibility(visible = visible) {
|
||||||
|
IconButton(
|
||||||
|
onClick = onClick
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = SignalIcons.XCircleFill.painter,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
tint = MaterialTheme.colorScheme.outline
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun defaultTextFieldColors(): TextFieldColors = TextFieldDefaults.colors(
|
||||||
|
unfocusedLabelColor = MaterialTheme.colorScheme.outline,
|
||||||
|
unfocusedIndicatorColor = MaterialTheme.colorScheme.outline
|
||||||
|
)
|
||||||
|
|
||||||
|
@DayNightPreviews
|
||||||
|
@Composable
|
||||||
|
private fun ClearableTextFieldPreview() {
|
||||||
|
Previews.Preview {
|
||||||
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
|
ClearableTextField(
|
||||||
|
value = "",
|
||||||
|
onValueChange = {},
|
||||||
|
hint = "without content",
|
||||||
|
clearContentDescription = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
|
ClearableTextField(
|
||||||
|
value = "foo bar",
|
||||||
|
onValueChange = {},
|
||||||
|
hint = "with content",
|
||||||
|
clearContentDescription = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
|
ClearableTextField(
|
||||||
|
value = "",
|
||||||
|
onValueChange = {},
|
||||||
|
hint = "disabled",
|
||||||
|
clearContentDescription = "",
|
||||||
|
enabled = false
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
|
ClearableTextField(
|
||||||
|
value = "",
|
||||||
|
onValueChange = {},
|
||||||
|
hint = "focused without content",
|
||||||
|
clearContentDescription = "",
|
||||||
|
modifier = Modifier.focusRequester(focusRequester)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DayNightPreviews
|
||||||
|
@Composable
|
||||||
|
private fun ClearableTextFieldCharacterCountPreview() {
|
||||||
|
Previews.Preview {
|
||||||
|
val countdownConfig = ClearableTextField.CountdownConfig(displayThreshold = 100, warnThreshold = 10)
|
||||||
|
|
||||||
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
|
ClearableTextField(
|
||||||
|
value = "Character count normal state",
|
||||||
|
onValueChange = {},
|
||||||
|
hint = "countdown shown",
|
||||||
|
clearContentDescription = "Clear",
|
||||||
|
charactersRemainingBeforeLimit = 50,
|
||||||
|
countdownConfig = countdownConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
|
ClearableTextField(
|
||||||
|
value = "Very long text showing the character count warning state",
|
||||||
|
onValueChange = {},
|
||||||
|
hint = "countdown warning",
|
||||||
|
clearContentDescription = "Clear",
|
||||||
|
charactersRemainingBeforeLimit = 8,
|
||||||
|
countdownConfig = countdownConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
|
||||||
|
ClearableTextField(
|
||||||
|
value = "No character count shown",
|
||||||
|
onValueChange = {},
|
||||||
|
hint = "no countdown shown",
|
||||||
|
clearContentDescription = "Clear",
|
||||||
|
charactersRemainingBeforeLimit = 150,
|
||||||
|
countdownConfig = countdownConfig
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,8 @@ enum class SignalIcons(private val icon: SignalIcon) : SignalIcon by icon {
|
|||||||
Settings(icon(R.drawable.symbol_settings_android_24)),
|
Settings(icon(R.drawable.symbol_settings_android_24)),
|
||||||
Share(icon(R.drawable.symbol_share_android_24)),
|
Share(icon(R.drawable.symbol_share_android_24)),
|
||||||
Trash(icon(R.drawable.symbol_trash_24)),
|
Trash(icon(R.drawable.symbol_trash_24)),
|
||||||
X(icon(R.drawable.symbol_x_24))
|
X(icon(R.drawable.symbol_x_24)),
|
||||||
|
XCircleFill(icon(R.drawable.symbol_x_circle_fill_24))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun icon(@DrawableRes id: Int) = SignalIcon.DrawableIcon(id)
|
private fun icon(@DrawableRes id: Int) = SignalIcon.DrawableIcon(id)
|
||||||
|
|||||||
Reference in New Issue
Block a user