Merge develop into feature/fga/permalink_timeline
This commit is contained in:
commit
6808edda86
398 changed files with 2667 additions and 2461 deletions
|
|
@ -18,6 +18,7 @@ package io.element.android.features.messages.impl
|
|||
|
||||
import com.bumble.appyx.core.modality.BuildContext
|
||||
import com.bumble.appyx.core.node.Node
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.features.messages.api.MessagesEntryPoint
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
|
|
@ -26,11 +27,23 @@ import javax.inject.Inject
|
|||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultMessagesEntryPoint @Inject constructor() : MessagesEntryPoint {
|
||||
override fun createNode(
|
||||
parentNode: Node,
|
||||
buildContext: BuildContext,
|
||||
callback: MessagesEntryPoint.Callback
|
||||
): Node {
|
||||
return parentNode.createNode<MessagesFlowNode>(buildContext, listOf(callback))
|
||||
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): MessagesEntryPoint.NodeBuilder {
|
||||
val plugins = ArrayList<Plugin>()
|
||||
|
||||
return object : MessagesEntryPoint.NodeBuilder {
|
||||
override fun params(params: MessagesEntryPoint.Params): MessagesEntryPoint.NodeBuilder {
|
||||
plugins += MessagesNode.Inputs(focusedEventId = params.focusedEventId)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun callback(callback: MessagesEntryPoint.Callback): MessagesEntryPoint.NodeBuilder {
|
||||
plugins += callback
|
||||
return this
|
||||
}
|
||||
|
||||
override fun build(): Node {
|
||||
return parentNode.createNode<MessagesFlowNode>(buildContext, plugins)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ 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.overlay.Overlay
|
||||
import io.element.android.libraries.architecture.overlay.operation.show
|
||||
|
|
@ -62,6 +63,7 @@ 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.core.UserId
|
||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||
import io.element.android.libraries.matrix.api.permalink.PermalinkData
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.mediaviewer.api.local.MediaInfo
|
||||
import io.element.android.libraries.mediaviewer.api.viewer.MediaViewerNode
|
||||
|
|
@ -79,7 +81,7 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
private val createPollEntryPoint: CreatePollEntryPoint,
|
||||
) : BaseFlowNode<MessagesFlowNode.NavTarget>(
|
||||
backstack = BackStack(
|
||||
initialElement = NavTarget.Messages,
|
||||
initialElement = NavTarget.Messages(plugins.filterIsInstance<Inputs>().firstOrNull()?.focusedEventId),
|
||||
savedStateMap = buildContext.savedStateMap,
|
||||
),
|
||||
overlay = Overlay(
|
||||
|
|
@ -88,12 +90,16 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
buildContext = buildContext,
|
||||
plugins = plugins
|
||||
) {
|
||||
data class Inputs(val focusedEventId: EventId?) : NodeInputs
|
||||
|
||||
sealed interface NavTarget : Parcelable {
|
||||
@Parcelize
|
||||
data object Empty : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data object Messages : NavTarget
|
||||
data class Messages(
|
||||
val focusedEventId: EventId? = null,
|
||||
) : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data class MediaViewer(
|
||||
|
|
@ -149,6 +155,10 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
callback?.onUserDataClicked(userId)
|
||||
}
|
||||
|
||||
override fun onPermalinkClicked(data: PermalinkData) {
|
||||
callback?.onPermalinkClicked(data)
|
||||
}
|
||||
|
||||
override fun onShowEventDebugInfoClicked(eventId: EventId?, debugInfo: TimelineItemDebugInfo) {
|
||||
backstack.push(NavTarget.EventDebugInfo(eventId, debugInfo))
|
||||
}
|
||||
|
|
@ -181,7 +191,10 @@ class MessagesFlowNode @AssistedInject constructor(
|
|||
ElementCallActivity.start(context, inputs)
|
||||
}
|
||||
}
|
||||
createNode<MessagesNode>(buildContext, listOf(callback))
|
||||
val params = MessagesNode.Inputs(
|
||||
focusedEventId = navTarget.focusedEventId,
|
||||
)
|
||||
createNode<MessagesNode>(buildContext, listOf(callback, params))
|
||||
}
|
||||
is NavTarget.MediaViewer -> {
|
||||
val inputs = MediaViewerNode.Inputs(
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPr
|
|||
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||
import io.element.android.libraries.androidutils.system.openUrlInExternalApp
|
||||
import io.element.android.libraries.androidutils.system.toast
|
||||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
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
|
||||
|
|
@ -42,6 +45,7 @@ import io.element.android.libraries.matrix.api.core.UserId
|
|||
import io.element.android.libraries.matrix.api.permalink.PermalinkData
|
||||
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.alias.matches
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.mediaplayer.api.MediaPlayer
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
|
|
@ -58,15 +62,21 @@ class MessagesNode @AssistedInject constructor(
|
|||
private val timelineItemPresenterFactories: TimelineItemPresenterFactories,
|
||||
private val mediaPlayer: MediaPlayer,
|
||||
private val permalinkParser: PermalinkParser,
|
||||
@ApplicationContext
|
||||
private val context: Context,
|
||||
) : Node(buildContext, plugins = plugins), MessagesNavigator {
|
||||
private val presenter = presenterFactory.create(this)
|
||||
private val callback = plugins<Callback>().firstOrNull()
|
||||
|
||||
// TODO Handle navigation to the Event
|
||||
data class Inputs(val focusedEventId: EventId?) : NodeInputs
|
||||
|
||||
interface Callback : Plugin {
|
||||
fun onRoomDetailsClicked()
|
||||
fun onEventClicked(event: TimelineItem.Event): Boolean
|
||||
fun onPreviewAttachments(attachments: ImmutableList<Attachment>)
|
||||
fun onUserDataClicked(userId: UserId)
|
||||
fun onPermalinkClicked(data: PermalinkData)
|
||||
fun onShowEventDebugInfoClicked(eventId: EventId?, debugInfo: TimelineItemDebugInfo)
|
||||
fun onForwardEventClicked(eventId: EventId)
|
||||
fun onReportMessage(eventId: EventId, senderId: UserId)
|
||||
|
|
@ -109,16 +119,12 @@ class MessagesNode @AssistedInject constructor(
|
|||
) {
|
||||
when (val permalink = permalinkParser.parse(url)) {
|
||||
is PermalinkData.UserLink -> {
|
||||
// Open the room member profile, it will fallback to
|
||||
// the user profile if the user is not in the room
|
||||
callback?.onUserDataClicked(permalink.userId)
|
||||
}
|
||||
is PermalinkData.RoomLink -> {
|
||||
// TODO Implement room link handling
|
||||
}
|
||||
is PermalinkData.EventIdAliasLink -> {
|
||||
// TODO Implement room and Event link handling
|
||||
}
|
||||
is PermalinkData.EventIdLink -> {
|
||||
// TODO Implement room and Event link handling
|
||||
handleRoomLinkClicked(permalink)
|
||||
}
|
||||
is PermalinkData.FallbackLink,
|
||||
is PermalinkData.RoomEmailInviteLink -> {
|
||||
|
|
@ -127,6 +133,20 @@ class MessagesNode @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleRoomLinkClicked(roomLink: PermalinkData.RoomLink) {
|
||||
if (room.matches(roomLink.roomIdOrAlias)) {
|
||||
if (roomLink.eventId != null) {
|
||||
// TODO Handle navigation to the Event
|
||||
context.toast("TODO Handle navigation to the Event ${roomLink.eventId}")
|
||||
} else {
|
||||
// Click on the same room, ignore
|
||||
context.toast("Already viewing this room!")
|
||||
}
|
||||
} else {
|
||||
callback?.onPermalinkClicked(roomLink)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onShowEventDebugInfoClicked(eventId: EventId?, debugInfo: TimelineItemDebugInfo) {
|
||||
callback?.onShowEventDebugInfoClicked(eventId, debugInfo)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ class MessagesPresenter @AssistedInject constructor(
|
|||
|
||||
private fun MatrixRoomInfo.avatarData(): AvatarData {
|
||||
return AvatarData(
|
||||
id = id,
|
||||
id = id.value,
|
||||
name = name,
|
||||
url = avatarUrl ?: room.avatarUrl,
|
||||
size = AvatarSize.TimelineRoom
|
||||
|
|
|
|||
|
|
@ -720,7 +720,7 @@ class MessagesPresenterTest {
|
|||
private fun TestScope.createMessagesPresenter(
|
||||
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
|
||||
matrixRoom: MatrixRoom = FakeMatrixRoom().apply {
|
||||
givenRoomInfo(aRoomInfo(id = roomId.value, name = ""))
|
||||
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
|
||||
},
|
||||
navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
|
||||
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ class TypingNotificationPresenterTest {
|
|||
|
||||
private fun createPresenter(
|
||||
matrixRoom: MatrixRoom = FakeMatrixRoom().apply {
|
||||
givenRoomInfo(aRoomInfo(id = roomId.value, name = ""))
|
||||
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
|
||||
},
|
||||
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(
|
||||
isRenderTypingNotificationsEnabled = true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue