0e659d294e
When multiple m.replace edits arrive concurrently, getLastReplacement() may block on decryption. If an older edit's decryption completes after a newer edit has already been applied, the older async result overwrites the target event with stale content. Add a monotonic update counter (replacementUpdateId) and centralise all replacement updates through updateTargetEventReplacement(). The method captures the counter before awaiting and discards the result if a newer update has started in the meantime. This race is especially pronounced in encrypted rooms with rapid streaming-style edits, where variable decryption timing causes out-of-order promise resolution.