Merge branch 'develop' into fix/6371-save-file-name-conflicts

This commit is contained in:
Benoit Marty
2026-08-24 09:38:35 +02:00
committed by GitHub
1451 changed files with 19439 additions and 7920 deletions
@@ -0,0 +1,29 @@
/*
* 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.androidutils.media
import android.app.PictureInPictureParams
import android.content.res.Configuration
import android.os.Build
import android.util.Rational
import androidx.annotation.RequiresApi
/**
* Set the aspect ratio of the Picture-in-Picture mode based on the current orientation of the other user's device.
*/
@RequiresApi(Build.VERSION_CODES.O)
fun PictureInPictureParams.Builder.setAspectRatioFromOrientation(orientation: Int): PictureInPictureParams.Builder {
val aspectRatio = if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// If landscape orientation, invert the aspect ratio
Rational(5, 3)
} else {
// In any other case, assume portrait orientation
Rational(3, 5)
}
return setAspectRatio(aspectRatio)
}
@@ -16,6 +16,7 @@ import androidx.core.text.toSpannable
import androidx.core.text.util.LinkifyCompat
import io.element.android.libraries.core.extensions.runCatchingExceptions
import timber.log.Timber
import java.net.URI
/**
* Helper class to linkify text while preserving existing URL spans.
@@ -23,6 +24,8 @@ import timber.log.Timber
* It also checks the linkified results to make sure URLs spans are not including trailing punctuation.
*/
object LinkifyHelper {
private val BRACKETED_AUTHORITY_URL_REGEX = Regex("""(?<![a-zA-Z0-9+.-])[a-zA-Z][a-zA-Z0-9+.-]*://\[\S*""")
fun linkify(
text: CharSequence,
@LinkifyCompat.LinkifyMask linkifyMask: Int = Linkify.WEB_URLS or Linkify.PHONE_NUMBERS or Linkify.EMAIL_ADDRESSES,
@@ -47,6 +50,11 @@ object LinkifyHelper {
val start = spannable.getSpanStart(urlSpan)
val end = spannable.getSpanEnd(urlSpan)
if (urlSpan !in oldURLSpans && spannable.isEmailInsideFediverseHandle(urlSpan, start)) {
spannable.removeSpan(urlSpan)
continue
}
// Try to avoid including trailing punctuation in the link.
// Since this might fail in some edge cases, we catch the exception and just use the original end index.
val newEnd = runCatchingExceptions {
@@ -67,6 +75,24 @@ object LinkifyHelper {
}
}
for (match in BRACKETED_AUTHORITY_URL_REGEX.findAll(spannable)) {
val start = match.range.first
val end = match.range.last + 1
val newEnd = runCatchingExceptions {
adjustLinkifiedUrlSpanEndIndex(spannable, start, end)
}.onFailure {
Timber.e(it, "Failed to adjust end index for link span")
}.getOrNull() ?: end
val url = spannable.substring(start, newEnd)
if (!url.hasBracketedHost()) continue
for (span in spannable.getSpans<URLSpan>(start, newEnd)) {
spannable.removeSpan(span)
}
spannable.setSpan(URLSpan(url), start, newEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
// Restore old spans, remove new ones if there is a conflict
for ((urlSpan, location) in oldURLSpans) {
val (start, end) = location
@@ -82,6 +108,15 @@ object LinkifyHelper {
return spannable
}
private fun String.hasBracketedHost(): Boolean {
val host = runCatchingExceptions { URI(this) }.getOrNull()?.host ?: return false
return host.startsWith('[') && host.endsWith(']')
}
private fun Spannable.isEmailInsideFediverseHandle(urlSpan: URLSpan, start: Int): Boolean {
return urlSpan.url.startsWith("mailto:") && start > 0 && this[start - 1] == '@'
}
private fun adjustLinkifiedUrlSpanEndIndex(spannable: Spannable, start: Int, end: Int): Int {
var end = end
@@ -13,3 +13,5 @@ import java.nio.charset.Charset
fun String.urlEncoded(charset: Charset = Charsets.UTF_8): String = URLEncoder.encode(this, charset.name())
fun String.urlDecoded(charset: Charset = Charsets.UTF_8): String = URLDecoder.decode(this, charset.name())
fun String.takeIfNotBlank(): String? = ifBlank { null }
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="error_no_compatible_app_found">"لم يُعثر على تطبيق ليتعامل مع هذا الحدث."</string>
</resources>