commit
edf4b7dc39
54 changed files with 4985 additions and 488 deletions
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -3,6 +3,23 @@
|
|||
|
||||
|
||||
|
||||
<h2>Version 3.6.0 - 30/07/2025</h2>
|
||||
<ul>
|
||||
<li>Now it's possibile to define custom data placeholders to be used in custom prompts [<a href="https://github.com/micz/ThunderAI/issues/156">#156</a>].</li>
|
||||
<li>Improved the handling of HTML and line breaks between the email text and the AI Chat.</li>
|
||||
<li>When replying, it's now possibile to choose a different reply type (between "all" or "sender only") directly in the AI chat window [<a href="https://github.com/micz/ThunderAI/issues/372">#372</a>].</li>
|
||||
<li>Added a new default prompt for replying to emails, which asks for a custom command each time it's used [<a href="https://github.com/micz/ThunderAI/issues/444">#444</a>].</li>
|
||||
<li><i>[All APIs]</i> Added an option to choose to exclude a tag only with an exact match in the excluded words list [<a href="https://github.com/micz/ThunderAI/issues/395">#395</a>].</li>
|
||||
<li><i>[OpenAI API]</i> Added an option to enable the OpenAI storage for API requests [<a href="https://github.com/micz/ThunderAI/issues/406">#406</a>].</li>
|
||||
<li><i>[OpenAI API]</i> In the AI chat page, the initial configuration now also displays the storage setting and the "Developer Messages" [<a href="https://github.com/micz/ThunderAI/issues/430">#430</a>].</li>
|
||||
<li><i>[Ollama API]</i> Added an option to enable the thinking feature [<a href="https://github.com/micz/ThunderAI/issues/398">#398</a>].</li>
|
||||
<li><i>[Google Gemini API]</i> In the AI chat page, the initial configuration now also displays the "System Instructions". [<a href="https://github.com/micz/ThunderAI/issues/429">#429</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Handling responses without choices when using RAG [<a href="https://github.com/micz/ThunderAI/issues/416">#416</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added Perplexity configuration [<a href="https://github.com/micz/ThunderAI/issues/405">#405</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added OpenRouter configuration [<a href="https://github.com/micz/ThunderAI/issues/401">#401</a>].</li>
|
||||
<li>Traditional Chinese (zh_Hant) translation added, thanks to <a href="https://github.com/evez">evez</a>.</li>
|
||||
<li>Some English typing errors have been fixed [<a href="https://github.com/micz/ThunderAI/issues/422">#422</a>].</li>
|
||||
</ul>
|
||||
<h2>Version 3.5.5 - ??/??/2025</h2>
|
||||
<ul>
|
||||
<li><i>[All APIs]</i> Fix: Autotag and Antispam filter working again [<a href="https://github.com/micz/ThunderAI/issues/449">#449</a>].</li>
|
||||
|
|
@ -33,7 +50,7 @@
|
|||
<ul>
|
||||
<li>Added Anthropic API support [<a href="https://github.com/micz/ThunderAI/issues/349">#349</a>].</li>
|
||||
<li>Added the <i>{%selected_html%}</i> placeholder to retrieve the HTML portion of the selected text [<a href="https://github.com/micz/ThunderAI/issues/368">#368</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added a shortcut to select configurations for known AI services. Currently, <i>Grok AI</i> and <i>Mistral AI</i> are available [<a href="https://github.com/micz/ThunderAI/issues/378">#378</a>]. <a href="https://github.com/micz/ThunderAI/issues/new?template=feature_request.md">Open an issue</a> to request additional services.</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added a shortcut to select configurations for known AI services. Currently, <i>Grok AI</i> and <i>Mistral AI</i> are available [<a href="https://github.com/micz/ThunderAI/issues/378">#378</a>]. <a href="https://github.com/micz/ThunderAI/issues/new?template=feature_request.md">Open an issue</a> to request additional services.</li>
|
||||
<li><i>[All APIs]</i> In the API WebChat is now possibile to select a part of the answer and use only that [<a href="https://github.com/micz/ThunderAI/issues/356">#356</a>].</li>
|
||||
<li><i>[All APIs]</i> Setting the "Max prompt length" to zero on the options page will disable the length check when sending a prompt to the AI. [<a href="https://github.com/micz/ThunderAI/issues/380">#380</a>].</li>
|
||||
<li><i>[All APIs]</i> Added a button to the options page to reset the 'Max prompt length' value to its default.</li>
|
||||
|
|
|
|||
6
LANG.md
6
LANG.md
|
|
@ -1,3 +1,4 @@
|
|||
cs
|
||||
de
|
||||
en
|
||||
fr
|
||||
|
|
@ -5,5 +6,6 @@ hr
|
|||
it
|
||||
pl
|
||||
pt-br
|
||||
cs
|
||||
zh_Hans
|
||||
ru
|
||||
zh_Hans
|
||||
zh_Hant
|
||||
|
|
@ -81,14 +81,18 @@ Are you using this addon in your Thunderbird?
|
|||
|
||||
### Translations
|
||||
- Chinese (Simplified): [jeklau](https://github.com/jeklau) <img src="https://micz.it/weblate/thunderai/zh_Hans.svg">
|
||||
- Chinese (Traditional): [evez](https://github.com/evez) <img src="https://micz.it/weblate/thunderai/zh_Hant.svg">
|
||||
- Czech (cs): [Fjuro](https://hosted.weblate.org/user/Fjuro/), [Jaroslav Staněk](https://hosted.weblate.org/user/jaroush/) <img src="https://micz.it/weblate/thunderai/cs.svg">
|
||||
- French (fr): Generated automatically, [Noam](https://github.com/noam-sc) <img src="https://micz.it/weblate/thunderai/fr.svg">
|
||||
- German (de): Generated automatically <img src="https://micz.it/weblate/thunderai/de.svg">
|
||||
- Italian (it): [Mic](https://github.com/micz/) <img src="https://micz.it/weblate/thunderai/it.svg">
|
||||
- Polski (pl): [neexpl](https://github.com/neexpl), [makkacprzak](https://github.com/makkacprzak) <img src="https://micz.it/weblate/thunderai/pl.svg">
|
||||
- Russian (ru): [Maksim](https://hosted.weblate.org/user/law820314/)
|
||||
- Português Brasileiro (pt-br): Bruno Pereira de Souza <img src="https://micz.it/weblate/thunderai/pt-br.svg">
|
||||
<br>
|
||||
|
||||
Do you want to help translate this addon? [Find out how!](https://micz.it/thunderbird-addon-thunderai/translate/)
|
||||
Do you want to help translate this addon? [Find out how!](https://micz.it/thunderbird-addon-thunderai/translate/) <br>
|
||||
_The language status represents the percentage of translated strings in the latest stable release._
|
||||
|
||||
|
||||
<br>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
"prompt_this": {
|
||||
"message": "Zeptat se"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "Další informace"
|
||||
},
|
||||
"customPrompts_start_saving": {
|
||||
|
|
@ -80,13 +80,13 @@
|
|||
"customPrompts_form_label_enabled": {
|
||||
"message": "Povoleno"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Uložit vše"
|
||||
},
|
||||
"customPrompts_do_reply": {
|
||||
"message": "Odpovědět"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Přidat nový"
|
||||
},
|
||||
"customPrompts_close_button": {
|
||||
|
|
@ -134,9 +134,6 @@
|
|||
"customPrompts_btnOK": {
|
||||
"message": "OK"
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Uložit"
|
||||
},
|
||||
"customPrompts_unsaved_changes": {
|
||||
"message": "Máte neuložené změny!"
|
||||
},
|
||||
|
|
@ -188,9 +185,6 @@
|
|||
"chatgpt_win_send": {
|
||||
"message": "Odeslat"
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Použít GPT3.5"
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "vynutit doplnění"
|
||||
},
|
||||
|
|
@ -353,7 +347,7 @@
|
|||
"chatgpt_api_request_failed": {
|
||||
"message": "Požadavek na OpenAI ChatGPT API selhal"
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "Čekám na odpověď serveru"
|
||||
},
|
||||
"prefs_API_Host_Info": {
|
||||
|
|
@ -467,9 +461,6 @@
|
|||
"SpamFilter_prompt_text_title": {
|
||||
"message": "Aktuální text přikazu"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "Příkaz můžete změnit, jak chcete, ale odpověď přijatá z AI musí být ve formátu JSON, jak je uvedeno ve výchozím příkazu!"
|
||||
},
|
||||
"Moved_to_Spam": {
|
||||
"message": "Přesunuto do Spamu"
|
||||
},
|
||||
|
|
@ -650,9 +641,6 @@
|
|||
"prompt_get_calendar_event": {
|
||||
"message": "Přidej novou událost do kalendáře"
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "Výzvu můžete změnit, jak chcete, ale odpověď obdržená od AI musí být seznam štítků oddělených čárkou!"
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto_only_inbox_Info": {
|
||||
"message": "Pokud je zaškrtnuto, AI bude přidávat štítky pouze e-mailům přijatým ve složce Doručená pošta."
|
||||
},
|
||||
|
|
@ -801,7 +789,7 @@
|
|||
"message": "Pokud je zaškrtnuto, štitky, které jsou přítomny v seznamu vyloučení, budou skryty v potvrzovacím dialogu."
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Analyzuj následující text e-mailu a vygeneruj seznam štítků oddělených čárkou, které shrnují jeho obsah. Použij témata, klíčová témata a relevantní deskriptory jako štitky. Zajisti, aby štitky byly stručné a relevantní k obsahu e-mailu.\nText e-mailu: {%mail_text_body%}\nPro kontext zvaž následující podrobnosti:\n- Odesílatel: {%author%}\n- Příjemci: {%recipients%}\n- Seznam kopií: {%cc_list%}\n- Předmět e-mailu: {%mail_subject%}\nZalož své štitky na textu a kontextu e-mailu, ignoruj zbytečné informace nebo triviální detaily. Výstup by měl být pouze seznam štítků oddělených čárkou bez jakéhokoli dalšího komentáře nebo textu."
|
||||
"message": "Analyzujte následující text e-mailu a vytvořte JSON pole tagů, které shrnují jeho obsah. Jako tagy použijte témata, klíčová témata a relevantní popisné prvky. Ujistěte se, že tagy jsou stručné a relevantní k obsahu e-mailu.\nText e-mailu: {%mail_text_body%}\nPro kontext zvaž následující podrobnosti:\n- Odesílatel: {%author%}\n- Příjemci: {%recipients%}\n- Seznam kopií: {%cc_list%}\n- Předmět e-mailu: {%mail_subject%}\nVycházejte z textu e-mailu a kontextu při generování tagů, ignorujte zbytečné informace nebo nepodstatné detaily.\nVygenerujte odpověď pouze ve formátu JSON. Výstupem by mělo být pouze JSON pole tagů, bez jakéhokoli dalšího komentáře nebo textu. Zde je příklad formátu JSON, který je třeba použít:\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}"
|
||||
},
|
||||
"prefs_OptionText_add_tags_maxnum": {
|
||||
"message": "Maximální počet štítků"
|
||||
|
|
@ -839,7 +827,7 @@
|
|||
"GetCalendarEvent_prompt_text_title": {
|
||||
"message": "Aktuální text výzvy"
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "Výzvu můžete změnit, jak si přejete, ale odpověď přijatá od AI musí být ve formátu JSON, jak je uvedeno ve výchozí výzvě!"
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_not_present": {
|
||||
|
|
@ -981,7 +969,7 @@
|
|||
"message": "POVINNÉ. Neměňte tuto hodnotu, pokud nevíte, co děláte. Více informací zde:"
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Verze: $api_version$",
|
||||
"message": "Verze",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
|
|
@ -1076,7 +1064,7 @@
|
|||
"message": "Selhal požadavek API Anthropic"
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Pokus o připojení k $api_string$ s následující konfigurací:",
|
||||
"message": "Pokus o připojení k $api_string$ s následující konfigurací...",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
"content": "$1"
|
||||
|
|
@ -1092,7 +1080,7 @@
|
|||
}
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Model: $model$",
|
||||
"message": "Model",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
|
|
@ -1103,7 +1091,7 @@
|
|||
"message": "Pokud vyberete nějaký text, bude zohledněna pouze tato část."
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "API Server: $api_host$",
|
||||
"message": "API Server",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
"customPrompts_managePrompts": {
|
||||
"message": "Eingabeaufforderungen verwalten"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "Informationen"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
|
|
@ -120,13 +120,10 @@
|
|||
"customPrompts_unsaved_changes": {
|
||||
"message": "Es gibt ungespeicherte Änderungen!"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Alle speichern"
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Speichern"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Neu hinzufügen"
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
|
|
@ -189,9 +186,6 @@
|
|||
"chatgpt_win_send": {
|
||||
"message": "Senden"
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Verwenden Sie GPT3.5"
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "Abschluss erzwingen"
|
||||
},
|
||||
|
|
@ -384,7 +378,7 @@
|
|||
"chatgpt_api_request_failed": {
|
||||
"message": "Anfrage an die OpenAI ChatGPT API fehlgeschlagen"
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "Warten auf die Serverantwort"
|
||||
},
|
||||
"prefs_API_Host_Info": {
|
||||
|
|
@ -513,9 +507,6 @@
|
|||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Sie können zusätzliche Datenplatzhalter verwenden."
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "Sie können den Prompt nach Wunsch ändern, aber die Antwort der KI muss eine durch Kommas getrennte Liste von Tags sein!"
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "\"v1\"-Kompatibilität beibehalten"
|
||||
},
|
||||
|
|
@ -571,7 +562,7 @@
|
|||
"message": "Tags zu dieser E-Mail hinzufügen"
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Analysieren Sie den folgenden E-Mail-Text und erstellen Sie eine durch Kommas getrennte Liste von Tags, die den Inhalt zusammenfassen. Verwenden Sie Themen, Hauptthemen und relevante Beschreibungen als Tags. Stellen Sie sicher, dass die Tags prägnant und relevant für den Inhalt der E-Mail sind.\nE-Mail-Text: {%mail_text_body%}\nBerücksichtigen Sie die folgenden Details als Kontext:\n- Absender: {%author%}\n- Empfänger: {%recipients%}\n- CC-Liste: {%cc_list%}\n- E-Mail-Betreff: {%mail_subject%}\nBitte basieren Sie Ihre Tags auf dem Text und Kontext der E-Mail und ignorieren Sie unnötige Informationen oder triviale Details. Die Ausgabe sollte nur eine Liste von durch Kommas getrennten Tags ohne zusätzlichen Kommentar oder Text sein."
|
||||
"message": "Analysiere den folgenden E-Mail-Text und erstelle ein JSON-Array mit Tags, die den Inhalt zusammenfassen. Verwende Themen, zentrale Schlagwörter und relevante Beschreibungen als Tags. Achte darauf, dass die Tags prägnant und inhaltlich relevant sind.\nE-Mail-Text: {%mail_text_body%}\nBerücksichtigen Sie die folgenden Details als Kontext:\n- Absender: {%author%}\n- Empfänger: {%recipients%}\n- CC-Liste: {%cc_list%}\n- E-Mail-Betreff: {%mail_subject%}\nErstelle die Tags auf Grundlage des E-Mail-Inhalts und Kontexts. Ignoriere unnötige Informationen oder unwichtige Details.\nGib die Antwort ausschließlich im JSON-Format aus. Die Ausgabe darf nur ein JSON-Array mit Tags enthalten – ohne weiteren Kommentar oder Text. Hier ein Beispiel für das zu verwendende JSON-Format:\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}"
|
||||
},
|
||||
"placeholder_tags_current_email": {
|
||||
"message": "E-Mail-Tags"
|
||||
|
|
@ -741,7 +732,7 @@
|
|||
"GetCalendarEvent_prompt_text_title": {
|
||||
"message": "Aktueller Prompt-Text"
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "Sie können den Prompt nach Belieben ändern, aber die von der KI erhaltene Antwort muss im JSON-Format sein, wie im Standard-Prompt angegeben!"
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_not_present": {
|
||||
|
|
@ -795,9 +786,6 @@
|
|||
"SpamFilter_prompt_text_title": {
|
||||
"message": "Aktueller Aufforderungstext"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "Sie können die Aufforderung nach Belieben ändern, aber die Antwort der KI muss im JSON-Format erfolgen, wie in der Standardaufforderung angegeben!"
|
||||
},
|
||||
"prompt_spamfilter": {
|
||||
"message": "Spam-E-Mails erkennen"
|
||||
},
|
||||
|
|
@ -916,7 +904,7 @@
|
|||
"message": "Empfange Daten"
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer": {
|
||||
"message": "Aktiviere den Unterschiedsbetrachter"
|
||||
"message": "Die Textvergleichsansicht aktivieren"
|
||||
},
|
||||
"btn_show_differences": {
|
||||
"message": "Unterschiede anzeigen"
|
||||
|
|
@ -982,7 +970,7 @@
|
|||
"message": "Wenn ein Projekt in den Optionen oder im Prompt angegeben ist, wird der temporäre Chat nicht verwendet."
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer_title": {
|
||||
"message": "Der Differenz-Viewer kann ausgewählt werden, wenn die Aktion auf „Text ersetzen“ gesetzt ist."
|
||||
"message": "Die Textvergleichsansicht kann ausgewählt werden, wenn die Aktion auf „Text ersetzen“ eingestellt ist."
|
||||
},
|
||||
"prefs_OptionText_CustomGPT_Warn": {
|
||||
"message": "Wenn ein Projekt in den Optionen oder im Prompt angegeben ist, überschreibt es die benutzerdefinierte GPT-Einstellung."
|
||||
|
|
@ -1102,7 +1090,7 @@
|
|||
"message": "Anfrage an die Anthropic-API fehlgeschlagen"
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Verbindungsversuch zu $api_string$ mit der folgenden Konfiguration:",
|
||||
"message": "Verbindungsversuch zu $api_string$ mit der folgenden Konfiguration...",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
"content": "$1"
|
||||
|
|
@ -1134,7 +1122,7 @@
|
|||
"message": "Sie haben kein Modell für die Anthropic-API ausgewählt. Bitte wählen Sie eines auf der Optionsseite aus."
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Modell: $model$",
|
||||
"message": "Modell",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
|
|
@ -1142,7 +1130,7 @@
|
|||
}
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "Host: $api_host$",
|
||||
"message": "Host",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
|
|
@ -1150,7 +1138,7 @@
|
|||
}
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Version: $api_version$",
|
||||
"message": "Version",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
|
|
@ -1179,5 +1167,86 @@
|
|||
},
|
||||
"Anthropic_Version_Info": {
|
||||
"message": "ERFORDERLICH. Ändern Sie diesen Wert nicht, es sei denn, Sie wissen, was Sie tun. Weitere Informationen unter:"
|
||||
},
|
||||
"prefs_OptionText_reply_type_Info": {
|
||||
"message": "Dies ist der Standard-Antworttyp, der beim Beantworten einer E-Mail verwendet wird. Du kannst später im Antwortdialog einen anderen auswählen."
|
||||
},
|
||||
"prefs_OptionText_btnManageCustomDataPH": {
|
||||
"message": "Verwalte deine Datenplatzhalter"
|
||||
},
|
||||
"ChatGPT_chatgpt_api_store_info": {
|
||||
"message": "Wenn markiert, werden deine Chats bei OpenAI gespeichert."
|
||||
},
|
||||
"prefs_ollama_think_Info": {
|
||||
"message": "Wenn markiert, wird das Modell nachdenken bevor es antwortet. Diese Option funtioniert nur mit Modellen, die das \"think\" Feature unterstützen."
|
||||
},
|
||||
"prefs_ollama_think": {
|
||||
"message": "Erlaube nachzudenken"
|
||||
},
|
||||
"chatgpt_win_change_reply_type": {
|
||||
"message": "Klicke, um den Rückgabetyp zu ändern"
|
||||
},
|
||||
"prefs_OptionText_add_tags_exclusions_exact_match": {
|
||||
"message": "Ausschlüsse exakte Übereinstimmung"
|
||||
},
|
||||
"prefs_OptionText_add_tags_exclusions_exact_match_Info": {
|
||||
"message": "Wenn aktiviert, werden die Wörter in der Ausschlussliste exakt mit den Tags abgeglichen. Andernfalls stimmen sie auch überein, wenn sie im Tag enthalten sind."
|
||||
},
|
||||
"customDataPH_manageDataPH": {
|
||||
"message": "Datenplatzhalter verwalten"
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default_3": {
|
||||
"message": "Du kannst auch die Standard-Datenplatzhalter mit Autovervollständigung verwenden, genau wie beim Schreiben benutzerdefinierter Prompts."
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default": {
|
||||
"message": "Auf dieser Seite kannst du benutzerdefinierte Datenplatzhalter definieren, die in deinen benutzerdefinierten Prompts verwendet werden sollen."
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default_2": {
|
||||
"message": "Vorhandene Datenplatzhalter mit derselben ID werden überschrieben. Platzhalter mit neuen IDs werden hinzugefügt."
|
||||
},
|
||||
"customDataPH_ExportAll": {
|
||||
"message": "Alle benutzerdefinierten Datenplatzhalter exportieren"
|
||||
},
|
||||
"customDataPH_Import": {
|
||||
"message": "Neue Datenplatzhalter importieren"
|
||||
},
|
||||
"customDataPH_form_label_Text": {
|
||||
"message": "Datenplatzhalter-Text"
|
||||
},
|
||||
"customDataPH_saving_custom": {
|
||||
"message": "Speichern der benutzerdefinierten Datenplatzhalter..."
|
||||
},
|
||||
"customDataPH_saved": {
|
||||
"message": "Benutzerdefinierte Datenplatzhalter gespeichert!"
|
||||
},
|
||||
"customDataPH_btnAddNewCommit": {
|
||||
"message": "Datenplatzhalter hinzufügen"
|
||||
},
|
||||
"importCustomDataPH_confirmText": {
|
||||
"message": "Du bist dabei, neue benutzerdefinierte Datenplatzhalter zu importieren."
|
||||
},
|
||||
"importCustomDataPH_start_import": {
|
||||
"message": "Import der benutzerdefinierten Datenplatzhalter wird gestartet..."
|
||||
},
|
||||
"importCustomDataPH_import_completed": {
|
||||
"message": "Import der benutzerdefinierten Datenplatzhalter abgeschlossen! Du musst auf die Schaltfläche „Alle speichern“ klicken, um deine Änderungen zu speichern."
|
||||
},
|
||||
"importCustomDataPH_invalidFile": {
|
||||
"message": "Die Datei, die du importieren möchtest, ist keine gültige Datei für benutzerdefinierte Datenplatzhalter."
|
||||
},
|
||||
"importCustomDataPH_invalidDataPHs": {
|
||||
"message": "Die Datei, die du importieren möchtest, enthält keine gültigen benutzerdefinierten Datenplatzhalter."
|
||||
},
|
||||
"customDataPH_add_to_menu": {
|
||||
"message": "Verwendbar in Prompts, die dem Menü hinzugefügt wurden"
|
||||
},
|
||||
"ChatGPT_chatgpt_api_store": {
|
||||
"message": "Verwende speicher"
|
||||
},
|
||||
"prompt_reply_custom_command_full_text": {
|
||||
"message": "Antworten Sie auf die folgende E-Mail „{%mail_text_body%}“. {%additional_text%}. Antworten Sie nur mit dem erforderlichen Text und ohne zusätzliche Kommentare oder anderen Text."
|
||||
},
|
||||
"prompt_reply_custom_command": {
|
||||
"message": "Mit Befehl antworten"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Use ChatGPT, Goolge Gemini, Anthropic or Ollama to enhance your emails!",
|
||||
"message": "Use ChatGPT, Google Gemini, Anthropic or Ollama to enhance your emails!",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
|
|
@ -19,6 +19,10 @@
|
|||
"message": "Reply to this thread",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply_custom_command": {
|
||||
"message": "Reply with command",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_polite": {
|
||||
"message": "Rewrite polite",
|
||||
"description": ""
|
||||
|
|
@ -51,7 +55,7 @@
|
|||
"message": "Manage Prompts",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "More info",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -132,11 +136,11 @@
|
|||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer": {
|
||||
"message": "Enable the diff viewer",
|
||||
"message": "Enable the text comparison viewer",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer_title": {
|
||||
"message": "The diff viewer can be selected when the action is set to \"Substitute text\".",
|
||||
"message": "The text comparison viewer can be selected when the action is set to \"Substitute text\".",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_required_fields": {
|
||||
|
|
@ -167,15 +171,11 @@
|
|||
"message": "There are unsaved changes!",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Save All",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Save",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Add New",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -259,10 +259,6 @@
|
|||
"message": "Send",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Use GPT3.5",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "force completion",
|
||||
"description": ""
|
||||
|
|
@ -304,21 +300,29 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_reply_all": {
|
||||
"message": "Reply to All",
|
||||
"message": "Reply to all",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_reply_sender": {
|
||||
"message": "Reply to Sender",
|
||||
"message": "Reply to sender",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_reply_type": {
|
||||
"message": "Reply type",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_reply_type_Info": {
|
||||
"message": "This is the default reply type that will be used when replying to an email. You can choose the other later in the reply dialog.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts": {
|
||||
"message": "Manage your prompts",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManageCustomDataPH": {
|
||||
"message": "Manage your data placeholders",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoTitle": {
|
||||
"message": "Important Information",
|
||||
"description": ""
|
||||
|
|
@ -400,7 +404,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"customprompts_form_label_define_response_lang": {
|
||||
"message": "Define the reponse language in the prompt",
|
||||
"message": "Define the response language in the prompt",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type": {
|
||||
|
|
@ -444,7 +448,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"chatgpt_empty_model": {
|
||||
"message": "You've not choosen a model for the ChatGPT API. Please choose one in the options page.",
|
||||
"message": "You've not chosen a model for the ChatGPT API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"chagpt_api_send_button": {
|
||||
|
|
@ -492,7 +496,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"ollama_empty_model": {
|
||||
"message": "You've not choosen a model for the Ollama API. Please choose one in the options page.",
|
||||
"message": "You've not chosen a model for the Ollama API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"error_connection_interrupted": {
|
||||
|
|
@ -507,7 +511,7 @@
|
|||
"message": "OpenAI ChatGPT API request failed",
|
||||
"description": ""
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "Waiting for the server response",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -532,7 +536,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"OpenAIComp_empty_model": {
|
||||
"message": "You've not choosen a model for the OpenAI Compatible API. Please choose one in the options page.",
|
||||
"message": "You've not chosen a model for the OpenAI Compatible API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_api_request_failed": {
|
||||
|
|
@ -560,7 +564,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_dynamic_menu_force_enter_info": {
|
||||
"message": "If checked, using the keyboard shortcut CTRL+ALT+A will automatically send the hightlighted prompt from the menu. Otherwise, the prompt name will be displayed to the user, requiring another press of the Enter key to send it.",
|
||||
"message": "If checked, using the keyboard shortcut CTRL+ALT+A will automatically send the highlighted prompt from the menu. Otherwise, the prompt name will be displayed to the user, requiring another press of the Enter key to send it.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_dynamic_menu_order_alphabet": {
|
||||
|
|
@ -695,10 +699,6 @@
|
|||
"message": "You can use additional data placeholders.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "You can change the prompt as you wish, but the response received from the AI must be a comma-separated list of tags!",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1" : {
|
||||
"message": "Keep the \"v1\" compatibility",
|
||||
"description": ""
|
||||
|
|
@ -739,6 +739,10 @@
|
|||
"message": "Reply to the following email \"{%selected_text%}\", considering this is the full thread of emails \"{%mail_html_body%}\". Reply with only the needed text and with no extra comments or other text.",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply_custom_command_full_text": {
|
||||
"message": "Reply to the following email \"{%mail_text_body%}\". {%additional_text%}. Reply with only the needed text and with no extra comments or other text.",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_full_text": {
|
||||
"message": "Rewrite the following text to be more polite. Reply with only the re-written text and with no extra comments or other text.",
|
||||
"description": ""
|
||||
|
|
@ -776,7 +780,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Analyze the following email text and generate a comma-separated list of tags that summarize its content. Use themes, key topics, and relevant descriptors as tags. Ensure the tags are concise and relevant to the email's content.\nEmail text: {%mail_text_body%}\nConsider the following details for context:\n- Sender: {%author%}\n- Recipients: {%recipients%}\n- CC list: {%cc_list%}\n- Email subject: {%mail_subject%}\nPlease base your tags on the email's text and context, ignoring unnecessary information or trivial details. The output should be only a list of comma separated tags without any additional comment or text.",
|
||||
"message": "Analyze the following email text and generate a JSON array of tags that summarize its content. Use themes, key topics, and relevant descriptors as tags. Ensure the tags are concise and relevant to the email's content.\nEmail text: {%mail_text_body%}\nConsider the following details for context:\n- Sender: {%author%}\n- Recipients: {%recipients%}\n- CC list: {%cc_list%}\n- Email subject: {%mail_subject%}\nPlease base your tags on the email's text and context, ignoring unnecessary information or trivial details.\nGenerate a response in JSON format only. The output should be only a JSON array of tags without any additional comment or text. Here is an example of the JSON format to be used:\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_proofread_this": {
|
||||
|
|
@ -948,7 +952,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"google_gemini_empty_model": {
|
||||
"message": "You've not choosen a model for the Google Gemini API. Please choose one in the options page.",
|
||||
"message": "You've not chosen a model for the Google Gemini API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"GoogleGemini_SystemInstruction": {
|
||||
|
|
@ -1047,7 +1051,7 @@
|
|||
"message": "Current prompt text",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "You can change the prompt as you wish, but the response received from the AI must be in JSON format as specified in the default prompt!",
|
||||
"description": ""
|
||||
},
|
||||
|
|
@ -1100,7 +1104,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"no_valid_data_received": {
|
||||
"message": "No valid data recevied from the AI.",
|
||||
"message": "No valid data received from the AI.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_auto": {
|
||||
|
|
@ -1167,10 +1171,6 @@
|
|||
"message": "Current prompt text",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "You can change the prompt as you wish, but the response received from the AI must be in JSON format as specified in the default prompt!",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_spamfilter" : {
|
||||
"message" : "Detect spam emails",
|
||||
"description" : ""
|
||||
|
|
@ -1468,7 +1468,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"anthropic_empty_model": {
|
||||
"message": "You've not choosen a model for the Anthropic API. Please choose one in the options page.",
|
||||
"message": "You've not chosen a model for the Anthropic API. Please choose one in the options page.",
|
||||
"description": ""
|
||||
},
|
||||
"anthropic_empty_version": {
|
||||
|
|
@ -1480,7 +1480,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Attempting to connect to $api_string$ using the following configuration:",
|
||||
"message": "Attempting to connect to $api_string$ using the following configuration...",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
|
|
@ -1489,31 +1489,16 @@
|
|||
}
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Model: $model$",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
"message": "Model",
|
||||
"description": ""
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "Host: $api_host$",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
"message": "Host",
|
||||
"description": ""
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Version: $api_version$",
|
||||
"description": "",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
"message": "Version",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OpenAIComp_AvailableServices": {
|
||||
"message": "Available Services",
|
||||
|
|
@ -1539,5 +1524,97 @@
|
|||
"apiwebchat_selection_info": {
|
||||
"message": "If you select some text, only that portion will be considered.",
|
||||
"description": ""
|
||||
},
|
||||
"ChatGPT_chatgpt_api_store": {
|
||||
"message": "Use storage",
|
||||
"description": ""
|
||||
},
|
||||
"ChatGPT_chatgpt_api_store_info": {
|
||||
"message": "If checked, your chats will be stored by OpenAI.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_ollama_think": {
|
||||
"message": "Enable thinking",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_ollama_think_Info": {
|
||||
"message": "If checked, the Model will think before answering. This option works only with models that support the 'think' feature.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_change_reply_type": {
|
||||
"message": "Click to change the reply type",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_exclusions_exact_match": {
|
||||
"message": "Exclusions exact match",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_exclusions_exact_match_Info": {
|
||||
"message": "If checked, the words in the exclusion list will be matched exactly with the tags. Otherwise, they will also match if included within the tag.",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_manageDataPH": {
|
||||
"message": "Manage Data Placeholders",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default_3": {
|
||||
"message": "You can also use the default data placeholders with autocomplete, just like when writing custom prompts.",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default": {
|
||||
"message": "On this page, it is possible to define custom data placeholders to be used in your custom prompts.",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default_2": {
|
||||
"message": "Existing data placeholders with the same ID will be overwritten. Placeholders with new IDs will be added.",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_ExportAll": {
|
||||
"message": "Export all custom data placeholders",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_Import": {
|
||||
"message": "Import new data placeholders",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_form_label_Text": {
|
||||
"message": "Data Placeholder Text",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_saving_custom": {
|
||||
"message": "Saving custom data placeholders...",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_saved": {
|
||||
"message": "Custom data placeholders saved!",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_btnAddNewCommit": {
|
||||
"message": "Add the Data Placeholder",
|
||||
"description": ""
|
||||
},
|
||||
"importCustomDataPH_confirmText": {
|
||||
"message": "You are about to import new custom data placeholders.",
|
||||
"description": ""
|
||||
},
|
||||
"importCustomDataPH_start_import": {
|
||||
"message": "Starting custom data placeholders import...",
|
||||
"description": ""
|
||||
},
|
||||
"importCustomDataPH_import_completed": {
|
||||
"message": "Custom data placeholders import completed! You need to click on the 'Save All' button to save your changes.",
|
||||
"description": ""
|
||||
},
|
||||
"importCustomDataPH_invalidFile": {
|
||||
"message": "The file you're trying to import is not a valid custom data placeholders file.",
|
||||
"description": ""
|
||||
},
|
||||
"importCustomDataPH_invalidDataPHs": {
|
||||
"message": "The file you're trying to import does not contain any valid custom data placeholders.",
|
||||
"description": ""
|
||||
},
|
||||
"customDataPH_add_to_menu": {
|
||||
"message": "Usable in prompts added to menu",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
{
|
||||
"customPrompts_save_button": {
|
||||
"message": "Konservi"
|
||||
},
|
||||
"prompt_lang": {
|
||||
"message": "Respondi per"
|
||||
},
|
||||
|
|
@ -11,7 +8,7 @@
|
|||
"prompt_rewrite_formal": {
|
||||
"message": "Reverki formale"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "Pliaj informoj"
|
||||
},
|
||||
"customPrompts_managePrompts": {
|
||||
|
|
@ -23,10 +20,10 @@
|
|||
"customPrompts_form_required_fields": {
|
||||
"message": "Postulataj kampoj"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Konservi ĉion"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Aldoni novan"
|
||||
},
|
||||
"chatgpt_btn_retry": {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
"customPrompts_managePrompts": {
|
||||
"message": "Gérer les prompts"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "Informations"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
|
|
@ -120,13 +120,10 @@
|
|||
"customPrompts_unsaved_changes": {
|
||||
"message": "Il y a des modifications non enregistrées !"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Tout enregistrer"
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Enregistrer"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Ajouter nouveau"
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
|
|
@ -189,9 +186,6 @@
|
|||
"chatgpt_win_send": {
|
||||
"message": "Envoyer"
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Utiliser GPT3.5"
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "forcer l'achèvement"
|
||||
},
|
||||
|
|
@ -384,7 +378,7 @@
|
|||
"chatgpt_api_request_failed": {
|
||||
"message": "La demande d'API OpenAI ChatGPT a échoué"
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "En attente de la réponse du serveur"
|
||||
},
|
||||
"prefs_API_Host_Info": {
|
||||
|
|
@ -513,9 +507,6 @@
|
|||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Vous pouvez utiliser des espaces réservés pour des données supplémentaires."
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "Vous pouvez modifier le prompt comme vous le souhaitez, mais la réponse de l'IA doit être une liste de tags séparés par des virgules !"
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Conserver la compatibilité \"v1\""
|
||||
},
|
||||
|
|
@ -571,7 +562,7 @@
|
|||
"message": "Ajoutez des tags à ce courriel"
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Analysez le texte de courriel suivant et générez une liste de tags séparés par des virgules qui résument son contenu. Utilisez des thèmes, des sujets clés et des descripteurs pertinents comme tags. Assurez-vous que les tags soient concis et pertinents pour le contenu du courriel.\nTexte du courriel : {%mail_text_body%}\nConsidérez les détails suivants pour le contexte :\n- Expéditeur : {%author%}\n- Destinataires : {%recipients%}\n- Liste CC : {%cc_list%}\n- Sujet du courriel : {%mail_subject%}\nVeuillez baser vos tags sur le texte et le contexte du courriel, en ignorant les informations inutiles ou triviales. La sortie doit être uniquement une liste de tags séparés par des virgules, sans aucun commentaire ou texte supplémentaire."
|
||||
"message": "Analyse le texte de l’e-mail suivant et génère un tableau JSON de tags résumant son contenu. Utilise des thèmes, des sujets clés et des descripteurs pertinents comme tags. Assure-toi que les tags soient concis et en lien direct avec le contenu de l’e-mail.\nTexte du courriel : {%mail_text_body%}\nConsidérez les détails suivants pour le contexte :\n- Expéditeur : {%author%}\n- Destinataires : {%recipients%}\n- Liste CC : {%cc_list%}\n- Sujet du courriel : {%mail_subject%}\nGénère les tags en te basant sur le texte de l’e-mail et le contexte, en ignorant les informations inutiles ou les détails sans importance.\nGénère une réponse uniquement au format JSON. La sortie doit être uniquement un tableau JSON de tags, sans commentaire ni texte supplémentaire. Voici un exemple du format JSON à utiliser :\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}"
|
||||
},
|
||||
"placeholder_tags_current_email": {
|
||||
"message": "Tags de courriels"
|
||||
|
|
@ -741,7 +732,7 @@
|
|||
"GetCalendarEvent_prompt_text_title": {
|
||||
"message": "Texte du prompt actuel"
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "Vous pouvez modifier le prompt comme vous le souhaitez, mais la réponse reçue de l'IA doit être au format JSON tel que spécifié dans l'invite par défaut !"
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_not_present": {
|
||||
|
|
@ -837,9 +828,6 @@
|
|||
"SpamFilter_prompt_text_title": {
|
||||
"message": "Texte du prompt actuelle"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "Vous pouvez modifier le prompt comme vous le souhaitez, mais la réponse de l'IA doit être au format JSON, comme spécifié dans le prompt par défaut !"
|
||||
},
|
||||
"thunderai_def_lang": {
|
||||
"message": "Langue par défaut telle que définie dans les options de ThunderAI."
|
||||
},
|
||||
|
|
@ -919,7 +907,7 @@
|
|||
"message": "Réception des données"
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer": {
|
||||
"message": "Activer le visualiseur de différences"
|
||||
"message": "Active la visionneuse de comparaison de texte"
|
||||
},
|
||||
"context_menu_mzta-spamfilter": {
|
||||
"message": "Analyser comme spam"
|
||||
|
|
@ -979,7 +967,7 @@
|
|||
"message": "GPT personnalisé pour ChatGPT Web"
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer_title": {
|
||||
"message": "Le visualiseur de différences peut être sélectionné lorsque l'action est définie sur \"Remplacer le texte\"."
|
||||
"message": "La visionneuse de comparaison de texte peut être sélectionnée lorsque l’action est définie sur « Substituer le texte »."
|
||||
},
|
||||
"ask_chatgptweb_permission_1": {
|
||||
"message": "Pour utiliser l'intégration Web de ChatGPT, vous devez accorder l'autorisation requise."
|
||||
|
|
@ -1084,7 +1072,7 @@
|
|||
"message": "Extrait tous les détails pertinents nécessaires pour générer une tâche à partir du texte suivant. Les informations extraites doivent inclure :\n- Date et heure d'échéance (incluant le fuseau horaire, si précisé)\n- Résumé de la tâche\n- Date et heure de début (incluant le fuseau horaire, si précisé)\nAssure-toi que les données sont clairement et uniformément formatées afin qu’elles puissent être utilisées directement pour créer une tâche.\nS'il y a des références temporelles relatives, considère que la date et l’heure de l’e-mail sont \"{%mail_datetime%}\". Calcule la date et l’heure de début en te basant sur cette référence. Si la date et l’heure de début calculées sont antérieures à \"{%current_datetime%}\", recalcule-les en utilisant \"{%current_datetime%}\" comme base.\nSi tu ne peux pas obtenir une ou plusieurs des informations requises, réponds par une chaîne vide.\nGénère une réponse uniquement au format JSON. N’inclus aucun texte ou explication supplémentaire – fournis uniquement le JSON. Voici le format à utiliser :\n{\n\"InitialDate\" : \"YYYYMMDDTHHMMSS\",\n\"dueDate\" : \"YYYYMMDDTHHMMSS\",\n\"summary\" : \"Résumé de la tâche ici\"\n}\nS'il n'y a pas d'informations concernant les dates, supprime-les.\nVoici le texte : \"{%selected_text%}\""
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Tentative de connexion à $api_string$ avec la configuration suivante :",
|
||||
"message": "Tentative de connexion à $api_string$ avec la configuration suivante ...",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
"content": "$1"
|
||||
|
|
@ -1151,7 +1139,7 @@
|
|||
"message": "Erreur lors de la tentative de récupération des modèles Anthropic"
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Modèle : $model$",
|
||||
"message": "Modèle",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
|
|
@ -1159,7 +1147,7 @@
|
|||
}
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "Hôte : $api_host$",
|
||||
"message": "Hôte",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
|
|
@ -1167,7 +1155,7 @@
|
|||
}
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Version : $api_version$",
|
||||
"message": "Version",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
|
|
@ -1179,5 +1167,86 @@
|
|||
},
|
||||
"Custom": {
|
||||
"message": "Personnalisé"
|
||||
},
|
||||
"prefs_OptionText_reply_type_Info": {
|
||||
"message": "Ceci est le type de réponse par défaut qui sera utilisé lors de la réponse à un e-mail. Vous pouvez choisir l'autre plus tard dans la fenêtre de réponse."
|
||||
},
|
||||
"prefs_OptionText_btnManageCustomDataPH": {
|
||||
"message": "Gérez vos espaces réservés de données"
|
||||
},
|
||||
"ChatGPT_chatgpt_api_store_info": {
|
||||
"message": "Si cette option est cochée, vos conversations seront enregistrées par OpenAI."
|
||||
},
|
||||
"prefs_ollama_think_Info": {
|
||||
"message": "Si cette option est cochée, le Modèle réfléchira avant de répondre. Cette option fonctionne uniquement avec les modèles qui prennent en charge la fonction « réfléchir »."
|
||||
},
|
||||
"chatgpt_win_change_reply_type": {
|
||||
"message": "Cliquez pour changer le type de réponse"
|
||||
},
|
||||
"prefs_OptionText_add_tags_exclusions_exact_match": {
|
||||
"message": "Correspondance exacte des exclusions"
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default": {
|
||||
"message": "Sur cette page, il est possible de définir des espaces réservés de données personnalisés à utiliser dans vos invites personnalisées."
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default_3": {
|
||||
"message": "Vous pouvez également utiliser les espaces réservés de données par défaut avec la saisie semi-automatique, comme lorsque vous rédigez des invites personnalisées."
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default_2": {
|
||||
"message": "Les espaces réservés de données existants avec le même identifiant seront écrasés. Les espaces réservés avec de nouveaux identifiants seront ajoutés."
|
||||
},
|
||||
"customDataPH_ExportAll": {
|
||||
"message": "Exporter tous les espaces réservés de données personnalisés"
|
||||
},
|
||||
"customDataPH_Import": {
|
||||
"message": "Importer de nouveaux espaces réservés de données"
|
||||
},
|
||||
"customDataPH_form_label_Text": {
|
||||
"message": "Texte de l'espace réservé de données"
|
||||
},
|
||||
"customDataPH_saving_custom": {
|
||||
"message": "Enregistrement des espaces réservés de données personnalisés..."
|
||||
},
|
||||
"customDataPH_saved": {
|
||||
"message": "Espaces réservés de données personnalisés enregistrés !"
|
||||
},
|
||||
"customDataPH_btnAddNewCommit": {
|
||||
"message": "Ajouter l'espace réservé de données"
|
||||
},
|
||||
"importCustomDataPH_confirmText": {
|
||||
"message": "Vous êtes sur le point d'importer de nouveaux espaces réservés de données personnalisés."
|
||||
},
|
||||
"importCustomDataPH_start_import": {
|
||||
"message": "Démarrage de l'importation des espaces réservés de données personnalisés..."
|
||||
},
|
||||
"importCustomDataPH_import_completed": {
|
||||
"message": "Importation des espaces réservés de données personnalisés terminée ! Vous devez cliquer sur le bouton « Enregistrer tout » pour sauvegarder vos modifications."
|
||||
},
|
||||
"importCustomDataPH_invalidFile": {
|
||||
"message": "Le fichier que vous essayez d'importer n'est pas un fichier valide d'espaces réservés de données personnalisés."
|
||||
},
|
||||
"importCustomDataPH_invalidDataPHs": {
|
||||
"message": "Le fichier que vous essayez d'importer ne contient aucun espace réservé de données personnalisés valide."
|
||||
},
|
||||
"customDataPH_add_to_menu": {
|
||||
"message": "Utilisable dans les invites ajoutées au menu"
|
||||
},
|
||||
"ChatGPT_chatgpt_api_store": {
|
||||
"message": "Utiliser le stockage"
|
||||
},
|
||||
"prefs_ollama_think": {
|
||||
"message": "Activer la réflexion"
|
||||
},
|
||||
"prefs_OptionText_add_tags_exclusions_exact_match_Info": {
|
||||
"message": "Si cette option est cochée, les mots de la liste d'exclusion correspondront exactement aux balises. Sinon, ils correspondront également s'ils sont inclus dans la balise."
|
||||
},
|
||||
"customDataPH_manageDataPH": {
|
||||
"message": "Gérer les espaces réservés de données"
|
||||
},
|
||||
"prompt_reply_custom_command": {
|
||||
"message": "Répondre avec une commande"
|
||||
},
|
||||
"prompt_reply_custom_command_full_text": {
|
||||
"message": "Répondez à l'e-mail suivant « {%mail_text_body%} ». {%additional_text%}. Répondez uniquement avec le texte nécessaire, sans commentaires ou texte supplémentaire."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
"customPrompts_managePrompts": {
|
||||
"message": "Upravljaj upitima"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "Više informacija"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
|
|
@ -120,13 +120,10 @@
|
|||
"customPrompts_unsaved_changes": {
|
||||
"message": "Ima nespremljenih promjena!"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Spremi sve"
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Spremi"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Dodaj novo"
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
|
|
@ -189,9 +186,6 @@
|
|||
"chatgpt_win_send": {
|
||||
"message": "Pošalji"
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Koristi GPT3.5"
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "prisilno dovrši"
|
||||
},
|
||||
|
|
@ -384,7 +378,7 @@
|
|||
"chatgpt_api_request_failed": {
|
||||
"message": "OpenAI ChatGPT API zahtjev nije uspio"
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "Čeka se odgovor poslužitelja"
|
||||
},
|
||||
"prefs_API_Host_Info": {
|
||||
|
|
@ -513,9 +507,6 @@
|
|||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Možete koristiti dodatna rezervirana mjesta za podatke."
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "Možete promijeniti upit kako želite, ali odgovor primljen od AI mora biti popis oznaka odvojenih zarezima!"
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Zadrži \"v1\" kompatibilnost"
|
||||
},
|
||||
|
|
@ -571,7 +562,7 @@
|
|||
"message": "Dodaj oznake ovoj e-poruci"
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Analiziraj sljedeći tekst e-poruke i generiraj popis oznaka odvojenih zarezima koji sažimaju njegov sadržaj. Koristi teme, ključne teme i relevantne deskriptore kao oznake. Provjeri jesu li oznake sažete i relevantne za sadržaj e-poruke.\nTekst e-poruke: {%mail_text_body%}\nUzmi u obzir sljedeće pojedinosti za kontekst:\n- Šalje: {%author%}\n- Primatelji: {%recipients%}\n- CC popis: {%cc_list%}\n- Naslov: {%mail_subject%}\nTemelji svoje oznake na tekstu i kontekstu e-poruke, zanemarujući nepotrebne informacije ili trivijalne detalje. Izlaz bi trebao biti samo popis oznaka odvojenih zarezom bez dodatnih komentara ili teksta."
|
||||
"message": "Analiziraj sljedeći tekst e-pošte i generiraj JSON niz oznaka koje sažimaju njezin sadržaj. Koristi teme, ključne pojmove i relevantne opise kao oznake. Pobrini se da oznake budu sažete i relevantne za sadržaj poruke.\nTekst e-poruke: {%mail_text_body%}\nUzmi u obzir sljedeće pojedinosti za kontekst:\n- Šalje: {%author%}\n- Primatelji: {%recipients%}\n- CC popis: {%cc_list%}\n- Naslov: {%mail_subject%}\nTemelji oznake na tekstu poruke i kontekstu, zanemarujući nebitne informacije ili trivijalne detalje.\nGeneriraj odgovor isključivo u JSON formatu. Izlaz mora biti samo JSON niz oznaka, bez ikakvih dodatnih komentara ili teksta. Evo primjera formata koji treba koristiti:\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}"
|
||||
},
|
||||
"placeholder_tags_current_email": {
|
||||
"message": "Oznake e-pošte"
|
||||
|
|
@ -741,7 +732,7 @@
|
|||
"GetCalendarEvent_prompt_text_title": {
|
||||
"message": "Trenutačni tekst upita"
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "Možete promijeniti upit kako želite, ali odgovor primljen od AI mora biti u JSON formatu kako je navedeno u zadanom upitu!"
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_not_present": {
|
||||
|
|
@ -807,9 +798,6 @@
|
|||
"SpamFilter_prompt_text_title": {
|
||||
"message": "Trenutačni tekst upita"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "Možete promijeniti upit kako želite, ali odgovor primljen od AI mora biti u JSON formatu kako je navedeno u zadanom upitu!"
|
||||
},
|
||||
"prompt_spamfilter": {
|
||||
"message": "Prepoznaj neželjenu poštu"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
"customPrompts_managePrompts": {
|
||||
"message": "Gestisci i prompt"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "Informazioni"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
|
|
@ -120,13 +120,10 @@
|
|||
"customPrompts_unsaved_changes": {
|
||||
"message": "Ci sono modifiche non salvate!"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Salva Tutto"
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Salva"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Aggiungi Nuovo"
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
|
|
@ -189,9 +186,6 @@
|
|||
"chatgpt_win_send": {
|
||||
"message": "Invia"
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Usa GPT3.5"
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "forza il completamento"
|
||||
},
|
||||
|
|
@ -384,7 +378,7 @@
|
|||
"chatgpt_api_request_failed": {
|
||||
"message": "Richiesta all'API compatibile con OpenAI ChatGPT fallita"
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "In attesa della risposta del server"
|
||||
},
|
||||
"prefs_API_Host_Info": {
|
||||
|
|
@ -513,9 +507,6 @@
|
|||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Puoi utilizzare segnaposto per dati aggiuntivi."
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "Puoi modificare il prompt come preferisci, ma la risposta ricevuta dall'IA deve essere una lista di tag separati da virgole!"
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Mantieni la compatibilità con \"v1\""
|
||||
},
|
||||
|
|
@ -571,7 +562,7 @@
|
|||
"message": "Aggiungi tag a questa email"
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Analizza il seguente testo email e genera una lista di tag separati da virgole che ne riassumano il contenuto. Usa temi, argomenti principali e descrittori pertinenti come tag. Assicurati che i tag siano concisi e rilevanti per il contenuto dell'email.\nTesto email: {%mail_text_body%}\nConsidera i seguenti dettagli come contesto:\n- Mittente: {%author%}\n- Destinatari: {%recipients%}\n- Lista CC: {%cc_list%}\n- Oggetto dell'email: {%mail_subject%}\nBasa i tuoi tag sul testo e sul contesto dell'email, ignorando informazioni superflue o dettagli banali. L'output dovrebbe essere solo un elenco di tag separati da virgole, senza alcun commento o testo aggiuntivo."
|
||||
"message": "Analizza il seguente testo email e genera un array JSON di tag che ne riassumano il contenuto. Utilizza come tag i temi, gli argomenti principali e i descrizioni rilevanti. Assicurati che i tag siano concisi e pertinenti al contenuto dell’email.\nTesto email: {%mail_text_body%}\nConsidera i seguenti dettagli come contesto:\n- Mittente: {%author%}\n- Destinatari: {%recipients%}\n- Lista CC: {%cc_list%}\n- Oggetto dell'email: {%mail_subject%}\nBasati sul testo dell’email e sul contesto per generare i tag, ignorando le informazioni superflue o i dettagli irrilevanti.\nGenera una risposta esclusivamente in formato JSON. L’output deve essere solo un array JSON di tag, senza alcun commento o testo aggiuntivo. Ecco un esempio del formato JSON da utilizzare:\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}"
|
||||
},
|
||||
"placeholder_tags_current_email": {
|
||||
"message": "Tag delle email"
|
||||
|
|
@ -741,7 +732,7 @@
|
|||
"GetCalendarEvent_prompt_text_title": {
|
||||
"message": "Testo attuale del prompt"
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "Puoi modificare il prompt come preferisci, ma la risposta ricevuta dall'AI deve essere in formato JSON come specificato nel prompt predefinito!"
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_not_present": {
|
||||
|
|
@ -849,9 +840,6 @@
|
|||
"prefs_OptionText_spamfilter_Info": {
|
||||
"message": "Se selezionato, ThunderAI sposterà automaticamente le email di spam nella cartella dello spam."
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "Puoi modificare il prompt come desideri, ma la risposta ricevuta dall'IA deve essere in formato JSON come specificato nel prompt predefinito!"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_threshold": {
|
||||
"message": "Valore soglia per lo spam"
|
||||
},
|
||||
|
|
@ -931,7 +919,7 @@
|
|||
"message": "Se selezionato, il fuso orario specificato verrà applicato agli eventi del calendario e alle attività."
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer": {
|
||||
"message": "Abilita il visualizzatore delle differenze"
|
||||
"message": "Abilita il visualizzatore di confronto del testo"
|
||||
},
|
||||
"apiwebchat_stopping": {
|
||||
"message": "Interruzione in corso"
|
||||
|
|
@ -973,7 +961,7 @@
|
|||
"message": "Nessun testo selezionato, vuoi inserire la risposta dell'IA all'inizio dell'email?"
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer_title": {
|
||||
"message": "Il visualizzatore delle differenze può essere selezionato quando l'azione è impostata su \"Sostituisci testo\"."
|
||||
"message": "Il visualizzatore di confronto del testo può essere selezionato quando l'azione è impostata su \"Sostituisci testo\"."
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_wrong_version": {
|
||||
"message": "Per utilizzare le funzionalità di eventi del calendario e delle attività, installa una versione aggiornata del componente aggiuntivo ThunderAI Sparks."
|
||||
|
|
@ -1132,7 +1120,7 @@
|
|||
"message": "Non hai aggiunto la versione per l'API di Anthropic. Inseriscila nella pagina delle opzioni."
|
||||
},
|
||||
"_api_connecting": {
|
||||
"message": "Tentativo di connessione a $api_string$ utilizzando la seguente configurazione:",
|
||||
"message": "Tentativo di connessione a $api_string$ utilizzando la seguente configurazione...",
|
||||
"placeholders": {
|
||||
"api_string": {
|
||||
"content": "$1"
|
||||
|
|
@ -1140,7 +1128,7 @@
|
|||
}
|
||||
},
|
||||
"_api_connecting_model": {
|
||||
"message": "Modello: $model$",
|
||||
"message": "Modello",
|
||||
"placeholders": {
|
||||
"model": {
|
||||
"content": "$1"
|
||||
|
|
@ -1148,7 +1136,7 @@
|
|||
}
|
||||
},
|
||||
"_api_connecting_host": {
|
||||
"message": "Host: $api_host$",
|
||||
"message": "Host",
|
||||
"placeholders": {
|
||||
"api_host": {
|
||||
"content": "$1"
|
||||
|
|
@ -1173,7 +1161,7 @@
|
|||
"message": "Se selezioni del testo, verrà considerata solo quella parte."
|
||||
},
|
||||
"_api_connecting_version": {
|
||||
"message": "Versione: $api_version$",
|
||||
"message": "Versione",
|
||||
"placeholders": {
|
||||
"api_version": {
|
||||
"content": "$1"
|
||||
|
|
@ -1182,5 +1170,86 @@
|
|||
},
|
||||
"anthropic_api_request_failed": {
|
||||
"message": "Richiesta all'API di Anthropic non riuscita"
|
||||
},
|
||||
"prefs_OptionText_reply_type_Info": {
|
||||
"message": "Questa è la modalità di risposta predefinita che verrà utilizzata quando rispondi a un'email. Puoi scegliere l'altra modalità nella finestra di risposta."
|
||||
},
|
||||
"ChatGPT_chatgpt_api_store": {
|
||||
"message": "Usa lo storage"
|
||||
},
|
||||
"ChatGPT_chatgpt_api_store_info": {
|
||||
"message": "Se selezionato, le tue chat verranno memorizzate da OpenAI."
|
||||
},
|
||||
"prefs_ollama_think": {
|
||||
"message": "Abilita il thinking"
|
||||
},
|
||||
"prefs_ollama_think_Info": {
|
||||
"message": "Se selezionato, il Modello rifletterà prima di rispondere. Questa opzione funziona solo con i modelli che supportano la funzione \"think\"."
|
||||
},
|
||||
"prefs_OptionText_btnManageCustomDataPH": {
|
||||
"message": "Gestisci i segnaposti dei tuoi dati"
|
||||
},
|
||||
"chatgpt_win_change_reply_type": {
|
||||
"message": "Fai clic per cambiare il tipo di risposta"
|
||||
},
|
||||
"prefs_OptionText_add_tags_exclusions_exact_match": {
|
||||
"message": "Esclusione con corrispondenza esatta"
|
||||
},
|
||||
"prefs_OptionText_add_tags_exclusions_exact_match_Info": {
|
||||
"message": "Se selezionato, le parole nell'elenco delle esclusioni verranno confrontate esattamente con i tag. Altrimenti, verranno considerate corrispondenti anche quando incluse all'interno del tag."
|
||||
},
|
||||
"customDataPH_manageDataPH": {
|
||||
"message": "Gestisci i segnaposto dei dati"
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default": {
|
||||
"message": "In questa pagina è possibile definire segnaposto di dati personalizzati da utilizzare nei tuoi prompt personalizzati."
|
||||
},
|
||||
"customDataPH_btnAddNewCommit": {
|
||||
"message": "Aggiungi il segnaposto di dati"
|
||||
},
|
||||
"customDataPH_saved": {
|
||||
"message": "Segnaposto di dati personalizzati salvati!"
|
||||
},
|
||||
"customDataPH_saving_custom": {
|
||||
"message": "Salvataggio dei segnaposto di dati personalizzati in corso..."
|
||||
},
|
||||
"importCustomDataPH_invalidFile": {
|
||||
"message": "Il file che stai cercando di importare non è un file valido di segnaposto di dati personalizzati."
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default_3": {
|
||||
"message": "Puoi anche usare i segnaposto dei dati predefiniti con il completamento automatico, proprio come quando scrivi prompt personalizzati."
|
||||
},
|
||||
"customDataPH_ExportAll": {
|
||||
"message": "Esporta tutti i segnaposto di dati personalizzati"
|
||||
},
|
||||
"customDataPH_Import": {
|
||||
"message": "Importa nuovi segnaposto di dati"
|
||||
},
|
||||
"customDataPH_form_label_Text": {
|
||||
"message": "Testo del segnaposto di dati"
|
||||
},
|
||||
"importCustomDataPH_confirmText": {
|
||||
"message": "Stai per importare nuovi segnaposto di dati personalizzati."
|
||||
},
|
||||
"importCustomDataPH_start_import": {
|
||||
"message": "Avvio dell'importazione dei segnaposto di dati personalizzati..."
|
||||
},
|
||||
"importCustomDataPH_import_completed": {
|
||||
"message": "Importazione dei segnaposto di dati personalizzati completata! Devi cliccare sul pulsante \"Salva tutto\" per salvare le modifiche."
|
||||
},
|
||||
"importCustomDataPH_invalidDataPHs": {
|
||||
"message": "Il file che stai cercando di importare non contiene alcun segnaposto di dati personalizzati valido."
|
||||
},
|
||||
"customDataPH_add_to_menu": {
|
||||
"message": "Utilizzabile nei prompt aggiunti al menu"
|
||||
},
|
||||
"customDataPH_manageDataPH_info_default_2": {
|
||||
"message": "I segnaposto di dati esistenti con lo stesso ID verranno sovrascritti. I segnaposto con ID nuovi verranno aggiunti."
|
||||
},
|
||||
"prompt_reply_custom_command": {
|
||||
"message": "Rispondi con istruzioni aggiuntive"
|
||||
},
|
||||
"prompt_reply_custom_command_full_text": {
|
||||
"message": "Rispondi alla seguente email \"{%mail_text_body%}\". {%additional_text%}. Rispondi solo con il testo necessario, senza commenti aggiuntivi o altro testo."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
"customPrompts_managePrompts": {
|
||||
"message": "Zarządzaj poleceniami"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "Więcej informacji"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
|
|
@ -120,13 +120,10 @@
|
|||
"customPrompts_unsaved_changes": {
|
||||
"message": "Istnieją niezapisane zmiany!"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Zapisz wszystko"
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Zapisz"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Dodaj nowe"
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
|
|
@ -189,9 +186,6 @@
|
|||
"chatgpt_win_send": {
|
||||
"message": "Wyślij"
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Użyj GPT3.5"
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "wymuś zakończenie"
|
||||
},
|
||||
|
|
@ -384,7 +378,7 @@
|
|||
"chatgpt_api_request_failed": {
|
||||
"message": "Zapytanie do API OpenAI ChatGPT nie powiodło się"
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "Oczekiwanie na odpowiedź serwera"
|
||||
},
|
||||
"prefs_API_Host_Info": {
|
||||
|
|
@ -513,9 +507,6 @@
|
|||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Możesz użyć dodatkowych symboli zastępczych danych."
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "Możesz zmienić polecenie według własnego uznania, ale odpowiedź otrzymana od AI musi być listą tagów oddzielonych przecinkami!"
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Zachowaj kompatybilność z \"v1\""
|
||||
},
|
||||
|
|
@ -571,7 +562,7 @@
|
|||
"message": "Dodaj tagi do tego e-maila"
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Przeanalizuj poniższy tekst e-maila i wygeneruj listę tagów oddzielonych przecinkami, które podsumowują jego treść. Użyj tematów, kluczowych zagadnień i odpowiednich opisów jako tagów. Upewnij się, że tagi są zwięzłe i odpowiednie do treści e-maila.\nTekst e-maila: {%mail_text_body%}\nWeź pod uwagę następujące szczegóły w kontekście:\n- Nadawca: {%author%}\n- Odbiorcy: {%recipients%}\n- Lista DW: {%cc_list%}\n- Temat e-maila: {%mail_subject%}\nOprzyj swoje tagi na treści i kontekście e-maila, ignorując zbędne informacje lub nieistotne szczegóły. Wynik powinien być jedynie listą tagów oddzielonych przecinkami, bez żadnych dodatkowych komentarzy ani tekstu."
|
||||
"message": "Przeanalizuj poniższy tekst e-maila i wygeneruj tablicę JSON z tagami podsumowującymi jego treść. Użyj tematów, kluczowych zagadnień i odpowiednich określeń jako tagów. Upewnij się, że tagi są zwięzłe i adekwatne do treści wiadomości.\nTekst e-maila: {%mail_text_body%}\nWeź pod uwagę następujące szczegóły w kontekście:\n- Nadawca: {%author%}\n- Odbiorcy: {%recipients%}\n- Lista DW: {%cc_list%}\n- Temat e-maila: {%mail_subject%}\nNa podstawie treści wiadomości i kontekstu wygeneruj tagi, pomijając zbędne informacje lub nieistotne szczegóły.\nWygeneruj odpowiedź wyłącznie w formacie JSON. Wynik powinien zawierać jedynie tablicę tagów w formacie JSON, bez dodatkowych komentarzy czy tekstu. Oto przykład wymaganego formatu:\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}"
|
||||
},
|
||||
"placeholder_tags_current_email": {
|
||||
"message": "Tagi e-maila"
|
||||
|
|
@ -732,7 +723,7 @@
|
|||
"GetCalendarEvent_prompt_text_title": {
|
||||
"message": "Bieżący tekst zapytania"
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "Możesz zmienić monit według własnego uznania, ale odpowiedź otrzymana od AI musi być w formacie JSON, jak określono w domyślnym zapytaniu!"
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_not_present": {
|
||||
|
|
@ -765,9 +756,6 @@
|
|||
"message": "Klucz API Google Gemini",
|
||||
"description": "Klucz API dla interfejsu API Google Gemini"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "Możesz zmienić prompt według własnego uznania, ale odpowiedź AI musi być w formacie JSON zgodnie z domyślnym promptem!"
|
||||
},
|
||||
"Subject": {
|
||||
"message": "Temat"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
"customPrompts_managePrompts": {
|
||||
"message": "Gerenciar Prompts"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "Mais informações"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
|
|
@ -120,13 +120,10 @@
|
|||
"customPrompts_unsaved_changes": {
|
||||
"message": "Existem alterações não salvas!"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "Salvar Tudo"
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Salvar"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "Adicionar Novo"
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
|
|
@ -189,9 +186,6 @@
|
|||
"chatgpt_win_send": {
|
||||
"message": "Enviar"
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Usar GPT-3.5"
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "forçar conclusão"
|
||||
},
|
||||
|
|
@ -384,7 +378,7 @@
|
|||
"chatgpt_api_request_failed": {
|
||||
"message": "A solicitação da API do OpenAI ChatGPT falhou"
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "Aguardando a resposta do servidor"
|
||||
},
|
||||
"prefs_API_Host_Info": {
|
||||
|
|
@ -513,9 +507,6 @@
|
|||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Você pode usar espaços reservados para dados adicionais."
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "Você pode alterar o prompt como quiser, mas a resposta recebida da IA deve ser uma lista de tags separadas por vírgulas!"
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Manter a compatibilidade com \"v1\""
|
||||
},
|
||||
|
|
@ -571,7 +562,7 @@
|
|||
"message": "Adicione tags a este e-mail"
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Analise o seguinte texto do e-mail e gere uma lista de tags separadas por vírgulas que resumam seu conteúdo. Use temas, tópicos principais e descritores relevantes como tags. Certifique-se de que as tags sejam concisas e relevantes para o conteúdo do e-mail.\nTexto do e-mail: {%mail_text_body%}\nConsidere os seguintes detalhes como contexto:\n- Remetente: {%author%}\n- Destinatários: {%recipients%}\n- Lista CC: {%cc_list%}\n- Assunto do e-mail: {%mail_subject%}\nBaseie suas tags no texto e contexto do e-mail, ignorando informações desnecessárias ou triviais. A saída deve ser apenas uma lista de tags separadas por vírgulas, sem nenhum comentário ou texto adicional."
|
||||
"message": "Analise o seguinte texto de e-mail e gere um array JSON de tags que resumam seu conteúdo. Use temas, tópicos principais e descritores relevantes como tags. Certifique-se de que as tags sejam concisas e pertinentes ao conteúdo do e-mail.\nTexto do e-mail: {%mail_text_body%}\nConsidere os seguintes detalhes como contexto:\n- Remetente: {%author%}\n- Destinatários: {%recipients%}\n- Lista CC: {%cc_list%}\n- Assunto do e-mail: {%mail_subject%}\nBaseie-se no texto do e-mail e no contexto para gerar as tags, ignorando informações desnecessárias ou detalhes triviais.\nGere uma resposta somente no formato JSON. A saída deve ser apenas um array JSON de tags, sem nenhum comentário ou texto adicional. Aqui está um exemplo do formato JSON a ser usado:\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}"
|
||||
},
|
||||
"placeholder_tags_current_email": {
|
||||
"message": "Tags do e-mail"
|
||||
|
|
@ -741,7 +732,7 @@
|
|||
"GetCalendarEvent_prompt_text_title": {
|
||||
"message": "Texto do prompt atual"
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "Você pode alterar o prompt como desejar, mas a resposta recebida da IA deve estar no formato JSON conforme especificado no prompt padrão!"
|
||||
},
|
||||
"prefs_OptionText_get_calendar_event_Sparks_not_present": {
|
||||
|
|
@ -762,9 +753,6 @@
|
|||
"calendar_opening_dialog_error": {
|
||||
"message": "Erro ao abrir a caixa de diálogo do evento de calendário"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "Você pode alterar o prompt como quiser, mas a resposta recebida da IA deve estar no formato JSON, conforme especificado no prompt padrão!"
|
||||
},
|
||||
"spamfilter_threshold_zero": {
|
||||
"message": "O limite de spam está em zero! Você marcará todos os e-mails como spam!"
|
||||
},
|
||||
|
|
|
|||
158
_locales/pt/messages.json
Normal file
158
_locales/pt/messages.json
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
{
|
||||
"prompt_lang": {
|
||||
"message": "Responder em"
|
||||
},
|
||||
"prompt_selection_needed": {
|
||||
"message": "Para avançar tens que selecionar texto!"
|
||||
},
|
||||
"customPrompts_form_label_need_custom_text": {
|
||||
"message": "Pedir texto adicional"
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer_title": {
|
||||
"message": "O visualizador de comparação de texto pode ser selecionado quando a ação escolhida é \"Substituir texto\"."
|
||||
},
|
||||
"chatgpt_win_job_completed": {
|
||||
"message": "Concluído!"
|
||||
},
|
||||
"chatgpt_win_job_completed_select": {
|
||||
"message": "Seleciona o texto que queres usar e carrega no botão."
|
||||
},
|
||||
"prompt_reply_advanced": {
|
||||
"message": "Responder a esta sequência"
|
||||
},
|
||||
"more_info_string": {
|
||||
"message": "Mais informação"
|
||||
},
|
||||
"menu_title": {
|
||||
"message": "IA"
|
||||
},
|
||||
"prompt_classify": {
|
||||
"message": "Classificar"
|
||||
},
|
||||
"customPrompts_add_to_menu_always": {
|
||||
"message": "Sempre"
|
||||
},
|
||||
"prompt_reply": {
|
||||
"message": "Responder a este email"
|
||||
},
|
||||
"prompt_rewrite_polite": {
|
||||
"message": "Rescrever educadamente"
|
||||
},
|
||||
"prompt_rewrite_formal": {
|
||||
"message": "Rescrever formalmente"
|
||||
},
|
||||
"prompt_translate_this": {
|
||||
"message": "Traduzir isto"
|
||||
},
|
||||
"customPrompts_reindexing_list": {
|
||||
"message": "A redefinir os índices da lista..."
|
||||
},
|
||||
"customPrompts_reloading_menus": {
|
||||
"message": "A recarregar menus..."
|
||||
},
|
||||
"customPrompts_form_label_ID": {
|
||||
"message": "ID"
|
||||
},
|
||||
"customPrompts_form_label_ID_rules": {
|
||||
"message": "Deve ser único, letra minúscula e sem espaços"
|
||||
},
|
||||
"customPrompts_form_label_Action": {
|
||||
"message": "Ação"
|
||||
},
|
||||
"customPrompts_form_label_need_selected": {
|
||||
"message": "Necessário selecionar texto"
|
||||
},
|
||||
"customPrompts_form_label_need_signature": {
|
||||
"message": "Adicionar sempre assinatura"
|
||||
},
|
||||
"customPrompts_form_label_enabled": {
|
||||
"message": "Ativo"
|
||||
},
|
||||
"customPrompts_form_required_fields": {
|
||||
"message": "Campos obrigatórios"
|
||||
},
|
||||
"customPrompts_btnEdit": {
|
||||
"message": "Editar"
|
||||
},
|
||||
"customPrompts_btnCancel": {
|
||||
"message": "Cancelar"
|
||||
},
|
||||
"customPrompts_btnOK": {
|
||||
"message": "OK"
|
||||
},
|
||||
"customPrompts_btnDelete": {
|
||||
"message": "Apagar"
|
||||
},
|
||||
"customPrompts_btnDelete_confirmText": {
|
||||
"message": "Tens a certeza que queres apagar este item?"
|
||||
},
|
||||
"customPrompts_unsaved_changes": {
|
||||
"message": "Existem alterações por guardar!"
|
||||
},
|
||||
"btnSaveAll_string": {
|
||||
"message": "Guardar Tudo"
|
||||
},
|
||||
"btnNew_string": {
|
||||
"message": "Adicionar Novo"
|
||||
},
|
||||
"customPrompts_add_to_menu": {
|
||||
"message": "Adicionar ao menu"
|
||||
},
|
||||
"customPrompts_add_to_menu_reading": {
|
||||
"message": "A ler um email"
|
||||
},
|
||||
"customPrompts_substitute_text": {
|
||||
"message": "Substituir texto"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default_3": {
|
||||
"message": "Se estiver tudo certo, depois de importar carrega no botão \"Guardar Tudo\"."
|
||||
},
|
||||
"extensionDescription": {
|
||||
"message": "Usa o ChatGPT, Google Gemini, Anthropic ou Ollama para melhorar os teus emails!"
|
||||
},
|
||||
"customPrompts_form_label_Name": {
|
||||
"message": "Nome"
|
||||
},
|
||||
"prompt_summarize_this": {
|
||||
"message": "Resumir isto"
|
||||
},
|
||||
"customPrompts_add_to_menu_composing": {
|
||||
"message": "A compor um email"
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer": {
|
||||
"message": "Ativar o visualizador de comparação de texto"
|
||||
},
|
||||
"chatgpt_win_working": {
|
||||
"message": "Trabalho em curso..."
|
||||
},
|
||||
"customPrompts_managePrompts": {
|
||||
"message": "Gerir prompts"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
"message": "Os prompts padrão não são editáveis. Podes desativá-los, copiar o texto do prompt e colá-lo num novo, para criar uma versão modificada."
|
||||
},
|
||||
"customPrompts_managePrompts_info_default_2": {
|
||||
"message": "Podes importar e exportar prompts. Prompts existentes com o mesmo ID serão escritos por cima. Prompts com um ID novo serão adicionados."
|
||||
},
|
||||
"customPrompts_start_saving": {
|
||||
"message": "A guardar prompts..."
|
||||
},
|
||||
"customPrompts_filtering_prompts": {
|
||||
"message": "A filtrar prompts..."
|
||||
},
|
||||
"customPrompts_saving_default_prompts": {
|
||||
"message": "A guardar prompts padrão..."
|
||||
},
|
||||
"customPrompts_saving_custom_prompts": {
|
||||
"message": "A guardar prompts personalizados..."
|
||||
},
|
||||
"customPrompts_saved": {
|
||||
"message": "Prompts guardados!"
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
"message": "Adicionar o prompt"
|
||||
},
|
||||
"customPrompts_do_reply": {
|
||||
"message": "Responder"
|
||||
}
|
||||
}
|
||||
1218
_locales/ru/messages.json
Normal file
1218
_locales/ru/messages.json
Normal file
File diff suppressed because it is too large
Load diff
1
_locales/sk/messages.json
Normal file
1
_locales/sk/messages.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -38,13 +38,13 @@
|
|||
"customPrompts_form_label_need_signature": {
|
||||
"message": "始终添加签名"
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"btnNew_string": {
|
||||
"message": "新增"
|
||||
},
|
||||
"chatgpt_win_job_completed": {
|
||||
"message": "完成了!"
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"btnSaveAll_string": {
|
||||
"message": "保存所有变动"
|
||||
},
|
||||
"extensionDescription": {
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
"customPrompts_managePrompts": {
|
||||
"message": "管理提示词"
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"more_info_string": {
|
||||
"message": "更多信息"
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
|
|
@ -116,9 +116,6 @@
|
|||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "您可以使用额外的数据占位符。"
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "您可以根据需要更改提示,但从 AI 收到的响应必须是以逗号分隔的标签列表!"
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "保持“v1”兼容性"
|
||||
},
|
||||
|
|
@ -197,9 +194,6 @@
|
|||
"customPrompts_btnCancel": {
|
||||
"message": "取消"
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "保存"
|
||||
},
|
||||
"customPrompts_add_to_menu": {
|
||||
"message": "添加到菜单"
|
||||
},
|
||||
|
|
@ -359,15 +353,12 @@
|
|||
"prefsDonation_2": {
|
||||
"message": "考虑捐款!"
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"WaitingServerResponse": {
|
||||
"message": "正在等待服务器响应"
|
||||
},
|
||||
"OpenAIComp_Models_Error_fetching": {
|
||||
"message": "尝试获取 OpenAI 兼容 API 模型时出错"
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "使用 GPT3.5"
|
||||
},
|
||||
"customPrompts_Import": {
|
||||
"message": "导入新提示词"
|
||||
},
|
||||
|
|
@ -651,7 +642,7 @@
|
|||
"message": "单击此处,只需一分钟!"
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "分析以下邮件文本,并生成一个用逗号分隔的标签列表,以概括其内容。使用主题、关键话题和相关描述词作为标签。确保标签简洁且与邮件内容相关。\n邮件文本:{%mail_text_body%}\n考虑以下细节以获取上下文:\n- 发件人:{%author%}\n- 收件人:{%recipients%}\n- 抄送列表:{%cc_list%}\n- 邮件主题:{%mail_subject%}\n请根据邮件文本和上下文生成标签,忽略不必要的信息或琐碎的细节。输出应仅为逗号分隔的标签列表,不包含任何额外评论或文字。"
|
||||
"message": "请分析以下电子邮件文本,并生成一个 JSON 数组的标签,总结其内容。请使用主题、关键话题和相关描述词作为标签。确保标签简洁且与邮件内容密切相关。\n邮件文本:{%mail_text_body%}\n考虑以下细节以获取上下文:\n- 发件人:{%author%}\n- 收件人:{%recipients%}\n- 抄送列表:{%cc_list%}\n- 邮件主题:{%mail_subject%}\n请仅根据邮件正文和上下文生成标签,忽略无关信息或琐碎细节。\n请仅以 JSON 格式生成回复。输出应仅包含标签的 JSON 数组,不包含任何额外注释或文本。以下是需使用的 JSON 格式示例:\n{\n\"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}"
|
||||
},
|
||||
"placeholder_tags_full_list": {
|
||||
"message": "现有标签"
|
||||
|
|
@ -830,15 +821,12 @@
|
|||
"GetCalendarEvent_prompt_text_title": {
|
||||
"message": "当前提示词文字"
|
||||
},
|
||||
"prefs_OptionText_GetCalendarEvent_infoline2": {
|
||||
"prefs_OptionText_AdvancedPromptResponse_infoline2": {
|
||||
"message": "您可以根据需要更改提示,但从 AI 收到的响应必须采用默认提示中指定的 JSON 格式!"
|
||||
},
|
||||
"calendar_getting_data_error": {
|
||||
"message": "获取日历事件数据时出错"
|
||||
},
|
||||
"prefs_OptionText_spamfilter_infoline": {
|
||||
"message": "您可以根据需要更改提示词,但从 AI 收到的响应必须采用默认提示中指定的 JSON 格式!"
|
||||
},
|
||||
"prompt_spamfilter_full_text": {
|
||||
"message": "分析以下邮件并判断它是否为垃圾邮件。考虑因素包括可疑关键词、过多的宣传语言、误导性的主题行、索取个人信息的请求以及异常的发件人地址。\n提供一个从 0(非垃圾邮件)到 100(垃圾邮件)的值,并附上不超过 10 个单词的解释。\n如果消息数据缺失,将数值设为0(非垃圾邮件),并说明原因。\n仅以 JSON 格式生成响应。不要包含任何额外文本或解释;仅提供 JSON。以下是使用的格式:\n{\n\"spamValue\": <0 到 100 的整数>,\n\"explanation\": \"简要说明您的判断理由\"\n}\n以下是邮件信息:\n发件人:“{%author%}”\n主题:“{%mail_subject%}”\nHTML 正文:“{%mail_html_body%}”"
|
||||
},
|
||||
|
|
@ -882,7 +870,7 @@
|
|||
"message": "如果选中,“添加标签”上下文菜单项将在消息列表中右键单击电子邮件时显示。"
|
||||
},
|
||||
"noActiveCalendar": {
|
||||
"message": "未找到激活的日历!"
|
||||
"message": "未找到可编辑的日历!"
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer": {
|
||||
"message": "启用差异查看器"
|
||||
|
|
@ -928,5 +916,8 @@
|
|||
},
|
||||
"Explanation": {
|
||||
"message": "说明"
|
||||
},
|
||||
"customPrompts_form_label_use_diff_viewer_title": {
|
||||
"message": "当操作设置为“替换文本”时,可以选择差异查看器。"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1230
_locales/zh_Hant/messages.json
Normal file
1230
_locales/zh_Hant/messages.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -73,14 +73,19 @@ messageInput.setMessagesArea(messagesArea);
|
|||
|
||||
switch (llm) {
|
||||
case "chatgpt_api": {
|
||||
let prefs_api = await browser.storage.sync.get({chatgpt_api_key: '', chatgpt_model: '', chatgpt_developer_messages:'', do_debug: false});
|
||||
let prefs_api = await browser.storage.sync.get({chatgpt_api_key: '', chatgpt_model: '', chatgpt_developer_messages:'', chatgpt_api_store: false, do_debug: false});
|
||||
let i18nStrings = {};
|
||||
i18nStrings["chatgpt_api_request_failed"] = browser.i18n.getMessage('chatgpt_api_request_failed');
|
||||
i18nStrings["error_connection_interrupted"] = browser.i18n.getMessage('error_connection_interrupted');
|
||||
messageInput.setModel(prefs_api.chatgpt_model);
|
||||
messagesArea.setLLMName("ChatGPT");
|
||||
worker.postMessage({ type: 'init', chatgpt_api_key: prefs_api.chatgpt_api_key, chatgpt_model: prefs_api.chatgpt_model, chatgpt_developer_messages: prefs_api.chatgpt_developer_messages, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("ChatGPT API", prefs_api.chatgpt_model), "info");
|
||||
worker.postMessage({ type: 'init', chatgpt_api_key: prefs_api.chatgpt_api_key, chatgpt_model: prefs_api.chatgpt_model, chatgpt_developer_messages: prefs_api.chatgpt_developer_messages, chatgpt_api_store: prefs_api.chatgpt_api_store, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
let additional_text_elements = [];
|
||||
additional_text_elements.push({label: 'OpenAI Store', value: (prefs_api.chatgpt_api_store ? 'Yes' : 'No')});
|
||||
if(prefs_api.chatgpt_developer_messages && prefs_api.chatgpt_developer_messages.length > 0) {
|
||||
additional_text_elements.push({label: browser.i18n.getMessage("ChatGPT_Developer_Messages"), value: prefs_api.chatgpt_developer_messages});
|
||||
}
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("ChatGPT API", prefs_api.chatgpt_model, '', '', additional_text_elements), "info");
|
||||
browser.runtime.sendMessage({command: "openai_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
}
|
||||
|
|
@ -91,19 +96,23 @@ switch (llm) {
|
|||
i18nStrings["error_connection_interrupted"] = browser.i18n.getMessage('error_connection_interrupted');
|
||||
messageInput.setModel(prefs_api.google_gemini_model);
|
||||
messagesArea.setLLMName("Google Gemini");
|
||||
let additional_text_elements = [];
|
||||
if(prefs_api.google_gemini_system_instruction && prefs_api.google_gemini_system_instruction.length > 0) {
|
||||
additional_text_elements.push({label: browser.i18n.getMessage("GoogleGemini_SystemInstruction"), value: prefs_api.google_gemini_system_instruction});
|
||||
}
|
||||
worker.postMessage({ type: 'init', google_gemini_api_key: prefs_api.google_gemini_api_key, google_gemini_model: prefs_api.google_gemini_model, google_gemini_system_instruction: prefs_api.google_gemini_system_instruction, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("Google Gemini API", prefs_api.google_gemini_model), "info");
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("Google Gemini API", prefs_api.google_gemini_model, '', '', additional_text_elements), "info");
|
||||
browser.runtime.sendMessage({command: "google_gemini_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
}
|
||||
case "ollama_api": {
|
||||
let prefs_api = await browser.storage.sync.get({ollama_host: '', ollama_model: '', ollama_num_ctx: 0, do_debug: false});
|
||||
let prefs_api = await browser.storage.sync.get({ollama_host: '', ollama_model: '', ollama_num_ctx: 0, ollama_think: false, do_debug: false});
|
||||
let i18nStrings = {};
|
||||
i18nStrings["ollama_api_request_failed"] = browser.i18n.getMessage('ollama_api_request_failed');
|
||||
i18nStrings["error_connection_interrupted"] = browser.i18n.getMessage('error_connection_interrupted');
|
||||
messageInput.setModel(prefs_api.ollama_model);
|
||||
messagesArea.setLLMName("Ollama Local");
|
||||
worker.postMessage({ type: 'init', ollama_host: prefs_api.ollama_host, ollama_model: prefs_api.ollama_model, ollama_num_ctx: prefs_api.ollama_num_ctx, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
worker.postMessage({ type: 'init', ollama_host: prefs_api.ollama_host, ollama_model: prefs_api.ollama_model, ollama_num_ctx: prefs_api.ollama_num_ctx, ollama_think: prefs_api.ollama_think, do_debug: prefs_api.do_debug, i18nStrings: i18nStrings});
|
||||
browser.runtime.sendMessage({command: "ollama_api_ready_" + call_id, window_id: (await browser.windows.getCurrent()).id});
|
||||
messagesArea.appendUserMessage(getAPIsInitMessageString("Ollama API", prefs_api.ollama_model, prefs_api.ollama_host), "info");
|
||||
break;
|
||||
|
|
@ -137,7 +146,7 @@ switch (llm) {
|
|||
//let prefs_ph = await browser.storage.sync.get({placeholders_use_default_value: false});
|
||||
|
||||
// Event listeners for worker messages
|
||||
worker.onmessage = function(event) {
|
||||
worker.onmessage = async function(event) {
|
||||
const { type, payload } = event.data;
|
||||
switch (type) {
|
||||
case 'messageSent':
|
||||
|
|
@ -148,7 +157,7 @@ worker.onmessage = function(event) {
|
|||
messageInput.setStatusMessage(browser.i18n.getMessage("apiwebchat_receiving_data") + '...');
|
||||
break;
|
||||
case 'tokensDone':
|
||||
messagesArea.handleTokensDone(promptData);
|
||||
await messagesArea.handleTokensDone(promptData);
|
||||
messageInput.enableInput();
|
||||
break;
|
||||
case 'error':
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ messagesInputStyle.textContent = `
|
|||
height: 36px;
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
border: 1px outset buttonface;
|
||||
}
|
||||
#stopButton {
|
||||
width: 44px;
|
||||
|
|
@ -296,7 +297,7 @@ class MessageInput extends HTMLElement {
|
|||
if (this.messagesAreaComponent) {
|
||||
this.messagesAreaComponent.appendUserMessage(messageContent);
|
||||
}
|
||||
this.setStatusMessage(browser.i18n.getMessage('WaitingServerReponse') + '...');
|
||||
this.setStatusMessage(browser.i18n.getMessage('WaitingServerResponse') + '...');
|
||||
this.showStatusMessage();
|
||||
this.worker.postMessage({ type: 'chatMessage', message: messageContent });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,14 +57,29 @@ messagesAreaStyle.textContent = `
|
|||
}
|
||||
.action-buttons {
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.action-buttons button {
|
||||
display: inline;
|
||||
margin: 0 10px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
border: 1px outset buttonface;
|
||||
}
|
||||
.action-buttons button.close_btn, .action-buttons button.diffv_btn {
|
||||
border-radius: 5px;
|
||||
}
|
||||
.action-buttons button.action_btn {
|
||||
margin-right: 0;
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
.action_btn_info {
|
||||
font-size: 0.6rem;
|
||||
color: gray;
|
||||
display: inline-block;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
to {
|
||||
|
|
@ -88,13 +103,20 @@ messagesAreaStyle.textContent = `
|
|||
background: lightblue;
|
||||
color: navy;
|
||||
margin-bottom: var(--margin);
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.info_obj{
|
||||
color:rgb(0, 71, 36);
|
||||
}
|
||||
.sel_info{
|
||||
font-size: 0.7rem;
|
||||
color: gray;
|
||||
margin-top: 5px;
|
||||
display: none;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* diff viewer */
|
||||
.added {
|
||||
background-color: #d4fcdc;
|
||||
|
|
@ -105,6 +127,73 @@ messagesAreaStyle.textContent = `
|
|||
display: inline;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* Split button styles */
|
||||
.split-button {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.split-button button {
|
||||
padding: 5px 0px 5px 10px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.split-button .dropdown-toggle {
|
||||
border-left: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 38px;
|
||||
margin-left:-1px;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.dropdown-toggle svg {
|
||||
fill: #555;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
position: absolute;
|
||||
top: 2.55rem;
|
||||
right:0;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
min-width: 160px;
|
||||
z-index: 1000;
|
||||
margin-top: 2px;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
border-radius: 5px;
|
||||
text-align: right;
|
||||
width: -moz-available;
|
||||
}
|
||||
|
||||
.dropdown-menu button {
|
||||
padding: 10px 14px;
|
||||
border: none;
|
||||
background-color: white;
|
||||
text-align: right;
|
||||
cursor: pointer;
|
||||
font-size: 0.6rem;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.dropdown-menu button:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.dropdown-menu.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Dark mode styles */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.added {
|
||||
background-color:rgb(0, 94, 0);
|
||||
|
|
@ -158,9 +247,9 @@ class MessagesArea extends HTMLElement {
|
|||
this.llmName = llmName;
|
||||
}
|
||||
|
||||
handleTokensDone(promptData = null) {
|
||||
async handleTokensDone(promptData = null) {
|
||||
this.flushAccumulatingMessage();
|
||||
this.addActionButtons(promptData);
|
||||
await this.addActionButtons(promptData);
|
||||
this.addDivider();
|
||||
}
|
||||
|
||||
|
|
@ -183,15 +272,16 @@ class MessagesArea extends HTMLElement {
|
|||
const messageElement = document.createElement('div');
|
||||
messageElement.classList.add('message', type);
|
||||
// Replace \n with <br> for correct HTML display
|
||||
messageElement.textContent = messageText;
|
||||
// Replace \n with <br> elements for correct HTML display
|
||||
messageElement.innerHTML = '';
|
||||
messageText.split('\n').forEach((line, idx, arr) => {
|
||||
messageElement.appendChild(document.createTextNode(line));
|
||||
if (idx < arr.length - 1) {
|
||||
messageElement.appendChild(document.createElement('br'));
|
||||
}
|
||||
});
|
||||
messageElement.appendChild(htmlStringToFragment(messageText));
|
||||
// messageElement.textContent = messageText;
|
||||
// // Replace \n with <br> elements for correct HTML display
|
||||
// messageElement.innerHTML = '';
|
||||
// messageText.split('\n').forEach((line, idx, arr) => {
|
||||
// messageElement.appendChild(document.createTextNode(line));
|
||||
// if (idx < arr.length - 1) {
|
||||
// messageElement.appendChild(document.createElement('br'));
|
||||
// }
|
||||
// });
|
||||
this.messages.appendChild(messageElement);
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
|
@ -238,31 +328,30 @@ class MessagesArea extends HTMLElement {
|
|||
this.messages.scrollTop = this.messages.scrollHeight;
|
||||
}
|
||||
|
||||
addActionButtons(promptData = null) {
|
||||
if(promptData == null) { return; }
|
||||
const actionButtons = document.createElement('div');
|
||||
actionButtons.classList.add('action-buttons');
|
||||
const selectionInfo = document.createElement('p');
|
||||
selectionInfo.textContent = browser.i18n.getMessage("apiwebchat_selection_info");
|
||||
selectionInfo.classList.add('sel_info');
|
||||
const actionButton = document.createElement('button');
|
||||
actionButton.textContent = browser.i18n.getMessage("apiwebchat_use_this_answer");
|
||||
const fullTextHTMLAtAssignment = this.fullTextHTML.trim().replace(/^"|"$/g, '').replace(/^<p>"/, '<p>').replace(/"<\/p>$/, '</p>'); // strip quotation marks
|
||||
//console.log(">>>>>>>>>>>> fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
actionButton.addEventListener('click', async () => {
|
||||
// Helper to create dropdown options
|
||||
createOption(label, callback) {
|
||||
const btn = document.createElement('button');
|
||||
btn.textContent = label;
|
||||
btn.onclick = callback;
|
||||
return btn;
|
||||
}
|
||||
|
||||
// click callcback for the "use this answer" button
|
||||
handleUseThisAnswerButtonClick(promptData, replyType, fullTextHTMLAtAssignment){
|
||||
return async () => {
|
||||
if(promptData.mailMessageId == -1) { // we are using the reply from the compose window!
|
||||
promptData.action = "2"; // replace text
|
||||
}
|
||||
let finalText = fullTextHTMLAtAssignment;
|
||||
let finalText = removeAloneBRs(fullTextHTMLAtAssignment);
|
||||
const selectedHTML = this.getCurrentSelectionHTML();
|
||||
if(selectedHTML != "") {
|
||||
finalText = selectedHTML;
|
||||
finalText = removeAloneBRs(selectedHTML);
|
||||
}
|
||||
|
||||
switch(promptData.action) {
|
||||
case "1": // do reply
|
||||
// console.log("[ThunderAI] (do reply) fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replyMessage", text: finalText, tabId: promptData.tabId, mailMessageId: promptData.mailMessageId});
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replyMessage", text: finalText, tabId: promptData.tabId, mailMessageId: promptData.mailMessageId, replyType: replyType});
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
case "2": // replace text
|
||||
|
|
@ -271,14 +360,96 @@ class MessagesArea extends HTMLElement {
|
|||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id});
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async addActionButtons(promptData = null) {
|
||||
if(promptData == null) { return; }
|
||||
const actionButtons = document.createElement('div');
|
||||
actionButtons.classList.add('action-buttons');
|
||||
// Create the main container for the "use this answer" button when replying
|
||||
const splitButton = document.createElement('div');
|
||||
splitButton.className = 'split-button';
|
||||
// selection info
|
||||
const selectionInfo = document.createElement('p');
|
||||
selectionInfo.textContent = browser.i18n.getMessage("apiwebchat_selection_info");
|
||||
selectionInfo.classList.add('sel_info');
|
||||
// main button
|
||||
const actionButton = document.createElement('button');
|
||||
actionButton.className = 'action_btn';
|
||||
const actionButton_line1 = document.createElement('span');
|
||||
actionButton_line1.textContent = browser.i18n.getMessage("apiwebchat_use_this_answer");
|
||||
actionButton.appendChild(actionButton_line1);
|
||||
splitButton.appendChild(actionButton);
|
||||
const fullTextHTMLAtAssignment = this.fullTextHTML.trim().replace(/^"|"$/g, '').replace(/^<p>"/, '<p>').replace(/"<\/p>$/, '</p>'); // strip quotation marks
|
||||
//console.log(">>>>>>>>>>>> fullTextHTMLAtAssignment: " + fullTextHTMLAtAssignment);
|
||||
let reply_type_pref = await browser.storage.sync.get({reply_type: 'reply_all'});
|
||||
if((promptData.action == "1") && (promptData.mailMessageId != -1)) {
|
||||
const actionButton_line2 = document.createElement('span');
|
||||
actionButton_line2.classList.add('action_btn_info');
|
||||
actionButton_line2.textContent = reply_type_pref.reply_type == 'reply_all' ? browser.i18n.getMessage("prefs_OptionText_reply_all") : browser.i18n.getMessage("prefs_OptionText_reply_sender");
|
||||
actionButton.appendChild(document.createElement('br'));
|
||||
actionButton.appendChild(actionButton_line2);
|
||||
// Dropdown toggle button
|
||||
const toggleBtn = document.createElement('button');
|
||||
toggleBtn.className = 'dropdown-toggle';
|
||||
toggleBtn.setAttribute('aria-label', 'Show options');
|
||||
// SVG icon
|
||||
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
svg.setAttribute('viewBox', '0 0 20 20');
|
||||
svg.setAttribute('width', '16');
|
||||
svg.setAttribute('height', '16');
|
||||
svg.setAttribute('fill', 'currentColor');
|
||||
svg.setAttribute('stroke-width', '2');
|
||||
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||
path.setAttribute('d', 'M19 9l-7 7-7-7');
|
||||
svg.appendChild(path);
|
||||
toggleBtn.appendChild(svg);
|
||||
splitButton.appendChild(toggleBtn);
|
||||
// Dropdown menu
|
||||
const dropdown = document.createElement('div');
|
||||
dropdown.className = 'dropdown-menu';
|
||||
dropdown.id = 'dropdown';
|
||||
// Add options
|
||||
dropdown.appendChild(this.createOption(
|
||||
reply_type_pref.reply_type == 'reply_all' ? browser.i18n.getMessage("prefs_OptionText_reply_sender") : browser.i18n.getMessage("prefs_OptionText_reply_all"),
|
||||
this.handleUseThisAnswerButtonClick(promptData, reply_type_pref.reply_type == 'reply_all' ? 'reply_sender' : 'reply_all', fullTextHTMLAtAssignment))
|
||||
);
|
||||
splitButton.appendChild(dropdown);
|
||||
let dropdownJustOpened = false;
|
||||
// Toggle function
|
||||
toggleBtn.onclick = () => {
|
||||
dropdownJustOpened = true;
|
||||
dropdown.classList.toggle('show');
|
||||
};
|
||||
// Close on outside click
|
||||
window.addEventListener('click', (e) => {
|
||||
// Delay the execution to allow other handlers (like toggle) to run first
|
||||
if (dropdownJustOpened) {
|
||||
dropdownJustOpened = false;
|
||||
return; // Skip this click because it's the one that opened the menu
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (!splitButton.contains(e.target)) {
|
||||
dropdown.classList.remove('show');
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
}else{
|
||||
actionButton.style.paddingRight = "10px";
|
||||
actionButton.style.borderTopRightRadius = "5px";
|
||||
actionButton.style.borderBottomRightRadius = "5px";
|
||||
actionButton.style.marginRight = "10px";
|
||||
}
|
||||
actionButton.addEventListener('click', this.handleUseThisAnswerButtonClick(promptData,reply_type_pref.reply_type, fullTextHTMLAtAssignment));
|
||||
const closeButton = document.createElement('button');
|
||||
closeButton.textContent = browser.i18n.getMessage("chatgpt_win_close");
|
||||
closeButton.classList.add('close_btn');
|
||||
closeButton.addEventListener('click', async () => {
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: (await browser.windows.getCurrent()).id}); // close window
|
||||
});
|
||||
if(promptData.action != 0) {
|
||||
actionButtons.appendChild(actionButton);
|
||||
actionButtons.appendChild(splitButton);
|
||||
selectionInfo.style.display = "block"; // show selection info
|
||||
}
|
||||
|
||||
|
|
@ -286,6 +457,7 @@ class MessagesArea extends HTMLElement {
|
|||
if(promptData.prompt_info?.use_diff_viewer == "1") {
|
||||
const diffvButton = document.createElement('button');
|
||||
diffvButton.textContent = browser.i18n.getMessage("btn_show_differences");
|
||||
diffvButton.classList.add('diffv_btn');
|
||||
diffvButton.addEventListener('click', async () => {
|
||||
let strippedText = fullTextHTMLAtAssignment.replace(/<\/?[^>]+(>|$)/g, "");
|
||||
let originalText = promptData.prompt_info?.selection_text;
|
||||
|
|
@ -299,8 +471,8 @@ class MessagesArea extends HTMLElement {
|
|||
}
|
||||
|
||||
actionButtons.appendChild(closeButton);
|
||||
actionButtons.appendChild(selectionInfo);
|
||||
this.messages.appendChild(actionButtons);
|
||||
this.messages.appendChild(selectionInfo);
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
||||
|
|
@ -318,22 +490,29 @@ class MessagesArea extends HTMLElement {
|
|||
|
||||
// Iterate over each part of the diff to create the HTML output
|
||||
wordDiff.forEach(part => {
|
||||
const diffElement = document.createElement("span");
|
||||
|
||||
// Apply a different class depending on whether the word is added, removed, or unchanged
|
||||
if (part.added) {
|
||||
diffElement.className = "added";
|
||||
diffElement.textContent = part.value;
|
||||
} else if (part.removed) {
|
||||
diffElement.className = "removed";
|
||||
diffElement.textContent = part.value;
|
||||
} else {
|
||||
diffElement.textContent = part.value;
|
||||
// Split part.value by <br> (handling <br>, <br/>, <br />)
|
||||
const brRegex = /(<br\s*\/?>)/gi;
|
||||
const segments = part.value.split(brRegex);
|
||||
|
||||
segments.forEach(segment => {
|
||||
if (segment.match(brRegex)) {
|
||||
// It's a <br>, add a real <br> element
|
||||
messageElement.appendChild(document.createElement("br"));
|
||||
} else if (segment.length > 0) {
|
||||
const diffElement = document.createElement("span");
|
||||
if (part.added) {
|
||||
diffElement.className = "added";
|
||||
diffElement.textContent = segment;
|
||||
} else if (part.removed) {
|
||||
diffElement.className = "removed";
|
||||
diffElement.textContent = segment;
|
||||
} else {
|
||||
diffElement.textContent = segment;
|
||||
}
|
||||
messageElement.appendChild(diffElement);
|
||||
}
|
||||
|
||||
// Add the element to the container
|
||||
messageElement.appendChild(diffElement);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const header = document.createElement('h2');
|
||||
header.textContent = browser.i18n.getMessage("chatgpt_win_diff_title");
|
||||
|
|
@ -354,9 +533,11 @@ class MessagesArea extends HTMLElement {
|
|||
|
||||
// Convert Markdown to DOM nodes using the markdown-it library
|
||||
const md = window.markdownit();
|
||||
const html = md.render(fullText);
|
||||
const html = convertNewlinesToBr(md.render(fullText));
|
||||
|
||||
this.fullTextHTML += html;
|
||||
|
||||
// console.log(">>>>>>>>>>>>>>>> flushAccumulatingMessage this.fullTextHTML: " + this.fullTextHTML);
|
||||
|
||||
// Create a new DOM parser
|
||||
const parser = new DOMParser();
|
||||
|
|
@ -390,4 +571,46 @@ class MessagesArea extends HTMLElement {
|
|||
|
||||
}
|
||||
|
||||
customElements.define('messages-area', MessagesArea);
|
||||
customElements.define('messages-area', MessagesArea);
|
||||
|
||||
|
||||
function htmlStringToFragment(htmlString) {
|
||||
// console.log(">>>>>>>>>>>>>>>> htmlStringToFragment htmlString: " + htmlString);
|
||||
const normalizedHtml = htmlString.replace(/\n/g, '<br>');
|
||||
// console.log(">>>>>>>>>>>>>>>> htmlStringToFragment normalizedHtml: " + normalizedHtml);
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(normalizedHtml, 'text/html');
|
||||
const fragment = document.createDocumentFragment();
|
||||
Array.from(doc.body.childNodes).forEach(node => fragment.appendChild(node));
|
||||
return fragment;
|
||||
}
|
||||
|
||||
function convertNewlinesToBr(text) {
|
||||
return text.replace(/\n/g, '<br>');
|
||||
}
|
||||
|
||||
function removeAloneBRs(htmlString) {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(htmlString, 'text/html');
|
||||
|
||||
const brElements = Array.from(doc.querySelectorAll('br'));
|
||||
|
||||
brElements.forEach(br => {
|
||||
let current = br;
|
||||
let isInsideP = false;
|
||||
|
||||
while (current.parentElement) {
|
||||
if (current.parentElement.tagName.toLowerCase() === 'p') {
|
||||
isInsideP = true;
|
||||
break;
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
|
||||
if (!isInsideP) {
|
||||
br.remove();
|
||||
}
|
||||
});
|
||||
|
||||
return doc.body.innerHTML;
|
||||
}
|
||||
|
|
@ -22,12 +22,14 @@ export class Ollama {
|
|||
model = '';
|
||||
stream = false;
|
||||
num_ctx = 0;
|
||||
think = false;
|
||||
|
||||
constructor(host, model, stream = false, num_ctx = 0) {
|
||||
constructor(host, model, stream = false, num_ctx = 0, think = false) {
|
||||
this.host = host.trim().replace(/\/+$/, "");
|
||||
this.model = model;
|
||||
this.stream = stream;
|
||||
this.num_ctx = num_ctx;
|
||||
this.think = think;
|
||||
}
|
||||
|
||||
fetchModels = async () => {
|
||||
|
|
@ -80,7 +82,8 @@ export class Ollama {
|
|||
model: this.model,
|
||||
messages: messages,
|
||||
stream: this.stream,
|
||||
...(this.num_ctx > 0 ? { options: { num_ctx: parseInt(this.num_ctx) } } : {})
|
||||
think: this.think,
|
||||
...(this.num_ctx > 0 ? { options: { num_ctx: parseInt(this.num_ctx) } } : {}),
|
||||
}),
|
||||
});
|
||||
return response;
|
||||
|
|
|
|||
|
|
@ -25,12 +25,14 @@ export class OpenAI {
|
|||
model = '';
|
||||
developer_messages = '';
|
||||
stream = false;
|
||||
store = false;
|
||||
|
||||
constructor(apiKey, model, developer_messages, stream) {
|
||||
constructor(apiKey, model, developer_messages, stream, store) {
|
||||
this.apiKey = apiKey;
|
||||
this.model = model;
|
||||
this.developer_messages = developer_messages;
|
||||
this.stream = stream;
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -89,6 +91,7 @@ export class OpenAI {
|
|||
model: this.model,
|
||||
messages: messages,
|
||||
stream: this.stream,
|
||||
store: this.store,
|
||||
...(maxTokens > 0 ? { 'max_tokens': parseInt(maxTokens) } : {})
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -41,6 +41,11 @@ export class OpenAIComp {
|
|||
"Content-Type": "application/json",
|
||||
};
|
||||
if(this.apiKey !== '') curr_headers["Authorization"] = "Bearer "+ this.apiKey;
|
||||
|
||||
if(this.host.includes('openrouter.ai')) {
|
||||
curr_headers['HTTP-Referer'] = 'https://micz.it/thunderbird-addon-thunderai/';
|
||||
curr_headers['X-Title'] = 'ThunderAI';
|
||||
}
|
||||
|
||||
const response = await fetch(this.host + (this.use_v1 ? "/v1" : "") + "/models", {
|
||||
method: "GET",
|
||||
|
|
|
|||
|
|
@ -34,16 +34,30 @@ export const openAICompConfigs = [
|
|||
},
|
||||
{
|
||||
id: 'grok',
|
||||
name: 'Grok AI API',
|
||||
chat_name: 'Grok AI',
|
||||
name: 'Grok API',
|
||||
chat_name: 'Grok',
|
||||
host: 'https://api.x.ai',
|
||||
use_v1: true,
|
||||
},
|
||||
{
|
||||
id: 'mistral',
|
||||
name: 'Mistral AI API',
|
||||
chat_name: 'Mistral AI',
|
||||
name: 'Mistral API',
|
||||
chat_name: 'Mistral',
|
||||
host: 'https://api.mistral.ai',
|
||||
use_v1: true,
|
||||
},
|
||||
{
|
||||
id: 'openrouter',
|
||||
name: 'OpenRouter API',
|
||||
chat_name: 'OpenRouter',
|
||||
host: 'https://openrouter.ai/api',
|
||||
use_v1: true,
|
||||
},
|
||||
{
|
||||
id: 'perplexity',
|
||||
name: 'Perplexity API',
|
||||
chat_name: 'Perplexity',
|
||||
host: 'https://api.perplexity.ai',
|
||||
use_v1: true,
|
||||
},
|
||||
];
|
||||
|
|
@ -26,4 +26,15 @@ export async function addTags_getExclusionList() {
|
|||
|
||||
export function addTags_setExclusionList(add_tags_exclusions) {
|
||||
browser.storage.local.set({add_tags_exclusions: add_tags_exclusions});
|
||||
}
|
||||
|
||||
export function checkExcludedTag(tag, excluded_word, exact_match = false) {
|
||||
// Check if the tag is in the exclusion list
|
||||
if (excluded_word === '') {
|
||||
return false; // No exclusion word, so no exclusion
|
||||
}
|
||||
if(exact_match) {
|
||||
return tag.toLowerCase() === excluded_word.toLowerCase();
|
||||
}
|
||||
return tag.toLowerCase().includes(excluded_word.toLowerCase());
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ function chatgpt_getRegenerateButton() {
|
|||
function chatpgt_scrollToBottom () {
|
||||
try {
|
||||
//document.querySelector('button[class*="cursor"][class*="bottom"]').click();
|
||||
document.querySelector('path[d^="M9.33468 3.33333C9.33468 2.96617"]')?.parentNode?.parentNode?.click();
|
||||
document.querySelector('path[d^="M9.33468 3.33333C9.33468"]')?.parentNode?.parentNode?.click();
|
||||
}
|
||||
catch (err) { console.error('[ThunderAI] ', err); }
|
||||
}
|
||||
|
|
@ -130,6 +130,8 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
|
|||
style.textContent += "#mzta-diff_content{overflow-y:scroll;text-align:justify;width:100%;height:22.5em;}";
|
||||
style.textContent += "#mzta-diff span.added{background-color: rgb(0, 94, 0);display:inline;} #mzta-diff span.removed{background-color: rgb(90, 0, 0);display:inline;text-decoration:line-through;}";
|
||||
style.textContent += "#mzta-btn_close_diff{position:absolute;bottom:10px;left:50%;transform:translateX(-50%);}";
|
||||
style.textContent += "#mzta-btn_change_reply_type{padding-left:4px;padding-right:10px;margin-left:0px;border-bottom-left-radius:0px;border-top-left-radius:0px;height:2.7em;}";
|
||||
style.textContent += ".mzta-btn_reply{padding-right:4px;margin-right:0px;border-bottom-right-radius:0px;border-top-right-radius:0px;}";
|
||||
|
||||
// Add <style> to the page's <head>
|
||||
document.head.appendChild(style);
|
||||
|
|
@ -203,18 +205,68 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
|
|||
btn_ok.onclick = async function() {
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: mztaWinId});
|
||||
};
|
||||
fixedDiv.appendChild(btn_ok);
|
||||
break;
|
||||
case "1": // do reply
|
||||
btn_ok.disabled = true;
|
||||
btn_ok.textContent = browser.i18n.getMessage("chatgpt_win_get_answer");
|
||||
btn_ok.onclick = async function() {
|
||||
disableButton(btn_ok);
|
||||
const btn_ok_line1 = document.createElement('span');
|
||||
btn_ok_line1.textContent = browser.i18n.getMessage("chatgpt_win_get_answer");
|
||||
const btn_ok_line2 = document.createElement('span');
|
||||
btn_ok_line2.classList.add('action_btn_info');
|
||||
btn_ok_line2.textContent = mztaReplyType == 'reply_all' ? browser.i18n.getMessage("prefs_OptionText_reply_all") : browser.i18n.getMessage("prefs_OptionText_reply_sender");
|
||||
btn_ok_line1.style.display = 'block';
|
||||
btn_ok_line1.style.margin = '0';
|
||||
btn_ok_line1.style.padding = '0';
|
||||
btn_ok_line1.style.lineHeight = '1';
|
||||
btn_ok_line2.style.display = 'block';
|
||||
btn_ok_line2.style.margin = '0';
|
||||
btn_ok_line2.style.padding = '0';
|
||||
btn_ok_line2.style.lineHeight = '1';
|
||||
btn_ok_line2.style.fontSize = '0.7em';
|
||||
btn_ok.appendChild(btn_ok_line1);
|
||||
//btn_ok.appendChild(document.createElement('br'));
|
||||
btn_ok.appendChild(btn_ok_line2);
|
||||
btn_ok.setAttribute('data-reply-type', mztaReplyType);
|
||||
btn_ok.addEventListener('click', async function() {
|
||||
const response = getSelectedHtml();
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replyMessage", text: response, tabId: tabId, mailMessageId: mailMessageId});
|
||||
const currentReplyType = btn_ok.getAttribute('data-reply-type');
|
||||
// console.log(">>>>>>>>>> btn_ok reply type: " + JSON.stringify(currentReplyType));
|
||||
await browser.runtime.sendMessage({command: "chatgpt_replyMessage", text: response, tabId: tabId, mailMessageId: mailMessageId, replyType: currentReplyType});
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: mztaWinId});
|
||||
};
|
||||
});
|
||||
btn_ok.classList.add('mzta-btn_reply');
|
||||
// change reply type button
|
||||
var btn_change_reply_type = document.createElement('button');
|
||||
disableButton(btn_change_reply_type);
|
||||
btn_change_reply_type.id = 'mzta-btn_change_reply_type';
|
||||
btn_change_reply_type.classList.add('mzta-btn');
|
||||
btn_change_reply_type.title = browser.i18n.getMessage("chatgpt_win_change_reply_type");
|
||||
// Create SVG element
|
||||
let currentIcon = createReplyToAllIcon();
|
||||
// Append SVG to button
|
||||
btn_change_reply_type.appendChild(currentIcon);
|
||||
btn_change_reply_type.addEventListener('click', function() {
|
||||
// console.log('>>>>>>>>>> change reply type clicked');
|
||||
btn_change_reply_type.removeChild(currentIcon);
|
||||
if(mztaReplyType == 'reply_all'){
|
||||
mztaReplyType = 'reply_sender';
|
||||
currentIcon = createReplyToSenderIcon();
|
||||
btn_change_reply_type.appendChild(currentIcon);
|
||||
btn_ok_line2.textContent = browser.i18n.getMessage("prefs_OptionText_reply_sender");
|
||||
}else{
|
||||
mztaReplyType = 'reply_all';
|
||||
currentIcon = createReplyToAllIcon();
|
||||
btn_change_reply_type.appendChild(currentIcon);
|
||||
btn_ok_line2.textContent = browser.i18n.getMessage("prefs_OptionText_reply_all");
|
||||
}
|
||||
btn_ok.setAttribute('data-reply-type', mztaReplyType);
|
||||
});
|
||||
fixedDiv.appendChild(btn_ok);
|
||||
fixedDiv.appendChild(btn_change_reply_type);
|
||||
btn_change_reply_type.style.display = 'none';
|
||||
break;
|
||||
case "2": // replace text
|
||||
btn_ok.disabled = true;
|
||||
disableButton(btn_ok);
|
||||
btn_ok.textContent = browser.i18n.getMessage("chatgpt_win_get_answer");
|
||||
btn_ok.onclick = async function() {
|
||||
const response = getSelectedHtml();
|
||||
|
|
@ -222,10 +274,10 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
|
|||
await browser.runtime.sendMessage({command: "chatgpt_replaceSelectedText", text: response, tabId: tabId, mailMessageId: mailMessageId});
|
||||
browser.runtime.sendMessage({command: "chatgpt_close", window_id: mztaWinId});
|
||||
};
|
||||
fixedDiv.appendChild(btn_ok);
|
||||
break;
|
||||
}
|
||||
btn_ok.style.display = 'none';
|
||||
fixedDiv.appendChild(btn_ok);
|
||||
|
||||
if(mztaUseDiffViewer == '1'){
|
||||
// diff overlay div
|
||||
|
|
@ -262,29 +314,36 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
|
|||
btn_diff.classList.add('mzta-btn');
|
||||
btn_diff.textContent = browser.i18n.getMessage('btn_show_differences');
|
||||
btn_diff.style.display = 'none';
|
||||
btn_diff.disabled = true;
|
||||
disableButton(btn_diff);
|
||||
btn_diff.onclick = async function() {
|
||||
diffContent.innerHTML = '';
|
||||
const response = getSelectedHtml();
|
||||
const wordDiff = Diff.diffWords(mztaOriginalText, response.replace(/<\\/?[^>]+(>|$)/g, ''));
|
||||
wordDiff.forEach(part => {
|
||||
const diffElement = document.createElement('span');
|
||||
|
||||
// Apply a different class depending on whether the word is added, removed, or unchanged
|
||||
if (part.added) {
|
||||
diffElement.className = 'added';
|
||||
diffElement.textContent = part.value;
|
||||
} else if (part.removed) {
|
||||
diffElement.className = 'removed';
|
||||
diffElement.textContent = part.value;
|
||||
} else {
|
||||
diffElement.textContent = part.value;
|
||||
// Split part.value by <br> (handling <br>, <br/>, <br />)
|
||||
const brRegex = /(<br\s*\\/?>)/gi;
|
||||
const segments = part.value.split(brRegex);
|
||||
|
||||
segments.forEach(segment => {
|
||||
if (segment.match(brRegex)) {
|
||||
// It's a <br>, add a real <br> element
|
||||
diffContent.appendChild(document.createElement("br"));
|
||||
} else if (segment.length > 0) {
|
||||
const diffElement = document.createElement("span");
|
||||
if (part.added) {
|
||||
diffElement.className = "added";
|
||||
diffElement.textContent = segment;
|
||||
} else if (part.removed) {
|
||||
diffElement.className = "removed";
|
||||
diffElement.textContent = segment;
|
||||
} else {
|
||||
diffElement.textContent = segment;
|
||||
}
|
||||
diffContent.appendChild(diffElement);
|
||||
}
|
||||
|
||||
// Add the element to the container
|
||||
diffContent.appendChild(diffElement);
|
||||
diffOverlay.style.display = 'block';
|
||||
});
|
||||
});
|
||||
});
|
||||
diffOverlay.style.display = 'block';
|
||||
};
|
||||
fixedDiv.appendChild(btn_diff);
|
||||
}
|
||||
|
|
@ -315,6 +374,44 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
|
|||
document.body.insertBefore(fixedDiv, document.body.firstChild);
|
||||
}
|
||||
|
||||
// Create SVG icons as functions
|
||||
function createReplyToSenderIcon() {
|
||||
const svgNS = 'http://www.w3.org/2000/svg';
|
||||
const svg = document.createElementNS(svgNS, 'svg');
|
||||
svg.setAttribute('xmlns', svgNS);
|
||||
svg.setAttribute('viewBox', '0 0 24 24');
|
||||
svg.setAttribute('width', '24');
|
||||
svg.setAttribute('height', '24');
|
||||
svg.setAttribute('fill', 'currentColor');
|
||||
const path1 = document.createElementNS(svgNS, 'path');
|
||||
path1.setAttribute('d', 'M0 0h24v24H0z');
|
||||
path1.setAttribute('fill', 'none');
|
||||
const path2 = document.createElementNS(svgNS, 'path');
|
||||
path2.setAttribute('d', 'M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z');
|
||||
svg.appendChild(path1);
|
||||
svg.appendChild(path2);
|
||||
return svg;
|
||||
}
|
||||
|
||||
|
||||
function createReplyToAllIcon() {
|
||||
const svgNS = 'http://www.w3.org/2000/svg';
|
||||
const svg = document.createElementNS(svgNS, 'svg');
|
||||
svg.setAttribute('xmlns', svgNS);
|
||||
svg.setAttribute('viewBox', '0 0 24 24');
|
||||
svg.setAttribute('width', '24');
|
||||
svg.setAttribute('height', '24');
|
||||
svg.setAttribute('fill', 'currentColor');
|
||||
const path1 = document.createElementNS(svgNS, 'path');
|
||||
path1.setAttribute('d', 'M0 0h24v24H0z');
|
||||
path1.setAttribute('fill', 'none');
|
||||
const path2 = document.createElementNS(svgNS, 'path');
|
||||
path2.setAttribute('d', 'M7 8V5l-7 7 7 7v-3l-4-4 4-4zm6 1V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z');
|
||||
svg.appendChild(path1);
|
||||
svg.appendChild(path2);
|
||||
return svg;
|
||||
}
|
||||
|
||||
function customTextBtnClick(args) {
|
||||
const customText = document.getElementById('mzta-custom_textarea').value;
|
||||
args.customBtn.disabled = true;
|
||||
|
|
@ -379,6 +476,9 @@ function operation_done(){
|
|||
}
|
||||
curr_msg.style.display = 'block';
|
||||
document.getElementById('mzta-btn_ok').style.display = 'inline';
|
||||
if(current_action == '1'){
|
||||
document.getElementById('mzta-btn_change_reply_type').style.display = 'inline';
|
||||
}
|
||||
if(mztaUseDiffViewer == '1'){
|
||||
document.getElementById('mzta-btn_diff').style.display = 'inline';
|
||||
}
|
||||
|
|
@ -550,23 +650,37 @@ document.addEventListener("selectionchange", function() {
|
|||
let btn_ok = document.getElementById('mzta-btn_ok');
|
||||
let btn_diff = document.getElementById('mzta-btn_diff');
|
||||
if (isSomethingSelected()) {
|
||||
btn_ok.disabled = false;
|
||||
btn_ok.classList.remove('btn_disabled');
|
||||
enableButton(btn_ok);
|
||||
if(current_action == '1'){
|
||||
let btn_reply_type = document.getElementById('mzta-btn_change_reply_type');
|
||||
enableButton(btn_reply_type);
|
||||
}
|
||||
if(mztaUseDiffViewer == '1'){
|
||||
btn_diff.disabled = false;
|
||||
btn_diff.classList.remove('btn_disabled');
|
||||
enableButton(btn_diff);
|
||||
}
|
||||
} else {
|
||||
btn_ok.disabled = true;
|
||||
btn_ok.classList.add('btn_disabled');
|
||||
disableButton(btn_ok);
|
||||
if(current_action == '1'){
|
||||
let btn_reply_type = document.getElementById('mzta-btn_change_reply_type');
|
||||
disableButton(btn_reply_type);
|
||||
}
|
||||
if(mztaUseDiffViewer == '1'){
|
||||
btn_diff.disabled = true;
|
||||
btn_diff.classList.add('btn_disabled');
|
||||
disableButton(btn_diff);
|
||||
}
|
||||
}
|
||||
}, 300); // Delay in milliseconds
|
||||
});
|
||||
|
||||
function enableButton(btn){
|
||||
btn.disabled = false;
|
||||
btn.classList.remove('btn_disabled');
|
||||
}
|
||||
|
||||
function disableButton(btn){
|
||||
btn.disabled = true;
|
||||
btn.classList.add('btn_disabled');
|
||||
}
|
||||
|
||||
function selectContentOnMouseDown(event) {
|
||||
// Reset the dragging flag when the mouse is pressed down
|
||||
isDragging = false;
|
||||
|
|
|
|||
|
|
@ -335,6 +335,17 @@ switch (message.command) {
|
|||
function addTags_setExclusionList(add_tags_exclusions) {
|
||||
browser.storage.local.set({add_tags_exclusions: add_tags_exclusions});
|
||||
}
|
||||
|
||||
function checkExcludedTag(tag, excluded_word, exact_match = false) {
|
||||
// Check if the tag is in the exclusion list
|
||||
if (excluded_word === '') {
|
||||
return false; // No exclusion word, so no exclusion
|
||||
}
|
||||
if(exact_match) {
|
||||
return tag.toLowerCase() === excluded_word.toLowerCase();
|
||||
}
|
||||
return tag.toLowerCase().includes(excluded_word.toLowerCase());
|
||||
}
|
||||
// ===================================================================================
|
||||
|
||||
// Create and append the styles
|
||||
|
|
@ -434,7 +445,7 @@ switch (message.command) {
|
|||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
async function createDialog(inputString, onSubmit) {
|
||||
async function createDialog(inputTags, onSubmit) {
|
||||
// Create the dialog
|
||||
const tags_dialog = document.createElement('dialog');
|
||||
tags_dialog.className = 'mzta_dialog';
|
||||
|
|
@ -450,8 +461,8 @@ switch (message.command) {
|
|||
|
||||
let no_submit = false;
|
||||
|
||||
// Parse the input string into labels
|
||||
const words = inputString.split(',').map(word => word.trim()).filter(word => word !== '');
|
||||
// Fix the input array
|
||||
const words = inputTags.map(word => word.trim()).filter(word => word !== '');
|
||||
|
||||
// console.log(">>>>>>>>>>>>> words: " + JSON.stringify(words));
|
||||
|
||||
|
|
@ -463,7 +474,7 @@ switch (message.command) {
|
|||
no_submit = true;
|
||||
}
|
||||
|
||||
let prefs_tags = await browser.storage.sync.get({add_tags_hide_exclusions: false});
|
||||
let prefs_tags = await browser.storage.sync.get({add_tags_hide_exclusions: false, add_tags_exclusions_exact_match: false});
|
||||
let add_tags_exclusions_list = await addTags_getExclusionList();
|
||||
|
||||
// console.log(">>>>>>>>>>>>> add_tags_exclusions_list: " + JSON.stringify(add_tags_exclusions_list));
|
||||
|
|
@ -472,7 +483,7 @@ switch (message.command) {
|
|||
.filter(word => word !== '')
|
||||
.map(word => {
|
||||
const isExcluded = add_tags_exclusions_list.some(exclusion =>
|
||||
word.toLowerCase().includes(exclusion.toLowerCase())
|
||||
checkExcludedTag(word, exclusion, prefs_tags.add_tags_exclusions_exact_match)
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// Some original methods are derived from https://github.com/ali-raheem/Aify/blob/cfadf52f576b7be3720b5b73af7c8d3129c054da/plugin/html/actions.js
|
||||
|
||||
import { getPrompts } from './mzta-prompts.js';
|
||||
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject, getTagsList, extractJsonObject } from './mzta-utils.js'
|
||||
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject, getTagsList, extractJsonObject, convertNewlinesToBr } from './mzta-utils.js'
|
||||
import { taPromptUtils } from './mzta-utils-prompt.js';
|
||||
import { taLogger } from './mzta-logger.js';
|
||||
import { placeholdersUtils } from './mzta-placeholders.js';
|
||||
|
|
@ -81,12 +81,12 @@ export class mzta_Menus {
|
|||
const getMailBody = async (tabs, do_autoselect = false) => {
|
||||
//const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
return {tabId: tabs[0].id,
|
||||
selection: await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedText" }),
|
||||
selection_html: await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedHtml" }),
|
||||
text: await browser.tabs.sendMessage(tabs[0].id, { command: "getTextOnly" }),
|
||||
html: await browser.tabs.sendMessage(tabs[0].id, { command: "getFullHtml" }),
|
||||
only_typed_text: await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyTypedText", do_autoselect: do_autoselect }),
|
||||
only_quoted_text: await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyQuotedText" })
|
||||
selection: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedText" })),
|
||||
selection_html: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedHtml" })),
|
||||
text: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getTextOnly" })),
|
||||
html: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getFullHtml" })),
|
||||
only_typed_text: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyTypedText", do_autoselect: do_autoselect })),
|
||||
only_quoted_text: convertNewlinesToBr(await browser.tabs.sendMessage(tabs[0].id, { command: "getOnlyQuotedText" }))
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ export class mzta_Menus {
|
|||
taWorkingStatus.startWorking();
|
||||
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
const msg_text = await getMailBody(tabs, placeholdersUtils.hasPlaceholder(curr_prompt.text,'mail_typed_text'));
|
||||
|
||||
// console.log(">>>>>>>>>>>>> msg_text: " + JSON.stringify(msg_text));
|
||||
//check if a selection is needed
|
||||
if(String(curr_prompt.need_selected) == "1" && (msg_text.selection==='')){
|
||||
//A selection is needed, but nothing is selected!
|
||||
|
|
@ -168,7 +168,7 @@ export class mzta_Menus {
|
|||
if(curr_prompt.is_special == '1'){ // Special prompts
|
||||
switch(curr_prompt.id){
|
||||
case 'prompt_add_tags': { // Add tags to the email
|
||||
let tags_current_email = '';
|
||||
let tags_current_email = [];
|
||||
let prefs_at = await browser.storage.sync.get({add_tags_maxnum: 3, connection_type: '', add_tags_force_lang: true, default_chatgpt_lang: '', do_debug: false});
|
||||
if((prefs_at.connection_type === '')||(prefs_at.connection_type === null)||(prefs_at.connection_type === undefined)||(prefs_at.connection_type === 'chatgpt_web')){
|
||||
console.error("[ThunderAI | AddTags] Invalid connection type: " + prefs_at.connection_type);
|
||||
|
|
@ -183,7 +183,7 @@ export class mzta_Menus {
|
|||
let cmd_addTags = new mzta_specialCommand(fullPrompt,prefs_at.connection_type,prefs_at.do_debug);
|
||||
await cmd_addTags.initWorker();
|
||||
try{
|
||||
tags_current_email = (await cmd_addTags.sendPrompt()).trim();
|
||||
tags_current_email = taPromptUtils.getTagsFromResponse(await cmd_addTags.sendPrompt());
|
||||
// console.log(">>>>>>>>>>> tags_current_email: " + tags_current_email);
|
||||
}catch(err){
|
||||
console.error("[ThunderAI] Error getting tags: ", err);
|
||||
|
|
@ -191,7 +191,7 @@ export class mzta_Menus {
|
|||
taWorkingStatus.stopWorking();
|
||||
return {ok:'0'};
|
||||
}
|
||||
this.logger.log("tags_current_email: " + tags_current_email);
|
||||
this.logger.log("tags_current_email: " + JSON.stringify(tags_current_email));
|
||||
this.logger.log("tags_full_list: " + JSON.stringify(tags_full_list));
|
||||
browser.tabs.sendMessage(tabs[0].id, {command: "getTags", tags: tags_current_email, messageId: curr_message.id});
|
||||
taWorkingStatus.stopWorking();
|
||||
|
|
@ -350,6 +350,7 @@ export class mzta_Menus {
|
|||
break;
|
||||
}
|
||||
}else{ // Classic prompts for the API webchat
|
||||
this.logger.log("fullPrompt: " + fullPrompt);
|
||||
this.openChatGPT(fullPrompt, curr_prompt.action, tabs[0].id, curr_prompt.name, curr_prompt.need_custom_text, curr_prompt);
|
||||
taWorkingStatus.stopWorking();
|
||||
return {ok:'1'};
|
||||
|
|
|
|||
|
|
@ -20,16 +20,26 @@
|
|||
|
||||
================ BASE PROPERTIES
|
||||
|
||||
Types (type attribute):
|
||||
id: unique identifier, used to identify the placeholder
|
||||
name: name of the placeholder, used for display purposes
|
||||
default_value: default value of the placeholder, used when the placeholder is not replaced (only for default placeholders)
|
||||
|
||||
type attribute:
|
||||
0: always show (when composing a part of the text must be selected if need_selected = 1)
|
||||
1: show when reading an email
|
||||
2: show when composing a mail (a part of the text must be selected if need_selected = 1)
|
||||
|
||||
is_default attribute:
|
||||
0: Custom placeholder
|
||||
1: Default placeholder (not editable, cannot be deleted)
|
||||
|
||||
================ USER PROPERTIES
|
||||
Enabled (enabled attribute):
|
||||
enabled attribute:
|
||||
0: Disabled
|
||||
1: Enabled
|
||||
|
||||
text: text of the placeholder (only for custom placeholders)
|
||||
|
||||
*/
|
||||
|
||||
import { transformTagsLabels, getCurrentIdentity } from './mzta-utils.js';
|
||||
|
|
@ -41,6 +51,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'mail_html_body',
|
||||
|
|
@ -48,6 +59,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'mail_typed_text',
|
||||
|
|
@ -55,6 +67,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 2,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'mail_quoted_text',
|
||||
|
|
@ -62,6 +75,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 2,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'mail_subject',
|
||||
|
|
@ -69,6 +83,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'mail_folder_name',
|
||||
|
|
@ -76,6 +91,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 1,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'mail_folder_path',
|
||||
|
|
@ -83,6 +99,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 1,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'selected_text',
|
||||
|
|
@ -90,6 +107,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'selected_html',
|
||||
|
|
@ -97,6 +115,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'additional_text',
|
||||
|
|
@ -104,6 +123,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'junk_score',
|
||||
|
|
@ -111,6 +131,7 @@ const defaultPlaceholders = [
|
|||
default_value: "0",
|
||||
type: 1,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'recipients',
|
||||
|
|
@ -118,6 +139,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'cc_list',
|
||||
|
|
@ -125,6 +147,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'author',
|
||||
|
|
@ -132,6 +155,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'mail_datetime',
|
||||
|
|
@ -139,6 +163,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 1,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'current_datetime',
|
||||
|
|
@ -146,6 +171,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'account_email_address',
|
||||
|
|
@ -153,6 +179,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'tags_current_email',
|
||||
|
|
@ -160,6 +187,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'tags_full_list',
|
||||
|
|
@ -167,6 +195,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'thunderai_def_sign',
|
||||
|
|
@ -174,6 +203,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'thunderai_def_lang',
|
||||
|
|
@ -181,6 +211,7 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
{
|
||||
id: 'empty',
|
||||
|
|
@ -188,12 +219,13 @@ const defaultPlaceholders = [
|
|||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
enabled: 1,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
export async function getPlaceholders(onlyEnabled = false){
|
||||
const _defaultPlaceholders = await getDefaultPlaceholders_withProps();
|
||||
const _defaultPlaceholders = await getDefaultPlaceholders();
|
||||
// console.log('>>>>>>>>>>>> getPlaceholders _defaultPlaceholders: ' + JSON.stringify(_defaultPlaceholders));
|
||||
const customPlaceholders = await getCustomPlaceholders();
|
||||
// console.log('>>>>>>>>>>>> getPlaceholders customPlaceholders: ' + JSON.stringify(customPlaceholders));
|
||||
|
|
@ -207,32 +239,14 @@ export async function getPlaceholders(onlyEnabled = false){
|
|||
return output;
|
||||
}
|
||||
|
||||
async function getDefaultPlaceholders_withProps() {
|
||||
let prefs = await browser.storage.local.get({_default_placeholders_properties: null});
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps prefs: ' + JSON.stringify(prefs));
|
||||
//let defaultPlaceholders_prop = [...defaultPlaceholders];
|
||||
async function getDefaultPlaceholders() {
|
||||
let defaultPlaceholders_prop = JSON.parse(JSON.stringify(defaultPlaceholders));
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps defaultPlaceholders: ' + JSON.stringify(defaultPlaceholders));
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
||||
if(prefs._default_placeholders_properties === null){ // no default Placeholders properties saved
|
||||
defaultPlaceholders_prop.forEach((placeholder) => {
|
||||
placeholder.enabled = 1;
|
||||
})
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps [no prop saved] defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
||||
} else { // we have saved default Placeholders properties
|
||||
defaultPlaceholders_prop.forEach((placeholder) => {
|
||||
if(prefs._default_Placeholders_properties?.[placeholder.id]){
|
||||
placeholder.enabled = prefs._default_Placeholders_properties[placeholder.id].enabled;
|
||||
}else{
|
||||
placeholder.enabled = 1;
|
||||
}
|
||||
})
|
||||
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps [prop saved] defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
||||
}
|
||||
return defaultPlaceholders_prop;
|
||||
}
|
||||
|
||||
async function getCustomPlaceholders() {
|
||||
export async function getCustomPlaceholders() {
|
||||
let prefs = await browser.storage.local.get({_custom_placeholder: null});
|
||||
if(prefs._custom_placeholder === null){
|
||||
return [];
|
||||
|
|
@ -241,22 +255,61 @@ async function getCustomPlaceholders() {
|
|||
}
|
||||
}
|
||||
|
||||
export async function setDefaultPlaceholdersProperties(placeholders) {
|
||||
let default_placeholders_properties = {};
|
||||
placeholders.forEach((placeholder) => {
|
||||
default_placeholders_properties[placeholder.id] = {enabled: placeholder.enabled};
|
||||
export async function setCustomPlaceholders(placeholders) {
|
||||
placeholders.forEach(ph => {
|
||||
ph.id = placeholdersUtils.validateCustomDataPH_ID(ph.id);
|
||||
ph.is_default = "0";
|
||||
});
|
||||
//console.log('>>>>>>>>>>>>>> default_placeholders_properties: ' + JSON.stringify(default_placeholders_properties));
|
||||
await browser.storage.local.set({_default_placeholders_properties: default_placeholders_properties});
|
||||
await browser.storage.local.set({_custom_placeholder: placeholders});
|
||||
}
|
||||
|
||||
export async function setCustomPlaceholders(placeholders) {
|
||||
await browser.storage.local.set({_custom_placeholder: placeholders});
|
||||
export function prepareCustomDataPHsForExport(placeholders){
|
||||
let output = [...placeholders];
|
||||
output.forEach(placeholder => {
|
||||
if(placeholder.is_default == 0){
|
||||
delete placeholder['idnum'];
|
||||
}
|
||||
});
|
||||
return output;
|
||||
}
|
||||
|
||||
export async function prepareCustomDataPHsForImport(placeholders){
|
||||
// console.log(">>>>>>>>>>> prepareCustomDataPHsForImport prompts: " + JSON.stringify(prompts));
|
||||
const output = await getCustomPlaceholders();
|
||||
// console.log(">>>>>>>>>>> prepareCustomDataPHsForImport output: " + JSON.stringify(output));
|
||||
placeholders.forEach(placeholder => {
|
||||
if(output.some(p => p.id == placeholder.id)){
|
||||
Object.keys(placeholder).forEach(key => {
|
||||
output.find(p => p.id == placeholder.id)[key] = placeholder[key];
|
||||
})
|
||||
}else{
|
||||
output.push(placeholder);
|
||||
}
|
||||
});
|
||||
output.sort((a, b) => a.id.localeCompare(b.id));
|
||||
// console.log(">>>>>>>>>>> prepareCustomDataPHsForImport final output: " + JSON.stringify(output));
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
export const placeholdersUtils = {
|
||||
|
||||
customPrefix: 'thunderai_custom_',
|
||||
|
||||
validateCustomDataPH_ID(placeholder_id){
|
||||
if (!placeholder_id.startsWith(this.customPrefix)) {
|
||||
return this.customPrefix + placeholder_id;
|
||||
}
|
||||
return placeholder_id;
|
||||
},
|
||||
|
||||
stripCustomDataPH_ID_Prefix(placeholder_id){
|
||||
if (placeholder_id.startsWith(this.customPrefix)) {
|
||||
return placeholder_id.substring(this.customPrefix.length);
|
||||
}
|
||||
return placeholder_id;
|
||||
},
|
||||
|
||||
async extractPlaceholders(text) {
|
||||
// Regular expression to match patterns like {%...%}
|
||||
const regex = /{%\s*(.*?)\s*%}/g;
|
||||
|
|
@ -292,6 +345,19 @@ export const placeholdersUtils = {
|
|||
});
|
||||
},
|
||||
|
||||
async replaceCustomPlaceholders(text) {
|
||||
let customPlaceholders = await getCustomPlaceholders(true);
|
||||
// Regular expression to match patterns like {%thunderai_custom_...%}
|
||||
return text.replace(/{%\s*thunderai_custom_(.*?)\s*%}/g, function(match, p1) {
|
||||
// p1 contains the key inside {% %}
|
||||
const currPlaceholder = customPlaceholders.find(ph => ph.id === 'thunderai_custom_' + p1);
|
||||
if (!currPlaceholder) {
|
||||
return match;
|
||||
}
|
||||
return currPlaceholder.text;
|
||||
});
|
||||
},
|
||||
|
||||
hasPlaceholder(text, placeholder = "") {
|
||||
let regex;
|
||||
|
||||
|
|
@ -306,7 +372,23 @@ export const placeholdersUtils = {
|
|||
|
||||
// Check if the specific or any placeholder is present in the text
|
||||
return regex.test(text);
|
||||
},
|
||||
},
|
||||
|
||||
hasCustomPlaceholder(text, placeholder = "") {
|
||||
let regex;
|
||||
|
||||
// If a specific placeholder is provided, we search for it
|
||||
if (placeholder !== "") {
|
||||
// Dynamically build the regex for the specific placeholder
|
||||
regex = new RegExp(`{%\s*${placeholder}\s*%}`);
|
||||
} else {
|
||||
// Otherwise, we search for any placeholder in the format {%thunderai_custom_ ... %}
|
||||
regex = /{%\s*thunderai_custom_(.*?)\s*%}/;
|
||||
}
|
||||
|
||||
// Check if the specific or any placeholder is present in the text
|
||||
return regex.test(text);
|
||||
},
|
||||
|
||||
async getPlaceholdersValues(prompt_text, curr_message, mail_subject, body_text, msg_text, only_typed_text, only_quoted_text, selection_text, selection_html, tags_full_list) {
|
||||
let currPHs = await placeholdersUtils.extractPlaceholders(prompt_text);
|
||||
|
|
|
|||
|
|
@ -109,6 +109,23 @@ const defaultPrompts = [
|
|||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_reply_custom_command',
|
||||
name: "__MSG_prompt_reply_custom_command__",
|
||||
text: "prompt_reply_custom_command_full_text",
|
||||
type: "1",
|
||||
action: "1",
|
||||
need_selected: "0",
|
||||
need_signature: "1",
|
||||
need_custom_text: "1",
|
||||
define_response_lang: "1",
|
||||
use_diff_viewer: "0",
|
||||
chatgpt_web_model: '',
|
||||
chatgpt_web_project: '',
|
||||
chatgpt_web_custom_gpt: '',
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_rewrite_polite',
|
||||
name: "__MSG_prompt_rewrite_polite__",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
import { placeholdersUtils } from './mzta-placeholders.js';
|
||||
import { extractJsonObject } from './mzta-utils.js';
|
||||
|
||||
export const taPromptUtils = {
|
||||
|
||||
|
|
@ -37,6 +38,10 @@ export const taPromptUtils = {
|
|||
fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await taPromptUtils.getDefaultSignature():"") + " " + chatgpt_lang + " \"" + (selection_text=='' ? body_text : selection_text) + "\" ";
|
||||
}else{
|
||||
// we have at least a placeholder, do the magic!
|
||||
// check if we have custom placeholders
|
||||
if(placeholdersUtils.hasCustomPlaceholder(curr_prompt.text)){
|
||||
curr_prompt.text = await placeholdersUtils.replaceCustomPlaceholders(curr_prompt.text);
|
||||
}
|
||||
let finalSubs = await placeholdersUtils.getPlaceholdersValues(curr_prompt.text, curr_message, subject_text, body_text, msg_text, only_typed_text, only_quoted_text, selection_text, selection_html, tags_full_list);
|
||||
// console.log(">>>>>>>>>> finalSubs: " + JSON.stringify(finalSubs));
|
||||
let prefs_ph = await browser.storage.sync.get({placeholders_use_default_value: false});
|
||||
|
|
@ -48,10 +53,10 @@ export const taPromptUtils = {
|
|||
|
||||
finalizePrompt_add_tags(fullPrompt, add_tags_maxnum, add_tags_force_lang, default_chatgpt_lang){
|
||||
if(add_tags_maxnum > 0){
|
||||
fullPrompt += " " + browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + add_tags_maxnum +".";
|
||||
fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + add_tags_maxnum +".";
|
||||
}
|
||||
if(add_tags_force_lang && default_chatgpt_lang !== ''){
|
||||
fullPrompt += " " + browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + default_chatgpt_lang + ".";
|
||||
fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + default_chatgpt_lang + ".";
|
||||
}
|
||||
|
||||
return fullPrompt;
|
||||
|
|
@ -78,4 +83,37 @@ export const taPromptUtils = {
|
|||
|
||||
return chatgpt_lang;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts tags from the response text.
|
||||
* @param {string} response_text - The response text from which to extract tags.
|
||||
* @returns {Array} An array of tags extracted from the response text.
|
||||
*
|
||||
* The response text should be a JSON with this structure:
|
||||
* {
|
||||
* "tags": ["tag1", "tag2", ...]
|
||||
* }
|
||||
*
|
||||
* For backwords compatibility, if the response text is not a valid JSON,
|
||||
* it will try to split the text by commas and return the resulting array.
|
||||
*/
|
||||
getTagsFromResponse(response_text){
|
||||
let tags = [];
|
||||
if(response_text && response_text.length > 0){
|
||||
try {
|
||||
// Try to parse the response text as JSON
|
||||
let response_json = extractJsonObject(response_text.trim());
|
||||
if(response_json && Array.isArray(response_json.tags)){
|
||||
tags = response_json.tags;
|
||||
} else if(response_json && response_json.tags && typeof response_json.tags === 'string'){
|
||||
// If tags is a string, split it by commas
|
||||
tags = response_json.tags.split(/,\s*/).map(tag => tag.trim());
|
||||
}
|
||||
} catch (e) {
|
||||
// If parsing fails, fallback to splitting by commas
|
||||
tags = response_text.split(/,\s*/).map(tag => tag.trim());
|
||||
}
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
};
|
||||
|
|
@ -192,13 +192,21 @@ export function sanitizeHtml(input) {
|
|||
export function stripHtmlKeepLines(htmlString) {
|
||||
// Replaces <p> tags with a newline at the beginning
|
||||
// and removes all other HTML tags
|
||||
return htmlString
|
||||
return convertBrToNewlines(htmlString)
|
||||
.replace(/<p>/gi, '') // removes <p> tags
|
||||
.replace(/<\/p>/gi, '\n') // replaces </p> tags with newline
|
||||
.replace(/<[^>]*>/g, '') // removes any other HTML tags
|
||||
.trim(); // removes leading/trailing whitespace
|
||||
}
|
||||
|
||||
export function convertNewlinesToBr(text) {
|
||||
return text.replace(/\n/g, '<br>');
|
||||
}
|
||||
|
||||
function convertBrToNewlines(html) {
|
||||
return html.replace(/<br\s*\/?>/gi, '\n');
|
||||
}
|
||||
|
||||
// This method is used to convert the model string id used in the URL
|
||||
// to the model string used in the webpage
|
||||
export function getGPTWebModelString(model) {
|
||||
|
|
@ -446,16 +454,23 @@ export async function transformTagsLabels(labels, tags_list) {
|
|||
return output;
|
||||
}
|
||||
|
||||
export function getAPIsInitMessageString(api_string, model_string = '', host_string = '', version_string = '') {
|
||||
let output = browser.i18n.getMessage("_api_connecting", api_string);
|
||||
export function getAPIsInitMessageString(api_string, model_string = '', host_string = '', version_string = '', additional_messages = []) {
|
||||
let output = "<i class='info_obj'>" + browser.i18n.getMessage("_api_connecting", api_string) + "</i>";
|
||||
if (model_string !== '') {
|
||||
output += "\n" + browser.i18n.getMessage("_api_connecting_model", model_string);
|
||||
output += "\n<span class='info_obj'>" + browser.i18n.getMessage("_api_connecting_model") + ":</span> " + model_string;
|
||||
}
|
||||
if (host_string !== '') {
|
||||
output += "\n" + browser.i18n.getMessage("_api_connecting_host", host_string);
|
||||
output += "\n<span class='info_obj'>" + browser.i18n.getMessage("_api_connecting_host") + ":</span> " + host_string;
|
||||
}
|
||||
if (version_string !== '') {
|
||||
output += "\n" + browser.i18n.getMessage("_api_connecting_version", version_string);
|
||||
output += "\n<span class='info_obj'>" + browser.i18n.getMessage("_api_connecting_version") + ":</span> " + version_string;
|
||||
}
|
||||
let additional_message = '';
|
||||
if (additional_messages.length > 0) {
|
||||
additional_message = additional_messages.map(msg => "<span class='info_obj'>" + msg.label + ":</span> " + msg.value).join("\n");
|
||||
}
|
||||
if (additional_message !== '') {
|
||||
output += "\n" + additional_message;
|
||||
}
|
||||
|
||||
return output;
|
||||
|
|
@ -587,7 +602,7 @@ const insertHtml = function (replyHtml, fullBody_string) {
|
|||
return fullBody.body.innerHTML;
|
||||
}
|
||||
|
||||
export async function getCustomPromptsUsedSpace(){
|
||||
export async function getLocalStorageUsedSpace(){
|
||||
// we can't use this, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1385832
|
||||
//let customprompts_space = await browser.storage.local.getBytesInUse("_custom_prompt");
|
||||
//let's use a workaround
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ self.onmessage = async function(event) {
|
|||
if (event.data.type === 'init') {
|
||||
chatgpt_api_key = event.data.chatgpt_api_key;
|
||||
chatgpt_model = event.data.chatgpt_model;
|
||||
openai = new OpenAI(chatgpt_api_key, chatgpt_model, event.data.chatgpt_developer_messages, true);
|
||||
openai = new OpenAI(chatgpt_api_key, chatgpt_model, event.data.chatgpt_developer_messages, true, event.data.chatgpt_api_store);
|
||||
do_debug = event.data.do_debug;
|
||||
i18nStrings = event.data.i18nStrings;
|
||||
taLog = new taLogger('model-worker-openai', do_debug);
|
||||
|
|
|
|||
|
|
@ -113,6 +113,10 @@ self.onmessage = async function(event) {
|
|||
|
||||
for (const parsedLine of parsedLines) {
|
||||
const { choices } = parsedLine;
|
||||
if (!choices || choices.length === 0) {
|
||||
taLog.error("No choices found in parsed line: " + JSON.stringify(parsedLine));
|
||||
continue;
|
||||
}
|
||||
const { delta } = choices[0];
|
||||
const { content } = delta;
|
||||
// Update the UI with the new content
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "ThunderAI",
|
||||
"description": "__MSG_extensionDescription__",
|
||||
"version": "3.5.5",
|
||||
"version": "3.6.0",
|
||||
"author": "Mic (m@micz.it)",
|
||||
"homepage_url": "https://micz.it/thunderbird-addon-thunderai/",
|
||||
"browser_specific_settings": {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { mzta_specialCommand } from './js/mzta-special-commands.js';
|
|||
import { getSpamFilterPrompt } from './js/mzta-prompts.js';
|
||||
import { taSpamReport } from './js/mzta-spamreport.js';
|
||||
import { taWorkingStatus } from './js/mzta-working-status.js';
|
||||
import { addTags_getExclusionList } from './js/mzta-addatags-exclusion-list.js';
|
||||
import { addTags_getExclusionList, checkExcludedTag } from './js/mzta-addatags-exclusion-list.js';
|
||||
|
||||
browser.runtime.onInstalled.addListener(({ reason, previousVersion }) => {
|
||||
// console.log(">>>>>>>>>>> onInstalled: " + JSON.stringify(reason) + ", previousVersion: " + previousVersion);
|
||||
|
|
@ -155,7 +155,7 @@ async function _reload_menus() {
|
|||
return true;
|
||||
}
|
||||
|
||||
async function _assign_tags(_data, create_new_tags = true) {
|
||||
async function _assign_tags(_data, create_new_tags = true, exclusions_exact_match = false) {
|
||||
let all_tags_list = await getTagsList();
|
||||
all_tags_list = all_tags_list[1];
|
||||
// console.log(">>>>>>>>>>>>>>> all_tags_list: " + JSON.stringify(all_tags_list));
|
||||
|
|
@ -165,7 +165,7 @@ async function _assign_tags(_data, create_new_tags = true) {
|
|||
taLog.log("add_tags_exclusions_list: " + JSON.stringify(add_tags_exclusions_list));
|
||||
const tags_final = _data.tags.filter(tag =>
|
||||
!add_tags_exclusions_list.some(exclusion =>
|
||||
tag.toLowerCase().includes(exclusion.toLowerCase())
|
||||
checkExcludedTag(tag, exclusion, exclusions_exact_match)
|
||||
)
|
||||
);
|
||||
if(!create_new_tags){
|
||||
|
|
@ -203,6 +203,7 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
case 'chatgpt_replaceSelectedText':
|
||||
async function _replaceSelectedText(tabId, text) {
|
||||
//console.log('chatgpt_replaceSelectedText: [' + tabId +'] ' + text)
|
||||
taLog.log("chatgpt_replaceSelectedText text: " + text);
|
||||
original_html = await getOriginalBody(tabId);
|
||||
let prefs_repl = await browser.storage.sync.get({composing_plain_text: prefs_default.composing_plain_text});
|
||||
if(prefs_repl.composing_plain_text){
|
||||
|
|
@ -216,15 +217,21 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
async function _replyMessage(message) {
|
||||
let paragraphsHtmlString = message.text;
|
||||
//console.log(">>>>>>>>>>>> paragraphsHtmlString: " + paragraphsHtmlString);
|
||||
let prefs = await browser.storage.sync.get({reply_type: prefs_default.reply_type, composing_plain_text: prefs_default.composing_plain_text});
|
||||
if(prefs.composing_plain_text){
|
||||
taLog.log("paragraphsHtmlString: " + paragraphsHtmlString);
|
||||
let prefs_reply = await browser.storage.sync.get({reply_type: prefs_default.reply_type, composing_plain_text: prefs_default.composing_plain_text});
|
||||
if(prefs_reply.composing_plain_text){
|
||||
paragraphsHtmlString = stripHtmlKeepLines(paragraphsHtmlString);
|
||||
}
|
||||
//console.log('reply_type: ' + prefs.reply_type);
|
||||
//console.log('reply_type: ' + prefs_reply.reply_type);
|
||||
let replyType = 'replyToAll';
|
||||
if(prefs.reply_type === 'reply_sender'){
|
||||
// console.log(">>>>>>>>>>> chatgpt_replyMessage replyType: " + message.replyType);
|
||||
if (typeof message.replyType === "undefined" || message.replyType === null || message.replyType === "") {
|
||||
message.replyType = prefs_reply.reply_type;
|
||||
}
|
||||
if(message.replyType === 'reply_sender'){
|
||||
replyType = 'replyToSender';
|
||||
}
|
||||
taLog.log("Reply type: " + replyType);
|
||||
//console.log('replyType: ' + replyType);
|
||||
// browser.messageDisplay.getDisplayedMessage(message.tabId).then(async (mailMessage) => {
|
||||
// let reply_tab = await browser.compose.beginReply(mailMessage.id, replyType, {
|
||||
|
|
@ -296,7 +303,11 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
return _popup_menu_ready();
|
||||
break;
|
||||
case 'assign_tags':
|
||||
return _assign_tags(message);
|
||||
async function _do_assign_tags(message) {
|
||||
let prefs_assign_tags = await browser.storage.sync.get({add_tags_exclusions_exact_match: prefs_default.add_tags_exclusions_exact_match});
|
||||
return _assign_tags(message,true, prefs_assign_tags.add_tags_exclusions_exact_match);
|
||||
}
|
||||
return _do_assign_tags(message);
|
||||
break;
|
||||
case 'api_send_custom_text':
|
||||
browser.tabs.sendMessage(message.tabId, { command: "api_send_custom_text", custom_text: message.custom_text });
|
||||
|
|
@ -403,6 +414,7 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
if((originalText == null) || (originalText == "")) {
|
||||
originalText = prompt_info.body_text;
|
||||
}
|
||||
let reply_type_pref = await browser.storage.sync.get({reply_type: 'reply_all'});
|
||||
//console.log(">>>>>>>>>> prompt_info: " + JSON.stringify(prompt_info));
|
||||
let pre_script = `let mztaWinId = `+ createdTab.windowId +`;
|
||||
let mztaStatusPageDesc="`+ browser.i18n.getMessage("prefs_status_page") +`";
|
||||
|
|
@ -415,6 +427,7 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
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) +`";
|
||||
let mztaReplyType="`+ reply_type_pref.reply_type + `";
|
||||
`;
|
||||
|
||||
taLog.log("Waiting " + _wait_time + " millisec");
|
||||
|
|
@ -944,7 +957,16 @@ const newEmailListener = (folder, messagesList) => {
|
|||
async function processEmails(messages, addTagsAuto, spamFilter) {
|
||||
taWorkingStatus.startWorking();
|
||||
|
||||
let prefs_aats = await browser.storage.sync.get({ add_tags_maxnum: prefs_default.add_tags_maxnum, connection_type: prefs_default.connection_type, add_tags_force_lang: prefs_default.add_tags_force_lang, default_chatgpt_lang: prefs_default.default_chatgpt_lang, add_tags_auto_force_existing: prefs_default.add_tags_auto_force_existing, add_tags_enabled_accounts: prefs_default.add_tags_enabled_accounts, spamfilter_enabled_accounts: prefs_default.spamfilter_enabled_accounts });
|
||||
let prefs_aats = await browser.storage.sync.get({
|
||||
add_tags_maxnum: prefs_default.add_tags_maxnum,
|
||||
connection_type: prefs_default.connection_type,
|
||||
add_tags_force_lang: prefs_default.add_tags_force_lang,
|
||||
default_chatgpt_lang: prefs_default.default_chatgpt_lang,
|
||||
add_tags_auto_force_existing: prefs_default.add_tags_auto_force_existing,
|
||||
add_tags_enabled_accounts: prefs_default.add_tags_enabled_accounts,
|
||||
add_tags_exclusions_exact_match: prefs_default.add_tags_exclusions_exact_match,
|
||||
spamfilter_enabled_accounts: prefs_default.spamfilter_enabled_accounts,
|
||||
});
|
||||
|
||||
for await (let message of messages) {
|
||||
let curr_fullMessage = null;
|
||||
|
|
@ -975,15 +997,15 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
|
|||
taLog.log("Special prompt: " + specialFullPrompt_add_tags);
|
||||
let cmd_addTags = new mzta_specialCommand(specialFullPrompt_add_tags, prefs_aats.connection_type, prefs_init.do_debug);
|
||||
await cmd_addTags.initWorker();
|
||||
let tags_current_email = '';
|
||||
let tags_current_email = [];
|
||||
try {
|
||||
tags_current_email = (await cmd_addTags.sendPrompt()).trim();
|
||||
tags_current_email = taPromptUtils.getTagsFromResponse(await cmd_addTags.sendPrompt());
|
||||
} catch (err) {
|
||||
console.error("[ThunderAI | Auto add_tags] Error getting tags: ", err);
|
||||
}
|
||||
taLog.log("tags_current_email: " + tags_current_email);
|
||||
let _data = { messageId: message.id, tags: tags_current_email.split(/,\s*/) };
|
||||
_assign_tags(_data, !prefs_aats.add_tags_auto_force_existing);
|
||||
taLog.log("tags_current_email: " + JSON.stringify(tags_current_email));
|
||||
let _data = { messageId: message.id, tags: tags_current_email };
|
||||
_assign_tags(_data, !prefs_aats.add_tags_auto_force_existing, prefs_aats.add_tags_exclusions_exact_match);
|
||||
}
|
||||
|
||||
if (spamFilter) {
|
||||
|
|
|
|||
|
|
@ -30,11 +30,13 @@ export const prefs_default = {
|
|||
chatgpt_web_project: '',
|
||||
chatgpt_web_custom_gpt: '',
|
||||
chatgpt_api_key: '',
|
||||
chatgpt_api_store: false,
|
||||
chatgpt_model: '',
|
||||
chatgpt_developer_messages: '',
|
||||
ollama_host: '',
|
||||
ollama_model: '',
|
||||
ollama_num_ctx: 0,
|
||||
ollama_think: false,
|
||||
openai_comp_host: '', // For OpenAI Compatible API as LM-Studio
|
||||
openai_comp_model: '',
|
||||
openai_comp_api_key: '',
|
||||
|
|
@ -54,6 +56,7 @@ export const prefs_default = {
|
|||
add_tags: false,
|
||||
add_tags_maxnum: 3,
|
||||
add_tags_hide_exclusions: false,
|
||||
add_tags_exclusions_exact_match: false,
|
||||
add_tags_first_uppercase: true,
|
||||
add_tags_force_lang: true,
|
||||
add_tags_auto: false,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<td colspan="2"><div>__MSG_prefs_SurveyLinkText__<br><a href="https://forms.gle/1qK2wcbuhaRzhwyt9">__MSG_prefs_SurveyLinkText2__</a></div></td>
|
||||
</tr>
|
||||
<tr id="owl_warning">
|
||||
<td colspan="2"><div class="warning">__MSG_prefs_OptionText_owl_warning__ <a href="https://micz.it/thunderbird-addon-thunderai/owl/">__MSG_customPrompts_managePrompts_help__</a></div></td>
|
||||
<td colspan="2"><div class="warning">__MSG_prefs_OptionText_owl_warning__ <a href="https://micz.it/thunderbird-addon-thunderai/owl/">__MSG_more_info_string__</a></div></td>
|
||||
</tr>
|
||||
<tr id="hyprland_warning">
|
||||
<td colspan="2" style="text-align:center;" class="warning"><b>__MSG_hyprland_warning__</b></td>
|
||||
|
|
@ -65,6 +65,7 @@
|
|||
<option value="reply_all">__MSG_prefs_OptionText_reply_all__</option>
|
||||
<option value="reply_sender">__MSG_prefs_OptionText_reply_sender__</option>
|
||||
</select>
|
||||
<br>__MSG_prefs_OptionText_reply_type_info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -217,6 +218,19 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_chatgpt_api">
|
||||
<td>
|
||||
<label>
|
||||
<span class="opt_title">__MSG_ChatGPT_chatgpt_api_store__</span>
|
||||
</label>
|
||||
</td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="chatgpt_api_store" name="chatgpt_api_store" class="option-input" />
|
||||
<span>__MSG_ChatGPT_chatgpt_api_store_info__</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_chatgpt_api">
|
||||
<td>
|
||||
<label>
|
||||
|
|
@ -283,23 +297,12 @@
|
|||
</tr>
|
||||
<tr class="conntype_ollama_api" id="ollama_api_cors_warning">
|
||||
<td colspan="2" style="text-align:center;">
|
||||
__MSG_remember_CORS__ [<a href="https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/">__MSG_customPrompts_managePrompts_help__</a>]
|
||||
__MSG_remember_CORS__ [<a href="https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/">__MSG_more_info_string__</a>]
|
||||
<br><br><b>__MSG_CORS_alternative_1__</b>
|
||||
<br>__MSG_CORS_alternative_2__
|
||||
<br><br><button id="btnGiveAllUrlsPermission_ollama_api">__MSG_CORS_give_allurls_perm__</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_ollama_api">
|
||||
<td><label>
|
||||
<span class="opt_title">__MSG_prefs_ollama_num_ctx__ <i>[num_ctx]</i></span>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="number" id="ollama_num_ctx" name="ollama_num_ctx" class="option-input"/>
|
||||
<br>__MSG_prefs_ollama_num_ctx_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_ollama_api">
|
||||
<td>
|
||||
<label>
|
||||
|
|
@ -314,6 +317,28 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_ollama_api">
|
||||
<td><label>
|
||||
<span class="opt_title">__MSG_prefs_ollama_think__</span>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="ollama_think" name="ollama_think" class="option-input"/>
|
||||
__MSG_prefs_ollama_think_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_ollama_api">
|
||||
<td><label>
|
||||
<span class="opt_title">__MSG_prefs_ollama_num_ctx__ <i>[num_ctx]</i></span>
|
||||
</label></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="number" id="ollama_num_ctx" name="ollama_num_ctx" class="option-input"/>
|
||||
<br>__MSG_prefs_ollama_num_ctx_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="conntype_openai_comp_api">
|
||||
<td><label>
|
||||
<span class="opt_title">__MSG_prefs_OpenAIComp_AvailableServices__</span>
|
||||
|
|
@ -340,7 +365,7 @@
|
|||
</tr>
|
||||
<tr class="conntype_openai_comp_api" id="openai_comp_api_cors_warning">
|
||||
<td colspan="2" style="text-align:center;">
|
||||
__MSG_maybe_CORS_openai_comp__ [<a href="https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/">__MSG_customPrompts_managePrompts_help__</a>]
|
||||
__MSG_maybe_CORS_openai_comp__ [<a href="https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/">__MSG_more_info_string__</a>]
|
||||
<br><br><b>__MSG_CORS_alternative_1__</b>
|
||||
<br>__MSG_CORS_alternative_2__
|
||||
<br><br><button id="btnGiveAllUrlsPermission_openai_comp_api">__MSG_CORS_give_allurls_perm__</button>
|
||||
|
|
@ -517,14 +542,15 @@
|
|||
</table>
|
||||
<div id="btn_custom_prompts">
|
||||
<button id="btnManagePrompts">__MSG_prefs_OptionText_btnManagePrompts__</button>
|
||||
<br>__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br>__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_more_info_string__</a>
|
||||
<br><button id="btnManageCustomDataPH">__MSG_prefs_OptionText_btnManageCustomDataPH__</button>
|
||||
</div>
|
||||
<div id="miczDescription">
|
||||
<h1>__MSG_prefsInfoTitle__</h1>
|
||||
<p>
|
||||
<span class="conntype_chatgpt_web">__MSG_prefsInfoDesc_1__<br></span>
|
||||
<span class="conntype_chatgpt_api">__MSG_prefsInfoDesc_2__<br></span>
|
||||
<span class="conntype_ollama_api">__MSG_prefsInfoDesc_3__ [<a href="https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/">__MSG_customPrompts_managePrompts_help__</a>]<br></span>
|
||||
<span class="conntype_ollama_api">__MSG_prefsInfoDesc_3__ [<a href="https://micz.it/thunderbird-addon-thunderai/ollama-cors-information/">__MSG_more_info_string__</a>]<br></span>
|
||||
<span class="conntype_openai_comp_api">__MSG_prefsInfoDesc_4__</span>
|
||||
<br><span>__MSG_prefsInfoDesc_5__
|
||||
<br>__MSG_prefsInfoDesc_6__</span>
|
||||
|
|
|
|||
|
|
@ -52,16 +52,16 @@ function saveOptions(e) {
|
|||
options[element.id] = element.value.trim();
|
||||
taLog.log('Saving option: ' + element.id + ' = *********');
|
||||
break;
|
||||
case 'select-one':
|
||||
options[element.id] = element.value;
|
||||
taLog.log('Saving option: ' + element.id + ' = ' + element.value);
|
||||
break;
|
||||
case 'textarea':
|
||||
options[element.id] = element.value.trim();
|
||||
taLog.log('Saving option: ' + element.id + ' = ' + element.value.trim());
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
options[element.id] = element.value;
|
||||
taLog.log('Saving option: ' + element.id + ' = ' + element.value);
|
||||
} if (element.tagName === 'TEXTAREA') {
|
||||
options[element.id] = element.value.trim();
|
||||
taLog.log('Saving option: ' + element.id + ' = ' + element.value.trim());
|
||||
} else {
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
}
|
||||
|
||||
browser.storage.sync.set(options);
|
||||
|
|
@ -87,8 +87,7 @@ async function restoreOptions() {
|
|||
if(element.id == 'default_chatgpt_lang') default_text_value = prefs_default.default_chatgpt_lang;
|
||||
element.value = result[element.id] || default_text_value;
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
case 'select-one':
|
||||
let default_select_value = '';
|
||||
if(element.id == 'reply_type') default_select_value = 'reply_all';
|
||||
if(element.id == 'connection_type') default_select_value = 'chatgpt_web';
|
||||
|
|
@ -96,11 +95,12 @@ async function restoreOptions() {
|
|||
if (element.value === '') {
|
||||
element.selectedIndex = -1;
|
||||
}
|
||||
} else if (element.tagName === 'TEXTAREA') {
|
||||
break;
|
||||
case 'textarea':
|
||||
element.value = result[element.id];
|
||||
}else{
|
||||
break;
|
||||
default:
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -479,23 +479,27 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
get_task_info_btn.disabled = get_task_el.checked ? '' : 'disabled';
|
||||
|
||||
document.getElementById('btnManagePrompts').addEventListener('click', () => {
|
||||
openTab('../pages/customprompts/mzta-custom-prompts.html');
|
||||
openTab('/pages/customprompts/mzta-custom-prompts.html');
|
||||
});
|
||||
|
||||
document.getElementById('btnManageCustomDataPH').addEventListener('click', () => {
|
||||
openTab('/pages/customdataplaceholders/mzta-custom-dataplaceholders.html');
|
||||
});
|
||||
|
||||
document.getElementById('btnManageTagsInfo').addEventListener('click', () => {
|
||||
openTab('../pages/addtags/mzta-add-tags.html');
|
||||
openTab('/pages/addtags/mzta-add-tags.html');
|
||||
});
|
||||
|
||||
document.getElementById('btnManageSpamFilterInfo').addEventListener('click', () => {
|
||||
openTab('../pages/spamfilter/mzta-spamfilter.html');
|
||||
openTab('/pages/spamfilter/mzta-spamfilter.html');
|
||||
});
|
||||
|
||||
document.getElementById('btnManageCalendarEventInfo').addEventListener('click', () => {
|
||||
openTab('../pages/get-calendar-event/mzta-get-calendar-event.html');
|
||||
openTab('/pages/get-calendar-event/mzta-get-calendar-event.html');
|
||||
});
|
||||
|
||||
document.getElementById('btnManageTaskInfo').addEventListener('click', () => {
|
||||
openTab('../pages/get-task/mzta-get-task.html');
|
||||
openTab('/pages/get-task/mzta-get-task.html');
|
||||
});
|
||||
|
||||
document.getElementById('btnOpenAICompForceModel').addEventListener('click', () => {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,24 @@
|
|||
<body>
|
||||
<div id="miczBackPrefs"><a href="mzta-options.html">__MSG_backToOptionsText__</a></div>
|
||||
<div id="miczRelNotes"><h1>ThunderAI Release Notes</h1>
|
||||
<h2>Version 3.6.0 - 30/07/2025</h2>
|
||||
<ul>
|
||||
<li>Now it's possibile to define custom data placeholders to be used in custom prompts [<a href="https://github.com/micz/ThunderAI/issues/156">#156</a>].</li>
|
||||
<li>Improved the handling of HTML and line breaks between the email text and the AI Chat.</li>
|
||||
<li>When replying, it's now possibile to choose a different reply type (between "all" or "sender only") directly in the AI chat window [<a href="https://github.com/micz/ThunderAI/issues/372">#372</a>].</li>
|
||||
<li>Added a new default prompt for replying to emails, which asks for a custom command each time it's used [<a href="https://github.com/micz/ThunderAI/issues/444">#444</a>].</li>
|
||||
<li><i>[All APIs]</i> Added an option to choose to exclude a tag only with an exact match in the excluded words list [<a href="https://github.com/micz/ThunderAI/issues/395">#395</a>].</li>
|
||||
<li><i>[OpenAI API]</i> Added an option to enable the OpenAI storage for API requests [<a href="https://github.com/micz/ThunderAI/issues/406">#406</a>].</li>
|
||||
<li><i>[OpenAI API]</i> In the AI chat page, the initial configuration now also displays the storage setting and the "Developer Messages" [<a href="https://github.com/micz/ThunderAI/issues/430">#430</a>].</li>
|
||||
<li><i>[Ollama API]</i> Added an option to enable the thinking feature [<a href="https://github.com/micz/ThunderAI/issues/398">#398</a>].</li>
|
||||
<li><i>[Google Gemini API]</i> In the AI chat page, the initial configuration now also displays the "System Instructions". [<a href="https://github.com/micz/ThunderAI/issues/429">#429</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Handling responses without choices when using RAG [<a href="https://github.com/micz/ThunderAI/issues/416">#416</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added Perplexity configuration [<a href="https://github.com/micz/ThunderAI/issues/405">#405</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added OpenRouter configuration [<a href="https://github.com/micz/ThunderAI/issues/401">#401</a>].</li>
|
||||
<li>Traditional Chinese (zh_Hant) translation added, thanks to <a href="https://github.com/evez">evez</a>.</li>
|
||||
<li>Russian (ru) translation added, thanks to <a href="https://hosted.weblate.org/user/law820314/">Maksim</a>.</li>
|
||||
<li>Some English typing errors have been fixed [<a href="https://github.com/micz/ThunderAI/issues/422">#422</a>].</li>
|
||||
</ul>
|
||||
<h2>Version 3.5.5 - ??/??/2025</h2>
|
||||
<ul>
|
||||
<li><i>[All APIs]</i> Fix: Autotag and Antispam filter working again [<a href="https://github.com/micz/ThunderAI/issues/449">#449</a>].</li>
|
||||
|
|
@ -37,7 +55,7 @@
|
|||
<ul>
|
||||
<li>Added Anthropic API support [<a href="https://github.com/micz/ThunderAI/issues/349">#349</a>].</li>
|
||||
<li>Added the <i>{%selected_html%}</i> placeholder to retrieve the HTML portion of the selected text [<a href="https://github.com/micz/ThunderAI/issues/368">#368</a>].</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added a shortcut to select configurations for known AI services. Currently, <i>Grok AI</i> and <i>Mistral AI</i> are available [<a href="https://github.com/micz/ThunderAI/issues/378">#378</a>]. <a href="https://github.com/micz/ThunderAI/issues/new?template=feature_request.md">Open an issue</a> to request additional services.</li>
|
||||
<li><i>[OpenAI Comp API]</i> Added a shortcut to select configurations for known AI services. Currently, <i>Grok AI</i> and <i>Mistral AI</i> are available [<a href="https://github.com/micz/ThunderAI/issues/378">#378</a>]. <a href="https://github.com/micz/ThunderAI/issues/new?template=feature_request.md">Open an issue</a> to request additional services.</li>
|
||||
<li><i>[All APIs]</i> In the API WebChat is now possibile to select a part of the answer and use only that [<a href="https://github.com/micz/ThunderAI/issues/356">#356</a>].</li>
|
||||
<li><i>[All APIs]</i> Setting the "Max prompt length" to zero on the options page will disable the length check when sending a prompt to the AI. [<a href="https://github.com/micz/ThunderAI/issues/380">#380</a>].</li>
|
||||
<li><i>[All APIs]</i> Added a button to the options page to reset the 'Max prompt length' value to its default.</li>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,15 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="add_tags_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags_exclusions_exact_match__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="add_tags_exclusions_exact_match" name="add_tags_exclusions_exact_match" class="option-input" />
|
||||
__MSG_prefs_OptionText_add_tags_exclusions_exact_match_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="add_tags_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags_hide_exclusions__</span></td>
|
||||
<td>
|
||||
|
|
@ -89,9 +98,9 @@
|
|||
</table>
|
||||
<div id="addtags_prompt_container">
|
||||
<span class="section_title">__MSG_AddTags_prompt_text_title__</span><span id="addtags_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_more_info_string__</a>
|
||||
<br>__MSG_prefs_OptionText_btnManagePrompts_infoline3__
|
||||
<br><b>__MSG_prefs_OptionText_btnManagePrompts_infoline2__</b></span>
|
||||
<br><b>__MSG_prefs_OptionText_AdvancedPromptResponse_infoline2__</b></span>
|
||||
<br>
|
||||
<div class="autocomplete-container">
|
||||
<textarea id="addtags_prompt_text" rows="15"></textarea>
|
||||
|
|
|
|||
|
|
@ -214,16 +214,15 @@ 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;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
options[element.id] = element.value;
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
||||
browser.storage.sync.set(options);
|
||||
|
|
|
|||
360
pages/customdataplaceholders/mzta-custom-dataplaceholders.css
Normal file
360
pages/customdataplaceholders/mzta-custom-dataplaceholders.css
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
@media (prefers-color-scheme: light) {
|
||||
table th {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#command_palette{
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
table.prompts_list tr:nth-child(even) {
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
|
||||
table.prompts_list tr:nth-child(odd) {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
thead {
|
||||
position: sticky;
|
||||
top: 26px;
|
||||
z-index: 90;
|
||||
}
|
||||
|
||||
#command_palette{
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding-top: 1px;
|
||||
height: 26px;
|
||||
width: 100%;
|
||||
z-index: 90;
|
||||
}
|
||||
|
||||
#btnNew{
|
||||
float: right;
|
||||
}
|
||||
|
||||
#btnSaveAll{
|
||||
float: left;
|
||||
}
|
||||
|
||||
#msgDisplay{
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
table tr {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
table.prompts_list th {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table td.w08{
|
||||
width: 8vw;
|
||||
}
|
||||
|
||||
table td.w17{
|
||||
width: 17vw;
|
||||
}
|
||||
|
||||
table td.w19{
|
||||
width: 19vw;
|
||||
}
|
||||
|
||||
table td.w25{
|
||||
width: 25vw;
|
||||
}
|
||||
|
||||
table td.w40{
|
||||
width: 40vw;
|
||||
}
|
||||
|
||||
table.prompts_list td.properties{
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
table .sort {
|
||||
background-image: url(../images/listjs-arrow-sort-inactive.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
padding-right: 14px;
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
}
|
||||
|
||||
table .sort.asc {
|
||||
background-image: url(../images/listjs-arrow-sort-active-down.png);
|
||||
}
|
||||
|
||||
table .sort.desc {
|
||||
background-image: url(../images/listjs-arrow-sort-active-up.png);
|
||||
}
|
||||
|
||||
tbody.list tr{
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.hiddendata{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#formNew{
|
||||
display: none;
|
||||
width: 100%;
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
.text_output{
|
||||
width: 98%;
|
||||
height: 9em;
|
||||
}
|
||||
|
||||
.go_right_float{
|
||||
float: right;
|
||||
}
|
||||
|
||||
.go_right{
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.width_all{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.small_label{
|
||||
font-size: small;
|
||||
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;
|
||||
}
|
||||
|
||||
#import_export{
|
||||
position: absolute;
|
||||
right:10px;
|
||||
top:10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#btnExportAll{
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.storage_space{
|
||||
font-size: 0.8em;
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
color: rgb(41, 41, 41);
|
||||
text-align: right;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.page_title{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.autocomplete-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.autocomplete-list {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
z-index: 1000;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.autocomplete-list li {
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.autocomplete-list li:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.autocomplete-list li.active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.need_custom_text_span, .need_selected_span{
|
||||
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_models_list_table{
|
||||
background-color: rgb(255, 209, 183);
|
||||
border:0;
|
||||
}
|
||||
|
||||
.chatgpt_web_models_list_table *{
|
||||
border:0;
|
||||
}
|
||||
|
||||
.chatgpt_web_models_list_table td{
|
||||
padding:2px;
|
||||
}
|
||||
|
||||
#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;
|
||||
color: rgb(251, 251, 254);
|
||||
}
|
||||
|
||||
a:link { color: #409EFF; }
|
||||
a:visited { color: #409EFF; }
|
||||
a:hover { color: #66B1FF; }
|
||||
a:active { color: #66B1FF; }
|
||||
|
||||
table {
|
||||
background-color: #1C1B22;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
table.prompts_list th {
|
||||
background-color: #4c4e58;
|
||||
border: 1px solid rgb(251, 251, 254);
|
||||
color: rgb(194, 194, 194);
|
||||
}
|
||||
|
||||
#command_palette{
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
table.prompts_list tr:nth-child(even) {
|
||||
background-color: #2E2F36;
|
||||
}
|
||||
|
||||
.storage_space{
|
||||
color: rgb(182, 182, 182);
|
||||
}
|
||||
|
||||
.autocomplete-list {
|
||||
background-color: #2E2F36;
|
||||
border: 1px solid #2E2F36;
|
||||
}
|
||||
|
||||
.autocomplete-list li:hover {
|
||||
background-color: #4c4e58;
|
||||
}
|
||||
|
||||
.autocomplete-list li.active {
|
||||
background-color: #4c4e58;
|
||||
}
|
||||
|
||||
#chatgpt_web_additional_info, #chatgpt_web_additional_info_toggle, .chatgpt_web_additional_info, .chatgpt_web_additional_info_toggle, .chatgpt_web_additional_info_show, .chatgpt_web_models_list_table{
|
||||
background-color: rgb(39, 11, 0);
|
||||
color: rgb(182, 182, 182);
|
||||
}
|
||||
|
||||
#chatgpt_web_additional_info_toggle:hover, .chatgpt_web_additional_info_toggle:hover{
|
||||
background-color: rgb(88, 25, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ThunderAI - __MSG_customDataPH_manageDataPH__</title>
|
||||
<link rel="stylesheet" href="mzta-custom-dataplaceholders.css">
|
||||
<link rel="icon" href="../../images/icon-16px.png">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1 class="page_title">__MSG_customDataPH_manageDataPH__</h1>
|
||||
<p>__MSG_customDataPH_manageDataPH_info_default__
|
||||
<br>__MSG_customDataPH_manageDataPH_info_default_3__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_more_info_string__</a>
|
||||
<!--<br><button id="btnManagePrompts">__MSG_prefs_OptionText_btnManagePrompts__</button>-->
|
||||
</p>
|
||||
</div>
|
||||
<div id="import_export">
|
||||
<button id="btnExportAll">__MSG_customDataPH_ExportAll__</button><br>
|
||||
<button id="btnImport">__MSG_customDataPH_Import__</button>
|
||||
</div>
|
||||
<div id="command_palette">
|
||||
<button id="btnSaveAll" disabled>__MSG_btnSaveAll_string__</button>
|
||||
<span id="msgDisplay"></span>
|
||||
<button id="btnNew">__MSG_btnNew_string__</button>
|
||||
</div>
|
||||
<div id="formNew">
|
||||
<table class="width_all">
|
||||
<tr>
|
||||
<td class="w19">
|
||||
<label for="txtIdNew" class="field_title">*__MSG_customPrompts_form_label_ID__:</label>
|
||||
<br>
|
||||
<i>thunderai_custom_</i><input type="text" id="txtIdNew" name="id" class="input_new" tabindex="1">
|
||||
<br><span class="small_label">[__MSG_customPrompts_form_label_ID_rules__]</span>
|
||||
</td>
|
||||
<td rowspan="2" class="w25">
|
||||
<label for="txtTextNew" class="field_title">*__MSG_customDataPH_form_label_Text__:</label>
|
||||
<br>
|
||||
<div class="autocomplete-container">
|
||||
<textarea id="txtTextNew" name="text" class="input_new text_output editor" tabindex="3"></textarea>
|
||||
<ul class="autocomplete-list hidden"></ul>
|
||||
</div>
|
||||
</td>
|
||||
<td rowspan="2" class="w19">
|
||||
<label for="selectTypeNew" class="field_title">__MSG_customDataPH_add_to_menu__:</label>
|
||||
<br>
|
||||
<select id="selectTypeNew" name="type" tabindex="4" class="type_output">
|
||||
<option value="0">__MSG_customPrompts_add_to_menu_always__</option>
|
||||
<option value="1">__MSG_customPrompts_add_to_menu_reading__</option>
|
||||
<option value="2">__MSG_customPrompts_add_to_menu_composing__</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="w19">
|
||||
<label for="txtNameNew" class="field_title">*__MSG_customPrompts_form_label_Name__:</label>
|
||||
<br>
|
||||
<input type="text" id="txtNameNew" name="name" class="input_new" tabindex="2">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="go_right_float">* __MSG_customPrompts_form_required_fields__</div>
|
||||
<br>
|
||||
<div class="go_right"><button id="btnAddNew" disabled>__MSG_customDataPH_btnAddNewCommit__</button></div>
|
||||
</div>
|
||||
<div id="all_custom_dataplaceholders">
|
||||
<table class="prompts_list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort" data-sort="id">__MSG_customPrompts_form_label_ID__</th>
|
||||
<th class="sort" data-sort="name">__MSG_customPrompts_form_label_Name__</th>
|
||||
<th class="sort" data-sort="text">__MSG_customDataPH_form_label_Text__</th>
|
||||
<th>__MSG_customPrompts_Properties__</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="storage_space">__MSG_StorageSpace__: <span id="storage_space"></span></div>
|
||||
<script src="../_lib/list.js"></script>
|
||||
<script src="mzta-custom-dataplaceholders.js" type="module"></script>
|
||||
<script src="../../js/mzta-i18n.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
561
pages/customdataplaceholders/mzta-custom-dataplaceholders.js
Normal file
561
pages/customdataplaceholders/mzta-custom-dataplaceholders.js
Normal file
|
|
@ -0,0 +1,561 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 - 2025 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { prefs_default } from "../../options/mzta-options-default.js";
|
||||
import { getLocalStorageUsedSpace, sanitizeHtml, isThunderbird128OrGreater, openTab } from "../../js/mzta-utils.js";
|
||||
import { taLogger } from "../../js/mzta-logger.js";
|
||||
import { getPlaceholders, setCustomPlaceholders, getCustomPlaceholders, prepareCustomDataPHsForExport, prepareCustomDataPHsForImport, placeholdersUtils } from "../../js/mzta-placeholders.js";
|
||||
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
|
||||
|
||||
let prefs = null;
|
||||
var customDataPHsList = null;
|
||||
var somethingChanged = false;
|
||||
var idnumMax = 0;
|
||||
var msgTimeout = null;
|
||||
let taLog = null;
|
||||
let autocompleteSuggestions = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
prefs = await browser.storage.sync.get({ do_debug: prefs_default.do_debug });
|
||||
taLog = new taLogger("mzta-custom-dataplaceholders", prefs.do_debug);
|
||||
|
||||
setStorageSpace();
|
||||
|
||||
let values = await getCustomPlaceholders();
|
||||
|
||||
//console.log('>>>>>>>>>>>>>>>> values: ' + JSON.stringify(values));
|
||||
|
||||
loadCustomDataPHsList(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';
|
||||
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())
|
||||
.filter(p => p.is_default == "1")
|
||||
.map(p => ({ command: '{%' + p.id + '%}', type: p.type }));
|
||||
|
||||
// console.log('>>>>>>>>>>> suggestions: ' + JSON.stringify(suggestions));
|
||||
|
||||
textareas.forEach(textarea => {
|
||||
textareaAutocomplete(textarea, autocompleteSuggestions);
|
||||
textareas.forEach(textarea => {
|
||||
textareaAutocomplete(textarea, autocompleteSuggestions);
|
||||
});
|
||||
});
|
||||
|
||||
i18n.updateDocument();
|
||||
|
||||
//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');
|
||||
|
||||
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,
|
||||
enabled: 1,
|
||||
is_default: 0,
|
||||
idnum: idnumMax + 1,
|
||||
};
|
||||
|
||||
let newItem = customDataPHsList.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);
|
||||
//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();
|
||||
exportCustomDataPHs();
|
||||
});
|
||||
|
||||
async function exportCustomDataPHs() {
|
||||
const manifest = browser.runtime.getManifest();
|
||||
const addonVersion = manifest.version;
|
||||
const outputCustomDataPHs = prepareCustomDataPHsForExport(await getCustomPlaceholders());
|
||||
let outputObj = {id: 'thunderai-custom-data-placeholders', addon_version: addonVersion, customdataplaceholders: outputCustomDataPHs};
|
||||
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-custom-data-placeholders-${time_stamp}.json`,
|
||||
saveAs: true,
|
||||
});
|
||||
}
|
||||
|
||||
const btnImport = document.getElementById('btnImport');
|
||||
btnImport.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
importCustomDataPHs();
|
||||
});
|
||||
|
||||
function importCustomDataPHs() {
|
||||
if(confirm(browser.i18n.getMessage("importCustomDataPH_confirmText") + '\n' + browser.i18n.getMessage("customDataPH_manageDataPH_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 importCustomDataPHs(), 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('importCustomDataPH_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-custom-data-placeholders') {
|
||||
alert(browser.i18n.getMessage("importCustomDataPH_invalidFile"));
|
||||
setMessage(browser.i18n.getMessage('importCustomDataPH_invalidFile'),'red');
|
||||
return;
|
||||
}
|
||||
// if(obj.addon_version !== manifest.version) {
|
||||
// alert(browser.i18n.getMessage("importPrompts_invalidVersion"));
|
||||
// return;
|
||||
// }
|
||||
if(!Array.isArray(obj.customdataplaceholders)) {
|
||||
alert(browser.i18n.getMessage("importCustomDataPH_invalidDataPHs"));
|
||||
setMessage(browser.i18n.getMessage('importCustomDataPH_invalidDataPHs'),'red');
|
||||
return;
|
||||
}
|
||||
customDataPHsList.clear();
|
||||
loadCustomDataPHsList(await prepareCustomDataPHsForImport(obj.customdataplaceholders));
|
||||
setSomethingChanged();
|
||||
i18n.updateDocument();
|
||||
setMessage(browser.i18n.getMessage('importCustomDataPH_import_completed'), 'orange');
|
||||
} catch(err) {
|
||||
alert(browser.i18n.getMessage("importCustomDataPH_invalidFile") + ' ' + err);
|
||||
setMessage(browser.i18n.getMessage('importCustomDataPH_invalidFile'),'red');
|
||||
return;
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
document.getElementById('btnManagePrompts').addEventListener('click', () => {
|
||||
openTab('/pages/customprompts/mzta-custom-prompts.html');
|
||||
});
|
||||
|
||||
}, { once: true });
|
||||
|
||||
//========= handling an item in a row
|
||||
function handleEditClick(e) {
|
||||
e.preventDefault();
|
||||
const tr = e.target.parentNode.parentNode;
|
||||
//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('.btnDeleteItem').style.display = 'none'; // Delete btn
|
||||
showItemRowEditor(tr);
|
||||
}
|
||||
|
||||
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';
|
||||
tr.querySelector('.type_output').style.display = 'inline';
|
||||
tr.querySelector('.type_show').style.display = 'none';
|
||||
}
|
||||
|
||||
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('.type_output').style.display = 'none';
|
||||
tr.querySelector('.type_show').style.display = 'inline';
|
||||
}
|
||||
|
||||
// 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'));
|
||||
customDataPHsList.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('.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(/<br\s*\/?>/gi, "\n");
|
||||
tr.querySelector('.type_output').value = tr.querySelector('.type').innerText;
|
||||
hideItemRowEditor(tr);
|
||||
}
|
||||
|
||||
function handleConfirmClick(e) {
|
||||
e.preventDefault();
|
||||
const tr = e.target.parentNode.parentNode;
|
||||
e.target.style.display = 'none'; // Ok btn
|
||||
// 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('.btnDeleteItem').style.display = 'inline'; // Delete btn
|
||||
// Update item data
|
||||
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('.type').innerText = tr.querySelector('.type_output').value;
|
||||
tr.querySelector('.type_show').innerText = tr.querySelector('.type_output').selectedOptions[0].text;
|
||||
// the checkboxes update is handled directly by themselves
|
||||
hideItemRowEditor(tr);
|
||||
setSomethingChanged();
|
||||
}
|
||||
|
||||
// Enable save button on input change
|
||||
function handleInputChange(e) {
|
||||
e.preventDefault();
|
||||
setSomethingChanged();
|
||||
}
|
||||
|
||||
//========= handling an item in a row - END
|
||||
|
||||
|
||||
function loadCustomDataPHsList(values){
|
||||
// console.log('>>>>>>>> loadCustomDataPHsList values: ' + JSON.stringify(values));
|
||||
let options = {
|
||||
valueNames: [
|
||||
{ data: ['idnum'] },
|
||||
'is_default',
|
||||
'id',
|
||||
'name',
|
||||
'text',
|
||||
'type',
|
||||
{ name: 'enabled', attr: 'checked_val'}
|
||||
],
|
||||
item: function(values) {
|
||||
values.id = placeholdersUtils.stripCustomDataPH_ID_Prefix(values.id);
|
||||
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 output = `<tr ` + ((values.is_default == 1) ? 'class="is_default"':'') + `>
|
||||
<td class="w08"><i>thunderai_custom_</i><span class="id id_show"></span><input type="text" class="hiddendata id_output" value="` + values.id + `" /></td>
|
||||
<td class="w08"><span class="name name_show"></span><input type="text" class="hiddendata name_output" value="` + values.name + `" /></td>
|
||||
<td class="w40">
|
||||
<span class="text text_show"></span>
|
||||
<div class="autocomplete-container">
|
||||
<textarea class="hiddendata text_output editor">` + values.text.replace(/<br\s*\/?>/gi, "\n") + `</textarea>
|
||||
<ul class="autocomplete-list hidden"></ul>
|
||||
</div>
|
||||
</td>
|
||||
<td class="w08"><span class="field_title_s">__MSG_customDataPH_add_to_menu__:</span>
|
||||
<br>
|
||||
<span class="type_show">` + type_output + `</span>
|
||||
<select class="type_output hiddendata">
|
||||
<option value="0"` + ((values.type == "0") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_always__</option>
|
||||
<option value="1"` + ((values.type == "1") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_reading__</option>
|
||||
<option value="2"` + ((values.type == "2") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_composing__</option>
|
||||
</select>` +
|
||||
`<span class="type hiddendata"></span>
|
||||
</td>
|
||||
<td class="w17">
|
||||
<label><input type="checkbox" class="enabled input_mod"> __MSG_customPrompts_form_label_enabled__</label>
|
||||
<span class="is_default hiddendata"></span>
|
||||
<span class="position_compose hiddendata"></span>
|
||||
<span class="position_display hiddendata"></span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btnEditItem"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnEdit__</button>
|
||||
<button class="btnCancelItem hiddendata"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnCancel__</button>
|
||||
<br><br>
|
||||
<button class="btnConfirmItem hiddendata"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnOK__</button>
|
||||
<button class="btnDeleteItem"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnDelete__</button>
|
||||
</td>
|
||||
</tr>`;
|
||||
//console.log('>>>>>>>> values.name: ' + JSON.stringify(values.name));
|
||||
idnumMax = Math.max(idnumMax, values.idnum);
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
// console.log('>>>>>>>>>>>>> options: ' + JSON.stringify(options));
|
||||
// console.log('>>>>>>>>>>>>> values: ' + JSON.stringify(values));
|
||||
|
||||
customDataPHsList = new List('all_custom_dataplaceholders', options, values);
|
||||
|
||||
checkSelectedBoxes();
|
||||
let btnEditItem_elements = document.querySelectorAll(".btnEditItem");
|
||||
btnEditItem_elements.forEach(element => {
|
||||
element.addEventListener('click', handleEditClick);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.input_mod').forEach(element => {
|
||||
element.addEventListener('change', handleInputChange);
|
||||
});
|
||||
}
|
||||
|
||||
function checkFields() {
|
||||
//console.log('>>>>>>>>>>>>> typeof customDataPHsList: ' + typeof customDataPHsList);
|
||||
//console.log('>>>>>>>>>>>>> Array.isArray(customDataPHsList): ' + Array.isArray(customDataPHsList));
|
||||
// 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 = customDataPHsList.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('selectTypeNew').value = '0';
|
||||
document.getElementById('formNew').style.display = 'none';
|
||||
}
|
||||
|
||||
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('.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 custom data placeholders
|
||||
async function saveAll() {
|
||||
setMessage(browser.i18n.getMessage('customDataPH_saving_custom'));
|
||||
setNothingChanged();
|
||||
if(customDataPHsList != null) {
|
||||
setMessage(browser.i18n.getMessage('customPrompts_reindexing_list'));
|
||||
customDataPHsList.reIndex();
|
||||
let newCustomDataPHs = customDataPHsList.items.filter(item => item.values().is_default == 0).map(item => item.values());
|
||||
taLog.log('newCustomDataPlaceholders: ' + JSON.stringify(newCustomDataPHs));
|
||||
// newCustomDataPHs.forEach(prompt => {
|
||||
// console.log('>>>>>>>>>>>>> id: ' + JSON.stringify(prompt));
|
||||
// });
|
||||
//console.log('>>>>>>>>>>>>> saveAll: ' + JSON.stringify(newCustomDataPHs));
|
||||
await setCustomPlaceholders(newCustomDataPHs);
|
||||
setMessage(browser.i18n.getMessage('customDataPH_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;
|
||||
}
|
||||
|
||||
|
||||
if(await isThunderbird128OrGreater()){
|
||||
window.addEventListener('beforeunload', function (event) {
|
||||
// Check if any changes have been made (Only for Thunderbird 128+ see https://github.com/micz/ThunderAI/issues/88)
|
||||
if (somethingChanged) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -11,17 +11,18 @@
|
|||
<h1 class="page_title">__MSG_customPrompts_managePrompts__</h1>
|
||||
<p>__MSG_customPrompts_managePrompts_info_default__<br>
|
||||
__MSG_customPrompts_managePrompts_info_default_2__<br>
|
||||
__MSG_customPrompts_managePrompts_info_default_3__ <a href="https://micz.it/thunderbird-addon-thunderai/custom-prompts/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br>__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a></p>
|
||||
__MSG_customPrompts_managePrompts_info_default_3__ <a href="https://micz.it/thunderbird-addon-thunderai/custom-prompts/">__MSG_more_info_string__</a>
|
||||
<br>__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_more_info_string__</a>
|
||||
<br><button id="btnManageCustomDataPH">__MSG_prefs_OptionText_btnManageCustomDataPH__</button></p>
|
||||
</div>
|
||||
<div id="import_export">
|
||||
<button id="btnExportAll">__MSG_customPrompts_ExportAll__</button><br>
|
||||
<button id="btnImport">__MSG_customPrompts_Import__</button>
|
||||
</div>
|
||||
<div id="command_palette">
|
||||
<button id="btnSaveAll" disabled>__MSG_customPrompts_btnSaveAll__</button>
|
||||
<button id="btnSaveAll" disabled>__MSG_btnSaveAll_string__</button>
|
||||
<span id="msgDisplay"></span>
|
||||
<button id="btnNew">__MSG_customPrompts_btnNew__</button>
|
||||
<button id="btnNew">__MSG_btnNew_string__</button>
|
||||
</div>
|
||||
<div id="formNew">
|
||||
<table class="width_all">
|
||||
|
|
@ -122,7 +123,7 @@
|
|||
</table>
|
||||
</div>
|
||||
<div class="storage_space">__MSG_StorageSpace__: <span id="storage_space"></span></div>
|
||||
<script src="list.js"></script>
|
||||
<script src="../_lib/list.js"></script>
|
||||
<script src="mzta-custom-prompts.js" type="module"></script>
|
||||
<script src="../../js/mzta-i18n.js"></script>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@
|
|||
|
||||
import { prefs_default } from "../../options/mzta-options-default.js";
|
||||
import { getPrompts, setDefaultPromptsProperties, setCustomPrompts, preparePromptsForExport, preparePromptsForImport } from "../../js/mzta-prompts.js";
|
||||
import { ChatGPTWeb_models, isThunderbird128OrGreater, getCustomPromptsUsedSpace, sanitizeHtml, validateCustomData_ChatGPTWeb, getChatGPTWebModelsList_HTML } from "../../js/mzta-utils.js";
|
||||
import { ChatGPTWeb_models, isThunderbird128OrGreater, getLocalStorageUsedSpace, sanitizeHtml, validateCustomData_ChatGPTWeb, getChatGPTWebModelsList_HTML, openTab } from "../../js/mzta-utils.js";
|
||||
import { taLogger } from "../../js/mzta-logger.js";
|
||||
import { getPlaceholders } from "../../js/mzta-placeholders.js";
|
||||
import { getPlaceholders, placeholdersUtils } from "../../js/mzta-placeholders.js";
|
||||
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
|
||||
|
||||
let prefs = null;
|
||||
|
|
@ -78,7 +78,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
let btnNew_elements = document.querySelectorAll(".input_new");
|
||||
if(btnNew_elements) {
|
||||
btnNew_elements.forEach(element => {
|
||||
element.addEventListener('change', (e) => {
|
||||
element.addEventListener('input', (e) => {
|
||||
e.preventDefault();
|
||||
checkFields();
|
||||
});
|
||||
|
|
@ -88,13 +88,13 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
const textareas = document.querySelectorAll('.editor');
|
||||
autocompleteSuggestions = (await getPlaceholders(true)).map(p => ({command: '{%'+p.id+'%}', type: p.type}));
|
||||
|
||||
// console.log('>>>>>>>>>>> suggestions: ' + JSON.stringify(suggestions));
|
||||
// console.log('>>>>>>>>>>> autocompleteSuggestions: ' + JSON.stringify(autocompleteSuggestions));
|
||||
|
||||
textareas.forEach(textarea => {
|
||||
textareaAutocomplete(textarea, autocompleteSuggestions);
|
||||
textareas.forEach(textarea => {
|
||||
textarea.addEventListener('input', (e) => {
|
||||
checkPromptsConfigForPlaceholders(e.target);
|
||||
textarea.addEventListener('input', async (e) => {
|
||||
await checkPromptsConfigForPlaceholders(e.target);
|
||||
});
|
||||
textareaAutocomplete(textarea, autocompleteSuggestions);
|
||||
});
|
||||
|
|
@ -161,7 +161,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
//To add a new item
|
||||
var txtIdNew = document.getElementById('txtIdNew');
|
||||
var txtNameNew = document.getElementById('txtNameNew');
|
||||
|
|
@ -370,6 +369,10 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
|
||||
}, { 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();
|
||||
|
|
@ -588,13 +591,13 @@ function handleConfirmClick(e) {
|
|||
}
|
||||
|
||||
// Handle checkbox changes and log new state
|
||||
function handleCheckboxChange(e) {
|
||||
async function handleCheckboxChange(e) {
|
||||
e.preventDefault();
|
||||
e.target.setAttribute('checked_val', 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');
|
||||
checkPromptsConfigForPlaceholders(textarea);
|
||||
await checkPromptsConfigForPlaceholders(textarea);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -936,7 +939,7 @@ function clearMessage() {
|
|||
}
|
||||
|
||||
async function setStorageSpace() {
|
||||
let storage_space = await getCustomPromptsUsedSpace();
|
||||
let storage_space = await getLocalStorageUsedSpace();
|
||||
document.getElementById('storage_space').textContent = storage_space;
|
||||
}
|
||||
|
||||
|
|
@ -950,11 +953,15 @@ if(await isThunderbird128OrGreater()){
|
|||
});
|
||||
}
|
||||
|
||||
function checkPromptsConfigForPlaceholders(textarea){
|
||||
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(String(textarea.value).indexOf('{%additional_text%}') != -1){
|
||||
if(String(curr_text).indexOf('{%additional_text%}') != -1){
|
||||
if(!need_custom_text_element.checked){
|
||||
need_custom_text_element.closest('.need_custom_text_span').style.border = '2px solid red';
|
||||
}else{
|
||||
|
|
@ -966,7 +973,7 @@ function checkPromptsConfigForPlaceholders(textarea){
|
|||
|
||||
let tr_ancestor2 = textarea.closest('tr');
|
||||
let selected_text_element = tr_ancestor2.querySelector('.need_selected') || tr_ancestor2.querySelector('.need_selected_new');
|
||||
if((String(textarea.value).indexOf('{%selected_text%}') != -1)||(String(textarea.value).indexOf('{%selected_html%}') != -1)){
|
||||
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{
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@
|
|||
</table>
|
||||
<div id="get_calendar_event_container">
|
||||
<span class="section_title">__MSG_GetCalendarEvent_prompt_text_title__</span><span id="get_calendar_event_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br><b>__MSG_prefs_OptionText_GetCalendarEvent_infoline2__</b></span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_more_info_string__</a>
|
||||
<br><b>__MSG_prefs_OptionText_AdvancedPromptResponse_infoline2__</b></span>
|
||||
<br>
|
||||
<div class="autocomplete-container">
|
||||
<textarea id="get_calendar_event_prompt_text" rows="15"></textarea>
|
||||
|
|
|
|||
|
|
@ -97,12 +97,11 @@ function saveOptions(e) {
|
|||
case 'password':
|
||||
options[element.id] = element.value.trim();
|
||||
break;
|
||||
case 'select-one':
|
||||
options[element.id] = element.value;
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
options[element.id] = element.value;
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
||||
browser.storage.sync.set(options);
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@
|
|||
</table>
|
||||
<div id="get_task_container">
|
||||
<span class="section_title">__MSG_GetCalendarEvent_prompt_text_title__</span><span id="get_task_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br><b>__MSG_prefs_OptionText_GetCalendarEvent_infoline2__</b></span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_more_info_string__</a>
|
||||
<br><b>__MSG_prefs_OptionText_AdvancedPromptResponse_infoline2__</b></span>
|
||||
<br>
|
||||
<div class="autocomplete-container">
|
||||
<textarea id="get_task_prompt_text" rows="15"></textarea>
|
||||
|
|
|
|||
|
|
@ -97,12 +97,11 @@ function saveOptions(e) {
|
|||
case 'password':
|
||||
options[element.id] = element.value.trim();
|
||||
break;
|
||||
case 'select-one':
|
||||
options[element.id] = element.value;
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
options[element.id] = element.value;
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
||||
browser.storage.sync.set(options);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@
|
|||
</tr>
|
||||
</table>
|
||||
<div id="spamfilter_container">
|
||||
<span class="section_title">__MSG_GetCalendarEvent_prompt_text_title__</span><span id="spamfilter_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br><b>__MSG_prefs_OptionText_GetCalendarEvent_infoline2__</b></span>
|
||||
<span class="section_title">__MSG_SpamFilter_prompt_text_title__</span><span id="spamfilter_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_more_info_string__</a>
|
||||
<br><b>__MSG_prefs_OptionText_AdvancedPromptResponse_infoline2__</b></span>
|
||||
<br>
|
||||
<div class="autocomplete-container">
|
||||
<textarea id="spamfilter_prompt_text" rows="15"></textarea>
|
||||
|
|
|
|||
|
|
@ -210,12 +210,11 @@ function saveOptions(e) {
|
|||
case 'password':
|
||||
options[element.id] = element.value.trim();
|
||||
break;
|
||||
case 'select-one':
|
||||
options[element.id] = element.value;
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
options[element.id] = element.value;
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
|
||||
browser.storage.sync.set(options);
|
||||
|
|
|
|||
Loading…
Reference in a new issue