| author | Eric Roberts
<eric@devl.me> 2026-09-28 14:06:00 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2026-09-28 14:08:30 UTC |
| parent | 875abe97d19c0ec5400dadbb8a01eb856af71b2f |
| borogove/persistence/IDB.js | +28 | -14 |
| test/persistence-tests.ts | +54 | -0 |
diff --git a/borogove/persistence/IDB.js b/borogove/persistence/IDB.js index 3e68e95..48b399d 100644 --- a/borogove/persistence/IDB.js +++ b/borogove/persistence/IDB.js @@ -610,24 +610,25 @@ export default async (dbname, media, tokenize, stemmer) => { ) .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime()); const head = { ...versions[0] }; + const outer = getOuter(result.value, message); // Can't change primary key - head.serverIdBy = result.value.serverIdBy; - head.serverId = result.value.serverId; - head.localId = result.value.localId; - head.replyId = result.value.replyId; + head.serverIdBy = outer.serverIdBy; + head.serverId = outer.serverId; + head.localId = outer.localId; + head.replyId = outer.replyId; // Edited version is not newer - head.timestamp = result.value.timestamp; - head.sortId = result.value.sortId; + head.timestamp = new Date(outer.timestamp); + head.sortId = outer.sortId; head.versions = versions; - head.reactions = result.value.reactions; // Preserve these, edit doesn't touch them + head.reactions = outer.reactions; // Preserve these, edit doesn't touch them // Calls can "edit" from multiple senders, but the original direction and sender holds - if (result.value.type === enums.borogove_MessageType.MessageCall) { - head.direction = result.value.direction; - head.senderId = result.value.senderId; - head.from = result.value.from; - head.to = result.value.to; - head.replyTo = result.value.replyTo; - head.recipients = result.value.recipients; + if (outer.type === enums.borogove_MessageType.MessageCall) { + head.direction = outer.direction; + head.senderId = outer.senderId; + head.from = outer.from; + head.to = outer.to; + head.replyTo = outer.replyTo; + head.recipients = outer.recipients; } result.update(head); if (!message.isIncoming()) { @@ -638,6 +639,19 @@ export default async (dbname, media, tokenize, stemmer) => { return head; } + function getOuter(original, possibleReplacement) { + if (!original.serverId) return original; + + if ( + original.serverId === possibleReplacement.serverId && + original.serverIdBy === possibleReplacement.serverIdBy + ) { + return possibleReplacement; + } + + return original; + } + function setReactions(reactionsMap, sender, reactions) { for (const [reaction, reacts] of reactionsMap) { const newReacts = reacts.filter((react) => react.senderId !== sender); diff --git a/test/persistence-tests.ts b/test/persistence-tests.ts index 7577243..a3d15ff 100644 --- a/test/persistence-tests.ts +++ b/test/persistence-tests.ts @@ -515,6 +515,60 @@ export function sharedPersistenceTests(test) { } }); + test("updates sortId when replaying an original after its correction", async ({ + borogove, + persistence, + }) => { + const account = "correction-sort-alice@example.com"; + const chatId = "correction-sort-hatter@example.com"; + const originalBuilder = new borogove.ChatMessageBuilder({ + serverId: "archive-original", + serverIdBy: chatId, + localId: "correction-sort-original", + senderId: chatId, + direction: 0, + timestamp: "2026-08-26T12:00:00Z", + }); + originalBuilder.sortId = "b0"; + originalBuilder.text = "Original text"; + originalBuilder.to = borogove.JID.parse(account); + originalBuilder.from = borogove.JID.parse(chatId); + originalBuilder.recipients = [originalBuilder.to]; + originalBuilder.replyTo = [originalBuilder.from]; + const original = originalBuilder.build(); + + const correctionBuilder = new borogove.ChatMessageBuilder({ + serverId: "archive-correction", + serverIdBy: chatId, + localId: "correction-sort-correction", + senderId: chatId, + direction: 0, + timestamp: "2026-08-26T12:01:00Z", + }); + correctionBuilder.sortId = "b0"; + correctionBuilder.text = "Corrected text"; + correctionBuilder.to = borogove.JID.parse(account); + correctionBuilder.from = borogove.JID.parse(chatId); + correctionBuilder.recipients = [correctionBuilder.to]; + correctionBuilder.replyTo = [correctionBuilder.from]; + const correctionVersion = correctionBuilder.build(); + correctionBuilder.versions = [correctionVersion]; + correctionBuilder.localId = original.localId; + + await persistence.storeMessages(account, [original]); + await persistence.storeMessages(account, [correctionBuilder.build()]); + + originalBuilder.sortId = "a0"; + const [stored] = await persistence.storeMessages(account, [ + originalBuilder.build(), + ]); + + await persistence.getMessage(account, chatId, original.serverId, null); + + expect(stored.text).toBe("Corrected text"); + expect(stored.sortId).toBe("a0"); + }); + test("storeReaction", async ({ borogove, persistence }) => { const builder = new borogove.ChatMessageBuilder({ serverId: "srv1",