fix(wallet): replace text-marker hack with proper raw event API (room.sendRaw + MsgLikeKind.Other)

- Add Timeline.sendRaw() to send custom Matrix events
- Add CustomEventContent type for receiving custom events
- Update TimelineEventContentMapper to handle MsgLikeKind.Other
- Update TimelineItemContentFactory to intercept payment events
- Rewrite DefaultPaymentEventSender to use sendRaw instead of text markers
- Update TimelineItemContentPaymentFactory to parse raw JSON
- Remove text-marker detection from TimelineItemContentMessageFactory
- Update tests to use raw event API
- Mark raw event SDK blocker as RESOLVED in BLOCKERS.md

Event type: co.sulkta.payment.request (reverse-domain format)
Status updates: co.sulkta.payment.status

Benefits:
- Proper Matrix protocol compliance
- No JSON embedded in text messages
- Events won't be indexed by search
- Clean separation from regular messages
This commit is contained in:
Kayos 2026-03-27 11:45:12 -07:00
parent adee67cf0d
commit f2b95d6b8a
10 changed files with 264 additions and 189 deletions

View file

@ -279,6 +279,15 @@ class RustTimeline(
}
}
override suspend fun sendRaw(
eventType: String,
content: String,
): Result<Unit> = withContext(dispatcher) {
runCatchingExceptions {
inner.sendRaw(eventType, content)
}
}
override suspend fun redactEvent(eventOrTransactionId: EventOrTransactionId, reason: String?): Result<Unit> = withContext(dispatcher) {
runCatchingExceptions {
inner.redactEvent(

View file

@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
import io.element.android.libraries.matrix.api.timeline.item.event.CustomEventContent
import io.element.android.libraries.matrix.api.timeline.item.event.UtdCause
import io.element.android.libraries.matrix.impl.media.map
import io.element.android.libraries.matrix.impl.poll.map
@ -111,7 +112,14 @@ class TimelineEventContentMapper(
// Live location messages are a special kind of message that we want to treat as unknown content for now
UnknownContent
}
is MsgLikeKind.Other -> UnknownContent
is MsgLikeKind.Other -> {
// MsgLikeKind.Other contains custom event types
// Pass through the event type so downstream handlers can process it
CustomEventContent(
eventType = kind.eventType,
rawJson = null, // Raw JSON accessed via TimelineItemDebugInfoProvider
)
}
}
}
is TimelineItemContent.ProfileChange -> {