MessageLogger: show edit history inline, not just the current content

This commit is contained in:
Ally Founder 2026-08-11 20:38:35 -04:00
parent 8da18c4f07
commit c7037387a9
2 changed files with 41 additions and 4 deletions

View file

@ -20,6 +20,11 @@ const UserStore = findByStoreName("UserStore");
// forever if the plugin gets disabled. // forever if the plugin gets disabled.
export const fakedMessages = new Map<string, string>(); export const fakedMessages = new Map<string, string>();
// Every past content version for a message, oldest first, current content NOT included (rowStyling
// appends that itself from the live record). Same id-in-external-map pattern as fakedMessages -
// row.message.id survives into the row JSON, a custom property doesn't (confirmed live).
export const editHistory = new Map<string, string[]>();
function currentUserId(): string | undefined { function currentUserId(): string | undefined {
return UserStore?.getCurrentUser?.()?.id; return UserStore?.getCurrentUser?.()?.id;
} }
@ -162,6 +167,10 @@ function handleUpdate(event: any): void {
if (!storage.options?.logEdited) return; if (!storage.options?.logEdited) return;
if (ignoredFor(original, true)) return; if (ignoredFor(original, true)) return;
const history = editHistory.get(updated.id) ?? [];
history.push(original.content ?? "");
editHistory.set(updated.id, history);
addLogEntry(snapshotMessage(original, "edited", newContent, false), limitsFromStorage()); addLogEntry(snapshotMessage(original, "edited", newContent, false), limitsFromStorage());
} }
@ -205,4 +214,5 @@ export function revertFakedMessages(): void {
} }
} }
fakedMessages.clear(); fakedMessages.clear();
editHistory.clear();
} }

View file

@ -2,18 +2,45 @@ import { ReactNative } from "@vendetta/metro/common";
import { after, before } from "@vendetta/patcher"; import { after, before } from "@vendetta/patcher";
import { waitFor } from "@shared/lib/waitFor"; import { waitFor } from "@shared/lib/waitFor";
import { rawFind, rawFindByName } from "@shared/lib/rawFind"; import { rawFind, rawFindByName } from "@shared/lib/rawFind";
import { fakedMessages } from "./fluxIntercept"; import { editHistory, fakedMessages } from "./fluxIntercept";
const TAG = "[MessageLogger]"; const TAG = "[MessageLogger]";
function textNode(text: string) {
return { content: text, type: "text" };
}
// Confirmed live: message.content in the row JSON is an array of {content, type} rich-text nodes,
// not a plain string. Old versions get an inline "(edited)" tag of their own here, stacked above
// the current content - the current version keeps Discord's own native "(edited)" tag rather than
// getting a second one from here, since that already renders correctly on a genuinely-edited
// message with no help needed.
function applyEditHistory(message: any) {
const history = editHistory.get(message.id);
if (!history?.length) return;
const currentContent: any[] = Array.isArray(message.content) ? message.content : [textNode(String(message.content ?? ""))];
const nodes: any[] = [];
for (const oldContent of history) {
nodes.push(textNode(oldContent || "(empty)"));
nodes.push(textNode(" (edited)\n"));
}
nodes.push(...currentContent);
message.content = nodes;
}
// Confirmed live: whatever builds the row JSON sent across the native bridge only carries known // Confirmed live: whatever builds the row JSON sent across the native bridge only carries known
// schema fields through - a custom property set directly on the MessageRecord (confirmed present // schema fields through - a custom property set directly on the MessageRecord (confirmed present
// there via eval) never survives into row.message here. message.id does survive, though, so // there via eval) never survives into row.message here. message.id does survive, though, so
// checking membership in fluxIntercept's own fakedMessages map (already tracked there for onUnload // checking membership in fluxIntercept's own fakedMessages/editHistory maps (already tracked there
// cleanup) works where a custom flag on the row itself can't. // for onUnload cleanup / log capture) works where a custom flag on the row itself can't.
function handleRow(row: any) { function handleRow(row: any) {
const message = row?.message; const message = row?.message;
if (!message?.id || !fakedMessages.has(message.id)) return; if (!message?.id) return;
applyEditHistory(message);
if (!fakedMessages.has(message.id)) return;
message.edited = "deleted"; message.edited = "deleted";
message.textColor = ReactNative.processColor("#E4404380"); message.textColor = ReactNative.processColor("#E4404380");