import React from 'react'; import ReactDOM from 'react-dom/client'; import { ILlmActionRequest, ILlmInitAction, ModalDisplayStyle } from './common/interfaces'; import { App } from './App'; import { getTargetText, isTargetCkeditor, setTargetText } from './common/textUtil'; import { getPromptStreamResponse } from './common/adminApiUtil'; // Store the React root globally to avoid remounting let modalRoot: ReactDOM.Root | null = null; export const initModal = (action: ILlmInitAction) => { // Find the modal container const modalContainer: Element | null = document.querySelector('[data-wpj-modal-mount]'); if (!modalContainer) { console.error('Modal container with [data-wpj-modal-mount] not found.'); return; } // Create a root if it doesn't exist if (!modalRoot) { modalRoot = ReactDOM.createRoot(modalContainer); } const dataAttr = modalContainer.getAttribute('data-wpj-modal-mount'); const displayStyle = (dataAttr ? dataAttr : 'modal') as ModalDisplayStyle; // Render modal with updated data modalRoot.render( // , // , ); }; let applyGlobalAbort: ((reason?: string) => void) | null = null; export const applyAction = (action: ILlmInitAction, buttonId?: string) => { const body: ILlmActionRequest = { ...action, text: getTargetText(action.target), }; const buttonEl = document.getElementById(buttonId ?? ''); buttonEl?.classList.add('is-submitting'); // eslint-disable-next-line @typescript-eslint/no-unused-expressions applyGlobalAbort && applyGlobalAbort('applyUser'); applyGlobalAbort = null; let result = ''; // throttle update interval, because ckeditor behaves weirdly when update interval is too fast let updateInterval: any = null; updateInterval = isTargetCkeditor(action.target) && setInterval(() => { setTargetText(action.target, result); }, 700); const request = getPromptStreamResponse(body, (partialResponse) => { result = partialResponse; !isTargetCkeditor(action.target) && setTargetText(action.target, result); }); applyGlobalAbort = request.abort; request.promise .then(() => { setTargetText(action.target, result); buttonEl?.classList.remove('is-submitting'); }) .catch((reason) => { if (reason !== 'applyUser') { buttonEl?.classList.remove('is-submitting'); } }) .finally(() => { updateInterval && clearInterval(updateInterval); }); }; export const cancelAction = () => { // eslint-disable-next-line @typescript-eslint/no-unused-expressions applyGlobalAbort && applyGlobalAbort(); applyGlobalAbort = null; }; export function closeModal() { if (modalRoot) { modalRoot.unmount(); modalRoot = null; window.parent.postMessage({ event: 'llm-modal-closed', }); } }