diff --git a/download-model.py b/download-model.py index 95d25e16..a31bbfc6 100644 --- a/download-model.py +++ b/download-model.py @@ -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 diff --git a/js/dark_theme.js b/js/dark_theme.js index 7136f5bf..9d7069e2 100644 --- a/js/dark_theme.js +++ b/js/dark_theme.js @@ -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(); }; } diff --git a/js/global_scope_js.js b/js/global_scope_js.js index 92f65622..20eeef66 100644 --- a/js/global_scope_js.js +++ b/js/global_scope_js.js @@ -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]; diff --git a/js/main.js b/js/main.js index f05f93c6..cba4c903 100644 --- a/js/main.js +++ b/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); diff --git a/js/save_files.js b/js/save_files.js index bdb0e334..c3cbf9ff 100644 --- a/js/save_files.js +++ b/js/save_files.js @@ -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); } diff --git a/js/show_controls.js b/js/show_controls.js index ff513395..d5642dc4 100644 --- a/js/show_controls.js +++ b/js/show_controls.js @@ -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"; + } } } diff --git a/js/switch_tabs.js b/js/switch_tabs.js index 36e5736b..a1b44ef3 100644 --- a/js/switch_tabs.js +++ b/js/switch_tabs.js @@ -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(); diff --git a/js/update_big_picture.js b/js/update_big_picture.js index ec51d63b..8f638c99 100644 --- a/js/update_big_picture.js +++ b/js/update_big_picture.js @@ -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(); } } diff --git a/modules/extensions.py b/modules/extensions.py index 09db9f40..afe847f0 100644 --- a/modules/extensions.py +++ b/modules/extensions.py @@ -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():