Add files via upload

This commit is contained in:
2025-10-06 19:53:48 +08:00
committed by GitHub
parent 880ab64313
commit 09a39b41fc
2 changed files with 2219 additions and 2223 deletions

View File

@@ -1,178 +1,184 @@
import { getMemoryState, getHighlights } from '../core/table-system/manager.js'; import { getMemoryState, getHighlights } from '../core/table-system/manager.js';
import { extension_settings } from '/scripts/extensions.js'; import { extension_settings } from '/scripts/extensions.js';
import { extensionName } from '../utils/settings.js'; import { extensionName } from '../utils/settings.js';
const TABLE_CONTAINER_ID = 'amily2-chat-table-container'; const TABLE_CONTAINER_ID = 'amily2-chat-table-container';
const isTouchDevice = () => window.matchMedia('(pointer: coarse)').matches; const isTouchDevice = () => window.matchMedia('(pointer: coarse)').matches;
function renderTablesToHtml(tables, highlights) { function renderTablesToHtml(tables, highlights) {
if (!tables || tables.length === 0) { if (!tables || tables.length === 0) {
return ''; return '';
} }
let html = ''; let html = '';
tables.forEach((table, tableIndex) => { tables.forEach((table, tableIndex) => {
if (table.rows && table.rows.length > 0) { if (table.rows && table.rows.length > 0) {
html += `<details class="amily2-chat-table-details">`; html += `<details class="amily2-chat-table-details">`;
html += `<summary class="amily2-chat-table-summary">${table.name}</summary>`; html += `<summary class="amily2-chat-table-summary">${table.name}</summary>`;
html += `<div class="amily2-chat-table" id="amily2-chat-table-${tableIndex}">`; html += `<div class="amily2-chat-table" id="amily2-chat-table-${tableIndex}">`;
html += '<table>'; html += '<table>';
html += '<thead><tr>'; html += '<thead><tr>';
table.headers.forEach(header => { table.headers.forEach(header => {
html += `<th>${header}</th>`; html += `<th>${header}</th>`;
}); });
html += '</tr></thead>'; html += '</tr></thead>';
html += '<tbody>'; html += '<tbody>';
table.rows.forEach((row, rowIndex) => { table.rows.forEach((row, rowIndex) => {
html += '<tr>'; html += '<tr>';
row.forEach((cell, colIndex) => { row.forEach((cell, colIndex) => {
const highlightKey = `${tableIndex}-${rowIndex}-${colIndex}`; const highlightKey = `${tableIndex}-${rowIndex}-${colIndex}`;
const isHighlighted = highlights.has(highlightKey); const isHighlighted = highlights.has(highlightKey);
const highlightClass = isHighlighted ? ' amily2-cell-highlight' : ''; const highlightClass = isHighlighted ? ' amily2-cell-highlight' : '';
html += `<td class="${highlightClass}">${cell}</td>`; html += `<td class="${highlightClass}">${cell}</td>`;
}); });
html += '</tr>'; html += '</tr>';
}); });
html += '</tbody>'; html += '</tbody>';
html += '</table>'; html += '</table>';
html += '</div>'; html += '</div>';
html += `</details>`; html += `</details>`;
} }
}); });
return html; return html;
} }
function removeTableContainer() { function removeTableContainer() {
const existingContainer = document.getElementById(TABLE_CONTAINER_ID); const existingContainer = document.getElementById(TABLE_CONTAINER_ID);
if (existingContainer) { if (existingContainer) {
existingContainer.remove(); existingContainer.remove();
} }
} }
function bindSwipePreventer(container) { function bindSwipePreventer(container) {
if (!isTouchDevice()) { if (!isTouchDevice()) {
return; return;
} }
let touchstartX = 0; let touchstartX = 0;
let touchstartY = 0; let touchstartY = 0;
container.addEventListener('touchstart', function(event) { container.addEventListener('touchstart', function(event) {
touchstartX = event.changedTouches[0].screenX; touchstartX = event.changedTouches[0].screenX;
touchstartY = event.changedTouches[0].screenY; touchstartY = event.changedTouches[0].screenY;
}, { passive: true }); }, { passive: true });
container.addEventListener('touchmove', function(event) { container.addEventListener('touchmove', function(event) {
const touchendX = event.changedTouches[0].screenX; const touchendX = event.changedTouches[0].screenX;
const touchendY = event.changedTouches[0].screenY; const touchendY = event.changedTouches[0].screenY;
const deltaX = Math.abs(touchendX - touchstartX); const deltaX = Math.abs(touchendX - touchstartX);
const deltaY = Math.abs(touchendY - touchstartY); const deltaY = Math.abs(touchendY - touchstartY);
if (deltaX > deltaY) { if (deltaX > deltaY) {
event.stopPropagation(); event.stopPropagation();
} }
}, { passive: false }); }, { passive: false });
} }
export function updateOrInsertTableInChat() { export function updateOrInsertTableInChat() {
setTimeout(() => { setTimeout(() => {
const settings = extension_settings[extensionName]; const settings = extension_settings[extensionName];
removeTableContainer(); removeTableContainer();
if (!settings || !settings.show_table_in_chat) { if (!settings || !settings.show_table_in_chat) {
return; return;
} }
const tables = getMemoryState(); const tables = getMemoryState();
if (!tables || tables.every(t => !t.rows || t.rows.length === 0)) { if (!tables || tables.every(t => !t.rows || t.rows.length === 0)) {
return; return;
} }
const highlights = getHighlights(); const highlights = getHighlights();
const htmlContent = renderTablesToHtml(tables, highlights); const htmlContent = renderTablesToHtml(tables, highlights);
if (!htmlContent) { if (!htmlContent) {
return; return;
} }
const lastMessage = document.querySelector('.last_mes .mes_text'); const lastMessage = document.querySelector('.last_mes .mes_text');
if (lastMessage) { if (lastMessage) {
const container = document.createElement('div'); const container = document.createElement('div');
container.id = TABLE_CONTAINER_ID; container.id = TABLE_CONTAINER_ID;
container.innerHTML = htmlContent; container.innerHTML = htmlContent;
lastMessage.appendChild(container);
bindSwipePreventer(container); // On mobile devices, add a specific class to enable horizontal scrolling via CSS
} else { if (isTouchDevice()) {
console.warn('[Amily2] 未找到最后一条消息的容器,无法插入表格。'); container.classList.add('mobile-table-view');
} }
}, 0);
} lastMessage.appendChild(container);
bindSwipePreventer(container);
function debounce(func, wait) { } else {
let timeout; console.warn('[Amily2] 未找到最后一条消息的容器,无法插入表格。');
return function executedFunction(...args) { }
const later = () => { }, 0);
clearTimeout(timeout); }
func(...args);
}; function debounce(func, wait) {
clearTimeout(timeout); let timeout;
timeout = setTimeout(later, wait); return function executedFunction(...args) {
}; const later = () => {
} clearTimeout(timeout);
func(...args);
let chatObserver = null; };
const debouncedUpdate = debounce(updateOrInsertTableInChat, 100); clearTimeout(timeout);
timeout = setTimeout(later, wait);
export function startContinuousRendering() { };
if (chatObserver) { }
console.log('[Amily2] Continuous rendering is already active.');
return; let chatObserver = null;
} const debouncedUpdate = debounce(updateOrInsertTableInChat, 100);
const chatContainer = document.getElementById('chat'); export function startContinuousRendering() {
if (!chatContainer) { if (chatObserver) {
console.error('[Amily2] Could not find chat container to observe.'); console.log('[Amily2] Continuous rendering is already active.');
setTimeout(startContinuousRendering, 500); return;
return; }
}
const chatContainer = document.getElementById('chat');
const observerConfig = { childList: true }; if (!chatContainer) {
console.error('[Amily2] Could not find chat container to observe.');
chatObserver = new MutationObserver((mutationsList, observer) => { setTimeout(startContinuousRendering, 500);
for (const mutation of mutationsList) { return;
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { }
let messageAdded = false;
mutation.addedNodes.forEach(node => { const observerConfig = { childList: true };
if (node.nodeType === 1 && node.classList.contains('mes')) {
messageAdded = true; chatObserver = new MutationObserver((mutationsList, observer) => {
} for (const mutation of mutationsList) {
}); if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
let messageAdded = false;
if (messageAdded) { mutation.addedNodes.forEach(node => {
debouncedUpdate(); if (node.nodeType === 1 && node.classList.contains('mes')) {
return; messageAdded = true;
} }
} });
}
}); if (messageAdded) {
debouncedUpdate();
chatObserver.observe(chatContainer, observerConfig); return;
console.log('[Amily2] Started continuous table rendering.'); }
updateOrInsertTableInChat(); }
} }
});
export function stopContinuousRendering() {
if (chatObserver) { chatObserver.observe(chatContainer, observerConfig);
chatObserver.disconnect(); console.log('[Amily2] Started continuous table rendering.');
chatObserver = null; updateOrInsertTableInChat();
removeTableContainer(); }
console.log('[Amily2] Stopped continuous table rendering.');
} export function stopContinuousRendering() {
} if (chatObserver) {
chatObserver.disconnect();
chatObserver = null;
removeTableContainer();
console.log('[Amily2] Stopped continuous table rendering.');
}
}

File diff suppressed because it is too large Load Diff