Skip to content

Commit

Permalink
Merge branch 'element-hq:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
daedric7 authored Oct 18, 2024
2 parents 65ef535 + b0df319 commit cdd80b7
Show file tree
Hide file tree
Showing 46 changed files with 457 additions and 650 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import io.element.android.features.location.impl.common.permissions.PermissionsS
import io.element.android.features.messages.test.FakeMessageComposerContext
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.textcomposer.model.MessageComposerMode
Expand Down Expand Up @@ -397,8 +399,7 @@ class SendLocationPresenterTest {
)
fakeMessageComposerContext.apply {
composerMode = MessageComposerMode.Edit(
eventId = null,
transactionId = null,
eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(),
content = ""
)
}
Expand Down Expand Up @@ -446,8 +447,7 @@ class SendLocationPresenterTest {
)
fakeMessageComposerContext.apply {
composerMode = MessageComposerMode.Edit(
eventId = null,
transactionId = null,
eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(),
content = ""
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ package io.element.android.features.messages.impl

import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId

sealed interface MessagesEvents {
data class HandleAction(val action: TimelineItemAction, val event: TimelineItem.Event) : MessagesEvents
data class ToggleReaction(val emoji: String, val uniqueId: UniqueId) : MessagesEvents
data class ToggleReaction(val emoji: String, val eventOrTransactionId: EventOrTransactionId) : MessagesEvents
data class InviteDialogDismissed(val action: InviteDialogAction) : MessagesEvents
data object Dismiss : MessagesEvents
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
Expand All @@ -73,6 +72,7 @@ import io.element.android.libraries.matrix.api.room.powerlevels.canPinUnpin
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn
import io.element.android.libraries.matrix.api.room.powerlevels.canSendMessage
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
import io.element.android.libraries.matrix.ui.messages.reply.map
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.matrix.ui.room.canCall
Expand Down Expand Up @@ -191,7 +191,7 @@ class MessagesPresenter @AssistedInject constructor(
)
}
is MessagesEvents.ToggleReaction -> {
localCoroutineScope.toggleReaction(event.emoji, event.uniqueId)
localCoroutineScope.toggleReaction(event.emoji, event.eventOrTransactionId)
}
is MessagesEvents.InviteDialogDismissed -> {
hasDismissedInviteDialog = true
Expand Down Expand Up @@ -327,10 +327,10 @@ class MessagesPresenter @AssistedInject constructor(

private fun CoroutineScope.toggleReaction(
emoji: String,
uniqueId: UniqueId,
eventOrTransactionId: EventOrTransactionId,
) = launch(dispatchers.io) {
timelineController.invokeOnCurrentTimeline {
toggleReaction(emoji, uniqueId)
toggleReaction(emoji, eventOrTransactionId)
.onFailure { Timber.e(it) }
}
}
Expand Down Expand Up @@ -360,7 +360,7 @@ class MessagesPresenter @AssistedInject constructor(

private suspend fun handleActionRedact(event: TimelineItem.Event) {
timelineController.invokeOnCurrentTimeline {
redactEvent(eventId = event.eventId, transactionId = event.transactionId, reason = null)
redactEvent(eventOrTransactionId = event.eventOrTransactionId, reason = null)
.onFailure { Timber.e(it) }
}
}
Expand All @@ -377,8 +377,7 @@ class MessagesPresenter @AssistedInject constructor(
}
else -> {
val composerMode = MessageComposerMode.Edit(
targetEvent.eventId,
targetEvent.transactionId,
targetEvent.eventOrTransactionId,
(targetEvent.content as? TimelineItemTextBasedContent)?.let {
if (enableTextFormatting) {
it.htmlBody ?: it.body
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ fun MessagesView(
}

fun onEmojiReactionClick(emoji: String, event: TimelineItem.Event) {
state.eventSink(MessagesEvents.ToggleReaction(emoji, event.id))
state.eventSink(MessagesEvents.ToggleReaction(emoji, event.eventOrTransactionId))
}

fun onEmojiReactionLongClick(emoji: String, event: TimelineItem.Event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.timeline.TimelineException
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
import io.element.android.libraries.matrix.ui.messages.RoomMemberProfilesCache
import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails
import io.element.android.libraries.matrix.ui.messages.reply.map
Expand Down Expand Up @@ -442,12 +443,11 @@ class MessageComposerPresenter @Inject constructor(
intentionalMentions = message.intentionalMentions
)
is MessageComposerMode.Edit -> {
val eventId = capturedMode.eventId
val transactionId = capturedMode.transactionId
timelineController.invokeOnCurrentTimeline {
// First try to edit the message in the current timeline
editMessage(eventId, transactionId, message.markdown, message.html, message.intentionalMentions)
editMessage(capturedMode.eventOrTransactionId, message.markdown, message.html, message.intentionalMentions)
.onFailure { cause ->
val eventId = capturedMode.eventOrTransactionId.eventId
if (cause is TimelineException.EventNotFound && eventId != null) {
// if the event is not found in the timeline, try to edit the message directly
room.editMessage(eventId, message.markdown, message.html, message.intentionalMentions)
Expand Down Expand Up @@ -581,8 +581,7 @@ class MessageComposerPresenter @Inject constructor(
when (val draftType = draft.draftType) {
ComposerDraftType.NewMessage -> messageComposerContext.composerMode = MessageComposerMode.Normal
is ComposerDraftType.Edit -> messageComposerContext.composerMode = MessageComposerMode.Edit(
eventId = draftType.eventId,
transactionId = null,
eventOrTransactionId = draftType.eventId.toEventOrTransactionId(),
content = htmlText ?: markdownText
)
is ComposerDraftType.Reply -> {
Expand Down Expand Up @@ -611,7 +610,7 @@ class MessageComposerPresenter @Inject constructor(
val draftType = when (val mode = messageComposerContext.composerMode) {
is MessageComposerMode.Normal -> ComposerDraftType.NewMessage
is MessageComposerMode.Edit -> {
mode.eventId?.let { eventId -> ComposerDraftType.Edit(eventId) }
mode.eventOrTransactionId.eventId?.let { eventId -> ComposerDraftType.Edit(eventId) }
}
is MessageComposerMode.Reply -> ComposerDraftType.Reply(mode.eventId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import androidx.compose.ui.Modifier
import io.element.android.emojibasebindings.Emoji
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.hide
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CustomReactionBottomSheet(
state: CustomReactionState,
onSelectEmoji: (UniqueId, Emoji) -> Unit,
onSelectEmoji: (EventOrTransactionId, Emoji) -> Unit,
modifier: Modifier = Modifier,
) {
val sheetState = rememberModalBottomSheetState()
Expand All @@ -37,7 +37,7 @@ fun CustomReactionBottomSheet(
if (target?.event == null) return
sheetState.hide(coroutineScope) {
state.eventSink(CustomReactionEvents.DismissCustomReactionSheet)
onSelectEmoji(target.event.id, emoji)
onSelectEmoji(target.event.eventOrTransactionId, emoji)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShieldProvider
Expand Down Expand Up @@ -92,6 +93,9 @@ sealed interface TimelineItem {

val isRemote = eventId != null

val eventOrTransactionId: EventOrTransactionId
get() = EventOrTransactionId.from(eventId = eventId, transactionId = transactionId)

// No need to be lazy here?
val messageShield: MessageShield? = messageShieldProvider(strict = false)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,21 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
Expand Down Expand Up @@ -164,8 +163,9 @@ class MessagesPresenterTest {
@Test
fun `present - handle toggling a reaction`() = runTest {
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
val toggleReactionSuccess = lambdaRecorder { _: String, _: UniqueId -> Result.success(Unit) }
val toggleReactionFailure = lambdaRecorder { _: String, _: UniqueId -> Result.failure<Unit>(IllegalStateException("Failed to send reaction")) }
val toggleReactionSuccess = lambdaRecorder { _: String, _: EventOrTransactionId -> Result.success(Unit) }
val toggleReactionFailure =
lambdaRecorder { _: String, _: EventOrTransactionId -> Result.failure<Unit>(IllegalStateException("Failed to send reaction")) }

val timeline = FakeTimeline().apply {
this.toggleReactionLambda = toggleReactionSuccess
Expand All @@ -185,23 +185,23 @@ class MessagesPresenterTest {
}.test {
skipItems(1)
val initialState = awaitItem()
initialState.eventSink(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId()))
assert(toggleReactionSuccess)
.isCalledOnce()
.with(value("👍"), value(A_UNIQUE_ID))
.with(value("👍"), value(AN_EVENT_ID.toEventOrTransactionId()))
// No crashes when sending a reaction failed
timeline.apply { toggleReactionLambda = toggleReactionFailure }
initialState.eventSink(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId()))
assert(toggleReactionFailure)
.isCalledOnce()
.with(value("👍"), value(A_UNIQUE_ID))
.with(value("👍"), value(AN_EVENT_ID.toEventOrTransactionId()))
}
}

@Test
fun `present - handle toggling a reaction twice`() = runTest {
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
val toggleReactionSuccess = lambdaRecorder { _: String, _: UniqueId -> Result.success(Unit) }
val toggleReactionSuccess = lambdaRecorder { _: String, _: EventOrTransactionId -> Result.success(Unit) }

val timeline = FakeTimeline().apply {
this.toggleReactionLambda = toggleReactionSuccess
Expand All @@ -220,13 +220,13 @@ class MessagesPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
initialState.eventSink(MessagesEvents.ToggleReaction("👍", A_UNIQUE_ID))
initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId()))
initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId()))
assert(toggleReactionSuccess)
.isCalledExactly(2)
.withSequence(
listOf(value("👍"), value(A_UNIQUE_ID)),
listOf(value("👍"), value(A_UNIQUE_ID)),
listOf(value("👍"), value(AN_EVENT_ID.toEventOrTransactionId())),
listOf(value("👍"), value(AN_EVENT_ID.toEventOrTransactionId())),
)
skipItems(1)
}
Expand Down Expand Up @@ -452,8 +452,7 @@ class MessagesPresenterTest {
composerRecorder.assertSingle(
MessageComposerEvents.SetMode(
composerMode = MessageComposerMode.Edit(
eventId = AN_EVENT_ID,
transactionId = null,
eventOrTransactionId = AN_EVENT_ID.toEventOrTransactionId(),
content = (aMessageEvent().content as TimelineItemTextContent).body
)
)
Expand Down Expand Up @@ -506,7 +505,7 @@ class MessagesPresenterTest {
canUserPinUnpinResult = { Result.success(true) },
)

val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(Unit) }
val redactEventLambda = lambdaRecorder { _: EventOrTransactionId, _: String? -> Result.success(Unit) }
liveTimeline.redactEventLambda = redactEventLambda
val presenter = createMessagesPresenter(
matrixRoom = matrixRoom,
Expand All @@ -521,7 +520,7 @@ class MessagesPresenterTest {
awaitItem()
assert(redactEventLambda)
.isCalledOnce()
.with(value(messageEvent.eventId), value(messageEvent.transactionId), value(null))
.with(value(messageEvent.eventOrTransactionId), value(null))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ class MessagesViewTest {
state = state,
)
rule.onAllNodesWithText("👍️").onFirst().performClick()
eventsRecorder.assertSingle(MessagesEvents.ToggleReaction("👍️", timelineItem.id))
eventsRecorder.assertSingle(MessagesEvents.ToggleReaction("👍️", timelineItem.eventOrTransactionId))
}

@Test
Expand Down Expand Up @@ -484,7 +484,7 @@ class MessagesViewTest {
// Give time for the close animation to complete
rule.mainClock.advanceTimeBy(milliseconds = 1_000)
customReactionStateEventsRecorder.assertSingle(CustomReactionEvents.DismissCustomReactionSheet)
eventsRecorder.assertSingle(MessagesEvents.ToggleReaction(aUnicode, timelineItem.id))
eventsRecorder.assertSingle(MessagesEvents.ToggleReaction(aUnicode, timelineItem.eventOrTransactionId))
}

@Test
Expand Down
Loading

0 comments on commit cdd80b7

Please sign in to comment.