Updates our base textfield and moves to it's a more general package
This commit is contained in:
+26
-22
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils
|
package com.vitorpamplona.amethyst.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||||
@@ -37,7 +37,6 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberUpdatedState
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Shape
|
import androidx.compose.ui.graphics.Shape
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
@@ -48,9 +47,12 @@ import androidx.compose.ui.text.input.VisualTransformation
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
|
|
||||||
|
// COPIED FROM TEXT FIELD
|
||||||
|
// The only change is the contentPadding below
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun MyTextField(
|
fun ThinPaddingTextField(
|
||||||
value: TextFieldValue,
|
value: TextFieldValue,
|
||||||
onValueChange: (TextFieldValue) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
@@ -71,9 +73,10 @@ fun MyTextField(
|
|||||||
singleLine: Boolean = false,
|
singleLine: Boolean = false,
|
||||||
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
||||||
minLines: Int = 1,
|
minLines: Int = 1,
|
||||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
interactionSource: MutableInteractionSource? = null,
|
||||||
shape: Shape = TextFieldDefaults.shape,
|
shape: Shape = TextFieldDefaults.shape,
|
||||||
colors: TextFieldColors = TextFieldDefaults.colors(),
|
colors: TextFieldColors = TextFieldDefaults.colors(),
|
||||||
|
// new fields
|
||||||
contentPadding: PaddingValues =
|
contentPadding: PaddingValues =
|
||||||
if (label == null) {
|
if (label == null) {
|
||||||
TextFieldDefaults.contentPaddingWithoutLabel(
|
TextFieldDefaults.contentPaddingWithoutLabel(
|
||||||
@@ -91,37 +94,38 @@ fun MyTextField(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
// COPIED FROM TEXT FIELD
|
@Suppress("NAME_SHADOWING")
|
||||||
// The only change is the contentPadding below
|
val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
|
||||||
|
|
||||||
|
// If color is not provided via the text style, use content color as a default
|
||||||
val textColor =
|
val textColor =
|
||||||
textStyle.color.takeOrElse {
|
textStyle.color.takeOrElse {
|
||||||
val focused by interactionSource.collectIsFocusedAsState()
|
val focused by interactionSource.collectIsFocusedAsState()
|
||||||
|
|
||||||
val targetValue =
|
// this has changed, but only because of private access on the original
|
||||||
when {
|
when {
|
||||||
!enabled -> MaterialTheme.colorScheme.placeholderText
|
!enabled -> MaterialTheme.colorScheme.placeholderText
|
||||||
isError -> MaterialTheme.colorScheme.onSurface
|
isError -> MaterialTheme.colorScheme.onSurface
|
||||||
focused -> MaterialTheme.colorScheme.onSurface
|
focused -> MaterialTheme.colorScheme.onSurface
|
||||||
else -> MaterialTheme.colorScheme.onSurface
|
else -> MaterialTheme.colorScheme.onSurface
|
||||||
}
|
}
|
||||||
|
|
||||||
rememberUpdatedState(targetValue).value
|
|
||||||
}
|
}
|
||||||
val mergedTextStyle = textStyle.merge(TextStyle(color = textColor))
|
val mergedTextStyle = textStyle.merge(TextStyle(color = textColor))
|
||||||
|
|
||||||
CompositionLocalProvider(LocalTextSelectionColors provides LocalTextSelectionColors.current) {
|
CompositionLocalProvider(LocalTextSelectionColors provides colors.textSelectionColors) {
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
value = value,
|
value = value,
|
||||||
modifier =
|
modifier =
|
||||||
modifier.defaultMinSize(
|
modifier
|
||||||
minWidth = TextFieldDefaults.MinWidth,
|
.defaultMinSize(
|
||||||
minHeight = 36.dp,
|
minWidth = TextFieldDefaults.MinWidth,
|
||||||
),
|
minHeight = 36.dp, // this has changed
|
||||||
|
),
|
||||||
onValueChange = onValueChange,
|
onValueChange = onValueChange,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
readOnly = readOnly,
|
readOnly = readOnly,
|
||||||
textStyle = mergedTextStyle,
|
textStyle = mergedTextStyle,
|
||||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
|
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary), // this has changed
|
||||||
visualTransformation = visualTransformation,
|
visualTransformation = visualTransformation,
|
||||||
keyboardOptions = keyboardOptions,
|
keyboardOptions = keyboardOptions,
|
||||||
keyboardActions = keyboardActions,
|
keyboardActions = keyboardActions,
|
||||||
@@ -148,7 +152,7 @@ fun MyTextField(
|
|||||||
isError = isError,
|
isError = isError,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
colors = colors,
|
colors = colors,
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding, // this has changed
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
+9
-10
@@ -53,7 +53,6 @@ import androidx.compose.foundation.selection.toggleable
|
|||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Assistant
|
|
||||||
import androidx.compose.material.icons.filled.Bolt
|
import androidx.compose.material.icons.filled.Bolt
|
||||||
import androidx.compose.material.icons.filled.CurrencyBitcoin
|
import androidx.compose.material.icons.filled.CurrencyBitcoin
|
||||||
import androidx.compose.material.icons.filled.LocationOff
|
import androidx.compose.material.icons.filled.LocationOff
|
||||||
@@ -149,6 +148,7 @@ import com.vitorpamplona.amethyst.ui.components.InvoiceRequest
|
|||||||
import com.vitorpamplona.amethyst.ui.components.LoadUrlPreview
|
import com.vitorpamplona.amethyst.ui.components.LoadUrlPreview
|
||||||
import com.vitorpamplona.amethyst.ui.components.LoadingAnimation
|
import com.vitorpamplona.amethyst.ui.components.LoadingAnimation
|
||||||
import com.vitorpamplona.amethyst.ui.components.SecretEmojiRequest
|
import com.vitorpamplona.amethyst.ui.components.SecretEmojiRequest
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.ThinPaddingTextField
|
||||||
import com.vitorpamplona.amethyst.ui.components.VideoView
|
import com.vitorpamplona.amethyst.ui.components.VideoView
|
||||||
import com.vitorpamplona.amethyst.ui.components.ZapRaiserRequest
|
import com.vitorpamplona.amethyst.ui.components.ZapRaiserRequest
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.Nav
|
import com.vitorpamplona.amethyst.ui.navigation.Nav
|
||||||
@@ -165,7 +165,6 @@ import com.vitorpamplona.amethyst.ui.note.ShowUserSuggestionList
|
|||||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||||
import com.vitorpamplona.amethyst.ui.note.WatchAndLoadMyEmojiList
|
import com.vitorpamplona.amethyst.ui.note.WatchAndLoadMyEmojiList
|
||||||
import com.vitorpamplona.amethyst.ui.note.ZapSplitIcon
|
import com.vitorpamplona.amethyst.ui.note.ZapSplitIcon
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.MyTextField
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||||
@@ -737,7 +736,7 @@ private fun MessageField(postViewModel: NewPostViewModel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = postViewModel.message,
|
value = postViewModel.message,
|
||||||
onValueChange = { postViewModel.updateMessage(it) },
|
onValueChange = { postViewModel.updateMessage(it) },
|
||||||
keyboardOptions =
|
keyboardOptions =
|
||||||
@@ -851,7 +850,7 @@ fun SendDirectMessageTo(postViewModel: NewPostViewModel) {
|
|||||||
fontWeight = FontWeight.W500,
|
fontWeight = FontWeight.W500,
|
||||||
)
|
)
|
||||||
|
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = postViewModel.toUsers,
|
value = postViewModel.toUsers,
|
||||||
onValueChange = { postViewModel.updateToUsers(it) },
|
onValueChange = { postViewModel.updateToUsers(it) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
@@ -885,7 +884,7 @@ fun SendDirectMessageTo(postViewModel: NewPostViewModel) {
|
|||||||
fontWeight = FontWeight.W500,
|
fontWeight = FontWeight.W500,
|
||||||
)
|
)
|
||||||
|
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = postViewModel.subject,
|
value = postViewModel.subject,
|
||||||
onValueChange = { postViewModel.updateSubject(it) },
|
onValueChange = { postViewModel.updateSubject(it) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
@@ -926,7 +925,7 @@ fun SellProduct(postViewModel: NewPostViewModel) {
|
|||||||
fontWeight = FontWeight.W500,
|
fontWeight = FontWeight.W500,
|
||||||
)
|
)
|
||||||
|
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = postViewModel.title,
|
value = postViewModel.title,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
postViewModel.updateTitle(it)
|
postViewModel.updateTitle(it)
|
||||||
@@ -962,7 +961,7 @@ fun SellProduct(postViewModel: NewPostViewModel) {
|
|||||||
fontWeight = FontWeight.W500,
|
fontWeight = FontWeight.W500,
|
||||||
)
|
)
|
||||||
|
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = postViewModel.price,
|
value = postViewModel.price,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
@@ -1039,7 +1038,7 @@ fun SellProduct(postViewModel: NewPostViewModel) {
|
|||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(end = 5.dp, bottom = 1.dp),
|
.padding(end = 5.dp, bottom = 1.dp),
|
||||||
) { currentOption, modifier ->
|
) { currentOption, modifier ->
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = TextFieldValue(currentOption),
|
value = TextFieldValue(currentOption),
|
||||||
onValueChange = {},
|
onValueChange = {},
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
@@ -1105,7 +1104,7 @@ fun SellProduct(postViewModel: NewPostViewModel) {
|
|||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(end = 5.dp, bottom = 1.dp),
|
.padding(end = 5.dp, bottom = 1.dp),
|
||||||
) { currentOption, modifier ->
|
) { currentOption, modifier ->
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = TextFieldValue(currentOption),
|
value = TextFieldValue(currentOption),
|
||||||
onValueChange = {},
|
onValueChange = {},
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
@@ -1132,7 +1131,7 @@ fun SellProduct(postViewModel: NewPostViewModel) {
|
|||||||
fontWeight = FontWeight.W500,
|
fontWeight = FontWeight.W500,
|
||||||
)
|
)
|
||||||
|
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = postViewModel.locationText,
|
value = postViewModel.locationText,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
postViewModel.updateLocation(it)
|
postViewModel.updateLocation(it)
|
||||||
|
|||||||
+2
-2
@@ -85,6 +85,7 @@ import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
|||||||
import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation
|
import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.ThinPaddingTextField
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.TopBarExtensibleWithBackButton
|
import com.vitorpamplona.amethyst.ui.navigation.TopBarExtensibleWithBackButton
|
||||||
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
||||||
@@ -107,7 +108,6 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.DisplayRoomSubje
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.DisplayUserSetAsSubject
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.DisplayUserSetAsSubject
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.LoadUser
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.LoadUser
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.DisplayReplyingToNote
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.DisplayReplyingToNote
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.MyTextField
|
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight
|
import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
@@ -551,7 +551,7 @@ fun PrivateMessageEditFieldRow(
|
|||||||
accountViewModel,
|
accountViewModel,
|
||||||
)
|
)
|
||||||
|
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = channelScreenModel.message,
|
value = channelScreenModel.message,
|
||||||
onValueChange = { channelScreenModel.updateMessage(it) },
|
onValueChange = { channelScreenModel.updateMessage(it) },
|
||||||
keyboardOptions =
|
keyboardOptions =
|
||||||
|
|||||||
+2
-6
@@ -98,6 +98,7 @@ import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
|||||||
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
||||||
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
||||||
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.ThinPaddingTextField
|
||||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||||
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
@@ -122,7 +123,6 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.RefreshingChatroomFeedView
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.RefreshingChatroomFeedView
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ThinSendButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ThinSendButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.DisplayReplyingToNote
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.DisplayReplyingToNote
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.MyTextField
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CrossfadeCheckIfVideoIsOnline
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CrossfadeCheckIfVideoIsOnline
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
@@ -171,7 +171,6 @@ import kotlinx.collections.immutable.ImmutableList
|
|||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.FlowPreview
|
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.debounce
|
import kotlinx.coroutines.flow.debounce
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
@@ -219,7 +218,6 @@ fun Channel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(FlowPreview::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PrepareChannelViewModels(
|
fun PrepareChannelViewModels(
|
||||||
baseChannel: Channel,
|
baseChannel: Channel,
|
||||||
@@ -257,8 +255,6 @@ fun ChannelScreen(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: INav,
|
nav: INav,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
NostrChannelDataSource.loadMessagesBetween(accountViewModel.account, channel)
|
NostrChannelDataSource.loadMessagesBetween(accountViewModel.account, channel)
|
||||||
|
|
||||||
val lifeCycleOwner = LocalLifecycleOwner.current
|
val lifeCycleOwner = LocalLifecycleOwner.current
|
||||||
@@ -507,7 +503,7 @@ fun EditFieldRow(
|
|||||||
accountViewModel,
|
accountViewModel,
|
||||||
)
|
)
|
||||||
|
|
||||||
MyTextField(
|
ThinPaddingTextField(
|
||||||
value = channelScreenModel.message,
|
value = channelScreenModel.message,
|
||||||
onValueChange = { channelScreenModel.updateMessage(it) },
|
onValueChange = { channelScreenModel.updateMessage(it) },
|
||||||
keyboardOptions =
|
keyboardOptions =
|
||||||
|
|||||||
Reference in New Issue
Block a user