mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-16 20:10:04 +03:00
Profile: Start fetching profile info from a user
This commit is contained in:
parent
ae1a24e948
commit
162f0949fa
16 changed files with 404 additions and 87 deletions
|
@ -26,7 +26,9 @@ 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.session.sync.SyncState
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
import im.vector.matrix.android.api.util.toOptional
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
|
@ -56,7 +58,8 @@ class RxSession(private val session: Session) {
|
|||
}
|
||||
|
||||
fun liveUser(userId: String): Observable<Optional<User>> {
|
||||
return session.getUserLive(userId).asObservable().distinctUntilChanged()
|
||||
return session.getUserLive(userId).asObservable()
|
||||
.startWith(session.getUser(userId).toOptional())
|
||||
}
|
||||
|
||||
fun liveUsers(): Observable<List<User>> {
|
||||
|
@ -91,6 +94,11 @@ class RxSession(private val session: Session) {
|
|||
searchOnServer: Boolean): Single<Optional<String>> = singleBuilder {
|
||||
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
|
||||
}
|
||||
|
||||
fun getProfileInfo(userId: String): Single<JsonDict> = singleBuilder {
|
||||
session.getProfile(userId, it)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun Session.rx(): RxSession {
|
||||
|
|
|
@ -28,6 +28,7 @@ import im.vector.matrix.android.api.session.crypto.CryptoService
|
|||
import im.vector.matrix.android.api.session.file.FileService
|
||||
import im.vector.matrix.android.api.session.group.GroupService
|
||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||
import im.vector.matrix.android.api.session.room.RoomService
|
||||
|
@ -51,6 +52,7 @@ interface Session :
|
|||
SignOutService,
|
||||
FilterService,
|
||||
FileService,
|
||||
ProfileService,
|
||||
PushRuleService,
|
||||
PushersService,
|
||||
InitialSyncProgressService,
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 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 im.vector.matrix.android.api.session.profile
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
|
||||
interface ProfileService {
|
||||
|
||||
companion object Constants {
|
||||
const val DISPLAY_NAME_KEY = "displayname"
|
||||
const val AVATAR_URL_KEY = "avatar_url"
|
||||
}
|
||||
|
||||
fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable
|
||||
|
||||
fun getAvatarUrl(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable
|
||||
|
||||
fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable
|
||||
|
||||
}
|
|
@ -34,6 +34,7 @@ import im.vector.matrix.android.api.session.crypto.CryptoService
|
|||
import im.vector.matrix.android.api.session.file.FileService
|
||||
import im.vector.matrix.android.api.session.group.GroupService
|
||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||
import im.vector.matrix.android.api.session.room.RoomService
|
||||
|
@ -76,6 +77,7 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
|||
private val cryptoService: Lazy<DefaultCryptoService>,
|
||||
private val fileService: Lazy<FileService>,
|
||||
private val secureStorageService: Lazy<SecureStorageService>,
|
||||
private val profileService: Lazy<ProfileService>,
|
||||
private val syncThreadProvider: Provider<SyncThread>,
|
||||
private val contentUrlResolver: ContentUrlResolver,
|
||||
private val syncTokenStore: SyncTokenStore,
|
||||
|
@ -97,7 +99,8 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
|
|||
FileService by fileService.get(),
|
||||
InitialSyncProgressService by initialSyncProgressService.get(),
|
||||
SecureStorageService by secureStorageService.get(),
|
||||
HomeServerCapabilitiesService by homeServerCapabilitiesService.get() {
|
||||
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
|
||||
ProfileService by profileService.get() {
|
||||
|
||||
private var isOpen = false
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.session.filter.FilterModule
|
|||
import im.vector.matrix.android.internal.session.group.GetGroupDataWorker
|
||||
import im.vector.matrix.android.internal.session.group.GroupModule
|
||||
import im.vector.matrix.android.internal.session.homeserver.HomeServerCapabilitiesModule
|
||||
import im.vector.matrix.android.internal.session.profile.ProfileModule
|
||||
import im.vector.matrix.android.internal.session.pushers.AddHttpPusherWorker
|
||||
import im.vector.matrix.android.internal.session.pushers.PushersModule
|
||||
import im.vector.matrix.android.internal.session.room.RoomModule
|
||||
|
@ -64,6 +65,7 @@ import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
|||
CryptoModule::class,
|
||||
PushersModule::class,
|
||||
AccountDataModule::class,
|
||||
ProfileModule::class,
|
||||
SessionAssistedInjectModule::class
|
||||
]
|
||||
)
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 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 im.vector.matrix.android.internal.session.profile
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.task.configureWith
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultProfileService @Inject constructor(private val taskExecutor: TaskExecutor,
|
||||
private val getProfileInfoTask: GetProfileInfoTask) : ProfileService {
|
||||
|
||||
override fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable {
|
||||
val params = GetProfileInfoTask.Params(userId)
|
||||
return getProfileInfoTask
|
||||
.configureWith(params) {
|
||||
this.callback = object : MatrixCallback<JsonDict> {
|
||||
override fun onSuccess(data: JsonDict) {
|
||||
val displayName = data[ProfileService.DISPLAY_NAME_KEY] as? String
|
||||
matrixCallback.onSuccess(Optional.from(displayName))
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
matrixCallback.onFailure(failure)
|
||||
}
|
||||
}
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun getAvatarUrl(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable {
|
||||
val params = GetProfileInfoTask.Params(userId)
|
||||
return getProfileInfoTask
|
||||
.configureWith(params) {
|
||||
this.callback = object : MatrixCallback<JsonDict> {
|
||||
override fun onSuccess(data: JsonDict) {
|
||||
val avatarUrl = data[ProfileService.AVATAR_URL_KEY] as? String
|
||||
matrixCallback.onSuccess(Optional.from(avatarUrl))
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
matrixCallback.onFailure(failure)
|
||||
}
|
||||
}
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable {
|
||||
val params = GetProfileInfoTask.Params(userId)
|
||||
return getProfileInfoTask
|
||||
.configureWith(params) {
|
||||
this.callback = matrixCallback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 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 im.vector.matrix.android.internal.session.profile
|
||||
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
import javax.inject.Inject
|
||||
|
||||
internal abstract class GetProfileInfoTask : Task<GetProfileInfoTask.Params, JsonDict> {
|
||||
data class Params(
|
||||
val userId: String
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultGetProfileInfoTask @Inject constructor(private val profileAPI: ProfileAPI) : GetProfileInfoTask() {
|
||||
|
||||
override suspend fun execute(params: Params): JsonDict {
|
||||
return executeRequest {
|
||||
apiCall = profileAPI.getProfile(params.userId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 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 im.vector.matrix.android.internal.session.profile
|
||||
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
|
||||
interface ProfileAPI {
|
||||
|
||||
/**
|
||||
* Get the combined profile information for this user. This API may be used to fetch the user's own profile information or other users; either locally or on remote homeservers. This API may return keys which are not limited to displayname or avatar_url.
|
||||
*
|
||||
* @param userId the user id to fetch profile info
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "profile/{userId}")
|
||||
fun getProfile(@Path("userId") roomId: String): Call<JsonDict>
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 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 im.vector.matrix.android.internal.session.profile
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import retrofit2.Retrofit
|
||||
|
||||
@Module
|
||||
internal abstract class ProfileModule {
|
||||
|
||||
@Module
|
||||
companion object {
|
||||
@Provides
|
||||
@JvmStatic
|
||||
@SessionScope
|
||||
fun providesProfileAPI(retrofit: Retrofit): ProfileAPI {
|
||||
return retrofit.create(ProfileAPI::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract fun bindProfileService(userService: DefaultProfileService): ProfileService
|
||||
|
||||
@Binds
|
||||
abstract fun bindGetProfileTask(getProfileInfoTask: DefaultGetProfileInfoTask): GetProfileInfoTask
|
||||
}
|
|
@ -25,7 +25,12 @@ import android.os.Build
|
|||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.text.Spannable
|
||||
import android.view.*
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.DrawableRes
|
||||
|
@ -45,7 +50,13 @@ import butterknife.BindView
|
|||
import com.airbnb.epoxy.EpoxyModel
|
||||
import com.airbnb.epoxy.EpoxyVisibilityTracker
|
||||
import com.airbnb.epoxy.OnModelBuildFinishedListener
|
||||
import com.airbnb.mvrx.*
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.args
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.github.piasy.biv.BigImageViewer
|
||||
import com.github.piasy.biv.loader.ImageLoader
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
@ -55,7 +66,13 @@ import im.vector.matrix.android.api.session.Session
|
|||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.message.*
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageInfoContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
||||
import im.vector.matrix.android.api.session.room.send.SendState
|
||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
|
@ -65,13 +82,31 @@ import im.vector.matrix.android.api.util.toMatrixItem
|
|||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.dialogs.withColoredButton
|
||||
import im.vector.riotx.core.epoxy.LayoutManagerStateRestorer
|
||||
import im.vector.riotx.core.extensions.*
|
||||
import im.vector.riotx.core.extensions.cleanup
|
||||
import im.vector.riotx.core.extensions.hideKeyboard
|
||||
import im.vector.riotx.core.extensions.observeEvent
|
||||
import im.vector.riotx.core.extensions.setTextOrHide
|
||||
import im.vector.riotx.core.extensions.showKeyboard
|
||||
import im.vector.riotx.core.files.addEntryToDownloadManager
|
||||
import im.vector.riotx.core.glide.GlideApp
|
||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||
import im.vector.riotx.core.ui.views.JumpToReadMarkerView
|
||||
import im.vector.riotx.core.ui.views.NotificationAreaView
|
||||
import im.vector.riotx.core.utils.*
|
||||
import im.vector.riotx.core.utils.Debouncer
|
||||
import im.vector.riotx.core.utils.KeyboardStateUtils
|
||||
import im.vector.riotx.core.utils.PERMISSIONS_FOR_WRITING_FILES
|
||||
import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_DOWNLOAD_FILE
|
||||
import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_INCOMING_URI
|
||||
import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_PICK_ATTACHMENT
|
||||
import im.vector.riotx.core.utils.TextUtils
|
||||
import im.vector.riotx.core.utils.allGranted
|
||||
import im.vector.riotx.core.utils.checkPermissions
|
||||
import im.vector.riotx.core.utils.copyToClipboard
|
||||
import im.vector.riotx.core.utils.createUIHandler
|
||||
import im.vector.riotx.core.utils.getColorFromUserId
|
||||
import im.vector.riotx.core.utils.openUrlInExternalBrowser
|
||||
import im.vector.riotx.core.utils.shareMedia
|
||||
import im.vector.riotx.core.utils.toast
|
||||
import im.vector.riotx.features.attachments.AttachmentTypeSelectorView
|
||||
import im.vector.riotx.features.attachments.AttachmentsHelper
|
||||
import im.vector.riotx.features.attachments.ContactAttachment
|
||||
|
@ -84,7 +119,12 @@ import im.vector.riotx.features.home.room.detail.timeline.action.EventSharedActi
|
|||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
|
||||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageSharedActionViewModel
|
||||
import im.vector.riotx.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.*
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.AbsMessageItem
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageFileItem
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageImageVideoItem
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageTextItem
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData
|
||||
import im.vector.riotx.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet
|
||||
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||
import im.vector.riotx.features.html.PillImageSpan
|
||||
|
@ -94,7 +134,7 @@ import im.vector.riotx.features.media.ImageMediaViewerActivity
|
|||
import im.vector.riotx.features.media.VideoContentRenderer
|
||||
import im.vector.riotx.features.media.VideoMediaViewerActivity
|
||||
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
||||
import im.vector.riotx.features.permalink.NavigateToRoomInterceptor
|
||||
import im.vector.riotx.features.permalink.NavigationInterceptor
|
||||
import im.vector.riotx.features.permalink.PermalinkHandler
|
||||
import im.vector.riotx.features.reactions.EmojiReactionPickerActivity
|
||||
import im.vector.riotx.features.settings.VectorPreferences
|
||||
|
@ -247,9 +287,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
roomDetailViewModel.selectSubscribe(RoomDetailViewState::sendMode) { mode ->
|
||||
when (mode) {
|
||||
is SendMode.REGULAR -> renderRegularMode(mode.text)
|
||||
is SendMode.EDIT -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_edit, R.string.edit, mode.text)
|
||||
is SendMode.QUOTE -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_quote, R.string.quote, mode.text)
|
||||
is SendMode.REPLY -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_reply, R.string.reply, mode.text)
|
||||
is SendMode.EDIT -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_edit, R.string.edit, mode.text)
|
||||
is SendMode.QUOTE -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_quote, R.string.quote, mode.text)
|
||||
is SendMode.REPLY -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_reply, R.string.reply, mode.text)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,9 +316,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
super.onActivityCreated(savedInstanceState)
|
||||
if (savedInstanceState == null) {
|
||||
when (val sharedData = roomDetailArgs.sharedData) {
|
||||
is SharedData.Text -> roomDetailViewModel.handle(RoomDetailAction.SendMessage(sharedData.text, false))
|
||||
is SharedData.Text -> roomDetailViewModel.handle(RoomDetailAction.SendMessage(sharedData.text, false))
|
||||
is SharedData.Attachments -> roomDetailViewModel.handle(RoomDetailAction.SendMedia(sharedData.attachmentData))
|
||||
null -> Timber.v("No share data to process")
|
||||
null -> Timber.v("No share data to process")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -415,7 +455,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
avatarRenderer.render(
|
||||
MatrixItem.UserItem(event.root.senderId
|
||||
?: "", event.getDisambiguatedDisplayName(), event.senderAvatar),
|
||||
?: "", event.getDisambiguatedDisplayName(), event.senderAvatar),
|
||||
composerLayout.composerRelatedMessageAvatar
|
||||
)
|
||||
|
||||
|
@ -504,7 +544,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
is MessageTextItem -> {
|
||||
return (model as AbsMessageItem).attributes.informationData.sendState == SendState.SYNCED
|
||||
}
|
||||
else -> false
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -519,9 +559,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
withState(roomDetailViewModel) {
|
||||
val showJumpToUnreadBanner = when (it.unreadState) {
|
||||
UnreadState.Unknown,
|
||||
UnreadState.HasNoUnread -> false
|
||||
UnreadState.HasNoUnread -> false
|
||||
is UnreadState.ReadMarkerNotLoaded -> true
|
||||
is UnreadState.HasUnread -> {
|
||||
is UnreadState.HasUnread -> {
|
||||
if (it.canShowJumpToReadMarker) {
|
||||
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
|
||||
val positionOfReadMarker = timelineEventController.getPositionOfReadMarker()
|
||||
|
@ -649,7 +689,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
navigator.openRoom(vectorBaseActivity, async())
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
is Fail -> {
|
||||
is Fail -> {
|
||||
vectorBaseActivity.hideWaitingView()
|
||||
vectorBaseActivity.toast(errorFormatter.toHumanReadable(async.error))
|
||||
}
|
||||
|
@ -658,23 +698,23 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
private fun renderSendMessageResult(sendMessageResult: SendMessageResult) {
|
||||
when (sendMessageResult) {
|
||||
is SendMessageResult.MessageSent -> {
|
||||
is SendMessageResult.MessageSent -> {
|
||||
updateComposerText("")
|
||||
}
|
||||
is SendMessageResult.SlashCommandHandled -> {
|
||||
is SendMessageResult.SlashCommandHandled -> {
|
||||
sendMessageResult.messageRes?.let { showSnackWithMessage(getString(it)) }
|
||||
updateComposerText("")
|
||||
}
|
||||
is SendMessageResult.SlashCommandError -> {
|
||||
is SendMessageResult.SlashCommandError -> {
|
||||
displayCommandError(getString(R.string.command_problem_with_parameters, sendMessageResult.command.command))
|
||||
}
|
||||
is SendMessageResult.SlashCommandUnknown -> {
|
||||
is SendMessageResult.SlashCommandUnknown -> {
|
||||
displayCommandError(getString(R.string.unrecognized_command, sendMessageResult.command))
|
||||
}
|
||||
is SendMessageResult.SlashCommandResultOk -> {
|
||||
is SendMessageResult.SlashCommandResultOk -> {
|
||||
updateComposerText("")
|
||||
}
|
||||
is SendMessageResult.SlashCommandResultError -> {
|
||||
is SendMessageResult.SlashCommandResultError -> {
|
||||
displayCommandError(sendMessageResult.throwable.localizedMessage)
|
||||
}
|
||||
is SendMessageResult.SlashCommandNotImplemented -> {
|
||||
|
@ -712,7 +752,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
private fun displayRoomDetailActionResult(result: Async<RoomDetailAction>) {
|
||||
when (result) {
|
||||
is Fail -> {
|
||||
is Fail -> {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.dialog_title_error)
|
||||
.setMessage(errorFormatter.toHumanReadable(result.error))
|
||||
|
@ -723,7 +763,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
when (val data = result.invoke()) {
|
||||
is RoomDetailAction.ReportContent -> {
|
||||
when {
|
||||
data.spam -> {
|
||||
data.spam -> {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.content_reported_as_spam_title)
|
||||
.setMessage(R.string.content_reported_as_spam_content)
|
||||
|
@ -745,7 +785,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
.show()
|
||||
.withColoredButton(DialogInterface.BUTTON_NEGATIVE)
|
||||
}
|
||||
else -> {
|
||||
else -> {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.content_reported_title)
|
||||
.setMessage(R.string.content_reported_content)
|
||||
|
@ -767,7 +807,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
override fun onUrlClicked(url: String): Boolean {
|
||||
permalinkHandler
|
||||
.launch(requireActivity(), url, object : NavigateToRoomInterceptor {
|
||||
.launch(requireActivity(), url, object : NavigationInterceptor {
|
||||
override fun navToRoom(roomId: String?, eventId: String?): Boolean {
|
||||
// Same room?
|
||||
if (roomId == roomDetailArgs.roomId) {
|
||||
|
@ -783,6 +823,11 @@ class RoomDetailFragment @Inject constructor(
|
|||
// Not handled
|
||||
return false
|
||||
}
|
||||
|
||||
override fun navToMemberProfile(userId: String): Boolean {
|
||||
navigator.openRoomMemberProfile(userId, roomDetailArgs.roomId, vectorBaseActivity)
|
||||
return true
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
@ -858,14 +903,14 @@ class RoomDetailFragment @Inject constructor(
|
|||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
if (allGranted(grantResults)) {
|
||||
when (requestCode) {
|
||||
PERMISSION_REQUEST_CODE_DOWNLOAD_FILE -> {
|
||||
PERMISSION_REQUEST_CODE_DOWNLOAD_FILE -> {
|
||||
val action = roomDetailViewModel.pendingAction
|
||||
if (action != null) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(action)
|
||||
}
|
||||
}
|
||||
PERMISSION_REQUEST_CODE_INCOMING_URI -> {
|
||||
PERMISSION_REQUEST_CODE_INCOMING_URI -> {
|
||||
val pendingUri = roomDetailViewModel.pendingUri
|
||||
if (pendingUri != null) {
|
||||
roomDetailViewModel.pendingUri = null
|
||||
|
@ -941,7 +986,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
override fun onRoomCreateLinkClicked(url: String) {
|
||||
permalinkHandler
|
||||
.launch(requireContext(), url, object : NavigateToRoomInterceptor {
|
||||
.launch(requireContext(), url, object : NavigationInterceptor {
|
||||
override fun navToRoom(roomId: String?, eventId: String?): Boolean {
|
||||
requireActivity().finish()
|
||||
return false
|
||||
|
@ -963,23 +1008,23 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
private fun handleActions(action: EventSharedAction) {
|
||||
when (action) {
|
||||
is EventSharedAction.AddReaction -> {
|
||||
is EventSharedAction.AddReaction -> {
|
||||
startActivityForResult(EmojiReactionPickerActivity.intent(requireContext(), action.eventId), REACTION_SELECT_REQUEST_CODE)
|
||||
}
|
||||
is EventSharedAction.ViewReactions -> {
|
||||
is EventSharedAction.ViewReactions -> {
|
||||
ViewReactionsBottomSheet.newInstance(roomDetailArgs.roomId, action.messageInformationData)
|
||||
.show(requireActivity().supportFragmentManager, "DISPLAY_REACTIONS")
|
||||
}
|
||||
is EventSharedAction.Copy -> {
|
||||
is EventSharedAction.Copy -> {
|
||||
// I need info about the current selected message :/
|
||||
copyToClipboard(requireContext(), action.content, false)
|
||||
val msg = requireContext().getString(R.string.copied_to_clipboard)
|
||||
showSnackWithMessage(msg, Snackbar.LENGTH_SHORT)
|
||||
}
|
||||
is EventSharedAction.Delete -> {
|
||||
is EventSharedAction.Delete -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.RedactAction(action.eventId, context?.getString(R.string.event_redacted_by_user_reason)))
|
||||
}
|
||||
is EventSharedAction.Share -> {
|
||||
is EventSharedAction.Share -> {
|
||||
// TODO current data communication is too limited
|
||||
// Need to now the media type
|
||||
// TODO bad, just POC
|
||||
|
@ -1007,10 +1052,10 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
)
|
||||
}
|
||||
is EventSharedAction.ViewEditHistory -> {
|
||||
is EventSharedAction.ViewEditHistory -> {
|
||||
onEditedDecorationClicked(action.messageInformationData)
|
||||
}
|
||||
is EventSharedAction.ViewSource -> {
|
||||
is EventSharedAction.ViewSource -> {
|
||||
val view = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_event_content, null)
|
||||
view.findViewById<TextView>(R.id.event_content_text_view)?.let {
|
||||
it.text = action.content
|
||||
|
@ -1021,7 +1066,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
is EventSharedAction.ViewDecryptedSource -> {
|
||||
is EventSharedAction.ViewDecryptedSource -> {
|
||||
val view = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_event_content, null)
|
||||
view.findViewById<TextView>(R.id.event_content_text_view)?.let {
|
||||
it.text = action.content
|
||||
|
@ -1032,31 +1077,31 @@ class RoomDetailFragment @Inject constructor(
|
|||
.setPositiveButton(R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
is EventSharedAction.QuickReact -> {
|
||||
is EventSharedAction.QuickReact -> {
|
||||
// eventId,ClickedOn,Add
|
||||
roomDetailViewModel.handle(RoomDetailAction.UpdateQuickReactAction(action.eventId, action.clickedOn, action.add))
|
||||
}
|
||||
is EventSharedAction.Edit -> {
|
||||
is EventSharedAction.Edit -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterEditMode(action.eventId, composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.Quote -> {
|
||||
is EventSharedAction.Quote -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterQuoteMode(action.eventId, composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.Reply -> {
|
||||
is EventSharedAction.Reply -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterReplyMode(action.eventId, composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.CopyPermalink -> {
|
||||
is EventSharedAction.CopyPermalink -> {
|
||||
val permalink = PermalinkFactory.createPermalink(roomDetailArgs.roomId, action.eventId)
|
||||
copyToClipboard(requireContext(), permalink, false)
|
||||
showSnackWithMessage(requireContext().getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT)
|
||||
}
|
||||
is EventSharedAction.Resend -> {
|
||||
is EventSharedAction.Resend -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ResendMessage(action.eventId))
|
||||
}
|
||||
is EventSharedAction.Remove -> {
|
||||
is EventSharedAction.Remove -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.RemoveFailedEcho(action.eventId))
|
||||
}
|
||||
is EventSharedAction.ReportContentSpam -> {
|
||||
is EventSharedAction.ReportContentSpam -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ReportContent(
|
||||
action.eventId, action.senderId, "This message is spam", spam = true))
|
||||
}
|
||||
|
@ -1064,19 +1109,19 @@ class RoomDetailFragment @Inject constructor(
|
|||
roomDetailViewModel.handle(RoomDetailAction.ReportContent(
|
||||
action.eventId, action.senderId, "This message is inappropriate", inappropriate = true))
|
||||
}
|
||||
is EventSharedAction.ReportContentCustom -> {
|
||||
is EventSharedAction.ReportContentCustom -> {
|
||||
promptReasonToReportContent(action)
|
||||
}
|
||||
is EventSharedAction.IgnoreUser -> {
|
||||
is EventSharedAction.IgnoreUser -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.IgnoreUser(action.senderId))
|
||||
}
|
||||
is EventSharedAction.OnUrlClicked -> {
|
||||
is EventSharedAction.OnUrlClicked -> {
|
||||
onUrlClicked(action.url)
|
||||
}
|
||||
is EventSharedAction.OnUrlLongClicked -> {
|
||||
is EventSharedAction.OnUrlLongClicked -> {
|
||||
onUrlLongClicked(action.url)
|
||||
}
|
||||
else -> {
|
||||
else -> {
|
||||
Toast.makeText(context, "Action $action is not implemented yet", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
@ -1092,7 +1137,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
val startToCompose = composerLayout.composerEditText.text.isNullOrBlank()
|
||||
|
||||
if (startToCompose
|
||||
&& userId == session.myUserId) {
|
||||
&& userId == session.myUserId) {
|
||||
// Empty composer, current user: start an emote
|
||||
composerLayout.composerEditText.setText(Command.EMOTE.command + " ")
|
||||
composerLayout.composerEditText.setSelection(Command.EMOTE.length)
|
||||
|
@ -1183,10 +1228,10 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
private fun launchAttachmentProcess(type: AttachmentTypeSelectorView.Type) {
|
||||
when (type) {
|
||||
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera()
|
||||
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile()
|
||||
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera()
|
||||
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile()
|
||||
AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery()
|
||||
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio()
|
||||
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio()
|
||||
AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact()
|
||||
AttachmentTypeSelectorView.Type.STICKER -> vectorBaseActivity.notImplemented("Adding stickers")
|
||||
}
|
||||
|
|
|
@ -35,17 +35,17 @@ class PermalinkHandler @Inject constructor(private val session: Session,
|
|||
fun launch(
|
||||
context: Context,
|
||||
deepLink: String?,
|
||||
navigateToRoomInterceptor: NavigateToRoomInterceptor? = null,
|
||||
navigationInterceptor: NavigationInterceptor? = null,
|
||||
buildTask: Boolean = false
|
||||
): Single<Boolean> {
|
||||
val uri = deepLink?.let { Uri.parse(it) }
|
||||
return launch(context, uri, navigateToRoomInterceptor, buildTask)
|
||||
return launch(context, uri, navigationInterceptor, buildTask)
|
||||
}
|
||||
|
||||
fun launch(
|
||||
context: Context,
|
||||
deepLink: Uri?,
|
||||
navigateToRoomInterceptor: NavigateToRoomInterceptor? = null,
|
||||
navigationInterceptor: NavigationInterceptor? = null,
|
||||
buildTask: Boolean = false
|
||||
): Single<Boolean> {
|
||||
if (deepLink == null) {
|
||||
|
@ -57,7 +57,7 @@ class PermalinkHandler @Inject constructor(private val session: Session,
|
|||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.map {
|
||||
val roomId = it.getOrNull()
|
||||
if (navigateToRoomInterceptor?.navToRoom(roomId, permalinkData.eventId) != true) {
|
||||
if (navigationInterceptor?.navToRoom(roomId, permalinkData.eventId) != true) {
|
||||
openRoom(context, roomId, permalinkData.eventId, buildTask)
|
||||
}
|
||||
true
|
||||
|
@ -68,7 +68,9 @@ class PermalinkHandler @Inject constructor(private val session: Session,
|
|||
Single.just(true)
|
||||
}
|
||||
is PermalinkData.UserLink -> {
|
||||
navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask)
|
||||
if (navigationInterceptor?.navToMemberProfile(permalinkData.userId) != true) {
|
||||
navigator.openRoomMemberProfile(userId = permalinkData.userId, roomId = null, context = context, buildTask = buildTask)
|
||||
}
|
||||
Single.just(true)
|
||||
}
|
||||
is PermalinkData.FallbackLink -> {
|
||||
|
@ -98,10 +100,21 @@ class PermalinkHandler @Inject constructor(private val session: Session,
|
|||
}
|
||||
}
|
||||
|
||||
interface NavigateToRoomInterceptor {
|
||||
interface NavigationInterceptor {
|
||||
|
||||
/**
|
||||
* Return true if the navigation has been intercepted
|
||||
*/
|
||||
fun navToRoom(roomId: String?, eventId: String? = null): Boolean
|
||||
fun navToRoom(roomId: String?, eventId: String? = null): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the navigation has been intercepted
|
||||
*/
|
||||
fun navToMemberProfile(userId: String): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -40,9 +40,11 @@ class RoomMemberProfileController @Inject constructor(private val stringProvider
|
|||
if (data == null) {
|
||||
return
|
||||
}
|
||||
if (data.roomId == null) {
|
||||
val roomMemberSummary = data.roomMemberSummary()
|
||||
val profileInfo = data.profileInfo()
|
||||
if (roomMemberSummary == null && profileInfo != null) {
|
||||
buildUserActions()
|
||||
} else {
|
||||
} else if (roomMemberSummary != null) {
|
||||
buildRoomMemberActions(data)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,13 +81,15 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
val memberMatrixItem = state.memberAsMatrixItem() ?: return@withState
|
||||
memberProfileIdView.text = memberMatrixItem.id
|
||||
val bestName = memberMatrixItem.getBestName()
|
||||
memberProfileNameView.text = bestName
|
||||
matrixProfileToolbarTitleView.text = bestName
|
||||
avatarRenderer.render(memberMatrixItem, memberProfileAvatarView)
|
||||
avatarRenderer.render(memberMatrixItem, matrixProfileToolbarAvatarImageView)
|
||||
val memberMatrixItem = state.memberAsMatrixItem()
|
||||
if (memberMatrixItem != null) {
|
||||
memberProfileIdView.text = memberMatrixItem.id
|
||||
val bestName = memberMatrixItem.getBestName()
|
||||
memberProfileNameView.text = bestName
|
||||
matrixProfileToolbarTitleView.text = bestName
|
||||
avatarRenderer.render(memberMatrixItem, memberProfileAvatarView)
|
||||
avatarRenderer.render(memberMatrixItem, matrixProfileToolbarAvatarImageView)
|
||||
}
|
||||
|
||||
val roomSummary = state.roomSummary()
|
||||
val powerLevelsContent = state.powerLevelsContent()
|
||||
|
|
|
@ -64,17 +64,17 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
|
|||
observeRoomSummary()
|
||||
observeRoomMemberSummary()
|
||||
observePowerLevel()
|
||||
observeUserIfRequired()
|
||||
fetchProfileInfoIfRequired()
|
||||
}
|
||||
|
||||
private fun observeUserIfRequired() {
|
||||
if (initialState.roomId != null) {
|
||||
private fun fetchProfileInfoIfRequired() {
|
||||
val roomMember = room?.getRoomMember(initialState.userId)
|
||||
if (roomMember != null) {
|
||||
return
|
||||
}
|
||||
session.rx().liveUser(initialState.userId)
|
||||
.unwrap()
|
||||
session.rx().getProfileInfo(initialState.userId)
|
||||
.execute {
|
||||
copy(user = it)
|
||||
copy(profileInfo = it)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,32 +20,33 @@ package im.vector.riotx.features.roommemberprofile
|
|||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.api.util.MatrixItem
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
|
||||
typealias ProfileInfo = JsonDict
|
||||
|
||||
data class RoomMemberProfileViewState(
|
||||
val userId: String,
|
||||
val roomId: String?,
|
||||
val isMine: Boolean = false,
|
||||
val roomSummary: Async<RoomSummary?> = Uninitialized,
|
||||
val roomSummary: Async<RoomSummary> = Uninitialized,
|
||||
val roomMemberSummary: Async<RoomMemberSummary> = Uninitialized,
|
||||
val user: Async<User> = Uninitialized,
|
||||
val profileInfo: Async<ProfileInfo> = Uninitialized,
|
||||
val powerLevelsContent: Async<PowerLevelsContent> = Uninitialized
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomMemberProfileArgs) : this(roomId = args.roomId, userId = args.userId)
|
||||
|
||||
|
||||
fun memberAsMatrixItem(): MatrixItem? {
|
||||
return if (roomId == null) {
|
||||
user.invoke()?.toMatrixItem()
|
||||
} else {
|
||||
roomMemberSummary.invoke()?.toMatrixItem()
|
||||
return roomMemberSummary()?.toMatrixItem() ?: profileInfo()?.let {
|
||||
MatrixItem.UserItem(userId, it[ProfileService.DISPLAY_NAME_KEY] as? String, it[ProfileService.AVATAR_URL_KEY] as? String)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
android:padding="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/memberProfileAvatarView"
|
||||
android:layout_width="128dp"
|
||||
|
|
Loading…
Add table
Reference in a new issue