feat(deeplink): point deeplinks at HealthChat hosts

Claims app.healthchat.ch and to.healthchat.ch as App Links, registers the
healthchat:// scheme, and drops the unreachable mobile.element.io handling.
This commit is contained in:
2026-08-03 10:53:35 +02:00
committed by Sedat Qaja
parent fd29aea9a9
commit e4ca0e6208
15 changed files with 155 additions and 168 deletions
@@ -22,25 +22,29 @@ import io.element.android.libraries.matrix.api.permalink.MatrixToConverter
@ContributesBinding(AppScope::class)
class DefaultMatrixToConverter : MatrixToConverter {
/**
* Try to convert a URL from an element web instance or from a client permalink to a matrix.to url.
* Try to convert a URL from a web client instance or from a client permalink to a matrix.to url.
* To be successfully converted, URL path should contain one of the [SUPPORTED_PATHS].
* Examples:
* - https://riot.im/develop/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
* - https://app.element.io/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
* - https://app.healthchat.ch/#/room/#room:healthchat.ch -> https://matrix.to/#/#room:healthchat.ch
* - https://www.example.org/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
* Also convert links coming from the matrix.to website:
* - element://room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
* - element://user/@alice:matrix.org -> https://matrix.to/#/@alice:matrix.org
* Also convert links coming from the HealthChat matrix.to website, which uses the matrix.to URL
* format on its own host and hands out a custom scheme to Android:
* - https://to.healthchat.ch/#/#room:healthchat.ch -> https://matrix.to/#/#room:healthchat.ch
* - healthchat://room/#room:healthchat.ch -> https://matrix.to/#/#room:healthchat.ch
* - healthchat://user/@alice:healthchat.ch -> https://matrix.to/#/@alice:healthchat.ch
*/
override fun convert(uri: Uri): Uri? {
val uriString = uri.toString()
// Handle links coming from the matrix.to website.
.replacePrefix(MATRIX_TO_CUSTOM_SCHEME_BASE_URL, "https://app.element.io/#/")
val baseUrl = MatrixConfiguration.MATRIX_TO_PERMALINK_BASE_URL
val uriString = uri.toString()
// Handle the custom scheme handed out by the HealthChat matrix.to website.
.replacePrefix(MATRIX_TO_CUSTOM_SCHEME_BASE_URL, MatrixConfiguration.HEALTHCHAT_WEB_BASE_URL)
// Our own matrix.to deployment already uses the matrix.to URL format.
.replacePrefix(MatrixConfiguration.HEALTHCHAT_TO_PERMALINK_BASE_URL, baseUrl)
return when {
// URL is already a matrix.to
uriString.startsWith(baseUrl) -> uri
uriString.startsWith(baseUrl) -> uriString.toUri()
// Web or client url
SUPPORTED_PATHS.any { it in uriString } -> {
val path = SUPPORTED_PATHS.first { it in uriString }
@@ -52,7 +56,7 @@ class DefaultMatrixToConverter : MatrixToConverter {
}
companion object {
private const val MATRIX_TO_CUSTOM_SCHEME_BASE_URL = "element://"
private const val MATRIX_TO_CUSTOM_SCHEME_BASE_URL = "healthchat://"
private val SUPPORTED_PATHS = listOf(
"/#/room/",
"/#/user/",
@@ -44,15 +44,46 @@ class DefaultMatrixToConverterTest : RobolectricTest() {
assertThat(DefaultMatrixToConverter().convert(url)).isNull()
}
@Test
fun `converting the root url of the HealthChat matrix-to website returns null`() {
val url = Uri.parse("https://to.healthchat.ch/")
assertThat(DefaultMatrixToConverter().convert(url)).isNull()
}
@Test
fun `converting a url from the HealthChat matrix-to website returns a matrix-to url for room case`() {
val url = Uri.parse("https://to.healthchat.ch/#/#room:healthchat.ch")
assertThat(DefaultMatrixToConverter().convert(url)).isEqualTo(Uri.parse("https://matrix.to/#/#room:healthchat.ch"))
}
@Test
fun `converting a url from the HealthChat matrix-to website returns a matrix-to url for user case`() {
val url = Uri.parse("https://to.healthchat.ch/#/@alice:healthchat.ch")
assertThat(DefaultMatrixToConverter().convert(url)).isEqualTo(Uri.parse("https://matrix.to/#/@alice:healthchat.ch"))
}
@Test
fun `converting a url from the HealthChat web client returns a matrix-to url`() {
val url = Uri.parse("https://app.healthchat.ch/#/room/%23room%3Ahealthchat.ch")
assertThat(DefaultMatrixToConverter().convert(url)).isEqualTo(Uri.parse("https://matrix.to/#/%23room%3Ahealthchat.ch"))
}
@Test
fun `converting url coming from the matrix-to website returns a matrix-to url for room case`() {
val url = Uri.parse("element://room/#element-android:matrix.org")
val url = Uri.parse("healthchat://room/#element-android:matrix.org")
assertThat(DefaultMatrixToConverter().convert(url)).isEqualTo(Uri.parse("https://matrix.to/#/#element-android:matrix.org"))
}
@Test
fun `converting url coming from the matrix-to website returns a matrix-to url for user case`() {
val url = Uri.parse("element://user/@alice:matrix.org")
val url = Uri.parse("healthchat://user/@alice:matrix.org")
assertThat(DefaultMatrixToConverter().convert(url)).isEqualTo(Uri.parse("https://matrix.to/#/@alice:matrix.org"))
}
@Test
fun `converting an event url coming from the matrix-to website keeps the event id and the via params`() {
val url = Uri.parse("healthchat://room/%23room%3Ahealthchat.ch/%24eventId?via=healthchat.ch")
assertThat(DefaultMatrixToConverter().convert(url))
.isEqualTo(Uri.parse("https://matrix.to/#/%23room%3Ahealthchat.ch/%24eventId?via=healthchat.ch"))
}
}