Fixes UTF-32 Reactions
This commit is contained in:
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,6 +48,7 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
|||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.model.UserMetadata
|
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.LnZapEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.LnZapRequestEvent
|
import com.vitorpamplona.amethyst.service.model.LnZapRequestEvent
|
||||||
import com.vitorpamplona.amethyst.ui.actions.ImmutableListOfLists
|
import com.vitorpamplona.amethyst.ui.actions.ImmutableListOfLists
|
||||||
@@ -180,7 +181,7 @@ fun RenderLikeGallery(
|
|||||||
|
|
||||||
val shortReaction by remember {
|
val shortReaction by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
reactionType.take(2)
|
reactionType.firstFullChar()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ import coil.request.CachePolicy
|
|||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.service.firstFullChar
|
||||||
import com.vitorpamplona.amethyst.ui.actions.NewPostView
|
import com.vitorpamplona.amethyst.ui.actions.NewPostView
|
||||||
import com.vitorpamplona.amethyst.ui.screen.CombinedZap
|
import com.vitorpamplona.amethyst.ui.screen.CombinedZap
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
@@ -677,7 +678,7 @@ fun LikeIcon(
|
|||||||
|
|
||||||
LaunchedEffect(key1 = reactionsState) {
|
LaunchedEffect(key1 = reactionsState) {
|
||||||
launch(Dispatchers.Default) {
|
launch(Dispatchers.Default) {
|
||||||
val newReactionType = reactionsState?.note?.isReactedBy(accountViewModel.userProfile())?.take(2)
|
val newReactionType = reactionsState?.note?.isReactedBy(accountViewModel.userProfile())?.firstFullChar()
|
||||||
if (reactionType != newReactionType) {
|
if (reactionType != newReactionType) {
|
||||||
reactionType = newReactionType
|
reactionType = newReactionType
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Account
|
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.CloseButton
|
||||||
import com.vitorpamplona.amethyst.ui.actions.SaveButton
|
import com.vitorpamplona.amethyst.ui.actions.SaveButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
@@ -64,7 +65,7 @@ class UpdateReactionTypeViewModel(val account: Account) : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addChoice() {
|
fun addChoice() {
|
||||||
val newValue = nextChoice.text.trim().take(2)
|
val newValue = nextChoice.text.trim().firstFullChar()
|
||||||
reactionSet = reactionSet + newValue
|
reactionSet = reactionSet + newValue
|
||||||
|
|
||||||
nextChoice = TextFieldValue("")
|
nextChoice = TextFieldValue("")
|
||||||
|
|||||||
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user