mirror of
https://github.com/oobabooga/text-generation-webui.git
synced 2025-06-07 14:17:09 -04:00
159 lines
5.3 KiB
JavaScript
159 lines
5.3 KiB
JavaScript
function copyToClipboard(element) {
|
|
if (!element) return;
|
|
|
|
const messageElement = element.closest(".message, .user-message, .assistant-message");
|
|
if (!messageElement) return;
|
|
|
|
const rawText = messageElement.getAttribute("data-raw");
|
|
if (!rawText) return;
|
|
|
|
navigator.clipboard.writeText(rawText).then(function() {
|
|
const originalSvg = element.innerHTML;
|
|
element.innerHTML = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"text-green-500 dark:text-green-400\"><path d=\"M5 12l5 5l10 -10\"></path></svg>";
|
|
setTimeout(() => {
|
|
element.innerHTML = originalSvg;
|
|
}, 1000);
|
|
}).catch(function(err) {
|
|
console.error("Failed to copy text: ", err);
|
|
});
|
|
}
|
|
|
|
function branchHere(element) {
|
|
if (!element) return;
|
|
|
|
const messageElement = element.closest(".message, .user-message, .assistant-message");
|
|
if (!messageElement) return;
|
|
|
|
const index = messageElement.getAttribute("data-index");
|
|
if (!index) return;
|
|
|
|
const branchIndexInput = document.getElementById("Branch-index").querySelector("input");
|
|
if (!branchIndexInput) {
|
|
console.error("Element with ID 'Branch-index' not found.");
|
|
return;
|
|
}
|
|
const branchButton = document.getElementById("Branch");
|
|
|
|
if (!branchButton) {
|
|
console.error("Required element 'Branch' not found.");
|
|
return;
|
|
}
|
|
|
|
branchIndexInput.value = index;
|
|
|
|
// Trigger any 'change' or 'input' events Gradio might be listening for
|
|
const event = new Event("input", { bubbles: true }); // 'change' might also work
|
|
branchIndexInput.dispatchEvent(event);
|
|
|
|
branchButton.click(); // Gradio will now pick up the 'index'
|
|
|
|
}
|
|
|
|
function regenerateClick() {
|
|
document.getElementById("Regenerate").click();
|
|
}
|
|
|
|
function continueClick() {
|
|
document.getElementById("Continue").click();
|
|
}
|
|
|
|
function removeLastClick() {
|
|
document.getElementById("Remove-last").click();
|
|
}
|
|
|
|
// === Version navigation handled in main.js === //
|
|
|
|
function handleMorphdomUpdate(text) {
|
|
// Track open blocks
|
|
const openBlocks = new Set();
|
|
document.querySelectorAll(".thinking-block").forEach(block => {
|
|
const blockId = block.getAttribute("data-block-id");
|
|
// If block exists and is open, add to open set
|
|
if (blockId && block.hasAttribute("open")) {
|
|
openBlocks.add(blockId);
|
|
}
|
|
});
|
|
|
|
// Store scroll positions for any open blocks
|
|
const scrollPositions = {};
|
|
document.querySelectorAll(".thinking-block[open]").forEach(block => {
|
|
const content = block.querySelector(".thinking-content");
|
|
const blockId = block.getAttribute("data-block-id");
|
|
if (content && blockId) {
|
|
const isAtBottom = Math.abs((content.scrollHeight - content.scrollTop) - content.clientHeight) < 5;
|
|
scrollPositions[blockId] = {
|
|
position: content.scrollTop,
|
|
isAtBottom: isAtBottom
|
|
};
|
|
}
|
|
});
|
|
|
|
morphdom(
|
|
document.getElementById("chat").parentNode,
|
|
"<div class=\"prose svelte-1ybaih5\">" + text + "</div>",
|
|
{
|
|
onBeforeElUpdated: function(fromEl, toEl) {
|
|
// Preserve code highlighting
|
|
if (fromEl.tagName === "PRE" && fromEl.querySelector("code[data-highlighted]")) {
|
|
const fromCode = fromEl.querySelector("code");
|
|
const toCode = toEl.querySelector("code");
|
|
|
|
if (fromCode && toCode && fromCode.textContent === toCode.textContent) {
|
|
toEl.className = fromEl.className;
|
|
toEl.innerHTML = fromEl.innerHTML;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// For thinking blocks, assume closed by default
|
|
if (fromEl.classList && fromEl.classList.contains("thinking-block") &&
|
|
toEl.classList && toEl.classList.contains("thinking-block")) {
|
|
const blockId = toEl.getAttribute("data-block-id");
|
|
// Remove open attribute by default
|
|
toEl.removeAttribute("open");
|
|
// If this block was explicitly opened by user, keep it open
|
|
if (blockId && openBlocks.has(blockId)) {
|
|
toEl.setAttribute("open", "");
|
|
}
|
|
}
|
|
|
|
return !fromEl.isEqualNode(toEl);
|
|
},
|
|
|
|
onElUpdated: function(el) {
|
|
// Restore scroll positions for open thinking blocks
|
|
if (el.classList && el.classList.contains("thinking-block") && el.hasAttribute("open")) {
|
|
const blockId = el.getAttribute("data-block-id");
|
|
const content = el.querySelector(".thinking-content");
|
|
|
|
if (content && blockId && scrollPositions[blockId]) {
|
|
setTimeout(() => {
|
|
if (scrollPositions[blockId].isAtBottom) {
|
|
content.scrollTop = content.scrollHeight;
|
|
} else {
|
|
content.scrollTop = scrollPositions[blockId].position;
|
|
}
|
|
}, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
// Add toggle listeners for new blocks
|
|
document.querySelectorAll(".thinking-block").forEach(block => {
|
|
if (!block._hasToggleListener) {
|
|
block.addEventListener("toggle", function(e) {
|
|
if (this.open) {
|
|
const content = this.querySelector(".thinking-content");
|
|
if (content) {
|
|
setTimeout(() => {
|
|
content.scrollTop = content.scrollHeight;
|
|
}, 0);
|
|
}
|
|
}
|
|
});
|
|
block._hasToggleListener = true;
|
|
}
|
|
});
|
|
}
|