diff --git a/CHANGELOG.md b/CHANGELOG.md index 737b418f..8c0ccbe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@
  • Added the {%empty%} placeholder to prevent the email body from being automatically appended at the end of the prompt [#345].
  • Added a check for the presence of the correct version of ThunderAI Sparks [#315].
  • [All APIs] Improved the form asking for additional text [#97].
  • +
  • Custom Prompts form improved.
  • Various improvements.
  • ...
  • diff --git a/_locales/en/messages.json b/_locales/en/messages.json index defbf4da..61c51288 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -607,6 +607,10 @@ "message": "In case of login issues in the ThunderAI window, open ChatGPT in a new tab using the button on the right, log in, then close the tab and continue using ThunderAI.", "description": "" }, + "OpenChatGPTTab_Info2": { + "message": "Opening ChatGPT Web from here will apply any configured settings for the model, project, and Custom GPT.", + "description": "" + }, "placeholder_mail_text_body": { "message": "Mail body", "description": "" @@ -672,11 +676,11 @@ "description": "" }, "prefs_OptionText_chatgpt_web_model": { - "message": "ChatGPT Web model", + "message": "ChatGPT Web Model", "description": "" }, "prefs_OptionText_chatgpt_web_model_info": { - "message": "This is the model that will be enforced for the ChatGPT Web Interface. If none is specified or an incorrect one is provided, the default model will be set by ChatGPT on the webpage.", + "message": "This is the Model that will be enforced for the ChatGPT Web Interface. If none is specified or an incorrect one is provided, the default model will be set by ChatGPT on the webpage.", "description": "" }, "prefs_OptionText_chatgpt_web_tempchat": { @@ -1386,5 +1390,53 @@ "AccountSelector_Spamfilter": { "message": "Choose the accounts where the spam filter is enabled", "description": "" + }, + "prefs_OptionText_chatgpt_web_project": { + "message": "ChatGPT Web Project", + "description": "" + }, + "prefs_OptionText_chatgpt_web_project_info": { + "message": "This is the Project that will be enforced for the ChatGPT Web Interface.", + "description": "" + }, + "prefs_OptionText_chatgpt_web_custom_gpt": { + "message": "ChatGPT Web Custom GPT", + "description": "" + }, + "prefs_OptionText_chatgpt_web_custom_gpt_info": { + "message": "This is the Custom GPT that will be enforced for the ChatGPT Web Interface.", + "description": "" + }, + "prefs_OptionText_chatgpt_web_custom_data_info": { + "message": "This must be in the following form:", + "description": "" + }, + "prefs_OptionText_chatgpt_web_custom_data_info2": { + "message": "You can find the correct value in the browser URL field when you open the related ChatGPT page.", + "description": "" + }, + "customPrompts_Properties": { + "message": "Properties", + "description": "" + }, + "customPrompts_show_additional_info": { + "message": "Show additional properties", + "description": "" + }, + "customPrompts_hide_additional_info": { + "message": "Hide additional properties", + "description": "" + }, + "customPrompts_show_additional_info_show": { + "message": "Additional properties", + "description": "" + }, + "prefs_OptionText_CustomGPT_Warn": { + "message": "If a Project is specified in the options or in a prompt, it will override the Custom GPT setting.", + "description": "" + }, + "prefs_OptionText_Project_No_temporary_chat_warn": { + "message": "If a Project is specified in the options or in a prompt, the temporary chat will not be used.", + "description": "" } } \ No newline at end of file diff --git a/api_webchat/messageInput.js b/api_webchat/messageInput.js index 5d726f09..80070659 100644 --- a/api_webchat/messageInput.js +++ b/api_webchat/messageInput.js @@ -310,9 +310,9 @@ class MessageInput extends HTMLElement { this._customTextArea.focus(); } - async _customTextBtnClick(args) { console.log('>>>>>>>>> this in _customTextBtnClick:', this); + async _customTextBtnClick(args) { const customText = this._customTextArea.value; - console.log(">>>>>>>>>>>>>>>> customText: " + customText); + // console.log(">>>>>>>>>>>>>>>> customText: " + customText); args.customBtn.disabled = true; args.customBtn.classList.add('disabled'); args.customLoading.style.display = 'inline-block'; diff --git a/js/mzta-chatgpt.js b/js/mzta-chatgpt.js index 9325e146..b538d855 100644 --- a/js/mzta-chatgpt.js +++ b/js/mzta-chatgpt.js @@ -83,8 +83,16 @@ async function chatgpt_isIdle() { function chatgpt_getRegenerateButton() { for (const mainSVG of document.querySelectorAll('main svg.icon-md')) { - if (mainSVG.querySelector('path[d^="M3.06957"]')) // regen icon found + if (mainSVG.querySelector('path[d^="M3.06957"]')){ // regen icon found + //console.log(">>>>>>>>>> found regen icon!"); return mainSVG.parentNode.parentNode; + } + } + for (const mainSVG of document.querySelectorAll('main svg.icon-md-heavy')) { + if (mainSVG.querySelector('path[d^="M11 4.9099C11 4.47485"]')){ // read aloud icon found + //console.log(">>>>>>>>>> found read aloud icon!"); + return mainSVG.parentNode.parentNode; + } } } @@ -317,13 +325,15 @@ function customTextBtnClick(args) { } function checkGPTModel(model) { - if(model == '') return; + if(model == '') return Promise.resolve(); doLog("checkGPTModel model: " + model); return new Promise((resolve, reject) => { // Set up an interval that shows the warning after 2 seconds const intervalId2 = setTimeout(() => { - document.getElementById('mzta-model_warn').style.display = 'inline-block'; - document.getElementById('mzta-btn_model').style.display = 'inline'; + let modelWarn = document.getElementById('mzta-model_warn'); + let btnModel = document.getElementById('mzta-btn_model'); + if (modelWarn) modelWarn.style.display = 'inline-block'; + if (btnModel) btnModel.style.display = 'inline'; }, 2000); // Set up an interval that checks the value every 100 milliseconds const intervalId = setInterval(() => { @@ -331,15 +341,13 @@ function checkGPTModel(model) { // const element = document.querySelector('div#radix-\\\\:ri2\\\\: > div > span.text-token-text-secondary'); const elements = document.querySelectorAll('[id*=radix] span') - for(element of elements){ + for(let element of elements){ // Check if the element exists and its content is '4' or '4o' doLog("checkGPTModel model found in DOM: " + element.textContent); if ((element && element.textContent === model)||(force_go)) { doLog("The GPT Model is now " + model); clearInterval(intervalId); clearTimeout(intervalId2); - document.getElementById('mzta-model_warn').style.display = 'none'; - document.getElementById('mzta-btn_model').style.display = 'none'; resolve(model); break; } else if (!element) { @@ -388,7 +396,7 @@ async function doProceed(message, customText = ''){ // console.log(">>>>>>>>>>>> doProceed customText: " + customText); // console.log(">>>>>>>>>>>> doProceed final_prompt: " + final_prompt); // console.log(">>>>>>>>>>>> doProceed mztaPhDefVal: " + JSON.stringify(mztaPhDefVal)); - //check if there is che additional_text placeholder + //check if there is the additional_text placeholder if(final_prompt.includes('{%additional_text%}')){ // console.log(">>>>>>>>>>>> found ph customText: " + customText); final_prompt = final_prompt.replace('{%additional_text%}', customText || (mztaPhDefVal == '1'?'':'{%additional_text%}')); @@ -408,14 +416,7 @@ async function doProceed(message, customText = ''){ break; case -2: // textarea not found let curr_model_warn = document.getElementById('mzta-model_warn'); - let message = browser.i18n.getMessage("chatgpt_textarea_not_found_error"); - let parts = message.split(/([^<]+)<\\/a>/); - curr_model_warn.textContent = parts[0]; - let link = document.createElement('a'); - link.href = parts[1]; - link.textContent = parts[2]; - curr_model_warn.appendChild(link); - curr_model_warn.appendChild(document.createTextNode(parts[3])); + curr_model_warn.textContent = browser.i18n.getMessage("chatgpt_textarea_not_found_error"); curr_model_warn.style.display = 'inline-block'; document.getElementById('mzta-curr_msg').textContent = ""; document.getElementById('mzta-loading').style.display = 'none'; @@ -437,6 +438,10 @@ async function doProceed(message, customText = ''){ } function doRetry(){ + document.getElementById('mzta-model_warn').style.display = 'none'; + document.getElementById('mzta-btn_retry').remove(); + document.getElementById('mzta-loading').style.display = 'inline-block'; + document.getElementById('mzta-curr_msg').textContent = browser.i18n.getMessage("chatgpt_win_working"); doProceed(current_message); } diff --git a/js/mzta-prompts.js b/js/mzta-prompts.js index 9ee7a1fa..238f40ca 100644 --- a/js/mzta-prompts.js +++ b/js/mzta-prompts.js @@ -63,6 +63,15 @@ Position Compose Message (position_compose attribute): : position number + ChatGPT Web Model (chatgpt_web_model attribute): + : model name (e.g. gpt-4, gpt-3.5-turbo, etc.) + + ChatGPT Web Project (chatgpt_web_project attribute): + : project id url + + ChatGPT Web Custom GPT (chatgpt_web_custom_gpt attribute): + : custom gpt id url + */ const defaultPrompts = [ @@ -77,6 +86,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "1", use_diff_viewer: "0", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -91,6 +103,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "1", use_diff_viewer: "0", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -105,6 +120,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "1", use_diff_viewer: "1", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -119,6 +137,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "1", use_diff_viewer: "1", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -133,6 +154,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "1", use_diff_viewer: "0", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -147,6 +171,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "1", use_diff_viewer: "0", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -161,6 +188,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "1", use_diff_viewer: "1", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -175,6 +205,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "0", use_diff_viewer: "0", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -189,6 +222,9 @@ const defaultPrompts = [ need_custom_text: "0", define_response_lang: "0", use_diff_viewer: "0", + chatgpt_web_model: '', + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', is_default: "1", is_special: "0", }, @@ -371,6 +407,15 @@ async function getCustomPrompts() { if (prompt.use_diff_viewer === undefined) { prompt.use_diff_viewer = "0"; } + if(prompt.chatgpt_web_model === undefined){ + prompt.chatgpt_web_model = ""; + } + if(prompt.chatgpt_web_project === undefined){ + prompt.chatgpt_web_project = ""; + } + if(prompt.chatgpt_web_custom_gpt === undefined){ + prompt.chatgpt_web_custom_gpt = ""; + } }); return prefs._custom_prompt; } diff --git a/js/mzta-utils.js b/js/mzta-utils.js index b16099a0..e62500ba 100644 --- a/js/mzta-utils.js +++ b/js/mzta-utils.js @@ -411,6 +411,24 @@ export async function checkSparksPresence() { } } +export function validateChatGPTWebCustomData(data) { + return /^\/g\/[a-zA-Z0-9/-]+$/.test(data) || data == ''; +} + +export function sanitizeChatGPTModelData(input) { + return encodeURIComponent(input).toLowerCase() +} + +export function sanitizeChatGPTWebCustomData(input) { + // Removes all characters that are not letters, numbers, dashes, or slashes + return input.replace(/[^\p{L}\p{N}\/-]+/gu, ''); +} + +export function validateCustomData_ChatGPTWeb(event) { + let is_valid = validateChatGPTWebCustomData(event.target.value); + event.target.style.borderColor = is_valid ? 'green' : 'red'; + document.getElementById(event.target.id + '_info').style.color = is_valid ? '' : 'red'; +} // The following methods are a modified version derived from https://github.com/ali-raheem/Aify/blob/13ff87583bc520fb80f555ab90a90c5c9df797a7/plugin/content_scripts/compose.js diff --git a/mzta-background.js b/mzta-background.js index 86b43752..4f3e3114 100644 --- a/mzta-background.js +++ b/mzta-background.js @@ -20,7 +20,7 @@ import { mzta_script } from './js/mzta-chatgpt.js'; import { prefs_default } from './options/mzta-options-default.js'; import { mzta_Menus } from './js/mzta-menus.js'; import { taLogger } from './js/mzta-logger.js'; -import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagExists, getActiveSpecialPromptsIDs, checkSparksPresence, getMessages, getMailBody, extractJsonObject, contextMenuID_AddTags, contextMenuID_Spamfilter } from './js/mzta-utils.js'; +import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagExists, getActiveSpecialPromptsIDs, checkSparksPresence, getMessages, getMailBody, extractJsonObject, contextMenuID_AddTags, contextMenuID_Spamfilter, sanitizeChatGPTModelData, sanitizeChatGPTWebCustomData } from './js/mzta-utils.js'; import { taPromptUtils } from './js/mzta-utils-prompt.js'; import { mzta_specialCommand } from './js/mzta-special-commands.js'; import { getSpamFilterPrompt } from './js/mzta-prompts.js'; @@ -317,6 +317,7 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_ taLog.changeDebug(prefs.do_debug); prefs = checkScreenDimensions(prefs); //console.log(">>>>>>>>>>>>>>>> prefs: " + JSON.stringify(prefs)); + console.log(">>>>>>>>>>>>>>>> prompt_info: " + JSON.stringify(prompt_info)); taLog.log("Prompt length: " + promptText.length); if(promptText.length > prefs.max_prompt_length){ // Prompt too long for ChatGPT @@ -334,18 +335,40 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_ let rand_call_id = '_chatgptweb_' + generateCallID(); let call_opt = ''; + let _wait_time = 1000; + let _base_url = "https://chatgpt.com"; + let _webproject_set = false; + let _custom_gpt_set = false; + let _use_prompt_info_custom_gpt = false; + let _custom_model = sanitizeChatGPTModelData(prompt_info.chatgpt_web_model != '' ? prompt_info.chatgpt_web_model : prefs.chatgpt_web_model); + let _web_project = sanitizeChatGPTWebCustomData(prompt_info.chatgpt_web_project != '' ? prompt_info.chatgpt_web_project : prefs.chatgpt_web_project) + let _custom_gpt = sanitizeChatGPTWebCustomData(prompt_info.chatgpt_web_custom_gpt != '' ? prompt_info.chatgpt_web_custom_gpt : prefs.chatgpt_web_custom_gpt) + if(prefs.chatgpt_web_tempchat){ call_opt += '&temporary-chat=true'; } - if(prefs.chatgpt_web_model != ''){ - call_opt += '&model=' + encodeURIComponent(prefs.chatgpt_web_model).toLowerCase(); + if((prompt_info.chatgpt_web_model != '') || (prefs.chatgpt_web_model != '')){ + call_opt += '&model=' + _custom_model; } taLog.log("[chatgpt_web] call_opt: " + call_opt); + // If there is a custom gpt on the prompt, but also a web_project on the prefs, we need to use the custom gpt + _use_prompt_info_custom_gpt = (prompt_info.chatgpt_web_custom_gpt != '' && prompt_info.chatgpt_web_project == ''); + + if(!_use_prompt_info_custom_gpt && ((prompt_info.chatgpt_web_project != '') || (prefs.chatgpt_web_project != ''))){ + _base_url += _web_project; + _webproject_set = true; + _wait_time = 2000; + } + if(!_webproject_set && ((prompt_info.chatgpt_web_custom_gpt != '') || (prefs.chatgpt_web_custom_gpt != ''))){ + _base_url += _custom_gpt; + _custom_gpt_set = true; + } + let win_options = { - url: "https://chatgpt.com?call_id=" + rand_call_id + call_opt, + url: _base_url + "?call_id=" + rand_call_id + call_opt, type: "popup", } @@ -360,9 +383,9 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_ async function handleChatGptWeb(createdTab) { taLog.log("ChatGPT web interface script started..."); - let _gpt_model = getGPTWebModelString(prefs.chatgpt_web_model); + let _gpt_model = getGPTWebModelString(_custom_model); - taLog.log("prefs.chatgpt_web_model: " + prefs.chatgpt_web_model); + taLog.log("_custom_model: " + _custom_model); taLog.log("_gpt_model: " + _gpt_model); let originalText = prompt_info.selection_text; @@ -377,15 +400,15 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_ let mztaDoCustomText=`+ do_custom_text +`; let mztaPromptName="[`+ i18nConditionalGet(prompt_name) +`]"; let mztaPhDefVal="`+(prefs.placeholders_use_default_value?'1':'0')+`"; - let mztaGPTModel="`+ _gpt_model +`"; + let mztaGPTModel="`+ (_custom_gpt_set ? '' : _gpt_model) +`"; let mztaDoDebug="`+(prefs.do_debug?'1':'0')+`"; let mztaUseDiffViewer="`+(prompt_info.use_diff_viewer=='1'?'1':'0')+`"; let mztaOriginalText="`+ JSON.stringify(originalText).slice(1, -1) +`"; `; - taLog.log("Waiting 1 sec"); - await new Promise(resolve => setTimeout(resolve, 1000)); - taLog.log("Waiting 1 sec done"); + taLog.log("Waiting " + _wait_time + " millisec"); + await new Promise(resolve => setTimeout(resolve, _wait_time)); + taLog.log("Waiting " + _wait_time + " millisec done"); await browser.tabs.executeScript(createdTab.id, { code: pre_script + mzta_script, matchAboutBlank: false }); // let mailMessage = await browser.messageDisplay.getDisplayedMessage(curr_tabId); diff --git a/options/mzta-options-default.js b/options/mzta-options-default.js index 501b0254..3f9fe33b 100644 --- a/options/mzta-options-default.js +++ b/options/mzta-options-default.js @@ -25,6 +25,8 @@ export const prefs_default = { connection_type: 'chatgpt_web', //Other values: 'chatgpt_api', 'ollama_api', 'openai_comp_api', 'google_gemini_api' chatgpt_web_model: '', chatgpt_web_tempchat: false, + chatgpt_web_project: '', + chatgpt_web_custom_gpt: '', chatgpt_api_key: '', chatgpt_model: '', chatgpt_developer_messages: '', diff --git a/options/mzta-options.css b/options/mzta-options.css index e556eee2..f30c0f42 100644 --- a/options/mzta-options.css +++ b/options/mzta-options.css @@ -74,6 +74,10 @@ span.dims_label{ display: inline-block; } +span.opt_title{ + font-weight: bold; +} + #btn_custom_prompts{ text-align: center; width: 100%; diff --git a/options/mzta-options.html b/options/mzta-options.html index 08d987b1..7c56b274 100644 --- a/options/mzta-options.html +++ b/options/mzta-options.html @@ -18,7 +18,7 @@ __MSG_hyprland_warning__ - __MSG_prefs_OptionText_chatgpt_win_text__ + __MSG_prefs_OptionText_chatgpt_win_text__
    @@ -167,7 +194,7 @@ @@ -181,7 +208,7 @@ @@ -193,7 +220,7 @@
    @@ -207,7 +234,7 @@ @@ -221,7 +248,7 @@ @@ -233,7 +260,7 @@ @@ -253,7 +280,7 @@ @@ -266,7 +293,7 @@ @@ -286,7 +313,7 @@
  • Added a check for the presence of the correct version of ThunderAI Sparks [#315].
  • Added the {%empty%} placeholder to prevent the email body from being automatically appended at the end of the prompt [#345].
  • [All APIs] Improved the form asking for additional text [#97].
  • +
  • Custom Prompts form improved.
  • Various improvements.
  • ...
  • diff --git a/pages/customprompts/mzta-custom-prompts.css b/pages/customprompts/mzta-custom-prompts.css index d96b29ca..07826f02 100644 --- a/pages/customprompts/mzta-custom-prompts.css +++ b/pages/customprompts/mzta-custom-prompts.css @@ -25,6 +25,7 @@ table { thead { position: sticky; top: 26px; + z-index: 90; } #command_palette{ @@ -33,6 +34,7 @@ thead { padding-top: 1px; height: 26px; width: 100%; + z-index: 90; } #btnNew{ @@ -102,6 +104,10 @@ table .sort.desc { background-image: url(../images/listjs-arrow-sort-active-up.png); } +tbody.list tr{ + vertical-align: top; +} + .hiddendata{ display: none; } @@ -135,6 +141,24 @@ table .sort.desc { font-style: italic; } +.field_title{ + font-weight: bold; +} + +.field_title_s{ + font-weight: bold; + font-size: small; +} + +.field_title_us{ + font-weight: bold; + font-size: smaller; +} + +label, .id_show, .text_show, .name_show, .type_show, .action_show{ + font-size: small; +} + #txtIdNew, .id_output{ text-transform: lowercase; } @@ -204,6 +228,67 @@ table .sort.desc { padding-right: 2px; } +#chatgpt_web_additional_info_toggle td{ + padding:0px 5px; + font-style: italic; +} + +#chatgpt_web_additional_info, #chatgpt_web_additional_info_toggle, .chatgpt_web_additional_info, .chatgpt_web_additional_info_toggle, .chatgpt_web_additional_info_show{ + background-color: rgb(255, 209, 183); + display:none; +} + +#chatgpt_web_additional_info_toggle, .chatgpt_web_additional_info_toggle{ + cursor: pointer; +} + +#chatgpt_web_additional_info_toggle:hover, .chatgpt_web_additional_info_toggle:hover{ + background-color: rgb(255, 189, 153); + text-decoration: underline; +} + +#chatgpt_web_additional_info_toggle td{ + text-align: center; +} + +#chatgpt_web_additional_info td{ + vertical-align: top; +} + +.chatgpt_web_additional_info_toggle{ + width: -moz-available; + text-align: center; + margin-top: 10px; +} + +.chatgpt_web_additional_info_show{ + flex-direction: column; + justify-content: space-between; + height: 100%; + padding: 3px; + margin-top: 5px; +} + +.chatgpt_web_additional_info_row{ + display: flex; +} + +.chatgpt_web_additional_info_row span{ + margin-right: 0.4em; +} + +input.input_additional[type="text"]{ + width: -moz-available; +} + +.small_info{ + font-size:smaller; +} + +.conntype_chatgpt_web_option{ + cursor: pointer; +} + @media (prefers-color-scheme: dark) { body { background-color: #1C1B22; @@ -250,4 +335,12 @@ table .sort.desc { .autocomplete-list li.active { background-color: #4c4e58; } + + #chatgpt_web_additional_info{ + background-color: rgb(39, 11, 0); + } + + #chatgpt_web_additional_info, #chatgpt_web_additional_info_toggle, .chatgpt_web_additional_info, .chatgpt_web_additional_info_toggle, .chatgpt_web_additional_info_show{ + color: black; + } } \ No newline at end of file diff --git a/pages/customprompts/mzta-custom-prompts.html b/pages/customprompts/mzta-custom-prompts.html index d83bc66f..38900061 100644 --- a/pages/customprompts/mzta-custom-prompts.html +++ b/pages/customprompts/mzta-custom-prompts.html @@ -27,29 +27,39 @@ - - + + + +
    - +

    [__MSG_customPrompts_form_label_ID_rules__]
    - +
    - + +
    +

    + +
    +
    + +

    @@ -63,18 +73,31 @@
    - +
    - -
    - +
    __MSG_customPrompts_show_additional_info__
    + +
    + + TODO
    +

    + +
    + +
    __MSG_prefs_OptionText_chatgpt_web_custom_data_info__ /g/PROJECT-ID-PROJECT-NAME/project +
    __MSG_prefs_OptionText_chatgpt_web_custom_data_info2__
    +
    + +
    + +
    __MSG_prefs_OptionText_chatgpt_web_custom_data_info__ /g/CUSTOM-GPT-ID +
    __MSG_prefs_OptionText_chatgpt_web_custom_data_info2__
    @@ -89,8 +112,8 @@ __MSG_customPrompts_form_label_ID__ __MSG_customPrompts_form_label_Name__ __MSG_customPrompts_form_label_Text__ - __MSG_customPrompts_add_to_menu__ - Properties +   + __MSG_customPrompts_Properties__   diff --git a/pages/customprompts/mzta-custom-prompts.js b/pages/customprompts/mzta-custom-prompts.js index e61d392c..9a09b907 100644 --- a/pages/customprompts/mzta-custom-prompts.js +++ b/pages/customprompts/mzta-custom-prompts.js @@ -16,12 +16,14 @@ * along with this program. If not, see . */ +import { prefs_default } from "../../options/mzta-options-default.js"; import { getPrompts, setDefaultPromptsProperties, setCustomPrompts, preparePromptsForExport, preparePromptsForImport } from "../../js/mzta-prompts.js"; -import { isThunderbird128OrGreater, getCustomPromptsUsedSpace, sanitizeHtml } from "../../js/mzta-utils.js"; +import { isThunderbird128OrGreater, getCustomPromptsUsedSpace, sanitizeHtml, validateCustomData_ChatGPTWeb } from "../../js/mzta-utils.js"; import { taLogger } from "../../js/mzta-logger.js"; import { getPlaceholders } from "../../js/mzta-placeholders.js"; import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js"; +let prefs = null; var promptsList = null; var somethingChanged = false; var positionMax_compose = 0; @@ -33,8 +35,8 @@ let autocompleteSuggestions = []; document.addEventListener('DOMContentLoaded', async () => { - let prefs_debug = await browser.storage.sync.get({do_debug: false}); - taLog = new taLogger("mzta-custom-prompts", prefs_debug.do_debug); + prefs = await browser.storage.sync.get({ connection_type:prefs_default.connection_type, do_debug: prefs_default.do_debug }); + taLog = new taLogger("mzta-custom-prompts", prefs.do_debug); setStorageSpace(); @@ -98,22 +100,68 @@ document.addEventListener('DOMContentLoaded', async () => { }); }); - // document.addEventListener('click', (e) => { - // // Check if the click was outside the textarea or suggestion list - // const isClickInsideTextarea = e.target.closest('.editor'); - // const isClickInsideAutocompleteList = e.target.closest('.autocomplete-list'); - - // if (!isClickInsideTextarea && !isClickInsideAutocompleteList) { - // textareas.forEach(textarea => { - // const container = textarea.closest('.autocomplete-container'); - // const autocompleteList = container.querySelector('.autocomplete-list'); - // hideSuggestions(autocompleteList); - // }); - // } - // }); - i18n.updateDocument(); + switch(prefs.connection_type) { + case 'chatgpt_web': { + // for the new item form + document.getElementById('chatgpt_web_additional_info_toggle').style.display = 'table-row'; + // for the edit list items form + document.querySelectorAll('.chatgpt_web_additional_info_toggle').forEach(element => { + element.addEventListener('click', (e) => { + e.preventDefault(); + let additionalInfoRow = e.target.closest('td').querySelector('.chatgpt_web_additional_info'); + if (additionalInfoRow.style.display === 'none' || additionalInfoRow.style.display === '') { + additionalInfoRow.style.display = 'block'; + e.target.innerText = browser.i18n.getMessage('customPrompts_hide_additional_info'); + } else { + additionalInfoRow.style.display = 'none'; + e.target.innerText = browser.i18n.getMessage('customPrompts_show_additional_info'); + } + }); + }); + document.querySelectorAll('input.chatgpt_web_project_output').forEach(element => { + element.addEventListener("input", validateCustomData_ChatGPTWeb); + }); + document.querySelectorAll('input.chatgpt_web_custom_gpt_output').forEach(element => { + element.addEventListener("input", validateCustomData_ChatGPTWeb); + }); + break; + } + // case 'chatgpt_api': + // document.getElementById('chatgpt_api').style.display = 'block'; + // break; + // case 'ollama_api': + // document.getElementById('ollama_api').style.display = 'block'; + // break; + // case 'openai_comp_api': + // document.getElementById('openai_comp_api').style.display = 'block'; + // break; + // case 'google_gemini_api': + // document.getElementById('google_gemini_api').style.display = 'block'; + // break; + } + + const chatgptWebAdditionalPropToggle = document.getElementById('chatgpt_web_additional_info_toggle'); + chatgptWebAdditionalPropToggle.addEventListener('click', (e) => { + e.preventDefault(); + const additionalInfoRow = document.getElementById('chatgpt_web_additional_info'); + if (additionalInfoRow.style.display === 'none' || additionalInfoRow.style.display === '') { + additionalInfoRow.style.display = 'table-row'; + let subspan = chatgptWebAdditionalPropToggle.querySelector('td span'); + if (subspan) { + subspan.innerText = browser.i18n.getMessage('customPrompts_hide_additional_info'); + } + } else { + additionalInfoRow.style.display = 'none'; + let subspan = chatgptWebAdditionalPropToggle.querySelector('td span'); + if (subspan) { + subspan.innerText = browser.i18n.getMessage('customPrompts_show_additional_info'); + } + } + }); + + //To add a new item var txtIdNew = document.getElementById('txtIdNew'); var txtNameNew = document.getElementById('txtNameNew'); @@ -125,6 +173,12 @@ document.addEventListener('DOMContentLoaded', async () => { var checkboxNeedCustomTextNew = document.getElementById('checkboxNeedCustomTextNew'); var checkboxDefineResponseLangNew = document.getElementById('checkboxDefineResponseLangNew'); var checkboxUseDiffViewerNew = document.getElementById('checkboxUseDiffViewerNew'); + // ChatGTP Web Integration + var chatgptWebModelNew = document.getElementById('chatGPTWebModelNew'); + var chatgptWebProjectNew = document.getElementById('chatGPTWebProjectNew'); + var chatgptWebCustomGptNew = document.getElementById('chatGPTWebCustomGPTNew'); + chatgptWebProjectNew.addEventListener("input", validateCustomData_ChatGPTWeb); + chatgptWebCustomGptNew.addEventListener("input", validateCustomData_ChatGPTWeb); selectActionNew.addEventListener('change', (e) => { if (e.target.value === "2") { @@ -141,7 +195,7 @@ document.addEventListener('DOMContentLoaded', async () => { if(!checkFields()) { return; } - let newItem = promptsList.add({ + let newItemData = { id: String(txtIdNew.value.trim()).toLocaleLowerCase(), name: txtNameNew.value.trim(), text: txtTextNew.value.trim(), @@ -157,7 +211,29 @@ document.addEventListener('DOMContentLoaded', async () => { position_display: positionMax_display + 1, is_default: 0, idnum: idnumMax + 1, - }); + }; + + switch(prefs.connection_type) { + case 'chatgpt_web': + newItemData.chatgpt_web_model = chatgptWebModelNew.value.trim(); + newItemData.chatgpt_web_project = chatgptWebProjectNew.value.trim(); + newItemData.chatgpt_web_custom_gpt = chatgptWebCustomGptNew.value.trim(); + break; + // case 'chatgpt_api': + // document.getElementById('chatgpt_api').style.display = 'block'; + // break; + // case 'ollama_api': + // document.getElementById('ollama_api').style.display = 'block'; + // break; + // case 'openai_comp_api': + // document.getElementById('openai_comp_api').style.display = 'block'; + // break; + // case 'google_gemini_api': + // document.getElementById('google_gemini_api').style.display = 'block'; + // break; + } + + let newItem = promptsList.add(newItemData); idnumMax++; let curr_idnum = newItem[0].values().idnum; let checkboxes = document.querySelectorAll(`tr[data-idnum="${curr_idnum}"] input[type="checkbox"]`); @@ -266,6 +342,10 @@ document.addEventListener('DOMContentLoaded', async () => { }; } + document.querySelectorAll('.chatgpt_web_additional_info_show').forEach(element => { + toggleAdditionalPropertiesShow(element.closest('tr')); + }); + }, { once: true }); //========= handling an item in a row @@ -291,6 +371,8 @@ function showItemRowEditor(tr) { text_output.style.display = 'inline'; textareaAutocomplete(text_output, autocompleteSuggestions) tr.querySelector('.text_show').style.display = 'none'; + toggleAdditionalPropertiesEditor(tr); + tr.querySelector('.chatgpt_web_additional_info_show').style.display = 'none'; tr.querySelector('.type_output').style.display = 'inline'; tr.querySelector('.type_show').style.display = 'none'; const action_output = tr.querySelector('.action_output') @@ -311,6 +393,9 @@ function hideItemRowEditor(tr) { tr.querySelector('.name_show').style.display = 'inline'; tr.querySelector('.text_output').style.display = 'none'; tr.querySelector('.text_show').style.display = 'inline'; + tr.querySelector('.chatgpt_web_additional_info_toggle').style.display = 'none'; + tr.querySelector('.chatgpt_web_additional_info').style.display = 'none'; + toggleAdditionalPropertiesShow(tr); tr.querySelector('.type_output').style.display = 'none'; tr.querySelector('.type_show').style.display = 'inline'; const action_output = tr.querySelector('.action_output') @@ -324,6 +409,85 @@ function hideItemRowEditor(tr) { tr.querySelector('input.use_diff_viewer').disabled = true; } +function toggleAdditionalPropertiesShow(tr) { + switch(prefs.connection_type) { + case 'chatgpt_web': { + let element = tr.querySelector('.chatgpt_web_additional_info_show'); + let chatGPTWebModel_show = tr.querySelector('.chatgpt_web_model_show'); + let chatGPTWebProject_show = tr.querySelector('.chatgpt_web_project_show'); + let chatGPTWebCustomGPT_show = tr.querySelector('.chatgpt_web_custom_gpt_show'); + + if ((chatGPTWebModel_show.innerText !== '' && chatGPTWebModel_show.innerText !== 'undefined') || + (chatGPTWebProject_show.innerText !== '' && chatGPTWebProject_show.innerText !== 'undefined') || + (chatGPTWebCustomGPT_show.innerText !== '' && chatGPTWebCustomGPT_show.innerText !== 'undefined')) { + element.style.display = 'flex'; + } else { + element.style.display = 'none'; + } + + if(chatGPTWebModel_show.innerText === '' || chatGPTWebModel_show.innerText === 'undefined') { + chatGPTWebModel_show.parentNode.style.display = 'none'; + } else { + chatGPTWebModel_show.parentNode.style.display = 'inline'; + } + if(chatGPTWebProject_show.innerText === '' || chatGPTWebProject_show.innerText === 'undefined') { + chatGPTWebProject_show.parentNode.style.display = 'none'; + } else { + chatGPTWebProject_show.parentNode.style.display = 'inline'; + } + if(chatGPTWebCustomGPT_show.innerText === '' || chatGPTWebCustomGPT_show.innerText === 'undefined') { + chatGPTWebCustomGPT_show.parentNode.style.display = 'none'; + } else { + chatGPTWebCustomGPT_show.parentNode.style.display = 'inline'; + } + break; + } + // case 'chatgpt_api': + // document.getElementById('chatgpt_api').style.display = 'block'; + // break; + // case 'ollama_api': + // document.getElementById('ollama_api').style.display = 'block'; + // break; + // case 'openai_comp_api': + // document.getElementById('openai_comp_api').style.display = 'block'; + // break; + // case 'google_gemini_api': + // document.getElementById('google_gemini_api').style.display = 'block'; + // break; + } +} + +function toggleAdditionalPropertiesEditor(tr) { + switch(prefs.connection_type) { + case 'chatgpt_web': { + let info_toggle = tr.querySelector('.chatgpt_web_additional_info_toggle'); + info_toggle.style.display = 'block'; + let chatGPTWebModel_show = tr.querySelector('.chatgpt_web_model_show').innerText; + let chatGPTWebProject_show = tr.querySelector('.chatgpt_web_project_show').innerText; + let chatGPTWebCustomGPT_show = tr.querySelector('.chatgpt_web_custom_gpt_show').innerText; + + if ((chatGPTWebModel_show !== '' && chatGPTWebModel_show !== 'undefined') || + (chatGPTWebProject_show !== '' && chatGPTWebProject_show !== 'undefined') || + (chatGPTWebCustomGPT_show !== '' && chatGPTWebCustomGPT_show !== 'undefined')) { + info_toggle.click(); + } + break; + } + // case 'chatgpt_api': + // document.getElementById('chatgpt_api').style.display = 'block'; + // break; + // case 'ollama_api': + // document.getElementById('ollama_api').style.display = 'block'; + // break; + // case 'openai_comp_api': + // document.getElementById('openai_comp_api').style.display = 'block'; + // break; + // case 'google_gemini_api': + // document.getElementById('google_gemini_api').style.display = 'block'; + // break; + } +} + function toggleDiffviewer(e) { e.preventDefault(); const tr = e.target.parentNode.parentNode; @@ -371,6 +535,9 @@ function handleCancelClick(e) { // tr.querySelector('.type_output').selectedOptions[0].text = tr.querySelector('.type_show').innerText; tr.querySelector('.action_output').value = tr.querySelector('.action').innerText; // tr.querySelector('.action_output').selectedOptions[0].text = tr.querySelector('.action_show').innerText; + tr.querySelector('.chatgpt_web_model_output').value = tr.querySelector('.chatgpt_web_model_show').innerText; + tr.querySelector('.chatgpt_web_project_output').value = tr.querySelector('.chatgpt_web_project_show').innerText; + tr.querySelector('.chatgpt_web_custom_gpt_output').value = tr.querySelector('.chatgpt_web_custom_gpt_show').innerText; hideItemRowEditor(tr); } @@ -386,6 +553,9 @@ function handleConfirmClick(e) { tr.querySelector('.id_show').innerText = String(tr.querySelector('.id_output').value).toLocaleLowerCase(); tr.querySelector('.name_show').innerText = tr.querySelector('.name_output').value; tr.querySelector('.text_show').innerText = tr.querySelector('.text_output').value; + tr.querySelector('.chatgpt_web_model_show').innerText = tr.querySelector('.chatgpt_web_model_output').value; + tr.querySelector('.chatgpt_web_project_show').innerText = tr.querySelector('.chatgpt_web_project_output').value; + tr.querySelector('.chatgpt_web_custom_gpt_show').innerText = tr.querySelector('.chatgpt_web_custom_gpt_output').value; tr.querySelector('.type').innerText = tr.querySelector('.type_output').value; tr.querySelector('.type_show').innerText = tr.querySelector('.type_output').selectedOptions[0].text; tr.querySelector('.action').innerText = tr.querySelector('.action_output').value; @@ -451,24 +621,53 @@ function loadPromptsList(values){ let output = ` -
    - ` + type_output + ` + + +
    + + +
    +
    __MSG_customPrompts_show_additional_info__
    +
    + __MSG_prefs_OptionText_chatgpt_web_model__: +
    + + TODO
    +

    + __MSG_prefs_OptionText_chatgpt_web_project__: +
    + +
    __MSG_prefs_OptionText_chatgpt_web_custom_data_info__ /g/PROJECT_ID-PROJECT_NAME/project +
    __MSG_prefs_OptionText_chatgpt_web_custom_data_info2__
    +

    + __MSG_prefs_OptionText_chatgpt_web_custom_gpt__: +
    + +
    __MSG_prefs_OptionText_chatgpt_web_custom_data_info__ /g/CUSTOM_GPT_ID +
    __MSG_prefs_OptionText_chatgpt_web_custom_data_info2__ +
    __MSG_prefs_OptionText_CustomGPT_Warn__
    +
    + + __MSG_customPrompts_add_to_menu__: +
    + ` + type_output + ` ` + ` +

    + __MSG_customPrompts_form_label_Action__: +
    ` + action_output + ` + ` + + ` - Action: ` + action_output + ` - ` + - ` -

    @@ -483,6 +682,11 @@ function loadPromptsList(values){ +
    __MSG_customPrompts_show_additional_info_show__ +
    __MSG_prefs_OptionText_chatgpt_web_model__:` + values.chatgpt_web_model + `
    +
    __MSG_prefs_OptionText_chatgpt_web_project__:` + values.chatgpt_web_project + `
    +
    __MSG_prefs_OptionText_chatgpt_web_custom_gpt__:` + values.chatgpt_web_custom_gpt + `
    +
    @@ -500,6 +704,28 @@ function loadPromptsList(values){ } }; + switch(prefs.connection_type) { + case 'chatgpt_web': { + options.valueNames.push('chatgpt_web_model', 'chatgpt_web_project', 'chatgpt_web_custom_gpt'); + break; + } + // case 'chatgpt_api': + // document.getElementById('chatgpt_api').style.display = 'block'; + // break; + // case 'ollama_api': + // document.getElementById('ollama_api').style.display = 'block'; + // break; + // case 'openai_comp_api': + // document.getElementById('openai_comp_api').style.display = 'block'; + // break; + // case 'google_gemini_api': + // document.getElementById('google_gemini_api').style.display = 'block'; + // break; + } + + // console.log('>>>>>>>>>>>>> options: ' + JSON.stringify(options)); + // console.log('>>>>>>>>>>>>> values: ' + JSON.stringify(values)); + promptsList = new List('all_prompts', options, values); checkSelectedBoxes(); @@ -574,6 +800,9 @@ function clearFields() { document.getElementById('txtIdNew').value = ''; document.getElementById('txtNameNew').value = ''; document.getElementById('txtTextNew').value = ''; + document.getElementById('chatGPTWebModelNew').value = ''; + document.getElementById('chatGPTWebProjectNew').value = ''; + document.getElementById('chatGPTWebCustomGPTNew').value = ''; document.getElementById('selectTypeNew').value = '0'; document.getElementById('selectActionNew').value = '0'; document.getElementById('checkboxNeedSelectedNew').value = '0'; @@ -643,6 +872,7 @@ async function saveAll() { promptsList.reIndex(); let newPrompts = promptsList.items.map(item => { // For each item in the array, return only the '_values' part + // console.log(">>>>>>>>>>>>>>>> item: " + JSON.stringify(item)) return item.values(); }); taLog.log('newPrompts: ' + JSON.stringify(newPrompts)); diff --git a/popup/mzta-popup.js b/popup/mzta-popup.js index f605bd23..0588e63b 100644 --- a/popup/mzta-popup.js +++ b/popup/mzta-popup.js @@ -49,10 +49,10 @@ document.addEventListener('DOMContentLoaded', async () => { get_calendar_event = prefs.get_calendar_event; get_task = prefs.get_task; _ok_sparks = await checkSparksPresence() == 1; - console.log(">>>>>>>>>>>>>>>>> add_tags: " + add_tags); - console.log(">>>>>>>>>>>>>>>>> get_calendar_event: " + get_calendar_event); - console.log(">>>>>>>>>>>>>>>>> get_task: " + get_task); - console.log(">>>>>>>>>>>>>>>>> _ok_sparks: " + _ok_sparks); + // console.log(">>>>>>>>>>>>>>>>> add_tags: " + add_tags); + // console.log(">>>>>>>>>>>>>>>>> get_calendar_event: " + get_calendar_event); + // console.log(">>>>>>>>>>>>>>>>> get_task: " + get_task); + // console.log(">>>>>>>>>>>>>>>>> _ok_sparks: " + _ok_sparks); searchPrompt(active_prompts, tabId, tabType); i18n.updateDocument(); @@ -127,18 +127,18 @@ async function searchPrompt(allPrompts, tabId, tabType){ let do_get_calendar_event = checkDoCalendarEvent(); let do_get_task = checkDoTask(); - console.log(">>>>>>>>>>> do_add_tags: " + do_add_tags); - console.log(">>>>>>>>>>> do_get_calendar_event: " + do_get_calendar_event); - console.log(">>>>>>>>>>> do_get_task: " + do_get_task); - console.log(">>>>>>>>>>> filteredData: " + JSON.stringify(filteredData)); + // console.log(">>>>>>>>>>> do_add_tags: " + do_add_tags); + // console.log(">>>>>>>>>>> do_get_calendar_event: " + do_get_calendar_event); + // console.log(">>>>>>>>>>> do_get_task: " + do_get_task); + // console.log(">>>>>>>>>>> filteredData: " + JSON.stringify(filteredData)); num_special_menu_items = (do_add_tags ? 1 : 0) + (do_get_calendar_event ? 1 : 0) + (do_get_task ? 1 : 0); // console.log(">>>>>>>>>>>> num_special_menu_items: " + num_special_menu_items); if(num_special_menu_items > 0){ max_num_el -= num_special_menu_items; first_num_el = num_special_menu_items; - console.log(">>>>>>>>>>>>> max_num_el: " + max_num_el); - console.log(">>>>>>>>>>>>> first_num_el: " + first_num_el); + // console.log(">>>>>>>>>>>>> max_num_el: " + max_num_el); + // console.log(">>>>>>>>>>>>> first_num_el: " + first_num_el); if(do_add_tags){ filteredData = ensurePromptAddTagsFirst(filteredData); if (!filteredData[0].numberPrepended) { @@ -164,7 +164,7 @@ async function searchPrompt(allPrompts, tabId, tabType){ } } - console.log(">>>>>>>>>>> filteredData after special items check: " + JSON.stringify(filteredData)); + // console.log(">>>>>>>>>>> filteredData after special items check: " + JSON.stringify(filteredData)); Array.from(filteredData).slice(first_num_el, max_num_el).forEach((item, index) => { let number = (index + first_num_el).toString();