feat(wallet): payment card timeline item and raw event handling (Tasks 7+8)
Task 7: Timeline Payment Card
- TimelineItemPaymentView integration with TimelineItemEventContentView
- Payment card rendering for both sender and recipient perspectives
- Unit tests for TimelineItemPaymentContent
Task 8: Raw Event Handling
- Modified TimelineItemContentMessageFactory to intercept payment events
- Added isSentByMe parameter propagation through content factories
- FakePaymentEventSender for testing
- Unit tests for TimelineItemContentPaymentFactory
SDK Limitation Workaround:
Since matrix-rust-sdk doesn't expose raw event sending or UnknownContent
raw JSON, payment events are encoded as text messages with a marker:
[cardano-payment:v1]{...json...}
This falls back gracefully for non-wallet clients while enabling
rich payment card rendering for wallet-enabled clients.
This commit is contained in:
parent
39561e1aeb
commit
adee67cf0d
16 changed files with 1410 additions and 12 deletions
|
|
@ -30,6 +30,8 @@ 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.wallet.api.timeline.TimelineItemPaymentContent
|
||||
import io.element.android.features.wallet.impl.timeline.TimelineItemPaymentView
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.voiceplayer.api.VoiceMessageState
|
||||
import io.element.android.wysiwyg.link.Link
|
||||
|
|
@ -134,6 +136,10 @@ fun TimelineItemEventContentView(
|
|||
modifier = modifier
|
||||
)
|
||||
}
|
||||
is TimelineItemPaymentContent -> TimelineItemPaymentView(
|
||||
content = content,
|
||||
modifier = modifier
|
||||
)
|
||||
is TimelineItemRtcNotificationContent -> error("This shouldn't be rendered as the content of a bubble")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ class TimelineItemContentFactory(
|
|||
senderProfile = senderProfile,
|
||||
content = itemContent,
|
||||
eventId = eventId,
|
||||
isSentByMe = isOutgoing,
|
||||
)
|
||||
}
|
||||
is ProfileChangeContent -> {
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ class TimelineItemContentMessageFactory(
|
|||
senderId: UserId,
|
||||
senderProfile: ProfileDetails,
|
||||
eventId: EventId?,
|
||||
isSentByMe: Boolean = false,
|
||||
): TimelineItemEventContent {
|
||||
return when (val messageType = content.type) {
|
||||
is EmoteMessageType -> {
|
||||
|
|
@ -256,16 +257,13 @@ class TimelineItemContentMessageFactory(
|
|||
}
|
||||
is TextMessageType -> {
|
||||
val body = messageType.body.trimEnd()
|
||||
val dom = messageType.formatted?.toHtmlDocument(permalinkParser = permalinkParser)
|
||||
val formattedBody = dom?.let(::parseHtml)
|
||||
?: textPillificationHelper.pillify(body).safeLinkify()
|
||||
val htmlDocument = messageType.formatted?.toHtmlDocument(permalinkParser = permalinkParser)
|
||||
TimelineItemTextContent(
|
||||
body = body,
|
||||
htmlDocument = htmlDocument,
|
||||
formattedBody = formattedBody,
|
||||
isEdited = content.isEdited,
|
||||
)
|
||||
// Check for Cardano payment events embedded in text messages
|
||||
if (paymentFactory.isPaymentEvent(body)) {
|
||||
paymentFactory.createFromBody(body, isSentByMe)
|
||||
?: createTextContent(body, messageType, content.isEdited)
|
||||
} else {
|
||||
createTextContent(body, messageType, content.isEdited)
|
||||
}
|
||||
}
|
||||
is OtherMessageType -> {
|
||||
val body = messageType.body.trimEnd()
|
||||
|
|
@ -279,6 +277,23 @@ class TimelineItemContentMessageFactory(
|
|||
}
|
||||
}
|
||||
|
||||
private fun createTextContent(
|
||||
body: String,
|
||||
messageType: TextMessageType,
|
||||
isEdited: Boolean,
|
||||
): TimelineItemTextContent {
|
||||
val dom = messageType.formatted?.toHtmlDocument(permalinkParser = permalinkParser)
|
||||
val formattedBody = dom?.let(::parseHtml)
|
||||
?: textPillificationHelper.pillify(body).safeLinkify()
|
||||
val htmlDocument = messageType.formatted?.toHtmlDocument(permalinkParser = permalinkParser)
|
||||
return TimelineItemTextContent(
|
||||
body = body,
|
||||
htmlDocument = htmlDocument,
|
||||
formattedBody = formattedBody,
|
||||
isEdited = isEdited,
|
||||
)
|
||||
}
|
||||
|
||||
private fun aspectRatioOf(width: Long?, height: Long?): Float? {
|
||||
val result = if (height != null && width != null) {
|
||||
width.toFloat() / height.toFloat()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue