diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/StringUtils.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/StringUtils.kt new file mode 100644 index 000000000..2fda4bc5c --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/StringUtils.kt @@ -0,0 +1,23 @@ +package com.vitorpamplona.amethyst.service + +fun String.isUTF16Char(pos: Int): Boolean { + return Character.charCount(this.codePointAt(pos)) == 2 +} + +fun String.firstFullChar(): String { + return when (this.length) { + 0, 1 -> return this + 2, 3 -> return if (isUTF16Char(0)) this.take(2) else this.take(1) + else -> { + val first = isUTF16Char(0) + val second = isUTF16Char(2) + if (first && second) { + this.take(4) + } else if (first) { + this.take(2) + } else { + this.take(1) + } + } + } +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt index 2bce342e8..0cc6cdba5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt @@ -48,6 +48,7 @@ import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.UserMetadata +import com.vitorpamplona.amethyst.service.firstFullChar import com.vitorpamplona.amethyst.service.model.LnZapEvent import com.vitorpamplona.amethyst.service.model.LnZapRequestEvent import com.vitorpamplona.amethyst.ui.actions.ImmutableListOfLists @@ -180,7 +181,7 @@ fun RenderLikeGallery( val shortReaction by remember { derivedStateOf { - reactionType.take(2) + reactionType.firstFullChar() } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index 108ec561c..50f38bb87 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -65,6 +65,7 @@ import coil.request.CachePolicy import coil.request.ImageRequest import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.service.firstFullChar import com.vitorpamplona.amethyst.ui.actions.NewPostView import com.vitorpamplona.amethyst.ui.screen.CombinedZap import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -677,7 +678,7 @@ fun LikeIcon( LaunchedEffect(key1 = reactionsState) { launch(Dispatchers.Default) { - val newReactionType = reactionsState?.note?.isReactedBy(accountViewModel.userProfile())?.take(2) + val newReactionType = reactionsState?.note?.isReactedBy(accountViewModel.userProfile())?.firstFullChar() if (reactionType != newReactionType) { reactionType = newReactionType } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateReactionTypeDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateReactionTypeDialog.kt index b7ba43edc..143090947 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateReactionTypeDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateReactionTypeDialog.kt @@ -45,6 +45,7 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Account +import com.vitorpamplona.amethyst.service.firstFullChar import com.vitorpamplona.amethyst.ui.actions.CloseButton import com.vitorpamplona.amethyst.ui.actions.SaveButton import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -64,7 +65,7 @@ class UpdateReactionTypeViewModel(val account: Account) : ViewModel() { } fun addChoice() { - val newValue = nextChoice.text.trim().take(2) + val newValue = nextChoice.text.trim().firstFullChar() reactionSet = reactionSet + newValue nextChoice = TextFieldValue("") diff --git a/app/src/test/java/com/vitorpamplona/amethyst/CharsetTest.kt b/app/src/test/java/com/vitorpamplona/amethyst/CharsetTest.kt new file mode 100644 index 000000000..13b862152 --- /dev/null +++ b/app/src/test/java/com/vitorpamplona/amethyst/CharsetTest.kt @@ -0,0 +1,37 @@ +package com.vitorpamplona.amethyst + +import com.vitorpamplona.amethyst.service.firstFullChar +import org.junit.Assert +import org.junit.Test + +class CharsetTest { + @Test + fun testASCIIChar() { + Assert.assertEquals("H", "Hi".firstFullChar()) + } + + @Test + fun testUTF16Char() { + Assert.assertEquals("\uD83C\uDF48", "\uD83C\uDF48Hi".firstFullChar()) + } + + @Test + fun testUTF32Char() { + Assert.assertEquals("\uD83E\uDDD1\uD83C\uDFFE", "\uD83E\uDDD1\uD83C\uDFFEHi".firstFullChar()) + } + + @Test + fun testAsciiWithUTF32Char() { + Assert.assertEquals("H", "Hi\uD83E\uDDD1\uD83C\uDFFEHi".firstFullChar()) + } + + @Test + fun testBlank() { + Assert.assertEquals("", "".firstFullChar()) + } + + @Test + fun testSpecialChars() { + Assert.assertEquals("=", "=x".firstFullChar()) + } +}