/* * ThunderAI [https://micz.it/thunderbird-addon-thunderai/] * Copyright (C) 2024 - 2026 Mic (m@micz.it) * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import { prefs_default, integration_options_config } from "../../options/mzta-options-default.js"; import { getPrompts, setDefaultPromptsProperties, setCustomPrompts, preparePromptsForExport, preparePromptsForImport } from "../../js/mzta-prompts.js"; import { injectConnectionUI, showConnectionOptions, updateWarnings } from "../../pages/_lib/connection-ui.js"; import { ChatGPTWeb_models, getLocalStorageUsedSpace, sanitizeHtml, validateCustomData_ChatGPTWeb, getChatGPTWebModelsList_HTML, openTab, setTomSelectBorder } from "../../js/mzta-utils.js"; import { taLogger } from "../../js/mzta-logger.js"; import { getPlaceholders, placeholdersUtils, mapPlaceholderToSuggestion } 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; var positionMax_display = 0; var idnumMax = 0; var msgTimeout = null; let taLog = null; let autocompleteSuggestions = []; document.addEventListener('DOMContentLoaded', async () => { let storedPrefs = await browser.storage.sync.get(null); prefs = { ...prefs_default, ...storedPrefs }; taLog = new taLogger("mzta-custom-prompts", prefs.do_debug); setStorageSpace(); let values = await getPrompts(); //console.log('>>>>>>>>>>>>>>>> values: ' + JSON.stringify(values)); loadPromptsList(values); const btnSaveAll = document.getElementById('btnSaveAll'); btnSaveAll.disabled = true; // Disable save button and handle save actions function handleSaveAllClick(e) { e.preventDefault(); saveAll(); clearFields(); } btnSaveAll.addEventListener('click', handleSaveAllClick); const btnNew = document.getElementById('btnNew'); // Show the new item form function handleNewClick(e) { e.preventDefault(); e.target.disabled = true; document.getElementById('formNew').style.display = 'block'; let _checkboxUseDiffViewerNew = document.getElementById('checkboxUseDiffViewerNew'); _checkboxUseDiffViewerNew.checked = false; _checkboxUseDiffViewerNew.disabled = true; window.scrollTo({ top: 0, behavior: 'smooth' }); } btnNew.addEventListener('click', handleNewClick); // for the new prompt form let btnNew_elements = document.querySelectorAll(".input_new"); if(btnNew_elements) { btnNew_elements.forEach(element => { element.addEventListener('input', (e) => { e.preventDefault(); checkFields(); }); }); } const textareas = document.querySelectorAll('.editor'); autocompleteSuggestions = (await getPlaceholders(true)).map(mapPlaceholderToSuggestion); // console.log('>>>>>>>>>>> autocompleteSuggestions: ' + JSON.stringify(autocompleteSuggestions)); textareas.forEach(textarea => { textareaAutocomplete(textarea, autocompleteSuggestions); textareas.forEach(textarea => { textarea.addEventListener('input', async (e) => { await checkPromptsConfigForPlaceholders(e.target); }); textareaAutocomplete(textarea, autocompleteSuggestions); }); }); const apiSettingsToggle = document.getElementById('api_additional_info_toggle'); const apiSettingsRow = document.getElementById('api_additional_info'); apiSettingsToggle.addEventListener('click', (e) => { e.preventDefault(); if (apiSettingsRow.style.display === 'none') { apiSettingsRow.style.display = 'table-row'; apiSettingsToggle.querySelector('span').innerText = browser.i18n.getMessage('customPrompts_hide_additional_info') + ' [API]'; } else { apiSettingsRow.style.display = 'none'; apiSettingsToggle.querySelector('span').innerText = browser.i18n.getMessage('customPrompts_show_additional_info') + ' [API]'; } }); await injectConnectionUI({ afterTrId: 'api_ui_anchor', selectId: 'new_prompt_api_type', no_chatgpt_web: true, taLog: taLog, customButtonLabel: browser.i18n.getMessage("Reset"), customButtonCallback: () => { resetApiSettings('new_prompt_api_type'); } }); // Fill defaults for new prompt form for (const [integration, options] of Object.entries(integration_options_config)) { for (const key of Object.keys(options)) { const propName = `${integration}_${key}`; const inputEl = document.getElementById(propName); if (inputEl && prefs[propName] !== undefined) { if (inputEl.type === 'checkbox') { inputEl.checked = (prefs[propName] === true || prefs[propName] === 'true'); } else { inputEl.value = prefs[propName]; } } } } i18n.updateDocument(); const apiSelect = document.getElementById('new_prompt_api_type'); // Remove chatgpt_web // for (let i = 0; i < apiSelect.options.length; i++) { // if (apiSelect.options[i].value === 'chatgpt_web') { // apiSelect.remove(i); // break; // } // } apiSelect.addEventListener('change', () => { showConnectionOptions(apiSelect); }); showConnectionOptions(apiSelect); if(prefs.connection_type == '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') + ' [ChatGPT Web]'; } else { additionalInfoRow.style.display = 'none'; e.target.innerText = browser.i18n.getMessage('customPrompts_show_additional_info') + ' [ChatGPT Web]'; } }); }); 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); }); } // for the edit list items form [API] document.querySelectorAll('.api_additional_info_toggle').forEach(element => { element.addEventListener('click', (e) => { e.preventDefault(); let additionalInfoRow = element.nextElementSibling; if (additionalInfoRow.style.display === 'none' || additionalInfoRow.style.display === '') { additionalInfoRow.style.display = 'block'; element.innerText = browser.i18n.getMessage('customPrompts_hide_additional_info') + ' [API]'; } else { additionalInfoRow.style.display = 'none'; element.innerText = browser.i18n.getMessage('customPrompts_show_additional_info') + ' [API]'; } }); }); 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') + ' [ChatGPT Web]'; } } else { additionalInfoRow.style.display = 'none'; let subspan = chatgptWebAdditionalPropToggle.querySelector('td span'); if (subspan) { subspan.innerText = browser.i18n.getMessage('customPrompts_show_additional_info') + ' [ChatGPT Web]'; } } }); //To add a new item var txtIdNew = document.getElementById('txtIdNew'); var txtNameNew = document.getElementById('txtNameNew'); var txtTextNew = document.getElementById('txtTextNew'); var selectTypeNew = document.getElementById('selectTypeNew'); var selectActionNew = document.getElementById('selectActionNew'); var checkboxNeedSelectedNew = document.getElementById('checkboxNeedSelectedNew'); var checkboxNeedSignatureNew = document.getElementById('checkboxNeedSignatureNew'); 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") { checkboxUseDiffViewerNew.disabled = false; } else { checkboxUseDiffViewerNew.checked = false; checkboxUseDiffViewerNew.disabled = true; } }); const btnAddNew = document.getElementById('btnAddNew'); btnAddNew.addEventListener('click', (e) => { e.preventDefault(); if(!checkFields()) { return; } let newItemData = { id: String(txtIdNew.value.trim()).toLocaleLowerCase(), name: txtNameNew.value.trim(), text: txtTextNew.value.trim(), type: selectTypeNew.value, action: selectActionNew.value, need_selected: (checkboxNeedSelectedNew.checked) ? 1 : 0, need_signature: (checkboxNeedSignatureNew.checked) ? 1 : 0, need_custom_text: (checkboxNeedCustomTextNew.checked) ? 1 : 0, define_response_lang: (checkboxDefineResponseLangNew.checked) ? 1 : 0, use_diff_viewer: (checkboxUseDiffViewerNew.checked) ? 1 : 0, enabled: 1, position_compose: positionMax_compose + 1, position_display: positionMax_display + 1, is_default: 0, idnum: idnumMax + 1, api_type: document.getElementById('new_prompt_api_type').value, show_in: document.getElementById('selectShowInNew').value, }; 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; } const apiValues = getAPIValuesFromUI(); Object.assign(newItemData, apiValues); 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"]`); checkSelectedBoxes(checkboxes); let editBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnEditItem`); //console.log(`>>>>>>>>>>>> tr[data-idnum="${curr_idnum}"] button.btnEditItem`); editBtn.addEventListener('click', handleEditClick); let copyBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnCopyItem`); copyBtn.addEventListener('click', handleCopyClick); //console.log('>>>>>>>>>>>>> editBtn: ' + JSON.stringify(editBtn)); let deleteBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnDeleteItem`); //console.log(`>>>>>>>>>>>> tr[data-idnum="${curr_idnum}"] button.btnDeleteItem`); deleteBtn.addEventListener('click', handleDeleteClick); let okBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnConfirmItem`); okBtn.addEventListener('click', handleConfirmClick); let cancelBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnCancelItem`); cancelBtn.addEventListener('click', handleCancelClick); // console.log('>>>>>>>>>>>>> deleteBtn: ' + JSON.stringify(deleteBtn)); // console.log('>>>>>>>>>>>>> newItem: ' + JSON.stringify(newItem)); document.getElementById('btnNew').disabled = false; clearFields(); setSomethingChanged(); i18n.updateDocument(); window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); }); //Import Export const btnExportAll = document.getElementById('btnExportAll'); btnExportAll.addEventListener('click', (e) => { e.preventDefault(); exportPrompts(); }); async function exportPrompts() { const manifest = browser.runtime.getManifest(); const addonVersion = manifest.version; const include_api_settings = await showYesNoDialog(browser.i18n.getMessage("customPrompts_export_include_api_settings")); if (include_api_settings === null) return; const outputPrompts = preparePromptsForExport(await getPrompts(), include_api_settings); let outputObj = {id: 'thunderai-prompts', addon_version: addonVersion, prompts: outputPrompts}; const blob = new Blob([JSON.stringify(outputObj, null, 2)], { type: "application/json", }); const currentDate = new Date(); const time_stamp = `${currentDate.getFullYear()}${String(currentDate.getMonth() + 1).padStart(2, '0')}${String(currentDate.getDate()).padStart(2, '0')}${String(currentDate.getHours()).padStart(2, '0')}${String(currentDate.getMinutes()).padStart(2, '0')}${String(currentDate.getSeconds()).padStart(2, '0')}`; messenger.downloads.download({ url: URL.createObjectURL(blob), filename: `thunderai-prompts-${time_stamp}.json`, saveAs: true, }); } async function showYesNoDialog(message) { return new Promise((resolve) => { const dialog = document.createElement('dialog'); dialog.className = 'export'; // dialog.style.cssText = ` // padding: 20px; // border: none; // border-radius: 8px; // background-color: var(--dialog-bg-color, #fff); // color: var(--dialog-text-color, #000); // max-width: 400px; // box-shadow: 0 4px 12px rgba(0,0,0,0.15); // font-family: system-ui, -apple-system, sans-serif; // `; if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { dialog.style.backgroundColor = '#2e2e2e'; dialog.style.color = '#ffffff'; } const text = document.createElement('p'); text.textContent = message; text.style.marginBottom = '20px'; text.style.fontSize = '14px'; text.style.lineHeight = '1.5'; dialog.appendChild(text); const btnContainer = document.createElement('div'); btnContainer.style.display = 'flex'; btnContainer.style.justifyContent = 'flex-end'; btnContainer.style.gap = '10px'; const createBtn = (text, bgColor) => { const btn = document.createElement('button'); btn.textContent = text; btn.style.padding = '8px 16px'; btn.style.borderRadius = '4px'; btn.style.border = 'none'; btn.style.cursor = 'pointer'; btn.style.fontSize = '14px'; btn.style.color = 'white'; btn.style.backgroundColor = bgColor; return btn; }; const cancelBtn = createBtn(browser.i18n.getMessage("customPrompts_btnCancel"), '#6c757d'); cancelBtn.onclick = () => { dialog.close(); dialog.remove(); resolve(null); }; const noBtn = createBtn(browser.i18n.getMessage("no_string"), '#007bff'); noBtn.onclick = () => { dialog.close(); dialog.remove(); resolve(false); }; const yesBtn = createBtn(browser.i18n.getMessage("yes_string"), '#6c757d'); yesBtn.onclick = () => { dialog.close(); dialog.remove(); resolve(true); }; btnContainer.appendChild(cancelBtn); btnContainer.appendChild(noBtn); btnContainer.appendChild(yesBtn); dialog.appendChild(btnContainer); document.body.appendChild(dialog); dialog.showModal(); }); } const btnImport = document.getElementById('btnImport'); btnImport.addEventListener('click', (e) => { e.preventDefault(); importPrompts(); }); function importPrompts() { if(confirm(browser.i18n.getMessage("importPrompts_confirmText") + '\n' + browser.i18n.getMessage("customPrompts_managePrompts_info_default_2") + '\n' + browser.i18n.getMessage("customPrompts_managePrompts_info_default_3"))) { //ask the user to choose a JSON file, and then read it, check if the serialized JSON is valid as generated from exportPrompts(), and if so, add it to the list const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'; input.click(); input.onchange = async () => { setMessage(browser.i18n.getMessage('customPrompts_start_import')); const file = input.files[0]; const reader = new FileReader(); reader.onload = async () => { const json = reader.result; try { const obj = JSON.parse(json); if(obj.id !== 'thunderai-prompts') { alert(browser.i18n.getMessage("importPrompts_invalidFile")); setMessage(browser.i18n.getMessage('importPrompts_invalidFile'),'red'); return; } // if(obj.addon_version !== manifest.version) { // alert(browser.i18n.getMessage("importPrompts_invalidVersion")); // return; // } if(!Array.isArray(obj.prompts)) { alert(browser.i18n.getMessage("importPrompts_invalidPrompts")); setMessage(browser.i18n.getMessage('customPrompts_invalidPrompts'),'red'); return; } //setCustomPrompts(obj.prompts); promptsList.clear(); loadPromptsList(await preparePromptsForImport(obj.prompts)); setSomethingChanged(); i18n.updateDocument(); // browser.runtime.sendMessage({command: "reload_menus"}); setMessage(browser.i18n.getMessage('customPrompts_import_completed'), 'orange'); // msgTimeout = setTimeout(() => { // clearMessage(); // }, 10000); } catch(err) { alert(browser.i18n.getMessage("importPrompts_invalidFile") + ' ' + err); setMessage(browser.i18n.getMessage('importPrompts_invalidFile'),'red'); return; } }; reader.readAsText(file); }; }; } document.querySelectorAll('.chatgpt_web_additional_info_show').forEach(element => { toggleAdditionalPropertiesShow(element.closest('tr')); }); document.querySelectorAll('.api_additional_info_show').forEach(element => { toggleApiPropertiesShow(element.closest('tr')); }); getChatGPTWebModelsList_HTML(ChatGPTWeb_models, 'chatgpt_web_models_list'); let formNewWebModelList = document.getElementById('chatgpt_web_models_list'); formNewWebModelList.querySelectorAll('.conntype_chatgpt_web_option').forEach(element => { element.addEventListener("click", () => { let el = document.getElementById("chatGPTWebModelNew"); el.value = element.textContent; el.dispatchEvent(new Event('change'), { bubbles: true }); }); }); document.querySelectorAll('.id_output').forEach(element => { getChatGPTWebModelsList_HTML(ChatGPTWeb_models, 'chatgpt_web_models_list_' + element.value); let formWebModelList = document.getElementById('chatgpt_web_models_list_' + element.value); formWebModelList.querySelectorAll('.conntype_chatgpt_web_option').forEach(element2 => { element2.addEventListener("click", () => { let el = document.getElementById("chatgpt_web_model_output_" + element.value); el.value = element2.textContent; el.dispatchEvent(new Event('change'), { bubbles: true }); }); }); }); }, { once: true }); document.getElementById('btnManageCustomDataPH').addEventListener('click', () => { openTab('/pages/customdataplaceholders/mzta-custom-dataplaceholders.html'); }); //========= handling an item in a row function handleEditClick(e) { e.preventDefault(); const tr = e.target.parentNode.parentNode; const id = tr.querySelector('.id_output').value.toLowerCase(); // Inject Connection UI if needed const anchorId = `api_ui_anchor_${id}`; const selectId = `api_type_${id}`; const prefix = `prompt_${id}_`; if (!document.getElementById(selectId)) { injectConnectionUI({ afterTrId: anchorId, selectId: selectId, modelId_prefix: prefix, no_chatgpt_web: true, taLog: taLog, customButtonLabel: browser.i18n.getMessage("Reset"), customButtonCallback: () => { resetApiSettings(selectId, id); } }).then(() => { populateConnectionUI(tr, id, prefix, selectId); updateWarnings(prefix); }); } else { populateConnectionUI(tr, id, prefix, selectId); updateWarnings(prefix); } // Show/Hide buttons //console.log('>>>>>>>> tr: ' + tr.getAttribute('data-idnum')); e.target.style.display = 'none'; // Edit btn tr.querySelector('.btnConfirmItem').style.display = 'inline'; // Save btn tr.querySelector('.btnCancelItem').style.display = 'inline'; // Cancel btn // tr.querySelector('.btnEditItem').style.display = 'none'; // Edit btn tr.querySelector('.btnCopyItem').style.display = 'none'; // Copy btn tr.querySelector('.btnDeleteItem').style.display = 'none'; // Delete btn showItemRowEditor(tr); toggleDiffviewer(e); toggleAdditionalPropertiesShow(tr); } function resetApiSettings(selectId, id = null) { let prefix = ''; if (id) prefix = `prompt_${id}_`; const selectEl = document.getElementById(selectId); if (selectEl) { selectEl.value = ''; selectEl.dispatchEvent(new Event('change')); } // Clear UI inputs for (const [integration, options] of Object.entries(integration_options_config)) { for (const key of Object.keys(options)) { const propName = `${integration}_${key}`; const inputId = `${prefix}${propName}`; const inputEl = document.getElementById(inputId); if (inputEl) { if (inputEl.type === 'checkbox') { inputEl.checked = false; } else { inputEl.value = ''; } } } } // Update promptsList const item = promptsList.get('id', id)[0]; if (item) { let newValues = item.values(); newValues.api_type = ''; for (const [integration, options] of Object.entries(integration_options_config)) { for (const key of Object.keys(options)) { const propName = `${integration}_${key}`; newValues[propName] = ''; } } item.values(newValues); } setSomethingChanged(); } function populateConnectionUI(tr, id, prefix, selectId) { const item = promptsList.get('id', id)[0]; const itemValues = item.values(); const selectEl = document.getElementById(selectId); if (selectEl) { selectEl.value = itemValues.api_type || ''; showConnectionOptions(selectEl); } for (const [integration, options] of Object.entries(integration_options_config)) { for (const key of Object.keys(options)) { const propName = `${integration}_${key}`; const inputId = `${prefix}${propName}`; const inputEl = document.getElementById(inputId); if (inputEl) { let val = itemValues[propName]; // Use default if undefined or empty string (for text inputs) if (val === undefined || (inputEl.type !== 'checkbox' && val === '')) { if (prefs[propName] !== undefined) { val = prefs[propName]; } } if (inputEl.type === 'checkbox') { inputEl.checked = (val === true || val === 'true'); } else { if (inputEl.tomselect) { const restoreValue = val || ''; let optionExists = Array.from(inputEl.options).some(opt => opt.value === restoreValue); if (!optionExists && restoreValue !== '') { let newOption = new Option(restoreValue, restoreValue); inputEl.add(newOption); } inputEl.value = restoreValue; inputEl.tomselect.sync(); inputEl.tomselect.setValue(restoreValue, true); setTomSelectBorder(inputEl.tomselect); } else { inputEl.value = val || ''; } } } } } i18n.updateDocument(); } function showItemRowEditor(tr) { tr.querySelector('.id_output').style.display = 'inline'; tr.querySelector('.id_show').style.display = 'none'; tr.querySelector('.name_output').style.display = 'inline'; tr.querySelector('.name_show').style.display = 'none'; const text_output = tr.querySelector('.text_output'); 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('.api_additional_info_show').style.display = 'none'; tr.querySelector('.type_output').style.display = 'inline'; tr.querySelector('.type_show').style.display = 'none'; tr.querySelector('.show_in_output').style.display = 'inline'; tr.querySelector('.show_in_show').style.display = 'none'; const action_output = tr.querySelector('.action_output') action_output.style.display = 'inline'; action_output.addEventListener('change', toggleDiffviewer); tr.querySelector('.action_show').style.display = 'none'; tr.querySelector('input.need_selected').disabled = false; tr.querySelector('input.need_signature').disabled = false; tr.querySelector('input.need_custom_text').disabled = false; tr.querySelector('input.define_response_lang').disabled = false; tr.querySelector('input.use_diff_viewer').disabled = false; } function hideItemRowEditor(tr) { tr.querySelector('.id_output').style.display = 'none'; tr.querySelector('.id_show').style.display = 'inline'; tr.querySelector('.name_output').style.display = 'none'; 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'; tr.querySelector('.api_additional_info_toggle').style.display = 'none'; tr.querySelector('.api_additional_info').style.display = 'none'; toggleAdditionalPropertiesShow(tr); tr.querySelector('.type_output').style.display = 'none'; tr.querySelector('.type_show').style.display = 'inline'; tr.querySelector('.show_in_output').style.display = 'none'; tr.querySelector('.show_in_show').style.display = 'inline'; const action_output = tr.querySelector('.action_output') action_output.style.display = 'none'; action_output.addEventListener('change', toggleDiffviewer); tr.querySelector('.action_show').style.display = 'inline'; tr.querySelector('input.need_selected').disabled = true; tr.querySelector('input.need_signature').disabled = true; tr.querySelector('input.need_custom_text').disabled = true; tr.querySelector('input.define_response_lang').disabled = true; tr.querySelector('input.use_diff_viewer').disabled = true; } function toggleAdditionalPropertiesShow(tr) { // console.log(">>>>>>>>>>>>>>>>> toggleAdditionalPropertiesShow tr.querySelector('.api_type_show').innerText: " + tr.querySelector('.api_type_show').innerText); 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(prefs.connection_type == 'chatgpt_web' && tr.querySelector('.api_type_show').innerText == '') { 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'; } }else{ element.style.display = 'none'; chatGPTWebModel_show.parentNode.style.display = 'none'; chatGPTWebProject_show.parentNode.style.display = 'none'; chatGPTWebCustomGPT_show.parentNode.style.display = 'none'; } } function toggleApiPropertiesShow(tr) { let element = tr.querySelector('.api_additional_info_show'); let api_type_show = tr.querySelector('.api_type_show'); if (api_type_show.innerText !== '' && api_type_show.innerText !== 'undefined') { element.style.display = 'flex'; } else { element.style.display = 'none'; } if(api_type_show.innerText === '' || api_type_show.innerText === 'undefined') { api_type_show.parentNode.style.display = 'none'; } else { api_type_show.parentNode.style.display = 'inline'; } } function toggleAdditionalPropertiesEditor(tr) { if(prefs.connection_type == 'chatgpt_web' && tr.querySelector('.api_type_show').innerText == '') { 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(); } } let api_info_toggle = tr.querySelector('.api_additional_info_toggle'); api_info_toggle.style.display = 'block'; let api_type_show = tr.querySelector('.api_type_show').innerText; if (api_type_show !== '' && api_type_show !== 'undefined') { api_info_toggle.click(); } } function toggleDiffviewer(e) { e.preventDefault(); const tr = e.target.parentNode.parentNode; const action = tr.querySelector('.action_output').value; const checkbox = tr.querySelector('.use_diff_viewer'); if (action === "2") { checkbox.disabled = false; } else { checkbox.checked = false; checkbox.setAttribute('checked_val', '0'); checkbox.disabled = true; } //console.log('>>>>>>>> tr: ' + tr.getAttribute('data-idnum')); //console.log('>>>>>>>> action: ' + action); //console.log('>>>>>>>> checkbox: ' + checkbox.checked); //console.log('>>>>>>>> checkbox: ' + checkbox.style.display); } // Confirm and log deletion action function handleDeleteClick(e) { e.preventDefault(); const checkConfirm = window.confirm(browser.i18n.getMessage("customPrompts_btnDelete_confirmText")); if (!checkConfirm) { return; } const tr = e.target.parentNode.parentNode; //console.log('>>>>>>>> tr: ' + tr.getAttribute('data-idnum')); promptsList.remove("id", tr.querySelector('span.id').innerText); setSomethingChanged(); } function handleCancelClick(e) { e.preventDefault(); const tr = e.target.parentNode.parentNode; e.target.style.display = 'none'; // Cancel btn tr.querySelector('.btnConfirmItem').style.display = 'none'; // Save btn // tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn tr.querySelector('.btnCopyItem').style.display = 'inline'; // Copy btn tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn tr.querySelector('.id_output').value = tr.querySelector('.id_show').innerText.toLocaleUpperCase(); tr.querySelector('.name_output').value = tr.querySelector('.name_show').innerText; tr.querySelector('.text_output').value = sanitizeHtml(tr.querySelector('.text_show').innerHTML).replace(//gi, "\n"); tr.querySelector('.type_output').value = tr.querySelector('.type').innerText; // tr.querySelector('.type_output').selectedOptions[0].text = tr.querySelector('.type_show').innerText; tr.querySelector('.show_in_output').value = tr.querySelector('.show_in').innerText || 'popup'; 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; tr.querySelector('.api_additional_info_toggle').innerText = browser.i18n.getMessage('customPrompts_show_additional_info') + ' [API]'; toggleApiPropertiesShow(tr); hideItemRowEditor(tr); } function handleConfirmClick(e) { e.preventDefault(); const tr = e.target.parentNode.parentNode; e.target.style.display = 'none'; // Ok btn const oldId = tr.querySelector('.id_show').innerText; const prefix = `prompt_${oldId}_`; const selectId = `api_type_${oldId}`; let newValues = {}; // Standard fields newValues.id = tr.querySelector('.id_output').value.trim().toLowerCase(); newValues.name = tr.querySelector('.name_output').value.trim(); newValues.text = tr.querySelector('.text_output').value; newValues.type = tr.querySelector('.type_output').value; newValues.show_in = tr.querySelector('.show_in_output').value; newValues.action = tr.querySelector('.action_output').value; newValues.need_selected = tr.querySelector('.need_selected').checked ? 1 : 0; newValues.need_signature = tr.querySelector('.need_signature').checked ? 1 : 0; newValues.need_custom_text = tr.querySelector('.need_custom_text').checked ? 1 : 0; newValues.define_response_lang = tr.querySelector('.define_response_lang').checked ? 1 : 0; newValues.use_diff_viewer = tr.querySelector('.use_diff_viewer').checked ? 1 : 0; newValues.enabled = tr.querySelector('.enabled').checked ? 1 : 0; newValues.chatgpt_web_model = tr.querySelector('.chatgpt_web_model_output').value.trim(); newValues.chatgpt_web_project = tr.querySelector('.chatgpt_web_project_output').value.trim(); newValues.chatgpt_web_custom_gpt = tr.querySelector('.chatgpt_web_custom_gpt_output').value.trim(); const selectEl = document.getElementById(selectId); if(selectEl) newValues.api_type = selectEl.value; const apiValues = getAPIValuesFromUI(prefix); Object.assign(newValues, apiValues); promptsList.get('id', oldId)[0].values(newValues); // tr.querySelector('.btnConfirmItem').style.display = 'none'; // Ok btn tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn tr.querySelector('.btnCopyItem').style.display = 'inline'; // Copy btn tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn // Update item data tr.querySelector('.type').innerText = tr.querySelector('.type_output').value; tr.querySelector('.type_show').innerText = tr.querySelector('.type_output').selectedOptions[0].text; tr.querySelector('.show_in').innerText = tr.querySelector('.show_in_output').value; tr.querySelector('.show_in_show').innerText = tr.querySelector('.show_in_output').selectedOptions[0].text; tr.querySelector('.action').innerText = tr.querySelector('.action_output').value; tr.querySelector('.action_show').innerText = tr.querySelector('.action_output').selectedOptions[0].text; if (newValues.api_type !== '') { tr.querySelector('.api_type_show').innerText = newValues.api_type; toggleApiPropertiesShow(tr); } // the checkboxes update is handled directly by themselves hideItemRowEditor(tr); setSomethingChanged(); } // Handle checkbox changes and log new state async function handleCheckboxChange(e) { e.preventDefault(); e.target.setAttribute('checked_val', e.target.checked ? '1' : '0'); if (e.target.classList.contains('enabled') || e.target.classList.contains('need_custom_text')) { let tr = e.target.closest('tr'); if (tr) { let idnum = tr.getAttribute('data-idnum'); let item = promptsList.get('idnum', idnum); if (item && item.length > 0) { if (e.target.classList.contains('enabled')) { item[0]._values.enabled = e.target.checked ? 1 : 0; } if (e.target.classList.contains('need_custom_text')) { item[0]._values.need_custom_text = e.target.checked ? 1 : 0; } } } } //console.log('>>>>>>>> checked_val: ' + e.target.getAttribute('checked_val')); if (e.target.classList.contains('need_selected') || e.target.classList.contains('need_custom_text') || e.target.classList.contains('need_selected_new') || e.target.classList.contains('need_custom_text_new')) { let textarea = e.target.closest('tr').querySelector('.text_output'); await checkPromptsConfigForPlaceholders(textarea); } } // Enable save button on input change function handleInputChange(e) { e.preventDefault(); setSomethingChanged(); } function handleCopyClick(e) { e.preventDefault(); const tr = e.target.parentNode.parentNode; let id = tr.querySelector('.id_output').value; let name = tr.querySelector('.name_output').value; let text = tr.querySelector('.text_output').value; let type = tr.querySelector('.type_output').value; let action = tr.querySelector('.action_output').value; let need_selected = tr.querySelector('.need_selected').checked; let need_signature = tr.querySelector('.need_signature').checked; let need_custom_text = tr.querySelector('.need_custom_text').checked; let define_response_lang = tr.querySelector('.define_response_lang').checked; let use_diff_viewer = tr.querySelector('.use_diff_viewer').checked; let chatgpt_web_model = tr.querySelector('.chatgpt_web_model_output').value; let chatgpt_web_project = tr.querySelector('.chatgpt_web_project_output').value; let chatgpt_web_custom_gpt = tr.querySelector('.chatgpt_web_custom_gpt_output').value; const item = promptsList.get('id', id.toLowerCase())[0]; const itemValues = item.values(); // Populate new form document.getElementById('txtIdNew').value = id + '_' + browser.i18n.getMessage("copy_text"); document.getElementById('txtNameNew').value = name + ' (' + browser.i18n.getMessage("copy_text") + ')'; document.getElementById('txtTextNew').value = text; document.getElementById('selectTypeNew').value = type; document.getElementById('selectShowInNew').value = tr.querySelector('.show_in_output').value || 'popup'; document.getElementById('selectActionNew').value = action; document.getElementById('checkboxNeedSelectedNew').checked = need_selected; document.getElementById('checkboxNeedSignatureNew').checked = need_signature; document.getElementById('checkboxNeedCustomTextNew').checked = need_custom_text; document.getElementById('checkboxDefineResponseLangNew').checked = define_response_lang; let checkboxUseDiffViewerNew = document.getElementById('checkboxUseDiffViewerNew'); checkboxUseDiffViewerNew.checked = use_diff_viewer; checkboxUseDiffViewerNew.disabled = (action !== "2"); document.getElementById('chatGPTWebModelNew').value = chatgpt_web_model; document.getElementById('chatGPTWebProjectNew').value = chatgpt_web_project; document.getElementById('chatGPTWebCustomGPTNew').value = chatgpt_web_custom_gpt; const apiSelect = document.getElementById('new_prompt_api_type'); if (apiSelect) { apiSelect.value = itemValues.api_type || ''; apiSelect.dispatchEvent(new Event('change')); for (const [integration, options] of Object.entries(integration_options_config)) { for (const key of Object.keys(options)) { const propName = `${integration}_${key}`; const inputEl = document.getElementById(propName); if (inputEl) { let val = itemValues[propName]; if (val === undefined) val = ''; if (inputEl.type === 'checkbox') { inputEl.checked = (val === true || val === 'true'); } else { if (inputEl.tomselect) { inputEl.tomselect.setValue(val, true); setTomSelectBorder(inputEl.tomselect); } else { inputEl.value = val; } } } } } } // Show form document.getElementById('formNew').style.display = 'block'; document.getElementById('btnNew').disabled = true; // Scroll to top window.scrollTo({ top: 0, behavior: 'smooth' }); checkFields(); } //========= handling an item in a row - END function loadPromptsList(values){ // console.log('>>>>>>>> loadPromptsList values: ' + JSON.stringify(values)); let api_fields = []; for (const [integration, options] of Object.entries(integration_options_config)) { for (const key of Object.keys(options)) { api_fields.push(`${integration}_${key}`); } } let options = { valueNames: [ { data: ['idnum'] }, 'is_default', 'id', 'name', 'text', 'type', 'action', 'position_compose', 'position_display', 'show_in', { name: 'need_selected', attr: 'checked_val'}, { name: 'need_signature', attr: 'checked_val'}, { name: 'need_custom_text', attr: 'checked_val'}, { name: 'define_response_lang', attr: 'checked_val'}, { name: 'use_diff_viewer', attr: 'checked_val'}, { name: 'enabled', attr: 'checked_val'}, 'api_type', ...api_fields ], item: function(values) { let type_output = ''; switch(String(values.type)){ case "0": type_output = `__MSG_customPrompts_add_to_menu_always__`; break; case "1": type_output = `__MSG_customPrompts_add_to_menu_reading__`; break; case "2": type_output = `__MSG_customPrompts_add_to_menu_composing__`; break; } let action_output = ''; switch(String(values.action)){ case "0": action_output = `__MSG_customPrompts_close_button__`; break; case "1": action_output = `__MSG_customPrompts_do_reply__`; break; case "2": action_output = `__MSG_customPrompts_substitute_text__`; break; } let show_in_output = ''; switch(String(values.show_in || 'popup')){ case "popup": show_in_output = `__MSG_show_in_popup__`; break; case "context": show_in_output = `__MSG_show_in_context__`; break; case "both": show_in_output = `__MSG_show_in_both__`; break; } let output = `
__MSG_customPrompts_show_additional_info__ [ChatGPT Web]
__MSG_prefs_OptionText_chatgpt_web_model__:


__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_show_additional_info__ [API]
__MSG_customPrompts_add_to_menu__:
` + type_output + ` ` + `

__MSG_show_in__:
` + show_in_output + ` ` + `

__MSG_customPrompts_form_label_Action__:
` + action_output + ` ` + `




__MSG_customPrompts_show_additional_info_show__ [ChatGPT Web]
__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 + `
__MSG_prefs_Connection_type__:
` + values.api_type + `




`; //console.log('>>>>>>>> values.name: ' + JSON.stringify(values.name)); positionMax_compose = Math.max(positionMax_compose, values.position_compose); positionMax_display = Math.max(positionMax_display, values.position_display); idnumMax = Math.max(idnumMax, values.idnum); return output; } }; 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(); let btnEditItem_elements = document.querySelectorAll(".btnEditItem"); btnEditItem_elements.forEach(element => { element.addEventListener('click', handleEditClick); }); let btnCopyItem_elements = document.querySelectorAll(".btnCopyItem"); btnCopyItem_elements.forEach(element => { element.addEventListener('click', handleCopyClick); }); let btnDeleteItem_elements = document.querySelectorAll(".btnDeleteItem"); btnDeleteItem_elements.forEach(element => { element.addEventListener('click', handleDeleteClick); }); let btnCancelItem_elements = document.querySelectorAll(".btnCancelItem"); btnCancelItem_elements.forEach(element => { element.addEventListener('click', handleCancelClick); }); let btnConfirmItem_elements = document.querySelectorAll(".btnConfirmItem"); btnConfirmItem_elements.forEach(element => { element.addEventListener('click', handleConfirmClick); }); let checkbox_elements = document.querySelectorAll("input[type='checkbox']"); checkbox_elements.forEach(element => { element.addEventListener('change', handleCheckboxChange); }); document.querySelectorAll('.input_mod').forEach(element => { element.addEventListener('change', handleInputChange); }); } function checkFields() { //console.log('>>>>>>>>>>>>> typeof promptsList: ' + typeof promptsList); //console.log('>>>>>>>>>>>>> Array.isArray(promptsList): ' + Array.isArray(promptsList)); // the id must be unique and without spaces let is_error = false; let id_value = document.getElementById('txtIdNew').value.trim(); if ((id_value == '')|| (/\s/.test(id_value))) { inputSetError('txtIdNew'); is_error = true; } else { let exists = promptsList.get("id", id_value); //console.log('>>>>>>>>>>>>> exists: ' + JSON.stringify(exists)); if(exists && exists.length > 0) { inputSetError('txtIdNew'); is_error = true; } else { inputClearError('txtIdNew'); } } if (document.getElementById('txtNameNew').value.trim() == '') { inputSetError('txtNameNew'); is_error = true; } else { inputClearError('txtNameNew'); } if (document.getElementById('txtTextNew').value.trim() == '') { inputSetError('txtTextNew'); is_error = true; } else { inputClearError('txtTextNew'); } document.getElementById('btnAddNew').disabled = is_error; return !is_error; } 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('selectShowInNew').value = 'popup'; document.getElementById('selectActionNew').value = '0'; document.getElementById('checkboxNeedSelectedNew').value = '0'; document.getElementById('checkboxNeedSignatureNew').value = '0'; document.getElementById('checkboxNeedCustomTextNew').value = '0'; document.getElementById('formNew').style.display = 'none'; } function getAPIValuesFromUI(prefix = '') { let values = {}; for (const [integration, options] of Object.entries(integration_options_config)) { for (const key of Object.keys(options)) { const propName = `${integration}_${key}`; const inputId = `${prefix}${propName}`; const inputEl = document.getElementById(inputId); if (inputEl) { values[propName] = (inputEl.type === 'checkbox') ? inputEl.checked : inputEl.value; } } } return values; } function inputSetError(input) { document.getElementById(input).style.borderColor = 'red'; } function inputClearError(input) { document.getElementById(input).style.borderColor = 'green'; } function setSomethingChanged(){ clearTimeout(msgTimeout); somethingChanged = true; document.getElementById('btnSaveAll').disabled = false; let msgDisplay = document.getElementById('msgDisplay'); msgDisplay.textContent = browser.i18n.getMessage('customPrompts_unsaved_changes'); msgDisplay.style.display = 'inline'; msgDisplay.style.color = 'red'; } function setNothingChanged(){ somethingChanged = false; document.getElementById('btnSaveAll').disabled = true; let msgDisplay = document.getElementById('msgDisplay'); msgDisplay.disabled = true; msgDisplay.textContent = '' msgDisplay.style.display = 'none'; msgDisplay.style.color = ''; } function checkSelectedBoxes(checkboxes = null) { if(checkboxes == null){ checkboxes = [ ...document.querySelectorAll('.need_selected[type="checkbox"]'), ...document.querySelectorAll('.need_signature[type="checkbox"]'), ...document.querySelectorAll('.need_custom_text[type="checkbox"]'), ...document.querySelectorAll('.define_response_lang[type="checkbox"]'), ...document.querySelectorAll('.use_diff_viewer[type="checkbox"]'), ...document.querySelectorAll('.enabled[type="checkbox"]'), ]; } // Iterate through the checkboxes checkboxes.forEach(checkbox => { // Check if the 'checked' attribute is "0" if (checkbox.getAttribute('checked_val') == "0") { // Uncheck the checkbox checkbox.checked = false; } else { checkbox.checked = true; } }); } //Save all prompts async function saveAll() { setMessage(browser.i18n.getMessage('customPrompts_start_saving')); setNothingChanged(); if(promptsList != null) { 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)); // newPrompts.forEach(prompt => { // console.log('>>>>>>>>>>>>> id: ' + JSON.stringify(prompt)); // }); //console.log('>>>>>>>>>>>>> saveAll: ' + JSON.stringify(newPrompts)); setMessage(browser.i18n.getMessage('customPrompts_filtering_prompts')); let newDefaultPrompts = newPrompts.filter(item => item.is_default == 1); //console.log('>>>>>>>>>>>>> newDefaultPrompts: ' + JSON.stringify(newDefaultPrompts)); let newCustomPrompts = newPrompts.filter(item => item.is_default == 0); setMessage(browser.i18n.getMessage('customPrompts_saving_default_prompts')); await setDefaultPromptsProperties(newDefaultPrompts); setMessage(browser.i18n.getMessage('customPrompts_saving_custom_prompts')); await setCustomPrompts(newCustomPrompts); setMessage(browser.i18n.getMessage('customPrompts_reloading_menus')); await browser.runtime.sendMessage({command: "reload_menus"}); setMessage(browser.i18n.getMessage('customPrompts_saved'),'green'); msgTimeout = setTimeout(() => { clearMessage(); }, 10000) } setStorageSpace(); } function setMessage(msg, color = '') { clearTimeout(msgTimeout); let msgDisplay = document.getElementById('msgDisplay'); msgDisplay.textContent = msg; msgDisplay.style.display = 'inline'; msgDisplay.style.color = color; } function clearMessage() { let msgDisplay = document.getElementById('msgDisplay'); msgDisplay.textContent = ''; msgDisplay.style.display = 'none'; msgDisplay.style.color = ''; } async function setStorageSpace() { let storage_space = await getLocalStorageUsedSpace(); document.getElementById('storage_space').textContent = storage_space; } window.addEventListener('beforeunload', function (event) { if (somethingChanged) { event.preventDefault(); } }); async function checkPromptsConfigForPlaceholders(textarea){ let curr_text = textarea.value; // First substitute the custom data placeholders curr_text = await placeholdersUtils.replaceCustomPlaceholders(curr_text); // console.log('>>>>>>>>>> curr_text after custom placeholders: ' + curr_text); // check additional_text and selected_text placeholders presence and the corrispondent checkboxes let tr_ancestor = textarea.closest('tr'); let need_custom_text_element = tr_ancestor.querySelector('.need_custom_text') || tr_ancestor.querySelector('.need_custom_text_new'); if(/{%\s*additional_text(?::.*?)?\s*%}/.test(String(curr_text))){ if(!need_custom_text_element.checked){ need_custom_text_element.closest('.need_custom_text_span').style.border = '2px solid red'; }else{ need_custom_text_element.closest('.need_custom_text_span').style.border = ''; } }else{ need_custom_text_element.closest('.need_custom_text_span').style.border = ''; } let tr_ancestor2 = textarea.closest('tr'); let selected_text_element = tr_ancestor2.querySelector('.need_selected') || tr_ancestor2.querySelector('.need_selected_new'); if((String(curr_text).indexOf('{%selected_text%}') != -1)||(String(curr_text).indexOf('{%selected_html%}') != -1)){ if(!selected_text_element.checked){ selected_text_element.closest('.need_selected_span').style.border = '2px solid red'; }else{ selected_text_element.closest('.need_selected_span').style.border = ''; } }else{ selected_text_element.closest('.need_selected_span').style.border = ''; } }