mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-24 14:58:59 +03:00
element:// support + basic peeking + fix join via server
This commit is contained in:
parent
43ac66feb3
commit
bd9da8eaa6
20 changed files with 488 additions and 55 deletions
matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx
matrix-sdk-android/src/main/java/org/matrix/android/sdk
api/session
internal/session/room
vector/src/main
|
@ -47,6 +47,7 @@ import org.matrix.android.sdk.api.util.toOptional
|
||||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||||
import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
|
import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||||
|
|
||||||
class RxSession(private val session: Session) {
|
class RxSession(private val session: Session) {
|
||||||
|
|
||||||
|
@ -139,7 +140,7 @@ class RxSession(private val session: Session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRoomIdByAlias(roomAlias: String,
|
fun getRoomIdByAlias(roomAlias: String,
|
||||||
searchOnServer: Boolean): Single<Optional<String>> = singleBuilder {
|
searchOnServer: Boolean): Single<Optional<RoomAliasDescription>> = singleBuilder {
|
||||||
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
|
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ interface PermalinkService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val MATRIX_TO_URL_BASE = "https://matrix.to/#/"
|
const val MATRIX_TO_URL_BASE = "https://matrix.to/#/"
|
||||||
|
const val MATRIX_TO_CUSTOM_SCHEME_URL_BASE = "element://"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,12 +18,15 @@ package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
import org.matrix.android.sdk.api.util.Cancelable
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.PeekResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to get rooms. It's implemented at the session level.
|
* This interface defines methods to get rooms. It's implemented at the session level.
|
||||||
|
@ -120,7 +123,7 @@ interface RoomService {
|
||||||
*/
|
*/
|
||||||
fun getRoomIdByAlias(roomAlias: String,
|
fun getRoomIdByAlias(roomAlias: String,
|
||||||
searchOnServer: Boolean,
|
searchOnServer: Boolean,
|
||||||
callback: MatrixCallback<Optional<String>>): Cancelable
|
callback: MatrixCallback<Optional<RoomAliasDescription>>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a room alias
|
* Delete a room alias
|
||||||
|
@ -163,4 +166,13 @@ interface RoomService {
|
||||||
* @return a LiveData of the optional found room member
|
* @return a LiveData of the optional found room member
|
||||||
*/
|
*/
|
||||||
fun getRoomMemberLive(userId: String, roomId: String): LiveData<Optional<RoomMemberSummary>>
|
fun getRoomMemberLive(userId: String, roomId: String): LiveData<Optional<RoomMemberSummary>>
|
||||||
|
|
||||||
|
fun getRoomState(roomId: String, callback: MatrixCallback<List<Event>>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this if you want to get information from a room that you are not yet in (or invited)
|
||||||
|
* It might be possible to get some information on this room if it is public or if guest access is allowed
|
||||||
|
* This call will try to gather some information on this room, but it could fail and get nothing more
|
||||||
|
*/
|
||||||
|
fun peekRoom(roomIdOrAlias: String, callback: MatrixCallback<PeekResult>)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.Transformations
|
import androidx.lifecycle.Transformations
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
import org.matrix.android.sdk.api.session.room.RoomService
|
import org.matrix.android.sdk.api.session.room.RoomService
|
||||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||||
|
@ -35,10 +36,14 @@ import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFie
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
|
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
|
||||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
|
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.joining.JoinRoomTask
|
import org.matrix.android.sdk.internal.session.room.membership.joining.JoinRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.PeekResult
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.PeekRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.ResolveRoomStateTask
|
||||||
import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask
|
import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask
|
||||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||||
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateBreadcrumbsTask
|
import org.matrix.android.sdk.internal.session.user.accountdata.UpdateBreadcrumbsTask
|
||||||
|
@ -55,6 +60,8 @@ internal class DefaultRoomService @Inject constructor(
|
||||||
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
||||||
private val roomIdByAliasTask: GetRoomIdByAliasTask,
|
private val roomIdByAliasTask: GetRoomIdByAliasTask,
|
||||||
private val deleteRoomAliasTask: DeleteRoomAliasTask,
|
private val deleteRoomAliasTask: DeleteRoomAliasTask,
|
||||||
|
private val resolveRoomStateTask: ResolveRoomStateTask,
|
||||||
|
private val peekRoomTask: PeekRoomTask,
|
||||||
private val roomGetter: RoomGetter,
|
private val roomGetter: RoomGetter,
|
||||||
private val roomSummaryDataSource: RoomSummaryDataSource,
|
private val roomSummaryDataSource: RoomSummaryDataSource,
|
||||||
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource,
|
||||||
|
@ -119,7 +126,7 @@ internal class DefaultRoomService @Inject constructor(
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRoomIdByAlias(roomAlias: String, searchOnServer: Boolean, callback: MatrixCallback<Optional<String>>): Cancelable {
|
override fun getRoomIdByAlias(roomAlias: String, searchOnServer: Boolean, callback: MatrixCallback<Optional<RoomAliasDescription>>): Cancelable {
|
||||||
return roomIdByAliasTask
|
return roomIdByAliasTask
|
||||||
.configureWith(GetRoomIdByAliasTask.Params(roomAlias, searchOnServer)) {
|
.configureWith(GetRoomIdByAliasTask.Params(roomAlias, searchOnServer)) {
|
||||||
this.callback = callback
|
this.callback = callback
|
||||||
|
@ -154,4 +161,20 @@ internal class DefaultRoomService @Inject constructor(
|
||||||
results.firstOrNull().toOptional()
|
results.firstOrNull().toOptional()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getRoomState(roomId: String, callback: MatrixCallback<List<Event>>) {
|
||||||
|
resolveRoomStateTask
|
||||||
|
.configureWith(ResolveRoomStateTask.Params(roomId)) {
|
||||||
|
this.callback = callback
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun peekRoom(roomIdOrAlias: String, callback: MatrixCallback<PeekResult>) {
|
||||||
|
peekRoomTask
|
||||||
|
.configureWith(PeekRoomTask.Params(roomIdOrAlias)) {
|
||||||
|
this.callback = callback
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,4 +354,7 @@ internal interface RoomAPI {
|
||||||
fun deleteTag(@Path("userId") userId: String,
|
fun deleteTag(@Path("userId") userId: String,
|
||||||
@Path("roomId") roomId: String,
|
@Path("roomId") roomId: String,
|
||||||
@Path("tag") tag: String): Call<Unit>
|
@Path("tag") tag: String): Call<Unit>
|
||||||
|
|
||||||
|
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/state")
|
||||||
|
fun getRoomState(@Path("roomId") roomId: String) : Call<List<Event>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,10 @@ import org.matrix.android.sdk.internal.session.room.membership.leaving.DefaultLe
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.leaving.LeaveRoomTask
|
import org.matrix.android.sdk.internal.session.room.membership.leaving.LeaveRoomTask
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.threepid.DefaultInviteThreePidTask
|
import org.matrix.android.sdk.internal.session.room.membership.threepid.DefaultInviteThreePidTask
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.threepid.InviteThreePidTask
|
import org.matrix.android.sdk.internal.session.room.membership.threepid.InviteThreePidTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.DefaultPeekRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.DefaultResolveRoomStateTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.PeekRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.ResolveRoomStateTask
|
||||||
import org.matrix.android.sdk.internal.session.room.read.DefaultMarkAllRoomsReadTask
|
import org.matrix.android.sdk.internal.session.room.read.DefaultMarkAllRoomsReadTask
|
||||||
import org.matrix.android.sdk.internal.session.room.read.DefaultSetReadMarkersTask
|
import org.matrix.android.sdk.internal.session.room.read.DefaultSetReadMarkersTask
|
||||||
import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask
|
import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask
|
||||||
|
@ -223,4 +227,10 @@ internal abstract class RoomModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindDeleteTagFromRoomTask(task: DefaultDeleteTagFromRoomTask): DeleteTagFromRoomTask
|
abstract fun bindDeleteTagFromRoomTask(task: DefaultDeleteTagFromRoomTask): DeleteTagFromRoomTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindResolveRoomStateTask(task: DefaultResolveRoomStateTask): ResolveRoomStateTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindPeekRoomTask(task: DefaultPeekRoomTask): PeekRoomTask
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.matrix.android.sdk.internal.session.directory.DirectoryAPI
|
||||||
import org.matrix.android.sdk.internal.task.Task
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface GetRoomIdByAliasTask : Task<GetRoomIdByAliasTask.Params, Optional<String>> {
|
internal interface GetRoomIdByAliasTask : Task<GetRoomIdByAliasTask.Params, Optional<RoomAliasDescription>> {
|
||||||
data class Params(
|
data class Params(
|
||||||
val roomAlias: String,
|
val roomAlias: String,
|
||||||
val searchOnServer: Boolean
|
val searchOnServer: Boolean
|
||||||
|
@ -42,21 +42,21 @@ internal class DefaultGetRoomIdByAliasTask @Inject constructor(
|
||||||
private val eventBus: EventBus
|
private val eventBus: EventBus
|
||||||
) : GetRoomIdByAliasTask {
|
) : GetRoomIdByAliasTask {
|
||||||
|
|
||||||
override suspend fun execute(params: GetRoomIdByAliasTask.Params): Optional<String> {
|
override suspend fun execute(params: GetRoomIdByAliasTask.Params): Optional<RoomAliasDescription> {
|
||||||
var roomId = Realm.getInstance(monarchy.realmConfiguration).use {
|
var roomId = Realm.getInstance(monarchy.realmConfiguration).use {
|
||||||
RoomSummaryEntity.findByAlias(it, params.roomAlias)?.roomId
|
RoomSummaryEntity.findByAlias(it, params.roomAlias)?.roomId
|
||||||
}
|
}
|
||||||
return if (roomId != null) {
|
return if (roomId != null) {
|
||||||
Optional.from(roomId)
|
Optional.from(RoomAliasDescription(roomId))
|
||||||
} else if (!params.searchOnServer) {
|
} else if (!params.searchOnServer) {
|
||||||
Optional.from<String>(null)
|
Optional.from<RoomAliasDescription>(null)
|
||||||
} else {
|
} else {
|
||||||
roomId = tryOrNull("## Failed to get roomId from alias") {
|
val description = tryOrNull("## Failed to get roomId from alias") {
|
||||||
executeRequest<RoomAliasDescription>(eventBus) {
|
executeRequest<RoomAliasDescription>(eventBus) {
|
||||||
apiCall = directoryAPI.getRoomIdByAlias(params.roomAlias)
|
apiCall = directoryAPI.getRoomIdByAlias(params.roomAlias)
|
||||||
}
|
}
|
||||||
}?.roomId
|
}
|
||||||
Optional.from(roomId)
|
Optional.from(description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
internal data class RoomAliasDescription(
|
data class RoomAliasDescription(
|
||||||
/**
|
/**
|
||||||
* The room ID for this alias.
|
* The room ID for this alias.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 org.matrix.android.sdk.internal.session.room.peeking
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.MatrixPatterns
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsFilter
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.directory.GetRoomDirectoryVisibilityTask
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
sealed class PeekResult {
|
||||||
|
data class Success(
|
||||||
|
val roomId: String,
|
||||||
|
val alias: String?,
|
||||||
|
val name: String?,
|
||||||
|
val topic: String?,
|
||||||
|
val avatarUrl: String?,
|
||||||
|
val numJoinedMembers: Int?,
|
||||||
|
val viaServers: List<String>
|
||||||
|
) : PeekResult()
|
||||||
|
|
||||||
|
data class PeekingNotAllowed(
|
||||||
|
val roomId: String,
|
||||||
|
val alias: String?,
|
||||||
|
val viaServers: List<String>
|
||||||
|
) : PeekResult()
|
||||||
|
|
||||||
|
object UnknownAlias : PeekResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal interface PeekRoomTask : Task<PeekRoomTask.Params, PeekResult> {
|
||||||
|
data class Params(
|
||||||
|
val roomIdOrAlias: String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultPeekRoomTask @Inject constructor(
|
||||||
|
private val getRoomIdByAliasTask: GetRoomIdByAliasTask,
|
||||||
|
private val getRoomDirectoryVisibilityTask: GetRoomDirectoryVisibilityTask,
|
||||||
|
private val getPublicRoomTask: GetPublicRoomTask,
|
||||||
|
private val resolveRoomStateTask: ResolveRoomStateTask
|
||||||
|
) : PeekRoomTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: PeekRoomTask.Params): PeekResult {
|
||||||
|
val roomId: String?
|
||||||
|
val serverList: List<String>
|
||||||
|
val isAlias: Boolean
|
||||||
|
if (MatrixPatterns.isRoomAlias(params.roomIdOrAlias)) {
|
||||||
|
isAlias = true
|
||||||
|
// get alias description
|
||||||
|
val aliasDescription = getRoomIdByAliasTask
|
||||||
|
.execute(GetRoomIdByAliasTask.Params(params.roomIdOrAlias, true))
|
||||||
|
.getOrNull()
|
||||||
|
?: return PeekResult.UnknownAlias
|
||||||
|
|
||||||
|
roomId = aliasDescription.roomId
|
||||||
|
serverList = aliasDescription.servers
|
||||||
|
} else {
|
||||||
|
isAlias = false
|
||||||
|
roomId = params.roomIdOrAlias
|
||||||
|
serverList = emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it a public room?
|
||||||
|
val publicRepoResult = when (getRoomDirectoryVisibilityTask.execute(GetRoomDirectoryVisibilityTask.Params(roomId))) {
|
||||||
|
RoomDirectoryVisibility.PRIVATE -> {
|
||||||
|
// We cannot resolve this room :/
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RoomDirectoryVisibility.PUBLIC -> {
|
||||||
|
// Try to find it in directory
|
||||||
|
val filter = if (isAlias) PublicRoomsFilter(searchTerm = params.roomIdOrAlias.substring(1))
|
||||||
|
else null
|
||||||
|
|
||||||
|
getPublicRoomTask.execute(GetPublicRoomTask.Params(
|
||||||
|
server = serverList.firstOrNull(),
|
||||||
|
publicRoomsParams = PublicRoomsParams(
|
||||||
|
filter = filter,
|
||||||
|
limit = 20.takeIf { filter != null } ?: 100
|
||||||
|
)
|
||||||
|
)).chunk?.firstOrNull { it.roomId == roomId }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publicRepoResult != null) {
|
||||||
|
return PeekResult.Success(
|
||||||
|
roomId = roomId,
|
||||||
|
alias = publicRepoResult.getPrimaryAlias() ?: params.roomIdOrAlias.takeIf { isAlias },
|
||||||
|
avatarUrl = publicRepoResult.avatarUrl,
|
||||||
|
name = publicRepoResult.name,
|
||||||
|
topic = publicRepoResult.topic,
|
||||||
|
numJoinedMembers = publicRepoResult.numJoinedMembers,
|
||||||
|
viaServers = serverList
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mm... try to peek state ? maybe the room is not public but yet allow guest to get events?
|
||||||
|
// this could be slow
|
||||||
|
try {
|
||||||
|
val stateEvents = resolveRoomStateTask
|
||||||
|
.execute(ResolveRoomStateTask.Params(roomId))
|
||||||
|
val name = stateEvents.lastOrNull {
|
||||||
|
it.type == EventType.STATE_ROOM_NAME
|
||||||
|
&& it.stateKey == ""
|
||||||
|
}?.let { it.content?.toModel<RoomNameContent>()?.name }
|
||||||
|
|
||||||
|
val topic = stateEvents.lastOrNull {
|
||||||
|
it.type == EventType.STATE_ROOM_TOPIC
|
||||||
|
&& it.stateKey == ""
|
||||||
|
}?.let { it.content?.toModel<RoomTopicContent>()?.topic }
|
||||||
|
|
||||||
|
val avatarUrl = stateEvents.lastOrNull {
|
||||||
|
it.type == EventType.STATE_ROOM_AVATAR
|
||||||
|
}?.let { it.content?.toModel<RoomAvatarContent>()?.avatarUrl }
|
||||||
|
|
||||||
|
val alias = stateEvents.lastOrNull {
|
||||||
|
it.type == EventType.STATE_ROOM_CANONICAL_ALIAS
|
||||||
|
}?.let {
|
||||||
|
it.content?.toModel<RoomCanonicalAliasContent>()?.canonicalAlias
|
||||||
|
?: it.content?.toModel<RoomCanonicalAliasContent>()?.alternativeAliases?.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
// not sure if it's the right way to do that :/
|
||||||
|
val memberCount = stateEvents.filter {
|
||||||
|
it.type == EventType.STATE_ROOM_MEMBER
|
||||||
|
&& it.stateKey?.isNotEmpty() == true
|
||||||
|
}.distinctBy { it.stateKey }
|
||||||
|
.count()
|
||||||
|
|
||||||
|
return PeekResult.Success(
|
||||||
|
roomId = roomId,
|
||||||
|
alias = alias,
|
||||||
|
avatarUrl = avatarUrl,
|
||||||
|
name = name,
|
||||||
|
topic = topic,
|
||||||
|
numJoinedMembers = memberCount,
|
||||||
|
viaServers = serverList
|
||||||
|
)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
// Would be M_FORBIDDEN if cannot peek :/
|
||||||
|
// User XXX not in room !XXX, and room previews are disabled
|
||||||
|
return PeekResult.PeekingNotAllowed(
|
||||||
|
roomId = roomId,
|
||||||
|
alias = params.roomIdOrAlias.takeIf { isAlias },
|
||||||
|
viaServers = serverList
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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 org.matrix.android.sdk.internal.session.room.peeking
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.session.room.RoomAPI
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface ResolveRoomStateTask : Task<ResolveRoomStateTask.Params, List<Event>> {
|
||||||
|
data class Params(
|
||||||
|
val roomId: String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultResolveRoomStateTask @Inject constructor(
|
||||||
|
private val roomAPI: RoomAPI,
|
||||||
|
private val eventBus: EventBus
|
||||||
|
) : ResolveRoomStateTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: ResolveRoomStateTask.Params): List<Event> {
|
||||||
|
return executeRequest(eventBus) {
|
||||||
|
apiCall = roomAPI.getRoomState(params.roomId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -199,6 +199,11 @@
|
||||||
<data android:scheme="http" />
|
<data android:scheme="http" />
|
||||||
<data android:scheme="https" />
|
<data android:scheme="https" />
|
||||||
<data android:host="matrix.to" />
|
<data android:host="matrix.to" />
|
||||||
|
<data android:scheme="element"
|
||||||
|
android:host="user"/>
|
||||||
|
<data android:scheme="element"
|
||||||
|
android:host="room"/>
|
||||||
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
|
|
@ -126,9 +126,9 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||||
.observe()
|
.observe()
|
||||||
.subscribe { sharedAction ->
|
.subscribe { sharedAction ->
|
||||||
when (sharedAction) {
|
when (sharedAction) {
|
||||||
is HomeActivitySharedAction.OpenDrawer -> drawerLayout.openDrawer(GravityCompat.START)
|
is HomeActivitySharedAction.OpenDrawer -> drawerLayout.openDrawer(GravityCompat.START)
|
||||||
is HomeActivitySharedAction.CloseDrawer -> drawerLayout.closeDrawer(GravityCompat.START)
|
is HomeActivitySharedAction.CloseDrawer -> drawerLayout.closeDrawer(GravityCompat.START)
|
||||||
is HomeActivitySharedAction.OpenGroup -> {
|
is HomeActivitySharedAction.OpenGroup -> {
|
||||||
drawerLayout.closeDrawer(GravityCompat.START)
|
drawerLayout.closeDrawer(GravityCompat.START)
|
||||||
replaceFragment(R.id.homeDetailFragmentContainer, HomeDetailFragment::class.java, allowStateLoss = true)
|
replaceFragment(R.id.homeDetailFragmentContainer, HomeDetailFragment::class.java, allowStateLoss = true)
|
||||||
}
|
}
|
||||||
|
@ -145,9 +145,9 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||||
homeActivityViewModel.observeViewEvents {
|
homeActivityViewModel.observeViewEvents {
|
||||||
when (it) {
|
when (it) {
|
||||||
is HomeActivityViewEvents.AskPasswordToInitCrossSigning -> handleAskPasswordToInitCrossSigning(it)
|
is HomeActivityViewEvents.AskPasswordToInitCrossSigning -> handleAskPasswordToInitCrossSigning(it)
|
||||||
is HomeActivityViewEvents.OnNewSession -> handleOnNewSession(it)
|
is HomeActivityViewEvents.OnNewSession -> handleOnNewSession(it)
|
||||||
HomeActivityViewEvents.PromptToEnableSessionPush -> handlePromptToEnablePush()
|
HomeActivityViewEvents.PromptToEnableSessionPush -> handlePromptToEnablePush()
|
||||||
is HomeActivityViewEvents.OnCrossSignedInvalidated -> handleCrossSigningInvalidated(it)
|
is HomeActivityViewEvents.OnCrossSignedInvalidated -> handleCrossSigningInvalidated(it)
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
homeActivityViewModel.subscribe(this) { renderState(it) }
|
homeActivityViewModel.subscribe(this) { renderState(it) }
|
||||||
|
@ -162,9 +162,27 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||||
|
|
||||||
private fun handleIntent(intent: Intent?) {
|
private fun handleIntent(intent: Intent?) {
|
||||||
intent?.dataString?.let { deepLink ->
|
intent?.dataString?.let { deepLink ->
|
||||||
if (!deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE)) return@let
|
val resolvedLink = if (deepLink.startsWith(PermalinkService.MATRIX_TO_URL_BASE)) {
|
||||||
|
deepLink
|
||||||
|
} else if (deepLink.startsWith(PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE)) {
|
||||||
|
// This is a bit hugly, but for now just convert to matrix.to link for compatibility
|
||||||
|
val service = activeSessionHolder.getSafeActiveSession()?.permalinkService()
|
||||||
|
val roomLinkPrefix = "${PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE}room/"
|
||||||
|
val userPrefix = "${PermalinkService.MATRIX_TO_CUSTOM_SCHEME_URL_BASE}user/"
|
||||||
|
when {
|
||||||
|
deepLink.startsWith(userPrefix) -> {
|
||||||
|
val userId = deepLink.substring(userPrefix.length)
|
||||||
|
service?.createPermalink(userId)
|
||||||
|
}
|
||||||
|
deepLink.startsWith(roomLinkPrefix) -> {
|
||||||
|
val param = deepLink.substring(roomLinkPrefix.length)
|
||||||
|
service?.createRoomPermalink(param)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
} else null
|
||||||
|
|
||||||
permalinkHandler.launch(this, deepLink,
|
permalinkHandler.launch(this, resolvedLink,
|
||||||
navigationInterceptor = this,
|
navigationInterceptor = this,
|
||||||
buildTask = true)
|
buildTask = true)
|
||||||
// .delay(500, TimeUnit.MILLISECONDS)
|
// .delay(500, TimeUnit.MILLISECONDS)
|
||||||
|
@ -180,7 +198,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||||
|
|
||||||
private fun renderState(state: HomeActivityViewState) {
|
private fun renderState(state: HomeActivityViewState) {
|
||||||
when (val status = state.initialSyncProgressServiceStatus) {
|
when (val status = state.initialSyncProgressServiceStatus) {
|
||||||
is InitialSyncProgressService.Status.Idle -> {
|
is InitialSyncProgressService.Status.Idle -> {
|
||||||
waiting_view.isVisible = false
|
waiting_view.isVisible = false
|
||||||
}
|
}
|
||||||
is InitialSyncProgressService.Status.Progressing -> {
|
is InitialSyncProgressService.Status.Progressing -> {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.matrix.android.sdk.api.session.permalinks.PermalinkData
|
||||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkParser
|
import org.matrix.android.sdk.api.session.permalinks.PermalinkParser
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||||
buildTask: Boolean
|
buildTask: Boolean
|
||||||
): Single<Boolean> {
|
): Single<Boolean> {
|
||||||
return when (permalinkData) {
|
return when (permalinkData) {
|
||||||
is PermalinkData.RoomLink -> {
|
is PermalinkData.RoomLink -> {
|
||||||
permalinkData.getRoomId()
|
permalinkData.getRoomId()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.map {
|
.map {
|
||||||
|
@ -92,11 +93,11 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PermalinkData.GroupLink -> {
|
is PermalinkData.GroupLink -> {
|
||||||
navigator.openGroupDetail(permalinkData.groupId, context, buildTask)
|
navigator.openGroupDetail(permalinkData.groupId, context, buildTask)
|
||||||
Single.just(true)
|
Single.just(true)
|
||||||
}
|
}
|
||||||
is PermalinkData.UserLink -> {
|
is PermalinkData.UserLink -> {
|
||||||
if (navigationInterceptor?.navToMemberProfile(permalinkData.userId, rawLink) != true) {
|
if (navigationInterceptor?.navToMemberProfile(permalinkData.userId, rawLink) != true) {
|
||||||
navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask)
|
navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask)
|
||||||
}
|
}
|
||||||
|
@ -111,7 +112,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||||
private fun PermalinkData.RoomLink.getRoomId(): Single<Optional<String>> {
|
private fun PermalinkData.RoomLink.getRoomId(): Single<Optional<String>> {
|
||||||
val session = activeSessionHolder.getSafeActiveSession()
|
val session = activeSessionHolder.getSafeActiveSession()
|
||||||
return if (isRoomAlias && session != null) {
|
return if (isRoomAlias && session != null) {
|
||||||
session.rx().getRoomIdByAlias(roomIdOrAlias, true).subscribeOn(Schedulers.io())
|
session.rx().getRoomIdByAlias(roomIdOrAlias, true).map { it.getOrNull()?.roomId.toOptional() }.subscribeOn(Schedulers.io())
|
||||||
} else {
|
} else {
|
||||||
Single.just(Optional.from(roomIdOrAlias))
|
Single.just(Optional.from(roomIdOrAlias))
|
||||||
}
|
}
|
||||||
|
@ -149,16 +150,28 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||||
navigator.openRoom(context, roomId, eventId, buildTask)
|
navigator.openRoom(context, roomId, eventId, buildTask)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val roomPreviewData = RoomPreviewData(
|
if (roomSummary == null) {
|
||||||
roomId = roomId,
|
// we don't know this room, try to peek
|
||||||
eventId = eventId,
|
val roomPreviewData = RoomPreviewData(
|
||||||
roomAlias = roomAlias ?: roomSummary?.canonicalAlias,
|
roomId = roomId,
|
||||||
roomName = roomSummary?.displayName,
|
roomAlias = roomAlias,
|
||||||
avatarUrl = roomSummary?.avatarUrl,
|
peekFromServer = true,
|
||||||
buildTask = buildTask,
|
buildTask = buildTask,
|
||||||
homeServers = permalinkData.viaParameters
|
homeServers = permalinkData.viaParameters
|
||||||
)
|
)
|
||||||
navigator.openRoomPreview(context, roomPreviewData)
|
navigator.openRoomPreview(context, roomPreviewData)
|
||||||
|
} else {
|
||||||
|
val roomPreviewData = RoomPreviewData(
|
||||||
|
roomId = roomId,
|
||||||
|
eventId = eventId,
|
||||||
|
roomAlias = roomAlias ?: roomSummary.canonicalAlias,
|
||||||
|
roomName = roomSummary.displayName,
|
||||||
|
avatarUrl = roomSummary.avatarUrl,
|
||||||
|
buildTask = buildTask,
|
||||||
|
homeServers = permalinkData.viaParameters
|
||||||
|
)
|
||||||
|
navigator.openRoomPreview(context, roomPreviewData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ class PopupAlertManager @Inject constructor(private val avatarRenderer: Lazy<Ava
|
||||||
|
|
||||||
private fun displayNextIfPossible() {
|
private fun displayNextIfPossible() {
|
||||||
val currentActivity = weakCurrentActivity?.get()
|
val currentActivity = weakCurrentActivity?.get()
|
||||||
if (Alerter.isShowing || currentActivity == null) {
|
if (Alerter.isShowing || currentActivity == null || currentActivity.isDestroyed) {
|
||||||
// will retry later
|
// will retry later
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ data class RoomPreviewData(
|
||||||
val worldReadable: Boolean = false,
|
val worldReadable: Boolean = false,
|
||||||
val avatarUrl: String? = null,
|
val avatarUrl: String? = null,
|
||||||
val homeServers: List<String> = emptyList(),
|
val homeServers: List<String> = emptyList(),
|
||||||
|
val peekFromServer: Boolean = false,
|
||||||
val buildTask: Boolean = false
|
val buildTask: Boolean = false
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
val matrixItem: MatrixItem
|
val matrixItem: MatrixItem
|
||||||
|
|
|
@ -20,6 +20,8 @@ import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.transition.TransitionManager
|
import androidx.transition.TransitionManager
|
||||||
|
import com.airbnb.mvrx.Loading
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.args
|
import com.airbnb.mvrx.args
|
||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
|
@ -30,6 +32,7 @@ import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.roomdirectory.JoinState
|
import im.vector.app.features.roomdirectory.JoinState
|
||||||
import kotlinx.android.synthetic.main.fragment_room_preview_no_preview.*
|
import kotlinx.android.synthetic.main.fragment_room_preview_no_preview.*
|
||||||
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,22 +51,6 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
setupToolbar(roomPreviewNoPreviewToolbar)
|
setupToolbar(roomPreviewNoPreviewToolbar)
|
||||||
val titleText = roomPreviewData.roomName ?: roomPreviewData.roomAlias ?: roomPreviewData.roomId
|
|
||||||
|
|
||||||
// Toolbar
|
|
||||||
avatarRenderer.render(roomPreviewData.matrixItem, roomPreviewNoPreviewToolbarAvatar)
|
|
||||||
roomPreviewNoPreviewToolbarTitle.text = titleText
|
|
||||||
|
|
||||||
// Screen
|
|
||||||
avatarRenderer.render(roomPreviewData.matrixItem, roomPreviewNoPreviewAvatar)
|
|
||||||
roomPreviewNoPreviewName.text = titleText
|
|
||||||
roomPreviewNoPreviewTopic.setTextOrHide(roomPreviewData.topic)
|
|
||||||
|
|
||||||
if (roomPreviewData.worldReadable) {
|
|
||||||
roomPreviewNoPreviewLabel.setText(R.string.room_preview_world_readable_room_not_supported_yet)
|
|
||||||
} else {
|
|
||||||
roomPreviewNoPreviewLabel.setText(R.string.room_preview_no_preview)
|
|
||||||
}
|
|
||||||
|
|
||||||
roomPreviewNoPreviewJoin.callback = object : ButtonStateView.Callback {
|
roomPreviewNoPreviewJoin.callback = object : ButtonStateView.Callback {
|
||||||
override fun onButtonClicked() {
|
override fun onButtonClicked() {
|
||||||
|
@ -100,7 +87,62 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
|
||||||
// Quit this screen
|
// Quit this screen
|
||||||
requireActivity().finish()
|
requireActivity().finish()
|
||||||
// Open room
|
// Open room
|
||||||
navigator.openRoom(requireActivity(), roomPreviewData.roomId, roomPreviewData.eventId, roomPreviewData.buildTask)
|
navigator.openRoom(requireActivity(), state.roomId, roomPreviewData.eventId, roomPreviewData.buildTask)
|
||||||
|
}
|
||||||
|
|
||||||
|
val bestName = state.roomName ?: state.roomAlias ?: state.roomId
|
||||||
|
when (state.peekingState) {
|
||||||
|
is Loading -> {
|
||||||
|
roomPreviewPeekingProgress.isVisible = true
|
||||||
|
roomPreviewNoPreviewJoin.isVisible = false
|
||||||
|
}
|
||||||
|
is Success -> {
|
||||||
|
roomPreviewPeekingProgress.isVisible = false
|
||||||
|
when (state.peekingState.invoke()) {
|
||||||
|
PeekingState.FOUND -> {
|
||||||
|
// show join buttons
|
||||||
|
roomPreviewNoPreviewJoin.isVisible = true
|
||||||
|
renderState(bestName, state.matrixItem(), state.roomTopic)
|
||||||
|
}
|
||||||
|
PeekingState.NO_ACCESS -> {
|
||||||
|
roomPreviewNoPreviewJoin.isVisible = true
|
||||||
|
roomPreviewNoPreviewLabel.isVisible = true
|
||||||
|
roomPreviewNoPreviewLabel.setText(R.string.room_preview_no_preview_join)
|
||||||
|
renderState(bestName, state.matrixItem().takeIf { state.roomAlias != null }, state.roomTopic)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
roomPreviewNoPreviewJoin.isVisible = false
|
||||||
|
roomPreviewNoPreviewLabel.isVisible = true
|
||||||
|
roomPreviewNoPreviewLabel.setText(R.string.room_preview_not_found)
|
||||||
|
renderState(bestName, null, state.roomTopic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// Render with initial state, no peeking
|
||||||
|
roomPreviewPeekingProgress.isVisible = false
|
||||||
|
roomPreviewNoPreviewJoin.isVisible = true
|
||||||
|
renderState(bestName, state.matrixItem(), state.roomTopic)
|
||||||
|
roomPreviewNoPreviewLabel.isVisible = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renderState(roomName: String, matrixItem: MatrixItem?, topic: String?) {
|
||||||
|
// Toolbar
|
||||||
|
if (matrixItem != null) {
|
||||||
|
roomPreviewNoPreviewToolbarAvatar.isVisible = true
|
||||||
|
roomPreviewNoPreviewAvatar.isVisible = true
|
||||||
|
avatarRenderer.render(matrixItem, roomPreviewNoPreviewToolbarAvatar)
|
||||||
|
avatarRenderer.render(matrixItem, roomPreviewNoPreviewAvatar)
|
||||||
|
} else {
|
||||||
|
roomPreviewNoPreviewToolbarAvatar.isVisible = false
|
||||||
|
roomPreviewNoPreviewAvatar.isVisible = false
|
||||||
|
}
|
||||||
|
roomPreviewNoPreviewToolbarTitle.text = roomName
|
||||||
|
|
||||||
|
// Screen
|
||||||
|
roomPreviewNoPreviewName.text = roomName
|
||||||
|
roomPreviewNoPreviewTopic.setTextOrHide(topic)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,11 @@
|
||||||
|
|
||||||
package im.vector.app.features.roomdirectory.roompreview
|
package im.vector.app.features.roomdirectory.roompreview
|
||||||
|
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
|
import com.airbnb.mvrx.Loading
|
||||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import com.squareup.inject.assisted.Assisted
|
import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
|
@ -25,12 +28,17 @@ import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.features.roomdirectory.JoinState
|
import im.vector.app.features.roomdirectory.JoinState
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
|
import org.matrix.android.sdk.internal.session.room.peeking.PeekResult
|
||||||
|
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
@ -56,6 +64,52 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted private val ini
|
||||||
// Observe joined room (from the sync)
|
// Observe joined room (from the sync)
|
||||||
observeRoomSummary()
|
observeRoomSummary()
|
||||||
observeMembershipChanges()
|
observeMembershipChanges()
|
||||||
|
|
||||||
|
if (initialState.shouldPeekFromServer) {
|
||||||
|
setState {
|
||||||
|
copy(peekingState = Loading())
|
||||||
|
}
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val peekResult = tryOrNull {
|
||||||
|
awaitCallback<PeekResult> {
|
||||||
|
session.peekRoom(initialState.roomAlias ?: initialState.roomId, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when (peekResult) {
|
||||||
|
is PeekResult.Success -> {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
roomId = peekResult.roomId,
|
||||||
|
avatarUrl = peekResult.avatarUrl,
|
||||||
|
roomAlias = peekResult.alias ?: initialState.roomAlias,
|
||||||
|
roomTopic = peekResult.topic,
|
||||||
|
homeServers = peekResult.viaServers,
|
||||||
|
peekingState = Success(PeekingState.FOUND)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is PeekResult.PeekingNotAllowed -> {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
roomId = peekResult.roomId,
|
||||||
|
roomAlias = peekResult.alias ?: initialState.roomAlias,
|
||||||
|
homeServers = peekResult.viaServers,
|
||||||
|
peekingState = Success(PeekingState.NO_ACCESS)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PeekResult.UnknownAlias,
|
||||||
|
null -> {
|
||||||
|
setState {
|
||||||
|
copy(
|
||||||
|
peekingState = Success(PeekingState.NOT_FOUND)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRoomSummary() {
|
private fun observeRoomSummary() {
|
||||||
|
@ -82,7 +136,7 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted private val ini
|
||||||
.subscribe {
|
.subscribe {
|
||||||
val changeMembership = it[initialState.roomId] ?: ChangeMembershipState.Unknown
|
val changeMembership = it[initialState.roomId] ?: ChangeMembershipState.Unknown
|
||||||
val joinState = when (changeMembership) {
|
val joinState = when (changeMembership) {
|
||||||
is ChangeMembershipState.Joining -> JoinState.JOINING
|
is ChangeMembershipState.Joining -> JoinState.JOINING
|
||||||
is ChangeMembershipState.FailedJoining -> JoinState.JOINING_ERROR
|
is ChangeMembershipState.FailedJoining -> JoinState.JOINING_ERROR
|
||||||
// Other cases are handled by room summary
|
// Other cases are handled by room summary
|
||||||
else -> null
|
else -> null
|
||||||
|
|
|
@ -16,13 +16,31 @@
|
||||||
|
|
||||||
package im.vector.app.features.roomdirectory.roompreview
|
package im.vector.app.features.roomdirectory.roompreview
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.Async
|
||||||
import com.airbnb.mvrx.MvRxState
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import im.vector.app.features.roomdirectory.JoinState
|
import im.vector.app.features.roomdirectory.JoinState
|
||||||
|
import org.matrix.android.sdk.api.util.MatrixItem
|
||||||
|
|
||||||
|
enum class PeekingState {
|
||||||
|
UNKNOWN,
|
||||||
|
FOUND,
|
||||||
|
NOT_FOUND,
|
||||||
|
NO_ACCESS
|
||||||
|
}
|
||||||
|
|
||||||
data class RoomPreviewViewState(
|
data class RoomPreviewViewState(
|
||||||
|
|
||||||
|
val peekingState: Async<PeekingState> = Uninitialized,
|
||||||
// The room id
|
// The room id
|
||||||
val roomId: String = "",
|
val roomId: String = "",
|
||||||
val roomAlias: String? = null,
|
val roomAlias: String? = null,
|
||||||
|
|
||||||
|
val roomName: String? = null,
|
||||||
|
val roomTopic: String? = null,
|
||||||
|
val avatarUrl: String? = null,
|
||||||
|
|
||||||
|
val shouldPeekFromServer: Boolean = false,
|
||||||
/**
|
/**
|
||||||
* Can be empty when the server is the current user's home server.
|
* Can be empty when the server is the current user's home server.
|
||||||
*/
|
*/
|
||||||
|
@ -36,6 +54,14 @@ data class RoomPreviewViewState(
|
||||||
constructor(args: RoomPreviewData) : this(
|
constructor(args: RoomPreviewData) : this(
|
||||||
roomId = args.roomId,
|
roomId = args.roomId,
|
||||||
roomAlias = args.roomAlias,
|
roomAlias = args.roomAlias,
|
||||||
homeServers = args.homeServers
|
homeServers = args.homeServers,
|
||||||
|
roomName = args.roomName,
|
||||||
|
roomTopic = args.topic,
|
||||||
|
avatarUrl = args.avatarUrl,
|
||||||
|
shouldPeekFromServer = args.peekFromServer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun matrixItem() : MatrixItem {
|
||||||
|
return MatrixItem.RoomItem(roomId, roomName ?: roomAlias, avatarUrl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,14 @@
|
||||||
|
|
||||||
</androidx.appcompat.widget.Toolbar>
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/roomPreviewPeekingProgress"
|
||||||
|
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="14dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="?riotx_header_panel_background"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -71,7 +79,7 @@
|
||||||
android:id="@+id/roomPreviewNoPreviewAvatar"
|
android:id="@+id/roomPreviewNoPreviewAvatar"
|
||||||
android:layout_width="128dp"
|
android:layout_width="128dp"
|
||||||
android:layout_height="128dp"
|
android:layout_height="128dp"
|
||||||
android:layout_marginTop="123dp"
|
android:layout_marginTop="60dp"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
|
@ -1711,7 +1711,8 @@
|
||||||
|
|
||||||
<string name="room_preview_no_preview">"This room can't be previewed"</string>
|
<string name="room_preview_no_preview">"This room can't be previewed"</string>
|
||||||
<string name="room_preview_world_readable_room_not_supported_yet">"The preview of world-readable room is not supported yet in Element"</string>
|
<string name="room_preview_world_readable_room_not_supported_yet">"The preview of world-readable room is not supported yet in Element"</string>
|
||||||
|
<string name="room_preview_not_found">This room is not accessible at this time.\nTry again later, or ask a room admin to check if you have access.</string>
|
||||||
|
<string name="room_preview_no_preview_join">"This room can't be previewed. Do you want to join it?"</string>
|
||||||
<string name="fab_menu_create_room">"Rooms"</string>
|
<string name="fab_menu_create_room">"Rooms"</string>
|
||||||
<string name="fab_menu_create_chat">"Direct Messages"</string>
|
<string name="fab_menu_create_chat">"Direct Messages"</string>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue