Merge branch 'v4.0.0' into main

This commit is contained in:
yonie 2026-02-12 21:10:43 +01:00 committed by GitHub
commit 1630b7c071
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 760 additions and 50 deletions

View file

@ -14,8 +14,19 @@
<li><i>[OpenAI Comp API][Ollama API]</i> Asking for the single host for permission to avoid CORS errors, instead of <i>all_urls</i>, as requested by the Thunderbird Review Team [<a href="https://github.com/micz/ThunderAI/issues/524">#524</a>].</li>
<li>Fix: Using also the mail folder owner to search for the right identity to use when composing a reply [<a href="https://github.com/micz/ThunderAI/issues/627">#627</a>].</li>
<li>Context menu items are always ordered alfabetically [<a href="https://github.com/micz/ThunderAI/issues/630">#630</a>].</li>
<li>The prompt export now includes an option to incorporate specific API settings, when present [<a href="https://github.com/micz/ThunderAI/issues/624">#624</a>].</li>
<li>Added the <i>{%mail_text_body_or_selected%}</i> placeholder to retrieve the selected text or the full text body of the email if no selection is present [<a href="https://github.com/micz/ThunderAI/issues/641">#641</a>].</li>
<li>Added the <i>{%mail_html_body_or_selected%}</i> placeholder to retrieve the selected HTML or the full HTML body of the email if no selection is present [<a href="https://github.com/micz/ThunderAI/issues/641">#641</a>].</li>
<li><i>[All APIs]</i> Added an option to get a calendar event without selecting some text, but using the full text body of the email [<a href="https://github.com/micz/ThunderAI/issues/518">#518</a>].</li>
<li><i>[All APIs]</i> Added a new menu item to create a calendar event from the text saved in the clipboard [<a href="https://github.com/micz/ThunderAI/issues/362">#362</a>].</li>
<li>Added a button to copy a prompt in the Custom Prompts page [<a href="https://github.com/micz/ThunderAI/issues/598">#598</a>].</li>
<li><i>[All APIs]</i> Showing the spam filter info at the top of the message. The data is saved only for the session in which the message has been checked for spam [<a href="https://github.com/micz/ThunderAI/issues/506">#506</a>].</li>
<li>...</li>
</ul>
<h2>Version 3.8.4 - 10/02/2026</h2>
<ul>
<li><i>[ChatGPT Web]</i> Fix: Correctly importing the selected text into the compose windows also when ChatGPT shows the advanced mail editor in the response [<a href="https://github.com/micz/ThunderAI/issues/646">#646</a>].</li>
</ul>
<h2>Version 3.8.3 - 22/01/2026</h2>
<ul>
<li>Fix: Correctly saving the API settings in new custom prompts [<a href="https://github.com/micz/ThunderAI/issues/623">#623</a>].</li>

View file

@ -18,6 +18,9 @@ ThunderAI is a Mozilla Thunderbird add-on that integrates Large Language Models
- **i18n:**
- The project supports multiple languages via `_locales/`. When adding UI strings, always use `messenger.i18n.getMessage()`.
- When you need to modify language file, modify only the english version.
- **Logging:**
- When possibile use the taLog object to log errors, otherwise use the console.error(<msg>) method.
- If it's useful to log add debug logs using taLog.log(<msg>) method.
## Files & Directories Structure
- `manifest.json`: Extension entry point and permission definitions.

View file

@ -51,6 +51,12 @@ Using an API integration, you can activate some automatic features:
> - **OpenAI Compatible API**
> - You can also use a local OpenAI Compatible API server, like LM Studio or Mistral AI!
> - There is also an option to remove the "v1" segment from the API url, if needed, and to manually set the model name if the server doesn't have a models list endpoint.
> - You can also use one of these predefined configurations:
> - DeepSeek API
> - Grok API
> - Mistral API
> - OpenRouter API
> - Perplexity API
@ -95,7 +101,7 @@ Are you using this addon in your Thunderbird?
- Português Brasileiro (pt-br): Bruno Pereira de Souza <img src="https://micz.it/weblate/thunderai/pt-br.svg">
- Russian (ru): [Maksim](https://hosted.weblate.org/user/law820314/) <img src="https://micz.it/weblate/thunderai/ru.svg">
- Spanish (es): [Gerardo Sobarzo](https://hosted.weblate.org/user/gerardo.sobarzo/), [Andrés Rendón Hernández](https://hosted.weblate.org/user/arendon/), [Erick Limon](https://hosted.weblate.org/user/ErickLimonG/) <img src="https://micz.it/weblate/thunderai/es.svg">
- Swedish (sv): [Andreas Pettersson](https://hosted.weblate.org/user/Andy_tb/) <img src="https://micz.it/weblate/thunderai/sv.svg">
- Swedish (sv): [Andreas Pettersson](https://hosted.weblate.org/user/Andy_tb/) , [Luna Jernberg](https://hosted.weblate.org/user/bittin1ddc447d824349b2/) <img src="https://micz.it/weblate/thunderai/sv.svg">
<br>
Do you want to help translate this addon? [Find out how!](https://micz.it/thunderbird-addon-thunderai/translate/) <br>

View file

@ -2,7 +2,7 @@ file: pages\_lib\list.js
source: https://raw.githubusercontent.com/javve/list.js/v2.3.1/dist/list.js
file: pages\_lib\tom-select.base.js
source: https://cdn.jsdelivr.net/npm/tom-select@2.4.4/dist/js/tom-select.base.js
source: https://cdn.jsdelivr.net/npm/tom-select@2.4.6/dist/js/tom-select.base.js
file: js\lib\diff.js
source: https://cdnjs.cloudflare.com/ajax/libs/jsdiff/7.0.0/diff.js

View file

@ -795,7 +795,7 @@
"message": "Spravovat nastavení štítků"
},
"prompt_get_calendar_event_full_text": {
"message": "Z následujícího textu extrahuj všechny relevantní podrobnosti potřebné k vygenerování události kalendáře. Extrahované informace by měly zahrnovat:\n- Název události\n- Datum a čas zahájení (včetně časového pásma, pokud je uvedeno)\n- Datum a čas ukončení (včetně časového pásma, pokud je uvedeno)\n- Celý den (pokud je zmíněn)\n- Účastníci\nZajisti, aby byla data formátována jasně a konzistentně, aby je bylo možné přímo použít k vytvoření události kalendáře.\nPokud existují relativní časové odkazy, vezmi v úvahu, že datum a čas e-mailu jsou \"{%mail_datetime%}\". Vypočítej datum a čas zahájení na základě tohoto odkazu. Pokud jsou vypočítané datum a čas zahájení dřívější než \"{%current_datetime%}\", přepočti datum a čas zahájení pomocí \"{%current_datetime%}\" jako základu.\nPokud není zadána doba trvání, nastav ji na jednu hodinu.\nToto jsou účastníci: {%author%}, {%recipients%}, {%cc_list%}. Pokud je přítomna, nezahrnuj mou adresu: {%account_email_address%}.\nPokud nejsi schopen získat jednu nebo více požadovaných informací, odpověz prázdným řetězcem.\nVygeneruj odpověď pouze ve formátu JSON. Nezahrnuj žádný další text ani vysvětlení; poskytni pouze JSON. Zde je formát, který se má použít:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Zde je souhrn události kalendáře\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nZde je text:\"{%selected_text%}\""
"message": "Z následujícího textu extrahuj všechny relevantní podrobnosti potřebné k vygenerování události kalendáře. Extrahované informace by měly zahrnovat:\n- Název události\n- Datum a čas zahájení (včetně časového pásma, pokud je uvedeno)\n- Datum a čas ukončení (včetně časového pásma, pokud je uvedeno)\n- Celý den (pokud je zmíněn)\n- Účastníci\nZajisti, aby byla data formátována jasně a konzistentně, aby je bylo možné přímo použít k vytvoření události kalendáře.\nPokud existují relativní časové odkazy, vezmi v úvahu, že datum a čas e-mailu jsou \"{%mail_datetime%}\". Vypočítej datum a čas zahájení na základě tohoto odkazu. Pokud jsou vypočítané datum a čas zahájení dřívější než \"{%current_datetime%}\", přepočti datum a čas zahájení pomocí \"{%current_datetime%}\" jako základu.\nPokud není zadána doba trvání, nastav ji na jednu hodinu.\nToto jsou účastníci: {%author%}, {%recipients%}, {%cc_list%}. Pokud je přítomna, nezahrnuj mou adresu: {%account_email_address%}.\nPokud nejsi schopen získat jednu nebo více požadovaných informací, odpověz prázdným řetězcem.\nVygeneruj odpověď pouze ve formátu JSON. Nezahrnuj žádný další text ani vysvětlení; poskytni pouze JSON. Zde je formát, který se má použít:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Zde je souhrn události kalendáře\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nZde je text:\"{%mail_text_body_or_selected%}\""
},
"prefs_OptionText_get_calendar_event": {
"message": "Přidat novou událost do kalendáře z vybraného textu"

View file

@ -697,7 +697,7 @@
"message": "Ein neues Kalenderevent hinzufügen"
},
"prompt_get_calendar_event_full_text": {
"message": "Extrahieren Sie alle relevanten Details, die erforderlich sind, um ein Kalenderevent aus dem folgenden Text zu erstellen. Die extrahierten Informationen sollten Folgendes enthalten:\n- Ereignistitel\n- Startdatum und -uhrzeit (einschließlich Zeitzone, falls angegeben)\n- Enddatum und -uhrzeit (einschließlich Zeitzone, falls angegeben)\n- Ganztägig (falls erwähnt)\n- Teilnehmer\nStellen Sie sicher, dass die Daten klar und konsistent formatiert sind, sodass sie direkt für die Erstellung eines Kalenderevents verwendet werden können.\nFalls relative Zeitangaben enthalten sind, beachten Sie, dass Datum und Uhrzeit der E-Mail \"{%mail_datetime%}\" sind. Berechnen Sie das Startdatum und die Startzeit basierend auf diesem Bezugspunkt. Falls das berechnete Startdatum und die Startzeit vor \"{%current_datetime%}\" liegen, berechnen Sie Startdatum und -zeit erneut, wobei Sie \"{%current_datetime%}\" als Grundlage verwenden.\nFalls keine Dauer angegeben ist, setzen Sie sie auf eine Stunde.\nDas sind die Teilnehmer: {%author%}, {%recipients%}, {%cc_list%}. Falls vorhanden, meine Adresse ausschließen: {%account_email_address%}.\nFalls Sie eine oder mehrere der erforderlichen Informationen nicht erhalten können, antworten Sie mit einem leeren String.\nErstellen Sie eine Antwort ausschließlich im JSON-Format. Fügen Sie keinen zusätzlichen Text oder Erklärungen hinzu; geben Sie nur das JSON an. Verwenden Sie folgendes Format:\n{\n \"startDate\": \"YYYYMMDDTHHMMSS\",\n \"endDate\": \"YYYYMMDDTHHMMSS\",\n \"summary\": \"Zusammenfassung des Kalenderevents hier\",\n \"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nHier ist der Text: \"{%selected_text%}\""
"message": "Extrahieren Sie alle relevanten Details, die erforderlich sind, um ein Kalenderevent aus dem folgenden Text zu erstellen. Die extrahierten Informationen sollten Folgendes enthalten:\n- Ereignistitel\n- Startdatum und -uhrzeit (einschließlich Zeitzone, falls angegeben)\n- Enddatum und -uhrzeit (einschließlich Zeitzone, falls angegeben)\n- Ganztägig (falls erwähnt)\n- Teilnehmer\nStellen Sie sicher, dass die Daten klar und konsistent formatiert sind, sodass sie direkt für die Erstellung eines Kalenderevents verwendet werden können.\nFalls relative Zeitangaben enthalten sind, beachten Sie, dass Datum und Uhrzeit der E-Mail \"{%mail_datetime%}\" sind. Berechnen Sie das Startdatum und die Startzeit basierend auf diesem Bezugspunkt. Falls das berechnete Startdatum und die Startzeit vor \"{%current_datetime%}\" liegen, berechnen Sie Startdatum und -zeit erneut, wobei Sie \"{%current_datetime%}\" als Grundlage verwenden.\nFalls keine Dauer angegeben ist, setzen Sie sie auf eine Stunde.\nDas sind die Teilnehmer: {%author%}, {%recipients%}, {%cc_list%}. Falls vorhanden, meine Adresse ausschließen: {%account_email_address%}.\nFalls Sie eine oder mehrere der erforderlichen Informationen nicht erhalten können, antworten Sie mit einem leeren String.\nErstellen Sie eine Antwort ausschließlich im JSON-Format. Fügen Sie keinen zusätzlichen Text oder Erklärungen hinzu; geben Sie nur das JSON an. Verwenden Sie folgendes Format:\n{\n \"startDate\": \"YYYYMMDDTHHMMSS\",\n \"endDate\": \"YYYYMMDDTHHMMSS\",\n \"summary\": \"Zusammenfassung des Kalenderevents hier\",\n \"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nHier ist der Text: \"{%mail_text_body_or_selected%}\""
},
"prefs_OptionText_get_calendar_event": {
"message": "Ein neues Kalenderevent aus ausgewähltem Text hinzufügen"

View file

@ -564,7 +564,7 @@
"message": "Προσθήκη νέου συμβάντος ημερολογίου"
},
"prompt_get_calendar_event_full_text": {
"message": "Εξαγάγετε όλες τις σχετικές λεπτομέρειες που απαιτούνται για τη δημιουργία ενός συμβάντος ημερολογίου από το ακόλουθο κείμενο. Οι εξαγόμενες πληροφορίες θα πρέπει να περιλαμβάνουν:\n- Τίτλο συμβάντος\n- Ημερομηνία και ώρα έναρξης (συμπεριλαμβανομένης της ζώνης ώρας, εάν καθορίζεται)\n- Ημερομηνία και ώρα λήξης (συμπεριλαμβανομένης της ζώνης ώρας, εάν καθορίζεται)\n- Ολόκληρη ημέρα (εάν αναφέρεται)\n- Συμμετέχοντες\nΒεβαιωθείτε ότι τα δεδομένα έχουν μορφοποιηθεί με σαφήνεια και συνέπεια, ώστε να μπορούν να χρησιμοποιηθούν άμεσα για τη δημιουργία ενός συμβάντος ημερολογίου.\nΕάν υπάρχουν σχετικές χρονικές αναφορές, λάβετε υπόψη ότι η ημερομηνία και η ώρα του email είναι \"{%mail_datetime%}\". Υπολογίστε την ημερομηνία και την ώρα έναρξης με βάση αυτήν την αναφορά. Εάν η υπολογισμένη ημερομηνία και ώρα έναρξης είναι προγενέστερες από το \"{%current_datetime%}\", υπολογίστε ξανά την ημερομηνία και την ώρα έναρξης χρησιμοποιώντας το \"{%current_datetime%}\" ως βάση.\nΕάν η διάρκεια δεν έχει καθοριστεί, ορίστε την σε μία ώρα.\nΑυτοί είναι οι συμμετέχοντες: {%author%}, {%recipients%}, {%cc_list%}. Εάν υπάρχει, εξαιρέστε τη διεύθυνσή μου: {%account_email_address%}.\nΕάν δεν μπορείτε να λάβετε μία ή περισσότερες από τις απαιτούμενες πληροφορίες, απαντήστε με μια κενή συμβολοσειρά.\nΔημιουργήστε μια απάντηση μόνο σε μορφή JSON. Μην συμπεριλάβετε κανένα επιπλέον κείμενο ή εξηγήσεις. Δώστε μόνο το JSON. Η μορφή που θα χρησιμοποιηθεί είναι η εξής:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Σύνοψη συμβάντος ημερολογίου εδώ\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nΤο κείμενο είναι: \"{%selected_text%}\""
"message": "Εξαγάγετε όλες τις σχετικές λεπτομέρειες που απαιτούνται για τη δημιουργία ενός συμβάντος ημερολογίου από το ακόλουθο κείμενο. Οι εξαγόμενες πληροφορίες θα πρέπει να περιλαμβάνουν:\n- Τίτλο συμβάντος\n- Ημερομηνία και ώρα έναρξης (συμπεριλαμβανομένης της ζώνης ώρας, εάν καθορίζεται)\n- Ημερομηνία και ώρα λήξης (συμπεριλαμβανομένης της ζώνης ώρας, εάν καθορίζεται)\n- Ολόκληρη ημέρα (εάν αναφέρεται)\n- Συμμετέχοντες\nΒεβαιωθείτε ότι τα δεδομένα έχουν μορφοποιηθεί με σαφήνεια και συνέπεια, ώστε να μπορούν να χρησιμοποιηθούν άμεσα για τη δημιουργία ενός συμβάντος ημερολογίου.\nΕάν υπάρχουν σχετικές χρονικές αναφορές, λάβετε υπόψη ότι η ημερομηνία και η ώρα του email είναι \"{%mail_datetime%}\". Υπολογίστε την ημερομηνία και την ώρα έναρξης με βάση αυτήν την αναφορά. Εάν η υπολογισμένη ημερομηνία και ώρα έναρξης είναι προγενέστερες από το \"{%current_datetime%}\", υπολογίστε ξανά την ημερομηνία και την ώρα έναρξης χρησιμοποιώντας το \"{%current_datetime%}\" ως βάση.\nΕάν η διάρκεια δεν έχει καθοριστεί, ορίστε την σε μία ώρα.\nΑυτοί είναι οι συμμετέχοντες: {%author%}, {%recipients%}, {%cc_list%}. Εάν υπάρχει, εξαιρέστε τη διεύθυνσή μου: {%account_email_address%}.\nΕάν δεν μπορείτε να λάβετε μία ή περισσότερες από τις απαιτούμενες πληροφορίες, απαντήστε με μια κενή συμβολοσειρά.\nΔημιουργήστε μια απάντηση μόνο σε μορφή JSON. Μην συμπεριλάβετε κανένα επιπλέον κείμενο ή εξηγήσεις. Δώστε μόνο το JSON. Η μορφή που θα χρησιμοποιηθεί είναι η εξής:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Σύνοψη συμβάντος ημερολογίου εδώ\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nΤο κείμενο είναι: \"{%mail_text_body_or_selected%}\""
},
"prompt_get_task": {
"message": "Προσθήκη νέας εργασίας"
@ -1304,5 +1304,131 @@
},
"prefs_anthropic_temperature_Info": {
"message": "Ποσότητα τυχαιότητας που εισάγεται στην απόκριση. Προεπιλογή 1,0. Εύρος από 0,0 έως 1,0. Χρησιμοποιήστε θερμοκρασία πιο κοντά στο 0,0 για αναλυτική ανάλυση."
},
"placeholder_mail_text_body_or_selected": {
"message": "Σώμα μηνύματος ή επιλεγμένο κείμενο"
},
"placeholder_mail_html_body_or_selected": {
"message": "Σώμα μηνύματος ή επιλεγμένη HTML"
},
"prompt_get_calendar_event_from_clipboard": {
"message": "Προσθήκη συμβάντος ημερολογίου από το πρόχειρο"
},
"clipboard_read_error": {
"message": "Δεν ήταν δυνατή η ανάγνωση του προχείρου. Ελέγξτε τα δικαιώματα."
},
"clipboard_empty_error": {
"message": "Το πρόχειρο είναι άδειο. Παρακαλώ αντιγράψτε πρώτα κάποιο κείμενο."
},
"clipboard_permission_denied": {
"message": "Η άδεια χρήσης του πρόχειρου απορρίφθηκε. Ενεργοποιήστε ξανά τη λειτουργία στις ρυθμίσεις για να παραχωρήσετε άδεια."
},
"clipboard_permission_error": {
"message": "Σφάλμα κατά την αίτηση άδειας στο πρόχειρο. Δοκιμάστε ξανά."
},
"prefs_OptionText_get_calendar_event_from_clipboard": {
"message": "Λήψη συμβάντος ημερολογίου από το πρόχειρο"
},
"prefs_OptionText_get_calendar_event_from_clipboard_Info": {
"message": "Εμφάνιση ενός επιπλέον στοιχείου μενού για τη δημιουργία συμβάντων ημερολογίου από περιεχόμενο κειμένου στο πρόχειρο."
},
"Summarize_prompt_prefs_title": {
"message": "Προσθήκη επιλογών σύνοψης"
},
"prompt_summarize": {
"message": "Συνοψίστε αυτό το μήνυμα ηλεκτρονικού ταχυδρομείου ή αυτά τα μηνύματα ηλεκτρονικού ταχυδρομείου"
},
"prompt_summarize_full_text": {
"message": "Είστε βοηθός που συνοψίζει συνομιλίες μέσω email. \nΔεδομένου ενός νήματος email, δημιουργήστε μια συνοπτική και ακριβή περίληψη που να καταγράφει: \n- Το κύριο θέμα ή τον σκοπό της συζήτησης \n- Βασικές αποφάσεις, συμπεράσματα ή συμφωνίες \n- Σημαντικές ερωτήσεις, αιτήματα ή ενέργειες \n- Ποιος είναι υπεύθυνος για κάθε ενέργεια (εάν αναφέρεται) \nΠαραλείψτε χαιρετισμούς, υπογραφές, παρατιθέμενο κείμενο και περιττές ανταλλαγές απόψεων. Μην προσθέτετε υποθέσεις ή πληροφορίες που δεν υπάρχουν στα email. \nΓράψτε την περίληψη σε σαφή, ουδέτερη γλώσσα, κατάλληλη για έναν πολυάσχολο επαγγελματία."
},
"prompt_summarize_email_template": {
"message": "Σύνοψη προτύπου email"
},
"prompt_summarize_email_template_full_text": {
"message": "Από: {%author%} \nΠρος: {%recipients%} \nΚοινοποίηση: {%cc_list%} \nΘέμα: {%mail_subject%} \nΗμερομηνία: {%mail_datetime%} \nΣυνημμένα: {%mail_attachments_info%} \nΚύριο κείμενο: \n{%mail_text_body%}"
},
"prompt_summarize_email_separator": {
"message": "Διαχωριστής email"
},
"prompt_summarize_email_separator_full_text": {
"message": "\n\n---------- ΕΠΟΜΕΝΟ EMAIL -----------\n\n"
},
"prefs_OptionText_Summarize_infoline2": {
"message": "Μπορείτε να αλλάξετε την προτροπή όπως επιθυμείτε. Το πρώτο πεδίο είναι η κύρια προτροπή, το δεύτερο πεδίο είναι το πρότυπο για ένα μόνο μήνυμα ηλεκτρονικού ταχυδρομείου. Η λίστα των email θα προσαρτηθεί στην κύρια προτροπή. Τα email θα διαχωρίζονται με το διαχωριστικό που καθορίζεται στο τρίτο πεδίο."
},
"prefs_OptionText_Summarize_main_prompt": {
"message": "Η κύρια προτροπή που περιγράφει την εργασία που θα εκτελεστεί σε όλα τα επιλεγμένα email:"
},
"prefs_OptionText_Summarize_email_template": {
"message": "Το πρότυπο για ένα μόνο email:"
},
"prefs_OptionText_Summarize_email_separator": {
"message": "Το διαχωριστικό μεταξύ των email:"
},
"prefs_OptionText_get_calendar_event_use_specific_integration_Info": {
"message": "Εάν επιλεγεί, το μοντέλο και το API που καθορίζονται παρακάτω θα χρησιμοποιηθούν για τη δημιουργία συμβάντων ημερολογίου, ανεξάρτητα από αυτό που έχει επιλεγεί στη σελίδα επιλογών ThunderAI."
},
"prefs_OptionText_summarize": {
"message": "Σύνοψη αλληλογραφίας"
},
"prefs_OptionText_summarize_use_specific_integration_Info": {
"message": "Εάν επιλεγεί, το μοντέλο και το API που καθορίζονται παρακάτω θα χρησιμοποιηθούν για τη σύνοψη email(s), ανεξάρτητα από αυτό που έχει επιλεγεί στη σελίδα επιλογών ThunderAI."
},
"prefs_OptionText_summarize_Info": {
"message": "Εάν είναι επιλεγμένο, προσθέτει μια επιλογή στο μενού περιβάλλοντος για τη σύνοψη της αλληλογραφίας."
},
"prefs_OptionText_btnManageSummarizeInfo": {
"message": "Διαχείριση ρυθμίσεων σύνοψης"
},
"Summarize_PageTitle": {
"message": "Διαχείριση ρυθμίσεων σύνοψης"
},
"Summarize_info_default": {
"message": "Σε αυτήν τη σελίδα μπορείτε να τροποποιήσετε την προεπιλεγμένη προτροπή που χρησιμοποιείται για τη σύνοψη των μηνυμάτων ηλεκτρονικού ταχυδρομείου."
},
"Summarize_prompt_text_title": {
"message": "Τρέχον κείμενο προτροπής"
},
"prefs_OptionText_spamfilter_show_msg_panel": {
"message": "Εμφάνιση πλαισίου αναφοράς ανεπιθύμητων μηνυμάτων"
},
"prefs_OptionText_spamfilter_show_msg_panel_Info": {
"message": "Εάν είναι επιλεγμένο, θα εμφανίζεται ένα πλαίσιο με την αναφορά ανεπιθύμητης αλληλογραφίας στο επάνω μέρος του μηνύματος."
},
"SpamReport_infoline": {
"message": "Αυτές οι πληροφορίες αποθηκεύονται μόνο για την τρέχουσα συνεδρία."
},
"Spam": {
"message": "Ανεπιθύμητα μηνύματα"
},
"Valid": {
"message": "Έγκυρα Μηνύματα"
},
"context_menu_mzta-summarize": {
"message": "Σύνοψη"
},
"CORS_alternative_2_new": {
"message": "Πατήστε το παρακάτω κουμπί για να δώσετε άδεια στον τρέχοντα κεντρικό υπολογιστή να αποφύγει οποιοδήποτε πρόβλημα με το CORS."
},
"CORS_give_host_perm": {
"message": "Δώστε άδεια στον τρέχοντα κεντρικό υπολογιστή"
},
"CORS_localhost_warn": {
"message": "Εάν χρησιμοποιείτε localhost ή 127.0.0.1 επειδή ο διακομιστής AI φιλοξενείται στον υπολογιστή σας, απαιτείται το δικαίωμα <all_urls>."
},
"customPrompts_export_include_api_settings": {
"message": "Θέλετε να συμπεριλάβετε τις ρυθμίσεις API στην εξαγωγή; Λάβετε υπόψη ότι και το Κλειδί API θα αποθηκευτεί στο αρχείο!"
},
"prefs_OptionText_calendar_no_selection": {
"message": "Μην ζητάτε να επιλέξετε κείμενο"
},
"prefs_OptionText_calendar_no_selection_Info": {
"message": "Εάν είναι επιλεγμένο, δεν χρειάζεται να επιλέξετε κάποιο κείμενο. Το πλήρες σώμα του μηνύματος θα χρησιμοποιηθεί για τη λήψη του συμβάντος ημερολογίου."
},
"customPrompts_btnCopy": {
"message": "Αντιγραφή"
},
"copy_text": {
"message": "αντιγραφή"
}
}

View file

@ -659,6 +659,14 @@
"message": "Account email address",
"description": ""
},
"placeholder_mail_text_body_or_selected": {
"message": "Mail body or selected text",
"description": ""
},
"placeholder_mail_html_body_or_selected": {
"message": "Mail body or selected HTML",
"description": ""
},
"prefs_OptionText_placeholders_use_default_value": {
"message": "Placeholders: use default value",
"description": ""
@ -1000,7 +1008,35 @@
"description": ""
},
"prompt_get_calendar_event_full_text": {
"message": "Extract all relevant details required to generate a calendar event from the following text. The extracted information should include:\n- Event Title\n- Start Date and Time (including timezone, if specified)\n- End Date and Time (including timezone, if specified)\n- Full day (if mentioned)\n- Attendees\nEnsure the data is formatted clearly and consistently so that it can be directly used for creating a calendar event.\nIf there are relative time references, consider that the date and time of the email are \"{%mail_datetime%}\". Calculate the start date and time based on this reference. If the calculated start date and time are earlier than \"{%current_datetime%}\", recalculate the start date and time using \"{%current_datetime%}\" as the base.\nIf the duration is not specified, set it to one hour.\nThese are the attendees: {%author%}, {%recipients%}, {%cc_list%}. If present, exclude my address: {%account_email_address%}.\nIf you're not able to get one or more of the required information, please respond with an empty string.\nGenerate a response in JSON format only. Do not include any additional text or explanations; provide only the JSON. Here is the format to be used:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Calendar event summary here\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nHere's the text:\"{%selected_text%}\"",
"message": "Extract all relevant details required to generate a calendar event from the following text. The extracted information should include:\n- Event Title\n- Start Date and Time (including timezone, if specified)\n- End Date and Time (including timezone, if specified)\n- Full day (if mentioned)\n- Attendees\nEnsure the data is formatted clearly and consistently so that it can be directly used for creating a calendar event.\nIf there are relative time references, consider that the date and time of the email are \"{%mail_datetime%}\". Calculate the start date and time based on this reference. If the calculated start date and time are earlier than \"{%current_datetime%}\", recalculate the start date and time using \"{%current_datetime%}\" as the base.\nIf the duration is not specified, set it to one hour.\nThese are the attendees: {%author%}, {%recipients%}, {%cc_list%}. If present, exclude my address: {%account_email_address%}.\nIf you're not able to get one or more of the required information, please respond with an empty string.\nGenerate a response in JSON format only. Do not include any additional text or explanations; provide only the JSON. Here is the format to be used:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Calendar event summary here\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nHere's the text:\"{%mail_text_body_or_selected%}\"",
"description": ""
},
"prompt_get_calendar_event_from_clipboard": {
"message": "Add calendar event from clipboard",
"description": ""
},
"clipboard_read_error": {
"message": "Could not read clipboard. Please check permissions.",
"description": ""
},
"clipboard_empty_error": {
"message": "Clipboard is empty. Please copy some text first.",
"description": ""
},
"clipboard_permission_denied": {
"message": "Clipboard permission was denied. Please enable the feature again in settings to grant permission.",
"description": ""
},
"clipboard_permission_error": {
"message": "Error requesting clipboard permission. Please try again.",
"description": ""
},
"prefs_OptionText_get_calendar_event_from_clipboard": {
"message": "Get calendar event from clipboard",
"description": ""
},
"prefs_OptionText_get_calendar_event_from_clipboard_Info": {
"message": "Show an additional menu item to create calendar events from clipboard text content.",
"description": ""
},
"Summarize_prompt_prefs_title": {
@ -1311,6 +1347,14 @@
"message": "If the value returned by the AI is above this threshold, the email will be moved to the spam folder.",
"description": ""
},
"prefs_OptionText_spamfilter_show_msg_panel": {
"message": "Show spam report panel",
"description": ""
},
"prefs_OptionText_spamfilter_show_msg_panel_Info": {
"message": "If checked, a panel with the spam report will be shown on top of the message.",
"description": ""
},
"spamfilter_threshold_too_low": {
"message": "The spam threshold is too low! You will likely mark too much mails as spam!",
"description": ""
@ -1327,6 +1371,10 @@
"message": "Spam Filter Reports",
"description": ""
},
"SpamReport_infoline": {
"message": "This information is saved only for the current session.",
"description": ""
},
"Date": {
"message": "Date",
"description": ""
@ -1343,6 +1391,14 @@
"message": "Spam Value",
"description": ""
},
"Spam": {
"message": "Spam",
"description": ""
},
"Valid": {
"message": "Valid",
"description": ""
},
"Moved_to_Spam": {
"message": "Moved to Spam",
"description": ""
@ -1826,5 +1882,21 @@
"customPrompts_export_include_api_settings": {
"message": "Do you want to include the API settings in the export? Be aware that also the API Key will be saved in the file!",
"description": ""
},
"prefs_OptionText_calendar_no_selection": {
"message": "Do not ask to select text",
"description": ""
},
"prefs_OptionText_calendar_no_selection_Info": {
"message": "If checked there is no need to select some text. The full message body will be used to get the calendar event.",
"description": ""
},
"customPrompts_btnCopy": {
"message": "Copy",
"description": ""
},
"copy_text": {
"message": "copy",
"description": ""
}
}

View file

@ -744,7 +744,7 @@
"message": "Agregar un nuevo evento de calendario"
},
"prompt_get_calendar_event_full_text": {
"message": "Extrae todos los detalles relevantes necesarios para generar un evento de calendario a partir del siguiente texto. La información extraída debe incluir:\n- Título del evento\n- Fecha y hora de inicio (incluyendo zona horaria, si se especifica)\n- Fecha y hora de fin (incluyendo zona horaria, si se especifica)\n- Día completo (si se menciona)\n- Asistentes\nAsegúrate de que los datos estén formateados de manera clara y consistente para que puedan usarse directamente en la creación de un evento de calendario.\nSi hay referencias de tiempo relativas, considera que la fecha y hora del correo son \"{%mail_datetime%}\". Calcula la fecha y hora de inicio basándote en esta referencia. Si la fecha y hora de inicio calculadas son anteriores a \"{%current_datetime%}\", recalcula la fecha y hora de inicio usando \"{%current_datetime%}\" como base.\nSi la duración no se especifica, establécela en una hora.\nEstos son los asistentes: {%author%}, {%recipients%}, {%cc_list%}. Si están presentes, excluye mi dirección: {%account_email_address%}.\nSi no puedes obtener uno o más de los datos requeridos, responde con una cadena vacía.\nGenera una respuesta solo en formato JSON. No incluyas texto adicional ni explicaciones; proporciona únicamente el JSON. El formato a usar es:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Resumen del evento de calendario aquí\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nEste es el texto:\"{%selected_text%}\""
"message": "Extrae todos los detalles relevantes necesarios para generar un evento de calendario a partir del siguiente texto. La información extraída debe incluir:\n- Título del evento\n- Fecha y hora de inicio (incluyendo zona horaria, si se especifica)\n- Fecha y hora de fin (incluyendo zona horaria, si se especifica)\n- Día completo (si se menciona)\n- Asistentes\nAsegúrate de que los datos estén formateados de manera clara y consistente para que puedan usarse directamente en la creación de un evento de calendario.\nSi hay referencias de tiempo relativas, considera que la fecha y hora del correo son \"{%mail_datetime%}\". Calcula la fecha y hora de inicio basándote en esta referencia. Si la fecha y hora de inicio calculadas son anteriores a \"{%current_datetime%}\", recalcula la fecha y hora de inicio usando \"{%current_datetime%}\" como base.\nSi la duración no se especifica, establécela en una hora.\nEstos son los asistentes: {%author%}, {%recipients%}, {%cc_list%}. Si están presentes, excluye mi dirección: {%account_email_address%}.\nSi no puedes obtener uno o más de los datos requeridos, responde con una cadena vacía.\nGenera una respuesta solo en formato JSON. No incluyas texto adicional ni explicaciones; proporciona únicamente el JSON. El formato a usar es:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Resumen del evento de calendario aquí\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nEste es el texto:\"{%mail_text_body_or_selected%}\""
},
"prompt_get_task": {
"message": "Agregar una nueva tarea"

View file

@ -697,7 +697,7 @@
"message": "Ajouter un nouvel événement au calendrier"
},
"prompt_get_calendar_event_full_text": {
"message": "Extrayez tous les détails pertinents nécessaires pour générer un événement de calendrier à partir du texte suivant. Les informations extraites doivent inclure :\n- Titre de l'événement\n- Date et heure de début (y compris le fuseau horaire, si spécifié)\n- Date et heure de fin (y compris le fuseau horaire, si spécifié)\n- Journée entière (si mentionnée)\n- Participants\nAssurez-vous que les données sont formatées clairement et de manière cohérente afin qu'elles puissent être utilisées directement pour créer un événement de calendrier.\nS'il y a des références temporelles relatives, considérez que la date et l'heure de l'email sont \"{%mail_datetime%}\". Calculez la date et l'heure de début sur cette base. Si la date et l'heure de début calculées sont antérieures à \"{%current_datetime%}\", recalculez-les en utilisant \"{%current_datetime%}\" comme base.\nSi la durée n'est pas spécifiée, définissez-la sur une heure.\nVoici les participants : {%author%}, {%recipients%}, {%cc_list%}. Si elle est présente, exclure mon adresse : {%account_email_address%}.\nSi vous n'êtes pas en mesure d'obtenir une ou plusieurs des informations requises, répondez avec une chaîne vide.\nGénérez une réponse uniquement au format JSON. N'incluez aucun texte ou explication supplémentaire; fournissez uniquement le JSON. Voici le format à utiliser :\n{\n\"startDate\" : \"YYYYMMDDTHHMMSS\",\n\"endDate\" : \"YYYYMMDDTHHMMSS\",\n\"summary\" : \"Résumé de l'événement du calendrier ici\",\n\"forceAllDay\" : false\n\"attendees\" : [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nVoici le texte : \"{%selected_text%}\""
"message": "Extrayez tous les détails pertinents nécessaires pour générer un événement de calendrier à partir du texte suivant. Les informations extraites doivent inclure :\n- Titre de l'événement\n- Date et heure de début (y compris le fuseau horaire, si spécifié)\n- Date et heure de fin (y compris le fuseau horaire, si spécifié)\n- Journée entière (si mentionnée)\n- Participants\nAssurez-vous que les données sont formatées clairement et de manière cohérente afin qu'elles puissent être utilisées directement pour créer un événement de calendrier.\nS'il y a des références temporelles relatives, considérez que la date et l'heure de l'email sont \"{%mail_datetime%}\". Calculez la date et l'heure de début sur cette base. Si la date et l'heure de début calculées sont antérieures à \"{%current_datetime%}\", recalculez-les en utilisant \"{%current_datetime%}\" comme base.\nSi la durée n'est pas spécifiée, définissez-la sur une heure.\nVoici les participants : {%author%}, {%recipients%}, {%cc_list%}. Si elle est présente, exclure mon adresse : {%account_email_address%}.\nSi vous n'êtes pas en mesure d'obtenir une ou plusieurs des informations requises, répondez avec une chaîne vide.\nGénérez une réponse uniquement au format JSON. N'incluez aucun texte ou explication supplémentaire; fournissez uniquement le JSON. Voici le format à utiliser :\n{\n\"startDate\" : \"YYYYMMDDTHHMMSS\",\n\"endDate\" : \"YYYYMMDDTHHMMSS\",\n\"summary\" : \"Résumé de l'événement du calendrier ici\",\n\"forceAllDay\" : false\n\"attendees\" : [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nVoici le texte : \"{%mail_text_body_or_selected%}\""
},
"prefs_OptionText_get_calendar_event": {
"message": "Ajouter un nouvel événement au calendrier à partir du texte sélectionné"

View file

@ -697,7 +697,7 @@
"message": "Dodaj novi kalendarski događaj"
},
"prompt_get_calendar_event_full_text": {
"message": "Izdvoji sve relevantne detalje potrebne za generiranje kalendarskog događaja iz sljedećeg teksta. Izdvojene informacije trebaju uključivati:\n- Naslov događaja\n- Datum i vrijeme početka (uključujući vremensku zonu, ako je navedeno)\n- Datum i vrijeme završetka (uključujući vremensku zonu, ako je navedeno)\n- Cijeli dan (ako je navedeno)\n- Sudionici\nOsiguraj da su podaci oblikovani jasno i dosljedno kako bi se mogli izravno koristiti za stvaranje kalendarskog događaja.\nAko postoje relativne vremenske napomene, smatraj da su datum i vrijeme e-poruke \"{%mail_datetime%}\". Izračunajte datum i vrijeme početka na temelju ove napomene. Ako su izračunati početni datum i vrijeme raniji od \"{%current_datetime%}\", ponovno izračunaj početni datum i vrijeme koristeći \"{%current_datetime%}\" kao osnovu.\nAko trajanje nije navedeno, postavi ga na jedan sat.\nOvo su sudionici: {%author%}, {%recipients%}, {%cc_list%}. Ako je prisutna, isključi moju adresu: {%account_email_address%}.\nAko ne možeš dobiti jednu ili više potrebnih informacija, odgovori praznim nizom.\nGeneriraj odgovor samo u JSON formatu. Nemoj uključivati nikakav dodatni tekst ili objašnjenja; pruži samo JSON. Ovo je format koji će se koristiti:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Sažetak kalendarskih događaja ovdje\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nOvo je tekst:\"{%selected_text%}\""
"message": "Izdvoji sve relevantne detalje potrebne za generiranje kalendarskog događaja iz sljedećeg teksta. Izdvojene informacije trebaju uključivati:\n- Naslov događaja\n- Datum i vrijeme početka (uključujući vremensku zonu, ako je navedeno)\n- Datum i vrijeme završetka (uključujući vremensku zonu, ako je navedeno)\n- Cijeli dan (ako je navedeno)\n- Sudionici\nOsiguraj da su podaci oblikovani jasno i dosljedno kako bi se mogli izravno koristiti za stvaranje kalendarskog događaja.\nAko postoje relativne vremenske napomene, smatraj da su datum i vrijeme e-poruke \"{%mail_datetime%}\". Izračunajte datum i vrijeme početka na temelju ove napomene. Ako su izračunati početni datum i vrijeme raniji od \"{%current_datetime%}\", ponovno izračunaj početni datum i vrijeme koristeći \"{%current_datetime%}\" kao osnovu.\nAko trajanje nije navedeno, postavi ga na jedan sat.\nOvo su sudionici: {%author%}, {%recipients%}, {%cc_list%}. Ako je prisutna, isključi moju adresu: {%account_email_address%}.\nAko ne možeš dobiti jednu ili više potrebnih informacija, odgovori praznim nizom.\nGeneriraj odgovor samo u JSON formatu. Nemoj uključivati nikakav dodatni tekst ili objašnjenja; pruži samo JSON. Ovo je format koji će se koristiti:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Sažetak kalendarskih događaja ovdje\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nOvo je tekst:\"{%mail_text_body_or_selected%}\""
},
"prefs_OptionText_get_calendar_event": {
"message": "Dodaj novi kalendarski događaj iz odabranog teksta"

View file

@ -697,7 +697,7 @@
"message": "Aggiungi un nuovo evento al calendario"
},
"prompt_get_calendar_event_full_text": {
"message": "Estrai tutti i dettagli rilevanti necessari per generare un evento del calendario dal seguente testo. Le informazioni estratte devono includere:\n- Titolo dell'evento\n- Data e ora di inizio (incluso il fuso orario, se specificato)\n- Data e ora di fine (incluso il fuso orario, se specificato)\n- Giornata intera (se menzionato)\n- I partecipanti\nAssicurati che i dati siano formattati in modo chiaro e coerente in modo che possano essere utilizzati direttamente per creare un evento del calendario.\nSe ci sono riferimenti temporali relativi, considera che la data e l'ora dell'email sono \"{%mail_datetime%}\". Calcola la data e l'ora di inizio in base a questo riferimento. Se la data e l'ora di inizio calcolate sono precedenti a \"{%current_datetime%}\", ricalcolale utilizzando \"{%current_datetime%}\" come base.\nSe la durata non è specificata, impostala a un'ora.\nQuesti sono i partecipanti: {%author%}, {%recipients%}, {%cc_list%}. Se presente, escludi il mio indirizzo: {%account_email_address%}.\nSe non riesci a ottenere una o più delle informazioni richieste, rispondi con una stringa vuota.\nGenera una risposta solo in formato JSON. Non includere testo o spiegazioni aggiuntive; fornisci solo il JSON. Ecco il formato da utilizzare:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Riassunto evento calendario qui\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nEcco il testo: \"{%selected_text%}\""
"message": "Estrai tutti i dettagli rilevanti necessari per generare un evento del calendario dal seguente testo. Le informazioni estratte devono includere:\n- Titolo dell'evento\n- Data e ora di inizio (incluso il fuso orario, se specificato)\n- Data e ora di fine (incluso il fuso orario, se specificato)\n- Giornata intera (se menzionato)\n- I partecipanti\nAssicurati che i dati siano formattati in modo chiaro e coerente in modo che possano essere utilizzati direttamente per creare un evento del calendario.\nSe ci sono riferimenti temporali relativi, considera che la data e l'ora dell'email sono \"{%mail_datetime%}\". Calcola la data e l'ora di inizio in base a questo riferimento. Se la data e l'ora di inizio calcolate sono precedenti a \"{%current_datetime%}\", ricalcolale utilizzando \"{%current_datetime%}\" come base.\nSe la durata non è specificata, impostala a un'ora.\nQuesti sono i partecipanti: {%author%}, {%recipients%}, {%cc_list%}. Se presente, escludi il mio indirizzo: {%account_email_address%}.\nSe non riesci a ottenere una o più delle informazioni richieste, rispondi con una stringa vuota.\nGenera una risposta solo in formato JSON. Non includere testo o spiegazioni aggiuntive; fornisci solo il JSON. Ecco il formato da utilizzare:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Riassunto evento calendario qui\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nEcco il testo: \"{%mail_text_body_or_selected%}\""
},
"prefs_OptionText_get_calendar_event": {
"message": "Aggiungi un nuovo evento al calendario dal testo selezionato"

View file

@ -750,7 +750,7 @@
"message": "新しいカレンダーイベントを追加"
},
"prompt_get_calendar_event_full_text": {
"message": "以下のテキストからカレンダーイベントを生成するために必要なすべての関連詳細を抽出してください。抽出情報には以下を含めてください:\n- イベントタイトル\n- 開始日時(指定されている場合はタイムゾーンを含む)\n- 終了日時(指定されている場合はタイムゾーンを含む)\n- 終日(言及されている場合)\n- 出席者\nデータはカレンダーイベントの作成に直接使用できるよう、明確かつ一貫した形式にしてください。\n相対的な時間参照がある場合、メールの日時は「{%mail_datetime%}」であることを考慮してください。この参照に基づいて開始日時を計算してください。計算された開始日時が「{%current_datetime%}」より前の場合、「{%current_datetime%}」を基準として開始日時を再計算してください。\n期間が指定されていない場合は、1時間に設定してください。\n出席者{%author%}、{%recipients%}、{%cc_list%}。存在する場合、私のアドレス{%account_email_address%}を除外してください。\n必要な情報の1つ以上を取得できない場合は、空の文字列で応答してください。\nJSON形式のみで応答を生成してください。追加のテキストや説明は含めず、JSONのみを提供してください。使用する形式\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"カレンダーイベントの概要をここに\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nテキスト「{%selected_text%}」"
"message": "以下のテキストからカレンダーイベントを生成するために必要なすべての関連詳細を抽出してください。抽出情報には以下を含めてください:\n- イベントタイトル\n- 開始日時(指定されている場合はタイムゾーンを含む)\n- 終了日時(指定されている場合はタイムゾーンを含む)\n- 終日(言及されている場合)\n- 出席者\nデータはカレンダーイベントの作成に直接使用できるよう、明確かつ一貫した形式にしてください。\n相対的な時間参照がある場合、メールの日時は「{%mail_datetime%}」であることを考慮してください。この参照に基づいて開始日時を計算してください。計算された開始日時が「{%current_datetime%}」より前の場合、「{%current_datetime%}」を基準として開始日時を再計算してください。\n期間が指定されていない場合は、1時間に設定してください。\n出席者{%author%}、{%recipients%}、{%cc_list%}。存在する場合、私のアドレス{%account_email_address%}を除外してください。\n必要な情報の1つ以上を取得できない場合は、空の文字列で応答してください。\nJSON形式のみで応答を生成してください。追加のテキストや説明は含めず、JSONのみを提供してください。使用する形式\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"カレンダーイベントの概要をここに\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nテキスト「{%mail_text_body_or_selected%}」"
},
"prompt_get_task": {
"message": "新しいタスクを追加"

View file

@ -688,7 +688,7 @@
"message": "Dodaj nowe wydarzenie w kalendarzu"
},
"prompt_get_calendar_event_full_text": {
"message": "Wyodrębnij wszystkie istotne szczegóły wymagane do wygenerowania wydarzenia w kalendarzu z poniższego tekstu. Wyodrębnione informacje powinny obejmować:\n- Tytuł wydarzenia\n- Datę i godzinę rozpoczęcia (w tym strefę czasową, jeśli została określona)\n- Datę i godzinę zakończenia (w tym strefę czasową, jeśli została określona)\n- Cały dzień (jeśli jest podany)\n- Uczestnicy\nUpewnij się, że dane są sformatowane w sposób jasny i spójny, tak aby można go bezpośrednio wykorzystać do utworzenia wydarzenia w kalendarzu.\nJeśli istnieją odniesienia do czasu względnego, pamiętaj, że data i godzina wysłania wiadomości e-mail to „{%mail_datetime%}”. Oblicz datę i godzinę rozpoczęcia na podstawie tego odniesienia. Jeśli obliczona data i godzina rozpoczęcia są wcześniejsze niż „{%current_datetime%}”, oblicz ponownie datę i godzinę rozpoczęcia, stosując jako podstawę „{%current_datetime%}”.\nJeśli czas trwania nie jest określony, ustaw go na jedną godzinę.\nOto uczestnicy: {%author%}, {%recipients%}, {%cc_list%}. Jeśli jest obecny, wyklucz mój adres: {%account_email_address%}.\nJeśli nie możesz uzyskać co najmniej jednej z wymaganych informacji, w odpowiedzi wpisz pusty ciąg znaków.\nWygeneruj odpowiedź tylko w formacie JSON. Nie dołączaj żadnego dodatkowego tekstu ani wyjaśnień; podaj tylko JSON. Oto format, którego należy użyć:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Tutaj podsumowanie wydarzenia w kalendarzu\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nOto tekst:\"{%selected_text %}\""
"message": "Wyodrębnij wszystkie istotne szczegóły wymagane do wygenerowania wydarzenia w kalendarzu z poniższego tekstu. Wyodrębnione informacje powinny obejmować:\n- Tytuł wydarzenia\n- Datę i godzinę rozpoczęcia (w tym strefę czasową, jeśli została określona)\n- Datę i godzinę zakończenia (w tym strefę czasową, jeśli została określona)\n- Cały dzień (jeśli jest podany)\n- Uczestnicy\nUpewnij się, że dane są sformatowane w sposób jasny i spójny, tak aby można go bezpośrednio wykorzystać do utworzenia wydarzenia w kalendarzu.\nJeśli istnieją odniesienia do czasu względnego, pamiętaj, że data i godzina wysłania wiadomości e-mail to „{%mail_datetime%}”. Oblicz datę i godzinę rozpoczęcia na podstawie tego odniesienia. Jeśli obliczona data i godzina rozpoczęcia są wcześniejsze niż „{%current_datetime%}”, oblicz ponownie datę i godzinę rozpoczęcia, stosując jako podstawę „{%current_datetime%}”.\nJeśli czas trwania nie jest określony, ustaw go na jedną godzinę.\nOto uczestnicy: {%author%}, {%recipients%}, {%cc_list%}. Jeśli jest obecny, wyklucz mój adres: {%account_email_address%}.\nJeśli nie możesz uzyskać co najmniej jednej z wymaganych informacji, w odpowiedzi wpisz pusty ciąg znaków.\nWygeneruj odpowiedź tylko w formacie JSON. Nie dołączaj żadnego dodatkowego tekstu ani wyjaśnień; podaj tylko JSON. Oto format, którego należy użyć:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Tutaj podsumowanie wydarzenia w kalendarzu\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nOto tekst:\"{%mail_text_body_or_selected%}\""
},
"prefs_OptionText_get_calendar_event": {
"message": "Dodaj nowe wydarzenie w kalendarzu z zaznaczonego tekstu"

View file

@ -697,7 +697,7 @@
"message": "Adicionar um novo evento ao calendário"
},
"prompt_get_calendar_event_full_text": {
"message": "Extraia todos os detalhes relevantes necessários para gerar um evento de calendário a partir do texto a seguir. As informações extraídas devem incluir:\n- Título do evento\n- Data e hora de início (incluindo fuso horário, se especificado)\n- Data e hora de término (incluindo fuso horário, se especificado)\n- Dia inteiro (se mencionado)\n- Participantes\nCertifique-se de que os dados estejam formatados de maneira clara e consistente para que possam ser usados diretamente para criar um evento de calendário.\nSe houver referências de tempo relativas, considere que a data e a hora do e-mail são \"{%mail_datetime%}\". Calcule a data e a hora de início com base nessa referência. Se a data e a hora de início calculadas forem anteriores a \"{%current_datetime%}\", recalcule a data e a hora de início usando \"{%current_datetime%}\" como base.\nSe a duração não for especificada, defina-a como uma hora.\nEstes são os participantes: {%author%}, {%recipients%}, {%cc_list%}. Se estiver presente, exclua meu endereço: {%account_email_address%}.\nSe você não conseguir obter uma ou mais informações necessárias, responda com uma string vazia.\nGere uma resposta apenas no formato JSON. Não inclua texto ou explicações adicionais; forneça apenas o JSON. Aqui está o formato a ser usado:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Resumo do evento do calendário aqui\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nAqui está o texto: \"{%selected_text%}\""
"message": "Extraia todos os detalhes relevantes necessários para gerar um evento de calendário a partir do texto a seguir. As informações extraídas devem incluir:\n- Título do evento\n- Data e hora de início (incluindo fuso horário, se especificado)\n- Data e hora de término (incluindo fuso horário, se especificado)\n- Dia inteiro (se mencionado)\n- Participantes\nCertifique-se de que os dados estejam formatados de maneira clara e consistente para que possam ser usados diretamente para criar um evento de calendário.\nSe houver referências de tempo relativas, considere que a data e a hora do e-mail são \"{%mail_datetime%}\". Calcule a data e a hora de início com base nessa referência. Se a data e a hora de início calculadas forem anteriores a \"{%current_datetime%}\", recalcule a data e a hora de início usando \"{%current_datetime%}\" como base.\nSe a duração não for especificada, defina-a como uma hora.\nEstes são os participantes: {%author%}, {%recipients%}, {%cc_list%}. Se estiver presente, exclua meu endereço: {%account_email_address%}.\nSe você não conseguir obter uma ou mais informações necessárias, responda com uma string vazia.\nGere uma resposta apenas no formato JSON. Não inclua texto ou explicações adicionais; forneça apenas o JSON. Aqui está o formato a ser usado:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"Resumo do evento do calendário aqui\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nAqui está o texto: \"{%mail_text_body_or_selected%}\""
},
"prefs_OptionText_get_calendar_event": {
"message": "Adicionar um novo evento ao calendário a partir do texto selecionado"

View file

@ -735,7 +735,7 @@
"message": "Добавьте новое событие календаря"
},
"prompt_get_calendar_event_full_text": {
"message": "Извлеките из следующего текста все необходимые сведения, необходимые для создания календарного события. Извлеченная информация должна включать:\n- Название события\n- Дата и время начала (включая часовой пояс, если он указан)\n- Дата и время окончания (включая часовой пояс, если он указан)\n- Полный день (если указано)\n- Участники\nУбедитесь, что данные отформатированы четко и последовательно, чтобы их можно было напрямую использовать для создания календарного события.\nЕсли есть относительные временные ссылки, считайте, что дата и время письма - это \"{%mail_datetime%}\". Рассчитайте дату и время начала на основе этой ссылки. Если вычисленные дата и время начала раньше, чем \"{%current_datetime%}\", пересчитайте дату и время начала, взяв за основу \"{%current_datetime%}\".\nЕсли продолжительность не указана, установите ее равной одному часу.\nК ним относятся: {%author%}, {%recipients%}, {%cc_list%}. Если присутствует, исключите мой адрес: {%account_email_address%}.\nЕсли вы не можете получить одну или несколько требуемых данных, ответьте пустой строкой.\nГенерируйте ответ только в формате JSON. Не включайте никаких дополнительных текстов или пояснений; предоставляйте только JSON. Вот формат, который следует использовать:\n{\n\"startDate\": \"ГГГГММДДДХММССС\",\n\"endDate\": \"ГГГГММДДДХММССС\",\n\"summary\": \"Здесь выводится краткое описание события календаря\",\n\"forceAllDay\": false,\n\"attendees\": [участник1@example.com,участник2@example.com,участник3@example.com]\n}\nВот текст: \"{%selected_text%}\""
"message": "Извлеките из следующего текста все необходимые сведения, необходимые для создания календарного события. Извлеченная информация должна включать:\n- Название события\n- Дата и время начала (включая часовой пояс, если он указан)\n- Дата и время окончания (включая часовой пояс, если он указан)\n- Полный день (если указано)\n- Участники\nУбедитесь, что данные отформатированы четко и последовательно, чтобы их можно было напрямую использовать для создания календарного события.\nЕсли есть относительные временные ссылки, считайте, что дата и время письма - это \"{%mail_datetime%}\". Рассчитайте дату и время начала на основе этой ссылки. Если вычисленные дата и время начала раньше, чем \"{%current_datetime%}\", пересчитайте дату и время начала, взяв за основу \"{%current_datetime%}\".\nЕсли продолжительность не указана, установите ее равной одному часу.\nК ним относятся: {%author%}, {%recipients%}, {%cc_list%}. Если присутствует, исключите мой адрес: {%account_email_address%}.\nЕсли вы не можете получить одну или несколько требуемых данных, ответьте пустой строкой.\nГенерируйте ответ только в формате JSON. Не включайте никаких дополнительных текстов или пояснений; предоставляйте только JSON. Вот формат, который следует использовать:\n{\n\"startDate\": \"ГГГГММДДДХММССС\",\n\"endDate\": \"ГГГГММДДДХММССС\",\n\"summary\": \"Здесь выводится краткое описание события календаря\",\n\"forceAllDay\": false,\n\"attendees\": [участник1@example.com,участник2@example.com,участник3@example.com]\n}\nВот текст: \"{%mail_text_body_or_selected%}\""
},
"prompt_get_task": {
"message": "Добавить новую задачу"

View file

@ -1297,7 +1297,7 @@
"message": "Citerad text i meddelandets brödtext"
},
"prompt_get_calendar_event_full_text": {
"message": "Extrahera all relevant information som krävs för att generera en kalenderhändelse från följande text. Den extraherade informationen bör innehålla:\n- Händelsetitel\n- Startdatum och tid (inklusive tidszon, om angiven)\n- Slutdatum och tid (inklusive tidszon, om angiven)\n- Heldag (om angiven)\n- Deltagare\nSe till att informationen är tydligt och konsekvent formaterad så att den kan användas direkt för att skapa en kalenderhändelse.\nOm det finns relativa tidsreferenser, tänk på att datum och tid för e-postmeddelandet är \"{%mail_datetime%}\". Beräkna startdatum och tid baserat på denna referens. Om det beräknade startdatumet och tiden är tidigare än \"{%current_datetime%}\", beräkna om startdatumet och tiden med \"{%current_datetime%}\" som bas.\nOm varaktigheten inte anges, sätt den till en timme.\nDessa är deltagarna: {%author%}, {%recipients%}, {%cc_list%}. Om det finns, exkludera min adress: {%account_email_address%}.\nOm du inte kan få en eller flera av de obligatoriska uppgifterna, vänligen svara med en tom sträng.\nGenerera ett svar endast i JSON-format. Inkludera inte ytterligare text eller förklaringar; ange endast JSON. Här är formatet som ska användas:\n{\n\"startDate\": \"ÅÅÅÅMMDDTHHMMSS\",\n\"endDate\": \"ÅÅÅÅMMDDTHHMMSS\",\n\"summary\": \"Sammanfattning av kalenderhändelse här\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nHär är texten: \"{%selected_text%}\""
"message": "Extrahera all relevant information som krävs för att generera en kalenderhändelse från följande text. Den extraherade informationen bör innehålla:\n- Händelsetitel\n- Startdatum och tid (inklusive tidszon, om angiven)\n- Slutdatum och tid (inklusive tidszon, om angiven)\n- Heldag (om angiven)\n- Deltagare\nSe till att informationen är tydligt och konsekvent formaterad så att den kan användas direkt för att skapa en kalenderhändelse.\nOm det finns relativa tidsreferenser, tänk på att datum och tid för e-postmeddelandet är \"{%mail_datetime%}\". Beräkna startdatum och tid baserat på denna referens. Om det beräknade startdatumet och tiden är tidigare än \"{%current_datetime%}\", beräkna om startdatumet och tiden med \"{%current_datetime%}\" som bas.\nOm varaktigheten inte anges, sätt den till en timme.\nDessa är deltagarna: {%author%}, {%recipients%}, {%cc_list%}. Om det finns, exkludera min adress: {%account_email_address%}.\nOm du inte kan få en eller flera av de obligatoriska uppgifterna, vänligen svara med en tom sträng.\nGenerera ett svar endast i JSON-format. Inkludera inte ytterligare text eller förklaringar; ange endast JSON. Här är formatet som ska användas:\n{\n\"startDate\": \"ÅÅÅÅMMDDTHHMMSS\",\n\"endDate\": \"ÅÅÅÅMMDDTHHMMSS\",\n\"summary\": \"Sammanfattning av kalenderhändelse här\",\n\"forceAllDay\": false,\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\nHär är texten: \"{%mail_text_body_or_selected%}\""
},
"prompt_get_task_full_text": {
"message": "Extrahera alla relevanta detaljer som krävs för att generera en uppgift från följande text. Den extraherade informationen bör innehålla:\n- Förfallodatum och tid (inklusive tidszon, om angiven)\n- Uppgiftssammanfattning\n- Initialt datum och tid (inklusive tidszon, om angiven)\nSe till att informationen är tydligt och konsekvent formaterad så att den kan användas direkt för att skapa en uppgift.\nOm det finns relativa tidsreferenser, tänk på att datum och tid för e-postmeddelandet är \"{%mail_datetime%}\". Beräkna startdatum och tid baserat på denna referens. Om det beräknade startdatumet och tiden är tidigare än \"{%current_datetime%}\", beräkna om startdatumet och tiden med \"{%current_datetime%}\" som bas.\nOm du inte kan få en eller flera av de obligatoriska uppgifterna, vänligen svara med en tom sträng.\nGenerera ett svar endast i JSON-format. Inkludera inte ytterligare text eller förklaringar; ange endast JSON. Här är formatet som ska användas:\n{\n\"InitialDate\": \"ÅÅÅÅMMDDTHHMMSS\",\n\"dueDate\": \"ÅÅÅÅMMDDTHHMMSS\",\n\"summary\": \"Uppgiftssammanfattning här\"\n}\nOm det inte finns någon information om datumen, ta bort dem.\nHär är texten: \"{%selected_text%}\""
@ -1370,5 +1370,65 @@
},
"CORS_localhost_warn": {
"message": "Om du använder localhost eller 127.0.0.1 eftersom AI-servern finns på din dator krävs behörigheten <all_urls>."
},
"prefs_OptionText_get_calendar_event_use_specific_integration_Info": {
"message": "Om markerat kommer modellen och API:et som anges nedan att användas för att skapa kalenderhändelser, oavsett vilket som valts på ThunderAI-alternativsidan."
},
"customPrompts_export_include_api_settings": {
"message": "Vill du inkludera API-inställningar i exporten? Tänk på att även API-nyckeln kommer att sparas i filen!"
},
"prompt_get_calendar_event_from_clipboard": {
"message": "Lägg till kalenderhändelse från urklipp"
},
"clipboard_read_error": {
"message": "Kunde inte läsa urklipp. Kontrollera behörigheterna."
},
"clipboard_empty_error": {
"message": "Urklipp är tom. Kopiera lite text först."
},
"clipboard_permission_denied": {
"message": "Åtkomst till urklipp nekades. Aktivera funktionen igen i inställningarna för att ge behörighet."
},
"clipboard_permission_error": {
"message": "Fel vid begäran om behörighet för urklipp. Försök igen."
},
"prefs_OptionText_get_calendar_event_from_clipboard": {
"message": "Hämta kalenderhändelse från urklipp"
},
"prefs_OptionText_get_calendar_event_from_clipboard_Info": {
"message": "Visa ytterligare ett menyalternativ för att skapa kalenderhändelser från textinnehåll i urklipp."
},
"prefs_OptionText_calendar_no_selection": {
"message": "Fråga inte om att markera text"
},
"prefs_OptionText_calendar_no_selection_Info": {
"message": "Om markerad behöver du inte markera någon text. Hela meddelandets innehåll kommer att användas för att hämta kalenderhändelsen."
},
"customPrompts_btnCopy": {
"message": "Kopiera"
},
"copy_text": {
"message": "kopiera"
},
"placeholder_mail_text_body_or_selected": {
"message": "Mejltext eller markerad text"
},
"placeholder_mail_html_body_or_selected": {
"message": "Mejltext eller vald HTML"
},
"Spam": {
"message": "Skräppost"
},
"Valid": {
"message": "Giltig"
},
"prefs_OptionText_spamfilter_show_msg_panel": {
"message": "Visa panelen för skräppostrapportering"
},
"prefs_OptionText_spamfilter_show_msg_panel_Info": {
"message": "Om markerat visas en panel med skräppostrapporten högst upp i meddelandet."
},
"SpamReport_infoline": {
"message": "Denna information sparas endast för den aktuella sessionen."
}
}

View file

@ -765,7 +765,7 @@
"message": "管理垃圾邮件过滤器设置"
},
"prompt_get_calendar_event_full_text": {
"message": "从以下文本中提取生成日历事件所需的所有相关细节。提取的信息应包括:\n- 事件标题\n- 开始日期和时间(如果指定时区,则包括时区)\n- 结束日期和时间(如果指定时区,则包括时区)\n- 全天事件(如果提及)\n- 参与者 \n确保数据格式清晰且一致以便可以直接用于创建日历事件。\n如果存在相对时间的引用请注意邮件的日期和时间为“{%mail_datetime%}”。基于此参考计算开始日期和时间。如果计算出的开始日期和时间早于“{%current_datetime%}”,则使用“{%current_datetime%}”作为基准重新计算开始日期和时间。\n如果未指定持续时间请将其设置为一小时。\n以下是参与者{%author%}, {%recipients%}, {%cc_list%}。如有,请排除我的地址:{%account_email_address%}。\n如果无法获取一个或多个所需信息请以空字符串响应。\n仅以 JSON 格式生成响应。不要包含任何额外的文本或说明,仅提供 JSON。以下是使用的格式\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"日历事件摘要\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\n以下是文本“{%selected_text%}”"
"message": "从以下文本中提取生成日历事件所需的所有相关细节。提取的信息应包括:\n- 事件标题\n- 开始日期和时间(如果指定时区,则包括时区)\n- 结束日期和时间(如果指定时区,则包括时区)\n- 全天事件(如果提及)\n- 参与者 \n确保数据格式清晰且一致以便可以直接用于创建日历事件。\n如果存在相对时间的引用请注意邮件的日期和时间为“{%mail_datetime%}”。基于此参考计算开始日期和时间。如果计算出的开始日期和时间早于“{%current_datetime%}”,则使用“{%current_datetime%}”作为基准重新计算开始日期和时间。\n如果未指定持续时间请将其设置为一小时。\n以下是参与者{%author%}, {%recipients%}, {%cc_list%}。如有,请排除我的地址:{%account_email_address%}。\n如果无法获取一个或多个所需信息请以空字符串响应。\n仅以 JSON 格式生成响应。不要包含任何额外的文本或说明,仅提供 JSON。以下是使用的格式\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"日历事件摘要\",\n\"forceAllDay\": false\n\"attendees\": [attendee1@example.com,attendee2@example.com,attendee3@example.com]\n}\n以下是文本“{%mail_text_body_or_selected%}”"
},
"prefs_OptionText_get_calendar_event": {
"message": "从所选文本添加新日历事件"

View file

@ -1075,7 +1075,7 @@
"message": "您尚未選擇 ChatGPT API 的模型。請在選項頁面中選擇一個。"
},
"prompt_get_calendar_event_full_text": {
"message": "從以下文字中提取所有需要生成日曆事件的相關資訊。 提取的資訊應包含:\n- 事件名稱\n- 起始日期和時間(包含時區,如果指定)\n- 結束日期和時間(包含時間區,如果指定)\n- 整天事件(如果提及\n- 參與者\n確保數據以清晰一致的方式格式化以便直接用於創建日曆事件。\n如果有相對時間參考請考慮電子郵件的日期和時間是 「{%mail_datetime%}」。 計算基於此參考的起日期和時間。 如果計算出的起日期和時間早於「{%current_datetime%}」,則使用「{%current_datetime%}」作為基準重新計算起日期和時間。\n如果持續時間沒有指定則設定為一小時。\n參與者{%author%}, {%recipients%}, {%cc_list%}。如果存在,請排除我的地址:{%account_email_address%}。\n如果無法獲得其中一個或多個所需的資訊請回覆一個空字串。\n請以 JSON 格式回覆,不要包含任何額外的文字或說明,提供僅 JSON。 以下是將要使用的格式:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"日曆事件摘要在此\",\n\"forceAllDay\": false,\n\"attendees\": [\"attendee1@example.com \",\"attendee2@example.com \",\"attendee3@example.com \"]\n}\n這裡是文字「{%selected_text%}」"
"message": "從以下文字中提取所有需要生成日曆事件的相關資訊。 提取的資訊應包含:\n- 事件名稱\n- 起始日期和時間(包含時區,如果指定)\n- 結束日期和時間(包含時間區,如果指定)\n- 整天事件(如果提及\n- 參與者\n確保數據以清晰一致的方式格式化以便直接用於創建日曆事件。\n如果有相對時間參考請考慮電子郵件的日期和時間是 「{%mail_datetime%}」。 計算基於此參考的起日期和時間。 如果計算出的起日期和時間早於「{%current_datetime%}」,則使用「{%current_datetime%}」作為基準重新計算起日期和時間。\n如果持續時間沒有指定則設定為一小時。\n參與者{%author%}, {%recipients%}, {%cc_list%}。如果存在,請排除我的地址:{%account_email_address%}。\n如果無法獲得其中一個或多個所需的資訊請回覆一個空字串。\n請以 JSON 格式回覆,不要包含任何額外的文字或說明,提供僅 JSON。 以下是將要使用的格式:\n{\n\"startDate\": \"YYYYMMDDTHHMMSS\",\n\"endDate\": \"YYYYMMDDTHHMMSS\",\n\"summary\": \"日曆事件摘要在此\",\n\"forceAllDay\": false,\n\"attendees\": [\"attendee1@example.com \",\"attendee2@example.com \",\"attendee3@example.com \"]\n}\n這裡是文字「{%mail_text_body_or_selected%}」"
},
"TranslateText": {
"message": "您願意幫忙翻譯這個附加元件嗎?"

View file

@ -30,6 +30,7 @@ let current_mailMessageId = null;
let selectionChangeTimeout = null;
let isDragging = false;
let delay_wait_completion = 7000; // milliseconds
let lastSelectedHtml = "";
async function chatgpt_sendMsg(msg, method ='') { // return -1 send button not found, -2 textarea not found
let textArea = document.getElementById('prompt-textarea')
@ -205,6 +206,10 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
var btn_ok = document.createElement('button');
btn_ok.id="mzta-btn_ok";
btn_ok.classList.add('mzta-btn');
// Prevent the button from stealing focus and clearing the selection
btn_ok.addEventListener('mousedown', function(e) {
e.preventDefault();
});
//console.log('>>>>>>>>>>>>>>> default: '+prompt_action)
switch(String(prompt_action)){
default:
@ -247,6 +252,10 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
var btn_change_reply_type = document.createElement('button');
disableButton(btn_change_reply_type);
btn_change_reply_type.id = 'mzta-btn_change_reply_type';
// Prevent the button from stealing focus and clearing the selection
btn_change_reply_type.addEventListener('mousedown', function(e) {
e.preventDefault();
});
btn_change_reply_type.classList.add('mzta-btn');
btn_change_reply_type.title = browser.i18n.getMessage("chatgpt_win_change_reply_type");
// Create SVG element
@ -320,6 +329,10 @@ function addCustomDiv(prompt_action,tabId,mailMessageId) {
var btn_diff = document.createElement('button');
btn_diff.id='mzta-btn_diff';
btn_diff.classList.add('mzta-btn');
// Prevent the button from stealing focus and clearing the selection
btn_diff.addEventListener('mousedown', function(e) {
e.preventDefault();
});
btn_diff.textContent = browser.i18n.getMessage('btn_show_differences');
btn_diff.style.display = 'none';
disableButton(btn_diff);
@ -672,7 +685,7 @@ function replaceNewlinesWithBr(node) {
function getSelectedHtml() {
// Get the Selection object
var selection = window.getSelection();
// console.log(">>>>>>>>>>>>> getSelectedHtml selection.rangeCount: " + selection.rangeCount);
if (selection.rangeCount > 0) {
// Get the first selected range
var range = selection.getRangeAt(0);
@ -682,10 +695,14 @@ function getSelectedHtml() {
// Clone the contents of the range into the temporary div
tempDiv.appendChild(range.cloneContents());
// console.log(">>>>>>>>>>>>>>>>>> tempDiv.innerHTML: " + tempDiv.innerHTML);
// Return the HTML of the selected content
return tempDiv.innerHTML.replace(/^<p>&quot;/, '<p>').replace(/&quot;<\\/p>$/, '</p>'); // strip quotation marks;
}
if (lastSelectedHtml) {
// console.log(">>>>>>>>>>>>> getSelectedHtml using cached selection lastSelectedHtml: "+ lastSelectedHtml);
return lastSelectedHtml;
}
return "";
}
@ -708,6 +725,14 @@ document.addEventListener("selectionchange", function() {
let btn_ok = document.getElementById('mzta-btn_ok');
let btn_diff = document.getElementById('mzta-btn_diff');
if (isSomethingSelected()) {
// Cache the selection
var selection = window.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
var tempDiv = document.createElement("div");
tempDiv.appendChild(range.cloneContents());
lastSelectedHtml = tempDiv.innerHTML.replace(/^<p>&quot;/, '<p>').replace(/&quot;<\\/p>$/, '</p>');
}
enableButton(btn_ok);
if(current_action == '1'){
let btn_reply_type = document.getElementById('mzta-btn_change_reply_type');
@ -756,7 +781,8 @@ function selectContentOnMouseUp(event) {
// If the click was inside the excluded area, do nothing
return;
}
// console.log(">>>>>>>>>>>>> selectContentOnMouseUp isDragging: " + isDragging);
// Reset the dragging flag when the mouse is released")
if ((!isDragging)&&(!isSomethingSelected())) {
// If no dragging has occurred, execute the selection code
selectContentOnClick(event);
@ -781,6 +807,8 @@ function selectContentOnClick(event) {
// Traverse the DOM upwards to find the nearest parent div
var parentDiv = clickedElement.closest('div');
// console.log(">>>>>>>>>>>>> parentDiv: " + parentDiv.classList);
if (parentDiv) {
// Create a range object
var range = document.createRange();
@ -796,6 +824,7 @@ function selectContentOnClick(event) {
// Add the new range to the selection
selection.addRange(range);
// console.log(">>>>>>>>>>>>> selectContentOnClick selection.rangeCount: " + selection.rangeCount);
}
}

View file

@ -617,9 +617,58 @@ switch (message.command) {
break;
case "showSpamReport":
const data = message.data;
if(document.getElementById('mzta-spam-report-banner')) return Promise.resolve(true);
const container = document.createElement('div');
container.id = 'mzta-spam-report-banner';
const isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
let bgColor = '#f8f9fa';
let textColor = '#333';
let borderColor = '#ccc';
if (data.spamValue >= (data.SpamThreshold || 50)) {
bgColor = isDark ? '#5a1a1a' : '#ffe6e6';
textColor = isDark ? '#ffcccc' : '#cc0000';
borderColor = '#cc0000';
} else {
bgColor = isDark ? '#1a401a' : '#e6ffe6';
textColor = isDark ? '#ccffcc' : '#006600';
borderColor = '#006600';
}
container.style.cssText = `background-color: ${bgColor}; color: ${textColor}; border-bottom: 1px solid ${borderColor}; padding: 8px 12px; font-family: system-ui, -apple-system, sans-serif; font-size: 13px; display: flex; align-items: center; gap: 15px; width: 100%; box-sizing: border-box;`;
const scoreText = document.createElement('strong');
scoreText.textContent = ((data.spamValue >= (data.SpamThreshold || 50)) ? browser.i18n.getMessage("Spam") : browser.i18n.getMessage("Valid")) + " [" + data.spamValue + "/100]";
const reasonText = document.createElement('span');
reasonText.textContent = browser.i18n.getMessage("Explanation") + ": " + data.explanation;
const closeBtn = document.createElement('span');
closeBtn.textContent = '×';
closeBtn.style.cssText = 'margin-left: auto; cursor: pointer; font-weight: bold; font-size: 16px; padding: 0 5px;';
closeBtn.title = browser.i18n.getMessage("chatgpt_win_close");
closeBtn.onclick = function() {
container.remove();
browser.runtime.sendMessage({ command: "removeSpamReport", headerMessageId: data.headerMessageId });
};
container.appendChild(scoreText);
container.appendChild(reasonText);
container.appendChild(closeBtn);
document.body.insertBefore(container, document.body.firstChild);
return Promise.resolve(true);
default:
// do nothing
return Promise.resolve(false);
break;
}
});
});
browser.runtime.sendMessage({ command: "checkSpamReport" });

View file

@ -110,6 +110,25 @@ 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'));
if (curr_prompt.id === 'prompt_get_calendar_event_from_clipboard') {
try {
const clipboardText = await navigator.clipboard.readText();
if (!clipboardText) {
browser.tabs.sendMessage(tabs[0].id, { command: "sendAlert", curr_tab_type: tabs[0].type, message: browser.i18n.getMessage('clipboard_empty_error') });
taWorkingStatus.stopWorking();
return {ok:'0'};
}
msg_text.selection = clipboardText;
msg_text.text = clipboardText;
} catch (e) {
console.error("Clipboard read error:", e);
browser.tabs.sendMessage(tabs[0].id, { command: "sendAlert", curr_tab_type: tabs[0].type, message: browser.i18n.getMessage('clipboard_read_error') });
taWorkingStatus.stopWorking();
return {ok:'0'};
}
}
// console.log(">>>>>>>>>>>>> msg_text: " + JSON.stringify(msg_text));
//check if a selection is needed
if(String(curr_prompt.need_selected) == "1" && (msg_text.selection==='')){
@ -256,7 +275,8 @@ export class mzta_Menus {
return {ok:'1'};
break; // Add tags to the email - END
}
case 'prompt_get_calendar_event': { // Get a calendar event info
case 'prompt_get_calendar_event': // Get a calendar event info
case 'prompt_get_calendar_event_from_clipboard': { // here from clipboard
let calendar_event_data = '';
let prefs_at = await browser.storage.sync.get({
connection_type: prefs_default.connection_type,

View file

@ -267,6 +267,24 @@ const defaultPlaceholders = [
is_default: "1",
is_dynamic: "0",
enabled: 1,
},
{
id: 'mail_text_body_or_selected',
name: "__MSG_placeholder_mail_text_body_or_selected__",
default_value: "",
type: 0,
is_default: "1",
is_dynamic: "0",
enabled: 1,
},
{
id: 'mail_html_body_or_selected',
name: "__MSG_placeholder_mail_html_body_or_selected__",
default_value: "",
type: 0,
is_default: "1",
is_dynamic: "0",
enabled: 1,
}
];
@ -517,6 +535,12 @@ export const placeholdersUtils = {
case 'selected_html':
finalSubs['selected_html'] = placeholdersUtils.failSafePlaceholders(selection_html);
break;
case 'mail_text_body_or_selected':
finalSubs['mail_text_body_or_selected'] = placeholdersUtils.failSafePlaceholders(selection_text || body_text);
break;
case 'mail_html_body_or_selected':
finalSubs['mail_html_body_or_selected'] = placeholdersUtils.failSafePlaceholders(selection_html || msg_text?.html);
break;
case 'author':
finalSubs['author'] = placeholdersUtils.failSafePlaceholders(curr_message.author);
break;

View file

@ -294,6 +294,21 @@ const specialPrompts = [
is_default: "1",
is_special: "1",
},
{
id: 'prompt_get_calendar_event_from_clipboard',
name: "__MSG_prompt_get_calendar_event_from_clipboard__",
text: "prompt_get_calendar_event_full_text",
type: "1",
action: "0",
need_selected: "0",
need_signature: "0",
need_custom_text: "0",
define_response_lang: "0",
use_diff_viewer: "0",
api_type: '',
is_default: "1",
is_special: "1",
},
{
id: 'prompt_get_task',
name: "__MSG_prompt_get_task__",

View file

@ -32,6 +32,11 @@ export const taSpamReport = {
return output[key] || null;
},
async removeReportData(data_id) {
const key = this._data_prefix + data_id;
await browser.storage.session.remove(key);
},
async getAllReportData() {
let allData = await browser.storage.session.get(null);
let reportData = {};

View file

@ -577,6 +577,7 @@ export function getActiveSpecialPromptsIDs(args = {}) {
addtags = false,
addtags_api = false,
get_calendar_event = false,
get_calendar_event_from_clipboard = false,
get_task = false,
is_chatgpt_web = false
} = args;
@ -596,6 +597,9 @@ export function getActiveSpecialPromptsIDs(args = {}) {
if (get_calendar_event) {
output.push('prompt_get_calendar_event');
}
if (get_calendar_event_from_clipboard) {
output.push('prompt_get_calendar_event_from_clipboard');
}
if (get_task) {
output.push('prompt_get_task');
}

View file

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "ThunderAI",
"description": "__MSG_extensionDescription__",
"version": "4.0.0",
"version": "4.0.0pre1",
"author": "Mic (m@micz.it)",
"homepage_url": "https://micz.it/thunderbird-addon-thunderai/",
"browser_specific_settings": {
@ -34,6 +34,7 @@
"messagesTagsList"
],
"optional_permissions": [
"clipboardRead",
"messagesTags",
"messagesUpdate",
"messagesMove",

View file

@ -99,6 +99,7 @@ let special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags,
addtags_api: hasSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: doGetSparkFeature(prefs_init.get_calendar_event),
get_calendar_event_from_clipboard: doGetSparkFeature(prefs_init.get_calendar_event_from_clipboard),
get_task: doGetSparkFeature(prefs_init.get_task),
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
});
@ -197,13 +198,15 @@ function preparePopupMenu(tab) {
}
async function _reload_menus() {
let prefs_reload = await browser.storage.sync.get({add_tags: prefs_default.add_tags, get_calendar_event: prefs_default.get_calendar_event, get_task: prefs_default.get_task, connection_type: prefs_default.connection_type});
let prefs_reload = await browser.storage.sync.get({add_tags: prefs_default.add_tags, get_calendar_event: prefs_default.get_calendar_event, get_calendar_event_from_clipboard: prefs_default.get_calendar_event_from_clipboard, get_task: prefs_default.get_task, connection_type: prefs_default.connection_type});
let getCalendarEvent = doGetSparkFeature(prefs_reload.get_calendar_event);
let getCalendarEventFromClipboard = doGetSparkFeature(prefs_reload.get_calendar_event_from_clipboard);
let getTask = doGetSparkFeature(prefs_reload.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_reload.add_tags,
addtags_api: hasSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent,
get_calendar_event_from_clipboard: getCalendarEventFromClipboard,
get_task: getTask,
is_chatgpt_web: (prefs_reload.connection_type === "chatgpt_web")
});
@ -401,6 +404,29 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
case 'api_send_custom_text':
browser.tabs.sendMessage(message.tabId, { command: "api_send_custom_text", custom_text: message.custom_text });
break;
case 'checkSpamReport':
if(!prefs_init.spamfilter_show_msg_panel){
return;
}
async function _checkSpamReport(tabId) {
try {
if (sender.tab.type !== 'messageDisplay' && sender.tab.type !== 'mail') return;
let message = await browser.messageDisplay.getDisplayedMessage(tabId);
if (!message) return;
let report = await taSpamReport.loadReportData(message.headerMessageId);
if (report) {
browser.tabs.sendMessage(tabId, { command: "showSpamReport", data: report });
}
} catch (e) {
taLog.error("Error in checkSpamReport: " + e);
}
}
_checkSpamReport(sender.tab.id);
break;
case 'removeSpamReport':
taSpamReport.removeReportData(message.headerMessageId);
break;
default:
break;
}
@ -849,6 +875,7 @@ async function reload_pref_init(){
do_debug: prefs_default.do_debug,
add_tags: prefs_default.add_tags,
get_calendar_event: prefs_default.get_calendar_event,
get_calendar_event_from_clipboard: prefs_default.get_calendar_event_from_clipboard,
get_task: prefs_default.get_task,
connection_type: prefs_default.connection_type,
add_tags_auto: prefs_default.add_tags_auto,
@ -857,6 +884,7 @@ async function reload_pref_init(){
spamfilter: prefs_default.spamfilter,
summarize: prefs_default.summarize,
spamfilter_threshold: prefs_default.spamfilter_threshold,
spamfilter_show_msg_panel: prefs_default.spamfilter_show_msg_panel,
dynamic_menu_force_enter: prefs_default.dynamic_menu_force_enter,
...getDynamicSettingsDefaults(['use_specific_integration', 'connection_type'])
});
@ -874,11 +902,13 @@ function setupStorageChangeListener() {
if (changes.add_tags) {
const newTags = changes.add_tags.newValue;
let getCalendarEvent = doGetSparkFeature(prefs_init.get_calendar_event);
let getCalendarEventFromClipboard = doGetSparkFeature(prefs_init.get_calendar_event_from_clipboard);
let getTask = doGetSparkFeature(prefs_init.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: newTags,
addtags_api: hasSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent,
get_calendar_event_from_clipboard: getCalendarEventFromClipboard,
get_task: getTask,
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
});
@ -889,11 +919,30 @@ function setupStorageChangeListener() {
if (changes.get_calendar_event) {
const newCalendarEvent = changes.get_calendar_event.newValue;
let getCalendarEvent = doGetSparkFeature(newCalendarEvent);
let getCalendarEventFromClipboard = doGetSparkFeature(prefs_init.get_calendar_event_from_clipboard);
let getTask = doGetSparkFeature(prefs_init.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags,
addtags_api: hasSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent,
get_calendar_event_from_clipboard: getCalendarEventFromClipboard,
get_task: getTask,
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
});
menus.reload(special_prompts_ids);
}
// Process 'get_calendar_event_from_clipboard' changes
if (changes.get_calendar_event_from_clipboard) {
const newCalendarEventFromClipboard = changes.get_calendar_event_from_clipboard.newValue;
let getCalendarEvent = doGetSparkFeature(prefs_init.get_calendar_event);
let getCalendarEventFromClipboard = doGetSparkFeature(newCalendarEventFromClipboard);
let getTask = doGetSparkFeature(prefs_init.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags,
addtags_api: hasSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent,
get_calendar_event_from_clipboard: getCalendarEventFromClipboard,
get_task: getTask,
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
});
@ -904,11 +953,13 @@ function setupStorageChangeListener() {
if (changes.get_task) {
const newTask = changes.get_task.newValue;
let getCalendarEvent = doGetSparkFeature(prefs_init.get_calendar_event);
let getCalendarEventFromClipboard = doGetSparkFeature(prefs_init.get_calendar_event_from_clipboard);
let getTask = doGetSparkFeature(newTask);
const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags,
addtags_api: hasSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent,
get_calendar_event_from_clipboard: getCalendarEventFromClipboard,
get_task: getTask,
is_chatgpt_web: (prefs_init.connection_type === "chatgpt_web")
});
@ -919,11 +970,13 @@ function setupStorageChangeListener() {
if (changes.connection_type) {
const newConnectionType = changes.connection_type.newValue;
let getCalendarEvent = doGetSparkFeature(prefs_init.get_calendar_event);
let getCalendarEventFromClipboard = doGetSparkFeature(prefs_init.get_calendar_event_from_clipboard);
let getTask = doGetSparkFeature(prefs_init.get_task);
const special_prompts_ids = getActiveSpecialPromptsIDs({
addtags: prefs_init.add_tags,
addtags_api: hasSpecificIntegration(prefs_init.add_tags_use_specific_integration, prefs_init.add_tags_connection_type),
get_calendar_event: getCalendarEvent,
get_calendar_event_from_clipboard: getCalendarEventFromClipboard,
get_task: getTask,
is_chatgpt_web: (newConnectionType === "chatgpt_web")
});
@ -1284,6 +1337,18 @@ async function processEmails(messages, addTagsAuto, spamFilter) {
}
taSpamReport.saveReportData(report_data, message.headerMessageId);
// Check if the message is currently displayed and update the banner
if (prefs_init.spamfilter_show_msg_panel) {
let tabs = await browser.tabs.query({ active: true, currentWindow: true });
if (tabs.length > 0) {
let activeTab = tabs[0];
let displayedMessage = await browser.messageDisplay.getDisplayedMessage(activeTab.id);
if (displayedMessage && displayedMessage.id === message.id) {
browser.tabs.sendMessage(activeTab.id, { command: "showSpamReport", data: report_data });
}
}
}
}
}
taWorkingStatus.stopWorking();

View file

@ -125,13 +125,16 @@ export const prefs_default = {
add_tags_auto_uselist_list: '',
add_tags_enabled_accounts: [],
get_calendar_event: true,
get_calendar_event_from_clipboard: false, // Enable calendar event from clipboard menu item
get_task: true,
calendar_enforce_timezone: false,
calendar_timezone: '',
calendar_no_selection: false, // If true do not ask for selection, but use the full prompt
spamfilter: false,
spamfilter_threshold: 70,
spamfilter_enabled_accounts: [],
auto_summary_enabled: false, // Enable automatic AI summarization for message previews
spamfilter_show_msg_panel: true,
summarize: false,
...generated_prefs
}

View file

@ -17,8 +17,19 @@
<li><i>[OpenAI Comp API][Ollama API]</i> Asking for the single host for permission to avoid CORS errors, instead of <i>all_urls</i>, as requested by the Thunderbird Review Team [<a href="https://github.com/micz/ThunderAI/issues/524">#524</a>].</li>
<li>Fix: Using also the mail folder owner to search for the right identity to use when composing a reply [<a href="https://github.com/micz/ThunderAI/issues/627">#627</a>].</li>
<li>Context menu items are always ordered alfabetically [<a href="https://github.com/micz/ThunderAI/issues/630">#630</a>].</li>
<li>The prompt export now includes an option to incorporate specific API settings, when present [<a href="https://github.com/micz/ThunderAI/issues/624">#624</a>].</li>
<li>Added the <i>{%mail_text_body_or_selected%}</i> placeholder to retrieve the selected text or the full text body of the email if no selection is present [<a href="https://github.com/micz/ThunderAI/issues/641">#641</a>].</li>
<li>Added the <i>{%mail_html_body_or_selected%}</i> placeholder to retrieve the selected HTML or the full HTML body of the email if no selection is present [<a href="https://github.com/micz/ThunderAI/issues/641">#641</a>].</li>
<li><i>[All APIs]</i> Added an option to get a calendar event without selecting some text, but using the full text body of the email [<a href="https://github.com/micz/ThunderAI/issues/518">#518</a>].</li>
<li><i>[All APIs]</i> Added a new menu item to create a calendar event from the text saved in the clipboard [<a href="https://github.com/micz/ThunderAI/issues/362">#362</a>].</li>
<li>Added a button to copy a prompt in the Custom Prompts page [<a href="https://github.com/micz/ThunderAI/issues/598">#598</a>].</li>
<li><i>[All APIs]</i> Showing the spam filter info at the top of the message. The data is saved only for the session in which the message has been checked for spam [<a href="https://github.com/micz/ThunderAI/issues/506">#506</a>].</li>
<li>...</li>
</ul>
<h2>Version 3.8.4 - 10/02/2026</h2>
<ul>
<li><i>[ChatGPT Web]</i> Fix: Correctly importing the selected text into the compose windows also when ChatGPT shows the advanced mail editor in the response [<a href="https://github.com/micz/ThunderAI/issues/646">#646</a>].</li>
</ul>
<h2>Version 3.8.3 - 22/01/2026</h2>
<ul>
<li>Fix: Correctly saving the API settings in new custom prompts [<a href="https://github.com/micz/ThunderAI/issues/623">#623</a>].</li>

View file

@ -1,5 +1,5 @@
/**
* Tom Select v2.4.4
* Tom Select v2.4.6
* Licensed under the Apache License, Version 2.0 (the "License");
*/
@ -1889,6 +1889,8 @@
});
}
wrapper.style.width = input.style.width;
wrapper.style.minWidth = input.style.minWidth;
wrapper.style.maxWidth = input.style.maxWidth;
if (self.plugins.names.length) {
const classes_plugins = 'plugin-' + self.plugins.names.join(' plugin-');
addClasses([wrapper, dropdown], classes_plugins);
@ -1985,10 +1987,19 @@
self.positionDropdown();
}
};
const input_invalid = () => {
if (self.isValid) {
self.isValid = false;
self.isInvalid = true;
self.refreshState();
}
};
addEvent(input, 'invalid', input_invalid);
addEvent(document, 'mousedown', doc_mousedown);
addEvent(window, 'scroll', win_scroll, passive_event);
addEvent(window, 'resize', win_scroll, passive_event);
this._destroy = () => {
input.removeEventListener('invalid', input_invalid);
document.removeEventListener('mousedown', doc_mousedown);
window.removeEventListener('scroll', win_scroll);
window.removeEventListener('resize', win_scroll);
@ -2007,13 +2018,6 @@
settings.items = [];
delete settings.optgroups;
delete settings.options;
addEvent(input, 'invalid', () => {
if (self.isValid) {
self.isValid = false;
self.isInvalid = true;
self.refreshState();
}
});
self.refreshItems();
self.close(false);
self.inputState();
@ -2128,7 +2132,8 @@
sync(get_settings = true) {
const self = this;
const settings = get_settings ? getSettings(self.input, {
delimiter: self.settings.delimiter
delimiter: self.settings.delimiter,
allowEmptyOption: self.settings.allowEmptyOption
}) : self.settings;
self.setupOptions(settings.options, settings.optgroups);
self.setValue(settings.items || [], true); // silent prevents recursion
@ -2315,8 +2320,7 @@
// prevent default [tab] behaviour of jump to the next field
// if select isFull, then the dropdown won't be open and [tab] will work normally
preventDefault(e);
}
if (self.settings.create && self.createItem()) {
} else if (self.settings.create && self.createItem()) {
preventDefault(e);
}
}
@ -3512,6 +3516,12 @@
var output;
input = input || self.inputValue();
if (!self.canCreate(input)) {
const hash = hash_key(input);
if (hash) {
if (this.options[input]) {
self.addItem(input);
}
}
callback();
return false;
}
@ -3831,7 +3841,7 @@
const values = items.map(item => item.dataset.value);
// allow the callback to abort
if (!values.length || typeof this.settings.onDelete === 'function' && this.settings.onDelete(values, evt) === false) {
if (!values.length || typeof this.settings.onDelete === 'function' && this.settings.onDelete.call(this, values, evt) === false) {
return false;
}
return true;

File diff suppressed because one or more lines are too long

View file

@ -324,6 +324,8 @@ document.addEventListener('DOMContentLoaded', async () => {
let editBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnEditItem`);
//console.log(`>>>>>>>>>>>> tr[data-idnum="${curr_idnum}"] button.btnEditItem`);
editBtn.addEventListener('click', handleEditClick);
let copyBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnCopyItem`);
copyBtn.addEventListener('click', handleCopyClick);
//console.log('>>>>>>>>>>>>> editBtn: ' + JSON.stringify(editBtn));
let deleteBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnDeleteItem`);
//console.log(`>>>>>>>>>>>> tr[data-idnum="${curr_idnum}"] button.btnDeleteItem`);
@ -576,6 +578,7 @@ function handleEditClick(e) {
tr.querySelector('.btnConfirmItem').style.display = 'inline'; // Save btn
tr.querySelector('.btnCancelItem').style.display = 'inline'; // Cancel btn
// tr.querySelector('.btnEditItem').style.display = 'none'; // Edit btn
tr.querySelector('.btnCopyItem').style.display = 'none'; // Copy btn
tr.querySelector('.btnDeleteItem').style.display = 'none'; // Delete btn
showItemRowEditor(tr);
toggleDiffviewer(e);
@ -838,6 +841,7 @@ function handleCancelClick(e) {
tr.querySelector('.btnConfirmItem').style.display = 'none'; // Save btn
// tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn
tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn
tr.querySelector('.btnCopyItem').style.display = 'inline'; // Copy btn
tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn
tr.querySelector('.id_output').value = tr.querySelector('.id_show').innerText.toLocaleUpperCase();
tr.querySelector('.name_output').value = tr.querySelector('.name_show').innerText;
@ -891,6 +895,7 @@ function handleConfirmClick(e) {
// tr.querySelector('.btnConfirmItem').style.display = 'none'; // Ok btn
tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn
tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn
tr.querySelector('.btnCopyItem').style.display = 'inline'; // Copy btn
tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn
// Update item data
tr.querySelector('.type').innerText = tr.querySelector('.type_output').value;
@ -942,6 +947,88 @@ function handleInputChange(e) {
setSomethingChanged();
}
function handleCopyClick(e) {
e.preventDefault();
const tr = e.target.parentNode.parentNode;
let id = tr.querySelector('.id_output').value;
let name = tr.querySelector('.name_output').value;
let text = tr.querySelector('.text_output').value;
let type = tr.querySelector('.type_output').value;
let action = tr.querySelector('.action_output').value;
let need_selected = tr.querySelector('.need_selected').checked;
let need_signature = tr.querySelector('.need_signature').checked;
let need_custom_text = tr.querySelector('.need_custom_text').checked;
let define_response_lang = tr.querySelector('.define_response_lang').checked;
let use_diff_viewer = tr.querySelector('.use_diff_viewer').checked;
let chatgpt_web_model = tr.querySelector('.chatgpt_web_model_output').value;
let chatgpt_web_project = tr.querySelector('.chatgpt_web_project_output').value;
let chatgpt_web_custom_gpt = tr.querySelector('.chatgpt_web_custom_gpt_output').value;
const item = promptsList.get('id', id.toLowerCase())[0];
const itemValues = item.values();
// Populate new form
document.getElementById('txtIdNew').value = id + '_' + browser.i18n.getMessage("copy_text");
document.getElementById('txtNameNew').value = name + ' (' + browser.i18n.getMessage("copy_text") + ')';
document.getElementById('txtTextNew').value = text;
document.getElementById('selectTypeNew').value = type;
document.getElementById('selectActionNew').value = action;
document.getElementById('checkboxNeedSelectedNew').checked = need_selected;
document.getElementById('checkboxNeedSignatureNew').checked = need_signature;
document.getElementById('checkboxNeedCustomTextNew').checked = need_custom_text;
document.getElementById('checkboxDefineResponseLangNew').checked = define_response_lang;
let checkboxUseDiffViewerNew = document.getElementById('checkboxUseDiffViewerNew');
checkboxUseDiffViewerNew.checked = use_diff_viewer;
checkboxUseDiffViewerNew.disabled = (action !== "2");
document.getElementById('chatGPTWebModelNew').value = chatgpt_web_model;
document.getElementById('chatGPTWebProjectNew').value = chatgpt_web_project;
document.getElementById('chatGPTWebCustomGPTNew').value = chatgpt_web_custom_gpt;
const apiSelect = document.getElementById('new_prompt_api_type');
if (apiSelect) {
apiSelect.value = itemValues.api_type || '';
apiSelect.dispatchEvent(new Event('change'));
for (const [integration, options] of Object.entries(integration_options_config)) {
for (const key of Object.keys(options)) {
const propName = `${integration}_${key}`;
const inputEl = document.getElementById(propName);
if (inputEl) {
let val = itemValues[propName];
if (val === undefined) val = '';
if (inputEl.type === 'checkbox') {
inputEl.checked = (val === true || val === 'true');
} else {
if (inputEl.tomselect) {
inputEl.tomselect.setValue(val, true);
setTomSelectBorder(inputEl.tomselect);
} else {
inputEl.value = val;
}
}
}
}
}
}
// Show form
document.getElementById('formNew').style.display = 'block';
// Scroll to top
window.scrollTo({
top: 0,
behavior: 'smooth'
});
checkFields();
}
//========= handling an item in a row - END
@ -1071,6 +1158,8 @@ function loadPromptsList(values){
<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>
<br><br>
<button class="btnCopyItem">__MSG_customPrompts_btnCopy__</button>
</td>
</tr>`;
//console.log('>>>>>>>> values.name: ' + JSON.stringify(values.name));
@ -1111,6 +1200,11 @@ function loadPromptsList(values){
element.addEventListener('click', handleEditClick);
});
let btnCopyItem_elements = document.querySelectorAll(".btnCopyItem");
btnCopyItem_elements.forEach(element => {
element.addEventListener('click', handleCopyClick);
});
let btnDeleteItem_elements = document.querySelectorAll(".btnDeleteItem");
btnDeleteItem_elements.forEach(element => {
element.addEventListener('click', handleDeleteClick);
@ -1279,7 +1373,7 @@ async function saveAll() {
setMessage(browser.i18n.getMessage('customPrompts_saving_custom_prompts'));
await setCustomPrompts(newCustomPrompts);
setMessage(browser.i18n.getMessage('customPrompts_reloading_menus'));
browser.runtime.sendMessage({command: "reload_menus"});
await browser.runtime.sendMessage({command: "reload_menus"});
setMessage(browser.i18n.getMessage('customPrompts_saved'),'green');
msgTimeout = setTimeout(() => {
clearMessage();

View file

@ -26,6 +26,26 @@
</tr>
<tr id="connection_ui_anchor"></tr>
<tr id="connection_ui_end"><td colspan="2"></td></tr>
<tr class="get_calendar_event_tr">
<td><span class="opt_title">__MSG_prefs_OptionText_calendar_no_selection__</span>
</td>
<td>
<label>
<input type="checkbox" id="calendar_no_selection" name="calendar_no_selection" class="option-input" />
__MSG_prefs_OptionText_calendar_no_selection_Info__
</label>
</td>
</tr>
<tr class="get_calendar_event_tr">
<td><span class="opt_title">__MSG_prefs_OptionText_get_calendar_event_from_clipboard__</span>
</td>
<td>
<label>
<input type="checkbox" id="get_calendar_event_from_clipboard" name="get_calendar_event_from_clipboard" class="option-input" />
__MSG_prefs_OptionText_get_calendar_event_from_clipboard_Info__
</label>
</td>
</tr>
<tr class="get_calendar_event_tr">
<td><span class="opt_title">__MSG_prefs_OptionText_calendar_enforce_timezone__</span></td>
<td>

View file

@ -78,6 +78,8 @@ document.addEventListener('DOMContentLoaded', async () => {
let get_calendar_event_save_btn = document.getElementById('btn_save_prompt');
let get_calendar_event_reset_btn = document.getElementById('btn_reset_prompt');
let get_calendar_event_use_specific_integration = document.getElementById('get_calendar_event_use_specific_integration');
let get_calendar_event_no_selection = document.getElementById('calendar_no_selection');
let get_calendar_event_from_clipboard = document.getElementById('get_calendar_event_from_clipboard');
get_calendar_event_textarea.addEventListener('input', (event) => {
get_calendar_event_reset_btn.disabled = (event.target.value === browser.i18n.getMessage('prompt_get_calendar_event_full_text'));
@ -95,6 +97,41 @@ document.addEventListener('DOMContentLoaded', async () => {
}
});
get_calendar_event_no_selection.addEventListener('change', async (event) => {
specialPrompts.find(prompt => prompt.id === 'prompt_get_calendar_event').need_selected = event.target.checked ? '0' : '1';
await setSpecialPrompts(specialPrompts);
browser.runtime.sendMessage({command: "reload_menus"});
});
get_calendar_event_from_clipboard.addEventListener('change', async (event) => {
if (event.target.checked) {
// Request clipboardRead permission when enabling the feature
try {
const granted = await browser.permissions.request({
permissions: ["clipboardRead"]
});
if (granted) {
// Permission granted, enable the feature
await browser.storage.sync.set({ get_calendar_event_from_clipboard: true });
browser.runtime.sendMessage({command: "reload_menus"});
} else {
// Permission denied, uncheck the checkbox
event.target.checked = false;
alert(browser.i18n.getMessage("clipboard_permission_denied"));
}
} catch (err) {
taLog.error("Error requesting clipboard permission:", err);
event.target.checked = false;
alert(browser.i18n.getMessage("clipboard_permission_error"));
}
} else {
// Disabling the feature
await browser.storage.sync.set({ get_calendar_event_from_clipboard: false });
browser.runtime.sendMessage({command: "reload_menus"});
}
});
get_calendar_event_reset_btn.addEventListener('click', () => {
get_calendar_event_textarea.value = browser.i18n.getMessage('prompt_get_calendar_event_full_text');
get_calendar_event_reset_btn.disabled = true;
@ -102,9 +139,10 @@ document.addEventListener('DOMContentLoaded', async () => {
get_calendar_event_textarea.dispatchEvent(event);
});
get_calendar_event_save_btn.addEventListener('click', () => {
get_calendar_event_save_btn.addEventListener('click', async () => {
specialPrompts.find(prompt => prompt.id === 'prompt_get_calendar_event').text = get_calendar_event_textarea.value;
setSpecialPrompts(specialPrompts);
specialPrompts.find(prompt => prompt.id === 'prompt_get_calendar_event_from_clipboard').text = get_calendar_event_textarea.value;
await setSpecialPrompts(specialPrompts);
get_calendar_event_save_btn.disabled = true;
document.getElementById('get_calendar_event_prompt_unsaved').classList.add('hidden');
browser.runtime.sendMessage({command: "reload_menus"});

View file

@ -35,6 +35,15 @@
</label>
</td>
</tr>
<tr class="spamfilter_tr">
<td><span class="opt_title">__MSG_prefs_OptionText_spamfilter_show_msg_panel__</span></td>
<td>
<label>
<input type="checkbox" id="spamfilter_show_msg_panel" name="spamfilter_show_msg_panel" class="option-input" />
__MSG_prefs_OptionText_spamfilter_show_msg_panel_Info__
</label>
</td>
</tr>
</table>
<div id="spamfilter_container">
@ -57,7 +66,8 @@
<button type="button" id="accounts_deselect_all">__MSG_DeselectAll__</button>
</div>
<div id="spamfitler_reports_container">
<h2>__MSG_SpamReport_Title__</h2>
<div><span class="section_title">__MSG_SpamReport_Title__</span>
<br><span class="infoline">__MSG_SpamReport_infoline__</span></div>
<table id="report_data">
<thead>
<tr>

View file

@ -30,6 +30,7 @@ let add_tags = false;
let add_tags_use_specific_integration = false;
let add_tags_connection_type = '';
let get_calendar_event = false;
let get_calendar_event_from_clipboard = false;
let get_task = false;
let _ok_sparks = false;
let tabType;
@ -43,6 +44,7 @@ document.addEventListener('DOMContentLoaded', async () => {
add_tags_use_specific_integration: prefs_default.add_tags_use_specific_integration,
add_tags_connection_type: prefs_default.add_tags_connection_type,
get_calendar_event: prefs_default.get_calendar_event,
get_calendar_event_from_clipboard: prefs_default.get_calendar_event_from_clipboard,
get_task: prefs_default.get_task,
connection_type: prefs_default.connection_type
});
@ -66,6 +68,7 @@ document.addEventListener('DOMContentLoaded', async () => {
add_tags_use_specific_integration = prefs.add_tags_use_specific_integration;
add_tags_connection_type = prefs.add_tags_connection_type;
get_calendar_event = prefs.get_calendar_event;
get_calendar_event_from_clipboard = prefs.get_calendar_event_from_clipboard;
get_task = prefs.get_task;
_ok_sparks = await checkSparksPresence() == 1;
// console.log(">>>>>>>>>>>>>>>>> add_tags: " + add_tags);
@ -164,6 +167,7 @@ async function searchPrompt(allPrompts, tabId, tabType){
let do_add_tags = checkDoAddTags();
let do_get_calendar_event = checkDoCalendarEvent();
let do_get_calendar_event_from_clipboard = checkDoCalendarEventFromClipboard();
let do_get_task = checkDoTask();
// console.log(">>>>>>>>>>> do_add_tags: " + do_add_tags);
@ -171,7 +175,7 @@ async function searchPrompt(allPrompts, tabId, tabType){
// console.log(">>>>>>>>>>> do_get_task: " + do_get_task);
// console.log(">>>>>>>>>>> filteredData: " + JSON.stringify(filteredData));
num_special_menu_items = (do_add_tags ? 1 : 0) + (do_get_calendar_event ? 1 : 0) + (do_get_task ? 1 : 0);
num_special_menu_items = (do_add_tags ? 1 : 0) + (do_get_calendar_event ? 1 : 0) + (do_get_calendar_event_from_clipboard ? 1 : 0) + (do_get_task ? 1 : 0);
// console.log(">>>>>>>>>>>> num_special_menu_items: " + num_special_menu_items);
if(num_special_menu_items > 0){
max_num_el -= num_special_menu_items;
@ -192,10 +196,18 @@ async function searchPrompt(allPrompts, tabId, tabType){
filteredData[gce_curr_pos].numberPrepended = 'true';
filteredData[gce_curr_pos].label = gce_curr_pos + '. ' + filteredData[gce_curr_pos].label;
}
}
if(do_get_calendar_event_from_clipboard){
filteredData = ensurePromptGetCalendarEventFromClipboardFirst(filteredData, do_add_tags, do_get_calendar_event);
let gcefc_curr_pos = (do_add_tags ? 1 : 0) + (do_get_calendar_event ? 1 : 0);
if (!filteredData[gcefc_curr_pos].numberPrepended) {
filteredData[gcefc_curr_pos].numberPrepended = 'true';
filteredData[gcefc_curr_pos].label = gcefc_curr_pos + '. ' + filteredData[gcefc_curr_pos].label;
}
}
if(do_get_task){
filteredData = ensurePromptGetTaskFirst(filteredData, do_add_tags, do_get_calendar_event);
let gtask_curr_pos = (do_add_tags ? 1 : 0) + (do_get_calendar_event ? 1 : 0);
filteredData = ensurePromptGetTaskFirst(filteredData, do_add_tags, do_get_calendar_event, do_get_calendar_event_from_clipboard);
let gtask_curr_pos = (do_add_tags ? 1 : 0) + (do_get_calendar_event ? 1 : 0) + (do_get_calendar_event_from_clipboard ? 1 : 0);
if (!filteredData[gtask_curr_pos].numberPrepended) {
filteredData[gtask_curr_pos].numberPrepended = 'true';
filteredData[gtask_curr_pos].label = gtask_curr_pos + '. ' + filteredData[gtask_curr_pos].label;
@ -222,7 +234,7 @@ async function searchPrompt(allPrompts, tabId, tabType){
itemDiv.classList.add('mzta_autocomplete-item');
itemDiv.textContent = item.label;
itemDiv.setAttribute('data-id', item.id);
if((item.id === 'prompt_add_tags')||(item.id === 'prompt_get_calendar_event')||(item.id === 'prompt_get_task')){
if((item.id === 'prompt_add_tags')||(item.id === 'prompt_get_calendar_event')||(item.id === 'prompt_get_calendar_event_from_clipboard')||(item.id === 'prompt_get_task')){
itemDiv.className += ' special_prompt';
}
@ -388,6 +400,10 @@ function checkDoCalendarEvent(){
return get_calendar_event && (connection_type !== "chatgpt_web" && tabType !== 'messageCompose') && _ok_sparks;
}
function checkDoCalendarEventFromClipboard(){
return get_calendar_event_from_clipboard && (connection_type !== "chatgpt_web" && tabType !== 'messageCompose') && _ok_sparks;
}
function checkDoTask(){
return get_task && (connection_type !== "chatgpt_web" && tabType !== 'messageCompose') && _ok_sparks;
}
@ -424,18 +440,36 @@ function ensurePromptGetCalendarEventFirst(arr, do_add_tags) {
return arr;
}
function ensurePromptGetTaskFirst(arr, do_add_tags, do_get_calendar_event) {
function ensurePromptGetCalendarEventFromClipboardFirst(arr, do_add_tags, do_get_calendar_event) {
// Find the index of the object with id "prompt_get_calendar_event_from_clipboard"
const index = arr.findIndex(item => item.id === "prompt_get_calendar_event_from_clipboard");
const targetPosition = (do_add_tags ? 1 : 0) + (do_get_calendar_event ? 1 : 0);
// If found and needs repositioning
if (index !== -1 && index !== targetPosition) {
// Remove it from its current position
const [promptAddTags] = arr.splice(index, 1);
// Add it to the specified position
arr.splice(targetPosition, 0, promptAddTags);
}
return arr;
}
function ensurePromptGetTaskFirst(arr, do_add_tags, do_get_calendar_event, do_get_calendar_event_from_clipboard) {
// Find the index of the object with id "prompt_get_task"
const index = arr.findIndex(item => item.id === "prompt_get_task");
// Determine the target position to insert "prompt_get_task" after calendar
const targetPosition = (do_add_tags ? 1 : 0) + (do_get_calendar_event ? 1 : 0) + (do_get_calendar_event_from_clipboard ? 1 : 0);
// If found and needs repositioning
if (index !== -1 && ((do_get_calendar_event && do_add_tags) ? index !== 2 : (do_get_calendar_event ? index !== 1 : index !== 0))) {
if (index !== -1 && index !== targetPosition) {
// Remove it from its current position
const [promptGetTask] = arr.splice(index, 1);
// Determine the target position to insert "prompt_get_task" after calendar
const targetPosition = do_add_tags && do_get_calendar_event ? 2 : (do_get_calendar_event ? 1 : 0);
// Add it to the specified position
arr.splice(targetPosition, 0, promptGetTask);
}