From 91c98d4bfb50303c4adbaeeb8f9bd676e6767cb1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 21 Nov 2019 19:15:58 +0100 Subject: [PATCH 1/7] Permalink: start handling permalink from outside the app --- vector/src/main/AndroidManifest.xml | 20 +++++- .../vector/riotx/core/di/ScreenComponent.kt | 3 + .../home/room/detail/RoomDetailFragment.kt | 4 +- .../features/navigation/DefaultNavigator.kt | 45 ++++++++------ .../riotx/features/navigation/Navigator.kt | 8 +-- .../{home => permalink}/PermalinkHandler.kt | 35 +++++++---- .../permalink/PermalinkHandlerActivity.kt | 61 +++++++++++++++++++ 7 files changed, 138 insertions(+), 38 deletions(-) rename vector/src/main/java/im/vector/riotx/features/{home => permalink}/PermalinkHandler.kt (76%) create mode 100644 vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 61eebc99db..068e7423d8 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -65,7 +65,13 @@ - + + + @@ -102,6 +108,18 @@ + + + + + + + + + + + + { if (navigateToRoomInterceptor?.navToRoom(permalinkData.roomIdOrAlias, permalinkData.eventId) != true) { - openRoom(context, permalinkData.roomIdOrAlias, permalinkData.eventId) + openRoom(context, permalinkData.roomIdOrAlias, permalinkData.eventId, buildTask) } - true } is PermalinkData.RoomLink -> { if (navigateToRoomInterceptor?.navToRoom(permalinkData.roomIdOrAlias) != true) { - openRoom(context, permalinkData.roomIdOrAlias) + openRoom(context, permalinkData.roomIdOrAlias, null, buildTask) } true } is PermalinkData.GroupLink -> { - navigator.openGroupDetail(permalinkData.groupId, context) - true + navigator.openGroupDetail(permalinkData.groupId, context, buildTask) + false } is PermalinkData.UserLink -> { - navigator.openUserDetail(permalinkData.userId, context) + navigator.openUserDetail(permalinkData.userId, context, buildTask) true } is PermalinkData.FallbackLink -> { @@ -69,11 +78,11 @@ class PermalinkHandler @Inject constructor(private val session: Session, /** * Open room either joined, or not unknown */ - private fun openRoom(context: Context, roomIdOrAlias: String, eventId: String? = null) { + private fun openRoom(context: Context, roomIdOrAlias: String, eventId: String? = null, buildTask: Boolean) { if (session.getRoom(roomIdOrAlias) != null) { - navigator.openRoom(context, roomIdOrAlias, eventId) + navigator.openRoom(context, roomIdOrAlias, eventId, buildTask) } else { - navigator.openNotJoinedRoom(context, roomIdOrAlias, eventId) + navigator.openNotJoinedRoom(context, roomIdOrAlias, eventId, buildTask) } } } diff --git a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt new file mode 100644 index 0000000000..3512cc8187 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.riotx.features.permalink + +import android.content.Intent +import android.os.Bundle +import im.vector.riotx.core.di.ActiveSessionHolder +import im.vector.riotx.core.di.ScreenComponent +import im.vector.riotx.core.platform.VectorBaseActivity +import im.vector.riotx.features.login.LoginActivity +import timber.log.Timber +import javax.inject.Inject + +class PermalinkHandlerActivity : VectorBaseActivity() { + + @Inject lateinit var permalinkHandler: PermalinkHandler + @Inject lateinit var sessionHolder: ActiveSessionHolder + + override fun injectWith(injector: ScreenComponent) { + injector.inject(this) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + // If we are not logged in, stop the sharing process and open login screen. + // In the future, we might want to relaunch the sharing process after login. + if (!sessionHolder.hasActiveSession()) { + startLoginActivity() + return + } + val uri = intent.dataString + val isHandled = permalinkHandler.launch(this, uri, buildTask = true) + if (!isHandled) { + Timber.v("Couldn't handle permalink") + } + finish() + } + + private fun startLoginActivity() { + val intent = LoginActivity.newIntent(this, null) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity(intent) + finish() + } + + +} From 02febfb01bf4611a7a551ac15b48f617f2dafe78 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 21 Nov 2019 20:38:01 +0100 Subject: [PATCH 2/7] Start handling room alias --- .../android/api/permalinks/PermalinkData.kt | 4 +- .../android/api/permalinks/PermalinkParser.kt | 21 +++++--- .../android/api/session/room/RoomService.kt | 7 +++ .../api/session/room/model/RoomSummary.kt | 3 ++ .../database/mapper/RoomSummaryMapper.kt | 4 +- .../database/model/RoomSummaryEntity.kt | 2 + .../query/RoomSummaryEntityQueries.kt | 12 +++++ .../session/room/DefaultRoomService.kt | 12 +++++ .../android/internal/session/room/RoomAPI.kt | 9 ++++ .../internal/session/room/RoomModule.kt | 5 ++ .../session/room/RoomSummaryUpdater.kt | 17 +++++-- .../room/alias/GetRoomIdByAliasTask.kt | 48 +++++++++++++++++++ .../room/alias/RoomAliasDescription.kt | 33 +++++++++++++ 13 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/GetRoomIdByAliasTask.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/RoomAliasDescription.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkData.kt index 47f8bf4505..626fc49e8e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkData.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkData.kt @@ -24,9 +24,9 @@ import android.net.Uri */ sealed class PermalinkData { - data class EventLink(val roomIdOrAlias: String, val eventId: String) : PermalinkData() + data class EventLink(val roomIdOrAlias: String, val eventId: String, val isRoomAlias: Boolean) : PermalinkData() - data class RoomLink(val roomIdOrAlias: String) : PermalinkData() + data class RoomLink(val roomIdOrAlias: String, val isRoomAlias: Boolean) : PermalinkData() data class UserLink(val userId: String) : PermalinkData() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkParser.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkParser.kt index 531f4ae523..588fbce9d0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkParser.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkParser.kt @@ -18,6 +18,8 @@ package im.vector.matrix.android.api.permalinks import android.net.Uri import im.vector.matrix.android.api.MatrixPatterns +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext /** * This class turns an uri to a [PermalinkData] @@ -60,16 +62,23 @@ object PermalinkParser { return PermalinkData.FallbackLink(uri) } return when { - MatrixPatterns.isUserId(identifier) -> PermalinkData.UserLink(userId = identifier) - MatrixPatterns.isGroupId(identifier) -> PermalinkData.GroupLink(groupId = identifier) - MatrixPatterns.isRoomId(identifier) -> { + MatrixPatterns.isUserId(identifier) -> PermalinkData.UserLink(userId = identifier) + MatrixPatterns.isGroupId(identifier) -> PermalinkData.GroupLink(groupId = identifier) + MatrixPatterns.isRoomId(identifier) -> { if (!extraParameter.isNullOrEmpty() && MatrixPatterns.isEventId(extraParameter)) { - PermalinkData.EventLink(roomIdOrAlias = identifier, eventId = extraParameter) + PermalinkData.EventLink(roomIdOrAlias = identifier, eventId = extraParameter, isRoomAlias = false) } else { - PermalinkData.RoomLink(roomIdOrAlias = identifier) + PermalinkData.RoomLink(roomIdOrAlias = identifier, isRoomAlias = false) } } - else -> PermalinkData.FallbackLink(uri) + MatrixPatterns.isRoomAlias(identifier) -> { + if (!extraParameter.isNullOrEmpty() && MatrixPatterns.isEventId(extraParameter)) { + PermalinkData.EventLink(roomIdOrAlias = identifier, eventId = extraParameter, isRoomAlias = true) + } else { + PermalinkData.RoomLink(roomIdOrAlias = identifier, isRoomAlias = true) + } + } + else -> PermalinkData.FallbackLink(uri) } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt index 98abce5898..75de4e44a6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt @@ -18,6 +18,7 @@ package im.vector.matrix.android.api.session.room import androidx.lifecycle.LiveData import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.internal.session.room.alias.RoomAliasDescription import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams import im.vector.matrix.android.api.util.Cancelable @@ -74,4 +75,10 @@ interface RoomService { */ fun markAllAsRead(roomIds: List, callback: MatrixCallback): Cancelable + + /** + * Resolve a room alias to a room ID. + */ + fun getRoomIdByAlias(roomAlias: String, + callback: MatrixCallback): Cancelable } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt index 447ba563de..4807ae605c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt @@ -19,6 +19,7 @@ package im.vector.matrix.android.api.session.room.model import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.matrix.android.api.session.room.send.UserDraft import im.vector.matrix.android.api.session.room.timeline.TimelineEvent +import io.realm.RealmList /** * This class holds some data of a room. @@ -29,6 +30,8 @@ data class RoomSummary( val displayName: String = "", val topic: String = "", val avatarUrl: String = "", + val canonicalAlias: String? = null, + val aliases: List = emptyList(), val isDirect: Boolean = false, val latestPreviewableEvent: TimelineEvent? = null, val otherMemberIds: List = emptyList(), diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt index 2577bec581..eeb340eacb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt @@ -68,7 +68,9 @@ internal class RoomSummaryMapper @Inject constructor( membership = roomSummaryEntity.membership, versioningState = roomSummaryEntity.versioningState, readMarkerId = roomSummaryEntity.readMarkerId, - userDrafts = roomSummaryEntity.userDrafts?.userDrafts?.map { DraftMapper.map(it) } ?: emptyList() + userDrafts = roomSummaryEntity.userDrafts?.userDrafts?.map { DraftMapper.map(it) } ?: emptyList(), + canonicalAlias = roomSummaryEntity.canonicalAlias, + aliases = roomSummaryEntity.aliases.toList() ) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt index 47904380a0..b5b1644e74 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt @@ -40,6 +40,8 @@ internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "", var tags: RealmList = RealmList(), var userDrafts: UserDraftsEntity? = null, var breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS + var canonicalAlias: String? = null, + var aliases: RealmList = RealmList() ) : RealmObject() { private var membershipStr: String = Membership.NONE.name diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/RoomSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/RoomSummaryEntityQueries.kt index 79473f3b10..07f5133128 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/RoomSummaryEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/RoomSummaryEntityQueries.kt @@ -32,6 +32,18 @@ internal fun RoomSummaryEntity.Companion.where(realm: Realm, roomId: String? = n return query } +internal fun RoomSummaryEntity.Companion.findByAlias(realm: Realm, roomAlias: String): RoomSummaryEntity? { + val roomSummary = realm.where() + .equalTo(RoomSummaryEntityFields.CANONICAL_ALIAS, roomAlias) + .findFirst() + if (roomSummary != null) { + return roomSummary + } + return realm.where() + .`in`(RoomSummaryEntityFields.ALIASES.`$`, arrayOf(roomAlias)) + .findFirst() +} + internal fun RoomSummaryEntity.Companion.getOrCreate(realm: Realm, roomId: String): RoomSummaryEntity { return where(realm, roomId).findFirst() ?: realm.createObject(roomId) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt index 22caf76eaf..a45e41295c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt @@ -21,6 +21,7 @@ import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.RoomService +import im.vector.matrix.android.internal.session.room.alias.RoomAliasDescription import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.VersioningState import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams @@ -30,6 +31,7 @@ import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.room.alias.GetRoomIdByAliasTask import im.vector.matrix.android.internal.session.room.create.CreateRoomTask import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask import im.vector.matrix.android.internal.session.room.read.MarkAllRoomsReadTask @@ -45,9 +47,11 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona private val joinRoomTask: JoinRoomTask, private val markAllRoomsReadTask: MarkAllRoomsReadTask, private val updateBreadcrumbsTask: UpdateBreadcrumbsTask, + private val roomIdByAliasTask: GetRoomIdByAliasTask, private val roomFactory: RoomFactory, private val taskExecutor: TaskExecutor) : RoomService { + override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback): Cancelable { return createRoomTask .configureWith(createRoomParams) { @@ -111,4 +115,12 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona } .executeBy(taskExecutor) } + + override fun getRoomIdByAlias(roomAlias: String, callback: MatrixCallback): Cancelable { + return roomIdByAliasTask + .configureWith(GetRoomIdByAliasTask.Params(roomAlias)) { + this.callback = callback + } + .executeBy(taskExecutor) + } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt index 40164d1697..c5b3f03d35 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAPI.kt @@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.room import im.vector.matrix.android.api.session.events.model.Content import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.internal.session.room.alias.RoomAliasDescription import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsParams @@ -258,4 +259,12 @@ internal interface RoomAPI { fun reportContent(@Path("roomId") roomId: String, @Path("eventId") eventId: String, @Body body: ReportContentBody): Call + + /** + * Get the room ID associated to the room alias. + * + * @param roomAlias the room alias. + */ + @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}") + fun getRoomIdByAlias(@Path("roomAlias") roomAlias: String): Call } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt index 1aca492b94..cc786a7493 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomModule.kt @@ -24,6 +24,8 @@ import im.vector.matrix.android.api.session.room.RoomDirectoryService import im.vector.matrix.android.api.session.room.RoomService import im.vector.matrix.android.internal.session.DefaultFileService import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.session.room.alias.DefaultGetRoomIdByAliasTask +import im.vector.matrix.android.internal.session.room.alias.GetRoomIdByAliasTask import im.vector.matrix.android.internal.session.room.create.CreateRoomTask import im.vector.matrix.android.internal.session.room.create.DefaultCreateRoomTask import im.vector.matrix.android.internal.session.room.directory.DefaultGetPublicRoomTask @@ -133,4 +135,7 @@ internal abstract class RoomModule { @Binds abstract fun bindFetchEditHistoryTask(fetchEditHistoryTask: DefaultFetchEditHistoryTask): FetchEditHistoryTask + + @Binds + abstract fun bindGetRoomIdByAliasTask(getRoomIdByAliasTask: DefaultGetRoomIdByAliasTask): GetRoomIdByAliasTask } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt index 1158c08984..11bc98164b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt @@ -20,6 +20,8 @@ import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.Membership +import im.vector.matrix.android.api.session.room.model.RoomAliasesContent +import im.vector.matrix.android.api.session.room.model.RoomCanonicalAliasContent import im.vector.matrix.android.api.session.room.model.RoomTopicContent import im.vector.matrix.android.internal.database.mapper.ContentMapper import im.vector.matrix.android.internal.database.model.EventEntity @@ -68,7 +70,7 @@ internal class RoomSummaryUpdater @Inject constructor(@UserId private val userId unreadNotifications: RoomSyncUnreadNotifications? = null, updateMembers: Boolean = false) { val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() - ?: realm.createObject(roomId) + ?: realm.createObject(roomId) if (roomSummary != null) { if (roomSummary.heroes.isNotEmpty()) { @@ -91,15 +93,24 @@ internal class RoomSummaryUpdater @Inject constructor(@UserId private val userId val latestPreviewableEvent = TimelineEventEntity.latestEvent(realm, roomId, includesSending = true, filterTypes = PREVIEWABLE_TYPES) val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).prev() + val lastCanonicalAliasEvent = EventEntity.where(realm, roomId, EventType.STATE_CANONICAL_ALIAS).prev() + val lastAliasesEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_ALIASES).prev() roomSummaryEntity.hasUnreadMessages = roomSummaryEntity.notificationCount > 0 - // avoid this call if we are sure there are unread events - || !isEventRead(monarchy, userId, roomId, latestPreviewableEvent?.eventId) + // avoid this call if we are sure there are unread events + || !isEventRead(monarchy, userId, roomId, latestPreviewableEvent?.eventId) roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(roomId).toString() roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(roomId) roomSummaryEntity.topic = ContentMapper.map(lastTopicEvent?.content).toModel()?.topic roomSummaryEntity.latestPreviewableEvent = latestPreviewableEvent + roomSummaryEntity.canonicalAlias = ContentMapper.map(lastCanonicalAliasEvent?.content).toModel() + ?.canonicalAlias + + val roomAliases = ContentMapper.map(lastAliasesEvent?.content).toModel()?.aliases ?: emptyList() + roomSummaryEntity.aliases.clear() + roomSummaryEntity.aliases.addAll(roomAliases) + if (updateMembers) { val otherRoomMembers = RoomMembers(realm, roomId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/GetRoomIdByAliasTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/GetRoomIdByAliasTask.kt new file mode 100644 index 0000000000..5ff2e47c70 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/GetRoomIdByAliasTask.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.matrix.android.internal.session.room.alias + +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.internal.database.model.RoomSummaryEntity +import im.vector.matrix.android.internal.database.query.findByAlias +import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.session.room.RoomAPI +import im.vector.matrix.android.internal.task.Task +import io.realm.Realm +import javax.inject.Inject + +internal interface GetRoomIdByAliasTask : Task { + data class Params( + val roomAlias: String + ) +} + +internal class DefaultGetRoomIdByAliasTask @Inject constructor(private val monarchy: Monarchy, + private val roomAPI: RoomAPI) : GetRoomIdByAliasTask { + + override suspend fun execute(params: GetRoomIdByAliasTask.Params): String? { + val roomId = Realm.getInstance(monarchy.realmConfiguration).use { + RoomSummaryEntity.findByAlias(it, params.roomAlias)?.roomId + } + if (roomId != null) { + return roomId + } + return executeRequest { + apiCall = roomAPI.getRoomIdByAlias(params.roomAlias) + }.roomId + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/RoomAliasDescription.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/RoomAliasDescription.kt new file mode 100644 index 0000000000..8d352cfed9 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/RoomAliasDescription.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.matrix.android.internal.session.room.alias + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class RoomAliasDescription( + /** + * The room ID for this alias. + */ + @Json(name = "room_id") val roomId: String, + + /** + * A list of servers that are aware of this room ID. + */ + @Json(name = "servers") val servers: List = emptyList() +) From abf0796794f88a3b34397a823e278c06253d04ed Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 25 Nov 2019 17:02:04 +0100 Subject: [PATCH 3/7] Room alias and matrix.to link: we can now open a room though roomAlias as long as it's a joined one --- .../matrix/rx/MatrixCallbackCompletable.kt | 38 ----------- .../vector/matrix/rx/MatrixCallbackSingle.kt | 38 ----------- .../im/vector/matrix/rx/RxCallbackBuilders.kt | 54 ++++++++++++++++ .../main/java/im/vector/matrix/rx/RxRoom.kt | 8 +-- .../java/im/vector/matrix/rx/RxSession.kt | 17 +++-- .../android/api/permalinks/PermalinkData.kt | 4 +- .../android/api/permalinks/PermalinkParser.kt | 16 ++--- .../android/api/session/room/RoomService.kt | 5 +- .../session/room/members/MembershipService.kt | 1 - .../api/session/room/model/RoomSummary.kt | 1 - .../database/model/RoomSummaryEntity.kt | 3 +- .../query/RoomSummaryEntityQueries.kt | 2 +- .../session/room/DefaultRoomService.kt | 7 +- .../session/room/RoomSummaryUpdater.kt | 2 +- .../room/alias/GetRoomIdByAliasTask.kt | 24 ++++--- .../home/room/detail/RoomDetailFragment.kt | 64 +++++++++++-------- .../features/navigation/DefaultNavigator.kt | 16 +++-- .../riotx/features/navigation/Navigator.kt | 2 +- .../features/permalink/PermalinkHandler.kt | 57 ++++++++++------- .../permalink/PermalinkHandlerActivity.kt | 26 +++++--- 20 files changed, 199 insertions(+), 186 deletions(-) delete mode 100644 matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/MatrixCallbackCompletable.kt delete mode 100644 matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/MatrixCallbackSingle.kt create mode 100644 matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxCallbackBuilders.kt diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/MatrixCallbackCompletable.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/MatrixCallbackCompletable.kt deleted file mode 100644 index cf0e955b00..0000000000 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/MatrixCallbackCompletable.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.matrix.rx - -import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.util.Cancelable -import io.reactivex.CompletableEmitter - -internal class MatrixCallbackCompletable(private val completableEmitter: CompletableEmitter) : MatrixCallback { - - override fun onSuccess(data: T) { - completableEmitter.onComplete() - } - - override fun onFailure(failure: Throwable) { - completableEmitter.tryOnError(failure) - } -} - -fun Cancelable.toCompletable(completableEmitter: CompletableEmitter) { - completableEmitter.setCancellable { - this.cancel() - } -} diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/MatrixCallbackSingle.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/MatrixCallbackSingle.kt deleted file mode 100644 index d638354dfd..0000000000 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/MatrixCallbackSingle.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.matrix.rx - -import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.api.util.Cancelable -import io.reactivex.SingleEmitter - -internal class MatrixCallbackSingle(private val singleEmitter: SingleEmitter) : MatrixCallback { - - override fun onSuccess(data: T) { - singleEmitter.onSuccess(data) - } - - override fun onFailure(failure: Throwable) { - singleEmitter.tryOnError(failure) - } -} - -fun Cancelable.toSingle(singleEmitter: SingleEmitter) { - singleEmitter.setCancellable { - this.cancel() - } -} diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxCallbackBuilders.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxCallbackBuilders.kt new file mode 100644 index 0000000000..92886777af --- /dev/null +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxCallbackBuilders.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.matrix.rx + +import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.util.Cancelable +import io.reactivex.Completable +import io.reactivex.Single + +fun singleBuilder(builder: (callback: MatrixCallback) -> Cancelable): Single = Single.create { + val callback: MatrixCallback = object : MatrixCallback { + override fun onSuccess(data: T) { + it.onSuccess(data) + } + + override fun onFailure(failure: Throwable) { + it.tryOnError(failure) + } + } + val cancelable = builder(callback) + it.setCancellable { + cancelable.cancel() + } +} + +fun completableBuilder(builder: (callback: MatrixCallback) -> Cancelable): Completable = Completable.create { + val callback: MatrixCallback = object : MatrixCallback { + override fun onSuccess(data: T) { + it.onComplete() + } + + override fun onFailure(failure: Throwable) { + it.tryOnError(failure) + } + } + val cancelable = builder(callback) + it.setCancellable { + cancelable.cancel() + } +} diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index bc0a866117..e5ebc536ff 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -53,13 +53,13 @@ class RxRoom(private val room: Room) { return room.getMyReadReceiptLive().asObservable() } - fun loadRoomMembersIfNeeded(): Single = Single.create { - room.loadRoomMembersIfNeeded(MatrixCallbackSingle(it)).toSingle(it) + fun loadRoomMembersIfNeeded(): Single = singleBuilder { + room.loadRoomMembersIfNeeded(it) } fun joinRoom(reason: String? = null, - viaServers: List = emptyList()): Single = Single.create { - room.join(reason, viaServers, MatrixCallbackSingle(it)).toSingle(it) + viaServers: List = emptyList()): Single = singleBuilder { + room.join(reason, viaServers, it) } fun liveEventReadReceipts(eventId: String): Observable> { diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 5a42dbb804..c9381b861d 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -66,20 +66,25 @@ class RxSession(private val session: Session) { return session.livePagedUsers(filter).asObservable() } - fun createRoom(roomParams: CreateRoomParams): Single = Single.create { - session.createRoom(roomParams, MatrixCallbackSingle(it)).toSingle(it) + fun createRoom(roomParams: CreateRoomParams): Single = singleBuilder { + session.createRoom(roomParams, it) } fun searchUsersDirectory(search: String, limit: Int, - excludedUserIds: Set): Single> = Single.create { - session.searchUsersDirectory(search, limit, excludedUserIds, MatrixCallbackSingle(it)).toSingle(it) + excludedUserIds: Set): Single> = singleBuilder { + session.searchUsersDirectory(search, limit, excludedUserIds, it) } fun joinRoom(roomId: String, reason: String? = null, - viaServers: List = emptyList()): Single = Single.create { - session.joinRoom(roomId, reason, viaServers, MatrixCallbackSingle(it)).toSingle(it) + viaServers: List = emptyList()): Single = singleBuilder { + session.joinRoom(roomId, reason, viaServers, it) + } + + fun getRoomIdByAlias(roomAlias: String, + searchOnServer: Boolean): Single> = singleBuilder { + session.getRoomIdByAlias(roomAlias, searchOnServer, it) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkData.kt index 626fc49e8e..ecdbe86b98 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkData.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkData.kt @@ -24,9 +24,7 @@ import android.net.Uri */ sealed class PermalinkData { - data class EventLink(val roomIdOrAlias: String, val eventId: String, val isRoomAlias: Boolean) : PermalinkData() - - data class RoomLink(val roomIdOrAlias: String, val isRoomAlias: Boolean) : PermalinkData() + data class RoomLink(val roomIdOrAlias: String, val isRoomAlias: Boolean, val eventId: String?) : PermalinkData() data class UserLink(val userId: String) : PermalinkData() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkParser.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkParser.kt index 588fbce9d0..d10152f4fe 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkParser.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/permalinks/PermalinkParser.kt @@ -18,8 +18,6 @@ package im.vector.matrix.android.api.permalinks import android.net.Uri import im.vector.matrix.android.api.MatrixPatterns -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext /** * This class turns an uri to a [PermalinkData] @@ -65,18 +63,16 @@ object PermalinkParser { MatrixPatterns.isUserId(identifier) -> PermalinkData.UserLink(userId = identifier) MatrixPatterns.isGroupId(identifier) -> PermalinkData.GroupLink(groupId = identifier) MatrixPatterns.isRoomId(identifier) -> { - if (!extraParameter.isNullOrEmpty() && MatrixPatterns.isEventId(extraParameter)) { - PermalinkData.EventLink(roomIdOrAlias = identifier, eventId = extraParameter, isRoomAlias = false) - } else { - PermalinkData.RoomLink(roomIdOrAlias = identifier, isRoomAlias = false) + val eventId = extraParameter.takeIf { + !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) } + PermalinkData.RoomLink(roomIdOrAlias = identifier, isRoomAlias = false, eventId = eventId) } MatrixPatterns.isRoomAlias(identifier) -> { - if (!extraParameter.isNullOrEmpty() && MatrixPatterns.isEventId(extraParameter)) { - PermalinkData.EventLink(roomIdOrAlias = identifier, eventId = extraParameter, isRoomAlias = true) - } else { - PermalinkData.RoomLink(roomIdOrAlias = identifier, isRoomAlias = true) + val eventId = extraParameter.takeIf { + !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) } + PermalinkData.RoomLink(roomIdOrAlias = identifier, isRoomAlias = true, eventId = eventId) } else -> PermalinkData.FallbackLink(uri) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt index 75de4e44a6..afe7cf8bc3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt @@ -18,10 +18,10 @@ package im.vector.matrix.android.api.session.room import androidx.lifecycle.LiveData import im.vector.matrix.android.api.MatrixCallback -import im.vector.matrix.android.internal.session.room.alias.RoomAliasDescription import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams import im.vector.matrix.android.api.util.Cancelable +import im.vector.matrix.android.api.util.Optional /** * This interface defines methods to get rooms. It's implemented at the session level. @@ -80,5 +80,6 @@ interface RoomService { * Resolve a room alias to a room ID. */ fun getRoomIdByAlias(roomAlias: String, - callback: MatrixCallback): Cancelable + searchOnServer: Boolean, + callback: MatrixCallback>): Cancelable } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/members/MembershipService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/members/MembershipService.kt index b750c5347e..34af2cf572 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/members/MembershipService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/members/MembershipService.kt @@ -59,7 +59,6 @@ interface MembershipService { /** * Join the room, or accept an invitation. */ - fun join(reason: String? = null, viaServers: List = emptyList(), callback: MatrixCallback): Cancelable diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt index 4807ae605c..129c35a17e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt @@ -19,7 +19,6 @@ package im.vector.matrix.android.api.session.room.model import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.matrix.android.api.session.room.send.UserDraft import im.vector.matrix.android.api.session.room.timeline.TimelineEvent -import io.realm.RealmList /** * This class holds some data of a room. diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt index b5b1644e74..26074f3687 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt @@ -41,7 +41,8 @@ internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "", var userDrafts: UserDraftsEntity? = null, var breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS var canonicalAlias: String? = null, - var aliases: RealmList = RealmList() + var aliases: RealmList = RealmList(), + var flatAliases: String = "" ) : RealmObject() { private var membershipStr: String = Membership.NONE.name diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/RoomSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/RoomSummaryEntityQueries.kt index 07f5133128..1f242ce83a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/RoomSummaryEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/RoomSummaryEntityQueries.kt @@ -40,7 +40,7 @@ internal fun RoomSummaryEntity.Companion.findByAlias(realm: Realm, roomAlias: St return roomSummary } return realm.where() - .`in`(RoomSummaryEntityFields.ALIASES.`$`, arrayOf(roomAlias)) + .contains(RoomSummaryEntityFields.FLAT_ALIASES, "|$roomAlias") .findFirst() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt index a45e41295c..de60e6e7e4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt @@ -21,11 +21,11 @@ import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.RoomService -import im.vector.matrix.android.internal.session.room.alias.RoomAliasDescription import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.VersioningState import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams import im.vector.matrix.android.api.util.Cancelable +import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity @@ -51,7 +51,6 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona private val roomFactory: RoomFactory, private val taskExecutor: TaskExecutor) : RoomService { - override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback): Cancelable { return createRoomTask .configureWith(createRoomParams) { @@ -116,9 +115,9 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona .executeBy(taskExecutor) } - override fun getRoomIdByAlias(roomAlias: String, callback: MatrixCallback): Cancelable { + override fun getRoomIdByAlias(roomAlias: String, searchOnServer: Boolean, callback: MatrixCallback>): Cancelable { return roomIdByAliasTask - .configureWith(GetRoomIdByAliasTask.Params(roomAlias)) { + .configureWith(GetRoomIdByAliasTask.Params(roomAlias, searchOnServer)) { this.callback = callback } .executeBy(taskExecutor) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt index 11bc98164b..126d13c5db 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt @@ -110,7 +110,7 @@ internal class RoomSummaryUpdater @Inject constructor(@UserId private val userId val roomAliases = ContentMapper.map(lastAliasesEvent?.content).toModel()?.aliases ?: emptyList() roomSummaryEntity.aliases.clear() roomSummaryEntity.aliases.addAll(roomAliases) - + roomSummaryEntity.flatAliases = roomAliases.joinToString(separator = "|", prefix = "|") if (updateMembers) { val otherRoomMembers = RoomMembers(realm, roomId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/GetRoomIdByAliasTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/GetRoomIdByAliasTask.kt index 5ff2e47c70..1a726c3fe5 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/GetRoomIdByAliasTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/GetRoomIdByAliasTask.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.internal.session.room.alias import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.query.findByAlias import im.vector.matrix.android.internal.network.executeRequest @@ -25,24 +26,29 @@ import im.vector.matrix.android.internal.task.Task import io.realm.Realm import javax.inject.Inject -internal interface GetRoomIdByAliasTask : Task { +internal interface GetRoomIdByAliasTask : Task> { data class Params( - val roomAlias: String + val roomAlias: String, + val searchOnServer: Boolean ) } internal class DefaultGetRoomIdByAliasTask @Inject constructor(private val monarchy: Monarchy, private val roomAPI: RoomAPI) : GetRoomIdByAliasTask { - override suspend fun execute(params: GetRoomIdByAliasTask.Params): String? { - val roomId = Realm.getInstance(monarchy.realmConfiguration).use { + override suspend fun execute(params: GetRoomIdByAliasTask.Params): Optional { + var roomId = Realm.getInstance(monarchy.realmConfiguration).use { RoomSummaryEntity.findByAlias(it, params.roomAlias)?.roomId } - if (roomId != null) { - return roomId + return if (roomId != null) { + Optional.from(roomId) + } else if (!params.searchOnServer) { + Optional.from(null) + } else { + roomId = executeRequest { + apiCall = roomAPI.getRoomIdByAlias(params.roomAlias) + }.roomId + Optional.from(roomId) } - return executeRequest { - apiCall = roomAPI.getRoomIdByAlias(params.roomAlias) - }.roomId } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 2dad3bcb8f..8887b94f92 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -113,6 +113,8 @@ import im.vector.riotx.features.reactions.EmojiReactionPickerActivity import im.vector.riotx.features.settings.VectorPreferences import im.vector.riotx.features.share.SharedData import im.vector.riotx.features.themes.ThemeUtils +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_room_detail.* import kotlinx.android.synthetic.main.merge_composer_layout.view.* @@ -851,30 +853,33 @@ class RoomDetailFragment @Inject constructor( // TimelineEventController.Callback ************************************************************ override fun onUrlClicked(url: String): Boolean { - val managed = permalinkHandler.launch(requireActivity(), url, object : NavigateToRoomInterceptor { - override fun navToRoom(roomId: String, eventId: String?): Boolean { - // Same room? - if (roomId == roomDetailArgs.roomId) { - // Navigation to same room - if (eventId == null) { - showSnackWithMessage(getString(R.string.navigate_to_room_when_already_in_the_room)) - } else { - // Highlight and scroll to this event - roomDetailViewModel.handle(RoomDetailAction.NavigateToEvent(eventId, true)) + permalinkHandler + .launch(requireActivity(), url, object : NavigateToRoomInterceptor { + override fun navToRoom(roomId: String?, eventId: String?): Boolean { + // Same room? + if (roomId == roomDetailArgs.roomId) { + // Navigation to same room + if (eventId == null) { + showSnackWithMessage(getString(R.string.navigate_to_room_when_already_in_the_room)) + } else { + // Highlight and scroll to this event + roomDetailViewModel.handle(RoomDetailAction.NavigateToEvent(eventId, true)) + } + return true + } + // Not handled + return false + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { managed -> + if (!managed) { + // Open in external browser, in a new Tab + openUrlInExternalBrowser(requireContext(), url) } - return true } - - // Not handled - return false - } - }) - - if (!managed) { - // Open in external browser, in a new Tab - openUrlInExternalBrowser(requireContext(), url) - } - + .disposeOnDestroyView() // In fact it is always managed return true } @@ -1022,12 +1027,15 @@ class RoomDetailFragment @Inject constructor( } override fun onRoomCreateLinkClicked(url: String) { - permalinkHandler.launch(requireContext(), url, object : NavigateToRoomInterceptor { - override fun navToRoom(roomId: String, eventId: String?): Boolean { - requireActivity().finish() - return false - } - }) + permalinkHandler + .launch(requireContext(), url, object : NavigateToRoomInterceptor { + override fun navToRoom(roomId: String?, eventId: String?): Boolean { + requireActivity().finish() + return false + } + }) + .subscribe() + .disposeOnDestroyView() } override fun onReadReceiptsClicked(readReceipts: List) { diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt index c57896bde1..19f6aece58 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt @@ -40,7 +40,6 @@ import javax.inject.Inject import javax.inject.Singleton import androidx.core.app.TaskStackBuilder - @Singleton class DefaultNavigator @Inject constructor() : Navigator { @@ -56,7 +55,7 @@ class DefaultNavigator @Inject constructor() : Navigator { } } - override fun openNotJoinedRoom(context: Context, roomIdOrAlias: String, eventId: String?, buildTask: Boolean) { + override fun openNotJoinedRoom(context: Context, roomIdOrAlias: String?, eventId: String?, buildTask: Boolean) { if (context is VectorBaseActivity) { context.notImplemented("Open not joined room") } else { @@ -64,13 +63,20 @@ class DefaultNavigator @Inject constructor() : Navigator { } } - override fun openGroupDetail(groupId: String, context: Context, buildTask: Boolean) { - Timber.v("Open group detail $groupId") + if (context is VectorBaseActivity) { + context.notImplemented("Open group detail") + } else { + context.toast(R.string.not_implemented) + } } override fun openUserDetail(userId: String, context: Context, buildTask: Boolean) { - Timber.v("Open user detail $userId") + if (context is VectorBaseActivity) { + context.notImplemented("Open user detail") + } else { + context.toast(R.string.not_implemented) + } } override fun openRoomForSharing(activity: Activity, roomId: String, sharedData: SharedData) { diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt index 30aa2605c1..278c8fdba0 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt @@ -27,7 +27,7 @@ interface Navigator { fun openRoomForSharing(activity: Activity, roomId: String, sharedData: SharedData) - fun openNotJoinedRoom(context: Context, roomIdOrAlias: String, eventId: String? = null, buildTask: Boolean = false) + fun openNotJoinedRoom(context: Context, roomIdOrAlias: String?, eventId: String? = null, buildTask: Boolean = false) fun openRoomPreview(publicRoom: PublicRoom, context: Context) diff --git a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandler.kt b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandler.kt index fab1e7288d..34f11378e7 100644 --- a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandler.kt +++ b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandler.kt @@ -21,7 +21,12 @@ import android.net.Uri import im.vector.matrix.android.api.permalinks.PermalinkData import im.vector.matrix.android.api.permalinks.PermalinkParser import im.vector.matrix.android.api.session.Session +import im.vector.matrix.android.api.util.Optional +import im.vector.matrix.rx.rx import im.vector.riotx.features.navigation.Navigator +import io.reactivex.Single +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers import javax.inject.Inject class PermalinkHandler @Inject constructor(private val session: Session, @@ -32,7 +37,7 @@ class PermalinkHandler @Inject constructor(private val session: Session, deepLink: String?, navigateToRoomInterceptor: NavigateToRoomInterceptor? = null, buildTask: Boolean = false - ): Boolean { + ): Single { val uri = deepLink?.let { Uri.parse(it) } return launch(context, uri, navigateToRoomInterceptor, buildTask) } @@ -42,47 +47,53 @@ class PermalinkHandler @Inject constructor(private val session: Session, deepLink: Uri?, navigateToRoomInterceptor: NavigateToRoomInterceptor? = null, buildTask: Boolean = false - ): Boolean { + ): Single { if (deepLink == null) { - return false + return Single.just(false) } - return when (val permalinkData = PermalinkParser.parse(deepLink)) { - is PermalinkData.EventLink -> { - if (navigateToRoomInterceptor?.navToRoom(permalinkData.roomIdOrAlias, permalinkData.eventId) != true) { - openRoom(context, permalinkData.roomIdOrAlias, permalinkData.eventId, buildTask) - } - true - } is PermalinkData.RoomLink -> { - if (navigateToRoomInterceptor?.navToRoom(permalinkData.roomIdOrAlias) != true) { - openRoom(context, permalinkData.roomIdOrAlias, null, buildTask) - } - - true + permalinkData.getRoomId() + .observeOn(AndroidSchedulers.mainThread()) + .map { + val roomId = it.getOrNull() + if (navigateToRoomInterceptor?.navToRoom(roomId) != true) { + openRoom(context, roomId, permalinkData.eventId, buildTask) + } + true + } } is PermalinkData.GroupLink -> { navigator.openGroupDetail(permalinkData.groupId, context, buildTask) - false + Single.just(true) } is PermalinkData.UserLink -> { navigator.openUserDetail(permalinkData.userId, context, buildTask) - true + Single.just(false) } is PermalinkData.FallbackLink -> { - false + Single.just(false) } } } + private fun PermalinkData.RoomLink.getRoomId(): Single> { + return if (isRoomAlias) { + // At the moment we are not fetching on the server as we don't handle not join room + session.rx().getRoomIdByAlias(roomIdOrAlias, false).subscribeOn(Schedulers.io()) + } else { + Single.just(Optional.from(roomIdOrAlias)) + } + } + /** * Open room either joined, or not unknown */ - private fun openRoom(context: Context, roomIdOrAlias: String, eventId: String? = null, buildTask: Boolean) { - if (session.getRoom(roomIdOrAlias) != null) { - navigator.openRoom(context, roomIdOrAlias, eventId, buildTask) + private fun openRoom(context: Context, roomId: String?, eventId: String? = null, buildTask: Boolean) { + return if (roomId != null && session.getRoom(roomId) != null) { + navigator.openRoom(context, roomId, eventId, buildTask) } else { - navigator.openNotJoinedRoom(context, roomIdOrAlias, eventId, buildTask) + navigator.openNotJoinedRoom(context, roomId, eventId, buildTask) } } } @@ -92,5 +103,5 @@ interface NavigateToRoomInterceptor { /** * Return true if the navigation has been intercepted */ - fun navToRoom(roomId: String, eventId: String? = null): Boolean + fun navToRoom(roomId: String?, eventId: String? = null): Boolean } diff --git a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt index 3512cc8187..26d8d04cda 100644 --- a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt @@ -18,11 +18,14 @@ package im.vector.riotx.features.permalink import android.content.Intent import android.os.Bundle +import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.platform.VectorBaseActivity +import im.vector.riotx.core.utils.toast import im.vector.riotx.features.login.LoginActivity -import timber.log.Timber +import io.reactivex.android.schedulers.AndroidSchedulers +import kotlinx.android.synthetic.debug.activity_test_material_theme.* import javax.inject.Inject class PermalinkHandlerActivity : VectorBaseActivity() { @@ -36,18 +39,23 @@ class PermalinkHandlerActivity : VectorBaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // If we are not logged in, stop the sharing process and open login screen. - // In the future, we might want to relaunch the sharing process after login. + setContentView(R.layout.activity) + // If we are not logged in, open login screen. + // In the future, we might want to relaunch the process after login. if (!sessionHolder.hasActiveSession()) { startLoginActivity() return } val uri = intent.dataString - val isHandled = permalinkHandler.launch(this, uri, buildTask = true) - if (!isHandled) { - Timber.v("Couldn't handle permalink") - } - finish() + permalinkHandler.launch(this, uri, buildTask = true) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { isHandled -> + if (!isHandled) { + toast("Your matrix.to link was malformed") + } + finish() + } + .disposeOnDestroy() } private fun startLoginActivity() { @@ -56,6 +64,4 @@ class PermalinkHandlerActivity : VectorBaseActivity() { startActivity(intent) finish() } - - } From bc568343a23be38bd3f0866b23c8688510839d20 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 25 Nov 2019 17:27:38 +0100 Subject: [PATCH 4/7] Open matrix.to with a loader --- .../riotx/features/permalink/PermalinkHandler.kt | 2 +- .../features/permalink/PermalinkHandlerActivity.kt | 13 +++++++++++-- vector/src/main/res/values/strings.xml | 1 + 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandler.kt b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandler.kt index 34f11378e7..c849166738 100644 --- a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandler.kt +++ b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandler.kt @@ -69,7 +69,7 @@ class PermalinkHandler @Inject constructor(private val session: Session, } is PermalinkData.UserLink -> { navigator.openUserDetail(permalinkData.userId, context, buildTask) - Single.just(false) + Single.just(true) } is PermalinkData.FallbackLink -> { Single.just(false) diff --git a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt index 26d8d04cda..026991b859 100644 --- a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt @@ -18,14 +18,19 @@ package im.vector.riotx.features.permalink import android.content.Intent import android.os.Bundle +import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.di.ScreenComponent +import im.vector.riotx.core.extensions.replaceFragment import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.utils.toast +import im.vector.riotx.features.home.LoadingFragment import im.vector.riotx.features.login.LoginActivity +import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.android.synthetic.debug.activity_test_material_theme.* +import java.util.concurrent.TimeUnit import javax.inject.Inject class PermalinkHandlerActivity : VectorBaseActivity() { @@ -39,7 +44,10 @@ class PermalinkHandlerActivity : VectorBaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity) + setContentView(R.layout.activity_simple) + if (isFirstCreation()) { + replaceFragment(R.id.simpleFragmentContainer, LoadingFragment::class.java) + } // If we are not logged in, open login screen. // In the future, we might want to relaunch the process after login. if (!sessionHolder.hasActiveSession()) { @@ -48,10 +56,11 @@ class PermalinkHandlerActivity : VectorBaseActivity() { } val uri = intent.dataString permalinkHandler.launch(this, uri, buildTask = true) + .delay(500, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe { isHandled -> if (!isHandled) { - toast("Your matrix.to link was malformed") + toast(R.string.permalink_malformed) } finish() } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 2e4d04354b..9f8fd7cb1b 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1800,5 +1800,6 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming Riot needs permission to save your E2E keys on disk.\n\nPlease allow access on the next pop-up to be able to export your keys manually. There is no network connection right now + Your matrix.to link was malformed From aa82cd2064d82896e430fcc352afd3f2733f515f Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 25 Nov 2019 17:59:19 +0100 Subject: [PATCH 5/7] Update CHANGES --- CHANGES.md | 3 ++- .../riotx/features/permalink/PermalinkHandlerActivity.kt | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 323f42186b..1228ea65ca 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,8 @@ Features ✨: - Implement soft logout (#281) Improvements 🙌: - - + - Handle navigation to room via room alias (#201) + - Open matrix.to link in RiotX (#57) Other changes: - Use same default room colors than Riot-Web diff --git a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt index 026991b859..08e09fa48d 100644 --- a/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/permalink/PermalinkHandlerActivity.kt @@ -18,7 +18,6 @@ package im.vector.riotx.features.permalink import android.content.Intent import android.os.Bundle -import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.di.ScreenComponent @@ -27,7 +26,6 @@ import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.utils.toast import im.vector.riotx.features.home.LoadingFragment import im.vector.riotx.features.login.LoginActivity -import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import kotlinx.android.synthetic.debug.activity_test_material_theme.* import java.util.concurrent.TimeUnit From e2b4899b36941c25f2b649e66931aaf3aa9e1598 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 16 Dec 2019 15:21:24 +0100 Subject: [PATCH 6/7] Internal review --- .../matrix/android/internal/database/model/RoomSummaryEntity.kt | 2 +- .../android/internal/session/room/alias/RoomAliasDescription.kt | 2 +- vector/src/main/res/values/strings.xml | 1 - vector/src/main/res/values/strings_riotX.xml | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt index 26074f3687..406c8700b6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt @@ -39,7 +39,7 @@ internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "", var hasUnreadMessages: Boolean = false, var tags: RealmList = RealmList(), var userDrafts: UserDraftsEntity? = null, - var breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS + var breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS, var canonicalAlias: String? = null, var aliases: RealmList = RealmList(), var flatAliases: String = "" diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/RoomAliasDescription.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/RoomAliasDescription.kt index 8d352cfed9..c7ddae0e10 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/RoomAliasDescription.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/alias/RoomAliasDescription.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -data class RoomAliasDescription( +internal data class RoomAliasDescription( /** * The room ID for this alias. */ diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 9f8fd7cb1b..2e4d04354b 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1800,6 +1800,5 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming Riot needs permission to save your E2E keys on disk.\n\nPlease allow access on the next pop-up to be able to export your keys manually. There is no network connection right now - Your matrix.to link was malformed diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 8c37ffd4b3..c9180c3878 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -161,4 +161,5 @@ Clear data The current session is for user %1$s and you provide credentials for user %2$s. This is not supported by RiotX.\nPlease first clear data, then sign in again on another account. + Your matrix.to link was malformed From c286f2a744a36577bf7cceed6ad30d3cfa06676d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 16 Dec 2019 15:43:58 +0100 Subject: [PATCH 7/7] ktlint --- .../im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt index 5a721b45f7..d3288c5b2e 100644 --- a/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/signout/soft/SoftLogoutFragment.kt @@ -27,8 +27,6 @@ import im.vector.riotx.core.dialogs.withColoredButton import im.vector.riotx.core.extensions.cleanup import im.vector.riotx.core.extensions.configureWith import im.vector.riotx.core.extensions.hideKeyboard -import im.vector.riotx.features.MainActivity -import im.vector.riotx.features.MainActivityArgs import im.vector.riotx.features.login.AbstractLoginFragment import im.vector.riotx.features.login.LoginAction import im.vector.riotx.features.login.LoginMode