From c8d0d430d3c8fa5f98b68b0495838968cfa7ed3b Mon Sep 17 00:00:00 2001 From: Mic Date: Tue, 2 Sep 2025 22:55:00 +0200 Subject: [PATCH] work in progress, moved html to connection-ui.js, starting to move the relative methods. see #438 --- options/mzta-options.css | 80 ---- options/mzta-options.html | 364 +---------------- options/mzta-options.js | 152 ++----- pages/_lib/connection-ui.css | 109 ++++++ pages/_lib/connection-ui.js | 652 +++++++++++++++++++++++++++++++ pages/addtags/mzta-add-tags.html | 11 +- pages/addtags/mzta-add-tags.js | 18 +- 7 files changed, 819 insertions(+), 567 deletions(-) create mode 100644 pages/_lib/connection-ui.css create mode 100644 pages/_lib/connection-ui.js diff --git a/options/mzta-options.css b/options/mzta-options.css index 280c5bcf..4cd0810b 100644 --- a/options/mzta-options.css +++ b/options/mzta-options.css @@ -104,40 +104,6 @@ div#miczTranslate{ font-size:smaller; } -tr.conntype_chatgpt_api, tr.conntype_chatgpt_api2{ - background-color: rgb(185, 220, 252); -} - -tr.conntype_chatgpt_web, tr.conntype_chatgpt_web2{ - background-color: rgb(255, 209, 183); -} - -tr.conntype_ollama_api, tr.conntype_ollama_api2{ - background-color: rgb(177, 238, 169); -} - -tr.conntype_openai_comp_api, tr.conntype_openai_comp_api2{ - background-color: rgb(213, 169, 238); -} - -tr.conntype_google_gemini_api, tr.conntype_google_gemini_api2{ - background-color: rgb(233, 238, 169); -} - -tr.conntype_anthropic_api, tr.conntype_anthropic_api2{ - background-color: rgb(255, 168, 204); -} - -#chatgpt_model_fetch_loading{ - display: none; - font-style: italic; -} - -#google_gemini_model_fetch_loading{ - display: none; - font-style: italic; -} - #no_sparks td{ text-align: center; padding: 1em !important; @@ -149,48 +115,6 @@ textarea.option-textarea{ height: 10em; } -.api_key-container { - position: relative; - width: 100%; -} - -.api_key-container input { - width: -moz-available; - margin-right: 25px; -} - -input[type="text"], input[type="password"]{ - border-radius: 4px; - padding: 2px; -} - -input.option-input[type="text"]{ - width: -moz-available; -} - -.api_key-container .toggle-icon { - position: absolute; - right: 0px; - top: 50%; - transform: translateY(-50%); - cursor: pointer; -} - -#ollama_model_fetch_loading{ - display: none; - font-style: italic; -} - -#openai_comp_model_fetch_loading{ - display: none; - font-style: italic; -} - -#anthropic_model_fetch_loading{ - display: none; - font-style: italic; -} - #owl_warning{ display: none; } @@ -235,10 +159,6 @@ input.option-input[type="text"]{ color: #FF6600; } -.conntype_chatgpt_web_option{ - cursor: pointer; -} - .btn_small{ font-size: 0.8em; } diff --git a/options/mzta-options.html b/options/mzta-options.html index a9c90554..9b1b9d58 100644 --- a/options/mzta-options.html +++ b/options/mzta-options.html @@ -3,6 +3,7 @@ +
__MSG_prefs_OptionText_release_notes__
@@ -113,368 +114,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - __MSG_OpenChatGPTTab_Info__ -

-

__MSG_OpenChatGPTTab_Info2__ - - - - - -
- - -
- - - - - - - - __MSG_Loading__
- - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - - - - __MSG_Loading__
- - - - - - - - - - - - - - - - - - - - __MSG_remember_CORS__ [__MSG_more_info_string__] -

__MSG_CORS_alternative_1__ -
__MSG_CORS_alternative_2__ -

- - - - - - - - __MSG_Loading__
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - __MSG_maybe_CORS_openai_comp__ [__MSG_more_info_string__] -

__MSG_CORS_alternative_1__ -
__MSG_CORS_alternative_2__ -

