Merge develop into the wildcard mime type branch

Develop gained resolveImageMimeType, which reads the image header so a
share that declares a broad type is encoded as the format it really is.
Resolving the wildcard first would hand that helper a concrete image/jpeg
and make it return early, so a transparent PNG shared as image/* would be
flattened and an animated GIF would be recompressed. The header is now
read from the type the sender declared and the default subtype is applied
to whatever comes back, so the sniffing still runs and an undecodable file
no longer keeps a wildcard.

A non-image shared as image/* is therefore sent as image/jpeg rather than
image/*, which is the whole point of this branch, so the test covering
that case now expects the default subtype.
This commit is contained in:
hayaksi1
2026-08-20 14:26:57 +03:00
418 changed files with 6374 additions and 4183 deletions
@@ -8,6 +8,7 @@
package io.element.android.libraries.core.extensions
import java.text.Normalizer
import java.util.Locale
fun Boolean.toOnOff() = if (this) "ON" else "OFF"
@@ -114,3 +115,14 @@ fun String.toSafeLength(
this
}
}
/**
* Remove accents and replace special characters by ASCII from the string.
* For instance, "é" will be replaced by "e", "ç" by "c", etc.
*/
fun String.normalized(): String {
// Normalize the string.
return Normalizer.normalize(this, Normalizer.Form.NFD)
// then keep only ASCII characters and replace non-ASCII characters with an empty string.
.replace("[^\\p{ASCII}]".toRegex(), "")
}
@@ -20,12 +20,13 @@ fun String.isValidUrl(): Boolean {
}
/**
* Ensure string starts with "http". If it is not the case, "https://" is added, only if the String is not empty
* Ensure string starts with "http" (case-insensitively, so "HTTP://" / "HTTPS://" are respected). If it is
* not the case, "https://" is added, only if the String is not empty.
*/
fun String.ensureProtocol(): String {
return when {
isEmpty() -> this
!startsWith("http") -> "https://$this"
!startsWith("http", ignoreCase = true) -> "https://$this"
else -> this
}
}
@@ -74,4 +74,10 @@ class BasicExtensionsTest {
val result = textWithDirectionOverrides.filterDirectionOverrides()
assertEquals("123456789", result)
}
@Test
fun `normalized removes accents and replace special characters from text`() {
assertEquals("Stefan", "Ștefan".normalized())
assertEquals("ca enleve etre", "ça enlève être".normalized())
}
}
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.core.uri
import com.google.common.truth.Truth.assertThat
import org.junit.Test
class UrlUtilsTest {
@Test
fun `ensureProtocol keeps an empty string unchanged`() {
assertThat("".ensureProtocol()).isEqualTo("")
}
@Test
fun `ensureProtocol prepends https when there is no scheme`() {
assertThat("matrix.org".ensureProtocol()).isEqualTo("https://matrix.org")
}
@Test
fun `ensureProtocol keeps an existing http or https scheme`() {
assertThat("https://matrix.org".ensureProtocol()).isEqualTo("https://matrix.org")
assertThat("http://matrix.org".ensureProtocol()).isEqualTo("http://matrix.org")
}
@Test
fun `ensureProtocol keeps an uppercase scheme rather than double-prepending`() {
assertThat("HTTPS://matrix.org".ensureProtocol()).isEqualTo("HTTPS://matrix.org")
assertThat("Http://matrix.org".ensureProtocol()).isEqualTo("Http://matrix.org")
}
}