mirror of
https://github.com/oobabooga/text-generation-webui.git
synced 2026-04-05 14:45:28 +00:00
Several small code simplifications
This commit is contained in:
parent
0466b6e271
commit
6382fbef83
9 changed files with 140 additions and 235 deletions
|
|
@ -158,28 +158,21 @@ class ModelDownloader:
|
|||
# Also if GGUF and safetensors are available, download only safetensors
|
||||
if (has_pytorch or has_pt or has_gguf) and has_safetensors:
|
||||
has_gguf = False
|
||||
for i in range(len(classifications) - 1, -1, -1):
|
||||
if classifications[i] in ['pytorch', 'pt', 'gguf']:
|
||||
links.pop(i)
|
||||
file_sizes.pop(i)
|
||||
keep = [i for i, c in enumerate(classifications) if c not in ['pytorch', 'pt', 'gguf']]
|
||||
links = [links[i] for i in keep]
|
||||
file_sizes = [file_sizes[i] for i in keep]
|
||||
|
||||
# For GGUF, try to download only the Q4_K_M if no specific file is specified.
|
||||
if has_gguf and specific_file is None:
|
||||
has_q4km = False
|
||||
for i in range(len(classifications) - 1, -1, -1):
|
||||
if 'q4_k_m' in links[i].lower():
|
||||
has_q4km = True
|
||||
has_q4km = any('q4_k_m' in link.lower() for link in links)
|
||||
|
||||
if has_q4km:
|
||||
for i in range(len(classifications) - 1, -1, -1):
|
||||
if 'q4_k_m' not in links[i].lower():
|
||||
links.pop(i)
|
||||
file_sizes.pop(i)
|
||||
keep = [i for i, link in enumerate(links) if 'q4_k_m' in link.lower()]
|
||||
else:
|
||||
for i in range(len(classifications) - 1, -1, -1):
|
||||
if links[i].lower().endswith('.gguf'):
|
||||
links.pop(i)
|
||||
file_sizes.pop(i)
|
||||
keep = [i for i, link in enumerate(links) if not link.lower().endswith('.gguf')]
|
||||
|
||||
links = [links[i] for i in keep]
|
||||
file_sizes = [file_sizes[i] for i in keep]
|
||||
|
||||
is_llamacpp = has_gguf and specific_file is not None
|
||||
return links, sha256, is_lora, is_llamacpp, file_sizes
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
function toggleDarkMode() {
|
||||
document.body.classList.toggle("dark");
|
||||
var currentCSS = document.getElementById("highlight-css");
|
||||
const currentCSS = document.getElementById("highlight-css");
|
||||
if (currentCSS.getAttribute("href") === "file/css/highlightjs/github-dark.min.css") {
|
||||
currentCSS.setAttribute("href", "file/css/highlightjs/github.min.css");
|
||||
} else {
|
||||
|
|
@ -9,12 +9,10 @@ function toggleDarkMode() {
|
|||
|
||||
// Re-highlight all code blocks once stylesheet loads
|
||||
currentCSS.onload = function() {
|
||||
const messageBodies = document.getElementById("chat").querySelectorAll(".message-body");
|
||||
messageBodies.forEach((messageBody) => {
|
||||
const codeBlocks = messageBody.querySelectorAll("pre code");
|
||||
codeBlocks.forEach((codeBlock) => {
|
||||
hljs.highlightElement(codeBlock);
|
||||
});
|
||||
// Clear data-highlighted so hljs will re-process with the new theme
|
||||
document.querySelectorAll("#chat .message-body pre code[data-highlighted]").forEach((codeBlock) => {
|
||||
delete codeBlock.dataset.highlighted;
|
||||
});
|
||||
doSyntaxHighlighting();
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,35 @@
|
|||
// -------------------------------------------------
|
||||
// Shared helpers
|
||||
// -------------------------------------------------
|
||||
|
||||
function getProfilePictureUrl() {
|
||||
return "/file/user_data/cache/pfp_character.png?time=" + Date.now();
|
||||
}
|
||||
|
||||
const MESSAGE_SELECTOR = ".message, .user-message, .assistant-message";
|
||||
|
||||
function getMessageElement(element) {
|
||||
if (!element) return null;
|
||||
return element.closest(MESSAGE_SELECTOR);
|
||||
}
|
||||
|
||||
function isUserRole(messageElement) {
|
||||
return messageElement.classList.contains("user-message") ||
|
||||
messageElement.querySelector(".text-you") !== null ||
|
||||
messageElement.querySelector(".circle-you") !== null;
|
||||
}
|
||||
|
||||
// Trigger a synthetic 'input' event so Gradio picks up programmatic value changes
|
||||
function dispatchGradioInput(element) {
|
||||
element.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
// Event handlers
|
||||
// -------------------------------------------------
|
||||
|
||||
function copyToClipboard(element) {
|
||||
if (!element) return;
|
||||
|
||||
const messageElement = element.closest(".message, .user-message, .assistant-message");
|
||||
const messageElement = getMessageElement(element);
|
||||
if (!messageElement) return;
|
||||
|
||||
const rawText = messageElement.getAttribute("data-raw");
|
||||
|
|
@ -48,9 +72,7 @@ function fallbackCopyToClipboard(text) {
|
|||
}
|
||||
|
||||
function branchHere(element) {
|
||||
if (!element) return;
|
||||
|
||||
const messageElement = element.closest(".message, .user-message, .assistant-message");
|
||||
const messageElement = getMessageElement(element);
|
||||
if (!messageElement) return;
|
||||
|
||||
const index = messageElement.getAttribute("data-index");
|
||||
|
|
@ -69,11 +91,7 @@ function branchHere(element) {
|
|||
}
|
||||
|
||||
branchIndexInput.value = index;
|
||||
|
||||
// Trigger any 'change' or 'input' events Gradio might be listening for
|
||||
const event = new Event("input", { bubbles: true });
|
||||
branchIndexInput.dispatchEvent(event);
|
||||
|
||||
dispatchGradioInput(branchIndexInput);
|
||||
branchButton.click();
|
||||
}
|
||||
|
||||
|
|
@ -82,9 +100,7 @@ function branchHere(element) {
|
|||
// -------------------------------------------------
|
||||
|
||||
function editHere(buttonElement) {
|
||||
if (!buttonElement) return;
|
||||
|
||||
const messageElement = buttonElement.closest(".message, .user-message, .assistant-message");
|
||||
const messageElement = getMessageElement(buttonElement);
|
||||
if (!messageElement) return;
|
||||
|
||||
const messageBody = messageElement.querySelector(".message-body");
|
||||
|
|
@ -97,12 +113,7 @@ function editHere(buttonElement) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Determine role based on message element - handle different chat modes
|
||||
const isUserMessage = messageElement.classList.contains("user-message") ||
|
||||
messageElement.querySelector(".text-you") !== null ||
|
||||
messageElement.querySelector(".circle-you") !== null;
|
||||
|
||||
startEditing(messageElement, messageBody, isUserMessage);
|
||||
startEditing(messageElement, messageBody, isUserRole(messageElement));
|
||||
}
|
||||
|
||||
function startEditing(messageElement, messageBody, isUserMessage) {
|
||||
|
|
@ -209,30 +220,22 @@ function submitMessageEdit(index, newText, isUserMessage) {
|
|||
editTextInput.value = newText;
|
||||
editRoleInput.value = isUserMessage ? "user" : "assistant";
|
||||
|
||||
editIndexInput.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
editTextInput.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
editRoleInput.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
dispatchGradioInput(editIndexInput);
|
||||
dispatchGradioInput(editTextInput);
|
||||
dispatchGradioInput(editRoleInput);
|
||||
|
||||
editButton.click();
|
||||
return true;
|
||||
}
|
||||
|
||||
function navigateVersion(element, direction) {
|
||||
if (!element) return;
|
||||
|
||||
const messageElement = element.closest(".message, .user-message, .assistant-message");
|
||||
const messageElement = getMessageElement(element);
|
||||
if (!messageElement) return;
|
||||
|
||||
const index = messageElement.getAttribute("data-index");
|
||||
if (!index) return;
|
||||
|
||||
// Determine role based on message element classes
|
||||
let role = "assistant"; // Default role
|
||||
if (messageElement.classList.contains("user-message") ||
|
||||
messageElement.querySelector(".text-you") ||
|
||||
messageElement.querySelector(".circle-you")) {
|
||||
role = "user";
|
||||
}
|
||||
const role = isUserRole(messageElement) ? "user" : "assistant";
|
||||
|
||||
const indexInput = document.getElementById("Navigate-message-index")?.querySelector("input");
|
||||
const directionInput = document.getElementById("Navigate-direction")?.querySelector("textarea");
|
||||
|
|
@ -248,11 +251,9 @@ function navigateVersion(element, direction) {
|
|||
directionInput.value = direction;
|
||||
roleInput.value = role;
|
||||
|
||||
// Trigger 'input' events for Gradio to pick up changes
|
||||
const event = new Event("input", { bubbles: true });
|
||||
indexInput.dispatchEvent(event);
|
||||
directionInput.dispatchEvent(event);
|
||||
roleInput.dispatchEvent(event);
|
||||
dispatchGradioInput(indexInput);
|
||||
dispatchGradioInput(directionInput);
|
||||
dispatchGradioInput(roleInput);
|
||||
|
||||
navigateButton.click();
|
||||
}
|
||||
|
|
@ -313,7 +314,7 @@ function handleMorphdomUpdate(data) {
|
|||
|
||||
function applyMorphdomUpdate(data) {
|
||||
// Determine target element and use it as query scope
|
||||
var target_element, target_html;
|
||||
let target_element, target_html;
|
||||
if (data.last_message_only) {
|
||||
const childNodes = document.getElementsByClassName("messages")[0].childNodes;
|
||||
target_element = childNodes[childNodes.length - 1];
|
||||
|
|
|
|||
171
js/main.js
171
js/main.js
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
// Sync highlight.js theme with the actual Gradio theme
|
||||
var defined_hljs_css = document.body.classList.contains("dark") ? "file/css/highlightjs/github-dark.min.css" : "file/css/highlightjs/github.min.css";
|
||||
if (document.getElementById("highlight-css").getAttribute("href") !== defined_hljs_css) {
|
||||
document.getElementById("highlight-css").setAttribute("href", defined_hljs_css);
|
||||
var hljsCssElement = document.getElementById("highlight-css");
|
||||
if (hljsCssElement.getAttribute("href") !== defined_hljs_css) {
|
||||
hljsCssElement.setAttribute("href", defined_hljs_css);
|
||||
}
|
||||
|
||||
let main_parent = document.getElementById("chat-tab").parentNode;
|
||||
|
|
@ -49,21 +50,18 @@ document.querySelector(".header_bar").addEventListener("click", function(event)
|
|||
//------------------------------------------------
|
||||
|
||||
// --- Helper functions --- //
|
||||
function isModifiedKeyboardEvent() {
|
||||
return (event instanceof KeyboardEvent &&
|
||||
event.shiftKey ||
|
||||
event.ctrlKey ||
|
||||
event.altKey ||
|
||||
event.metaKey);
|
||||
function isModifiedKeyboardEvent(event) {
|
||||
return event instanceof KeyboardEvent &&
|
||||
(event.shiftKey || event.ctrlKey || event.altKey || event.metaKey);
|
||||
}
|
||||
|
||||
function isFocusedOnEditableTextbox() {
|
||||
function isFocusedOnEditableTextbox(event) {
|
||||
if (event.target.tagName === "INPUT" || event.target.tagName === "TEXTAREA") {
|
||||
return !!event.target.value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
let previousTabId = "chat-tab-button";
|
||||
document.addEventListener("keydown", function(event) {
|
||||
// Stop generation on Esc pressed
|
||||
if (event.key === "Escape") {
|
||||
|
|
@ -117,14 +115,14 @@ document.addEventListener("keydown", function(event) {
|
|||
}
|
||||
|
||||
// --- Simple version navigation --- //
|
||||
if (!isFocusedOnEditableTextbox()) {
|
||||
if (!isFocusedOnEditableTextbox(event)) {
|
||||
// Version navigation on Arrow keys (horizontal)
|
||||
if (!isModifiedKeyboardEvent() && event.key === "ArrowLeft") {
|
||||
if (!isModifiedKeyboardEvent(event) && event.key === "ArrowLeft") {
|
||||
event.preventDefault();
|
||||
navigateLastAssistantMessage("left");
|
||||
}
|
||||
|
||||
else if (!isModifiedKeyboardEvent() && event.key === "ArrowRight") {
|
||||
else if (!isModifiedKeyboardEvent(event) && event.key === "ArrowRight") {
|
||||
event.preventDefault();
|
||||
if (!navigateLastAssistantMessage("right")) {
|
||||
// If can't navigate right (last version), regenerate
|
||||
|
|
@ -159,9 +157,8 @@ targetElement.addEventListener("scroll", function() {
|
|||
let diff = targetElement.scrollHeight - targetElement.clientHeight;
|
||||
let isAtBottomNow = Math.abs(targetElement.scrollTop - diff) <= 10 || diff <= 0;
|
||||
|
||||
// Add scrolling class to disable hover effects
|
||||
if (window.isScrolled || !isAtBottomNow) {
|
||||
targetElement.classList.add("scrolling");
|
||||
targetElement.classList.add("scrolling"); // Disables hover effects during scroll
|
||||
}
|
||||
|
||||
if(isAtBottomNow) {
|
||||
|
|
@ -202,12 +199,8 @@ const observer = new MutationObserver(function() {
|
|||
});
|
||||
|
||||
// Only watch for attribute changes on targetElement (e.g. _generating class)
|
||||
const config = {
|
||||
attributes: true
|
||||
};
|
||||
|
||||
// Start observing the target element
|
||||
observer.observe(targetElement, config);
|
||||
observer.observe(targetElement, { attributes: true });
|
||||
|
||||
//------------------------------------------------
|
||||
// Handle syntax highlighting / LaTeX
|
||||
|
|
@ -228,7 +221,7 @@ window.doSyntaxHighlighting = function() {
|
|||
if (messageBodies.length > 0) {
|
||||
let hasSeenVisible = false;
|
||||
|
||||
// Go from last message to first
|
||||
// Go from last message to first so we can early-exit once past visible area
|
||||
for (let i = messageBodies.length - 1; i >= 0; i--) {
|
||||
const messageBody = messageBodies[i];
|
||||
|
||||
|
|
@ -243,8 +236,8 @@ window.doSyntaxHighlighting = function() {
|
|||
codeBlock.classList.add("pretty_scrollbar");
|
||||
});
|
||||
|
||||
// Only render math in visible elements
|
||||
const mathContainers = messageBody.querySelectorAll("p, span, li, td, th, h1, h2, h3, h4, h5, h6, blockquote, figcaption, caption, dd, dt");
|
||||
// Only render math in individually visible containers (the outer check is on the message body)
|
||||
mathContainers.forEach(container => {
|
||||
if (isElementVisibleOnScreen(container)) {
|
||||
renderMathInElement(container, {
|
||||
|
|
@ -271,7 +264,7 @@ const doSyntaxHighlighting = window.doSyntaxHighlighting;
|
|||
// Add some scrollbars
|
||||
//------------------------------------------------
|
||||
const scrollbarElements = document.querySelectorAll(".add_scrollbar textarea, .add_scrollbar .drag-drop-list");
|
||||
for(i = 0; i < scrollbarElements.length; i++) {
|
||||
for(let i = 0; i < scrollbarElements.length; i++) {
|
||||
scrollbarElements[i].classList.remove("scroll-hide");
|
||||
scrollbarElements[i].classList.add("pretty_scrollbar");
|
||||
scrollbarElements[i].style.resize = "none";
|
||||
|
|
@ -298,13 +291,13 @@ if (toolsInfo) {
|
|||
// Remove some backgrounds
|
||||
//------------------------------------------------
|
||||
const noBackgroundelements = document.querySelectorAll(".no-background");
|
||||
for(i = 0; i < noBackgroundelements.length; i++) {
|
||||
for(let i = 0; i < noBackgroundelements.length; i++) {
|
||||
noBackgroundelements[i].parentNode.style.border = "none";
|
||||
noBackgroundelements[i].parentNode.parentNode.parentNode.style.alignItems = "center";
|
||||
}
|
||||
|
||||
const slimDropdownElements = document.querySelectorAll(".slim-dropdown");
|
||||
for (i = 0; i < slimDropdownElements.length; i++) {
|
||||
for (let i = 0; i < slimDropdownElements.length; i++) {
|
||||
const parentNode = slimDropdownElements[i].parentNode;
|
||||
parentNode.style.background = "transparent";
|
||||
parentNode.style.border = "0";
|
||||
|
|
@ -374,49 +367,43 @@ button.addEventListener("click", function () {
|
|||
}
|
||||
});
|
||||
|
||||
// Add event listener for mouseleave on the button
|
||||
button.addEventListener("mouseleave", function () {
|
||||
// Delay to prevent menu hiding when the mouse leaves the button into the menu
|
||||
// Delay to prevent menu hiding when the mouse leaves the button or menu
|
||||
function delayedHideMenu() {
|
||||
setTimeout(function () {
|
||||
if (!isMouseOverButtonOrMenu()) {
|
||||
hideMenu();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
// Add event listener for mouseleave on the button
|
||||
button.addEventListener("mouseleave", delayedHideMenu);
|
||||
// Add event listener for mouseleave on the menu
|
||||
menu.addEventListener("mouseleave", function () {
|
||||
// Delay to prevent menu hide when the mouse leaves the menu into the button
|
||||
setTimeout(function () {
|
||||
if (!isMouseOverButtonOrMenu()) {
|
||||
hideMenu();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
menu.addEventListener("mouseleave", delayedHideMenu);
|
||||
|
||||
// Add event listener for click anywhere in the document
|
||||
document.addEventListener("click", function (event) {
|
||||
const target = event.target;
|
||||
|
||||
// Check if the click is outside the button/menu and the menu is visible
|
||||
if (!isMouseOverButtonOrMenu() && menu.style.display === "flex") {
|
||||
hideMenu();
|
||||
}
|
||||
|
||||
if (event.target.classList.contains("pfp_character")) {
|
||||
const target = event.target;
|
||||
|
||||
if (target.classList.contains("pfp_character")) {
|
||||
toggleBigPicture();
|
||||
}
|
||||
|
||||
// Handle sidebar clicks on mobile
|
||||
if (isMobile()) {
|
||||
// Check if the click did NOT originate from any of the specified toggle buttons or elements
|
||||
// Check if the click did NOT originate from any of the specified toggle buttons or elements
|
||||
if (
|
||||
target.closest("#navigation-toggle") !== navigationToggle &&
|
||||
target.closest("#past-chats-toggle") !== pastChatsToggle &&
|
||||
target.closest("#chat-controls-toggle") !== chatControlsToggle &&
|
||||
target.closest(".header_bar") !== headerBar &&
|
||||
target.closest("#past-chats-row") !== pastChatsRow &&
|
||||
target.closest("#chat-controls") !== chatControlsRow
|
||||
target.closest("#past-chats-toggle") !== pastChatsToggle &&
|
||||
target.closest("#chat-controls-toggle") !== chatControlsToggle &&
|
||||
target.closest(".header_bar") !== headerBar &&
|
||||
target.closest("#past-chats-row") !== pastChatsRow &&
|
||||
target.closest("#chat-controls") !== chatControlsRow
|
||||
) {
|
||||
handleIndividualSidebarClose(event);
|
||||
}
|
||||
|
|
@ -433,27 +420,19 @@ document.getElementById("chat-input-row").classList.add("chat-input-positioned")
|
|||
//------------------------------------------------
|
||||
const chatTextArea = document.getElementById("chat-input").querySelector("textarea");
|
||||
|
||||
function respondToChatInputVisibility(element, callback) {
|
||||
var options = {
|
||||
root: document.documentElement,
|
||||
};
|
||||
|
||||
var observer = new IntersectionObserver((entries, observer) => {
|
||||
function focusOnVisible(element) {
|
||||
var observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
callback(entry.intersectionRatio > 0);
|
||||
if (entry.intersectionRatio > 0) {
|
||||
element.focus();
|
||||
}
|
||||
});
|
||||
}, options);
|
||||
}, { root: document.documentElement });
|
||||
|
||||
observer.observe(element);
|
||||
}
|
||||
|
||||
function handleChatInputVisibilityChange(isVisible) {
|
||||
if (isVisible) {
|
||||
chatTextArea.focus();
|
||||
}
|
||||
}
|
||||
|
||||
respondToChatInputVisibility(chatTextArea, handleChatInputVisibilityChange);
|
||||
focusOnVisible(chatTextArea);
|
||||
|
||||
//------------------------------------------------
|
||||
// Show enlarged character picture when the profile
|
||||
|
|
@ -463,8 +442,7 @@ let bigPictureVisible = false;
|
|||
|
||||
function addBigPicture() {
|
||||
var imgElement = document.createElement("img");
|
||||
var timestamp = new Date().getTime();
|
||||
imgElement.src = "/file/user_data/cache/pfp_character.png?time=" + timestamp;
|
||||
imgElement.src = getProfilePictureUrl();
|
||||
imgElement.classList.add("bigProfilePicture");
|
||||
imgElement.addEventListener("load", function () {
|
||||
this.style.visibility = "visible";
|
||||
|
|
@ -478,9 +456,8 @@ function addBigPicture() {
|
|||
}
|
||||
|
||||
function deleteBigPicture() {
|
||||
var bigProfilePictures = document.querySelectorAll(".bigProfilePicture");
|
||||
bigProfilePictures.forEach(function (element) {
|
||||
element.parentNode.removeChild(element);
|
||||
document.querySelectorAll(".bigProfilePicture").forEach(function (element) {
|
||||
element.remove();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -494,44 +471,11 @@ function toggleBigPicture() {
|
|||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
// Handle the chat input box growth
|
||||
//------------------------------------------------
|
||||
|
||||
// Cache DOM elements
|
||||
const chatContainer = document.getElementById("chat").parentNode.parentNode.parentNode;
|
||||
const chatInput = document.querySelector("#chat-input textarea");
|
||||
|
||||
// Variables to store current dimensions
|
||||
let currentChatInputHeight = chatInput.clientHeight;
|
||||
|
||||
//------------------------------------------------
|
||||
// Focus on the rename text area when it becomes visible
|
||||
//------------------------------------------------
|
||||
const renameTextArea = document.getElementById("rename-row").querySelector("textarea");
|
||||
|
||||
function respondToRenameVisibility(element, callback) {
|
||||
var options = {
|
||||
root: document.documentElement,
|
||||
};
|
||||
|
||||
var observer = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
callback(entry.intersectionRatio > 0);
|
||||
});
|
||||
}, options);
|
||||
|
||||
observer.observe(element);
|
||||
}
|
||||
|
||||
|
||||
function handleVisibilityChange(isVisible) {
|
||||
if (isVisible) {
|
||||
renameTextArea.focus();
|
||||
}
|
||||
}
|
||||
|
||||
respondToRenameVisibility(renameTextArea, handleVisibilityChange);
|
||||
focusOnVisible(renameTextArea);
|
||||
|
||||
//------------------------------------------------
|
||||
// Adjust the chat tab margin if no extension UI
|
||||
|
|
@ -737,21 +681,21 @@ function handleIndividualSidebarClose(event) {
|
|||
|
||||
// Close navigation bar if click is outside and it is open
|
||||
if (!headerBar.contains(target) && !headerBar.classList.contains("sidebar-hidden")) {
|
||||
toggleSidebar(headerBar, navigationToggle, true);
|
||||
toggleSidebar(headerBar, navigationToggle);
|
||||
}
|
||||
|
||||
// Close past chats row if click is outside and it is open
|
||||
if (!pastChatsRow.contains(target) && !pastChatsRow.classList.contains("sidebar-hidden")) {
|
||||
toggleSidebar(pastChatsRow, pastChatsToggle, true);
|
||||
toggleSidebar(pastChatsRow, pastChatsToggle);
|
||||
}
|
||||
|
||||
// Close chat controls row if click is outside and it is open
|
||||
if (!chatControlsRow.contains(target) && !chatControlsRow.classList.contains("sidebar-hidden")) {
|
||||
toggleSidebar(chatControlsRow, chatControlsToggle, true);
|
||||
toggleSidebar(chatControlsRow, chatControlsToggle);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSidebar(sidebar, toggle, forceClose = false) {
|
||||
function toggleSidebar(sidebar, toggle) {
|
||||
const isCurrentlyHidden = sidebar.classList.contains("sidebar-hidden");
|
||||
const shouldClose = !isCurrentlyHidden;
|
||||
|
||||
|
|
@ -776,11 +720,6 @@ function toggleSidebar(sidebar, toggle, forceClose = false) {
|
|||
toggle.classList.toggle("chat-controls-open", !shouldClose);
|
||||
toggle.innerHTML = shouldClose ? leftArrowSVG : rightArrowSVG;
|
||||
}
|
||||
|
||||
// Mobile handling
|
||||
if (isMobile()) {
|
||||
sidebar.classList.toggle("sidebar-shown", !shouldClose);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if the device is mobile
|
||||
|
|
@ -840,17 +779,17 @@ pastChatsToggle.addEventListener("click", () => {
|
|||
const isCurrentlyOpen = !pastChatsRow.classList.contains("sidebar-hidden");
|
||||
toggleSidebar(pastChatsRow, pastChatsToggle);
|
||||
|
||||
// On desktop, open/close both sidebars at the same time
|
||||
// On desktop, sync both sidebars together
|
||||
if (!isMobile()) {
|
||||
if (isCurrentlyOpen) {
|
||||
// If we just closed the left sidebar, also close the right sidebar
|
||||
if (!chatControlsRow.classList.contains("sidebar-hidden")) {
|
||||
toggleSidebar(chatControlsRow, chatControlsToggle, true);
|
||||
toggleSidebar(chatControlsRow, chatControlsToggle);
|
||||
}
|
||||
} else {
|
||||
// If we just opened the left sidebar, also open the right sidebar
|
||||
if (chatControlsRow.classList.contains("sidebar-hidden")) {
|
||||
toggleSidebar(chatControlsRow, chatControlsToggle, false);
|
||||
toggleSidebar(chatControlsRow, chatControlsToggle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -860,17 +799,17 @@ chatControlsToggle.addEventListener("click", () => {
|
|||
const isCurrentlyOpen = !chatControlsRow.classList.contains("sidebar-hidden");
|
||||
toggleSidebar(chatControlsRow, chatControlsToggle);
|
||||
|
||||
// On desktop, open/close both sidebars at the same time
|
||||
// On desktop, sync both sidebars together
|
||||
if (!isMobile()) {
|
||||
if (isCurrentlyOpen) {
|
||||
// If we just closed the right sidebar, also close the left sidebar
|
||||
if (!pastChatsRow.classList.contains("sidebar-hidden")) {
|
||||
toggleSidebar(pastChatsRow, pastChatsToggle, true);
|
||||
toggleSidebar(pastChatsRow, pastChatsToggle);
|
||||
}
|
||||
} else {
|
||||
// If we just opened the right sidebar, also open the left sidebar
|
||||
if (pastChatsRow.classList.contains("sidebar-hidden")) {
|
||||
toggleSidebar(pastChatsRow, pastChatsToggle, false);
|
||||
toggleSidebar(pastChatsRow, pastChatsToggle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -890,7 +829,7 @@ if (isMobile()) {
|
|||
const textarea = document.querySelector("#chat-input textarea");
|
||||
|
||||
if (textarea) {
|
||||
// Simulate adding and removing a newline
|
||||
// Force textarea height recalculation by simulating content change
|
||||
textarea.value += "\n";
|
||||
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
textarea.value = textarea.value.slice(0, -1);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
// Functions for downloading JSON files
|
||||
function getCurrentTimestamp() {
|
||||
const now = new Date();
|
||||
const timezoneOffset = now.getTimezoneOffset() * 60000; // Convert to milliseconds
|
||||
const timezoneOffset = now.getTimezoneOffset() * 60000; // Convert minutes to milliseconds
|
||||
const localTime = new Date(now.getTime() - timezoneOffset);
|
||||
const formattedTimestamp = localTime.toISOString().replace(/[-:]/g, "").slice(0, 15);
|
||||
return formattedTimestamp;
|
||||
return localTime.toISOString().replace(/[-:]/g, "").slice(0, 15);
|
||||
}
|
||||
|
||||
function saveFile(contents, filename) {
|
||||
|
|
@ -18,23 +17,18 @@ function saveFile(contents, filename) {
|
|||
}
|
||||
|
||||
function saveHistory(history, character, mode) {
|
||||
let path = null;
|
||||
let path;
|
||||
|
||||
if (["chat", "chat-instruct"].includes(mode) && character && character.trim() !== "") {
|
||||
path = `history_${character}_${getCurrentTimestamp()}.json`;
|
||||
} else {
|
||||
try {
|
||||
path = `history_${mode}_${getCurrentTimestamp()}.json`;
|
||||
} catch (error) {
|
||||
path = `history_${getCurrentTimestamp()}.json`;
|
||||
}
|
||||
path = `history_${mode || "unknown"}_${getCurrentTimestamp()}.json`;
|
||||
}
|
||||
|
||||
saveFile(history, path);
|
||||
}
|
||||
|
||||
function saveSession(session) {
|
||||
let path = null;
|
||||
|
||||
path = `session_${getCurrentTimestamp()}.json`;
|
||||
const path = `session_${getCurrentTimestamp()}.json`;
|
||||
saveFile(session, path);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
const chatParent = document.querySelector(".chat-parent");
|
||||
|
||||
function toggle_controls(value) {
|
||||
const navToggle = document.getElementById("navigation-toggle");
|
||||
const pastChatsToggle = document.getElementById("past-chats-toggle");
|
||||
const extensions = document.querySelector("#extensions");
|
||||
const galleryExtension = document.getElementById("gallery-extension");
|
||||
|
||||
if (value) {
|
||||
// SHOW MODE: Click toggles to show hidden sidebars
|
||||
const navToggle = document.getElementById("navigation-toggle");
|
||||
const pastChatsToggle = document.getElementById("past-chats-toggle");
|
||||
|
||||
if (navToggle && document.querySelector(".header_bar")?.classList.contains("sidebar-hidden")) {
|
||||
navToggle.click();
|
||||
}
|
||||
|
|
@ -19,17 +17,11 @@ function toggle_controls(value) {
|
|||
if (extensions) {
|
||||
extensions.style.display = "inherit";
|
||||
}
|
||||
|
||||
let gallery_element = document.getElementById("gallery-extension");
|
||||
if (gallery_element) {
|
||||
gallery_element.style.display = "block";
|
||||
if (galleryExtension) {
|
||||
galleryExtension.style.display = "block";
|
||||
}
|
||||
|
||||
} else {
|
||||
// HIDE MODE: Click toggles to hide visible sidebars
|
||||
const navToggle = document.getElementById("navigation-toggle");
|
||||
const pastChatsToggle = document.getElementById("past-chats-toggle");
|
||||
|
||||
if (navToggle && !document.querySelector(".header_bar")?.classList.contains("sidebar-hidden")) {
|
||||
navToggle.click();
|
||||
}
|
||||
|
|
@ -41,5 +33,8 @@ function toggle_controls(value) {
|
|||
if (extensions) {
|
||||
extensions.style.display = "none";
|
||||
}
|
||||
if (galleryExtension) {
|
||||
galleryExtension.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,17 +2,9 @@ function scrollToTop() {
|
|||
window.scrollTo({ top: 0 });
|
||||
}
|
||||
|
||||
function findButtonsByText(buttonText) {
|
||||
const buttons = document.getElementsByTagName("button");
|
||||
const matchingButtons = [];
|
||||
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
if (buttons[i].textContent.trim() === buttonText) {
|
||||
matchingButtons.push(buttons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return matchingButtons;
|
||||
function findButtonsByText(buttonText, container = document) {
|
||||
return Array.from(container.getElementsByTagName("button"))
|
||||
.filter(btn => btn.textContent.trim() === buttonText);
|
||||
}
|
||||
|
||||
function switch_to_chat() {
|
||||
|
|
@ -39,13 +31,9 @@ function switch_to_character() {
|
|||
|
||||
function switch_to_image_ai_generate() {
|
||||
const container = document.querySelector("#image-ai-tab");
|
||||
const buttons = container.getElementsByTagName("button");
|
||||
|
||||
for (let i = 0; i < buttons.length; i++) {
|
||||
if (buttons[i].textContent.trim() === "Generate") {
|
||||
buttons[i].click();
|
||||
break;
|
||||
}
|
||||
const generateBtn = findButtonsByText("Generate", container)[0];
|
||||
if (generateBtn) {
|
||||
generateBtn.click();
|
||||
}
|
||||
|
||||
scrollToTop();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
function updateBigPicture() {
|
||||
var existingElement = document.querySelector(".bigProfilePicture");
|
||||
if (existingElement) {
|
||||
var timestamp = new Date().getTime();
|
||||
existingElement.src = "/file/user_data/cache/pfp_character.png?time=" + timestamp;
|
||||
existingElement.src = getProfilePictureUrl();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -191,21 +191,19 @@ def _apply_custom_generate_reply():
|
|||
|
||||
|
||||
def _apply_custom_css():
|
||||
all_css = ''
|
||||
for extension, _ in iterator():
|
||||
if hasattr(extension, 'custom_css'):
|
||||
all_css += getattr(extension, 'custom_css')()
|
||||
|
||||
return all_css
|
||||
return ''.join(
|
||||
getattr(extension, 'custom_css')()
|
||||
for extension, _ in iterator()
|
||||
if hasattr(extension, 'custom_css')
|
||||
)
|
||||
|
||||
|
||||
def _apply_custom_js():
|
||||
all_js = ''
|
||||
for extension, _ in iterator():
|
||||
if hasattr(extension, 'custom_js'):
|
||||
all_js += getattr(extension, 'custom_js')()
|
||||
|
||||
return all_js
|
||||
return ''.join(
|
||||
getattr(extension, 'custom_js')()
|
||||
for extension, _ in iterator()
|
||||
if hasattr(extension, 'custom_js')
|
||||
)
|
||||
|
||||
|
||||
def create_extensions_block():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue