@@ -477,6 +477,22 @@ impl Timeline {
477477 } )
478478 }
479479
480+ /// Given a transaction id, try to find a remote echo that used this
481+ /// transaction id upon sending.
482+ async fn find_remote_by_transaction_id ( & self , txn_id : & TransactionId ) -> Option < OwnedEventId > {
483+ let items = self . inner . items ( ) . await ;
484+
485+ let ( _, found) = rfind_event_item ( & items, |item| {
486+ if let Some ( remote) = item. as_remote ( ) {
487+ remote. transaction_id . as_deref ( ) == Some ( txn_id)
488+ } else {
489+ false
490+ }
491+ } ) ?;
492+
493+ Some ( found. event_id ( ) . expect ( "remote echoes have event id" ) . to_owned ( ) )
494+ }
495+
480496 /// Edit an event.
481497 ///
482498 /// Only supports events for which [`EventTimelineItem::is_editable()`]
@@ -503,19 +519,38 @@ impl Timeline {
503519 ) -> Result < bool , RoomSendQueueError > {
504520 let event_id = match edit_info. id {
505521 TimelineEventItemId :: TransactionId ( txn_id) => {
506- let Some ( item) = self . item_by_transaction_id ( & txn_id) . await else {
507- warn ! ( "Couldn't find the local echo anymore" ) ;
508- return Ok ( false ) ;
509- } ;
522+ if let Some ( item) = self . item_by_transaction_id ( & txn_id) . await {
523+ let Some ( handle) = item. as_local ( ) . and_then ( |item| item. send_handle . clone ( ) )
524+ else {
525+ warn ! ( "No handle for a local echo; is this a test?" ) ;
526+ return Ok ( false ) ;
527+ } ;
510528
511- if let Some ( handle) = item. as_local ( ) . and_then ( |item| item. send_handle . clone ( ) ) {
512529 // Assume no relations, since it's not been sent yet.
513- let new_content: RoomMessageEventContent = new_content. into ( ) ;
514- return Ok ( handle. edit ( new_content. into ( ) ) . await ?) ;
530+ let new_content: RoomMessageEventContent = new_content. clone ( ) . into ( ) ;
531+
532+ if handle. edit ( new_content. into ( ) ) . await ? {
533+ return Ok ( true ) ;
534+ }
515535 }
516536
517- warn ! ( "No handle for a local echo; should only happen in testing situations" ) ;
518- return Ok ( false ) ;
537+ // We end up here in two cases: either there wasn't a local echo with this
538+ // transaction id, or the send queue refused to edit the local echo (likely
539+ // because it's sent).
540+ //
541+ // Try to find a matching local echo that now has an event id (it's been sent),
542+ // or a remote echo with a matching transaction id, so as to
543+ // send an actual edit.
544+ if let Some ( TimelineEventItemId :: EventId ( event_id) ) =
545+ self . item_by_transaction_id ( & txn_id) . await . map ( |item| item. identifier ( ) )
546+ {
547+ event_id
548+ } else if let Some ( event_id) = self . find_remote_by_transaction_id ( & txn_id) . await {
549+ event_id
550+ } else {
551+ warn ! ( "Couldn't find the local echo anymore, nor a matching remote echo" ) ;
552+ return Ok ( false ) ;
553+ }
519554 }
520555
521556 TimelineEventItemId :: EventId ( event_id) => event_id,
0 commit comments