From ad281c76072cf5df334c1b053fb0ffd4299b17d6 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 5 Jun 2024 16:28:44 -0400 Subject: [PATCH] BugFix crashing with old keyboards: Forces transformations to have middle positions before the last cursor position. --- .../amethyst/UrlUserTagTransformationTest.kt | 147 +++++++++++++++++- .../ui/actions/UrlUserTagTransformation.kt | 125 +++++++-------- 2 files changed, 199 insertions(+), 73 deletions(-) diff --git a/app/src/androidTest/java/com/vitorpamplona/amethyst/UrlUserTagTransformationTest.kt b/app/src/androidTest/java/com/vitorpamplona/amethyst/UrlUserTagTransformationTest.kt index 92f0af91b..7616ecabd 100644 --- a/app/src/androidTest/java/com/vitorpamplona/amethyst/UrlUserTagTransformationTest.kt +++ b/app/src/androidTest/java/com/vitorpamplona/amethyst/UrlUserTagTransformationTest.kt @@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.input.TransformedText import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.vitorpamplona.amethyst.model.LocalCache @@ -47,6 +48,136 @@ class UrlUserTagTransformationTest { assertEquals("com.vitorpamplona.amethyst", appContext.packageName.removeSuffix(".debug")) } + fun debugCursor( + original: String, + transformedText: TransformedText, + offset: Int, + ): String { + val offsetTransformed = transformedText.offsetMapping.originalToTransformed(offset) + val originalWithCursor = original.substring(0, offset) + "|" + original.substring(offset, original.length) + val transformedWithCursor = transformedText.text.text.substring(0, offsetTransformed) + "|" + transformedText.text.text.substring(offsetTransformed, transformedText.text.text.length) + return "$originalWithCursor $transformedWithCursor" + } + + fun debugCursorReverse( + original: String, + transformedText: TransformedText, + offsetTransformed: Int, + ): String { + val offset = transformedText.offsetMapping.transformedToOriginal(offsetTransformed) + val originalWithCursor = original.substring(0, offset) + "|" + original.substring(offset, original.length) + val transformedWithCursor = transformedText.text.text.substring(0, offsetTransformed) + "|" + transformedText.text.text.substring(offsetTransformed, transformedText.text.text.length) + return "$originalWithCursor $transformedWithCursor" + } + + @Test + fun testKeepTransformedIndexFullyInsideTransformedText() { + val user = + LocalCache.getOrCreateUser( + decodePublicKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z") + .toHexKey(), + ) + user.info = UserMetadata() + user.info?.displayName = "Vitor Pamplona" + + val original = "@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z" + + val transformedText = + buildAnnotatedStringWithUrlHighlighting( + AnnotatedString(original), + Color.Red, + ) + + val expected = "@Vitor Pamplona" + assertEquals(expected, transformedText.text.text) + + assertEquals("|@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 0)) + assertEquals("@|npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 1)) + assertEquals("@n|pub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 2)) + assertEquals("@np|ub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 3)) + assertEquals("@npu|b1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 4)) + assertEquals("@npub|1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursor(original, transformedText, 5)) + assertEquals("@npub1|gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursor(original, transformedText, 6)) + assertEquals("@npub1g|cxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursor(original, transformedText, 7)) + assertEquals("@npub1gc|xzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursor(original, transformedText, 8)) + assertEquals("@npub1gcx|zte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursor(original, transformedText, 9)) + assertEquals("@npub1gcxz|te5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursor(original, transformedText, 10)) + assertEquals("@npub1gcxzt|e5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursor(original, transformedText, 11)) + assertEquals("@npub1gcxzte|5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursor(original, transformedText, 12)) + assertEquals("@npub1gcxzte5|zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 13)) + assertEquals("@npub1gcxzte5z|lkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 14)) + assertEquals("@npub1gcxzte5zl|kncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 15)) + assertEquals("@npub1gcxzte5zlk|ncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 16)) + assertEquals("@npub1gcxzte5zlkn|cx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 17)) + assertEquals("@npub1gcxzte5zlknc|x26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursor(original, transformedText, 18)) + assertEquals("@npub1gcxzte5zlkncx|26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursor(original, transformedText, 19)) + assertEquals("@npub1gcxzte5zlkncx2|6j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursor(original, transformedText, 20)) + assertEquals("@npub1gcxzte5zlkncx26|j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursor(original, transformedText, 21)) + assertEquals("@npub1gcxzte5zlkncx26j|68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursor(original, transformedText, 22)) + assertEquals("@npub1gcxzte5zlkncx26j6|8ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursor(original, transformedText, 23)) + assertEquals("@npub1gcxzte5zlkncx26j68|ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursor(original, transformedText, 24)) + assertEquals("@npub1gcxzte5zlkncx26j68e|z60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursor(original, transformedText, 25)) + assertEquals("@npub1gcxzte5zlkncx26j68ez|60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursor(original, transformedText, 26)) + assertEquals("@npub1gcxzte5zlkncx26j68ez6|0fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursor(original, transformedText, 27)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60|fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursor(original, transformedText, 28)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60f|zkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursor(original, transformedText, 29)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fz|kvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 30)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzk|vtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 31)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkv|tkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 32)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvt|km9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 33)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtk|m9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 34)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm|9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursor(original, transformedText, 35)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9|e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursor(original, transformedText, 36)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e|0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursor(original, transformedText, 37)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0|vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursor(original, transformedText, 38)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0v|rwdcvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursor(original, transformedText, 39)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vr|wdcvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursor(original, transformedText, 40)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrw|dcvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursor(original, transformedText, 41)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwd|cvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursor(original, transformedText, 42)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdc|vsjakxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursor(original, transformedText, 43)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcv|sjakxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursor(original, transformedText, 44)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvs|jakxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursor(original, transformedText, 45)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsj|akxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursor(original, transformedText, 46)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsja|kxf9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 47)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjak|xf9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 48)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakx|f9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 49)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf|9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 50)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9|mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 51)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9m|u9qewqlfnj5z @Vitor Pampl|ona", debugCursor(original, transformedText, 52)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu|9qewqlfnj5z @Vitor Pampl|ona", debugCursor(original, transformedText, 53)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9|qewqlfnj5z @Vitor Pampl|ona", debugCursor(original, transformedText, 54)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9q|ewqlfnj5z @Vitor Pampl|ona", debugCursor(original, transformedText, 55)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qe|wqlfnj5z @Vitor Pamplo|na", debugCursor(original, transformedText, 56)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qew|qlfnj5z @Vitor Pamplo|na", debugCursor(original, transformedText, 57)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewq|lfnj5z @Vitor Pamplo|na", debugCursor(original, transformedText, 58)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewql|fnj5z @Vitor Pamplo|na", debugCursor(original, transformedText, 59)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlf|nj5z @Vitor Pamplon|a", debugCursor(original, transformedText, 60)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfn|j5z @Vitor Pamplon|a", debugCursor(original, transformedText, 61)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj|5z @Vitor Pamplon|a", debugCursor(original, transformedText, 62)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5|z @Vitor Pamplon|a", debugCursor(original, transformedText, 63)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z| @Vitor Pamplona|", debugCursor(original, transformedText, 64)) + + assertEquals("|@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursorReverse(original, transformedText, 0)) + assertEquals("@npu|b1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursorReverse(original, transformedText, 1)) + assertEquals("@npub1gc|xzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursorReverse(original, transformedText, 2)) + assertEquals("@npub1gcxzte|5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursorReverse(original, transformedText, 3)) + assertEquals("@npub1gcxzte5zlkn|cx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursorReverse(original, transformedText, 4)) + assertEquals("@npub1gcxzte5zlkncx26|j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursorReverse(original, transformedText, 5)) + assertEquals("@npub1gcxzte5zlkncx26j68e|z60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursorReverse(original, transformedText, 6)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60f|zkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursorReverse(original, transformedText, 7)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtk|m9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursorReverse(original, transformedText, 8)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0|vrwdcvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursorReverse(original, transformedText, 9)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwd|cvsjakxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursorReverse(original, transformedText, 10)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsj|akxf9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursorReverse(original, transformedText, 11)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9|mu9qewqlfnj5z @Vitor Pampl|ona", debugCursorReverse(original, transformedText, 12)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9q|ewqlfnj5z @Vitor Pamplo|na", debugCursorReverse(original, transformedText, 13)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewql|fnj5z @Vitor Pamplon|a", debugCursorReverse(original, transformedText, 14)) + assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z| @Vitor Pamplona|", debugCursorReverse(original, transformedText, 15)) + + assertEquals(0, transformedText.offsetMapping.originalToTransformed(0)) + assertEquals(15, transformedText.offsetMapping.originalToTransformed(64)) + } + @Test fun transformationText() { val user = @@ -70,11 +201,11 @@ class UrlUserTagTransformationTest { assertEquals(8, transformedText.offsetMapping.originalToTransformed(8)) // Before @ assertEquals(8, transformedText.offsetMapping.originalToTransformed(9)) // Before n assertEquals(8, transformedText.offsetMapping.originalToTransformed(10)) // Before p - assertEquals(9, transformedText.offsetMapping.originalToTransformed(11)) // Before u - assertEquals(9, transformedText.offsetMapping.originalToTransformed(12)) // Before b + assertEquals(8, transformedText.offsetMapping.originalToTransformed(11)) // Before u + assertEquals(8, transformedText.offsetMapping.originalToTransformed(12)) // Before b assertEquals(9, transformedText.offsetMapping.originalToTransformed(13)) // Before 1 - assertEquals(23, transformedText.offsetMapping.originalToTransformed(71)) + assertEquals(22, transformedText.offsetMapping.originalToTransformed(71)) assertEquals(23, transformedText.offsetMapping.originalToTransformed(72)) assertEquals(0, transformedText.offsetMapping.transformedToOriginal(0)) @@ -106,12 +237,12 @@ class UrlUserTagTransformationTest { assertEquals("New Hey @Vitor Pamplona and @Vitor Pamplona", transformedText.text.text) - assertEquals(9, transformedText.offsetMapping.originalToTransformed(11)) - assertEquals(9, transformedText.offsetMapping.originalToTransformed(12)) + assertEquals(8, transformedText.offsetMapping.originalToTransformed(11)) + assertEquals(8, transformedText.offsetMapping.originalToTransformed(12)) assertEquals(9, transformedText.offsetMapping.originalToTransformed(13)) - assertEquals(23, transformedText.offsetMapping.originalToTransformed(70)) // Before 5 - assertEquals(23, transformedText.offsetMapping.originalToTransformed(71)) // Before z + assertEquals(22, transformedText.offsetMapping.originalToTransformed(70)) // Before 5 + assertEquals(22, transformedText.offsetMapping.originalToTransformed(71)) // Before z assertEquals(23, transformedText.offsetMapping.originalToTransformed(72)) // Before assertEquals(24, transformedText.offsetMapping.originalToTransformed(73)) // Before a assertEquals(25, transformedText.offsetMapping.originalToTransformed(74)) // Before n @@ -120,7 +251,7 @@ class UrlUserTagTransformationTest { assertEquals(28, transformedText.offsetMapping.originalToTransformed(77)) // Before @ assertEquals(28, transformedText.offsetMapping.originalToTransformed(78)) // Before n - assertEquals(68, transformedText.offsetMapping.transformedToOriginal(22)) // Before a + assertEquals(67, transformedText.offsetMapping.transformedToOriginal(22)) // Before a assertEquals(72, transformedText.offsetMapping.transformedToOriginal(23)) // Before assertEquals(73, transformedText.offsetMapping.transformedToOriginal(24)) // Before a assertEquals(74, transformedText.offsetMapping.transformedToOriginal(25)) // Before n diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/UrlUserTagTransformation.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/UrlUserTagTransformation.kt index de8140fbe..7c2c34965 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/UrlUserTagTransformation.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/UrlUserTagTransformation.kt @@ -34,7 +34,6 @@ import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.quartz.encoders.decodePublicKey import com.vitorpamplona.quartz.encoders.toHexKey import kotlin.coroutines.cancellation.CancellationException -import kotlin.math.roundToInt data class RangesChanges(val original: TextRange, val modified: TextRange) @@ -55,71 +54,69 @@ fun buildAnnotatedStringWithUrlHighlighting( val builderBefore = StringBuilder() // important to correctly measure Tag start and end val builderAfter = StringBuilder() // important to correctly measure Tag start and end append( - text - .split('\n').joinToString("\n") { paragraph: String -> - paragraph - .split(' ').joinToString(" ") { word: String -> - try { - if (word.startsWith("@npub") && word.length >= 64) { - val keyB32 = word.substring(0, 64) - val restOfWord = word.substring(64) + text.text.split('\n').joinToString("\n") { paragraph: String -> + paragraph.split(' ').joinToString(" ") { word: String -> + try { + if (word.startsWith("@npub") && word.length >= 64) { + val keyB32 = word.substring(0, 64) + val restOfWord = word.substring(64) - val startIndex = builderBefore.toString().length + val startIndex = builderBefore.toString().length - builderBefore.append( - "$keyB32$restOfWord ", - ) // accounts for the \n at the end of each paragraph + builderBefore.append( + "$keyB32$restOfWord ", + ) // accounts for the \n at the end of each paragraph - val endIndex = startIndex + keyB32.length + val endIndex = startIndex + keyB32.length - val key = decodePublicKey(keyB32.removePrefix("@")) - val user = LocalCache.getOrCreateUser(key.toHexKey()) + val key = decodePublicKey(keyB32.removePrefix("@")) + val user = LocalCache.getOrCreateUser(key.toHexKey()) - val newWord = "@${user.toBestDisplayName()}" - val startNew = builderAfter.toString().length + val newWord = "@${user.toBestDisplayName()}" + val startNew = builderAfter.toString().length - builderAfter.append( - "$newWord$restOfWord ", - ) // accounts for the \n at the end of each paragraph + builderAfter.append( + "$newWord$restOfWord ", + ) // accounts for the \n at the end of each paragraph - substitutions.add( - RangesChanges( - TextRange(startIndex, endIndex), - TextRange(startNew, startNew + newWord.length), - ), - ) - newWord + restOfWord - } else if (Patterns.WEB_URL.matcher(word).matches()) { - val startIndex = builderBefore.toString().length - val endIndex = startIndex + word.length + substitutions.add( + RangesChanges( + TextRange(startIndex, endIndex), + TextRange(startNew, startNew + newWord.length), + ), + ) + newWord + restOfWord + } else if (Patterns.WEB_URL.matcher(word).matches()) { + val startIndex = builderBefore.toString().length + val endIndex = startIndex + word.length - val startNew = builderAfter.toString().length - val endNew = startNew + word.length + val startNew = builderAfter.toString().length + val endNew = startNew + word.length - substitutions.add( - RangesChanges( - TextRange(startIndex, endIndex), - TextRange(startNew, endNew), - ), - ) + substitutions.add( + RangesChanges( + TextRange(startIndex, endIndex), + TextRange(startNew, endNew), + ), + ) - builderBefore.append("$word ") - builderAfter.append("$word ") - word - } else { - builderBefore.append("$word ") - builderAfter.append("$word ") - word - } - } catch (e: Exception) { - if (e is CancellationException) throw e - // if it can't parse the key, don't try to change. - builderBefore.append("$word ") - builderAfter.append("$word ") - word - } + builderBefore.append("$word ") + builderAfter.append("$word ") + word + } else { + builderBefore.append("$word ") + builderAfter.append("$word ") + word } - }, + } catch (e: Exception) { + if (e is CancellationException) throw e + // if it can't parse the key, don't try to change. + builderBefore.append("$word ") + builderAfter.append("$word ") + word + } + } + }, ) substitutions.forEach { @@ -144,16 +141,15 @@ fun buildAnnotatedStringWithUrlHighlighting( if (inInsideRange != null) { val percentInRange = (offset - inInsideRange.original.start) / (inInsideRange.original.length.toFloat()) - return (inInsideRange.modified.start + inInsideRange.modified.length * percentInRange) - .roundToInt() + return (inInsideRange.modified.start + inInsideRange.modified.length * percentInRange).toInt() } val lastRangeThrough = substitutions.lastOrNull { offset >= it.original.end } - if (lastRangeThrough != null) { - return lastRangeThrough.modified.end + (offset - lastRangeThrough.original.end) + return if (lastRangeThrough != null) { + lastRangeThrough.modified.end + (offset - lastRangeThrough.original.end) } else { - return offset + offset } } @@ -164,16 +160,15 @@ fun buildAnnotatedStringWithUrlHighlighting( if (inInsideRange != null) { val percentInRange = (offset - inInsideRange.modified.start) / (inInsideRange.modified.length.toFloat()) - return (inInsideRange.original.start + inInsideRange.original.length * percentInRange) - .roundToInt() + return (inInsideRange.original.start + inInsideRange.original.length * percentInRange).toInt() } val lastRangeThrough = substitutions.lastOrNull { offset >= it.modified.end } - if (lastRangeThrough != null) { - return lastRangeThrough.original.end + (offset - lastRangeThrough.modified.end) + return if (lastRangeThrough != null) { + lastRangeThrough.original.end + (offset - lastRangeThrough.modified.end) } else { - return offset + offset } } }