- - - - - - - - - - - -
- - -
- - - - - - - - __MSG_Loading__
- - - - - - - - - - - - -
- - -
- - - - - - - - __MSG_Loading__
- - - - - - - - - - - - - __MSG_prefs_OptionText_anthropic_max_tokens__ - - - - + __MSG_prefs_OptionText_max_prompt_length__ diff --git a/options/mzta-options.js b/options/mzta-options.js index 794a3d7a..ddc27be1 100644 --- a/options/mzta-options.js +++ b/options/mzta-options.js @@ -23,12 +23,12 @@ import { Ollama } from '../js/api/ollama.js'; import { OpenAIComp } from '../js/api/openai_comp.js' import { GoogleGemini } from '../js/api/google_gemini.js'; import { Anthropic } from '../js/api/anthropic.js'; -import { ChatGPTWeb_models, checkSparksPresence, isThunderbird128OrGreater, openTab, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData, validateCustomData_ChatGPTWeb, getChatGPTWebModelsList_HTML, populateConnectionTypeOptions } from '../js/mzta-utils.js'; +import { ChatGPTWeb_models, checkSparksPresence, isThunderbird128OrGreater, openTab, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData, validateCustomData_ChatGPTWeb, getChatGPTWebModelsList_HTML, isAPIKeyValue } from '../js/mzta-utils.js'; import { openAICompConfigs } from '../js/api/openai_comp_configs.js'; +import { injectConnectionUI, varConnectionUI, showConnectionOptions } from '../pages/_lib/connection-ui.js'; let taLog = new taLogger("mzta-options",true); let _isThunderbird128OrGreater = true; -let permission_all_urls = false; function saveOptions(e) { e.preventDefault(); @@ -70,7 +70,7 @@ function saveOptions(e) { async function restoreOptions() { function setCurrentChoice(result) { document.querySelectorAll(".option-input").forEach(element => { - taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" || element.id=="google_gemini_api_key" || element.id=="anthropic_api_key" ? "****************" : result[element.id])); + taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id])); switch (element.type) { case 'checkbox': element.checked = result[element.id] || false; @@ -109,79 +109,6 @@ async function restoreOptions() { setCurrentChoice(getting); } -function showConnectionOptions() { - disable_MaxPromptLength(); - disable_AddTags(); - disable_SpamFilter(); - disable_GetCalendarEvent(); - let chatgpt_web_display = 'table-row'; - let chatgpt_api_display = 'none'; - let ollama_api_display = 'none'; - let openai_comp_api_display = 'none'; - let google_gemini_api_display = 'none'; - let anthropic_api_display = 'none'; - let conntype_select = document.getElementById("connection_type"); - let parent = conntype_select.parentElement.parentElement.parentElement; - parent.classList.toggle("conntype_chatgpt_web", (conntype_select.value === "chatgpt_web")); - parent.classList.toggle("conntype_chatgpt_api", (conntype_select.value === "chatgpt_api")); - parent.classList.toggle("conntype_ollama_api", (conntype_select.value === "ollama_api")); - parent.classList.toggle("conntype_openai_comp_api", (conntype_select.value === "openai_comp_api")); - parent.classList.toggle("conntype_google_gemini_api", (conntype_select.value === "google_gemini_api")); - parent.classList.toggle("conntype_anthropic_api", (conntype_select.value === "anthropic_api")); - if (conntype_select.value === "chatgpt_web") { - chatgpt_web_display = 'table-row'; - }else{ - chatgpt_web_display = 'none'; - } - if (conntype_select.value === "chatgpt_api") { - chatgpt_api_display = 'table-row'; - }else{ - chatgpt_api_display = 'none'; - } - if (conntype_select.value === "ollama_api") { - ollama_api_display = 'table-row'; - }else{ - ollama_api_display = 'none'; - } - if (conntype_select.value === "openai_comp_api") { - openai_comp_api_display = 'table-row'; - }else{ - openai_comp_api_display = 'none'; - } - if (conntype_select.value === "google_gemini_api") { - google_gemini_api_display = 'table-row'; - }else{ - google_gemini_api_display = 'none'; - } - if (conntype_select.value === "anthropic_api") { - anthropic_api_display = 'table-row'; - }else{ - anthropic_api_display = 'none'; - } - document.querySelectorAll(".conntype_chatgpt_web").forEach(element => { - element.style.display = chatgpt_web_display; - }); - document.querySelectorAll(".conntype_chatgpt_api").forEach(element => { - element.style.display = chatgpt_api_display; - }); - document.querySelectorAll(".conntype_ollama_api").forEach(element => { - element.style.display = ollama_api_display; - }); - document.querySelectorAll(".conntype_openai_comp_api").forEach(element => { - element.style.display = openai_comp_api_display; - }); - document.querySelectorAll(".conntype_google_gemini_api").forEach(element => { - element.style.display = google_gemini_api_display; - }); - document.querySelectorAll(".conntype_anthropic_api").forEach(element => { - element.style.display = anthropic_api_display; - }); - if (permission_all_urls) { - document.getElementById('openai_comp_api_cors_warning').style.display = 'none'; - document.getElementById('ollama_api_cors_warning').style.display = 'none'; - } -} - function warn_ChatGPT_APIKeyEmpty() { let apiKeyInput = document.getElementById('chatgpt_api_key'); let btnFetchChatGPTModels = document.getElementById('btnUpdateChatGPTModels'); @@ -405,10 +332,10 @@ function resetMaxPromptLength(){ } document.addEventListener('DOMContentLoaded', async () => { - populateConnectionTypeOptions('connection_type'); + injectConnectionUI({ afterTrId: 'connection_ui_anchor', selectId: 'connection_type' }); await restoreOptions(); - permission_all_urls = await messenger.permissions.contains({ origins: [""] }) + varConnectionUI.permission_all_urls = await messenger.permissions.contains({ origins: [""] }) _isThunderbird128OrGreater = await isThunderbird128OrGreater(); @@ -503,38 +430,38 @@ document.addEventListener('DOMContentLoaded', async () => { openTab('/pages/get-task/mzta-get-task.html'); }); - document.getElementById('btnOpenAICompForceModel').addEventListener('click', () => { - let modelName = prompt(browser.i18n.getMessage('OpenAIComp_force_model_ask')).trim(); - if ((modelName !== null) && (modelName !== undefined) && (modelName !== '')) { - let select_openai_comp_model = document.getElementById('openai_comp_model'); - let option = document.createElement('option'); - option.value = modelName; - option.text = modelName; - select_openai_comp_model.appendChild(option); - select_openai_comp_model.value = modelName; - select_openai_comp_model.dispatchEvent(new Event('change', { bubbles: true })); - } - }); + // document.getElementById('btnOpenAICompForceModel').addEventListener('click', () => { + // let modelName = prompt(browser.i18n.getMessage('OpenAIComp_force_model_ask')).trim(); + // if ((modelName !== null) && (modelName !== undefined) && (modelName !== '')) { + // let select_openai_comp_model = document.getElementById('openai_comp_model'); + // let option = document.createElement('option'); + // option.value = modelName; + // option.text = modelName; + // select_openai_comp_model.appendChild(option); + // select_openai_comp_model.value = modelName; + // select_openai_comp_model.dispatchEvent(new Event('change', { bubbles: true })); + // } + // }); - document.getElementById('btnOpenAICompClearModelsList').addEventListener('click', () => { - if (!confirm(browser.i18n.getMessage('OpenAIComp_ClearModelsList_Confirm'))) { - return; - } - let select_openai_comp_model = document.getElementById('openai_comp_model'); - while (select_openai_comp_model.options.length > 0) { - select_openai_comp_model.remove(0); - } - select_openai_comp_model.value = ''; - select_openai_comp_model.dispatchEvent(new Event('change', { bubbles: true })); - }); + // document.getElementById('btnOpenAICompClearModelsList').addEventListener('click', () => { + // if (!confirm(browser.i18n.getMessage('OpenAIComp_ClearModelsList_Confirm'))) { + // return; + // } + // let select_openai_comp_model = document.getElementById('openai_comp_model'); + // while (select_openai_comp_model.options.length > 0) { + // select_openai_comp_model.remove(0); + // } + // select_openai_comp_model.value = ''; + // select_openai_comp_model.dispatchEvent(new Event('change', { bubbles: true })); + // }); - document.getElementById('btnGiveAllUrlsPermission_ollama_api').addEventListener('click', async () => { - permission_all_urls = await messenger.permissions.request({ origins: [""] }); - }); + // document.getElementById('btnGiveAllUrlsPermission_ollama_api').addEventListener('click', async () => { + // permission_all_urls = await messenger.permissions.request({ origins: [""] }); + // }); - document.getElementById('btnGiveAllUrlsPermission_openai_comp_api').addEventListener('click', async () => { - permission_all_urls = await messenger.permissions.request({ origins: [""] }); - }); + // document.getElementById('btnGiveAllUrlsPermission_openai_comp_api').addEventListener('click', async () => { + // permission_all_urls = await messenger.permissions.request({ origins: [""] }); + // }); getChatGPTWebModelsList_HTML(ChatGPTWeb_models, 'chatgpt_web_models_list'); document.querySelectorAll(".conntype_chatgpt_web_option").forEach(element => { @@ -546,13 +473,13 @@ document.addEventListener('DOMContentLoaded', async () => { }); let conntype_select = document.getElementById("connection_type"); - conntype_select.addEventListener("change", showConnectionOptions); conntype_select.addEventListener("change", warn_ChatGPT_APIKeyEmpty); conntype_select.addEventListener("change", warn_Ollama_HostEmpty); conntype_select.addEventListener("change", warn_OpenAIComp_HostEmpty); conntype_select.addEventListener("change", warn_GoogleGemini_APIKeyEmpty); conntype_select.addEventListener("change", warn_Anthropic_APIKeyEmpty); conntype_select.addEventListener("change", warn_Anthropic_VersionEmpty); + conntype_select.addEventListener("change", disable_MaxPromptLength); conntype_select.addEventListener("change", disable_AddTags); conntype_select.addEventListener("change", disable_SpamFilter); conntype_select.addEventListener("change", disable_GetCalendarEvent); @@ -568,7 +495,12 @@ document.addEventListener('DOMContentLoaded', async () => { document.getElementById("openai_comp_chat_name").addEventListener("input", resetOpenAICompConfigs); document.getElementById("openai_comp_use_v1").addEventListener("input", resetOpenAICompConfigs); - + showConnectionOptions(conntype_select); + disable_MaxPromptLength(); + disable_AddTags(); + disable_SpamFilter(); + disable_GetCalendarEvent(); + let prefs = await browser.storage.sync.get({chatgpt_web_model: '', chatgpt_model: '', ollama_model: '', openai_comp_model: '', google_gemini_model: '', anthropic_model: '', anthropic_version: '', chatgpt_win_height: 0, chatgpt_win_width: 0 }); // OpenAI API ChatGPT model fetching @@ -793,14 +725,12 @@ document.addEventListener('DOMContentLoaded', async () => { warn_Anthropic_APIKeyEmpty(); }); - showConnectionOptions(); warn_ChatGPT_APIKeyEmpty(); warn_Ollama_HostEmpty(); warn_OpenAIComp_HostEmpty(); warn_GoogleGemini_APIKeyEmpty(); warn_Anthropic_APIKeyEmpty(); warn_Anthropic_VersionEmpty(); - disable_MaxPromptLength(); disable_AddTags(); disable_SpamFilter(); disable_GetCalendarEvent(); diff --git a/pages/_lib/connection-ui.css b/pages/_lib/connection-ui.css new file mode 100644 index 00000000..1a203629 --- /dev/null +++ b/pages/_lib/connection-ui.css @@ -0,0 +1,109 @@ +tr.conntype_chatgpt_api, tr.conntype_chatgpt_api2{ + background-color: rgb(185, 220, 252); +} + +tr.conntype_chatgpt_web, tr.conntype_chatgpt_web2{ + background-color: rgb(255, 209, 183); +} + +tr.conntype_ollama_api, tr.conntype_ollama_api2{ + background-color: rgb(177, 238, 169); +} + +tr.conntype_openai_comp_api, tr.conntype_openai_comp_api2{ + background-color: rgb(213, 169, 238); +} + +tr.conntype_google_gemini_api, tr.conntype_google_gemini_api2{ + background-color: rgb(233, 238, 169); +} + +tr.conntype_anthropic_api, tr.conntype_anthropic_api2{ + background-color: rgb(255, 168, 204); +} + +#chatgpt_model_fetch_loading{ + display: none; + font-style: italic; +} + +#google_gemini_model_fetch_loading{ + display: none; + font-style: italic; +} + +.api_key-container { + position: relative; + width: 100%; +} + +.api_key-container input { + width: -moz-available; + margin-right: 25px; +} + +input[type="text"], input[type="password"]{ + border-radius: 4px; + padding: 2px; +} + +input.option-input[type="text"]{ + width: -moz-available; +} + +.api_key-container .toggle-icon { + position: absolute; + right: 0px; + top: 50%; + transform: translateY(-50%); + cursor: pointer; +} + +#ollama_model_fetch_loading{ + display: none; + font-style: italic; +} + +#openai_comp_model_fetch_loading{ + display: none; + font-style: italic; +} + +#anthropic_model_fetch_loading{ + display: none; + font-style: italic; +} + +.conntype_chatgpt_web_option{ + cursor: pointer; +} + +@media (prefers-color-scheme: dark) { + tr.conntype_chatgpt_api, tr.conntype_chatgpt_api2{ + background-color: rgb(0, 0, 58); + } + + tr.conntype_chatgpt_web,tr.conntype_chatgpt_web2{ + background-color: rgb(39, 11, 0); + } + + tr.conntype_ollama_api, tr.conntype_ollama_api2{ + background-color: rgb(7, 58, 0); + } + + tr.conntype_openai_comp_api, tr.conntype_openai_comp_api2{ + background-color: rgb(89, 20, 129); + } + + tr.conntype_google_gemini_api, tr.conntype_google_gemini_api2{ + background-color: rgb(72, 77, 3); + } + + tr.conntype_anthropic_api, tr.conntype_anthropic_api2{ + background-color: rgb(83, 0, 35); + } + + .api_key-container .toggle-icon img { + filter: invert(1); + } +} \ No newline at end of file diff --git a/pages/_lib/connection-ui.js b/pages/_lib/connection-ui.js new file mode 100644 index 00000000..517f7b8b --- /dev/null +++ b/pages/_lib/connection-ui.js @@ -0,0 +1,652 @@ +// connection-ui.js +// Public API: +// injectConnectionUI({ afterTrId, groupId?, selectId?, defaultType?, idSuffix?, onTypeChange? }) +// +// All variable names and comments are in English. +// It generates the connection type UI rows and handles basic show/hide behavior. + +export const varConnectionUI = { + permission_all_urls: false +} + +export function injectConnectionUI({ + afterTrId = '', + selectId = '', + no_chatgpt_web = false, + defaultType = '', + tr_class = '', + } = {}) { + + const anchorTr = document.getElementById(afterTrId); + if (!anchorTr) { + console.error(`[ThuderAI | injectConnectionUI] Can't find tr#${afterTrId}`); + return null; + } + + let tpl = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + __MSG_OpenChatGPTTab_Info__ +

+

__MSG_OpenChatGPTTab_Info2__ + + + + + +
+ + +
+ + + + + + + + __MSG_Loading__
+ + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + __MSG_Loading__
+ + + + + + + + + + + + + + + + + + + + __MSG_remember_CORS__ [__MSG_more_info_string__] +

__MSG_CORS_alternative_1__ +
__MSG_CORS_alternative_2__ +

+ + + + + + + + __MSG_Loading__
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + __MSG_maybe_CORS_openai_comp__ [__MSG_more_info_string__] +

__MSG_CORS_alternative_1__ +
__MSG_CORS_alternative_2__ +

+ + + + + + + + + + + +
+ + +
+ + + + + + + + __MSG_Loading__
+ + + + + + + + + + + + +
+ + +
+ + + + + + + + __MSG_Loading__
+ + + + + + + + + + + + + __MSG_prefs_OptionText_anthropic_max_tokens__ + + + + + `; + + const template = document.createElement('template'); + template.innerHTML = tpl.trim(); + const frag = template.content; + + const parent = anchorTr.parentElement; + const nodes = Array.from(frag.childNodes); + let last = anchorTr; + nodes.forEach(node => { + if (node.nodeType === Node.ELEMENT_NODE) { + parent.insertBefore(node, last.nextSibling); + last = node; + } + }); + + // Bindings + const bindClick = (id, cb) => { const el = document.getElementById(id); if (el && typeof cb === 'function') el.addEventListener('click', cb); }; + const bindChange = (id, cb) => { const el = document.getElementById(id); if (el && typeof cb === 'function') el.addEventListener('change', cb); }; + const bindInput = (id, cb) => { const el = document.getElementById(id); if (el && typeof cb === 'function') el.addEventListener('input', cb); }; + + populateConnectionTypeOptions(selectId, no_chatgpt_web); + + let selectEl = document.getElementById(selectId); + + if (!selectEl) { + console.error('[ThuderAI | injectConnectionUI] Select not found after insertion.'); + } + + const bindPasswordToggle = (idBase) => { + const input = document.getElementById(idBase); + const toggler = document.getElementById(`toggle_\${idBase}`); + const icon = document.getElementById(`pwd-icon_\${idBase}`); + if (!input || !toggler) return; + toggler.addEventListener('click', () => { + input.type = input.type === 'password' ? 'text' : 'password'; + if (icon) icon.src = input.type === 'password' ? '/images/pwd-show.png' : '/images/pwd-hide.png'; + }); + }; + + bindPasswordToggle('chatgpt_api_key'); + bindPasswordToggle('google_gemini_api_key'); + bindPasswordToggle('openai_comp_api_key'); + bindPasswordToggle('anthropic_api_key'); + + // Live warnings and enable/disable logic + const applyLiveWarnings = () => { + // ChatGPT API + const chatgptKey = document.getElementById('chatgpt_api_key'); + const btnChatGPT = document.getElementById('btnUpdateChatGPTModels'); + const selChatGPT = document.getElementById('chatgpt_model'); + if (chatgptKey && btnChatGPT && selChatGPT) { + const empty = !chatgptKey.value; + chatgptKey.style.border = empty ? '2px solid red' : ''; + btnChatGPT.disabled = !!empty; + selChatGPT.disabled = !!empty; + if (!empty) { + selChatGPT.style.border = (!selChatGPT.value || selChatGPT.selectedIndex === -1) ? '2px solid red' : ''; + } else { + selChatGPT.style.border = ''; + } + } + + // Google Gemini API + const geminiKey = document.getElementById('google_gemini_api_key'); + const btnGemini = document.getElementById('btnUpdateGoogleGeminiModels'); + const selGemini = document.getElementById('google_gemini_model'); + if (geminiKey && btnGemini && selGemini) { + const empty = !geminiKey.value; + geminiKey.style.border = empty ? '2px solid red' : ''; + btnGemini.disabled = !!empty; + selGemini.disabled = !!empty; + if (!empty) { + selGemini.style.border = (!selGemini.value || selGemini.selectedIndex === -1) ? '2px solid red' : ''; + } else { + selGemini.style.border = ''; + } + } + + // Ollama API + const ollamaHost = document.getElementById('ollama_host'); + const btnOllama = document.getElementById('btnUpdateOllamaModels'); + const selOllama = document.getElementById('ollama_model'); + if (ollamaHost && btnOllama && selOllama) { + const empty = !ollamaHost.value; + ollamaHost.style.border = empty ? '2px solid red' : ''; + btnOllama.disabled = !!empty; + selOllama.disabled = !!empty; + if (!empty) { + selOllama.style.border = (!selOllama.value || selOllama.selectedIndex === -1) ? '2px solid red' : ''; + } else { + selOllama.style.border = ''; + } + } + + // OpenAI-Compatible API + const openaiCompHost = document.getElementById('openai_comp_host'); + const btnOpenAIComp = document.getElementById('btnUpdateOpenAICompModels'); + const selOpenAIComp = document.getElementById('openai_comp_model'); + if (openaiCompHost && btnOpenAIComp && selOpenAIComp) { + const empty = !openaiCompHost.value; + openaiCompHost.style.border = empty ? '2px solid red' : ''; + btnOpenAIComp.disabled = !!empty; + selOpenAIComp.disabled = !!empty; + if (!empty) { + selOpenAIComp.style.border = (!selOpenAIComp.value || selOpenAIComp.selectedIndex === -1) ? '2px solid red' : ''; + } else { + selOpenAIComp.style.border = ''; + } + } + + // Anthropic API + const anthropicKey = document.getElementById('anthropic_api_key'); + const btnAnthropic = document.getElementById('btnUpdateAnthropicModels'); + const selAnthropic = document.getElementById('anthropic_model'); + const anthropicVersion = document.getElementById('anthropic_version'); + if (anthropicKey && selAnthropic) { + const emptyKey = !anthropicKey.value; + anthropicKey.style.border = emptyKey ? '2px solid red' : ''; + if (btnAnthropic) btnAnthropic.disabled = !!emptyKey; + if (selAnthropic) selAnthropic.disabled = !!emptyKey; + if (!emptyKey && selAnthropic) { + selAnthropic.style.border = (!selAnthropic.value || selAnthropic.selectedIndex === -1) ? '2px solid red' : ''; + } else if (selAnthropic) { + selAnthropic.style.border = ''; + } + } + if (anthropicVersion) { + const emptyVer = !anthropicVersion.value; + anthropicVersion.style.border = emptyVer ? '2px solid red' : ''; + } + }; + + // Bind inputs to live warnings + bindInput('chatgpt_api_key', applyLiveWarnings); + bindInput('google_gemini_api_key', applyLiveWarnings); + bindInput('ollama_host', applyLiveWarnings); + bindInput('openai_comp_host', applyLiveWarnings); + bindInput('anthropic_api_key', applyLiveWarnings); + bindInput('anthropic_version', applyLiveWarnings); + + bindChange('chatgpt_model', applyLiveWarnings); + bindChange('google_gemini_model', applyLiveWarnings); + bindChange('ollama_model', applyLiveWarnings); + bindChange('openai_comp_model', applyLiveWarnings); + bindChange('anthropic_model', applyLiveWarnings); + + // Run once on init + applyLiveWarnings(); + + + // Bind button clicks to provided callbacks (page-specific logic stays outside) + // bindClick('btnChatGPTWeb_Tab', onOpenChatGPTWebTab); + // bindClick('btnUpdateChatGPTModels', onFetchChatGPTModels); + // bindClick('btnUpdateGoogleGeminiModels', onFetchGoogleGeminiModels); + // bindClick('btnUpdateOllamaModels', onFetchOllamaModels); + // bindClick('btnUpdateOpenAICompModels', onFetchOpenAICompModels); + // bindClick('btnOpenAICompForceModel', onOpenAICompForceModel); + // bindClick('btnOpenAICompClearModelsList', onOpenAICompClearModelsList); + // bindClick('btnUpdateAnthropicModels', onFetchAnthropicModels); + // bindClick('btnGiveAllUrlsPermission_ollama_api', onGiveAllUrlsPermissionOllama); + // bindClick('btnGiveAllUrlsPermission_openai_comp_api', onGiveAllUrlsPermissionOpenAIComp); + + selectEl.addEventListener("change", () => showConnectionOptions(selectEl)); + + showConnectionOptions(selectEl); + + return { + select: selectEl, + onTypeChange: (fn) => { onTypeChange = fn; fn(selectEl.value, { select: selectEl }); } + }; +} + + +function populateConnectionTypeOptions(selectId, no_chatgpt_web = false) { + const selectEl = document.getElementById(selectId); + if (!selectEl) return; + + const prevValue = selectEl.value; + + const options = [ + { value: 'chatgpt_web', msgKey: 'prefs_Connection_type_ChatGPT_Web' }, + { value: 'chatgpt_api', msgKey: 'prefs_Connection_type_ChatGPT_API' }, + { value: 'google_gemini_api', msgKey: 'prefs_Connection_type_Google_Gemini_API' }, + { value: 'anthropic_api', msgKey: 'prefs_Connection_type_Anthropic_API' }, + { value: 'ollama_api', msgKey: 'prefs_Connection_type_Ollama_API' }, + { value: 'openai_comp_api', msgKey: 'prefs_Connection_type_OpenAI_Comp_API' } + ]; + + selectEl.innerHTML = ''; + + for (const opt of options.filter(o => !(no_chatgpt_web && o.value === 'chatgpt_web'))) { + const optionEl = document.createElement('option'); + optionEl.value = opt.value; + optionEl.textContent = browser.i18n.getMessage(opt.msgKey) || opt.msgKey; + selectEl.appendChild(optionEl); + } + + if (options.some(o => o.value === prevValue)) { + selectEl.value = prevValue; + } +} + + +export function showConnectionOptions(conntype_select) { + let chatgpt_web_display = 'table-row'; + let chatgpt_api_display = 'none'; + let ollama_api_display = 'none'; + let openai_comp_api_display = 'none'; + let google_gemini_api_display = 'none'; + let anthropic_api_display = 'none'; + let parent = conntype_select.parentElement.parentElement.parentElement; + parent.classList.toggle("conntype_chatgpt_web", (conntype_select.value === "chatgpt_web")); + parent.classList.toggle("conntype_chatgpt_api", (conntype_select.value === "chatgpt_api")); + parent.classList.toggle("conntype_ollama_api", (conntype_select.value === "ollama_api")); + parent.classList.toggle("conntype_openai_comp_api", (conntype_select.value === "openai_comp_api")); + parent.classList.toggle("conntype_google_gemini_api", (conntype_select.value === "google_gemini_api")); + parent.classList.toggle("conntype_anthropic_api", (conntype_select.value === "anthropic_api")); + if (conntype_select.value === "chatgpt_web") { + chatgpt_web_display = 'table-row'; + }else{ + chatgpt_web_display = 'none'; + } + if (conntype_select.value === "chatgpt_api") { + chatgpt_api_display = 'table-row'; + }else{ + chatgpt_api_display = 'none'; + } + if (conntype_select.value === "ollama_api") { + ollama_api_display = 'table-row'; + }else{ + ollama_api_display = 'none'; + } + if (conntype_select.value === "openai_comp_api") { + openai_comp_api_display = 'table-row'; + }else{ + openai_comp_api_display = 'none'; + } + if (conntype_select.value === "google_gemini_api") { + google_gemini_api_display = 'table-row'; + }else{ + google_gemini_api_display = 'none'; + } + if (conntype_select.value === "anthropic_api") { + anthropic_api_display = 'table-row'; + }else{ + anthropic_api_display = 'none'; + } + document.querySelectorAll(".conntype_chatgpt_web").forEach(element => { + element.style.display = chatgpt_web_display; + }); + document.querySelectorAll(".conntype_chatgpt_api").forEach(element => { + element.style.display = chatgpt_api_display; + }); + document.querySelectorAll(".conntype_ollama_api").forEach(element => { + element.style.display = ollama_api_display; + }); + document.querySelectorAll(".conntype_openai_comp_api").forEach(element => { + element.style.display = openai_comp_api_display; + }); + document.querySelectorAll(".conntype_google_gemini_api").forEach(element => { + element.style.display = google_gemini_api_display; + }); + document.querySelectorAll(".conntype_anthropic_api").forEach(element => { + element.style.display = anthropic_api_display; + }); + if (varConnectionUI.permission_all_urls) { + document.getElementById('openai_comp_api_cors_warning').style.display = 'none'; + document.getElementById('ollama_api_cors_warning').style.display = 'none'; + } +} \ No newline at end of file diff --git a/pages/addtags/mzta-add-tags.html b/pages/addtags/mzta-add-tags.html index 0f525f84..298cf42a 100644 --- a/pages/addtags/mzta-add-tags.html +++ b/pages/addtags/mzta-add-tags.html @@ -4,6 +4,7 @@ ThunderAI - __MSG_AddTags_PageTitle__ + @@ -23,15 +24,7 @@ - - __MSG_prefs_Connection_type__ - - - - - + __MSG_prefs_OptionText_add_tags_maxnum__ diff --git a/pages/addtags/mzta-add-tags.js b/pages/addtags/mzta-add-tags.js index 9fc4113b..e068b0df 100644 --- a/pages/addtags/mzta-add-tags.js +++ b/pages/addtags/mzta-add-tags.js @@ -22,15 +22,23 @@ import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js"; import { getPlaceholders } from "../../js/mzta-placeholders.js"; import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js"; import { addTags_getExclusionList, addTags_setExclusionList } from "../../js/mzta-addatags-exclusion-list.js"; -import { getAccountsList, normalizeStringList, populateConnectionTypeOptions } from "../../js/mzta-utils.js"; +import { getAccountsList, normalizeStringList, isAPIKeyValue } from "../../js/mzta-utils.js"; +import { injectConnectionUI } from "../_lib/connection-ui.js"; let autocompleteSuggestions = []; let taLog = new taLogger("mzta-addtags-page",true); document.addEventListener('DOMContentLoaded', async () => { - + try { + injectConnectionUI({ + afterTrId: 'connection_ui_anchor', + selectId: 'add_tags_connection_type', + no_chatgpt_web: true + }); + } catch (e) { + console.error('Failed to inject connection UI (add-tags)', e); + } i18n.updateDocument(); - populateConnectionTypeOptions('add_tags_connection_type', true); await restoreOptions(); document.querySelectorAll(".option-input").forEach(element => { @@ -257,7 +265,7 @@ function saveOptions(e) { async function restoreOptions() { function setCurrentChoice(result) { document.querySelectorAll(".option-input").forEach(element => { - taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" ? "****************" : result[element.id])); + taLog.log("Options restoring " + element.id + " = " + (isAPIKeyValue(element.id) ? "****************" : result[element.id])); switch (element.type) { case 'checkbox': element.checked = result[element.id] || false; @@ -296,4 +304,4 @@ async function restoreOptions() { let getting = await browser.storage.sync.get(prefs_default); setCurrentChoice(getting); -} \ No newline at end of file +}