mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
Permalink: handle via parameters
This commit is contained in:
parent
9970398cf2
commit
b986bfd509
@ -25,7 +25,12 @@ import android.net.Uri
|
||||
*/
|
||||
sealed class PermalinkData {
|
||||
|
||||
data class RoomLink(val roomIdOrAlias: String, val isRoomAlias: Boolean, val eventId: String?) : PermalinkData()
|
||||
data class RoomLink(
|
||||
val roomIdOrAlias: String,
|
||||
val isRoomAlias: Boolean,
|
||||
val eventId: String?,
|
||||
val viaParameters: List<String>
|
||||
) : PermalinkData()
|
||||
|
||||
data class UserLink(val userId: String) : PermalinkData()
|
||||
|
||||
|
@ -19,6 +19,10 @@ package org.matrix.android.sdk.api.session.permalinks
|
||||
|
||||
import android.net.Uri
|
||||
import org.matrix.android.sdk.api.MatrixPatterns
|
||||
import java.io.UnsupportedEncodingException
|
||||
import java.net.URLEncoder
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
|
||||
/**
|
||||
* This class turns an uri to a [PermalinkData]
|
||||
@ -40,14 +44,13 @@ object PermalinkParser {
|
||||
if (!uri.toString().startsWith(PermalinkService.MATRIX_TO_URL_BASE)) {
|
||||
return PermalinkData.FallbackLink(uri)
|
||||
}
|
||||
|
||||
val fragment = uri.fragment
|
||||
if (fragment.isNullOrEmpty()) {
|
||||
return PermalinkData.FallbackLink(uri)
|
||||
}
|
||||
|
||||
val indexOfQuery = fragment.indexOf("?")
|
||||
val safeFragment = if (indexOfQuery != -1) fragment.substring(0, indexOfQuery) else fragment
|
||||
val viaQueryParameters = fragment.getViaParameters(indexOfQuery)
|
||||
|
||||
// we are limiting to 2 params
|
||||
val params = safeFragment
|
||||
@ -65,17 +68,58 @@ object PermalinkParser {
|
||||
PermalinkData.RoomLink(
|
||||
roomIdOrAlias = identifier,
|
||||
isRoomAlias = false,
|
||||
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }
|
||||
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
|
||||
viaParameters = viaQueryParameters
|
||||
)
|
||||
}
|
||||
MatrixPatterns.isRoomAlias(identifier) -> {
|
||||
PermalinkData.RoomLink(
|
||||
roomIdOrAlias = identifier,
|
||||
isRoomAlias = true,
|
||||
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }
|
||||
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
|
||||
viaParameters = viaQueryParameters
|
||||
)
|
||||
}
|
||||
else -> PermalinkData.FallbackLink(uri)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.getViaParameters(indexOfQuery: Int): List<String> {
|
||||
val query = try {
|
||||
substring(indexOfQuery + 1)
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
return emptyList()
|
||||
}
|
||||
val encodedKey = try {
|
||||
URLEncoder.encode("via", "UTF-8")
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
return emptyList()
|
||||
}
|
||||
val values = ArrayList<String>()
|
||||
var start = 0
|
||||
do {
|
||||
val nextAmpersand = query.indexOf('&', start)
|
||||
val end = if (nextAmpersand != -1) nextAmpersand else query.length
|
||||
var separator = query.indexOf('=', start)
|
||||
if (separator > end || separator == -1) {
|
||||
separator = end
|
||||
}
|
||||
if (separator - start == encodedKey.length
|
||||
&& query.regionMatches(start, encodedKey, 0, encodedKey.length)) {
|
||||
if (separator == end) {
|
||||
values.add("")
|
||||
} else {
|
||||
values.add(Uri.decode(query.substring(separator + 1, end)))
|
||||
}
|
||||
}
|
||||
|
||||
// Move start to end of name.
|
||||
start = if (nextAmpersand != -1) {
|
||||
nextAmpersand + 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} while (true)
|
||||
return Collections.unmodifiableList(values)
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,25 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||
if (deepLink == null) {
|
||||
return Single.just(false)
|
||||
}
|
||||
return when (val permalinkData = PermalinkParser.parse(deepLink)) {
|
||||
return Single
|
||||
.fromCallable {
|
||||
PermalinkParser.parse(deepLink)
|
||||
}
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.flatMap { permalinkData ->
|
||||
handlePermalink(permalinkData, context, navigationInterceptor, buildTask)
|
||||
}
|
||||
.onErrorReturnItem(false)
|
||||
}
|
||||
|
||||
private fun handlePermalink(
|
||||
permalinkData: PermalinkData,
|
||||
context: Context,
|
||||
navigationInterceptor: NavigationInterceptor?,
|
||||
buildTask: Boolean
|
||||
): Single<Boolean> {
|
||||
return when (permalinkData) {
|
||||
is PermalinkData.RoomLink -> {
|
||||
permalinkData.getRoomId()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -66,8 +84,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||
openRoom(
|
||||
context = context,
|
||||
roomId = roomId,
|
||||
roomAlias = permalinkData.getRoomAliasOrNull(),
|
||||
eventId = permalinkData.eventId,
|
||||
permalinkData = permalinkData,
|
||||
buildTask = buildTask
|
||||
)
|
||||
}
|
||||
@ -87,7 +104,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||
is PermalinkData.FallbackLink -> {
|
||||
Single.just(false)
|
||||
}
|
||||
}.onErrorReturnItem(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun PermalinkData.RoomLink.getRoomId(): Single<Optional<String>> {
|
||||
@ -110,13 +127,20 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||
/**
|
||||
* Open room either joined, or not
|
||||
*/
|
||||
private fun openRoom(context: Context, roomId: String?, roomAlias: String?, eventId: String?, buildTask: Boolean) {
|
||||
private fun openRoom(
|
||||
context: Context,
|
||||
roomId: String?,
|
||||
permalinkData: PermalinkData.RoomLink,
|
||||
buildTask: Boolean
|
||||
) {
|
||||
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||
if (roomId == null) {
|
||||
context.toast(R.string.room_error_not_found)
|
||||
return
|
||||
}
|
||||
val roomSummary = session.getRoomSummary(roomId)
|
||||
val eventId = permalinkData.eventId
|
||||
val roomAlias = permalinkData.getRoomAliasOrNull()
|
||||
return when {
|
||||
roomSummary?.membership?.isActive().orFalse() -> {
|
||||
navigator.openRoom(context, roomId, eventId, buildTask)
|
||||
@ -128,7 +152,8 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||
roomAlias = roomAlias ?: roomSummary?.canonicalAlias,
|
||||
roomName = roomSummary?.displayName,
|
||||
avatarUrl = roomSummary?.avatarUrl,
|
||||
buildTask = buildTask
|
||||
buildTask = buildTask,
|
||||
homeServers = permalinkData.viaParameters
|
||||
)
|
||||
navigator.openRoomPreview(context, roomPreviewData)
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ data class RoomPreviewData(
|
||||
val topic: String? = null,
|
||||
val worldReadable: Boolean = false,
|
||||
val avatarUrl: String? = null,
|
||||
val homeServer: String? = null,
|
||||
val homeServers: List<String> = emptyList(),
|
||||
val buildTask: Boolean = false
|
||||
) : Parcelable {
|
||||
val matrixItem: MatrixItem
|
||||
@ -64,7 +64,7 @@ class RoomPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||
topic = publicRoom.topic,
|
||||
worldReadable = publicRoom.worldReadable,
|
||||
avatarUrl = publicRoom.avatarUrl,
|
||||
homeServer = roomDirectoryData.homeServer
|
||||
homeServers = listOfNotNull(roomDirectoryData.homeServer)
|
||||
)
|
||||
return newIntent(context, roomPreviewData)
|
||||
}
|
||||
|
@ -106,10 +106,7 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted private val ini
|
||||
Timber.w("Try to join an already joining room. Should not happen")
|
||||
return@withState
|
||||
}
|
||||
val viaServers = state.homeServer?.let {
|
||||
listOf(it)
|
||||
} ?: emptyList()
|
||||
session.joinRoom(state.roomId, viaServers = viaServers, callback = object : MatrixCallback<Unit> {
|
||||
session.joinRoom(state.roomId, viaServers = state.homeServers, callback = object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
// We do not update the joiningRoomsIds here, because, the room is not joined yet regarding the sync data.
|
||||
// Instead, we wait for the room to be joined
|
||||
|
@ -24,10 +24,9 @@ data class RoomPreviewViewState(
|
||||
val roomId: String = "",
|
||||
val roomAlias: String? = null,
|
||||
/**
|
||||
* The server name (might be null)
|
||||
* Set null when the server is the current user's home server.
|
||||
* Can be empty when the server is the current user's home server.
|
||||
*/
|
||||
val homeServer: String? = null,
|
||||
val homeServers: List<String> = emptyList(),
|
||||
// Current state of the room in preview
|
||||
val roomJoinState: JoinState = JoinState.NOT_JOINED,
|
||||
// Last error of join room request
|
||||
@ -37,6 +36,6 @@ data class RoomPreviewViewState(
|
||||
constructor(args: RoomPreviewData) : this(
|
||||
roomId = args.roomId,
|
||||
roomAlias = args.roomAlias,
|
||||
homeServer = args.homeServer
|
||||
homeServers = args.homeServers
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user