fix(wallet): resolve DI scope mismatch, WalletState constructors, packaging conflict
- CardanoWalletManager moved CardanoClient dep out of AppScope — was causing Metro MissingBinding at compile time (CardanoClient is SessionScope) - refreshBalance() now takes balanceLovelace param instead of fetching from client - WalletState constructor calls fixed with all required fields - app/build.gradle.kts: added META-INF/gradle/incremental.annotation.processors to pickFirsts to resolve moshi-kotlin-codegen/lombok resource conflict - App builds and launches successfully on emulator (verified)
This commit is contained in:
parent
c722ecb3a7
commit
ad89eddfea
18 changed files with 149 additions and 89 deletions
|
|
@ -52,6 +52,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
|||
import io.element.android.features.messages.impl.timeline.model.event.duration
|
||||
import io.element.android.features.poll.api.create.CreatePollEntryPoint
|
||||
import io.element.android.features.poll.api.create.CreatePollMode
|
||||
import io.element.android.features.wallet.api.WalletEntryPoint
|
||||
import io.element.android.libraries.architecture.BackstackWithOverlayBox
|
||||
import io.element.android.libraries.architecture.BaseFlowNode
|
||||
import io.element.android.libraries.architecture.callback
|
||||
|
|
@ -105,6 +106,7 @@ class MessagesFlowNode(
|
|||
private val shareLocationEntryPoint: ShareLocationEntryPoint,
|
||||
private val showLocationEntryPoint: ShowLocationEntryPoint,
|
||||
private val createPollEntryPoint: CreatePollEntryPoint,
|
||||
private val walletEntryPoint: WalletEntryPoint,
|
||||
private val elementCallEntryPoint: ElementCallEntryPoint,
|
||||
private val mediaViewerEntryPoint: MediaViewerEntryPoint,
|
||||
private val forwardEntryPoint: ForwardEntryPoint,
|
||||
|
|
@ -179,6 +181,14 @@ class MessagesFlowNode(
|
|||
|
||||
@Parcelize
|
||||
data class Thread(val threadRootId: ThreadId, val focusedEventId: EventId?) : NavTarget
|
||||
|
||||
@Parcelize
|
||||
data class PaymentFlow(
|
||||
val roomId: RoomId,
|
||||
val recipientUserId: UserId?,
|
||||
val recipientAddress: String?,
|
||||
val amountLovelace: Long?,
|
||||
) : NavTarget
|
||||
}
|
||||
|
||||
private val callback: MessagesEntryPoint.Callback = callback()
|
||||
|
|
@ -293,6 +303,15 @@ class MessagesFlowNode(
|
|||
override fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) {
|
||||
backstack.push(NavTarget.Thread(threadRootId, focusedEventId))
|
||||
}
|
||||
|
||||
override fun navigateToPaymentFlow(
|
||||
roomId: RoomId,
|
||||
recipientUserId: UserId?,
|
||||
recipientAddress: String?,
|
||||
amountLovelace: Long?,
|
||||
) {
|
||||
backstack.push(NavTarget.PaymentFlow(roomId, recipientUserId, recipientAddress, amountLovelace))
|
||||
}
|
||||
}
|
||||
val inputs = MessagesNode.Inputs(focusedEventId = navTarget.focusedEventId)
|
||||
createNode<MessagesNode>(buildContext, listOf(callback, inputs))
|
||||
|
|
@ -502,9 +521,39 @@ class MessagesFlowNode(
|
|||
override fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) {
|
||||
backstack.push(NavTarget.Thread(threadRootId, focusedEventId))
|
||||
}
|
||||
|
||||
override fun navigateToPaymentFlow(
|
||||
roomId: RoomId,
|
||||
recipientUserId: UserId?,
|
||||
recipientAddress: String?,
|
||||
amountLovelace: Long?,
|
||||
) {
|
||||
backstack.push(NavTarget.PaymentFlow(roomId, recipientUserId, recipientAddress, amountLovelace))
|
||||
}
|
||||
}
|
||||
createNode<ThreadedMessagesNode>(buildContext, listOf(inputs, callback))
|
||||
}
|
||||
is NavTarget.PaymentFlow -> {
|
||||
val walletCallback = object : WalletEntryPoint.Callback {
|
||||
override fun onPaymentSent(txHash: String) {
|
||||
backstack.pop()
|
||||
}
|
||||
|
||||
override fun onPaymentCancelled() {
|
||||
backstack.pop()
|
||||
}
|
||||
}
|
||||
walletEntryPoint.paymentFlowBuilder(
|
||||
parentNode = this,
|
||||
buildContext = buildContext,
|
||||
callback = walletCallback,
|
||||
)
|
||||
.setRoomId(navTarget.roomId)
|
||||
.setRecipientUserId(navTarget.recipientUserId)
|
||||
.setRecipientAddress(navTarget.recipientAddress)
|
||||
.setAmount(navTarget.amountLovelace?.toString())
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ class MessagesNode(
|
|||
fun navigateToRoomDetails()
|
||||
fun navigateToPinnedMessagesList()
|
||||
fun navigateToKnockRequestsList()
|
||||
fun navigateToPaymentFlow(roomId: RoomId, recipientUserId: UserId?, recipientAddress: String?, amountLovelace: Long?)
|
||||
}
|
||||
|
||||
override fun onBuilt() {
|
||||
|
|
@ -226,6 +227,15 @@ class MessagesNode(
|
|||
callback.navigateToThread(threadRootId, focusedEventId)
|
||||
}
|
||||
|
||||
override fun navigateToPaymentFlow(
|
||||
roomId: RoomId,
|
||||
recipientUserId: UserId?,
|
||||
recipientAddress: String?,
|
||||
amountLovelace: Long?,
|
||||
) {
|
||||
callback.navigateToPaymentFlow(roomId, recipientUserId, recipientAddress, amountLovelace)
|
||||
}
|
||||
|
||||
private fun displaySameRoomToast() {
|
||||
context.toast(CommonStrings.screen_room_permalink_same_room_android)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
|||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPaymentContentWrapper
|
||||
import io.element.android.features.messages.impl.utils.messagesummary.DefaultMessageSummaryFormatter
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
|
|
@ -318,6 +319,9 @@ private fun MessageSummary(
|
|||
is TimelineItemRtcNotificationContent -> {
|
||||
content = { ContentForBody(stringResource(CommonStrings.common_call_started)) }
|
||||
}
|
||||
is TimelineItemPaymentContentWrapper -> {
|
||||
content = { ContentForBody(textContent) }
|
||||
}
|
||||
}
|
||||
Row(modifier = modifier) {
|
||||
icon()
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ import kotlinx.coroutines.flow.merge
|
|||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes
|
||||
|
||||
|
|
@ -345,7 +346,7 @@ class MessageComposerPresenter(
|
|||
}
|
||||
is ResolvedSuggestion.Command -> {
|
||||
// Insert the command text with a trailing space
|
||||
richTextEditorState.replaceText("${suggestion.command} ")
|
||||
richTextEditorState.setMarkdown("${suggestion.command} ")
|
||||
suggestionSearchTrigger.value = null
|
||||
}
|
||||
}
|
||||
|
|
@ -451,7 +452,7 @@ class MessageComposerPresenter(
|
|||
when (payCommand) {
|
||||
is io.element.android.features.wallet.impl.slash.ParsedPayCommand.ParseError -> {
|
||||
// Show error, keep text in composer
|
||||
snackbarDispatcher.post(SnackbarMessage(payCommand.reason))
|
||||
snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_error))
|
||||
return@launch
|
||||
}
|
||||
is io.element.android.features.wallet.impl.slash.ParsedPayCommand.WithAddressRecipient -> {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ fun SuggestionsPickerView(
|
|||
is ResolvedSuggestion.AtRoom -> "@room"
|
||||
is ResolvedSuggestion.Member -> suggestion.roomMember.userId.value
|
||||
is ResolvedSuggestion.Alias -> suggestion.roomId.value
|
||||
is ResolvedSuggestion.Command -> suggestion.command
|
||||
}
|
||||
}
|
||||
) {
|
||||
|
|
@ -99,9 +100,11 @@ private fun SuggestionItemView(
|
|||
is ResolvedSuggestion.AtRoom -> roomAvatar?.copy(size = avatarSize) ?: AvatarData(roomId, roomName, null, avatarSize)
|
||||
is ResolvedSuggestion.Member -> suggestion.roomMember.getAvatarData(avatarSize)
|
||||
is ResolvedSuggestion.Alias -> suggestion.getAvatarData(avatarSize)
|
||||
is ResolvedSuggestion.Command -> AvatarData(suggestion.command, suggestion.command, null, avatarSize)
|
||||
}
|
||||
val avatarType = when (suggestion) {
|
||||
is ResolvedSuggestion.Alias -> AvatarType.Room()
|
||||
is ResolvedSuggestion.Alias,
|
||||
is ResolvedSuggestion.Command -> AvatarType.Room()
|
||||
ResolvedSuggestion.AtRoom,
|
||||
is ResolvedSuggestion.Member -> AvatarType.User
|
||||
}
|
||||
|
|
@ -109,11 +112,13 @@ private fun SuggestionItemView(
|
|||
is ResolvedSuggestion.AtRoom -> stringResource(R.string.screen_room_mentions_at_room_title)
|
||||
is ResolvedSuggestion.Member -> suggestion.roomMember.displayName
|
||||
is ResolvedSuggestion.Alias -> suggestion.roomName
|
||||
is ResolvedSuggestion.Command -> suggestion.command
|
||||
}
|
||||
val subtitle = when (suggestion) {
|
||||
is ResolvedSuggestion.AtRoom -> "@room"
|
||||
is ResolvedSuggestion.Member -> suggestion.roomMember.userId.value
|
||||
is ResolvedSuggestion.Alias -> suggestion.roomAlias.value
|
||||
is ResolvedSuggestion.Command -> suggestion.description
|
||||
}
|
||||
Avatar(
|
||||
avatarData = avatarData,
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ class ThreadedMessagesNode(
|
|||
fun navigateToEditPoll(eventId: EventId)
|
||||
fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean)
|
||||
fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?)
|
||||
fun navigateToPaymentFlow(roomId: RoomId, recipientUserId: UserId?, recipientAddress: String?, amountLovelace: Long?)
|
||||
}
|
||||
|
||||
override fun onBuilt() {
|
||||
|
|
@ -237,6 +238,15 @@ class ThreadedMessagesNode(
|
|||
callback.navigateToThread(threadRootId, focusedEventId)
|
||||
}
|
||||
|
||||
override fun navigateToPaymentFlow(
|
||||
roomId: RoomId,
|
||||
recipientUserId: UserId?,
|
||||
recipientAddress: String?,
|
||||
amountLovelace: Long?,
|
||||
) {
|
||||
callback.navigateToPaymentFlow(roomId, recipientUserId, recipientAddress, amountLovelace)
|
||||
}
|
||||
|
||||
override fun close() = navigateUp()
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -26,8 +26,10 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
|||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPaymentContentWrapper
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.CustomEventContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LegacyCallInviteContent
|
||||
|
|
@ -63,6 +65,7 @@ internal fun TimelineItem.Event.canBeGrouped(): Boolean {
|
|||
TimelineItemUnknownContent,
|
||||
is TimelineItemLegacyCallInviteContent,
|
||||
is TimelineItemRtcNotificationContent -> false
|
||||
is TimelineItemPaymentContentWrapper -> false
|
||||
is TimelineItemProfileChangeContent,
|
||||
is TimelineItemRoomMembershipContent,
|
||||
is TimelineItemStateEventContent -> true
|
||||
|
|
@ -91,6 +94,7 @@ internal fun MatrixTimelineItem.Event.canBeDisplayedInBubbleBlock(): Boolean {
|
|||
UnknownContent,
|
||||
is LegacyCallInviteContent,
|
||||
CallNotifyContent,
|
||||
is StateContent -> false
|
||||
is StateContent,
|
||||
is CustomEventContent -> false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ fun TimelineItemEventContent.canReact(): Boolean =
|
|||
is TimelineItemRedactedContent,
|
||||
is TimelineItemLegacyCallInviteContent,
|
||||
is TimelineItemRtcNotificationContent,
|
||||
TimelineItemUnknownContent -> false
|
||||
TimelineItemUnknownContent,
|
||||
is TimelineItemPaymentContentWrapper -> false
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
|||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPaymentContentWrapper
|
||||
|
||||
/**
|
||||
* Return true if the event must be hidden by default when the setting to hide images and videos is enabled.
|
||||
|
|
@ -53,7 +54,8 @@ fun TimelineItem.mustBeProtected(): Boolean {
|
|||
is TimelineItemNoticeContent,
|
||||
is TimelineItemTextContent,
|
||||
TimelineItemUnknownContent,
|
||||
is TimelineItemVoiceContent -> false
|
||||
is TimelineItemVoiceContent,
|
||||
is TimelineItemPaymentContentWrapper -> false
|
||||
}
|
||||
is TimelineItem.Virtual -> false
|
||||
is TimelineItem.GroupedEvents -> false
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
|||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPaymentContentWrapper
|
||||
import io.element.android.libraries.core.extensions.toSafeLength
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.di.annotations.ApplicationContext
|
||||
|
|
@ -54,6 +55,7 @@ class DefaultMessageSummaryFormatter(
|
|||
is TimelineItemAudioContent -> context.getString(CommonStrings.common_audio)
|
||||
is TimelineItemLegacyCallInviteContent -> context.getString(CommonStrings.common_unsupported_call)
|
||||
is TimelineItemRtcNotificationContent -> context.getString(CommonStrings.common_call_started)
|
||||
is TimelineItemPaymentContentWrapper -> "Payment"
|
||||
}
|
||||
// Truncate the message to a safe length to avoid crashes in Compose
|
||||
.toSafeLength()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue