Repository: tuskyapp/Tusky (language: kotlin)

Issue:
Tusky URL detection breaks if capital letters in scheme://
### Steps to reproduce the problem

1. Open Compose in Mastodon Web on PC, and Tusky side by side.
2. In both, type: `Https://example.com` or `HTTPS://EXAMPLE.COM`

**Expected behavior:** Mastodon Web and Tusky should have identical behavior.

**Observed behavior:** Mastodon Web recognizes this as a url the moment you type the letter "O". Tusky cannot recognize anything as a URL, whether typed or pasted, if "https" contains an uppercase letter. After typing the url Tusky predicts 481 letters and Mastodon Web predicts 477 characters.

RFC 1738 §2.1 states clients such as Tusky should accept URL scheme as case insensitive.

#### Notes

This causes problems on my phone because GBoard wants to capitalize the leading H in a URL.

### Debug information

mastodon.social, Android 13, Tusky 26.1 from Play Store


Discussion hints:
nan

Pull request: Fix detecting urls
closes #4641 

Test command: ./gradlew :app:testBlueDebugUnitTest --tests "com.keylesspalace.tusky.SpanUtilsTest" --tests "com.keylesspalace.tusky.components.compose.StatusLengthTest"

Fix patch:
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/SpanUtils.kt b/app/src/main/java/com/keylesspalace/tusky/util/SpanUtils.kt
index 0a6b1ca00e..4da9b16d46 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/SpanUtils.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/util/SpanUtils.kt
@@ -66,7 +66,7 @@ fun Spannable.highlightSpans(colour: Int, finders: List<PatternFinder> = default
 
     for (finder in finders) {
         // before running the regular expression, check if there is even a chance of it finding something
-        if (this.contains(finder.searchString)) {
+        if (this.contains(finder.searchString, ignoreCase = true)) {
             val matcher = finder.pattern.matcher(this)
 
             while (matcher.find()) {


Test patch:
diff --git a/app/src/test/java/com/keylesspalace/tusky/SpanUtilsTest.kt b/app/src/test/java/com/keylesspalace/tusky/SpanUtilsTest.kt
index 6d12f7634b..7a369d7bb2 100644
--- a/app/src/test/java/com/keylesspalace/tusky/SpanUtilsTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/SpanUtilsTest.kt
@@ -115,6 +115,10 @@ class SpanUtilsTest(
             arrayOf("😜https://connyduck.at", listOf(2 to 22)),
             arrayOf("😜#tag", listOf(2 to 6)),
             arrayOf("😜@user@mastodon.example", listOf(2 to 24)),
+            // case should be ignored on protocols https://github.com/tuskyapp/Tusky/issues/4641
+            arrayOf("HTTPS://example.com", listOf(0 to 19)),
+            arrayOf("Http://example.com/test", listOf(0 to 23)),
+            arrayOf("test Https://example.com/test", listOf(5 to 29)),
         )
     }
 
diff --git a/app/src/test/java/com/keylesspalace/tusky/components/compose/StatusLengthTest.kt b/app/src/test/java/com/keylesspalace/tusky/components/compose/StatusLengthTest.kt
index 9b1404dbeb..8b2b0113ab 100644
--- a/app/src/test/java/com/keylesspalace/tusky/components/compose/StatusLengthTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/components/compose/StatusLengthTest.kt
@@ -43,7 +43,7 @@ class StatusLengthTest(
                 arrayOf("🫣", 1),
                 // "@user@server" should be treated as "@user"
                 arrayOf("123 @example@example.org", 12),
-                // URLs under 23 chars are treated as 23 chars
+                // URLs are always treated as 23 even if they are shorter
                 arrayOf("123 http://example.org", 27),
                 // URLs over 23 chars are treated as 23 chars
                 arrayOf("123 http://urlthatislongerthan23characters.example.org", 27),
@@ -52,7 +52,11 @@ class StatusLengthTest(
                 // Long hashtags are *also* treated as is (not treated as 23, like URLs)
                 arrayOf("123 #atagthatislongerthan23characters", 37),
                 // urls can have balanced parenthesis, otherwise they are ignored https://github.com/tuskyapp/Tusky/issues/4425
-                arrayOf("(https://en.wikipedia.org/wiki/Beethoven_(horse))", 25)
+                arrayOf("(https://en.wikipedia.org/wiki/Beethoven_(horse))", 25),
+                // protocols can have any case https://github.com/tuskyapp/Tusky/issues/4641
+                arrayOf("Http://example.org", 23),
+                arrayOf("HTTPS://example.org", 23),
+                arrayOf("HTTPS://EXAMPLE.ORG", 23)
             )
         }
     }