Skip to content

Commit e37fb31

Browse files
committed
Permalink: Merge LinkHandlerActivity with PermalinkHandlerActivity
Also convert links to matrix.to before permalink parsing
1 parent 21d0a28 commit e37fb31

File tree

9 files changed

+163
-198
lines changed

9 files changed

+163
-198
lines changed

changelog.d/4027.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add client base url config to customize permalinks
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2020 The Matrix.org Foundation C.I.C.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.matrix.android.sdk.api.session.permalinks
18+
19+
import android.net.Uri
20+
21+
/**
22+
* Mapping of an input URI to a matrix.to compliant URI.
23+
*/
24+
object MatrixToMapper {
25+
26+
/**
27+
* Try to convert a URL from an element web instance or from a client permalink to a matrix.to url.
28+
* To be successfully converted, URL path should contain one of the [SUPPORTED_PATHS].
29+
* Examples:
30+
* - https://riot.im/develop/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
31+
* - https://app.element.io/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
32+
* - https://www.example.org/#/room/#element-android:matrix.org -> https://matrix.to/#/#element-android:matrix.org
33+
*/
34+
fun map(uri: Uri): Uri? {
35+
val uriString = uri.toString()
36+
37+
return when {
38+
// URL is already a matrix.to
39+
uriString.startsWith(PermalinkService.MATRIX_TO_URL_BASE) -> uri
40+
// Web or client url
41+
SUPPORTED_PATHS.any { it in uriString } -> {
42+
val path = SUPPORTED_PATHS.first { it in uriString }
43+
Uri.parse(PermalinkService.MATRIX_TO_URL_BASE + uriString.substringAfter(path))
44+
}
45+
// URL is not supported
46+
else -> null
47+
}
48+
}
49+
50+
private val SUPPORTED_PATHS = listOf(
51+
"/#/room/",
52+
"/#/user/",
53+
"/#/group/"
54+
)
55+
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/permalinks/PermalinkParser.kt

+9-12
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import java.net.URLDecoder
2626
* This class turns a uri to a [PermalinkData]
2727
* element-based domains (e.g. https://app.element.io/#/user/@chagai95:matrix.org) permalinks
2828
* or matrix.to permalinks (e.g. https://matrix.to/#/@chagai95:matrix.org)
29+
* or client permalinks (e.g. https://www.example.com/#/user/@chagai95:matrix.org)
2930
*/
3031
object PermalinkParser {
3132

@@ -42,12 +43,14 @@ object PermalinkParser {
4243
* https://github.com/matrix-org/matrix-doc/blob/master/proposals/1704-matrix.to-permalinks.md
4344
*/
4445
fun parse(uri: Uri): PermalinkData {
45-
if (!uri.toString().startsWith(PermalinkService.MATRIX_TO_URL_BASE)) {
46-
return PermalinkData.FallbackLink(uri)
47-
}
46+
// the client or element-based domain permalinks (e.g. https://app.element.io/#/user/@chagai95:matrix.org) don't have the
47+
// mxid in the first param (like matrix.to does - https://matrix.to/#/@chagai95:matrix.org) but rather in the second after /user/ so /user/mxid
48+
// so convert URI to matrix.to to simplify parsing process
49+
val matrixToUri = MatrixToMapper.map(uri) ?: return PermalinkData.FallbackLink(uri)
50+
4851
// We can't use uri.fragment as it is decoding to early and it will break the parsing
4952
// of parameters that represents url (like signurl)
50-
val fragment = uri.toString().substringAfter("#") // uri.fragment
53+
val fragment = matrixToUri.toString().substringAfter("#") // uri.fragment
5154
if (fragment.isNullOrEmpty()) {
5255
return PermalinkData.FallbackLink(uri)
5356
}
@@ -61,20 +64,14 @@ object PermalinkParser {
6164
.map { URLDecoder.decode(it, "UTF-8") }
6265
.take(2)
6366

64-
// the element-based domain permalinks (e.g. https://app.element.io/#/user/@chagai95:matrix.org) don't have the
65-
// mxid in the first param (like matrix.to does - https://matrix.to/#/@chagai95:matrix.org) but rather in the second after /user/ so /user/mxid
66-
var identifier = params.getOrNull(0)
67-
if (identifier.equals("user")) {
68-
identifier = params.getOrNull(1)
69-
}
70-
67+
val identifier = params.getOrNull(0)
7168
val extraParameter = params.getOrNull(1)
7269
return when {
7370
identifier.isNullOrEmpty() -> PermalinkData.FallbackLink(uri)
7471
MatrixPatterns.isUserId(identifier) -> PermalinkData.UserLink(userId = identifier)
7572
MatrixPatterns.isGroupId(identifier) -> PermalinkData.GroupLink(groupId = identifier)
7673
MatrixPatterns.isRoomId(identifier) -> {
77-
handleRoomIdCase(fragment, identifier, uri, extraParameter, viaQueryParameters)
74+
handleRoomIdCase(fragment, identifier, matrixToUri, extraParameter, viaQueryParameters)
7875
}
7976
MatrixPatterns.isRoomAlias(identifier) -> {
8077
PermalinkData.RoomLink(

vector/src/main/AndroidManifest.xml

+31-26
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@
180180
<activity android:name=".features.createdirect.CreateDirectRoomActivity" />
181181
<activity android:name=".features.invite.InviteUsersToRoomActivity" />
182182
<activity android:name=".features.webview.VectorWebViewActivity" />
183-
<activity android:name=".features.link.LinkHandlerActivity">
183+
<activity
184+
android:name=".features.link.LinkHandlerActivity"
185+
android:exported="true">
184186
<intent-filter>
185187
<action android:name="android.intent.action.VIEW" />
186188

@@ -196,6 +198,30 @@
196198
</intent-filter>
197199
</activity>
198200

201+
<activity-alias
202+
android:name=".features.permalink.PermalinkHandlerActivity"
203+
android:exported="true"
204+
android:launchMode="singleTask"
205+
android:targetActivity=".features.link.LinkHandlerActivity">
206+
<intent-filter>
207+
<action android:name="android.intent.action.VIEW" />
208+
209+
<category android:name="android.intent.category.DEFAULT" />
210+
<category android:name="android.intent.category.BROWSABLE" />
211+
212+
<data android:scheme="http" />
213+
<data android:scheme="https" />
214+
<data android:host="matrix.to" />
215+
<data
216+
android:host="user"
217+
android:scheme="element" />
218+
<data
219+
android:host="room"
220+
android:scheme="element" />
221+
222+
</intent-filter>
223+
</activity-alias>
224+
199225
<activity
200226
android:name=".features.share.IncomingShareActivity"
201227
android:parentActivityName=".features.home.HomeActivity">
@@ -230,27 +256,6 @@
230256
<activity
231257
android:name=".features.signout.soft.SoftLogoutActivity"
232258
android:windowSoftInputMode="adjustResize" />
233-
<activity
234-
android:name=".features.permalink.PermalinkHandlerActivity"
235-
android:launchMode="singleTask">
236-
<intent-filter>
237-
<action android:name="android.intent.action.VIEW" />
238-
239-
<category android:name="android.intent.category.DEFAULT" />
240-
<category android:name="android.intent.category.BROWSABLE" />
241-
242-
<data android:scheme="http" />
243-
<data android:scheme="https" />
244-
<data android:host="matrix.to" />
245-
<data
246-
android:host="user"
247-
android:scheme="element" />
248-
<data
249-
android:host="room"
250-
android:scheme="element" />
251-
252-
</intent-filter>
253-
</activity>
254259

255260
<activity
256261
android:name=".features.roommemberprofile.RoomMemberProfileActivity"
@@ -271,12 +276,12 @@
271276
android:name=".features.attachments.preview.AttachmentsPreviewActivity"
272277
android:theme="@style/Theme.Vector.Black.AttachmentsPreview" />
273278
<activity
274-
android:supportsPictureInPicture="true"
275-
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
276279
android:name=".features.call.VectorCallActivity"
280+
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
281+
android:excludeFromRecents="true"
277282
android:launchMode="singleTask"
278-
android:taskAffinity=".features.call.VectorCallActivity"
279-
android:excludeFromRecents="true" />
283+
android:supportsPictureInPicture="true"
284+
android:taskAffinity=".features.call.VectorCallActivity" />
280285
<!-- PIP Support https://developer.android.com/guide/topics/ui/picture-in-picture -->
281286
<activity
282287
android:name=".features.call.conference.VectorJitsiActivity"

vector/src/main/java/im/vector/app/core/di/ScreenComponent.kt

-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ import im.vector.app.features.matrixto.MatrixToBottomSheet
6262
import im.vector.app.features.media.BigImageViewerActivity
6363
import im.vector.app.features.media.VectorAttachmentViewerActivity
6464
import im.vector.app.features.navigation.Navigator
65-
import im.vector.app.features.permalink.PermalinkHandlerActivity
6665
import im.vector.app.features.pin.PinLocker
6766
import im.vector.app.features.qrcode.QrCodeScannerActivity
6867
import im.vector.app.features.rageshake.BugReportActivity
@@ -153,7 +152,6 @@ interface ScreenComponent {
153152
fun inject(activity: CreateDirectRoomActivity)
154153
fun inject(activity: IncomingShareActivity)
155154
fun inject(activity: SoftLogoutActivity)
156-
fun inject(activity: PermalinkHandlerActivity)
157155
fun inject(activity: QrCodeScannerActivity)
158156
fun inject(activity: DebugMenuActivity)
159157
fun inject(activity: SharedSecureStorageActivity)

vector/src/main/java/im/vector/app/features/home/HomeActivity.kt

+13-13
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ import im.vector.app.features.navigation.Navigator
5151
import im.vector.app.features.notifications.NotificationDrawerManager
5252
import im.vector.app.features.permalink.NavigationInterceptor
5353
import im.vector.app.features.permalink.PermalinkHandler
54+
import im.vector.app.features.permalink.PermalinkHandler.Companion.MATRIX_TO_CUSTOM_SCHEME_URL_BASE
55+
import im.vector.app.features.permalink.PermalinkHandler.Companion.ROOM_LINK_PREFIX
56+
import im.vector.app.features.permalink.PermalinkHandler.Companion.USER_LINK_PREFIX
5457
import im.vector.app.features.popup.DefaultVectorAlert
5558
import im.vector.app.features.popup.PopupAlertManager
5659
import im.vector.app.features.popup.VerificationVectorAlert
@@ -266,20 +269,19 @@ class HomeActivity :
266269
private fun handleIntent(intent: Intent?) {
267270
intent?.dataString?.let { deepLink ->
268271
val resolvedLink = when {
269-
deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE) -> deepLink
270-
deepLink.startsWith(MATRIX_TO_CUSTOM_SCHEME_URL_BASE) -> {
271-
// This is a bit ugly, but for now just convert to matrix.to link for compatibility
272-
when {
272+
// Element custom scheme is not handled by the sdk, convert it to matrix.to link for compatibility
273+
deepLink.startsWith(MATRIX_TO_CUSTOM_SCHEME_URL_BASE) -> {
274+
val let = when {
273275
deepLink.startsWith(USER_LINK_PREFIX) -> deepLink.substring(USER_LINK_PREFIX.length)
274276
deepLink.startsWith(ROOM_LINK_PREFIX) -> deepLink.substring(ROOM_LINK_PREFIX.length)
275277
else -> null
276-
}?.let {
277-
activeSessionHolder.getSafeActiveSession()?.permalinkService()?.createPermalink(it)
278+
}?.let { permalinkId ->
279+
activeSessionHolder.getSafeActiveSession()?.permalinkService()?.createPermalink(permalinkId)
278280
}
281+
let
279282
}
280-
else -> return@let
283+
else -> deepLink
281284
}
282-
283285
permalinkHandler.launch(
284286
context = this,
285287
deepLink = resolvedLink,
@@ -290,9 +292,11 @@ class HomeActivity :
290292
.observeOn(AndroidSchedulers.mainThread())
291293
.subscribe { isHandled ->
292294
if (!isHandled) {
295+
val isMatrixToLink = deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE)
296+
|| deepLink.startsWith(MATRIX_TO_CUSTOM_SCHEME_URL_BASE)
293297
MaterialAlertDialogBuilder(this)
294298
.setTitle(R.string.dialog_title_error)
295-
.setMessage(R.string.permalink_malformed)
299+
.setMessage(if (isMatrixToLink) R.string.permalink_malformed else R.string.universal_link_malformed)
296300
.setPositiveButton(R.string.ok, null)
297301
.show()
298302
}
@@ -559,10 +563,6 @@ class HomeActivity :
559563
putExtra(MvRx.KEY_ARG, args)
560564
}
561565
}
562-
563-
private const val MATRIX_TO_CUSTOM_SCHEME_URL_BASE = "element://"
564-
private const val ROOM_LINK_PREFIX = "${MATRIX_TO_CUSTOM_SCHEME_URL_BASE}room/"
565-
private const val USER_LINK_PREFIX = "${MATRIX_TO_CUSTOM_SCHEME_URL_BASE}user/"
566566
}
567567

568568
override fun create(initialState: ActiveSpaceViewState) = promoteRestrictedViewModelFactory.create(initialState)

0 commit comments

Comments
 (0)