From ea01247bcf758c354e80186636816a5b2c4d21d6 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Fri, 8 Sep 2023 22:44:06 +0300 Subject: [PATCH] #1090 Save Kobold/ooba servers history --- public/index.html | 11 ++-- public/script.js | 2 - public/scripts/RossAscends-mods.js | 11 +--- public/scripts/power-user.js | 1 + public/scripts/server-history.js | 86 ++++++++++++++++++++++++++++++ public/scripts/utils.js | 11 +++- 6 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 public/scripts/server-history.js diff --git a/public/index.html b/public/index.html index 105457fa6..890be2906 100644 --- a/public/index.html +++ b/public/index.html @@ -83,6 +83,7 @@ + SillyTavern @@ -1766,8 +1767,8 @@

API url

Example: http://127.0.0.1:5000/api - - + +
@@ -1857,15 +1858,15 @@

Blocking API url

Example: http://127.0.0.1:5000/api - +

Streaming API url

Example: ws://127.0.0.1:5005/api/v1/stream - +
- +
diff --git a/public/script.js b/public/script.js index edda1c376..7a23fc25a 100644 --- a/public/script.js +++ b/public/script.js @@ -7535,7 +7535,6 @@ jQuery(async function () { /////////////////////////////////////////////////////////////////////////////////// $("#api_button").click(function (e) { - e.stopPropagation(); if ($("#api_url_text").val() != "") { let value = formatKoboldUrl(String($("#api_url_text").val()).trim()); @@ -7568,7 +7567,6 @@ jQuery(async function () { }); $("#api_button_textgenerationwebui").click(async function (e) { - e.stopPropagation(); const url_source = api_use_mancer_webui ? "#mancer_api_url_text" : "#textgenerationwebui_api_url_text"; if ($(url_source).val() != "") { let value = formatTextGenURL(String($(url_source).val()).trim(), api_use_mancer_webui); diff --git a/public/scripts/RossAscends-mods.js b/public/scripts/RossAscends-mods.js index 99ffdfc13..0bbd92665 100644 --- a/public/scripts/RossAscends-mods.js +++ b/public/scripts/RossAscends-mods.js @@ -31,7 +31,7 @@ import { SECRET_KEYS, secret_state, } from "./secrets.js"; -import { debounce, delay, getStringHash, waitUntilCondition } from "./utils.js"; +import { debounce, delay, getStringHash, isUrlOrAPIKey, waitUntilCondition } from "./utils.js"; import { chat_completion_sources, oai_settings } from "./openai.js"; import { getTokenCount } from "./tokenizers.js"; @@ -403,15 +403,6 @@ function RA_autoconnect(PrevApi) { } } -function isUrlOrAPIKey(string) { - try { - new URL(string); - return true; - } catch (_) { - // return pattern.test(string); - } -} - function OpenNavPanels() { const deviceInfo = getDeviceInfo(); if (deviceInfo && deviceInfo.device.type === 'desktop') { diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js index aa4edc312..d6c27f546 100644 --- a/public/scripts/power-user.js +++ b/public/scripts/power-user.js @@ -201,6 +201,7 @@ let power_user = { fuzzy_search: false, encode_tags: false, lazy_load: 0, + servers: [], }; let themes = []; diff --git a/public/scripts/server-history.js b/public/scripts/server-history.js new file mode 100644 index 000000000..03d1a8fcf --- /dev/null +++ b/public/scripts/server-history.js @@ -0,0 +1,86 @@ +import { saveSettingsDebounced } from "../script.js"; +import { power_user } from "./power-user.js"; +import { isUrlOrAPIKey } from "./utils.js"; + +/** + * @param {{ term: string; }} request + * @param {function} resolve + * @param {string} serverLabel + */ +function findServers(request, resolve, serverLabel) { + if (!power_user.servers) { + power_user.servers = []; + } + + const needle = request.term.toLowerCase(); + const result = power_user.servers.filter(x => x.label == serverLabel).sort((a, b) => b.lastConnection - a.lastConnection).map(x => x.url).slice(0, 5); + const hasExactMatch = result.findIndex(x => x.toLowerCase() == needle) !== -1; + + if (request.term && !hasExactMatch) { + result.unshift(request.term); + } + + resolve(result); +} + +function selectServer(event, ui, serverLabel) { + // unfocus the input + $(event.target).val(ui.item.value).trigger('blur'); + + $('[data-server-connect]').each(function () { + const serverLabels = String($(this).data('server-connect')).split(','); + + if (serverLabels.includes(serverLabel)) { + $(this).trigger('click'); + } + }); +} + +function createServerAutocomplete() { + const inputElement = $(this); + const serverLabel = inputElement.data('server-history'); + + inputElement + .autocomplete({ + source: (i, o) => findServers(i, o, serverLabel), + select: (e, u) => selectServer(e, u, serverLabel), + minLength: 0, + }) + .focus(onInputFocus); // <== show tag list on click +} + +function onInputFocus() { + $(this).autocomplete('search', $(this).val()); +} + +function onServerConnectClick() { + const serverLabels = String($(this).data('server-connect')).split(','); + + serverLabels.forEach(serverLabel => { + if (!power_user.servers) { + power_user.servers = []; + } + + const value = String($(`[data-server-history="${serverLabel}"]`).val()).toLowerCase().trim(); + + // Don't save empty values or invalid URLs + if (!value || !isUrlOrAPIKey(value)) { + return; + } + + const server = power_user.servers.find(x => x.url === value && x.label === serverLabel); + + if (!server) { + power_user.servers.push({ label: serverLabel, url: value, lastConnection: Date.now() }); + } else { + server.lastConnection = Date.now(); + } + + saveSettingsDebounced(); + }); +} + +jQuery(function () { + $('[data-server-history]').each(createServerAutocomplete); + $(document).on('click', '[data-server-connect]', onServerConnectClick); +}); diff --git a/public/scripts/utils.js b/public/scripts/utils.js index da011a00a..121c97334 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -18,6 +18,15 @@ export function escapeHtml(str) { return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } +export function isUrlOrAPIKey(value) { + try { + new URL(value); + return true; + } catch (_) { + return false; + } +} + /** * Determines if a value is unique in an array. * @param {any} value Current value. @@ -850,7 +859,7 @@ export async function saveBase64AsFile(base64Data, characterName, filename = "", /** * Loads either a CSS or JS file and appends it to the appropriate document section. - * + * * @param {string} url - The URL of the file to be loaded. * @param {string} type - The type of file to load: "css" or "js". * @returns {Promise} - Resolves when the file has loaded, rejects if there's an error or invalid type.