mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-23 06:45:57 +00:00
ui: chat tag fixes (#5427)
* ui: chat tag fixes * fix switching tags * change * android: fix switching profile * change * sp * change --------- Co-authored-by: Avently <7953703+avently@users.noreply.github.com>
This commit is contained in:
@@ -163,7 +163,7 @@ class ChatTagsModel: ObservableObject {
|
||||
|
||||
func markChatTagRead(_ chat: Chat) -> Void {
|
||||
if chat.unreadTag, let tags = chat.chatInfo.chatTags {
|
||||
markChatTagRead_(chat, tags)
|
||||
decTagsReadCount(tags)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +175,11 @@ class ChatTagsModel: ObservableObject {
|
||||
unreadTags[tag] = (unreadTags[tag] ?? 0) + 1
|
||||
}
|
||||
} else if !nowUnread && wasUnread {
|
||||
markChatTagRead_(chat, tags)
|
||||
decTagsReadCount(tags)
|
||||
}
|
||||
}
|
||||
|
||||
private func markChatTagRead_(_ chat: Chat, _ tags: [Int64]) -> Void {
|
||||
func decTagsReadCount(_ tags: [Int64]) -> Void {
|
||||
for tag in tags {
|
||||
if let count = unreadTags[tag] {
|
||||
unreadTags[tag] = max(0, count - 1)
|
||||
|
||||
@@ -748,7 +748,11 @@ private func setChatTag(tagId: Int64?, chat: Chat, closeSheet: @escaping () -> V
|
||||
|
||||
await MainActor.run {
|
||||
let m = ChatModel.shared
|
||||
ChatTagsModel.shared.userTags = userTags
|
||||
let tm = ChatTagsModel.shared
|
||||
tm.userTags = userTags
|
||||
if chat.unreadTag, let tags = chat.chatInfo.chatTags {
|
||||
tm.decTagsReadCount(tags)
|
||||
}
|
||||
if var contact = chat.chatInfo.contact {
|
||||
contact.chatTags = chatTags
|
||||
m.updateContact(contact)
|
||||
@@ -756,6 +760,7 @@ private func setChatTag(tagId: Int64?, chat: Chat, closeSheet: @escaping () -> V
|
||||
group.chatTags = chatTags
|
||||
m.updateGroup(group)
|
||||
}
|
||||
ChatTagsModel.shared.updateChatTagRead(chat, wasUnread: false)
|
||||
closeSheet()
|
||||
}
|
||||
} catch let error {
|
||||
|
||||
+1
@@ -625,6 +625,7 @@ object ChatController {
|
||||
updateChats(chats)
|
||||
}
|
||||
chatModel.userTags.value = apiGetChatTags(rhId).takeIf { hasUser } ?: emptyList()
|
||||
chatModel.activeChatTagFilter.value = null
|
||||
chatModel.updateChatTags(rhId)
|
||||
}
|
||||
|
||||
|
||||
+91
-88
@@ -33,8 +33,7 @@ import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.views.call.Call
|
||||
import chat.simplex.common.views.chat.item.CIFileViewScope
|
||||
import chat.simplex.common.views.chat.item.ItemAction
|
||||
import chat.simplex.common.views.chat.item.*
|
||||
import chat.simplex.common.views.chat.topPaddingToContent
|
||||
import chat.simplex.common.views.newchat.*
|
||||
import chat.simplex.common.views.onboarding.*
|
||||
@@ -877,7 +876,7 @@ private fun NoChatsView(searchText: MutableState<TextFieldValue>) {
|
||||
is ActiveFilter.UserTag -> Text(String.format(generalGetString(MR.strings.no_chats_in_list), activeFilter.tag.chatTagText), color = MaterialTheme.colors.secondary, textAlign = TextAlign.Center)
|
||||
is ActiveFilter.Unread -> {
|
||||
Row(
|
||||
Modifier.clip(shape = RoundedCornerShape(percent = 50)).clickable { chatModel.activeChatTagFilter.value = null }.padding(DEFAULT_PADDING_HALF),
|
||||
Modifier.clip(shape = CircleShape).clickable { chatModel.activeChatTagFilter.value = null }.padding(DEFAULT_PADDING_HALF),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
@@ -917,6 +916,8 @@ private fun ChatListFeatureCards() {
|
||||
}
|
||||
}
|
||||
|
||||
private val TAG_MIN_HEIGHT = 35.dp
|
||||
|
||||
@Composable
|
||||
private fun TagsView() {
|
||||
val userTags = remember { chatModel.userTags }
|
||||
@@ -929,7 +930,7 @@ private fun TagsView() {
|
||||
ModalManager.start.showCustomModal { close ->
|
||||
val editMode = remember { stateGetOrPut("editMode") { false } }
|
||||
ModalView(close, showClose = true, endButtons = {
|
||||
TextButton(onClick = { editMode.value = !editMode.value }, modifier = Modifier.clip(shape = RoundedCornerShape(percent = 50))) {
|
||||
TextButton(onClick = { editMode.value = !editMode.value }, modifier = Modifier.clip(shape = CircleShape)) {
|
||||
Text(stringResource(if (editMode.value) MR.strings.cancel_verb else MR.strings.edit_verb))
|
||||
}
|
||||
}) {
|
||||
@@ -937,7 +938,7 @@ private fun TagsView() {
|
||||
}
|
||||
}
|
||||
}
|
||||
val rowSizeModifier = Modifier.sizeIn(minHeight = 35.dp * fontSizeSqrtMultiplier)
|
||||
val rowSizeModifier = Modifier.sizeIn(minHeight = TAG_MIN_HEIGHT * fontSizeSqrtMultiplier)
|
||||
|
||||
TagsRow {
|
||||
if (presetTags.size > 1) {
|
||||
@@ -946,9 +947,7 @@ private fun TagsView() {
|
||||
ExpandedTagFilterView(tag)
|
||||
}
|
||||
} else {
|
||||
Column(rowSizeModifier, verticalArrangement = Arrangement.Center) {
|
||||
CollapsedTagsFilterView()
|
||||
}
|
||||
CollapsedTagsFilterView()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -958,71 +957,68 @@ private fun TagsView() {
|
||||
else -> false
|
||||
}
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
|
||||
Column(rowSizeModifier, verticalArrangement = Arrangement.Center) {
|
||||
Row(
|
||||
Modifier
|
||||
.clip(shape = RoundedCornerShape(percent = 50))
|
||||
.combinedClickable(
|
||||
onClick = {
|
||||
if (chatModel.activeChatTagFilter.value == ActiveFilter.UserTag(tag)) {
|
||||
chatModel.activeChatTagFilter.value = null
|
||||
} else {
|
||||
chatModel.activeChatTagFilter.value = ActiveFilter.UserTag(tag)
|
||||
}
|
||||
},
|
||||
onLongClick = { showTagList() },
|
||||
interactionSource = interactionSource,
|
||||
indication = LocalIndication.current
|
||||
)
|
||||
.onRightClick { showTagList() }
|
||||
.padding(4.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (tag.chatTagEmoji != null) {
|
||||
Text(
|
||||
tag.chatTagEmoji
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
painterResource(if (current) MR.images.ic_label_filled else MR.images.ic_label),
|
||||
null,
|
||||
Modifier.size(20.dp),
|
||||
tint = if (current) MaterialTheme.colors.primary else MaterialTheme.colors.onBackground
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.width(4.dp))
|
||||
Box {
|
||||
val badgeText = if ((unreadTags[tag.chatTagId] ?: 0) > 0) " ●" else ""
|
||||
val invisibleText = buildAnnotatedString {
|
||||
append(tag.chatTagText)
|
||||
withStyle(SpanStyle(fontSize = 12.sp, fontWeight = FontWeight.SemiBold)) {
|
||||
append(badgeText)
|
||||
Row(
|
||||
rowSizeModifier
|
||||
.clip(shape = CircleShape)
|
||||
.combinedClickable(
|
||||
onClick = {
|
||||
if (chatModel.activeChatTagFilter.value == ActiveFilter.UserTag(tag)) {
|
||||
chatModel.activeChatTagFilter.value = null
|
||||
} else {
|
||||
chatModel.activeChatTagFilter.value = ActiveFilter.UserTag(tag)
|
||||
}
|
||||
},
|
||||
onLongClick = { showTagList() },
|
||||
interactionSource = interactionSource,
|
||||
indication = LocalIndication.current
|
||||
)
|
||||
.onRightClick { showTagList() }
|
||||
.padding(4.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (tag.chatTagEmoji != null) {
|
||||
ReactionIcon(tag.chatTagEmoji, fontSize = 14.sp)
|
||||
} else {
|
||||
Icon(
|
||||
painterResource(if (current) MR.images.ic_label_filled else MR.images.ic_label),
|
||||
null,
|
||||
Modifier.size(18.sp.toDp()),
|
||||
tint = if (current) MaterialTheme.colors.primary else MaterialTheme.colors.onBackground
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.width(4.dp))
|
||||
Box {
|
||||
val badgeText = if ((unreadTags[tag.chatTagId] ?: 0) > 0) " ●" else ""
|
||||
val invisibleText = buildAnnotatedString {
|
||||
append(tag.chatTagText)
|
||||
withStyle(SpanStyle(fontSize = 12.sp, fontWeight = FontWeight.SemiBold)) {
|
||||
append(badgeText)
|
||||
}
|
||||
Text(
|
||||
text = invisibleText,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = Color.Transparent,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
// Visible text with styles
|
||||
val visibleText = buildAnnotatedString {
|
||||
append(tag.chatTagText)
|
||||
withStyle(SpanStyle(fontSize = 12.sp, color = MaterialTheme.colors.primary)) {
|
||||
append(badgeText)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = visibleText,
|
||||
fontWeight = if (current) FontWeight.SemiBold else FontWeight.Normal,
|
||||
color = if (current) MaterialTheme.colors.primary else MaterialTheme.colors.secondary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = invisibleText,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 15.sp,
|
||||
color = Color.Transparent,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
// Visible text with styles
|
||||
val visibleText = buildAnnotatedString {
|
||||
append(tag.chatTagText)
|
||||
withStyle(SpanStyle(fontSize = 12.5.sp, color = MaterialTheme.colors.primary)) {
|
||||
append(badgeText)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = visibleText,
|
||||
fontWeight = if (current) FontWeight.Medium else FontWeight.Normal,
|
||||
fontSize = 15.sp,
|
||||
color = if (current) MaterialTheme.colors.primary else MaterialTheme.colors.secondary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1033,16 +1029,16 @@ private fun TagsView() {
|
||||
}
|
||||
}
|
||||
|
||||
Column(rowSizeModifier, verticalArrangement = Arrangement.Center) {
|
||||
if (userTags.value.isEmpty()) {
|
||||
Row(Modifier.clip(shape = RoundedCornerShape(percent = 50)).then(plusClickModifier).padding(vertical = 4.dp), horizontalArrangement = Arrangement.Center) {
|
||||
Icon(painterResource(MR.images.ic_add), stringResource(MR.strings.chat_list_add_list), tint = MaterialTheme.colors.secondary)
|
||||
Spacer(Modifier.width(2.dp))
|
||||
Text(stringResource(MR.strings.chat_list_add_list), color = MaterialTheme.colors.secondary)
|
||||
}
|
||||
} else {
|
||||
if (userTags.value.isEmpty()) {
|
||||
Row(rowSizeModifier.clip(shape = CircleShape).then(plusClickModifier).padding(start = 2.dp, top = 4.dp, end = 6.dp, bottom = 4.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(painterResource(MR.images.ic_add), stringResource(MR.strings.chat_list_add_list), Modifier.size(18.sp.toDp()), tint = MaterialTheme.colors.secondary)
|
||||
Spacer(Modifier.width(2.dp))
|
||||
Text(stringResource(MR.strings.chat_list_add_list), color = MaterialTheme.colors.secondary, fontSize = 15.sp)
|
||||
}
|
||||
} else {
|
||||
Box(rowSizeModifier, contentAlignment = Alignment.Center) {
|
||||
Icon(
|
||||
painterResource(MR.images.ic_add), stringResource(MR.strings.chat_list_add_list), Modifier.clip(shape = CircleShape).then(plusClickModifier).padding(4.dp), tint = MaterialTheme.colors.secondary
|
||||
painterResource(MR.images.ic_add), stringResource(MR.strings.chat_list_add_list), Modifier.clip(shape = CircleShape).then(plusClickModifier).padding(2.dp), tint = MaterialTheme.colors.secondary
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1074,12 +1070,13 @@ private fun ExpandedTagFilterView(tag: PresetTagKind) {
|
||||
is ActiveFilter.PresetTag -> af.tag == tag
|
||||
else -> false
|
||||
}
|
||||
val rowSizeModifier = Modifier.sizeIn(minHeight = TAG_MIN_HEIGHT * fontSizeSqrtMultiplier)
|
||||
val (icon, text) = presetTagLabel(tag, active)
|
||||
val color = if (active) MaterialTheme.colors.primary else MaterialTheme.colors.secondary
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clip(shape = RoundedCornerShape(percent = 50))
|
||||
modifier = rowSizeModifier
|
||||
.clip(shape = CircleShape)
|
||||
.clickable {
|
||||
if (activeFilter.value == ActiveFilter.PresetTag(tag)) {
|
||||
chatModel.activeChatTagFilter.value = null
|
||||
@@ -1087,7 +1084,7 @@ private fun ExpandedTagFilterView(tag: PresetTagKind) {
|
||||
chatModel.activeChatTagFilter.value = ActiveFilter.PresetTag(tag)
|
||||
}
|
||||
}
|
||||
.padding(4.dp)
|
||||
.padding(horizontal = 5.dp, vertical = 4.dp)
|
||||
,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center
|
||||
@@ -1095,6 +1092,7 @@ private fun ExpandedTagFilterView(tag: PresetTagKind) {
|
||||
Icon(
|
||||
painterResource(icon),
|
||||
stringResource(text),
|
||||
Modifier.size(18.sp.toDp()),
|
||||
tint = color
|
||||
)
|
||||
Spacer(Modifier.width(4.dp))
|
||||
@@ -1102,12 +1100,14 @@ private fun ExpandedTagFilterView(tag: PresetTagKind) {
|
||||
Text(
|
||||
stringResource(text),
|
||||
color = if (active) MaterialTheme.colors.primary else MaterialTheme.colors.secondary,
|
||||
fontWeight = if (active) FontWeight.SemiBold else FontWeight.Normal,
|
||||
fontWeight = if (active) FontWeight.Medium else FontWeight.Normal,
|
||||
fontSize = 15.sp
|
||||
)
|
||||
Text(
|
||||
stringResource(text),
|
||||
color = Color.Transparent,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 15.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1125,17 +1125,20 @@ private fun CollapsedTagsFilterView() {
|
||||
else -> null
|
||||
}
|
||||
|
||||
Column(Modifier
|
||||
val rowSizeModifier = Modifier.sizeIn(minHeight = TAG_MIN_HEIGHT * fontSizeSqrtMultiplier)
|
||||
Box(rowSizeModifier
|
||||
.padding(vertical = 4.dp)
|
||||
.clip(shape = CircleShape)
|
||||
.clickable { showMenu.value = true }
|
||||
.padding(4.dp)
|
||||
.size(30.sp.toDp())
|
||||
.clickable { showMenu.value = true },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (selectedPresetTag != null) {
|
||||
val (icon, text) = presetTagLabel(selectedPresetTag, true)
|
||||
|
||||
Icon(
|
||||
painterResource(icon),
|
||||
stringResource(text),
|
||||
Modifier.size(18.sp.toDp()),
|
||||
tint = MaterialTheme.colors.secondary
|
||||
)
|
||||
} else {
|
||||
|
||||
+42
-51
@@ -14,6 +14,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.MaterialTheme.colors
|
||||
import androidx.compose.material.TextFieldDefaults.indicatorLine
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -35,6 +36,7 @@ import chat.simplex.common.model.ChatModel.withChats
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.views.chat.item.ItemAction
|
||||
import chat.simplex.common.views.chat.item.ReactionIcon
|
||||
import chat.simplex.common.views.chat.topPaddingToContent
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.res.MR
|
||||
@@ -148,11 +150,9 @@ fun TagListView(rhId: Long?, chat: Chat? = null, close: () -> Unit, editMode: Mu
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (tag.chatTagEmoji != null) {
|
||||
Text(
|
||||
tag.chatTagEmoji
|
||||
)
|
||||
ReactionIcon(tag.chatTagEmoji, fontSize = 14.sp)
|
||||
} else {
|
||||
Icon(painterResource(MR.images.ic_label), null, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
||||
Icon(painterResource(MR.images.ic_label), null, Modifier.size(18.sp.toDp()), tint = MaterialTheme.colors.onBackground)
|
||||
}
|
||||
Spacer(Modifier.padding(horizontal = 4.dp))
|
||||
Text(
|
||||
@@ -196,7 +196,6 @@ fun ModalData.TagListEditor(
|
||||
) {
|
||||
val userTags = remember { chatModel.userTags }
|
||||
val oneHandUI = remember { appPrefs.oneHandUI.state }
|
||||
val keyboardState by getKeyboardState()
|
||||
val newEmoji = remember { stateGetOrPutNullable("chatTagEmoji") { emoji } }
|
||||
val newName = remember { stateGetOrPut("chatTagName") { name } }
|
||||
val saving = remember { mutableStateOf<Boolean?>(null) }
|
||||
@@ -351,53 +350,45 @@ expect fun ChatTagInput(name: MutableState<String>, showError: State<Boolean>, e
|
||||
fun TagListNameTextField(name: MutableState<String>, showError: State<Boolean>) {
|
||||
var focused by rememberSaveable { mutableStateOf(false) }
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val strokeColor by remember {
|
||||
derivedStateOf {
|
||||
if (showError.value) {
|
||||
Color.Red
|
||||
} else {
|
||||
if (focused) {
|
||||
CurrentColors.value.colors.secondary.copy(alpha = 0.6f)
|
||||
} else {
|
||||
CurrentColors.value.colors.secondary.copy(alpha = 0.3f)
|
||||
}
|
||||
}
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val colors = TextFieldDefaults.textFieldColors(
|
||||
backgroundColor = Color.Unspecified,
|
||||
focusedIndicatorColor = MaterialTheme.colors.secondary.copy(alpha = 0.6f),
|
||||
unfocusedIndicatorColor = CurrentColors.value.colors.secondary.copy(alpha = 0.3f),
|
||||
cursorColor = MaterialTheme.colors.secondary,
|
||||
)
|
||||
BasicTextField(
|
||||
value = name.value,
|
||||
onValueChange = { name.value = it },
|
||||
interactionSource = interactionSource,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.indicatorLine(true, showError.value, interactionSource, colors)
|
||||
.heightIn(min = TextFieldDefaults.MinHeight)
|
||||
.onFocusChanged { focused = it.isFocused }
|
||||
.focusRequester(focusRequester),
|
||||
textStyle = TextStyle(fontSize = 18.sp, color = MaterialTheme.colors.onBackground),
|
||||
singleLine = true,
|
||||
cursorBrush = SolidColor(MaterialTheme.colors.secondary),
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
TextFieldDefaults.TextFieldDecorationBox(
|
||||
value = name.value,
|
||||
innerTextField = innerTextField,
|
||||
placeholder = {
|
||||
Text(generalGetString(MR.strings.list_name_field_placeholder), style = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.secondary, lineHeight = 22.sp))
|
||||
},
|
||||
contentPadding = PaddingValues(),
|
||||
label = null,
|
||||
visualTransformation = VisualTransformation.None,
|
||||
leadingIcon = null,
|
||||
singleLine = true,
|
||||
enabled = true,
|
||||
isError = false,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
colors = TextFieldDefaults.textFieldColors(backgroundColor = Color.Unspecified)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
BasicTextField(
|
||||
value = name.value,
|
||||
onValueChange = { name.value = it },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 50.dp)
|
||||
.onFocusChanged { focused = it.isFocused }
|
||||
.focusRequester(focusRequester),
|
||||
textStyle = TextStyle(fontSize = 18.sp, color = colors.onBackground),
|
||||
singleLine = true,
|
||||
cursorBrush = SolidColor(MaterialTheme.colors.secondary),
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
TextFieldDefaults.TextFieldDecorationBox(
|
||||
value = name.value,
|
||||
innerTextField = innerTextField,
|
||||
placeholder = {
|
||||
Text(generalGetString(MR.strings.list_name_field_placeholder), style = MaterialTheme.typography.body1.copy(color = MaterialTheme.colors.secondary, lineHeight = 22.sp))
|
||||
},
|
||||
contentPadding = PaddingValues(),
|
||||
label = null,
|
||||
visualTransformation = VisualTransformation.None,
|
||||
leadingIcon = null,
|
||||
singleLine = true,
|
||||
enabled = true,
|
||||
isError = false,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
colors = TextFieldDefaults.textFieldColors(backgroundColor = Color.Unspecified)
|
||||
)
|
||||
}
|
||||
)
|
||||
Divider(color = strokeColor, thickness = if (focused) 2.dp else 1.dp)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun setTag(rhId: Long?, tagId: Long?, chat: Chat, close: () -> Unit) {
|
||||
|
||||
+35
-20
@@ -5,13 +5,19 @@ import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.simplex.common.ui.theme.CurrentColors
|
||||
import chat.simplex.common.ui.theme.DEFAULT_PADDING
|
||||
import androidx.compose.ui.unit.sp
|
||||
import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.ui.theme.ThemeManager.colorFromReadableHex
|
||||
import chat.simplex.common.views.chat.item.isHeartEmoji
|
||||
import chat.simplex.common.views.chat.item.isShortEmoji
|
||||
import chat.simplex.common.views.helpers.toDp
|
||||
import chat.simplex.res.MR
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
|
||||
@@ -27,31 +33,40 @@ actual fun ChatTagInput(name: MutableState<String>, showError: State<Boolean>, e
|
||||
private fun SingleEmojiInput(
|
||||
emoji: MutableState<String?>
|
||||
) {
|
||||
val state = remember { mutableStateOf(TextFieldValue(emoji.value ?: "")) }
|
||||
val colors = TextFieldDefaults.textFieldColors(
|
||||
textColor = if (isHeartEmoji(emoji.value ?: "")) Color(0xffD63C31) else MaterialTheme.colors.onPrimary,
|
||||
backgroundColor = Color.Unspecified,
|
||||
focusedIndicatorColor = MaterialTheme.colors.secondary.copy(alpha = 0.6f),
|
||||
unfocusedIndicatorColor = CurrentColors.value.colors.secondary.copy(alpha = 0.3f),
|
||||
cursorColor = MaterialTheme.colors.secondary,
|
||||
)
|
||||
TextField(
|
||||
value = emoji.value?.let { TextFieldValue(it) } ?: TextFieldValue(""),
|
||||
value = state.value,
|
||||
onValueChange = { newValue ->
|
||||
if (newValue.text == emoji.value) return@TextField
|
||||
if (newValue.text == emoji.value) {
|
||||
state.value = newValue
|
||||
return@TextField
|
||||
}
|
||||
val newValueClamped = newValue.text.replace(emoji.value ?: "", "")
|
||||
emoji.value = if (isShortEmoji(newValueClamped)) newValueClamped else null
|
||||
val isEmoji = isShortEmoji(newValueClamped)
|
||||
emoji.value = if (isEmoji) newValueClamped else null
|
||||
state.value = if (isEmoji) newValue else TextFieldValue()
|
||||
},
|
||||
singleLine = true,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.size(60.dp)
|
||||
.padding(4.dp),
|
||||
.padding(4.dp)
|
||||
.size(width = TextFieldDefaults.MinHeight.value.sp.toDp(), height = TextFieldDefaults.MinHeight),
|
||||
textStyle = LocalTextStyle.current.copy(fontFamily = EmojiFont, textAlign = TextAlign.Center),
|
||||
placeholder = {
|
||||
Icon(
|
||||
painter = painterResource(MR.images.ic_add_reaction),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colors.secondary
|
||||
)
|
||||
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Icon(
|
||||
painter = painterResource(MR.images.ic_add_reaction),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colors.secondary
|
||||
)
|
||||
}
|
||||
},
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
backgroundColor = Color.Unspecified,
|
||||
focusedIndicatorColor = MaterialTheme.colors.secondary.copy(alpha = 0.6f),
|
||||
unfocusedIndicatorColor = CurrentColors.value.colors.secondary.copy(alpha = 0.3f),
|
||||
cursorColor = MaterialTheme.colors.secondary,
|
||||
),
|
||||
colors = colors,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user