Rename getTimeLine to getTimeline to align naming. Also create TimelineEventDataSource.

This commit is contained in:
ganfra 2022-02-23 18:00:31 +01:00
parent 924a4f8c94
commit fb2ed9a7ac
18 changed files with 113 additions and 80 deletions

View file

@ -58,9 +58,9 @@ class FlowRoom(private val room: Room) {
} }
fun liveTimelineEvent(eventId: String): Flow<Optional<TimelineEvent>> { fun liveTimelineEvent(eventId: String): Flow<Optional<TimelineEvent>> {
return room.getTimeLineEventLive(eventId).asFlow() return room.getTimelineEventLive(eventId).asFlow()
.startWith(room.coroutineDispatchers.io) { .startWith(room.coroutineDispatchers.io) {
room.getTimeLineEvent(eventId).toOptional() room.getTimelineEvent(eventId).toOptional()
} }
} }

View file

@ -95,7 +95,7 @@ class PreShareKeysTest : InstrumentedTest {
assertEquals(megolmSessionId, sentEvent.root.content.toModel<EncryptedEventContent>()?.sessionId, "Unexpected megolm session") assertEquals(megolmSessionId, sentEvent.root.content.toModel<EncryptedEventContent>()?.sessionId, "Unexpected megolm session")
testHelper.waitWithLatch { latch -> testHelper.waitWithLatch { latch ->
testHelper.retryPeriodicallyWithLatch(latch) { testHelper.retryPeriodicallyWithLatch(latch) {
bobSession.getRoom(e2eRoomID)?.getTimeLineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE
} }
} }

View file

@ -92,7 +92,7 @@ class KeyShareTests : InstrumentedTest {
val roomSecondSessionPOV = aliceSession2.getRoom(roomId) val roomSecondSessionPOV = aliceSession2.getRoom(roomId)
val receivedEvent = roomSecondSessionPOV?.getTimeLineEvent(sentEventId) val receivedEvent = roomSecondSessionPOV?.getTimelineEvent(sentEventId)
assertNotNull(receivedEvent) assertNotNull(receivedEvent)
assert(receivedEvent!!.isEncrypted()) assert(receivedEvent!!.isEncrypted())
@ -382,7 +382,7 @@ class KeyShareTests : InstrumentedTest {
commonTestHelper.sendTextMessage(roomAlicePov, "After", 1) commonTestHelper.sendTextMessage(roomAlicePov, "After", 1)
val roomRoomBobPov = aliceSession.getRoom(roomId) val roomRoomBobPov = aliceSession.getRoom(roomId)
val beforeJoin = roomRoomBobPov!!.getTimeLineEvent(secondEventId) val beforeJoin = roomRoomBobPov!!.getTimelineEvent(secondEventId)
var dRes = tryOrNull { bobSession.cryptoService().decryptEvent(beforeJoin!!.root, "") } var dRes = tryOrNull { bobSession.cryptoService().decryptEvent(beforeJoin!!.root, "") }

View file

@ -80,11 +80,11 @@ class WithHeldTests : InstrumentedTest {
// await for bob unverified session to get the message // await for bob unverified session to get the message
testHelper.waitWithLatch { latch -> testHelper.waitWithLatch { latch ->
testHelper.retryPeriodicallyWithLatch(latch) { testHelper.retryPeriodicallyWithLatch(latch) {
bobUnverifiedSession.getRoom(roomId)?.getTimeLineEvent(timelineEvent.eventId) != null bobUnverifiedSession.getRoom(roomId)?.getTimelineEvent(timelineEvent.eventId) != null
} }
} }
val eventBobPOV = bobUnverifiedSession.getRoom(roomId)?.getTimeLineEvent(timelineEvent.eventId)!! val eventBobPOV = bobUnverifiedSession.getRoom(roomId)?.getTimelineEvent(timelineEvent.eventId)!!
// ============================= // =============================
// ASSERT // ASSERT
@ -109,7 +109,7 @@ class WithHeldTests : InstrumentedTest {
testHelper.waitWithLatch { latch -> testHelper.waitWithLatch { latch ->
testHelper.retryPeriodicallyWithLatch(latch) { testHelper.retryPeriodicallyWithLatch(latch) {
val ev = bobUnverifiedSession.getRoom(roomId)?.getTimeLineEvent(secondEvent.eventId) val ev = bobUnverifiedSession.getRoom(roomId)?.getTimelineEvent(secondEvent.eventId)
// wait until it's decrypted // wait until it's decrypted
ev?.root?.getClearType() == EventType.MESSAGE ev?.root?.getClearType() == EventType.MESSAGE
} }
@ -157,12 +157,12 @@ class WithHeldTests : InstrumentedTest {
// await for bob session to get the message // await for bob session to get the message
testHelper.waitWithLatch { latch -> testHelper.waitWithLatch { latch ->
testHelper.retryPeriodicallyWithLatch(latch) { testHelper.retryPeriodicallyWithLatch(latch) {
bobSession.getRoom(testData.roomId)?.getTimeLineEvent(eventId) != null bobSession.getRoom(testData.roomId)?.getTimelineEvent(eventId) != null
} }
} }
// Previous message should still be undecryptable (partially withheld session) // Previous message should still be undecryptable (partially withheld session)
val eventBobPOV = bobSession.getRoom(testData.roomId)?.getTimeLineEvent(eventId) val eventBobPOV = bobSession.getRoom(testData.roomId)?.getTimelineEvent(eventId)
try { try {
// .. might need to wait a bit for stability? // .. might need to wait a bit for stability?
bobSession.cryptoService().decryptEvent(eventBobPOV!!.root, "") bobSession.cryptoService().decryptEvent(eventBobPOV!!.root, "")
@ -190,7 +190,7 @@ class WithHeldTests : InstrumentedTest {
// await for bob SecondSession session to get the message // await for bob SecondSession session to get the message
testHelper.waitWithLatch { latch -> testHelper.waitWithLatch { latch ->
testHelper.retryPeriodicallyWithLatch(latch) { testHelper.retryPeriodicallyWithLatch(latch) {
bobSecondSession.getRoom(testData.roomId)?.getTimeLineEvent(secondMessageId) != null bobSecondSession.getRoom(testData.roomId)?.getTimelineEvent(secondMessageId) != null
} }
} }
@ -231,7 +231,7 @@ class WithHeldTests : InstrumentedTest {
// await for bob SecondSession session to get the message // await for bob SecondSession session to get the message
testHelper.waitWithLatch { latch -> testHelper.waitWithLatch { latch ->
testHelper.retryPeriodicallyWithLatch(latch) { testHelper.retryPeriodicallyWithLatch(latch) {
val timeLineEvent = bobSecondSession.getRoom(testData.roomId)?.getTimeLineEvent(eventId)?.also { val timeLineEvent = bobSecondSession.getRoom(testData.roomId)?.getTimelineEvent(eventId)?.also {
// try to decrypt and force key request // try to decrypt and force key request
tryOrNull { bobSecondSession.cryptoService().decryptEvent(it.root, "") } tryOrNull { bobSecondSession.cryptoService().decryptEvent(it.root, "") }
} }

View file

@ -41,7 +41,7 @@ interface TimelineService {
* At the opposite of getTimeLineEventLive which will be updated when local echo event is synced, it will return null in this case. * At the opposite of getTimeLineEventLive which will be updated when local echo event is synced, it will return null in this case.
* @param eventId the eventId to get the TimelineEvent * @param eventId the eventId to get the TimelineEvent
*/ */
fun getTimeLineEvent(eventId: String): TimelineEvent? fun getTimelineEvent(eventId: String): TimelineEvent?
/** /**
* Creates a LiveData of Optional TimelineEvent event with eventId. * Creates a LiveData of Optional TimelineEvent event with eventId.
@ -49,7 +49,7 @@ interface TimelineService {
* In this case, makes sure to use the new synced eventId from the TimelineEvent class if you want to interact, as the local echo is removed from the SDK. * In this case, makes sure to use the new synced eventId from the TimelineEvent class if you want to interact, as the local echo is removed from the SDK.
* @param eventId the eventId to listen for TimelineEvent * @param eventId the eventId to listen for TimelineEvent
*/ */
fun getTimeLineEventLive(eventId: String): LiveData<Optional<TimelineEvent>> fun getTimelineEventLive(eventId: String): LiveData<Optional<TimelineEvent>>
/** /**
* Returns a snapshot list of TimelineEvent with EventType.MESSAGE and MessageType.MSGTYPE_IMAGE or MessageType.MSGTYPE_VIDEO. * Returns a snapshot list of TimelineEvent with EventType.MESSAGE and MessageType.MSGTYPE_IMAGE or MessageType.MSGTYPE_VIDEO.

View file

@ -513,7 +513,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
private fun getPollEvent(roomId: String, eventId: String): TimelineEvent? { private fun getPollEvent(roomId: String, eventId: String): TimelineEvent? {
val session = sessionManager.getSessionComponent(sessionId)?.session() val session = sessionManager.getSessionComponent(sessionId)?.session()
return session?.getRoom(roomId)?.getTimeLineEvent(eventId) ?: return null.also { return session?.getRoom(roomId)?.getTimelineEvent(eventId) ?: return null.also {
Timber.v("## POLL target poll event $eventId not found in room $roomId") Timber.v("## POLL target poll event $eventId not found in room $roomId")
} }
} }

View file

@ -30,15 +30,14 @@ import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.NoOpCancellable import org.matrix.android.sdk.api.util.NoOpCancellable
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.api.util.toOptional
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
import org.matrix.android.sdk.internal.database.mapper.asDomain import org.matrix.android.sdk.internal.database.mapper.asDomain
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity
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.relation.threads.FetchThreadTimelineTask import org.matrix.android.sdk.internal.session.room.relation.threads.FetchThreadTimelineTask
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.queue.EventSenderProcessor import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
import org.matrix.android.sdk.internal.session.room.timeline.TimelineEventDataSource
import org.matrix.android.sdk.internal.util.fetchCopyMap import org.matrix.android.sdk.internal.util.fetchCopyMap
import timber.log.Timber import timber.log.Timber
@ -50,7 +49,7 @@ internal class DefaultRelationService @AssistedInject constructor(
private val findReactionEventForUndoTask: FindReactionEventForUndoTask, private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
private val fetchEditHistoryTask: FetchEditHistoryTask, private val fetchEditHistoryTask: FetchEditHistoryTask,
private val fetchThreadTimelineTask: FetchThreadTimelineTask, private val fetchThreadTimelineTask: FetchThreadTimelineTask,
private val timelineEventMapper: TimelineEventMapper, private val timelineEventDataSource: TimelineEventDataSource,
@SessionDatabase private val monarchy: Monarchy @SessionDatabase private val monarchy: Monarchy
) : RelationService { ) : RelationService {
@ -60,14 +59,8 @@ internal class DefaultRelationService @AssistedInject constructor(
} }
override fun sendReaction(targetEventId: String, reaction: String): Cancelable { override fun sendReaction(targetEventId: String, reaction: String): Cancelable {
return if (monarchy val targetTimelineEvent = timelineEventDataSource.getTimelineEvent(roomId, targetEventId)
.fetchCopyMap( return if (targetTimelineEvent
{ realm ->
TimelineEventEntity.where(realm, roomId, targetEventId).findFirst()
},
{ entity, _ ->
timelineEventMapper.map(entity)
})
?.annotations ?.annotations
?.reactionsSummary ?.reactionsSummary
.orEmpty() .orEmpty()

View file

@ -21,36 +21,23 @@ import com.zhuinden.monarchy.Monarchy
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.realm.Sort
import io.realm.kotlin.where
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.session.events.model.isImageMessage
import org.matrix.android.sdk.api.session.events.model.isVideoMessage
import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineService import org.matrix.android.sdk.api.session.room.timeline.TimelineService
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.database.RealmSessionProvider
import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
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.TimelineEventEntityFields
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.di.UserId
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHandler import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHandler
import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler
import org.matrix.android.sdk.internal.task.TaskExecutor
internal class DefaultTimelineService @AssistedInject constructor( internal class DefaultTimelineService @AssistedInject constructor(
@Assisted private val roomId: String, @Assisted private val roomId: String,
@UserId private val userId: String,
@SessionDatabase private val monarchy: Monarchy, @SessionDatabase private val monarchy: Monarchy,
private val realmSessionProvider: RealmSessionProvider,
private val timelineInput: TimelineInput, private val timelineInput: TimelineInput,
private val taskExecutor: TaskExecutor,
private val contextOfEventTask: GetContextOfEventTask, private val contextOfEventTask: GetContextOfEventTask,
private val eventDecryptor: TimelineEventDecryptor, private val eventDecryptor: TimelineEventDecryptor,
private val paginationTask: PaginationTask, private val paginationTask: PaginationTask,
@ -60,7 +47,8 @@ internal class DefaultTimelineService @AssistedInject constructor(
private val threadsAwarenessHandler: ThreadsAwarenessHandler, private val threadsAwarenessHandler: ThreadsAwarenessHandler,
private val lightweightSettingsStorage: LightweightSettingsStorage, private val lightweightSettingsStorage: LightweightSettingsStorage,
private val readReceiptHandler: ReadReceiptHandler, private val readReceiptHandler: ReadReceiptHandler,
private val coroutineDispatchers: MatrixCoroutineDispatchers private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val timelineEventDataSource: TimelineEventDataSource
) : TimelineService { ) : TimelineService {
@AssistedFactory @AssistedFactory
@ -88,27 +76,15 @@ internal class DefaultTimelineService @AssistedInject constructor(
) )
} }
override fun getTimeLineEvent(eventId: String): TimelineEvent? { override fun getTimelineEvent(eventId: String): TimelineEvent? {
return realmSessionProvider.withRealm { realm -> return timelineEventDataSource.getTimelineEvent(roomId, eventId)
TimelineEventEntity.where(realm, roomId = roomId, eventId = eventId).findFirst()?.let {
timelineEventMapper.map(it)
}
}
} }
override fun getTimeLineEventLive(eventId: String): LiveData<Optional<TimelineEvent>> { override fun getTimelineEventLive(eventId: String): LiveData<Optional<TimelineEvent>> {
return LiveTimelineEvent(monarchy, taskExecutor.executorScope, timelineEventMapper, roomId, eventId) return timelineEventDataSource.getTimelineEventLive(roomId, eventId)
} }
override fun getAttachmentMessages(): List<TimelineEvent> { override fun getAttachmentMessages(): List<TimelineEvent> {
// TODO pretty bad query.. maybe we should denormalize clear type in base? return timelineEventDataSource.getAttachmentMessages(roomId)
return realmSessionProvider.withRealm { realm ->
realm.where<TimelineEventEntity>()
.equalTo(TimelineEventEntityFields.ROOM_ID, roomId)
.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.ASCENDING)
.findAll()
?.mapNotNull { timelineEventMapper.map(it).takeIf { it.root.isImageMessage() || it.root.isVideoMessage() } }
.orEmpty()
}
} }
} }

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2022 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.timeline
import androidx.lifecycle.LiveData
import com.zhuinden.monarchy.Monarchy
import io.realm.Sort
import io.realm.kotlin.where
import org.matrix.android.sdk.api.session.events.model.isImageMessage
import org.matrix.android.sdk.api.session.events.model.isVideoMessage
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.database.RealmSessionProvider
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.TimelineEventEntityFields
import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionDatabase
import org.matrix.android.sdk.internal.task.TaskExecutor
import javax.inject.Inject
internal class TimelineEventDataSource @Inject constructor(private val realmSessionProvider: RealmSessionProvider,
private val timelineEventMapper: TimelineEventMapper,
private val taskExecutor: TaskExecutor,
@SessionDatabase private val monarchy: Monarchy) {
fun getTimelineEvent(roomId: String, eventId: String): TimelineEvent? {
return realmSessionProvider.withRealm { realm ->
TimelineEventEntity.where(realm, roomId = roomId, eventId = eventId).findFirst()?.let {
timelineEventMapper.map(it)
}
}
}
fun getTimelineEventLive(roomId: String, eventId: String): LiveData<Optional<TimelineEvent>> {
return LiveTimelineEvent(monarchy, taskExecutor.executorScope, timelineEventMapper, roomId, eventId)
}
fun getAttachmentMessages(roomId: String): List<TimelineEvent> {
// TODO pretty bad query.. maybe we should denormalize clear type in base?
return realmSessionProvider.withRealm { realm ->
realm.where<TimelineEventEntity>()
.equalTo(TimelineEventEntityFields.ROOM_ID, roomId)
.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.ASCENDING)
.findAll()
?.mapNotNull { timelineEventMapper.map(it).takeIf { it.root.isImageMessage() || it.root.isVideoMessage() } }
.orEmpty()
}
}
}

View file

@ -213,7 +213,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
try { try {
val session = activeSessionHolder.getSafeActiveSession() ?: return false val session = activeSessionHolder.getSafeActiveSession() ?: return false
val room = session.getRoom(roomId) ?: return false val room = session.getRoom(roomId) ?: return false
return room.getTimeLineEvent(eventId) != null return room.getTimelineEvent(eventId) != null
} catch (e: Exception) { } catch (e: Exception) {
Timber.tag(loggerTag.value).e(e, "## isEventAlreadyKnown() : failed to check if the event was already defined") Timber.tag(loggerTag.value).e(e, "## isEventAlreadyKnown() : failed to check if the event was already defined")
} }

View file

@ -742,7 +742,7 @@ class TimelineViewModel @AssistedInject constructor(
} }
private fun handleRedactEvent(action: RoomDetailAction.RedactAction) { private fun handleRedactEvent(action: RoomDetailAction.RedactAction) {
val event = room.getTimeLineEvent(action.targetEventId) ?: return val event = room.getTimelineEvent(action.targetEventId) ?: return
room.redactEvent(event.root, action.reason) room.redactEvent(event.root, action.reason)
} }
@ -782,7 +782,7 @@ class TimelineViewModel @AssistedInject constructor(
} }
// We need to update this with the related m.replace also (to move read receipt) // We need to update this with the related m.replace also (to move read receipt)
action.event.annotations?.editSummary?.sourceEvents?.forEach { action.event.annotations?.editSummary?.sourceEvents?.forEach {
room.getTimeLineEvent(it)?.let { event -> room.getTimelineEvent(it)?.let { event ->
visibleEventsSource.post(RoomDetailAction.TimelineEventTurnsVisible(event)) visibleEventsSource.post(RoomDetailAction.TimelineEventTurnsVisible(event))
} }
} }
@ -886,7 +886,7 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleResendEvent(action: RoomDetailAction.ResendMessage) { private fun handleResendEvent(action: RoomDetailAction.ResendMessage) {
val targetEventId = action.eventId val targetEventId = action.eventId
room.getTimeLineEvent(targetEventId)?.let { room.getTimelineEvent(targetEventId)?.let {
// State must be UNDELIVERED or Failed // State must be UNDELIVERED or Failed
if (!it.root.sendState.hasFailed()) { if (!it.root.sendState.hasFailed()) {
Timber.e("Cannot resend message, it is not failed, Cancel first") Timber.e("Cannot resend message, it is not failed, Cancel first")
@ -904,7 +904,7 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleRemove(action: RoomDetailAction.RemoveFailedEcho) { private fun handleRemove(action: RoomDetailAction.RemoveFailedEcho) {
val targetEventId = action.eventId val targetEventId = action.eventId
room.getTimeLineEvent(targetEventId)?.let { room.getTimelineEvent(targetEventId)?.let {
// State must be UNDELIVERED or Failed // State must be UNDELIVERED or Failed
if (!it.root.sendState.hasFailed()) { if (!it.root.sendState.hasFailed()) {
Timber.e("Cannot resend message, it is not failed, Cancel first") Timber.e("Cannot resend message, it is not failed, Cancel first")
@ -920,7 +920,7 @@ class TimelineViewModel @AssistedInject constructor(
return return
} }
val targetEventId = action.eventId val targetEventId = action.eventId
room.getTimeLineEvent(targetEventId)?.let { room.getTimelineEvent(targetEventId)?.let {
// State must be in one of the sending states // State must be in one of the sending states
if (!it.root.sendState.isSending()) { if (!it.root.sendState.isSending()) {
Timber.e("Cannot cancel message, it is not sending") Timber.e("Cannot cancel message, it is not sending")
@ -1046,14 +1046,14 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleReRequestKeys(action: RoomDetailAction.ReRequestKeys) { private fun handleReRequestKeys(action: RoomDetailAction.ReRequestKeys) {
// Check if this request is still active and handled by me // Check if this request is still active and handled by me
room.getTimeLineEvent(action.eventId)?.let { room.getTimelineEvent(action.eventId)?.let {
session.cryptoService().reRequestRoomKeyForEvent(it.root) session.cryptoService().reRequestRoomKeyForEvent(it.root)
_viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.e2e_re_request_encryption_key_dialog_content))) _viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.e2e_re_request_encryption_key_dialog_content)))
} }
} }
private fun handleTapOnFailedToDecrypt(action: RoomDetailAction.TapOnFailedToDecrypt) { private fun handleTapOnFailedToDecrypt(action: RoomDetailAction.TapOnFailedToDecrypt) {
room.getTimeLineEvent(action.eventId)?.let { room.getTimelineEvent(action.eventId)?.let {
val code = when (it.root.mCryptoError) { val code = when (it.root.mCryptoError) {
MXCryptoError.ErrorType.KEYS_WITHHELD -> { MXCryptoError.ErrorType.KEYS_WITHHELD -> {
WithHeldCode.fromCode(it.root.mCryptoErrorReason) WithHeldCode.fromCode(it.root.mCryptoErrorReason)
@ -1069,7 +1069,7 @@ class TimelineViewModel @AssistedInject constructor(
// Do not allow to vote unsent local echo of the poll event // Do not allow to vote unsent local echo of the poll event
if (LocalEcho.isLocalEchoId(action.eventId)) return if (LocalEcho.isLocalEchoId(action.eventId)) return
// Do not allow to vote the same option twice // Do not allow to vote the same option twice
room.getTimeLineEvent(action.eventId)?.let { pollTimelineEvent -> room.getTimelineEvent(action.eventId)?.let { pollTimelineEvent ->
val currentVote = pollTimelineEvent.annotations?.pollResponseSummary?.aggregatedContent?.myVote val currentVote = pollTimelineEvent.annotations?.pollResponseSummary?.aggregatedContent?.myVote
if (currentVote != action.optionKey) { if (currentVote != action.optionKey) {
room.voteToPoll(action.eventId, action.optionKey) room.voteToPoll(action.eventId, action.optionKey)

View file

@ -143,7 +143,7 @@ class MessageComposerViewModel @AssistedInject constructor(
} }
private fun handleEnterEditMode(action: MessageComposerAction.EnterEditMode) { private fun handleEnterEditMode(action: MessageComposerAction.EnterEditMode) {
room.getTimeLineEvent(action.eventId)?.let { timelineEvent -> room.getTimelineEvent(action.eventId)?.let { timelineEvent ->
setState { copy(sendMode = SendMode.Edit(timelineEvent, timelineEvent.getTextEditableContent())) } setState { copy(sendMode = SendMode.Edit(timelineEvent, timelineEvent.getTextEditableContent())) }
} }
} }
@ -175,13 +175,13 @@ class MessageComposerViewModel @AssistedInject constructor(
} }
private fun handleEnterQuoteMode(action: MessageComposerAction.EnterQuoteMode) { private fun handleEnterQuoteMode(action: MessageComposerAction.EnterQuoteMode) {
room.getTimeLineEvent(action.eventId)?.let { timelineEvent -> room.getTimelineEvent(action.eventId)?.let { timelineEvent ->
setState { copy(sendMode = SendMode.Quote(timelineEvent, action.text)) } setState { copy(sendMode = SendMode.Quote(timelineEvent, action.text)) }
} }
} }
private fun handleEnterReplyMode(action: MessageComposerAction.EnterReplyMode) { private fun handleEnterReplyMode(action: MessageComposerAction.EnterReplyMode) {
room.getTimeLineEvent(action.eventId)?.let { timelineEvent -> room.getTimelineEvent(action.eventId)?.let { timelineEvent ->
setState { copy(sendMode = SendMode.Reply(timelineEvent, action.text)) } setState { copy(sendMode = SendMode.Reply(timelineEvent, action.text)) }
} }
} }
@ -479,7 +479,7 @@ class MessageComposerViewModel @AssistedInject constructor(
if (inReplyTo != null) { if (inReplyTo != null) {
// TODO check if same content? // TODO check if same content?
room.getTimeLineEvent(inReplyTo)?.let { room.getTimelineEvent(inReplyTo)?.let {
room.editReply(state.sendMode.timelineEvent, it, action.text.toString()) room.editReply(state.sendMode.timelineEvent, it, action.text.toString())
} }
} else { } else {
@ -555,17 +555,17 @@ class MessageComposerViewModel @AssistedInject constructor(
sendMode = when (currentDraft) { sendMode = when (currentDraft) {
is UserDraft.Regular -> SendMode.Regular(currentDraft.content, false) is UserDraft.Regular -> SendMode.Regular(currentDraft.content, false)
is UserDraft.Quote -> { is UserDraft.Quote -> {
room.getTimeLineEvent(currentDraft.linkedEventId)?.let { timelineEvent -> room.getTimelineEvent(currentDraft.linkedEventId)?.let { timelineEvent ->
SendMode.Quote(timelineEvent, currentDraft.content) SendMode.Quote(timelineEvent, currentDraft.content)
} }
} }
is UserDraft.Reply -> { is UserDraft.Reply -> {
room.getTimeLineEvent(currentDraft.linkedEventId)?.let { timelineEvent -> room.getTimelineEvent(currentDraft.linkedEventId)?.let { timelineEvent ->
SendMode.Reply(timelineEvent, currentDraft.content) SendMode.Reply(timelineEvent, currentDraft.content)
} }
} }
is UserDraft.Edit -> { is UserDraft.Edit -> {
room.getTimeLineEvent(currentDraft.linkedEventId)?.let { timelineEvent -> room.getTimelineEvent(currentDraft.linkedEventId)?.let { timelineEvent ->
SendMode.Edit(timelineEvent, currentDraft.content) SendMode.Edit(timelineEvent, currentDraft.content)
} }
} }

View file

@ -65,7 +65,7 @@ class VerificationItemFactory @Inject constructor(
?: return ignoredConclusion(params) ?: return ignoredConclusion(params)
// If we cannot find the referenced request we do not display the done event // If we cannot find the referenced request we do not display the done event
val refEvent = session.getRoom(event.root.roomId ?: "")?.getTimeLineEvent(refEventId) val refEvent = session.getRoom(event.root.roomId ?: "")?.getTimelineEvent(refEventId)
?: return ignoredConclusion(params) ?: return ignoredConclusion(params)
// If it's not a request ignore this event // If it's not a request ignore this event

View file

@ -86,7 +86,7 @@ class ViewReactionsViewModel @AssistedInject constructor(@Assisted
annotationsSummary.reactionsSummary annotationsSummary.reactionsSummary
.flatMap { reactionsSummary -> .flatMap { reactionsSummary ->
reactionsSummary.sourceEvents.map { reactionsSummary.sourceEvents.map {
val event = room.getTimeLineEvent(it) val event = room.getTimelineEvent(it)
?: throw RuntimeException("Your eventId is not valid") ?: throw RuntimeException("Your eventId is not valid")
ReactionInfo( ReactionInfo(
event.root.eventId!!, event.root.eventId!!,

View file

@ -81,7 +81,7 @@ class DataAttachmentRoomProvider(
override fun getTimelineEventAtPosition(position: Int): TimelineEvent? { override fun getTimelineEventAtPosition(position: Int): TimelineEvent? {
val item = getItem(position) val item = getItem(position)
return room?.getTimeLineEvent(item.eventId) return room?.getTimelineEvent(item.eventId)
} }
override suspend fun getFileForSharing(position: Int): File? { override suspend fun getFileForSharing(position: Int): File? {

View file

@ -65,7 +65,7 @@ class NotifiableEventResolver @Inject constructor(
if (event.getClearType() == EventType.STATE_ROOM_MEMBER) { if (event.getClearType() == EventType.STATE_ROOM_MEMBER) {
return resolveStateRoomEvent(event, session, canBeReplaced = false, isNoisy = isNoisy) return resolveStateRoomEvent(event, session, canBeReplaced = false, isNoisy = isNoisy)
} }
val timelineEvent = session.getRoom(roomID)?.getTimeLineEvent(eventId) ?: return null val timelineEvent = session.getRoom(roomID)?.getTimelineEvent(eventId) ?: return null
return when (event.getClearType()) { return when (event.getClearType()) {
EventType.MESSAGE, EventType.MESSAGE,
EventType.ENCRYPTED -> { EventType.ENCRYPTED -> {

View file

@ -89,7 +89,7 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
val rootThreadEventId = permalinkData.eventId?.let { eventId -> val rootThreadEventId = permalinkData.eventId?.let { eventId ->
val room = roomId?.let { session?.getRoom(it) } val room = roomId?.let { session?.getRoom(it) }
room?.getTimeLineEvent(eventId)?.root?.getRootThreadEventId() room?.getTimelineEvent(eventId)?.root?.getRootThreadEventId()
} }
openRoom( openRoom(
navigationInterceptor, navigationInterceptor,

View file

@ -68,7 +68,7 @@ class CreatePollViewModel @AssistedInject constructor(
} }
private fun initializeEditedPoll(eventId: String) { private fun initializeEditedPoll(eventId: String) {
val event = room.getTimeLineEvent(eventId) ?: return val event = room.getTimelineEvent(eventId) ?: return
val content = event.getLastMessageContent() as? MessagePollContent ?: return val content = event.getLastMessageContent() as? MessagePollContent ?: return
val pollType = content.pollCreationInfo?.kind ?: PollType.DISCLOSED val pollType = content.pollCreationInfo?.kind ?: PollType.DISCLOSED
@ -115,7 +115,7 @@ class CreatePollViewModel @AssistedInject constructor(
} }
private fun sendEditedPoll(editedEventId: String, pollType: PollType, question: String, options: List<String>) { private fun sendEditedPoll(editedEventId: String, pollType: PollType, question: String, options: List<String>) {
val editedEvent = room.getTimeLineEvent(editedEventId) ?: return val editedEvent = room.getTimelineEvent(editedEventId) ?: return
room.editPoll(editedEvent, pollType, question, options) room.editPoll(editedEvent, pollType, question, options)
} }