BayernMessenger/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailViewModel.kt

248 lines
11 KiB
Kotlin
Raw Normal View History

2019-01-18 10:12:08 +00:00
/*
* Copyright 2019 New Vector Ltd
2019-01-18 10:12:08 +00:00
*
* 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
2019-01-18 10:12:08 +00:00
*
* 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.
2019-01-18 10:12:08 +00:00
*/
2018-12-29 16:54:03 +00:00
package im.vector.riotredesign.features.home.room.detail
2019-04-09 11:36:33 +00:00
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
2018-12-29 16:54:03 +00:00
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import com.jakewharton.rxrelay2.BehaviorRelay
2018-12-29 16:54:03 +00:00
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.content.ContentAttachmentData
2019-04-09 15:53:23 +00:00
import im.vector.matrix.android.api.session.room.model.message.MessageType
2018-12-29 16:54:03 +00:00
import im.vector.matrix.rx.rx
2019-04-05 08:40:59 +00:00
import im.vector.riotredesign.core.platform.VectorViewModel
2019-04-09 11:36:33 +00:00
import im.vector.riotredesign.core.utils.LiveEvent
import im.vector.riotredesign.features.command.CommandParser
import im.vector.riotredesign.features.command.ParsedCommand
2019-02-19 10:16:31 +00:00
import im.vector.riotredesign.features.home.room.VisibleRoomStore
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
import io.reactivex.rxkotlin.subscribeBy
import org.koin.android.ext.android.get
import java.util.concurrent.TimeUnit
2018-12-29 16:54:03 +00:00
class RoomDetailViewModel(initialState: RoomDetailViewState,
private val session: Session,
2019-02-19 10:16:31 +00:00
private val visibleRoomHolder: VisibleRoomStore
2019-04-05 08:40:59 +00:00
) : VectorViewModel<RoomDetailViewState>(initialState) {
2018-12-29 16:54:03 +00:00
private val room = session.getRoom(initialState.roomId)!!
private val roomId = initialState.roomId
private val eventId = initialState.eventId
private val displayedEventsObservable = BehaviorRelay.create<RoomDetailActions.EventDisplayed>()
private val timeline = room.createTimeline(eventId, TimelineDisplayableEvents.DISPLAYABLE_TYPES)
companion object : MvRxViewModelFactory<RoomDetailViewModel, RoomDetailViewState> {
2018-12-29 16:54:03 +00:00
const val PAGINATION_COUNT = 50
2018-12-29 16:54:03 +00:00
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: RoomDetailViewState): RoomDetailViewModel? {
val currentSession = viewModelContext.activity.get<Session>()
2019-02-19 10:16:31 +00:00
val visibleRoomHolder = viewModelContext.activity.get<VisibleRoomStore>()
return RoomDetailViewModel(state, currentSession, visibleRoomHolder)
2018-12-29 16:54:03 +00:00
}
}
init {
observeRoomSummary()
observeEventDisplayedActions()
2018-12-29 16:54:03 +00:00
room.loadRoomMembersIfNeeded()
timeline.start()
setState { copy(timeline = this@RoomDetailViewModel.timeline) }
2018-12-29 16:54:03 +00:00
}
fun process(action: RoomDetailActions) {
2018-12-29 16:54:03 +00:00
when (action) {
is RoomDetailActions.SendMessage -> handleSendMessage(action)
is RoomDetailActions.IsDisplayed -> handleIsDisplayed()
is RoomDetailActions.SendMedia -> handleSendMedia(action)
is RoomDetailActions.EventDisplayed -> handleEventDisplayed(action)
is RoomDetailActions.LoadMore -> handleLoadMore(action)
is RoomDetailActions.AcceptInvite -> handleAcceptInvite()
is RoomDetailActions.RejectInvite -> handleRejectInvite()
2018-12-29 16:54:03 +00:00
}
}
2019-04-09 11:36:33 +00:00
private val _sendMessageResultLiveData = MutableLiveData<LiveEvent<SendMessageResult>>()
val sendMessageResultLiveData: LiveData<LiveEvent<SendMessageResult>>
get() = _sendMessageResultLiveData
2018-12-29 16:54:03 +00:00
// PRIVATE METHODS *****************************************************************************
private fun handleSendMessage(action: RoomDetailActions.SendMessage) {
2019-04-09 11:36:33 +00:00
// Handle slash command
val slashCommandResult = CommandParser.parseSplashCommand(action.text)
when (slashCommandResult) {
is ParsedCommand.ErrorNotACommand -> {
2019-04-09 11:36:33 +00:00
// Send the text message to the room
room.sendTextMessage(action.text)
2019-04-09 11:36:33 +00:00
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.MessageSent))
}
is ParsedCommand.ErrorSyntax -> {
2019-04-09 11:36:33 +00:00
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandError(slashCommandResult.command)))
}
is ParsedCommand.ErrorEmptySlashCommand -> {
2019-04-09 11:36:33 +00:00
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandUnknown("/")))
}
is ParsedCommand.ErrorUnknownSlashCommand -> {
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandUnknown(slashCommandResult.slashCommand)))
}
is ParsedCommand.Invite -> {
2019-04-09 12:35:18 +00:00
handleInviteSlashCommand(slashCommandResult)
}
is ParsedCommand.SetUserPowerLevel -> {
2019-04-09 13:21:17 +00:00
// TODO
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
}
is ParsedCommand.ClearScalarToken -> {
2019-04-09 13:21:17 +00:00
// TODO
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
}
is ParsedCommand.SetMarkdown -> {
2019-04-09 13:21:17 +00:00
// TODO
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
}
is ParsedCommand.UnbanUser -> {
2019-04-09 13:21:17 +00:00
// TODO
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
}
is ParsedCommand.BanUser -> {
2019-04-09 13:21:17 +00:00
// TODO
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
}
is ParsedCommand.KickUser -> {
2019-04-09 13:21:17 +00:00
// TODO
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
}
is ParsedCommand.JoinRoom -> {
2019-04-09 13:21:17 +00:00
// TODO
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
}
is ParsedCommand.PartRoom -> {
2019-04-09 13:21:17 +00:00
// TODO
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
}
is ParsedCommand.SendEmote -> {
room.sendTextMessage(slashCommandResult.message, msgType = MessageType.MSGTYPE_EMOTE)
2019-04-09 15:53:23 +00:00
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled))
2019-04-09 13:21:17 +00:00
}
is ParsedCommand.ChangeTopic -> {
2019-04-09 16:33:28 +00:00
handleChangeTopicSlashCommand(slashCommandResult)
2019-04-09 13:21:17 +00:00
}
is ParsedCommand.ChangeDisplayName -> {
2019-04-09 13:21:17 +00:00
// TODO
2019-04-09 12:35:18 +00:00
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
2019-04-09 11:36:33 +00:00
}
}
}
2019-04-09 16:33:28 +00:00
private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) {
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled))
room.updateTopic(changeTopic.topic, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandResultOk))
}
override fun onFailure(failure: Throwable) {
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandResultError(failure)))
}
})
}
2019-04-09 12:35:18 +00:00
private fun handleInviteSlashCommand(invite: ParsedCommand.Invite) {
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled))
room.invite(invite.userId, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandResultOk))
2019-04-09 11:36:33 +00:00
}
2019-04-09 12:35:18 +00:00
override fun onFailure(failure: Throwable) {
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandResultError(failure)))
2019-04-09 11:36:33 +00:00
}
2019-04-09 12:35:18 +00:00
})
2018-12-29 16:54:03 +00:00
}
private fun handleSendMedia(action: RoomDetailActions.SendMedia) {
val attachments = action.mediaFiles.map {
ContentAttachmentData(
size = it.size,
duration = it.duration,
date = it.date,
height = it.height,
width = it.width,
name = it.name,
path = it.path,
mimeType = it.mimeType,
type = ContentAttachmentData.Type.values()[it.mediaType]
)
}
room.sendMedias(attachments)
}
private fun handleEventDisplayed(action: RoomDetailActions.EventDisplayed) {
displayedEventsObservable.accept(action)
}
private fun handleIsDisplayed() {
2019-02-19 10:16:31 +00:00
visibleRoomHolder.post(roomId)
}
private fun handleLoadMore(action: RoomDetailActions.LoadMore) {
timeline.paginate(action.direction, PAGINATION_COUNT)
}
private fun handleRejectInvite() {
room.leave(object : MatrixCallback<Unit> {})
}
private fun handleAcceptInvite() {
room.join(object : MatrixCallback<Unit> {})
}
private fun observeEventDisplayedActions() {
// We are buffering scroll events for one second
// and keep the most recent one to set the read receipt on.
displayedEventsObservable
.buffer(1, TimeUnit.SECONDS)
.filter { it.isNotEmpty() }
.subscribeBy(onNext = { actions ->
val mostRecentEvent = actions.maxBy { it.event.displayIndex }
mostRecentEvent?.event?.root?.eventId?.let { eventId ->
2019-04-03 14:36:45 +00:00
room.setReadReceipt(eventId, callback = object : MatrixCallback<Unit> {})
}
})
.disposeOnClear()
}
2018-12-29 16:54:03 +00:00
private fun observeRoomSummary() {
room.rx().liveRoomSummary()
.execute { async ->
copy(asyncRoomSummary = async)
}
}
override fun onCleared() {
timeline.dispose()
super.onCleared()
2018-12-29 16:54:03 +00:00
}
2018-12-29 16:54:03 +00:00
}