import { useCallback, useEffect, useRef } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
export const UpdatePostConfirm = ({ inputs, onConfirm, onCancel, onRetry }) => {
const undoTextReplacements = useCallback(() => {
const replacements = inputs.replacements || [];
const reversed = replacements.map(({ original, updated }) => ({
original: updated,
updated: original,
}));
updateAllTextNodesAndAttributes(reversed);
}, [inputs]);
const confirmed = useRef(false);
useEffect(() => {
return () => {
if (!confirmed.current) undoTextReplacements();
};
}, []);
const handleConfirm = () => {
confirmed.current = true;
// The preview patched the DOM, so only a reload shows what was saved.
onConfirm({ data: inputs, shouldRefreshPage: true });
};
const handleRetry = useCallback(() => {
undoTextReplacements();
onRetry();
}, [undoTextReplacements, onRetry]);
useEffect(() => {
updateAllTextNodesAndAttributes(inputs.replacements);
}, [inputs.replacements]);
return (
{__(
'The agent has made the changes in the browser. Please review and confirm.',
'extendify-local',
)}
);
};
const PART_ID_ATTR = 'data-extendify-part-block-id';
// The save rewrites this post alone, so a part preview reverts on the reload.
const isInTemplatePart = (el) => Boolean(el?.closest?.(`[${PART_ID_ATTR}]`));
const updateAllTextNodesAndAttributes = (replacements) => {
const chat = document.getElementById('extendify-agent-chat');
const isInChat = (node) => chat?.contains(node);
// Update all text nodes
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false,
);
let node = walker.nextNode();
while (node) {
const current = node;
node = walker.nextNode();
if (isInChat(current.parentNode)) continue;
if (isInTemplatePart(current.parentElement)) continue;
for (const { original, updated } of replacements ?? []) {
const value = current.nodeValue ?? '';
if (!value.includes(original)) continue;
current.nodeValue = value.split(original).join(updated);
}
}
// Update attributes
['alt', 'title', 'aria-label', 'href', 'data-id'].forEach((attr) => {
document.querySelectorAll(`[${attr}]`).forEach((el) => {
if (isInChat(el)) return;
if (isInTemplatePart(el)) return;
for (const { original, updated } of replacements ?? []) {
const val = el.getAttribute(attr);
if (!val?.includes(original)) continue;
el.setAttribute(attr, val.split(original).join(updated));
}
});
});
};