mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-24 23:09:02 +03:00
Message state: fix and clean code after Benoits review
This commit is contained in:
parent
6c8e2f1fd6
commit
ea21892d03
4 changed files with 29 additions and 19 deletions
matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room
vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action
|
@ -38,7 +38,6 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
||||||
import org.matrix.android.sdk.internal.database.query.where
|
import org.matrix.android.sdk.internal.database.query.where
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory
|
import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory
|
||||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
|
|
||||||
import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
|
import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
import org.matrix.android.sdk.internal.task.TaskExecutor
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
import org.matrix.android.sdk.internal.task.configureWith
|
||||||
|
|
|
@ -87,7 +87,7 @@ internal class DefaultTimelineService @AssistedInject constructor(@Assisted priv
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTimeLineEventLive(eventId: String): LiveData<Optional<TimelineEvent>> {
|
override fun getTimeLineEventLive(eventId: String): LiveData<Optional<TimelineEvent>> {
|
||||||
return LiveTimelineEvent(timelineInput, monarchy, taskExecutor, timelineEventMapper, roomId, eventId)
|
return LiveTimelineEvent(timelineInput, monarchy, taskExecutor.executorScope, timelineEventMapper, roomId, eventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttachmentMessages(): List<TimelineEvent> {
|
override fun getAttachmentMessages(): List<TimelineEvent> {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MediatorLiveData
|
import androidx.lifecycle.MediatorLiveData
|
||||||
import androidx.lifecycle.Transformations
|
import androidx.lifecycle.Transformations
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
||||||
|
@ -29,14 +30,14 @@ import org.matrix.android.sdk.api.util.toOptional
|
||||||
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
|
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
|
||||||
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
|
||||||
import org.matrix.android.sdk.internal.database.query.where
|
import org.matrix.android.sdk.internal.database.query.where
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class takes care of handling case where local echo is replaced by the synced event in the db.
|
* This class takes care of handling case where local echo is replaced by the synced event in the db.
|
||||||
*/
|
*/
|
||||||
internal class LiveTimelineEvent(private val timelineInput: TimelineInput,
|
internal class LiveTimelineEvent(private val timelineInput: TimelineInput,
|
||||||
private val monarchy: Monarchy,
|
private val monarchy: Monarchy,
|
||||||
private val taskExecutor: TaskExecutor,
|
private val coroutineScope: CoroutineScope,
|
||||||
private val timelineEventMapper: TimelineEventMapper,
|
private val timelineEventMapper: TimelineEventMapper,
|
||||||
private val roomId: String,
|
private val roomId: String,
|
||||||
private val eventId: String)
|
private val eventId: String)
|
||||||
|
@ -45,12 +46,15 @@ internal class LiveTimelineEvent(private val timelineInput: TimelineInput,
|
||||||
|
|
||||||
private var queryLiveData: LiveData<Optional<TimelineEvent>>? = null
|
private var queryLiveData: LiveData<Optional<TimelineEvent>>? = null
|
||||||
|
|
||||||
|
// If we are listening to local echo, we want to be aware when event is synced
|
||||||
|
private var shouldObserveSync = AtomicBoolean(LocalEcho.isLocalEchoId(eventId))
|
||||||
|
|
||||||
init {
|
init {
|
||||||
buildAndObserveQuery(eventId)
|
buildAndObserveQuery(eventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes sure it's made on the main thread
|
// Makes sure it's made on the main thread
|
||||||
private fun buildAndObserveQuery(eventIdToObserve: String) = taskExecutor.executorScope.launch(Dispatchers.Main) {
|
private fun buildAndObserveQuery(eventIdToObserve: String) = coroutineScope.launch(Dispatchers.Main) {
|
||||||
queryLiveData?.also {
|
queryLiveData?.also {
|
||||||
removeSource(it)
|
removeSource(it)
|
||||||
}
|
}
|
||||||
|
@ -60,14 +64,15 @@ internal class LiveTimelineEvent(private val timelineInput: TimelineInput,
|
||||||
)
|
)
|
||||||
queryLiveData = Transformations.map(liveData) { events ->
|
queryLiveData = Transformations.map(liveData) { events ->
|
||||||
events.firstOrNull().toOptional()
|
events.firstOrNull().toOptional()
|
||||||
}
|
}.also {
|
||||||
queryLiveData?.also {
|
|
||||||
addSource(it) { newValue -> value = newValue }
|
addSource(it) { newValue -> value = newValue }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLocalEchoSynced(roomId: String, localEchoEventId: String, syncedEventId: String) {
|
override fun onLocalEchoSynced(roomId: String, localEchoEventId: String, syncedEventId: String) {
|
||||||
if (localEchoEventId == eventId) {
|
if (this.roomId == roomId && localEchoEventId == this.eventId) {
|
||||||
|
timelineInput.listeners.remove(this)
|
||||||
|
shouldObserveSync.set(false)
|
||||||
// rebuild the query with the new eventId
|
// rebuild the query with the new eventId
|
||||||
buildAndObserveQuery(syncedEventId)
|
buildAndObserveQuery(syncedEventId)
|
||||||
}
|
}
|
||||||
|
@ -75,15 +80,14 @@ internal class LiveTimelineEvent(private val timelineInput: TimelineInput,
|
||||||
|
|
||||||
override fun onActive() {
|
override fun onActive() {
|
||||||
super.onActive()
|
super.onActive()
|
||||||
// If we are listening to local echo, we want to be aware when event is synced
|
if (shouldObserveSync.get()) {
|
||||||
if (LocalEcho.isLocalEchoId(eventId)) {
|
|
||||||
timelineInput.listeners.add(this)
|
timelineInput.listeners.add(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInactive() {
|
override fun onInactive() {
|
||||||
super.onInactive()
|
super.onInactive()
|
||||||
if (LocalEcho.isLocalEchoId(eventId)) {
|
if (shouldObserveSync.get()) {
|
||||||
timelineInput.listeners.remove(this)
|
timelineInput.listeners.remove(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.app.features.home.room.detail.timeline.action
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
|
import com.jakewharton.rxrelay2.BehaviorRelay
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
@ -75,6 +76,8 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
pillsPostProcessorFactory.create(initialState.roomId)
|
pillsPostProcessorFactory.create(initialState.roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val eventIdObservable = BehaviorRelay.createDefault(initialState.eventId)
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(initialState: MessageActionState): MessageActionsViewModel
|
fun create(initialState: MessageActionState): MessageActionsViewModel
|
||||||
|
@ -90,6 +93,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
|
|
||||||
init {
|
init {
|
||||||
observeEvent()
|
observeEvent()
|
||||||
|
observeReactions()
|
||||||
observePowerLevel()
|
observePowerLevel()
|
||||||
observeTimelineEventState()
|
observeTimelineEventState()
|
||||||
}
|
}
|
||||||
|
@ -135,8 +139,10 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeReactions(eventId: String) {
|
private fun observeReactions() {
|
||||||
if (room == null) return
|
if (room == null) return
|
||||||
|
eventIdObservable
|
||||||
|
.switchMap { eventId ->
|
||||||
room.rx()
|
room.rx()
|
||||||
.liveAnnotationSummary(eventId)
|
.liveAnnotationSummary(eventId)
|
||||||
.map { annotations ->
|
.map { annotations ->
|
||||||
|
@ -144,6 +150,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
ToggleState(emoji, annotations.getOrNull()?.reactionsSummary?.firstOrNull { it.key == emoji }?.addedByMe ?: false)
|
ToggleState(emoji, annotations.getOrNull()?.reactionsSummary?.firstOrNull { it.key == emoji }?.addedByMe ?: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.execute {
|
.execute {
|
||||||
copy(quickStates = it)
|
copy(quickStates = it)
|
||||||
}
|
}
|
||||||
|
@ -152,7 +159,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
private fun observeTimelineEventState() {
|
private fun observeTimelineEventState() {
|
||||||
selectSubscribe(MessageActionState::timelineEvent, MessageActionState::actionPermissions) { timelineEvent, permissions ->
|
selectSubscribe(MessageActionState::timelineEvent, MessageActionState::actionPermissions) { timelineEvent, permissions ->
|
||||||
val nonNullTimelineEvent = timelineEvent() ?: return@selectSubscribe
|
val nonNullTimelineEvent = timelineEvent() ?: return@selectSubscribe
|
||||||
observeReactions(nonNullTimelineEvent.eventId)
|
eventIdObservable.accept(nonNullTimelineEvent.eventId)
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
eventId = nonNullTimelineEvent.eventId,
|
eventId = nonNullTimelineEvent.eventId,
|
||||||
|
|
Loading…
Add table
Reference in a new issue