mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Membership: refact a bit and add a left message when kicked or banned
This commit is contained in:
parent
6ca69a9947
commit
171a945de9
@ -44,6 +44,10 @@ enum class Membership(val value: String) {
|
||||
return this == KNOCK || this == LEAVE || this == BAN
|
||||
}
|
||||
|
||||
fun isActive(): Boolean {
|
||||
return activeMemberships().contains(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun activeMemberships(): List<Membership> {
|
||||
return listOf(INVITE, JOIN)
|
||||
|
@ -47,6 +47,10 @@ data class Optional<T : Any> constructor(private val value: T?) {
|
||||
fun <T : Any> from(value: T?): Optional<T> {
|
||||
return Optional(value)
|
||||
}
|
||||
|
||||
fun <T: Any> empty(): Optional<T> {
|
||||
return Optional(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.internal.session.room.membership
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
|
||||
import im.vector.matrix.android.internal.session.user.UserEntityFactory
|
||||
import io.realm.Realm
|
||||
@ -35,7 +34,7 @@ internal class RoomMemberEventHandler @Inject constructor() {
|
||||
val userId = event.stateKey ?: return false
|
||||
val roomMemberEntity = RoomMemberEntityFactory.create(roomId, userId, roomMember)
|
||||
realm.insertOrUpdate(roomMemberEntity)
|
||||
if (roomMember.membership in Membership.activeMemberships()) {
|
||||
if (roomMember.membership.isActive()) {
|
||||
val userEntity = UserEntityFactory.create(userId, roomMember)
|
||||
realm.insertOrUpdate(userEntity)
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import im.vector.matrix.android.internal.database.mapper.toEntity
|
||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.query.copyToRealmOrIgnore
|
||||
import im.vector.matrix.android.internal.database.query.find
|
||||
import im.vector.matrix.android.internal.database.query.findLastForwardChunkOfRoom
|
||||
@ -42,6 +43,7 @@ import im.vector.matrix.android.internal.database.query.getOrCreate
|
||||
import im.vector.matrix.android.internal.database.query.getOrNull
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.di.UserId
|
||||
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
|
||||
import im.vector.matrix.android.internal.session.mapWithProgress
|
||||
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
||||
@ -67,6 +69,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||
private val roomFullyReadHandler: RoomFullyReadHandler,
|
||||
private val cryptoService: DefaultCryptoService,
|
||||
private val roomMemberEventHandler: RoomMemberEventHandler,
|
||||
@UserId private val userId: String,
|
||||
private val eventBus: EventBus) {
|
||||
|
||||
sealed class HandlingStrategy {
|
||||
@ -208,8 +211,6 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||
roomId: String,
|
||||
roomSync: RoomSync): RoomEntity {
|
||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId)
|
||||
roomEntity.membership = Membership.LEAVE
|
||||
roomEntity.chunks.deleteAllFromRealm()
|
||||
for (event in roomSync.state?.events.orEmpty()) {
|
||||
if (event.eventId == null || event.stateKey == null) {
|
||||
continue
|
||||
@ -221,7 +222,26 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
||||
}
|
||||
roomMemberEventHandler.handle(realm, roomId, event)
|
||||
}
|
||||
roomSummaryUpdater.update(realm, roomId, Membership.LEAVE, roomSync.summary, roomSync.unreadNotifications)
|
||||
for (event in roomSync.timeline?.events.orEmpty()) {
|
||||
if (event.eventId == null || event.senderId == null) {
|
||||
continue
|
||||
}
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED).copyToRealmOrIgnore(realm)
|
||||
if (event.stateKey != null) {
|
||||
CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply {
|
||||
eventId = event.eventId
|
||||
root = eventEntity
|
||||
}
|
||||
if (event.type == EventType.STATE_ROOM_MEMBER) {
|
||||
roomMemberEventHandler.handle(realm, roomEntity.roomId, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
val leftMember = RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()
|
||||
val membership = leftMember?.membership ?: Membership.LEAVE
|
||||
roomEntity.membership = membership
|
||||
roomEntity.chunks.deleteAllFromRealm()
|
||||
roomSummaryUpdater.update(realm, roomId, membership, roomSync.summary, roomSync.unreadNotifications)
|
||||
return roomEntity
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ package im.vector.riotx.features.home.room.detail
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
@ -31,6 +32,7 @@ import im.vector.riotx.core.platform.ToolbarConfigurable
|
||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||
import im.vector.riotx.features.home.room.breadcrumbs.BreadcrumbsFragment
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipAction
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewEvents
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewModel
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewState
|
||||
import kotlinx.android.synthetic.main.activity_room_detail.*
|
||||
@ -91,11 +93,21 @@ class RoomDetailActivity :
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
|
||||
requireActiveMembershipViewModel.observeViewEvents { finish() }
|
||||
|
||||
requireActiveMembershipViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RequireActiveMembershipViewEvents.RoomLeft -> handleRoomLeft(it)
|
||||
}
|
||||
}
|
||||
drawerLayout.addDrawerListener(drawerListener)
|
||||
}
|
||||
|
||||
private fun handleRoomLeft(roomLeft: RequireActiveMembershipViewEvents.RoomLeft) {
|
||||
if (roomLeft.leftMessage != null) {
|
||||
Toast.makeText(this, roomLeft.leftMessage, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun switchToRoom(switchToRoom: RoomDetailSharedAction.SwitchToRoom) {
|
||||
drawerLayout.closeDrawer(GravityCompat.START)
|
||||
// Do not replace the Fragment if it's the same roomId
|
||||
|
@ -19,5 +19,5 @@ package im.vector.riotx.features.room
|
||||
import im.vector.riotx.core.platform.VectorViewEvents
|
||||
|
||||
sealed class RequireActiveMembershipViewEvents : VectorViewEvents {
|
||||
object RoomLeft : RequireActiveMembershipViewEvents()
|
||||
data class RoomLeft(val leftMessage: String?) : RequireActiveMembershipViewEvents()
|
||||
}
|
||||
|
@ -20,21 +20,31 @@ import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.jakewharton.rxrelay2.BehaviorRelay
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.query.QueryStringValue
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.room.Room
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.matrix.rx.unwrap
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import io.reactivex.disposables.Disposable
|
||||
import timber.log.Timber
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* This ViewModel observe a room summary and notify when the room is left
|
||||
*/
|
||||
class RequireActiveMembershipViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: RequireActiveMembershipViewState,
|
||||
private val stringProvider: StringProvider,
|
||||
private val session: Session)
|
||||
: VectorViewModel<RequireActiveMembershipViewState, RequireActiveMembershipAction, RequireActiveMembershipViewEvents>(initialState) {
|
||||
|
||||
@ -55,32 +65,60 @@ class RequireActiveMembershipViewModel @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private var currentDisposable: Disposable? = null
|
||||
private val roomIdObservable = BehaviorRelay.createDefault(Optional.from(initialState.roomId))
|
||||
|
||||
init {
|
||||
observeRoomSummary(initialState.roomId)
|
||||
observeRoomSummary()
|
||||
}
|
||||
|
||||
private fun observeRoomSummary(roomId: String?) {
|
||||
currentDisposable?.dispose()
|
||||
|
||||
currentDisposable = roomId
|
||||
?.let { session.getRoom(it) }
|
||||
?.let { room ->
|
||||
room.rx().liveRoomSummary()
|
||||
private fun observeRoomSummary() {
|
||||
roomIdObservable
|
||||
.unwrap()
|
||||
.switchMap { roomId ->
|
||||
val room = session.getRoom(roomId) ?: return@switchMap Observable.just(Optional.empty<RequireActiveMembershipViewEvents.RoomLeft>())
|
||||
room.rx()
|
||||
.liveRoomSummary()
|
||||
.unwrap()
|
||||
.subscribe {
|
||||
if (it.membership.isLeft()) {
|
||||
Timber.w("The room has been left")
|
||||
_viewEvents.post(RequireActiveMembershipViewEvents.RoomLeft)
|
||||
}
|
||||
}
|
||||
.observeOn(Schedulers.computation())
|
||||
.map { mapToLeftViewEvent(room, it) }
|
||||
}
|
||||
.unwrap()
|
||||
.subscribe { event ->
|
||||
_viewEvents.post(event)
|
||||
}
|
||||
.disposeOnClear()
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
currentDisposable?.dispose()
|
||||
private fun mapToLeftViewEvent(room: Room, roomSummary: RoomSummary): Optional<RequireActiveMembershipViewEvents.RoomLeft> {
|
||||
if (roomSummary.membership.isActive()) {
|
||||
return Optional.empty()
|
||||
}
|
||||
val senderId = room.getStateEvent(EventType.STATE_ROOM_MEMBER, QueryStringValue.Equals(session.myUserId))?.senderId
|
||||
val senderDisplayName = senderId?.takeIf { it != session.myUserId }?.let {
|
||||
room.getRoomMember(it)?.displayName ?: it
|
||||
}
|
||||
val viewEvent = when (roomSummary.membership) {
|
||||
Membership.LEAVE -> {
|
||||
val message = senderDisplayName?.let {
|
||||
stringProvider.getString(R.string.has_been_kicked, roomSummary.displayName, it)
|
||||
}
|
||||
RequireActiveMembershipViewEvents.RoomLeft(message)
|
||||
}
|
||||
Membership.KNOCK -> {
|
||||
val message = senderDisplayName?.let {
|
||||
stringProvider.getString(R.string.has_been_kicked, roomSummary.displayName, it)
|
||||
}
|
||||
RequireActiveMembershipViewEvents.RoomLeft(message)
|
||||
}
|
||||
Membership.BAN -> {
|
||||
val message = senderDisplayName?.let {
|
||||
stringProvider.getString(R.string.has_been_banned, roomSummary.displayName, it)
|
||||
}
|
||||
RequireActiveMembershipViewEvents.RoomLeft(message)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
return Optional.from(viewEvent)
|
||||
}
|
||||
|
||||
override fun handle(action: RequireActiveMembershipAction) {
|
||||
@ -89,7 +127,7 @@ class RequireActiveMembershipViewModel @AssistedInject constructor(
|
||||
setState {
|
||||
copy(roomId = action.roomId)
|
||||
}
|
||||
observeRoomSummary(action.roomId)
|
||||
roomIdObservable.accept(Optional.from(action.roomId))
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package im.vector.riotx.features.roommemberprofile
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.airbnb.mvrx.MvRx
|
||||
import com.airbnb.mvrx.viewModel
|
||||
@ -27,6 +28,7 @@ import im.vector.riotx.core.di.ScreenComponent
|
||||
import im.vector.riotx.core.extensions.addFragment
|
||||
import im.vector.riotx.core.platform.ToolbarConfigurable
|
||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewEvents
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewModel
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewState
|
||||
import javax.inject.Inject
|
||||
@ -66,10 +68,21 @@ class RoomMemberProfileActivity :
|
||||
addFragment(R.id.simpleFragmentContainer, RoomMemberProfileFragment::class.java, fragmentArgs)
|
||||
}
|
||||
|
||||
requireActiveMembershipViewModel.observeViewEvents { finish() }
|
||||
requireActiveMembershipViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RequireActiveMembershipViewEvents.RoomLeft -> handleRoomLeft(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun configure(toolbar: Toolbar) {
|
||||
configureToolbar(toolbar)
|
||||
}
|
||||
|
||||
private fun handleRoomLeft(roomLeft: RequireActiveMembershipViewEvents.RoomLeft) {
|
||||
if (roomLeft.leftMessage != null) {
|
||||
Toast.makeText(this, roomLeft.leftMessage, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package im.vector.riotx.features.roomprofile
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.airbnb.mvrx.MvRx
|
||||
import com.airbnb.mvrx.viewModel
|
||||
@ -28,6 +29,7 @@ import im.vector.riotx.core.extensions.addFragment
|
||||
import im.vector.riotx.core.extensions.addFragmentToBackstack
|
||||
import im.vector.riotx.core.platform.ToolbarConfigurable
|
||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewEvents
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewModel
|
||||
import im.vector.riotx.features.room.RequireActiveMembershipViewState
|
||||
import im.vector.riotx.features.roomprofile.members.RoomMemberListFragment
|
||||
@ -86,7 +88,18 @@ class RoomProfileActivity :
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
|
||||
requireActiveMembershipViewModel.observeViewEvents { finish() }
|
||||
requireActiveMembershipViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RequireActiveMembershipViewEvents.RoomLeft -> handleRoomLeft(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRoomLeft(roomLeft: RequireActiveMembershipViewEvents.RoomLeft) {
|
||||
if (roomLeft.leftMessage != null) {
|
||||
Toast.makeText(this, roomLeft.leftMessage, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun openRoomUploads() {
|
||||
|
Loading…
Reference in New Issue
Block a user