spamfilter settings page updated. see #438

This commit is contained in:
Mic 2025-09-07 20:00:00 +02:00
parent 6cb2cffd27
commit 124b31c830
4 changed files with 125 additions and 11 deletions

View file

@ -1151,11 +1151,11 @@
"message": "If checked, the AI will only add tags to emails received in the inbox folder.",
"description": ""
},
"prefs_OptionText_add_tags_use_specific_integration": {
"prefs_OptionText_use_specific_integration": {
"message": "Use specific Model and API",
"description": ""
},
"prefs_OptionText_add_tags_use_specific_integration_Info": {
"prefs_OptionText_use_specific_integration_Info": {
"message": "If checked, the Model and API specified below will be used for adding tags to emails, regardless the one choosen in the ThunderAI options page.",
"description": ""
},
@ -1211,6 +1211,14 @@
"message": "Spam Filter Options",
"description": ""
},
"prefs_OptionText_spamfilter_use_specific_integration": {
"message": "Use specific Model and API",
"description": ""
},
"prefs_OptionText_spamfilter_use_specific_integration_Info": {
"message": "If checked, the Model and API specified below will be used for the spam filter, regardless the one chosen in the ThunderAI options page.",
"description": ""
},
"prefs_OptionText_spamfilter_threshold": {
"message": "Spam threshold",
"description": ""
@ -1665,4 +1673,4 @@
"message": "To use this feature, you need an API integration rather than the ChatGPT Web Integration. You can define a specific API in the feature settings page by first checking the checkbox above and then clicking the button on the left.",
"description": ""
}
}
}

View file

@ -82,10 +82,10 @@ export const prefs_default = {
spamfilter_context_menu: true,
spamfilter_enabled_accounts: [],
spamfilter_use_specific_integration: false,
spamfilter_connection_type: '',
spamfilter_connection_type: 'chatgpt_api',
spamfilter_chatgpt_model: '',
spamfilter_ollama_model: '',
spamfilter_openai_comp_model: '',
spamfilter_google_gemini_model: '',
spamfilter_anthropic_model: '',
}
}

View file

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<title>ThunderAI - __MSG_SpamFilter_PageTitle__</title>
<link rel="stylesheet" href="mzta-spamfilter.css">
<link rel="stylesheet" href="../_lib/connection-ui.css">
<link rel="icon" href="../../images/icon-16px.png">
</head>
<body>
@ -13,6 +14,18 @@
</div>
<div class="spamfilter_table_title section_title">__MSG_SpamFilter_prompt_prefs_title__</div>
<table id="miczPrefs">
<tr class="spamfilter_tr specific_integration">
<td><span>__MSG_prefs_OptionText_use_specific_integration__</span>
</td>
<td>
<label>
<input type="checkbox" id="spamfilter_use_specific_integration" name="spamfilter_use_specific_integration" class="option-input" />
__MSG_prefs_OptionText_spamfilter_use_specific_integration_Info__
</label>
</td>
</tr>
<tr id="connection_ui_anchor"></tr>
<tr id="connection_ui_end"><td colspan="2"></td></tr>
<tr class="spamfilter_tr">
<td><span>__MSG_prefs_OptionText_spamfilter_threshold__</span></td>
<td>
@ -74,4 +87,4 @@
<script src="mzta-spamfilter.js" type="module"></script>
<script src="../../js/mzta-i18n.js"></script>
</body>
</html>
</html>

View file

