Pinned messages: clean code
This commit is contained in:
@@ -34,7 +34,6 @@ import com.bumble.appyx.core.node.Node
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import com.bumble.appyx.core.plugin.plugins
|
||||
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||
import com.bumble.appyx.navmodel.backstack.operation.pop
|
||||
import com.bumble.appyx.navmodel.backstack.operation.push
|
||||
import com.bumble.appyx.navmodel.backstack.operation.replace
|
||||
import com.bumble.appyx.navmodel.backstack.operation.singleTop
|
||||
|
||||
@@ -29,7 +29,6 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkData
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
interface MessagesEntryPoint : FeatureEntryPoint {
|
||||
|
||||
sealed interface InitialTarget : Parcelable {
|
||||
@Parcelize
|
||||
data class Messages(val focusedEventId: EventId?) : InitialTarget
|
||||
|
||||
@@ -48,7 +48,6 @@ class DefaultMessagesEntryPoint @Inject constructor() : MessagesEntryPoint {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun MessagesEntryPoint.InitialTarget.toNavTarget() = when (this) {
|
||||
is MessagesEntryPoint.InitialTarget.Messages -> MessagesFlowNode.NavTarget.Messages(focusedEventId)
|
||||
MessagesEntryPoint.InitialTarget.PinnedMessages -> MessagesFlowNode.NavTarget.PinnedMessagesList
|
||||
|
||||
@@ -58,7 +58,6 @@ import io.element.android.features.poll.api.create.CreatePollEntryPoint
|
||||
import io.element.android.features.poll.api.create.CreatePollMode
|
||||
import io.element.android.libraries.architecture.BackstackWithOverlayBox
|
||||
import io.element.android.libraries.architecture.BaseFlowNode
|
||||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.architecture.overlay.Overlay
|
||||
@@ -114,7 +113,6 @@ class MessagesFlowNode @AssistedInject constructor(
|
||||
buildContext = buildContext,
|
||||
plugins = plugins
|
||||
) {
|
||||
|
||||
sealed interface NavTarget : Parcelable {
|
||||
@Parcelize
|
||||
data object Empty : NavTarget
|
||||
|
||||
@@ -199,8 +199,6 @@ class MessagesNode @AssistedInject constructor(
|
||||
callbacks.forEach { it.onJoinCallClick(room.roomId) }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val context = LocalContext.current
|
||||
|
||||
@@ -66,10 +66,9 @@ class DefaultActionListPresenter @AssistedInject constructor(
|
||||
private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled,
|
||||
private val room: MatrixRoom,
|
||||
) : ActionListPresenter {
|
||||
|
||||
@AssistedFactory
|
||||
@ContributesBinding(RoomScope::class)
|
||||
interface Factory: ActionListPresenter.Factory {
|
||||
interface Factory : ActionListPresenter.Factory {
|
||||
override fun create(postProcessor: TimelineItemActionPostProcessor): DefaultActionListPresenter
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ sealed class TimelineItemAction(
|
||||
@DrawableRes val icon: Int,
|
||||
val destructive: Boolean = false
|
||||
) {
|
||||
data object ViewInTimeline: TimelineItemAction(CommonStrings.action_view_in_timeline, CompoundDrawables.ic_compound_visibility_on)
|
||||
data object ViewInTimeline : TimelineItemAction(CommonStrings.action_view_in_timeline, CompoundDrawables.ic_compound_visibility_on)
|
||||
data object Forward : TimelineItemAction(CommonStrings.action_forward, CompoundDrawables.ic_compound_forward)
|
||||
data object Copy : TimelineItemAction(CommonStrings.action_copy, CompoundDrawables.ic_compound_copy)
|
||||
data object CopyLink : TimelineItemAction(CommonStrings.action_copy_link_to_message, CompoundDrawables.ic_compound_link)
|
||||
|
||||
@@ -24,5 +24,4 @@ fun interface TimelineItemActionPostProcessor {
|
||||
return actions
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,11 +34,9 @@ import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
|
||||
import io.element.android.libraries.roomselect.api.RoomSelectEntryPoint
|
||||
import io.element.android.libraries.roomselect.api.RoomSelectMode
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@ContributesNode(RoomScope::class)
|
||||
|
||||
@@ -18,7 +18,6 @@ package io.element.android.features.messages.impl.forward
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
@@ -28,16 +27,12 @@ import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
|
||||
import io.element.android.libraries.matrix.api.timeline.getActiveTimeline
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import java.sql.Time
|
||||
|
||||
class ForwardMessagesPresenter @AssistedInject constructor(
|
||||
@Assisted eventId: String,
|
||||
|
||||
@@ -58,7 +58,8 @@ class PinnedEventsTimelineProvider @Inject constructor(
|
||||
networkMonitor.connectivity
|
||||
) {
|
||||
// do not use connectivity here as data can be loaded from cache, it's just to trigger retry if needed
|
||||
isEnabled, _ -> isEnabled
|
||||
isEnabled, _ ->
|
||||
isEnabled
|
||||
}
|
||||
.onEach { isFeatureEnabled ->
|
||||
if (isFeatureEnabled) {
|
||||
|
||||
@@ -30,7 +30,6 @@ import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories
|
||||
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories
|
||||
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactory
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||
import io.element.android.libraries.androidutils.system.openUrlInExternalApp
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
@@ -48,7 +47,6 @@ class PinnedMessagesListNode @AssistedInject constructor(
|
||||
private val timelineItemPresenterFactories: TimelineItemPresenterFactories,
|
||||
private val permalinkParser: PermalinkParser,
|
||||
) : Node(buildContext, plugins = plugins), PinnedMessagesListNavigator {
|
||||
|
||||
interface Callback : Plugin {
|
||||
fun onEventClick(event: TimelineItem.Event)
|
||||
fun onUserDataClick(userId: UserId)
|
||||
|
||||
@@ -69,7 +69,6 @@ class PinnedMessagesListPresenter @AssistedInject constructor(
|
||||
private val snackbarDispatcher: SnackbarDispatcher,
|
||||
actionListPresenterFactory: ActionListPresenter.Factory,
|
||||
) : Presenter<PinnedMessagesListState> {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(navigator: PinnedMessagesListNavigator): PinnedMessagesListPresenter
|
||||
|
||||
@@ -20,7 +20,6 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc
|
||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
|
||||
|
||||
object PinnedMessagesListTimelineActionPostProcessor : TimelineItemActionPostProcessor {
|
||||
|
||||
override fun process(actions: List<TimelineItemAction>): List<TimelineItemAction> {
|
||||
return buildList {
|
||||
add(TimelineItemAction.ViewInTimeline)
|
||||
|
||||
@@ -46,7 +46,6 @@ import io.element.android.libraries.matrix.api.room.MessageEventType
|
||||
import io.element.android.libraries.matrix.api.room.isDm
|
||||
import io.element.android.libraries.matrix.api.room.roomMembers
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.matrix.api.timeline.getActiveTimeline
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin
|
||||
import io.element.android.libraries.matrix.ui.room.canSendMessageAsState
|
||||
|
||||
@@ -20,7 +20,6 @@ import androidx.compose.runtime.Immutable
|
||||
import io.element.android.features.messages.impl.timeline.model.NewEventState
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlin.time.Duration
|
||||
|
||||
@@ -34,7 +34,6 @@ 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.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
|
||||
|
||||
@@ -59,15 +59,16 @@ fun TimelineItemGroupedEventsRow(
|
||||
onReadReceiptClick: (TimelineItem.Event) -> Unit,
|
||||
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange ->
|
||||
TimelineItemEventContentView(
|
||||
content = event.content,
|
||||
onLinkClick = onLinkClick,
|
||||
eventSink = eventSink,
|
||||
modifier = contentModifier,
|
||||
onContentLayoutChange = onContentLayoutChange
|
||||
)
|
||||
},
|
||||
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit =
|
||||
{ event, contentModifier, onContentLayoutChange ->
|
||||
TimelineItemEventContentView(
|
||||
content = event.content,
|
||||
onLinkClick = onLinkClick,
|
||||
eventSink = eventSink,
|
||||
modifier = contentModifier,
|
||||
onContentLayoutChange = onContentLayoutChange
|
||||
)
|
||||
},
|
||||
) {
|
||||
val isExpanded = rememberSaveable(key = timelineItem.identifier().value) { mutableStateOf(false) }
|
||||
|
||||
@@ -120,15 +121,16 @@ private fun TimelineItemGroupedEventsRowContent(
|
||||
onReadReceiptClick: (TimelineItem.Event) -> Unit,
|
||||
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange ->
|
||||
TimelineItemEventContentView(
|
||||
content = event.content,
|
||||
onLinkClick = onLinkClick,
|
||||
eventSink = eventSink,
|
||||
modifier = contentModifier,
|
||||
onContentLayoutChange = onContentLayoutChange
|
||||
)
|
||||
},
|
||||
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit =
|
||||
{ event, contentModifier, onContentLayoutChange ->
|
||||
TimelineItemEventContentView(
|
||||
content = event.content,
|
||||
onLinkClick = onLinkClick,
|
||||
eventSink = eventSink,
|
||||
modifier = contentModifier,
|
||||
onContentLayoutChange = onContentLayoutChange
|
||||
)
|
||||
},
|
||||
) {
|
||||
Column(modifier = modifier.animateContentSize()) {
|
||||
GroupHeaderView(
|
||||
|
||||
@@ -62,15 +62,16 @@ internal fun TimelineItemRow(
|
||||
onJoinCallClick: () -> Unit,
|
||||
eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange ->
|
||||
TimelineItemEventContentView(
|
||||
content = event.content,
|
||||
onLinkClick = onLinkClick,
|
||||
eventSink = eventSink,
|
||||
modifier = contentModifier,
|
||||
onContentLayoutChange = onContentLayoutChange
|
||||
)
|
||||
},
|
||||
eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit =
|
||||
{ event, contentModifier, onContentLayoutChange ->
|
||||
TimelineItemEventContentView(
|
||||
content = event.content,
|
||||
onLinkClick = onLinkClick,
|
||||
eventSink = eventSink,
|
||||
modifier = contentModifier,
|
||||
onContentLayoutChange = onContentLayoutChange
|
||||
)
|
||||
},
|
||||
) {
|
||||
val backgroundModifier = if (timelineItem.isEvent(focusedEventId)) {
|
||||
val focusedEventOffset = if ((timelineItem as? TimelineItem.Event)?.showSenderInformation == true) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
||||
@@ -22,12 +22,9 @@ import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.ReceiveTurbine
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.messages.impl.actionlist.ActionListPresenter
|
||||
import io.element.android.features.messages.impl.actionlist.ActionListState
|
||||
import io.element.android.features.messages.impl.actionlist.FakeActionListPresenter
|
||||
import io.element.android.features.messages.impl.actionlist.anActionListState
|
||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
|
||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
|
||||
import io.element.android.features.messages.impl.draft.FakeComposerDraftService
|
||||
import io.element.android.features.messages.impl.fixtures.aMessageEvent
|
||||
import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactory
|
||||
@@ -63,7 +60,6 @@ import io.element.android.features.poll.test.actions.FakeEndPollAction
|
||||
import io.element.android.features.poll.test.actions.FakeSendPollResponseAction
|
||||
import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
@@ -104,7 +100,6 @@ import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory
|
||||
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
||||
import io.element.android.libraries.permissions.test.FakePermissionsPresenter
|
||||
import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory
|
||||
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
||||
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
|
||||
import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider
|
||||
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
||||
|
||||
@@ -33,8 +33,6 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI
|
||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent
|
||||
import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_MESSAGE
|
||||
@@ -978,7 +976,7 @@ private fun createActionListPresenter(
|
||||
return DefaultActionListPresenter(
|
||||
postProcessor = TimelineItemActionPostProcessor.Default,
|
||||
appPreferencesStore = preferencesStore,
|
||||
isPinnedMessagesFeatureEnabled = {isPinFeatureEnabled},
|
||||
isPinnedMessagesFeatureEnabled = { isPinFeatureEnabled },
|
||||
room = room
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import androidx.compose.runtime.Composable
|
||||
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
|
||||
|
||||
class FakeActionListPresenter : ActionListPresenter {
|
||||
|
||||
object Factory : ActionListPresenter.Factory {
|
||||
override fun create(postProcessor: TimelineItemActionPostProcessor): ActionListPresenter {
|
||||
return FakeActionListPresenter()
|
||||
|
||||
@@ -36,12 +36,8 @@ import io.element.android.libraries.matrix.test.timeline.aMessageContent
|
||||
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
|
||||
import io.element.android.tests.testutils.test
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@ package io.element.android.features.messages.impl.pinned.list
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
|
||||
class FakePinnedMessagesListNavigator: PinnedMessagesListNavigator {
|
||||
|
||||
class FakePinnedMessagesListNavigator : PinnedMessagesListNavigator {
|
||||
var onViewInTimelineClickLambda: ((EventId) -> Unit)? = null
|
||||
override fun onViewInTimelineClick(eventId: EventId) {
|
||||
onViewInTimelineClickLambda?.invoke(eventId)
|
||||
|
||||
@@ -40,7 +40,6 @@ import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class PinnedMessagesListPresenterTest {
|
||||
|
||||
@Test
|
||||
fun `present - initial state feature disabled`() = runTest {
|
||||
val room = FakeMatrixRoom(
|
||||
|
||||
@@ -34,7 +34,6 @@ import io.element.android.features.poll.impl.history.model.PollHistoryItemsFacto
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -152,6 +152,4 @@ class RoomDetailsNode @AssistedInject constructor(
|
||||
onPinnedMessagesClick = ::openPinnedMessages
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -127,7 +127,6 @@ class RoomDetailsViewTest {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Config(qualifiers = "h1024dp")
|
||||
@Test
|
||||
fun `click on pinned messages invokes expected callback`() {
|
||||
|
||||
@@ -32,7 +32,6 @@ class DerivedStateFlow<T>(
|
||||
private val getValue: () -> T,
|
||||
private val flow: Flow<T>
|
||||
) : StateFlow<T> {
|
||||
|
||||
override val replayCache: List<T>
|
||||
get() = listOf(value)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user