mirror of
https://github.com/SilenceLurker/ST-Amily2-Chat-Optimisation.git
synced 2026-06-06 20:35:51 +00:00
602 lines
23 KiB
JavaScript
602 lines
23 KiB
JavaScript
import { eventSource, event_types } from '/script.js';
|
|
import { extension_settings } from '/scripts/extensions.js';
|
|
import { extensionName } from '../../utils/settings.js';
|
|
|
|
const settings = {
|
|
sandboxMode: false,
|
|
useBlob: false,
|
|
wrapperIframe: true,
|
|
renderEnabled: true
|
|
};
|
|
|
|
const winMap = new Map();
|
|
let lastHeights = new WeakMap();
|
|
const blobUrls = new WeakMap();
|
|
const hashToBlobUrl = new Map();
|
|
const blobLRU = [];
|
|
const BLOB_CACHE_LIMIT = 32;
|
|
|
|
function generateUniqueId() {
|
|
return `amily2-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
}
|
|
|
|
function shouldRenderContentByBlock(codeBlock) {
|
|
if (!codeBlock) return false;
|
|
const content = (codeBlock.textContent || '').trim();
|
|
if (!content) return false;
|
|
return /^\s*<!doctype html/i.test(content) || /^\s*<html/i.test(content) || /<script/i.test(content);
|
|
}
|
|
|
|
function djb2(str) {
|
|
let h = 5381;
|
|
for (let i = 0; i < str.length; i++) {
|
|
h = ((h << 5) + h) ^ str.charCodeAt(i);
|
|
}
|
|
return (h >>> 0).toString(16);
|
|
}
|
|
|
|
function buildResourceHints(html) {
|
|
const urls = Array.from(new Set((html.match(/https?:\/\/[^"'()\s]+/gi) || []).map(u => { try { return new URL(u).origin } catch { return null } }).filter(Boolean)));
|
|
let hints = "";
|
|
const maxHosts = 6;
|
|
for (let i = 0; i < Math.min(urls.length, maxHosts); i++) {
|
|
const origin = urls[i];
|
|
hints += `<link rel="dns-prefetch" href="${origin}">`;
|
|
hints += `<link rel="preconnect" href="${origin}" crossorigin>`;
|
|
}
|
|
let preload = "";
|
|
const font = (html.match(/https?:\/\/[^"'()\s]+\.(?:woff2|woff|ttf|otf)/i) || [])[0];
|
|
if (font) {
|
|
const type = font.endsWith(".woff2") ? "font/woff2" : font.endsWith(".woff") ? "font/woff" : font.endsWith(".ttf") ? "font/ttf" : "font/otf";
|
|
preload += `<link rel="preload" as="font" href="${font}" type="${type}" crossorigin fetchpriority="high">`;
|
|
}
|
|
const css = (html.match(/https?:\/\/[^"'()\s]+\.css/i) || [])[0];
|
|
if (css) {
|
|
preload += `<link rel="preload" as="style" href="${css}" crossorigin fetchpriority="high">`;
|
|
}
|
|
const img = (html.match(/https?:\/\/[^"'()\s]+\.(?:png|jpg|jpeg|webp|gif|svg)/i) || [])[0];
|
|
if (img) {
|
|
preload += `<link rel="preload" as="image" href="${img}" crossorigin fetchpriority="high">`;
|
|
}
|
|
return hints + preload;
|
|
}
|
|
|
|
function iframeClientScript() {
|
|
return `
|
|
(function(){
|
|
function measureVisibleHeight(){
|
|
try{
|
|
var doc = document;
|
|
var target = doc.querySelector('.calendar-wrapper') || doc.body;
|
|
if(!target) return 0;
|
|
var minTop = Infinity, maxBottom = 0;
|
|
var addRect = function(el){
|
|
try{
|
|
var r = el.getBoundingClientRect();
|
|
if(r && r.height > 0){
|
|
if(minTop > r.top) minTop = r.top;
|
|
if(maxBottom < r.bottom) maxBottom = r.bottom;
|
|
}
|
|
}catch(e){}
|
|
};
|
|
addRect(target);
|
|
var children = target.children || [];
|
|
for(var i=0;i<children.length;i++){
|
|
var child = children[i];
|
|
if(!child) continue;
|
|
try{
|
|
var s = window.getComputedStyle(child);
|
|
if(s.display === 'none' || s.visibility === 'hidden') continue;
|
|
if(!child.offsetParent && s.position !== 'fixed') continue;
|
|
}catch(e){}
|
|
addRect(child);
|
|
}
|
|
return maxBottom > 0 ? Math.ceil(maxBottom - Math.min(minTop, 0)) : (target.scrollHeight || 0);
|
|
}catch(e){
|
|
return (document.body && document.body.scrollHeight) || 0;
|
|
}
|
|
} function post(m){ try{ parent.postMessage(m,'*') }catch(e){} }
|
|
var rafPending=false, lastH=0;
|
|
var HYSTERESIS = 2;
|
|
function send(force){
|
|
if(rafPending && !force) return;
|
|
rafPending = true;
|
|
requestAnimationFrame(function(){
|
|
rafPending = false;
|
|
var h = measureVisibleHeight();
|
|
if(force || Math.abs(h - lastH) >= HYSTERESIS){
|
|
lastH = h;
|
|
post({height:h, force:!!force});
|
|
}
|
|
});
|
|
}
|
|
try{ send(true) }catch(e){}
|
|
document.addEventListener('DOMContentLoaded', function(){ send(true) }, {once:true});
|
|
window.addEventListener('load', function(){ send(true) }, {once:true});
|
|
try{
|
|
if(document.fonts){
|
|
document.fonts.ready.then(function(){ send(true) }).catch(function(){});
|
|
if(document.fonts.addEventListener){
|
|
document.fonts.addEventListener('loadingdone', function(){ send(true) });
|
|
document.fonts.addEventListener('loadingerror', function(){ send(true) });
|
|
}
|
|
}
|
|
}catch(e){}
|
|
['transitionend','animationend'].forEach(function(evt){
|
|
document.addEventListener(evt, function(){ send(false) }, {passive:true, capture:true});
|
|
});
|
|
try{
|
|
var root = document.querySelector('.calendar-wrapper') || document.body || document.documentElement;
|
|
var ro = new ResizeObserver(function(){ send(false) });
|
|
ro.observe(root);
|
|
}catch(e){
|
|
try{
|
|
var rootMO = document.querySelector('.calendar-wrapper') || document.body || document.documentElement;
|
|
new MutationObserver(function(){ send(false) })
|
|
.observe(rootMO, {childList:true, subtree:true, attributes:true, characterData:true});
|
|
}catch(e){}
|
|
window.addEventListener('resize', function(){ send(false) }, {passive:true});
|
|
}
|
|
window.addEventListener('message', function(e){
|
|
var d = e && e.data || {};
|
|
if(d && d.type === 'probe') setTimeout(function(){ send(true) }, 10);
|
|
});
|
|
})();`;
|
|
}
|
|
|
|
function buildWrappedHtml(html) {
|
|
const origin = (typeof location !== 'undefined' && location.origin) ? location.origin : '';
|
|
const baseTag = settings && settings.useBlob ? `<base href="${origin}/">` : "";
|
|
const headHints = buildResourceHints(html);
|
|
const vhFix = `<style>html,body{height:auto!important;min-height:0!important;max-height:none!important}.profile-container,[style*="100vh"]{height:auto!important;min-height:600px!important}[style*="height:100%"]{height:auto!important;min-height:100%!important}</style>`;
|
|
|
|
const apiScript = `
|
|
<script>
|
|
window.makeRequest = function(request, data) {
|
|
return new Promise(function(resolve, reject) {
|
|
var uid = Date.now() + Math.random();
|
|
var callbackRequest = request + '_callback';
|
|
|
|
function handleMessage(event) {
|
|
var msgData = event.data || {};
|
|
if (msgData.request === callbackRequest && msgData.uid === uid) {
|
|
window.removeEventListener('message', handleMessage);
|
|
if (msgData.error) {
|
|
reject(new Error(msgData.error));
|
|
} else {
|
|
resolve(msgData.result);
|
|
}
|
|
}
|
|
}
|
|
|
|
window.addEventListener('message', handleMessage);
|
|
|
|
setTimeout(function() {
|
|
window.removeEventListener('message', handleMessage);
|
|
reject(new Error('请求 "' + request + '" 超时 (30秒)'));
|
|
}, 30000);
|
|
|
|
window.parent.postMessage({
|
|
source: 'amily2-iframe-request',
|
|
request: request,
|
|
uid: uid,
|
|
data: data
|
|
}, '*');
|
|
});
|
|
};
|
|
|
|
window.AmilyHelper = {
|
|
getChatMessages: function(range, options) {
|
|
return makeRequest('getChatMessages', { range: range, options: options });
|
|
},
|
|
setChatMessages: function(messages, options) {
|
|
return makeRequest('setChatMessages', { messages: messages, options: options });
|
|
},
|
|
setChatMessage: function(index, content) {
|
|
return makeRequest('setChatMessage', { index: index, content: content });
|
|
},
|
|
createChatMessages: function(messages, options) {
|
|
return makeRequest('createChatMessages', { messages: messages, options: options });
|
|
},
|
|
deleteChatMessages: function(ids, options) {
|
|
return makeRequest('deleteChatMessages', { ids: ids, options: options });
|
|
},
|
|
getLorebooks: function() {
|
|
return makeRequest('getLorebooks', {});
|
|
},
|
|
getCharLorebooks: function(options) {
|
|
return makeRequest('getCharLorebooks', { options: options });
|
|
},
|
|
getLorebookEntries: function(bookName) {
|
|
return makeRequest('getLorebookEntries', { bookName: bookName });
|
|
},
|
|
setLorebookEntries: function(bookName, entries) {
|
|
return makeRequest('setLorebookEntries', { bookName: bookName, entries: entries });
|
|
},
|
|
createLorebookEntries: function(bookName, entries) {
|
|
return makeRequest('createLorebookEntries', { bookName: bookName, entries: entries });
|
|
},
|
|
createLorebook: function(bookName) {
|
|
return makeRequest('createLorebook', { bookName: bookName });
|
|
},
|
|
triggerSlash: function(command) {
|
|
return makeRequest('triggerSlash', { command: command });
|
|
},
|
|
getLastMessageId: function() {
|
|
return makeRequest('getLastMessageId', {});
|
|
},
|
|
toastr: function(type, message, title) {
|
|
return makeRequest('toastr', { type: type, message: message, title: title });
|
|
}
|
|
};
|
|
|
|
if (!window.TavernHelper) {
|
|
window.TavernHelper = window.AmilyHelper;
|
|
console.log('[Amily2-Iframe] TavernHelper 别名已创建');
|
|
} else {
|
|
console.log('[Amily2-Iframe] 检测到已存在的 TavernHelper,保持原有实现');
|
|
}
|
|
|
|
window.triggerSlash = function(command) {
|
|
return makeRequest('triggerSlash', { command: command });
|
|
};
|
|
|
|
window.getChatMessages = function(range, options) {
|
|
return makeRequest('getChatMessages', { range: range, options: options });
|
|
};
|
|
|
|
window.setChatMessages = function(messages, options) {
|
|
return makeRequest('setChatMessages', { messages: messages, options: options });
|
|
};
|
|
|
|
window.setChatMessage = function(field_values, message_id, options) {
|
|
return makeRequest('setChatMessage', {
|
|
field_values: field_values,
|
|
message_id: message_id,
|
|
options: options || {}
|
|
});
|
|
};
|
|
|
|
window.switchSwipe = function(messageIndex, swipeIndex) {
|
|
return makeRequest('switchSwipe', { messageIndex: messageIndex, swipeIndex: swipeIndex });
|
|
};
|
|
|
|
window.createChatMessages = function(messages, options) {
|
|
return makeRequest('createChatMessages', { messages: messages, options: options });
|
|
};
|
|
|
|
window.deleteChatMessages = function(ids, options) {
|
|
return makeRequest('deleteChatMessages', { ids: ids, options: options });
|
|
};
|
|
|
|
window.getLorebooks = function() {
|
|
return makeRequest('getLorebooks', {});
|
|
};
|
|
|
|
window.getCharLorebooks = function(options) {
|
|
return makeRequest('getCharLorebooks', { options: options });
|
|
};
|
|
|
|
window.getLorebookEntries = function(bookName) {
|
|
return makeRequest('getLorebookEntries', { bookName: bookName });
|
|
};
|
|
|
|
window.setLorebookEntries = function(bookName, entries) {
|
|
return makeRequest('setLorebookEntries', { bookName: bookName, entries: entries });
|
|
};
|
|
|
|
window.createLorebookEntries = function(bookName, entries) {
|
|
return makeRequest('createLorebookEntries', { bookName: bookName, entries: entries });
|
|
};
|
|
|
|
window.createLorebook = function(bookName) {
|
|
return makeRequest('createLorebook', { bookName: bookName });
|
|
};
|
|
|
|
window.getLastMessageId = function() {
|
|
return makeRequest('getLastMessageId', {});
|
|
};
|
|
|
|
window.getVariables = function(options) {
|
|
return makeRequest('getVariables', { options: options });
|
|
};
|
|
|
|
window.setVariables = function(variables, options) {
|
|
return makeRequest('setVariables', { variables: variables, options: options });
|
|
};
|
|
|
|
window.deleteVariable = function(variablePath, options) {
|
|
return makeRequest('deleteVariable', { variablePath: variablePath, options: options });
|
|
};
|
|
|
|
window.getCharData = function(name) {
|
|
return makeRequest('getCharData', { name: name });
|
|
};
|
|
|
|
window.getCharAvatarPath = function(name) {
|
|
return makeRequest('getCharAvatarPath', { name: name });
|
|
};
|
|
|
|
window.getLorebookSettings = function() {
|
|
return makeRequest('getLorebookSettings', {});
|
|
};
|
|
|
|
window.setLorebookSettings = function(settings) {
|
|
return makeRequest('setLorebookSettings', { settings: settings });
|
|
};
|
|
|
|
window.getChatLorebook = function() {
|
|
return makeRequest('getChatLorebook', {});
|
|
};
|
|
|
|
window.setChatLorebook = function(lorebook) {
|
|
return makeRequest('setChatLorebook', { lorebook: lorebook });
|
|
};
|
|
|
|
window.substitudeMacros = function(text) {
|
|
return makeRequest('substitudeMacros', { text: text });
|
|
};
|
|
|
|
window.toastr = {
|
|
success: function(message, title) {
|
|
return makeRequest('toastr', { type: 'success', message: message, title: title });
|
|
},
|
|
info: function(message, title) {
|
|
return makeRequest('toastr', { type: 'info', message: message, title: title });
|
|
},
|
|
warning: function(message, title) {
|
|
return makeRequest('toastr', { type: 'warning', message: message, title: title });
|
|
},
|
|
warn: function(message, title) {
|
|
return makeRequest('toastr', { type: 'warning', message: message, title: title });
|
|
},
|
|
error: function(message, title) {
|
|
return makeRequest('toastr', { type: 'error', message: message, title: title });
|
|
}
|
|
};
|
|
|
|
console.log('[Amily2-Iframe] 完整的 API 已加载到全局作用域');
|
|
console.log('[Amily2-Iframe] 可用的全局对象: AmilyHelper, TavernHelper');
|
|
console.log('[Amily2-Iframe] 可用的全局函数: triggerSlash, getChatMessages, setChatMessage, toastr, 等');
|
|
</script>
|
|
<script type="module" src="/scripts/extensions/third-party/${extensionName}/core/tavern-helper/iframe_client.js"></script>
|
|
`;
|
|
|
|
const injectionBlock = `
|
|
${baseTag}
|
|
<script>${iframeClientScript()}</script>
|
|
${headHints}
|
|
${vhFix}
|
|
${apiScript}
|
|
`;
|
|
|
|
const isFullHtml = /<html/i.test(html) && /<\/html>/i.test(html);
|
|
|
|
if (isFullHtml) {
|
|
if (html.includes('</head>')) {
|
|
return html.replace('</head>', `${injectionBlock}</head>`);
|
|
} else if (html.includes('<body')) {
|
|
return html.replace('<body', `<head>${injectionBlock}</head><body`);
|
|
}
|
|
return `<!DOCTYPE html>${injectionBlock}${html}`;
|
|
}
|
|
|
|
return `<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="color-scheme" content="dark light">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<style>html,body{margin:0;padding:0;background:transparent;font-family:inherit;color:inherit}</style>
|
|
${injectionBlock}
|
|
</head>
|
|
<body>${html}</body></html>`;
|
|
}
|
|
|
|
|
|
function getOrCreateWrapper(preEl) {
|
|
let wrapper = preEl.previousElementSibling;
|
|
if (!wrapper || !wrapper.classList.contains('amily2-iframe-wrapper')) {
|
|
wrapper = document.createElement('div');
|
|
wrapper.className = 'amily2-iframe-wrapper';
|
|
wrapper.style.cssText = 'margin:0;';
|
|
preEl.parentNode.insertBefore(wrapper, preEl);
|
|
}
|
|
return wrapper;
|
|
}
|
|
|
|
function registerIframeMapping(iframe, wrapper) {
|
|
const tryMap = () => {
|
|
try {
|
|
if (iframe && iframe.contentWindow) {
|
|
winMap.set(iframe.contentWindow, { iframe, wrapper });
|
|
return true;
|
|
}
|
|
} catch (e) { }
|
|
return false;
|
|
};
|
|
if (tryMap()) return;
|
|
let tries = 0;
|
|
const t = setInterval(() => {
|
|
tries++;
|
|
if (tryMap() || tries > 20) clearInterval(t);
|
|
}, 25);
|
|
}
|
|
|
|
function handleIframeMessage(event) {
|
|
const data = event.data || {};
|
|
let rec = winMap.get(event.source);
|
|
if (!rec || !rec.iframe) {
|
|
const iframes = document.querySelectorAll('iframe.amily2-iframe');
|
|
for (const iframe of iframes) {
|
|
if (iframe.contentWindow === event.source) {
|
|
rec = { iframe, wrapper: iframe.parentElement };
|
|
winMap.set(event.source, rec);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (rec && rec.iframe && typeof data.height === 'number') {
|
|
const next = Math.max(0, Number(data.height) || 0);
|
|
if (next < 1) return;
|
|
const prev = lastHeights.get(rec.iframe) || 0;
|
|
if (!data.force && Math.abs(next - prev) < 1) return;
|
|
lastHeights.set(rec.iframe, next);
|
|
requestAnimationFrame(() => { rec.iframe.style.height = `${next}px`; });
|
|
}
|
|
}
|
|
|
|
function setIframeBlobHTML(iframe, fullHTML, codeHash) {
|
|
const existing = hashToBlobUrl.get(codeHash);
|
|
if (existing) {
|
|
iframe.src = existing;
|
|
blobUrls.set(iframe, existing);
|
|
return;
|
|
}
|
|
const blob = new Blob([fullHTML], { type: 'text/html' });
|
|
const url = URL.createObjectURL(blob);
|
|
iframe.src = url;
|
|
blobUrls.set(iframe, url);
|
|
hashToBlobUrl.set(codeHash, url);
|
|
blobLRU.push(codeHash);
|
|
while (blobLRU.length > BLOB_CACHE_LIMIT) {
|
|
const old = blobLRU.shift();
|
|
const u = hashToBlobUrl.get(old);
|
|
hashToBlobUrl.delete(old);
|
|
try { URL.revokeObjectURL(u) } catch (e) { }
|
|
}
|
|
}
|
|
|
|
function releaseIframeBlob(iframe) {
|
|
try {
|
|
const url = blobUrls.get(iframe);
|
|
if (url) URL.revokeObjectURL(url);
|
|
blobUrls.delete(iframe);
|
|
} catch (e) { }
|
|
}
|
|
|
|
function renderHtmlInIframe(htmlContent, container, preElement) {
|
|
try {
|
|
const originalHash = djb2(htmlContent);
|
|
const iframe = document.createElement('iframe');
|
|
iframe.id = generateUniqueId();
|
|
iframe.className = 'amily2-iframe';
|
|
iframe.style.cssText = 'width:100%;border:none;background:transparent;overflow:hidden;height:0;margin:0;padding:0;display:block;contain:layout paint style;will-change:height;min-height:50px';
|
|
iframe.setAttribute('frameborder', '0');
|
|
iframe.setAttribute('scrolling', 'no');
|
|
iframe.loading = 'eager';
|
|
if (settings.sandboxMode) {
|
|
iframe.setAttribute('sandbox', 'allow-scripts allow-modals');
|
|
} else {
|
|
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-modals allow-popups');
|
|
}
|
|
const wrapper = getOrCreateWrapper(preElement);
|
|
wrapper.querySelectorAll('.amily2-iframe').forEach(old => {
|
|
try { old.src = 'about:blank'; } catch (e) { }
|
|
releaseIframeBlob(old);
|
|
old.remove();
|
|
});
|
|
const codeHash = djb2(htmlContent);
|
|
const full = buildWrappedHtml(htmlContent);
|
|
if (settings.useBlob) {
|
|
setIframeBlobHTML(iframe, full, codeHash);
|
|
} else {
|
|
iframe.srcdoc = full;
|
|
}
|
|
wrapper.appendChild(iframe);
|
|
preElement.classList.remove('xb-show');
|
|
preElement.style.display = 'none';
|
|
registerIframeMapping(iframe, wrapper);
|
|
try { iframe.contentWindow?.postMessage({ type: 'probe' }, '*'); } catch (e) { }
|
|
preElement.dataset.xbFinal = 'true';
|
|
preElement.dataset.xbHash = originalHash;
|
|
return iframe;
|
|
} catch (err) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function processCodeBlocks(messageElement) {
|
|
if (extension_settings[extensionName].render_enabled === false) return;
|
|
try {
|
|
const codeBlocks = messageElement.querySelectorAll('pre > code');
|
|
codeBlocks.forEach(codeBlock => {
|
|
const preElement = codeBlock.parentElement;
|
|
const should = shouldRenderContentByBlock(codeBlock);
|
|
const html = codeBlock.textContent || '';
|
|
const hash = djb2(html);
|
|
const isFinal = preElement.dataset.xbFinal === 'true';
|
|
const same = preElement.dataset.xbHash === hash;
|
|
if (isFinal && same) return;
|
|
if (should) {
|
|
renderHtmlInIframe(html, preElement.parentNode, preElement);
|
|
} else {
|
|
preElement.classList.add('xb-show');
|
|
preElement.removeAttribute('data-xbfinal');
|
|
preElement.removeAttribute('data-xbhash');
|
|
preElement.style.display = '';
|
|
}
|
|
preElement.dataset.xiaobaixBound = 'true';
|
|
});
|
|
} catch (err) {
|
|
console.error('[Amily2-Renderer] Error during processCodeBlocks:', err);
|
|
}
|
|
}
|
|
|
|
function processMessageById(messageId) {
|
|
const messageElement = document.querySelector(`div.mes[mesid="${messageId}"] .mes_text`);
|
|
if (!messageElement) return;
|
|
processCodeBlocks(messageElement);
|
|
}
|
|
|
|
export function initializeRenderer() {
|
|
const handleMessage = (data) => {
|
|
const messageId = typeof data === 'object' ? data.messageId : data;
|
|
if (messageId == null) return;
|
|
console.log('[Amily2-Renderer] 处理消息渲染:', messageId);
|
|
setTimeout(() => processMessageById(messageId), 50);
|
|
};
|
|
|
|
eventSource.on(event_types.MESSAGE_RECEIVED, handleMessage);
|
|
eventSource.on(event_types.MESSAGE_UPDATED, handleMessage);
|
|
eventSource.on(event_types.MESSAGE_SWIPED, handleMessage);
|
|
eventSource.on(event_types.MESSAGE_EDITED, handleMessage);
|
|
eventSource.on(event_types.USER_MESSAGE_RENDERED, handleMessage);
|
|
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, handleMessage);
|
|
eventSource.on(event_types.IMPERSONATE_READY, handleMessage);
|
|
|
|
eventSource.on(event_types.CHAT_CHANGED, () => {
|
|
console.log('[Amily2-Renderer] 聊天已切换,重新渲染所有 iframe');
|
|
setTimeout(renderAllIframes, 100);
|
|
});
|
|
|
|
window.addEventListener('message', handleIframeMessage);
|
|
|
|
console.log('[Amily2-Renderer] 渲染器已初始化,监听事件: MESSAGE_RECEIVED, MESSAGE_UPDATED, MESSAGE_SWIPED, MESSAGE_EDITED, USER_MESSAGE_RENDERED, CHARACTER_MESSAGE_RENDERED, IMPERSONATE_READY');
|
|
}
|
|
|
|
export function renderAllIframes() {
|
|
const messages = document.querySelectorAll('.mes');
|
|
messages.forEach(message => {
|
|
const messageId = message.getAttribute('mesid');
|
|
if (messageId) {
|
|
processMessageById(messageId);
|
|
}
|
|
});
|
|
}
|
|
|
|
export function clearAllIframes() {
|
|
const iframes = document.querySelectorAll('.amily2-iframe');
|
|
iframes.forEach(iframe => {
|
|
const wrapper = iframe.parentElement;
|
|
if (wrapper && wrapper.classList.contains('amily2-iframe-wrapper')) {
|
|
const preElement = wrapper.nextElementSibling;
|
|
if (preElement && preElement.tagName === 'PRE') {
|
|
preElement.classList.add('xb-show');
|
|
preElement.style.display = '';
|
|
}
|
|
wrapper.remove();
|
|
}
|
|
});
|
|
}
|