Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import io.element.android.libraries.matrix.api.core.EventId

sealed interface MessagesEvents {
data class HandleAction(val action: TimelineItemAction, val event: TimelineItem.Event) : MessagesEvents
data class ToggleReaction(val emoji: String, val eventId: EventId) : MessagesEvents
data class ToggleReaction(val reaction: String, val eventId: EventId) : 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 @@ -208,7 +208,7 @@ class MessagesPresenter @AssistedInject constructor(
)
}
is MessagesEvents.ToggleReaction -> {
localCoroutineScope.toggleReaction(event.emoji, event.eventId)
localCoroutineScope.toggleReaction(event.reaction, event.eventId)
}
is MessagesEvents.InviteDialogDismissed -> {
hasDismissedInviteDialog = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemList
import io.element.android.features.messages.impl.timeline.aTimelineState
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState
import io.element.android.features.messages.impl.timeline.components.customreaction.EmojiPickerState
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents
Expand All @@ -42,6 +43,7 @@ import io.element.android.features.messages.impl.voicemessages.composer.aVoiceMe
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.textcomposer.aRichTextEditorState
import io.element.android.libraries.textcomposer.model.MessageComposerMode
Expand Down Expand Up @@ -160,6 +162,7 @@ fun aCustomReactionState(
target = target,
selectedEmoji = persistentSetOf(),
eventSink = eventSink,
searchState = EmojiPickerState(false, "", SearchBarResultState.Initial()) {}
)

fun aReadReceiptBottomSheetState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ fun MessagesView(
state = state.customReactionState,
onEmojiSelected = { eventId, emoji ->
state.eventSink(MessagesEvents.ToggleReaction(emoji.unicode, eventId))
},
onReactionSelected = { eventId, reaction ->
state.eventSink(MessagesEvents.ToggleReaction(reaction, eventId))
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,16 @@ fun MessagesReactionButton(

@Immutable
sealed interface MessagesReactionsButtonContent {
data class Text(val text: String) : MessagesReactionsButtonContent
data class Text(val text: String, val highlight: Boolean = false) : MessagesReactionsButtonContent
data class Icon(@DrawableRes val resourceId: Int) : MessagesReactionsButtonContent

data class Reaction(val reaction: AggregatedReaction) : MessagesReactionsButtonContent

val isHighlighted get() = this is Reaction && reaction.isHighlighted
val isHighlighted get() = when(this) {
is Reaction -> reaction.isHighlighted
is Text -> highlight
else -> false
}
}

internal val REACTION_EMOJI_LINE_HEIGHT = 20.sp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import io.element.android.libraries.matrix.api.core.EventId
fun CustomReactionBottomSheet(
state: CustomReactionState,
onEmojiSelected: (EventId, Emoji) -> Unit,
onReactionSelected: (EventId, String) -> Unit,
modifier: Modifier = Modifier,
) {
val sheetState = rememberModalBottomSheetState()
Expand All @@ -50,16 +51,26 @@ fun CustomReactionBottomSheet(
}
}

fun onReactionSelectedDismiss(reaction: String) {
if (target?.event?.eventId == null) return
sheetState.hide(coroutineScope) {
state.eventSink(CustomReactionEvents.DismissCustomReactionSheet)
onReactionSelected(target.event.eventId, reaction)
}
}

if (target?.emojibaseStore != null && target.event.eventId != null) {
ModalBottomSheet(
onDismissRequest = ::onDismiss,
sheetState = sheetState,
modifier = modifier
modifier = modifier,
) {
EmojiPicker(
onEmojiSelected = ::onEmojiSelectedDismiss,
onReactionSelected = ::onReactionSelectedDismiss,
emojibaseStore = target.emojibaseStore,
selectedEmojis = state.selectedEmoji,
state = state.searchState,
modifier = Modifier.fillMaxSize(),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ import kotlinx.coroutines.launch
import javax.inject.Inject

class CustomReactionPresenter @Inject constructor(
private val emojibaseProvider: EmojibaseProvider
private val emojibaseProvider: EmojibaseProvider,
private val emojiPickerStatePresenter: EmojiPickerStatePresenter,
) : Presenter<CustomReactionState> {
@Composable
override fun present(): CustomReactionState {
val target: MutableState<CustomReactionState.Target> = remember {
mutableStateOf(CustomReactionState.Target.None)
}
val searchState = emojiPickerStatePresenter.present()

val localCoroutineScope = rememberCoroutineScope()
fun handleShowCustomReactionSheet(event: TimelineItem.Event) {
Expand All @@ -49,6 +51,7 @@ class CustomReactionPresenter @Inject constructor(

fun handleDismissCustomReactionSheet() {
target.value = CustomReactionState.Target.None
searchState.eventSink(EmojiPickerEvents.Reset)
}

fun handleEvents(event: CustomReactionEvents) {
Expand All @@ -57,6 +60,7 @@ class CustomReactionPresenter @Inject constructor(
is CustomReactionEvents.DismissCustomReactionSheet -> handleDismissCustomReactionSheet()
}
}

val event = (target.value as? CustomReactionState.Target.Success)?.event
val selectedEmoji = event
?.reactionsState
Expand All @@ -67,7 +71,8 @@ class CustomReactionPresenter @Inject constructor(
return CustomReactionState(
target = target.value,
selectedEmoji = selectedEmoji,
eventSink = { handleEvents(it) }
eventSink = ::handleEvents,
searchState = searchState,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ data class CustomReactionState(
val target: Target,
val selectedEmoji: ImmutableSet<String>,
val eventSink: (CustomReactionEvents) -> Unit,
val searchState: EmojiPickerState,
) {
sealed interface Target {
data object None : Target
Expand Down
Loading