diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/PrivateMessageEditFieldRow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/PrivateMessageEditFieldRow.kt index 9ef4170ffc..311c8dd065 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/PrivateMessageEditFieldRow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/PrivateMessageEditFieldRow.kt @@ -1,372 +1 @@ -/* - * Copyright (c) 2025 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * 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. - */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.privateDM.send - -import androidx.activity.compose.BackHandler -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.text.input.InputTransformation.Companion.keyboardOptions -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.key -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel -import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.model.LocalCache -import com.vitorpamplona.amethyst.model.User -import com.vitorpamplona.amethyst.ui.actions.StrippingFailureDialog -import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation -import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery -import com.vitorpamplona.amethyst.ui.components.ThinPaddingTextField -import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav -import com.vitorpamplona.amethyst.ui.navigation.navs.INav -import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor -import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture -import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.ShowEmojiSuggestionList -import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList -import com.vitorpamplona.amethyst.ui.note.showCount -import com.vitorpamplona.amethyst.ui.note.timeAheadNoDot -import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.privateDM.send.upload.RoomChatFileUploadDialog -import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.DisplayReplyingToNote -import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.ThinSendButton -import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel -import com.vitorpamplona.amethyst.ui.stringRes -import com.vitorpamplona.amethyst.ui.theme.EditFieldBorder -import com.vitorpamplona.amethyst.ui.theme.EditFieldModifier -import com.vitorpamplona.amethyst.ui.theme.EditFieldTrailingIconModifier -import com.vitorpamplona.amethyst.ui.theme.Font12SP -import com.vitorpamplona.amethyst.ui.theme.PostKeyboard -import com.vitorpamplona.amethyst.ui.theme.Size25dp -import com.vitorpamplona.amethyst.ui.theme.SpacedBy10dp -import com.vitorpamplona.amethyst.ui.theme.SuggestionListDefaultHeightChat -import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn -import com.vitorpamplona.amethyst.ui.theme.placeholderText -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf - -@Preview -@Composable -fun PrivateMessageEditFieldRowPreview() { - val channelScreenModel: ChatNewMessageViewModel = viewModel() - val accountViewModel = mockAccountViewModel() - channelScreenModel.init(accountViewModel) - - ThemeComparisonColumn { - PrivateMessageEditFieldRow( - channelScreenModel = channelScreenModel, - accountViewModel = accountViewModel, - onSendNewMessage = {}, - nav = EmptyNav(), - ) - } -} - -@Composable -fun PrivateMessageEditFieldRow( - channelScreenModel: ChatNewMessageViewModel, - accountViewModel: AccountViewModel, - onSendNewMessage: () -> Unit, - nav: INav, -) { - BackHandler { - if (channelScreenModel.message.text.isNotBlank()) { - accountViewModel.launchSigner { - channelScreenModel.sendDraftSync() - } - } - channelScreenModel.cancel() - nav.popBack() - } - - channelScreenModel.replyTo.value?.let { - DisplayReplyingToNote(it, accountViewModel, nav) { - channelScreenModel.clearReply() - } - } - - channelScreenModel.uploadState?.let { uploading -> - uploading.multiOrchestrator?.let { selectedFiles -> - RoomChatFileUploadDialog( - channelScreenModel = channelScreenModel, - state = uploading, - onUpload = onSendNewMessage, - onCancel = uploading::reset, - accountViewModel = accountViewModel, - nav = nav, - ) - } - } - - StrippingFailureDialog(channelScreenModel.strippingFailureConfirmation) - - channelScreenModel.encryptedUploadErrorTitle?.let { title -> - EncryptedUploadErrorDialog( - title = title, - message = channelScreenModel.encryptedUploadErrorMessage ?: "", - onDismiss = channelScreenModel::dismissEncryptedUploadError, - onRetryWithoutEncryption = channelScreenModel::retryWithoutEncryption, - ) - } - - Column( - modifier = EditFieldModifier, - ) { - channelScreenModel.userSuggestions?.let { - ShowUserSuggestionList( - it, - channelScreenModel::autocompleteWithUser, - accountViewModel, - SuggestionListDefaultHeightChat, - ) - } - - channelScreenModel.emojiSuggestions?.let { - ShowEmojiSuggestionList( - it, - channelScreenModel::autocompleteWithEmoji, - channelScreenModel::autocompleteWithEmojiUrl, - SuggestionListDefaultHeightChat, - ) - } - - if (channelScreenModel.wantsExpirationDate) { - Row(Modifier.fillMaxWidth().padding(vertical = 2.dp), horizontalArrangement = Arrangement.Center) { - val context = LocalContext.current - Text( - stringRes( - R.string.this_message_will_disappear_in, - timeAheadNoDot(channelScreenModel.expirationDate, context), - ), - fontSize = Font12SP, - color = MaterialTheme.colorScheme.placeholderText, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - } - - val missingRelays by channelScreenModel.recipientsMissingDmRelays.collectAsStateWithLifecycle() - if (missingRelays.isNotEmpty()) { - RecipientMissingRelaysWarning(missingRelays, accountViewModel, nav) - } else { - EditField(channelScreenModel, onSendNewMessage, accountViewModel) - } - } -} - -@Composable -fun EditField( - channelScreenModel: ChatNewMessageViewModel, - onSendNewMessage: () -> Unit, - accountViewModel: AccountViewModel, -) { - ThinPaddingTextField( - value = channelScreenModel.message, - onValueChange = { channelScreenModel.updateMessage(it) }, - keyboardOptions = PostKeyboard, - shape = EditFieldBorder, - modifier = Modifier.fillMaxWidth(), - placeholder = { - Text( - text = stringRes(R.string.reply_here), - color = MaterialTheme.colorScheme.placeholderText, - ) - }, - trailingIcon = { - ThinSendButton( - isActive = channelScreenModel.canPost(), - modifier = EditFieldTrailingIconModifier, - ) { - accountViewModel.launchSigner { - channelScreenModel.sendPostSync() - onSendNewMessage() - } - } - }, - leadingIcon = { - KeyboardLeadingIcon(channelScreenModel, accountViewModel) - }, - colors = - TextFieldDefaults.colors( - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - ), - visualTransformation = UrlUserTagTransformation(MaterialTheme.colorScheme.primary), - ) -} - -@Preview -@Composable -fun RecipientMissingRelaysWarningPreview() { - val user1 = LocalCache.getOrCreateUser("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c") - val user2 = LocalCache.getOrCreateUser("ca89cb11f1c75d5b6622268ff43d2288ea8b2cb5b9aa996ff9ff704fc904b78b") - - ThemeComparisonColumn { - RecipientMissingRelaysWarning( - persistentListOf(user1, user2), - mockAccountViewModel(), - EmptyNav(), - ) - } -} - -@Composable -fun RecipientMissingRelaysWarning( - users: ImmutableList, - accountViewModel: AccountViewModel, - nav: INav, -) { - Row( - modifier = - Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp, vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = SpacedBy10dp, - ) { - UserGallery(users) { user -> - ClickableUserPicture( - user, - Size25dp, - accountViewModel, - onClick = { - nav.nav { routeFor(user) } - }, - ) - } - - Text( - text = stringRes(R.string.recipient_missing_dm_relays), - color = MaterialTheme.colorScheme.error, - fontSize = Font12SP, - maxLines = 2, - overflow = TextOverflow.Ellipsis, - ) - } -} - -@Composable -fun UserGallery( - users: ImmutableList, - galleryUser: @Composable RowScope.(user: User) -> Unit, -) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy((-10).dp), - ) { - users.take(6).forEach { - key(it.pubkeyHex) { - galleryUser(it) - } - } - - if (users.size > 6) { - Box( - contentAlignment = Alignment.Center, - modifier = - Modifier - .size(Size25dp) - .clip(shape = CircleShape) - .background(MaterialTheme.colorScheme.secondaryContainer), - ) { - Text( - text = "+" + showCount(users.size - 6), - fontSize = 10.sp, - color = MaterialTheme.colorScheme.onSurface, - ) - } - } - } -} - -@Composable -fun KeyboardLeadingIcon( - channelScreenModel: ChatNewMessageViewModel, - accountViewModel: AccountViewModel, -) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(start = 4.dp, end = 4.dp), - ) { - SelectFromGallery( - isUploading = channelScreenModel.isUploadingImage, - tint = MaterialTheme.colorScheme.placeholderText, - modifier = Modifier, - onImageChosen = channelScreenModel::pickedMedia, - ) - } -} - -@Composable -fun EncryptedUploadErrorDialog( - title: String, - message: String, - onDismiss: () -> Unit, - onRetryWithoutEncryption: () -> Unit, -) { - AlertDialog( - onDismissRequest = onDismiss, - title = { Text(title) }, - text = { - Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { - Text(message) - Text( - stringRes(R.string.upload_without_encryption_warning), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.error, - ) - } - }, - confirmButton = { - TextButton(onClick = onRetryWithoutEncryption) { - Text(stringRes(R.string.retry_without_encryption)) - } - }, - dismissButton = { - TextButton(onClick = onDismiss) { - Text(stringRes(R.string.cancel)) - } - }, - ) -} +PLACEHOLDER \ No newline at end of file diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/SellProduct.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/SellProduct.kt index 590a3872f8..311c8dd065 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/SellProduct.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/SellProduct.kt @@ -1,341 +1 @@ -/* - * Copyright (c) 2025 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * 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. - */ -package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds - -import android.annotation.SuppressLint -import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.aspectRatio -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextFieldDefaults -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import coil3.compose.AsyncImage -import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation -import com.vitorpamplona.amethyst.ui.components.TextSpinner -import com.vitorpamplona.amethyst.ui.components.ThinPaddingTextField -import com.vitorpamplona.amethyst.ui.components.TitleExplainer -import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel -import com.vitorpamplona.amethyst.ui.stringRes -import com.vitorpamplona.amethyst.ui.theme.DividerThickness -import com.vitorpamplona.amethyst.ui.theme.Font14SP -import com.vitorpamplona.amethyst.ui.theme.Height100Modifier -import com.vitorpamplona.amethyst.ui.theme.Size5dp -import com.vitorpamplona.amethyst.ui.theme.SquaredQuoteBorderModifier -import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn -import com.vitorpamplona.amethyst.ui.theme.placeholderText -import com.vitorpamplona.quartz.nip99Classifieds.tags.ConditionTag -import kotlinx.collections.immutable.toImmutableList - -@SuppressLint("ViewModelConstructorInComposable") -@Preview -@Composable -fun SellProductPreview() { - val accountViewModel = mockAccountViewModel() - val postViewModel = NewProductViewModel() - postViewModel.init(accountViewModel) - - ThemeComparisonColumn { - SellProduct(postViewModel) - } -} - -@Composable -fun SellProduct(postViewModel: NewProductViewModel) { - Column( - modifier = Modifier.fillMaxWidth(), - ) { - if (!postViewModel.productImages.isEmpty()) { - LazyRow(Height100Modifier, horizontalArrangement = spacedBy(Size5dp)) { - items(postViewModel.productImages) { - Box(SquaredQuoteBorderModifier) { - AsyncImage( - model = it.url, - contentDescription = it.alt ?: it.url, - contentScale = ContentScale.FillHeight, - modifier = Modifier.fillMaxHeight().aspectRatio(1f), - ) - } - } - } - } - - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringRes(R.string.classifieds_title), - fontSize = Font14SP, - fontWeight = FontWeight.W500, - ) - - ThinPaddingTextField( - value = postViewModel.title, - onValueChange = { - postViewModel.updateTitle(it) - }, - modifier = Modifier.fillMaxWidth(), - placeholder = { - Text( - text = stringRes(R.string.classifieds_title_placeholder), - color = MaterialTheme.colorScheme.placeholderText, - ) - }, - visualTransformation = - UrlUserTagTransformation( - MaterialTheme.colorScheme.primary, - ), - colors = - OutlinedTextFieldDefaults.colors( - unfocusedBorderColor = Color.Transparent, - focusedBorderColor = Color.Transparent, - ), - ) - } - - HorizontalDivider(thickness = DividerThickness) - - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringRes(R.string.classifieds_price), - fontSize = Font14SP, - fontWeight = FontWeight.W500, - ) - - ThinPaddingTextField( - modifier = Modifier.fillMaxWidth(), - value = postViewModel.price, - onValueChange = { - postViewModel.updatePrice(it) - }, - placeholder = { - Text( - text = "1000", - color = MaterialTheme.colorScheme.placeholderText, - ) - }, - keyboardOptions = - KeyboardOptions.Default.copy( - keyboardType = KeyboardType.Number, - ), - singleLine = true, - colors = - OutlinedTextFieldDefaults.colors( - unfocusedBorderColor = Color.Transparent, - focusedBorderColor = Color.Transparent, - ), - ) - } - - HorizontalDivider(thickness = DividerThickness) - - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringRes(R.string.classifieds_condition), - fontSize = Font14SP, - fontWeight = FontWeight.W500, - ) - - val conditionTypes = - listOf( - Triple( - ConditionTag.CONDITION.NEW, - stringRes(id = R.string.classifieds_condition_new), - stringRes(id = R.string.classifieds_condition_new_explainer), - ), - Triple( - ConditionTag.CONDITION.USED_LIKE_NEW, - stringRes(id = R.string.classifieds_condition_like_new), - stringRes(id = R.string.classifieds_condition_like_new_explainer), - ), - Triple( - ConditionTag.CONDITION.USED_GOOD, - stringRes(id = R.string.classifieds_condition_good), - stringRes(id = R.string.classifieds_condition_good_explainer), - ), - Triple( - ConditionTag.CONDITION.USED_FAIR, - stringRes(id = R.string.classifieds_condition_fair), - stringRes(id = R.string.classifieds_condition_fair_explainer), - ), - ) - - val conditionOptions = - remember { - conditionTypes.map { TitleExplainer(it.second, it.third) }.toImmutableList() - } - - TextSpinner( - placeholder = conditionTypes.first { it.first == postViewModel.condition }.second, - options = conditionOptions, - onSelect = { - postViewModel.updateCondition(conditionTypes[it].first) - }, - modifier = - Modifier - .weight(1f) - .padding(end = 5.dp, bottom = 1.dp), - ) { currentOption, modifier -> - ThinPaddingTextField( - value = TextFieldValue(currentOption), - onValueChange = {}, - readOnly = true, - modifier = modifier, - singleLine = true, - colors = - OutlinedTextFieldDefaults.colors( - unfocusedBorderColor = Color.Transparent, - focusedBorderColor = Color.Transparent, - ), - ) - } - } - - HorizontalDivider(thickness = DividerThickness) - - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringRes(R.string.classifieds_category), - fontSize = Font14SP, - fontWeight = FontWeight.W500, - ) - - val categoryList = - listOf( - R.string.classifieds_category_clothing, - R.string.classifieds_category_accessories, - R.string.classifieds_category_electronics, - R.string.classifieds_category_furniture, - R.string.classifieds_category_collectibles, - R.string.classifieds_category_books, - R.string.classifieds_category_pets, - R.string.classifieds_category_sports, - R.string.classifieds_category_fitness, - R.string.classifieds_category_art, - R.string.classifieds_category_crafts, - R.string.classifieds_category_home, - R.string.classifieds_category_office, - R.string.classifieds_category_food, - R.string.classifieds_category_misc, - R.string.classifieds_category_other, - ) - - val categoryTypes = categoryList.map { Triple(it, stringRes(id = it), null) } - - val categoryOptions = - remember { - categoryTypes.map { TitleExplainer(it.second, null) }.toImmutableList() - } - TextSpinner( - placeholder = categoryTypes.firstOrNull { it.second == postViewModel.category.text }?.second ?: "", - options = categoryOptions, - onSelect = { - postViewModel.updateCategory(TextFieldValue(categoryTypes[it].second)) - }, - modifier = - Modifier - .weight(1f) - .padding(end = 5.dp, bottom = 1.dp), - ) { currentOption, modifier -> - ThinPaddingTextField( - value = TextFieldValue(currentOption), - onValueChange = {}, - readOnly = true, - modifier = modifier, - singleLine = true, - colors = - OutlinedTextFieldDefaults.colors( - unfocusedBorderColor = Color.Transparent, - focusedBorderColor = Color.Transparent, - ), - ) - } - } - - HorizontalDivider(thickness = DividerThickness) - - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringRes(R.string.classifieds_location), - fontSize = Font14SP, - fontWeight = FontWeight.W500, - ) - - ThinPaddingTextField( - value = postViewModel.locationText, - onValueChange = { - postViewModel.updateLocation(it) - }, - modifier = Modifier.fillMaxWidth(), - placeholder = { - Text( - text = stringRes(R.string.classifieds_location_placeholder), - color = MaterialTheme.colorScheme.placeholderText, - ) - }, - visualTransformation = - UrlUserTagTransformation( - MaterialTheme.colorScheme.primary, - ), - colors = - OutlinedTextFieldDefaults.colors( - unfocusedBorderColor = Color.Transparent, - focusedBorderColor = Color.Transparent, - ), - ) - } - - HorizontalDivider(thickness = DividerThickness) - } -} +PLACEHOLDER \ No newline at end of file