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 {
|
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()
|
data class UserLink(val userId: String) : PermalinkData()
|
||||||
|
|
||||||
|
@ -19,6 +19,10 @@ package org.matrix.android.sdk.api.session.permalinks
|
|||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import org.matrix.android.sdk.api.MatrixPatterns
|
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]
|
* This class turns an uri to a [PermalinkData]
|
||||||
@ -40,14 +44,13 @@ object PermalinkParser {
|
|||||||
if (!uri.toString().startsWith(PermalinkService.MATRIX_TO_URL_BASE)) {
|
if (!uri.toString().startsWith(PermalinkService.MATRIX_TO_URL_BASE)) {
|
||||||
return PermalinkData.FallbackLink(uri)
|
return PermalinkData.FallbackLink(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
val fragment = uri.fragment
|
val fragment = uri.fragment
|
||||||
if (fragment.isNullOrEmpty()) {
|
if (fragment.isNullOrEmpty()) {
|
||||||
return PermalinkData.FallbackLink(uri)
|
return PermalinkData.FallbackLink(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
val indexOfQuery = fragment.indexOf("?")
|
val indexOfQuery = fragment.indexOf("?")
|
||||||
val safeFragment = if (indexOfQuery != -1) fragment.substring(0, indexOfQuery) else fragment
|
val safeFragment = if (indexOfQuery != -1) fragment.substring(0, indexOfQuery) else fragment
|
||||||
|
val viaQueryParameters = fragment.getViaParameters(indexOfQuery)
|
||||||
|
|
||||||
// we are limiting to 2 params
|
// we are limiting to 2 params
|
||||||
val params = safeFragment
|
val params = safeFragment
|
||||||
@ -65,17 +68,58 @@ object PermalinkParser {
|
|||||||
PermalinkData.RoomLink(
|
PermalinkData.RoomLink(
|
||||||
roomIdOrAlias = identifier,
|
roomIdOrAlias = identifier,
|
||||||
isRoomAlias = false,
|
isRoomAlias = false,
|
||||||
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }
|
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
|
||||||
|
viaParameters = viaQueryParameters
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
MatrixPatterns.isRoomAlias(identifier) -> {
|
MatrixPatterns.isRoomAlias(identifier) -> {
|
||||||
PermalinkData.RoomLink(
|
PermalinkData.RoomLink(
|
||||||
roomIdOrAlias = identifier,
|
roomIdOrAlias = identifier,
|
||||||
isRoomAlias = true,
|
isRoomAlias = true,
|
||||||
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) }
|
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
|
||||||
|
viaParameters = viaQueryParameters
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> PermalinkData.FallbackLink(uri)
|
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) {
|
if (deepLink == null) {
|
||||||
return Single.just(false)
|
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 -> {
|
is PermalinkData.RoomLink -> {
|
||||||
permalinkData.getRoomId()
|
permalinkData.getRoomId()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -66,8 +84,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
|||||||
openRoom(
|
openRoom(
|
||||||
context = context,
|
context = context,
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
roomAlias = permalinkData.getRoomAliasOrNull(),
|
permalinkData = permalinkData,
|
||||||
eventId = permalinkData.eventId,
|
|
||||||
buildTask = buildTask
|
buildTask = buildTask
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -87,7 +104,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
|||||||
is PermalinkData.FallbackLink -> {
|
is PermalinkData.FallbackLink -> {
|
||||||
Single.just(false)
|
Single.just(false)
|
||||||
}
|
}
|
||||||
}.onErrorReturnItem(false)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PermalinkData.RoomLink.getRoomId(): Single<Optional<String>> {
|
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
|
* 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
|
val session = activeSessionHolder.getSafeActiveSession() ?: return
|
||||||
if (roomId == null) {
|
if (roomId == null) {
|
||||||
context.toast(R.string.room_error_not_found)
|
context.toast(R.string.room_error_not_found)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val roomSummary = session.getRoomSummary(roomId)
|
val roomSummary = session.getRoomSummary(roomId)
|
||||||
|
val eventId = permalinkData.eventId
|
||||||
|
val roomAlias = permalinkData.getRoomAliasOrNull()
|
||||||
return when {
|
return when {
|
||||||
roomSummary?.membership?.isActive().orFalse() -> {
|
roomSummary?.membership?.isActive().orFalse() -> {
|
||||||
navigator.openRoom(context, roomId, eventId, buildTask)
|
navigator.openRoom(context, roomId, eventId, buildTask)
|
||||||
@ -128,7 +152,8 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
|||||||
roomAlias = roomAlias ?: roomSummary?.canonicalAlias,
|
roomAlias = roomAlias ?: roomSummary?.canonicalAlias,
|
||||||
roomName = roomSummary?.displayName,
|
roomName = roomSummary?.displayName,
|
||||||
avatarUrl = roomSummary?.avatarUrl,
|
avatarUrl = roomSummary?.avatarUrl,
|
||||||
buildTask = buildTask
|
buildTask = buildTask,
|
||||||
|
homeServers = permalinkData.viaParameters
|
||||||
)
|
)
|
||||||
navigator.openRoomPreview(context, roomPreviewData)
|
navigator.openRoomPreview(context, roomPreviewData)
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ data class RoomPreviewData(
|
|||||||
val topic: String? = null,
|
val topic: String? = null,
|
||||||
val worldReadable: Boolean = false,
|
val worldReadable: Boolean = false,
|
||||||
val avatarUrl: String? = null,
|
val avatarUrl: String? = null,
|
||||||
val homeServer: String? = null,
|
val homeServers: List<String> = emptyList(),
|
||||||
val buildTask: Boolean = false
|
val buildTask: Boolean = false
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
val matrixItem: MatrixItem
|
val matrixItem: MatrixItem
|
||||||
@ -64,7 +64,7 @@ class RoomPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||||||
topic = publicRoom.topic,
|
topic = publicRoom.topic,
|
||||||
worldReadable = publicRoom.worldReadable,
|
worldReadable = publicRoom.worldReadable,
|
||||||
avatarUrl = publicRoom.avatarUrl,
|
avatarUrl = publicRoom.avatarUrl,
|
||||||
homeServer = roomDirectoryData.homeServer
|
homeServers = listOfNotNull(roomDirectoryData.homeServer)
|
||||||
)
|
)
|
||||||
return newIntent(context, roomPreviewData)
|
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")
|
Timber.w("Try to join an already joining room. Should not happen")
|
||||||
return@withState
|
return@withState
|
||||||
}
|
}
|
||||||
val viaServers = state.homeServer?.let {
|
session.joinRoom(state.roomId, viaServers = state.homeServers, callback = object : MatrixCallback<Unit> {
|
||||||
listOf(it)
|
|
||||||
} ?: emptyList()
|
|
||||||
session.joinRoom(state.roomId, viaServers = viaServers, callback = object : MatrixCallback<Unit> {
|
|
||||||
override fun onSuccess(data: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
// We do not update the joiningRoomsIds here, because, the room is not joined yet regarding the sync data.
|
// 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
|
// Instead, we wait for the room to be joined
|
||||||
|
@ -24,10 +24,9 @@ data class RoomPreviewViewState(
|
|||||||
val roomId: String = "",
|
val roomId: String = "",
|
||||||
val roomAlias: String? = null,
|
val roomAlias: String? = null,
|
||||||
/**
|
/**
|
||||||
* The server name (might be null)
|
* Can be empty when the server is the current user's home server.
|
||||||
* Set null 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
|
// Current state of the room in preview
|
||||||
val roomJoinState: JoinState = JoinState.NOT_JOINED,
|
val roomJoinState: JoinState = JoinState.NOT_JOINED,
|
||||||
// Last error of join room request
|
// Last error of join room request
|
||||||
@ -37,6 +36,6 @@ data class RoomPreviewViewState(
|
|||||||
constructor(args: RoomPreviewData) : this(
|
constructor(args: RoomPreviewData) : this(
|
||||||
roomId = args.roomId,
|
roomId = args.roomId,
|
||||||
roomAlias = args.roomAlias,
|
roomAlias = args.roomAlias,
|
||||||
homeServer = args.homeServer
|
homeServers = args.homeServers
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user