@ -18,18 +18,39 @@
import { prefs_default } from '../../options/mzta-options-default.js';
import { taLogger } from '../../js/mzta-logger.js';
import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js";
import { getSpecialPrompts, setSpecialPrompts, loadPrompt, savePrompt, clearPromptAPI } from "../../js/mzta-prompts.js";
import { getPlaceholders } from "../../js/mzta-placeholders.js";
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
import { taSpamReport } from '../../js/mzta-spamreport.js';
import { getAccountsList, isAPIKeyValue } from "../../js/mzta-utils.js";
import {
injectConnectionUI,
updateWarnings,
changeConnTypeRowColor
} from "../_lib/connection-ui.js";
let autocompleteSuggestions = [];
let taLog = new taLogger("mzta-spamfilter-page",true);
taSpamReport.logger = taLog;
let conntype_select_id = 'spamfilter_connection_type';
let model_prefix = 'spamfilter_';
document.addEventListener('DOMContentLoaded', async () => {
try {
await injectConnectionUI({
afterTrId: 'connection_ui_anchor',
tr_class: 'specific_integration_sub',
selectId: conntype_select_id,
modelId_prefix: model_prefix,
no_chatgpt_web: true,
taLog: taLog
});
} catch (e) {
console.error('Failed to inject connection UI (spamfilter)', e);
}
i18n.updateDocument();
await restoreOptions();
@ -40,6 +61,48 @@ document.addEventListener('DOMContentLoaded', async () => {
document.getElementById("spamfilter_threshold").addEventListener("input", check_spamfilter_threshold);
check_spamfilter_threshold({target: document.getElementById("spamfilter_threshold")});
// Bind prompt API updates to connection type and model selects
document.querySelectorAll(".option-input-model").forEach(element => {
element.addEventListener("change", updatePromptAPIInfo);
});
const conntype_el = document.getElementById(conntype_select_id);
if (conntype_el) {
conntype_el.addEventListener('change', updatePromptAPIInfo);
const conntype_row = document.getElementById(conntype_select_id + '_tr');
if (conntype_row) changeConnTypeRowColor(conntype_row, conntype_el);
}
// Specific integration toggle behavior
const spamfilter_use_specific_integration_el = document.getElementById('spamfilter_use_specific_integration');
let prefs_spamfilter_init = await browser.storage.sync.get({ spamfilter_enabled_accounts: [], connection_type: 'chatgpt_web' });
if(prefs_spamfilter_init.connection_type == 'chatgpt_web'){
spamfilter_use_specific_integration_el.checked = true;
spamfilter_use_specific_integration_el.dispatchEvent(new Event('change'));
spamfilter_use_specific_integration_el.disabled = true;
}
const conntype_end_el = document.getElementById('connection_ui_end');
const conntype_row = document.getElementById(conntype_select_id + '_tr');
spamfilter_use_specific_integration_el.addEventListener('change', async (event) => {
document.querySelectorAll('.specific_integration_sub').forEach(tr => {
tr.style.display = event.target.checked && tr.classList.contains('conntype_' + conntype_el.value) ? 'table-row' : 'none';
});
if (conntype_row) conntype_row.style.display = event.target.checked ? 'table-row' : 'none';
if (conntype_end_el) conntype_end_el.style.display = event.target.checked ? 'table-row' : 'none';
if(!event.target.checked){
await clearPromptAPI('prompt_spamfilter');
}else{
updatePromptAPIInfo();
}
if (conntype_row) changeConnTypeRowColor(conntype_row, conntype_el);
});
// Initialize visibility per current toggle value
document.querySelectorAll('.specific_integration_sub').forEach(tr => {
tr.style.display = spamfilter_use_specific_integration_el.checked && tr.classList.contains('conntype_' + conntype_el.value) ? 'table-row' : 'none';
});
if (conntype_row) conntype_row.style.display = spamfilter_use_specific_integration_el.checked ? 'table-row' : 'none';
if (conntype_end_el) conntype_end_el.style.display = spamfilter_use_specific_integration_el.checked ? 'table-row' : 'none';
let spamfilter_textarea = document.getElementById('spamfilter_prompt_text');
let spamfilter_save_btn = document.getElementById('btn_save_prompt');
let spamfilter_reset_btn = document.getElementById('btn_reset_prompt');
@ -136,6 +199,9 @@ document.addEventListener('DOMContentLoaded', async () => {
});
loadSpamReport();
updateWarnings(model_prefix);
// Sync prompt API/model once on load
updatePromptAPIInfo();
});
function check_spamfilter_threshold(event) {
@ -165,6 +231,21 @@ async function loadSpamReport(){
}
}
async function updatePromptAPIInfo(){
const conntypeEl = document.getElementById(conntype_select_id);
if (!conntypeEl || !conntypeEl.value) return;
const conntype = conntypeEl.value;
const model_value = conntype.substring(0, conntype.length - 4) + '_model';
const modelEl = document.getElementById(model_prefix + model_value);
if (!modelEl) return;
const model = modelEl.value;
let spamfilter_prompt = await loadPrompt('prompt_spamfilter');
if (!spamfilter_prompt) return;
spamfilter_prompt.api = conntype;
spamfilter_prompt.model = model;
await savePrompt(spamfilter_prompt);
}
// Function to populate the table
function populateTable(data) {
const tableBody = document.getElementById("report_data_body");
@ -228,13 +309,16 @@ function saveOptions(e) {
case 'number':
options[element.id] = element.valueAsNumber;
break;
case 'text':
case 'password':
case 'text':
case 'password':
options[element.id] = element.value.trim();
break;
case 'select-one':
options[element.id] = element.value;
break;
case 'textarea':
options[element.id] = element.value;
break;
default:
console.error("[ThunderAI] Unhandled input type:", element.type);
}
@ -257,6 +341,7 @@ async function restoreOptions() {
element.value = result[element.id] ?? default_number_value;
break;
case 'text':
case 'textarea':
case 'password':
let default_text_value = '';
if(element.id == 'default_chatgpt_lang') default_text_value = prefs_default.default_chatgpt_lang;
@ -267,7 +352,15 @@ async function restoreOptions() {
let default_select_value = '';
if(element.id == 'reply_type') default_select_value = 'reply_all';
if(element.id == 'connection_type') default_select_value = 'chatgpt_web';
element.value = result[element.id] || default_select_value;
if(element.id == 'spamfilter_connection_type') default_select_value = 'chatgpt_api';
const restoreValue = result[element.id] || default_select_value;
// Ensure option exists before restoring
let optionExists = Array.from(element.options).some(opt => opt.value === restoreValue);
if (!optionExists && restoreValue !== '') {
let newOption = new Option(restoreValue, restoreValue);
element.add(newOption);
}
element.value = restoreValue;
if (element.value === '') {
element.selectedIndex = -1;
}
@ -280,4 +373,4 @@ async function restoreOptions() {
let getting = await browser.storage.sync.get(prefs_default);
setCurrentChoice(getting);
}
}