Merge pull request #2047 from vector-im/feature/universal_link_navigation

Handle room, user, group, email verification links by converting them to permalinks.
This commit is contained in:
Benoit Marty 2020-09-08 12:21:54 +02:00 committed by GitHub
commit 22cd6ae239
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 16 deletions

View file

@ -22,6 +22,8 @@ Bugfix 🐛:
- Loudspeaker is always used (#1685)
- Fix uploads still don't work with room v6 (#1879)
- Can't handle ongoing call events in background (#1992)
- Handle room, user and group links by the Element app (#1795)
- Update associated site domain (#1833)
- Crash / Attachment viewer: Cannot draw a recycled Bitmap #2034
- Login with Matrix-Id | Autodiscovery fails if identity server is invalid and Homeserver ok (#2027)
- Support for image compression on Android 10

View file

@ -1,3 +1,3 @@
#!/usr/bin/env bash
adb shell am start -a android.intent.action.VIEW -d "https://riot.im/config/config?hs_url=https%3A%2F%2Fmozilla-test.modular.im"
adb shell am start -a android.intent.action.VIEW -d "https://mobile.element.io?hs_url=https%3A%2F%2Fmozilla-test.modular.im"

View file

@ -144,8 +144,10 @@
<data android:scheme="https" />
<data android:host="riot.im" />
<data android:host="element.io" />
<data android:pathPrefix="/config/" />
<data android:host="app.element.io" />
<data android:host="mobile.element.io" />
<data android:host="develop.element.io" />
<data android:host="staging.element.io" />
</intent-filter>
</activity>

View file

@ -24,10 +24,14 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.toast
import im.vector.app.features.login.LoginActivity
import im.vector.app.features.login.LoginConfig
import im.vector.app.features.permalink.PermalinkHandler
import io.reactivex.android.schedulers.AndroidSchedulers
import org.matrix.android.sdk.api.MatrixCallback
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
/**
@ -37,6 +41,7 @@ class LinkHandlerActivity : VectorBaseActivity() {
@Inject lateinit var sessionHolder: ActiveSessionHolder
@Inject lateinit var errorFormatter: ErrorFormatter
@Inject lateinit var permalinkHandler: PermalinkHandler
override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
@ -54,19 +59,56 @@ class LinkHandlerActivity : VectorBaseActivity() {
return
}
if (uri.path == PATH_CONFIG) {
if (uri.getQueryParameter(CONFIG_PATH_HS_PARAMETER) != null) {
handleConfigUrl(uri)
} else if (SUPPORTED_HOSTS.contains(uri.host)) {
handleSupportedHostUrl(uri)
}
}
private fun handleConfigUrl(uri: Uri) {
if (sessionHolder.hasActiveSession()) {
displayAlreadyLoginPopup(uri)
} else {
// user is not yet logged in, this is the nominal case
startLoginActivity(uri)
}
}
private fun handleSupportedHostUrl(uri: Uri) {
if (!sessionHolder.hasActiveSession()) {
startLoginActivity(uri)
finish()
} else {
// Other link are not yet handled, but should not comes here (manifest configuration error?)
Timber.w("Unable to handle this uir: $uri")
convertUriToPermalink(uri)?.let { permalink ->
startPermalinkHandler(permalink)
} ?: run {
// Host is correct but we do not recognize path
Timber.w("Unable to handle this uri: $uri")
finish()
}
}
}
private fun convertUriToPermalink(uri: Uri): String? {
val path = SUPPORTED_PATHS.find { it in uri.toString() } ?: return null
// 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
return "https://$MATRIX_TO_HOST/#" + uri.toString().substringAfter(path)
}
private fun startPermalinkHandler(permalink: String) {
permalinkHandler.launch(this, permalink, buildTask = true)
.delay(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { isHandled ->
if (!isHandled) {
toast(R.string.universal_link_malformed)
}
finish()
}
.disposeOnDestroy()
}
/**
* Start the login screen with identity server and home server pre-filled
@ -113,6 +155,10 @@ class LinkHandlerActivity : VectorBaseActivity() {
}
companion object {
private const val PATH_CONFIG = "/config/config"
private const val CONFIG_PATH_HS_PARAMETER = "hs_url"
private val SUPPORTED_HOSTS = arrayOf("app.element.io", "riot.im", "develop.element.io", "staging.element.io")
private val SUPPORTED_PATHS = arrayOf("/#/room", "/#/user", "/#/group")
private const val MATRIX_TO_HOST = "matrix.to"
}
}

View file

@ -22,7 +22,7 @@ import kotlinx.android.parcel.Parcelize
/**
* Parameters extracted from a configuration url
* Ex: https://riot.im/config/config?hs_url=https%3A%2F%2Fexample.modular.im&is_url=https%3A%2F%2Fcustom.identity.org
* Ex: https://mobile.element.io?hs_url=https%3A%2F%2Fexample.modular.im&is_url=https%3A%2F%2Fcustom.identity.org
*
* Note: On RiotX, identityServerUrl will never be used, so is declared private. Keep it for compatibility reason.
*/

View file

@ -2564,4 +2564,7 @@
<string name="auth_pin_confirm_to_disable_title">Confirm PIN to disable PIN</string>
<string name="error_opening_banned_room">Can\'t open a room where you are banned from.</string>
<string name="room_error_not_found">Can\'t find this room. Make sure it exists.</string>
<!-- Universal link -->
<string name="universal_link_malformed">The link was malformed</string>
</resources>