commit
3c053d55d9
37 changed files with 2355 additions and 250 deletions
|
|
@ -8,6 +8,13 @@
|
|||
<h2>Version 2.4.0 - ??/??/2024</h2>
|
||||
<ul>
|
||||
<li>Default prompts text has been translated [<a href="https://github.com/micz/ThunderAI/issues/185">#185</a>].</li>
|
||||
<li>Data placeholder for the full available tags list added [<a href="https://github.com/micz/ThunderAI/issues/197">#197</a>].</li>
|
||||
<li>Data placeholder for the single mail tags list added [<a href="https://github.com/micz/ThunderAI/issues/198">#198</a>].</li>
|
||||
<li>User <a href="https://forms.gle/1qK2wcbuhaRzhwyt9">survey link</a> added [<a href="https://github.com/micz/ThunderAI/issues/202">#202</a>].</li>
|
||||
<li>Polish (pl) translation added, thanks to <a href="https://github.com/neexpl">neexpl</a>.</li>
|
||||
<li>The Custom Prompts tab has now an icon.</li>
|
||||
<li>The red border in the Custom Prompts configuration page that highlights a needed prompt configuration that is not selected is now removed when the corresponding placeholder is removed [<a href="https://github.com/micz/ThunderAI/issues/201">#201</a>].</li>
|
||||
<li>Minor bugs fixed.</li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
<h2>Version 2.3.4 - 06/12/2024</h2>
|
||||
|
|
|
|||
32
README.md
32
README.md
|
|
@ -6,11 +6,9 @@ It enables users to analyse, write, correct, and optimize their emails, facilita
|
|||
|
||||
ThunderAI is a tool for anyone looking to improve their email quality, both in content and grammar, making the writing process quicker and more intuitive.
|
||||
|
||||
You can also define, export and import your own **custom prompts**!
|
||||
[Find out how!](https://micz.it/thunderbird-addon-thunderai/custom-prompts/)
|
||||
You can also define, export and import your own **[custom prompts](https://micz.it/thunderbird-addon-thunderai/custom-prompts/)**!
|
||||
|
||||
In any custom prompt you can use additional **data placeholders**!
|
||||
[Find out how!](https://micz.it/thunderbird-addon-thunderai/data-placeholders/)
|
||||
In any custom prompt you can use additional **[data placeholders](https://micz.it/thunderbird-addon-thunderai/data-placeholders/)**!
|
||||
|
||||
|
||||
<br>
|
||||
|
|
@ -19,16 +17,16 @@ In any custom prompt you can use additional **data placeholders**!
|
|||
> [!TIP]
|
||||
> **Using ChatGPT**
|
||||
>
|
||||
> There is no need for an API key and is possibile to use this extension even with a free account, using the web interface!
|
||||
> There is no need for an API key and is possibile to use this extension even with a free account, using the **ChatGPT web interface**!
|
||||
>
|
||||
> Starting from version 2.0.0, if you want to connect with the OpenAI API integration, now you can use an API Key!
|
||||
> If you want to connect with the OpenAI API integration, instead, you can use an **API Key**!
|
||||
|
||||
<br>
|
||||
|
||||
> [!TIP]
|
||||
> **Using Ollama**
|
||||
>
|
||||
> From version 2.1.0 is possible to use a local Ollama server!
|
||||
> It's also possible to use a local Ollama server!
|
||||
>
|
||||
> Just remember to add `OLLAMA_ORIGINS = moz-extension://*` to the Ollama server environment variables.
|
||||
>
|
||||
|
|
@ -39,7 +37,8 @@ In any custom prompt you can use additional **data placeholders**!
|
|||
> [!TIP]
|
||||
> **Using an OpenAI Compatible API**
|
||||
>
|
||||
> From version 2.2.0 is possible to use a local OpenAI Compatible API server, like LM Studio!
|
||||
> You can also use a local OpenAI Compatible API server, like LM Studio!
|
||||
>
|
||||
> There is also an option to remove the "v1" segment from the API url, if needed.
|
||||
|
||||
|
||||
|
|
@ -75,16 +74,10 @@ Are you using this addon in your Thunderbird?
|
|||
- French (fr): Generated automatically
|
||||
- German (de): Generated automatically
|
||||
- Italian (it): [Mic](https://github.com/micz/)
|
||||
- Polski (pl): [neexpl](https://github.com/neexpl)
|
||||
- Português Brasileiro (pt-br): Bruno Pereira de Souza
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
### Miscellaneous
|
||||
- <a href="https://github.com/KudoAI/chatgpt.js">chatgpt.js</a> for providing methods to interact with the ChatGPT web frontend
|
||||
- <a href="https://github.com/ali-raheem/Aify">Aify</a> for inspiration
|
||||
- <a href="https://github.com/boxabirds">Julian Harris</a> for his project <a href="https://github.com/boxabirds/chatgpt-frontend-nobuild">chatgpt-frontend-nobuild</a>, that has been used as a starting point for the API Web Interface
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
|
|
@ -93,3 +86,12 @@ Are you using this addon in your Thunderbird?
|
|||
- <a href="https://loading.io">loading.io</a> for the dynamic menu loading SVG
|
||||
- [Fluent Design System](https://www.iconfinder.com/fluent-designsystem) for the Custom Prompts table sorting icons
|
||||
- [JessiGue](https://www.flaticon.com/authors/jessigue) for the show/hide icon for api key fields
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
### Miscellaneous
|
||||
- <a href="https://github.com/KudoAI/chatgpt.js">chatgpt.js</a> for providing methods to interact with the ChatGPT web frontend
|
||||
- <a href="https://github.com/boxabirds">Julian Harris</a> for his project <a href="https://github.com/boxabirds/chatgpt-frontend-nobuild">chatgpt-frontend-nobuild</a>, that has been used as a starting point for the API Web Interface
|
||||
- <a href="https://github.com/ali-raheem/Aify">Aify</a> for inspiration
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Sie können jetzt zusätzliche Datenplatzhalter verwenden!",
|
||||
"message": "Sie können zusätzliche Datenplatzhalter verwenden.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
|
|
|
|||
|
|
@ -680,7 +680,11 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "You can now use additional data placeholders!",
|
||||
"message": "You can use additional data placeholders.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline2": {
|
||||
"message": "You can change the prompt as you wish, but the response received from the AI must be a comma-separated list of tags!",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1" : {
|
||||
|
|
@ -742,5 +746,133 @@
|
|||
"prompt_this_full_text": {
|
||||
"message": "Reply with only the needed text and with no extra comments or other text.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags": {
|
||||
"message": "Add tags to emails",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_Info": {
|
||||
"message": "If checked, a menu item will be added to the menu to add tags to emails.",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_add_tags": {
|
||||
"message": "Add tags to this email",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_add_tags_full_text": {
|
||||
"message": "Analyze the following email text and generate a comma-separated list of tags that summarize its content. Use themes, key topics, and relevant descriptors as tags. Ensure the tags are concise and relevant to the email's content.\nEmail text: {%mail_text_body%}\nConsider the following details for context:\n- Sender: {%author%}\n- Recipients: {%recipients%}\n- CC list: {%cc_list%}\n- Email subject: {%mail_subject%}\nPlease base your tags on the email's text and context, ignoring unnecessary information or trivial details.",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_tags": {
|
||||
"message": "Mail tags",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_full_tags_list": {
|
||||
"message": "Existing tags",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_maxnum": {
|
||||
"message": "Maximum number of tags",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_maxnum_Info": {
|
||||
"message": "The maximum number of tags proposed by the AI. Set to 0 if you don't want to limit the number of tags.",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_add_tags_maxnum": {
|
||||
"message": "Limit the number of tags to",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_hide_exclusions": {
|
||||
"message": "Hide excluded tags",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_hide_exclusions_Info": {
|
||||
"message": "If checked, the tags that are present in the exclusion list will be hidden in the confirm dialog.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManageTagsInfo": {
|
||||
"message": "Manage tags settings",
|
||||
"description": ""
|
||||
},
|
||||
"AddTags_PageTitle": {
|
||||
"message": "Manage Tags Settings",
|
||||
"description": ""
|
||||
},
|
||||
"AddTags_info_default": {
|
||||
"message": "In this page you can modify the default prompt used to add tags to emails and manage the exclusion list.",
|
||||
"description": ""
|
||||
},
|
||||
"AddTags_prompt_text_title": {
|
||||
"message": "Current prompt text",
|
||||
"description": ""
|
||||
},
|
||||
"AddTags_excl_list_title": {
|
||||
"message": "Exclusion list",
|
||||
"description": ""
|
||||
},
|
||||
"AddTags_excl_list_infoline": {
|
||||
"message": "This is a list of tags that are not allowed to be added to emails.",
|
||||
"description": ""
|
||||
},
|
||||
"save": {
|
||||
"message": "Save",
|
||||
"description": ""
|
||||
},
|
||||
"addtags_info_limit_num": {
|
||||
"message": "This statement will be added at the end of the prompt:",
|
||||
"description": ""
|
||||
},
|
||||
"reset_default": {
|
||||
"message": "Reset to default",
|
||||
"description": ""
|
||||
},
|
||||
"addtags_excl_list_infoline2": {
|
||||
"message": "Add a word per line, or separated by a comma.",
|
||||
"description": ""
|
||||
},
|
||||
"addtags_dialog_title": {
|
||||
"message": "Add tags to the email",
|
||||
"description": ""
|
||||
},
|
||||
"addtags_exclude_tag": {
|
||||
"message": "Exclude tag",
|
||||
"description": ""
|
||||
},
|
||||
"addtags_no_tags_received": {
|
||||
"message": "No tags received from the AI.",
|
||||
"description": ""
|
||||
},
|
||||
"addtags_no_valid_tags": {
|
||||
"message": "No valid tags found, after filtering with the exclusion list.",
|
||||
"description": ""
|
||||
},
|
||||
"thunderai_error_title": {
|
||||
"message": "ThunderAI Error",
|
||||
"description": ""
|
||||
},
|
||||
"thunderai_warning_title": {
|
||||
"message": "ThunderAI Warning",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_first_uppercase": {
|
||||
"message": "First letter uppercase",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_add_tags_first_uppercase_Info": {
|
||||
"message": "If checked, the tags label will be set to lowercase letters with only the first letter uppercase.",
|
||||
"description": ""
|
||||
},
|
||||
"AddTags_prompt_prefs_title": {
|
||||
"message": "Add Tags Options",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_SurveyLinkText": {
|
||||
"message": "Share your feedback and help us improve ThunderAI!",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_SurveyLinkText2": {
|
||||
"message": "Click here, it only takes a minute!",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
|
|
@ -680,7 +680,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Vous pouvez maintenant utiliser des espaces réservés de données supplémentaires !",
|
||||
"message": "Vous pouvez utiliser des espaces réservés supplémentaires pour les données.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Ora puoi utilizzare segnaposti per i dati aggiuntivi!",
|
||||
"message": "Puoi utilizzare segnaposti per i dati aggiuntivi.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
|
|
|
|||
702
_locales/pl/messages.json
Normal file
702
_locales/pl/messages.json
Normal file
|
|
@ -0,0 +1,702 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Używaj ChatGPT lub Ollama do ulepszania swoich e-maili!",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"menu_title": {
|
||||
"message": "AI",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_lang": {
|
||||
"message": "Odpowiedz w ",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply": {
|
||||
"message": "Odpowiedz na ten e-mail",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_reply_advanced": {
|
||||
"message": "Odpowiedz na ten wątek",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_polite": {
|
||||
"message": "Przepisz uprzejmie",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_rewrite_formal": {
|
||||
"message": "Przepisz formalnie",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_classify": {
|
||||
"message": "Klasyfikuj",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_summarize_this": {
|
||||
"message": "Podsumuj to",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_translate_this": {
|
||||
"message": "Przetłumacz to",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_this": {
|
||||
"message": "Zapytaj o to",
|
||||
"description": ""
|
||||
},
|
||||
"prompt_selection_needed": {
|
||||
"message": "Aby kontynuować, musisz zaznaczyć tekst!",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_managePrompts": {
|
||||
"message": "Zarządzaj poleceniami",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_managePrompts_help": {
|
||||
"message": "Więcej informacji",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_managePrompts_info_default": {
|
||||
"message": "Domyślne polecenia nie są edytowalne. Możesz je wyłączyć, skopiować tekst polecenia i wkleić go do nowego, aby stworzyć zmodyfikowaną wersję.",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_managePrompts_info_default_2": {
|
||||
"message": "Możesz importować i eksportować polecenia. Istniejące polecenia o tym samym ID zostaną nadpisane. Polecenia z nowymi ID zostaną dodane.",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_managePrompts_info_default_3": {
|
||||
"message": "Jeśli wszystko jest poprawne, po imporcie kliknij przycisk 'Zapisz wszystko'.",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_start_saving": {
|
||||
"message": "Zapisywanie poleceń...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_reindexing_list": {
|
||||
"message": "Ponowne indeksowanie listy...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_filtering_prompts": {
|
||||
"message": "Filtrowanie polece<63><65>...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_saving_default_prompts": {
|
||||
"message": "Zapisywanie domyślnych poleceń...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_saving_custom_prompts": {
|
||||
"message": "Zapisywanie własnych poleceń...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_reloading_menus": {
|
||||
"message": "Odświeżanie menu...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_saved": {
|
||||
"message": "Polecenia zapisane!",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_ID": {
|
||||
"message": "ID",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_ID_rules": {
|
||||
"message": "Musi być unikalne, pisane małymi literami i bez spacji",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_Name": {
|
||||
"message": "Nazwa",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_Text": {
|
||||
"message": "Tekst polecenia",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_Action": {
|
||||
"message": "Akcja",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_need_selected": {
|
||||
"message": "Wymagane zaznaczenie tekstu",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_need_signature": {
|
||||
"message": "Zawsze dodawaj podpis",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_need_custom_text": {
|
||||
"message": "Poproś o dodatkowy tekst",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_enabled": {
|
||||
"message": "Włączone",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_required_fields": {
|
||||
"message": "Pola wymagane",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnEdit": {
|
||||
"message": "Edytuj",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnCancel": {
|
||||
"message": "Anuluj",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnOK": {
|
||||
"message": "OK",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnDelete": {
|
||||
"message": "Usuń",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnDelete_confirmText": {
|
||||
"message": "Czy na pewno chcesz usunąć ten element?",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_unsaved_changes": {
|
||||
"message": "Istnieją niezapisane zmiany!",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"message": "Zapisz wszystko",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Zapisz",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"message": "Dodaj nowe",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
"message": "Dodaj polecenie",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_add_to_menu": {
|
||||
"message": "Dodaj do menu",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_add_to_menu_always": {
|
||||
"message": "Zawsze",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_add_to_menu_reading": {
|
||||
"message": "Podczas czytania e-maila",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_add_to_menu_composing": {
|
||||
"message": "Podczas pisania e-maila",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_close_button": {
|
||||
"message": "Przycisk zamknięcia",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_do_reply": {
|
||||
"message": "Odpowiedz",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_substitute_text": {
|
||||
"message": "Zastąp tekst",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_working": {
|
||||
"message": "Praca w toku...",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_job_completed": {
|
||||
"message": "Zakończono!",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_job_completed_select": {
|
||||
"message": "Wybierz tekst, którego chcesz użyć i kliknij przycisk.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_get_answer": {
|
||||
"message": "Użyj wybranej odpowiedzi",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_close": {
|
||||
"message": "Zamknij",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_textarea_not_found_error": {
|
||||
"message": "Wygląda na to, że strona ChatGPT ładuje się zbyt długo. Jeśli ładowanie zakończy się, kliknij przycisk po prawej stronie. Jeśli problem będzie się powtarzał, sprawdź status usługi.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_btn_retry": {
|
||||
"message": "Spróbuj ponownie",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_sendbutton_not_found_error": {
|
||||
"message": "Kliknij przycisk wysyłania, aby przesłać zapytanie.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_user_not_logged_in": {
|
||||
"message": "Nie jesteś zalogowany do ChatGPT. Zaloguj się swoimi danymi, zamknij okno ChatGPT, a następnie powtórz próbę. Po autoryzacji pozostaniesz zalogowany.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_model_warning": {
|
||||
"message": "Ustawiłeś opcję używania określonego modelu, ale wygląda na to, że nie ładuje się on poprawnie. Sprawdź wartość i spróbuj ponownie. Na razie możesz nacisnąć niebieski przycisk, aby kontynuować.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_custom_text": {
|
||||
"message": "Wstaw tutaj dodatkowy tekst dla zapytania.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_send": {
|
||||
"message": "Wyślij",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Użyj GPT3.5",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_force_completion": {
|
||||
"message": "wymuś zakończenie",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_force_completion_title": {
|
||||
"message": "Kliknij tutaj, aby wyświetlić przycisk 'Użyj ostatniej odpowiedzi', jeśli ChatGPT zakończył pracę, ale przycisk się nie pojawił.",
|
||||
"description": ""
|
||||
},
|
||||
"msg_prompt_too_long": {
|
||||
"message": "Podany tekst jest zbyt długi. Musisz go skrócić.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_release_notes": {
|
||||
"message": "Informacje o wydaniu",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_status_page": {
|
||||
"message": "status usługi",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_text": {
|
||||
"message": "Wymiary okna ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_height": {
|
||||
"message": "Wysokość",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_width": {
|
||||
"message": "Szerokość",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_default_sign_name": {
|
||||
"message": "Domyślna nazwa podpisu",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_default_chatgpt_lang": {
|
||||
"message": "Domyślny język odpowiedzi",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_reply_all": {
|
||||
"message": "Odpowiedz wszystkim",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_reply_sender": {
|
||||
"message": "Odpowiedz nadawcy",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_reply_type": {
|
||||
"message": "Typ odpowiedzi",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts": {
|
||||
"message": "Zarządzaj poleceniami",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoTitle": {
|
||||
"message": "Ważne informacje",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoDesc_1": {
|
||||
"message": "Może się zdarzyć, że interfejs ChatGPT zmieni się w sposób, który zakłóci działanie dodatku. Sprawdź stronę \"Status usługi\" połączoną na dole tej strony. Pamiętaj też, że przy pierwszym użyciu ThunderAI musisz zalogować się do ChatGPT.",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoDesc_2": {
|
||||
"message": "Aby korzystać z API ChatGPT, potrzebujesz klucza API OpenAI ChatGPT i musisz wybrać model.",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoDesc_3": {
|
||||
"message": "Aby korzystać z integracji z Ollama, musisz skonfigurować lokalny serwer Ollama. Po uruchomieniu serwera wprowadź jego adres w odpowiednim polu w aplikacji. Aby zapewnić prawidłową komunikację między ThunderAI a serwerem Ollama pamiętaj o ustawieniu OLLAMA_ORIGINS=moz-extension://*.",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoDesc_4": {
|
||||
"message": "Aby korzystać z tej integracji, musisz skonfigurować lokalny serwer kompatybilny z API OpenAI, jak LM Studio. Po uruchomieniu serwera wprowadź jego adres w odpowiednim polu w aplikacji. Aby zapewnić prawidłową komunikację między ThunderAI a serwerem lokalnym pamiętaj o prawidłowym ustawieniu CORS.",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoDesc_5": {
|
||||
"message": "Pamiętaj, że możesz otworzyć menu ThunderAI używając skrótu klawiszowego CTRL+ALT+A.",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoDesc_6": {
|
||||
"message": "Możesz zmienić skrót klikając ikonę koła zębatego w prawym górnym rogu tej strony i wybierając \"Zarządzaj skrótami rozszerzenia\".",
|
||||
"description": ""
|
||||
},
|
||||
"prefsDonation_1": {
|
||||
"message": "Czy podoba Ci się ten dodatek?",
|
||||
"description": ""
|
||||
},
|
||||
"prefsDonation_2": {
|
||||
"message": "Rozważ wsparcie poprzez darowiznę!",
|
||||
"description": ""
|
||||
},
|
||||
"backToOptionsText": {
|
||||
"message": "Opcje",
|
||||
"description": ""
|
||||
},
|
||||
"TranslateText": {
|
||||
"message": "Czy chcesz pomóc w tłumaczeniu tego dodatku?",
|
||||
"description": ""
|
||||
},
|
||||
"TranslateLink": {
|
||||
"message": "Dowiedz się jak!",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_ExportAll": {
|
||||
"message": "Eksportuj wszystkie polecenia",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_Import": {
|
||||
"message": "Importuj nowe polecenia",
|
||||
"description": ""
|
||||
},
|
||||
"importPrompts_confirmText": {
|
||||
"message": "Zamierzasz zaimportować nowe polecenia.",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_start_import": {
|
||||
"message": "Rozpoczynanie importu własnych poleceń...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_import_completed": {
|
||||
"message": "Import własnych poleceń zakończony! Musisz kliknąć przycisk 'Zapisz wszystko', aby zapisać zmiany.",
|
||||
"description": ""
|
||||
},
|
||||
"importPrompts_invalidFile": {
|
||||
"message": "Plik, który próbujesz zaimportować, nie jest prawidłowym plikiem poleceń.",
|
||||
"description": ""
|
||||
},
|
||||
"importPrompts_invalidPrompts": {
|
||||
"message": "Plik, który próbujesz zaimportować, nie zawiera żadnych prawidłowych poleceń.",
|
||||
"description": ""
|
||||
},
|
||||
"currently_used_prompt": {
|
||||
"message": "Aktualnie używana nazwa polecenia",
|
||||
"description": ""
|
||||
},
|
||||
"customprompts_form_label_define_response_lang": {
|
||||
"message": "Określ język odpowiedzi w poleceniu",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type": {
|
||||
"message": "Typ połączenia",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGPT_Web": {
|
||||
"message": "Interfejs webowy ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_ChatGPT_API": {
|
||||
"message": "API ChatGPT OpenAI",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_ChatGPT_API_Key": {
|
||||
"message": "Klucz API ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"ChatGPT_Models": {
|
||||
"message": "Modele ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"ChatGPT_Models_Fetch": {
|
||||
"message": "Zaktualizuj listę modeli ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"ChatGPT_Models_Error_fetching": {
|
||||
"message": "Błąd podczas pobierania modeli ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"Loading": {
|
||||
"message": "Ładowanie...",
|
||||
"description": ""
|
||||
},
|
||||
"error": {
|
||||
"message": "Błąd ThunderAI!",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_empty_apikey": {
|
||||
"message": "Nie dodałeś klucza API dla ChatGPT API. Proszę wprowadź go na stronie opcji.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_empty_model": {
|
||||
"message": "Nie wybrałeś modelu dla ChatGPT API. Proszę wybierz jeden na stronie opcji.",
|
||||
"description": ""
|
||||
},
|
||||
"chagpt_api_send_button": {
|
||||
"message": "Używając modelu",
|
||||
"description": ""
|
||||
},
|
||||
"chagpt_api_connecting": {
|
||||
"message": "Próba połączenia z OpenAI ChatGPT przy użyciu podanego klucza API",
|
||||
"description": ""
|
||||
},
|
||||
"Debug": {
|
||||
"message": "Debugowanie",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_do_debug_info": {
|
||||
"message": "Aktywuj system debugowania",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_Ollama_API": {
|
||||
"message": "API Ollama (Lokalny LLM)",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_Connection_type_OpenAI_Comp_API": {
|
||||
"message": "API kompatybilne z OpenAI",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_API_Host": {
|
||||
"message": "Adres hosta",
|
||||
"description": ""
|
||||
},
|
||||
"Ollama_Models": {
|
||||
"message": "Modele Ollama",
|
||||
"description": ""
|
||||
},
|
||||
"Ollama_Models_Fetch": {
|
||||
"message": "Zaktualizuj listę modeli Ollama",
|
||||
"description": ""
|
||||
},
|
||||
"Ollama_Models_Error_fetching": {
|
||||
"message": "Błąd podczas pobierania modeli Ollama",
|
||||
"description": ""
|
||||
},
|
||||
"API_Models_Error_NoModels": {
|
||||
"message": "Nie znaleziono modeli",
|
||||
"description": ""
|
||||
},
|
||||
"ollama_empty_host": {
|
||||
"message": "Nie dodałeś adresu hosta dla API Ollama. Proszę wprowadź go na stronie opcji.",
|
||||
"description": ""
|
||||
},
|
||||
"ollama_empty_model": {
|
||||
"message": "Nie wybrałeś modelu dla API Ollama. Proszę wybierz jeden na stronie opcji.",
|
||||
"description": ""
|
||||
},
|
||||
"ollama_api_connecting": {
|
||||
"message": "Próba połączenia z lokalnym serwerem Ollama używając hosta",
|
||||
"description": ""
|
||||
},
|
||||
"andModel": {
|
||||
"message": "i modelu",
|
||||
"description": ""
|
||||
},
|
||||
"error_connection_interrupted": {
|
||||
"message": "Połączenie z serwerem zostało nieoczekiwanie przerwane",
|
||||
"description": ""
|
||||
},
|
||||
"ollama_api_request_failed": {
|
||||
"message": "Zapytanie do API Ollama nie powiodło się",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_api_request_failed": {
|
||||
"message": "Zapytanie do API OpenAI ChatGPT nie powiodło się",
|
||||
"description": ""
|
||||
},
|
||||
"WaitingServerReponse": {
|
||||
"message": "Oczekiwanie na odpowiedź serwera",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_API_Host_Info": {
|
||||
"message": "Taki jak",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_Models": {
|
||||
"message": "Modele API kompatybilne z OpenAI",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_Models_Fetch": {
|
||||
"message": "Zaktualizuj listę modeli API kompatybilnych z OpenAI",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_Models_Error_fetching": {
|
||||
"message": "Błąd podczas pobierania modeli API kompatybilnych z OpenAI",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_empty_host": {
|
||||
"message": "Nie dodałeś adresu hosta dla API kompatybilnego z OpenAI. Proszę wprowadź go na stronie opcji.",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_empty_model": {
|
||||
"message": "Nie wybrałeś modelu dla API kompatybilnego z OpenAI. Proszę wybierz jeden na stronie opcji.",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_api_connecting": {
|
||||
"message": "Próba połączenia z lokalnym serwerem API kompatybilnym z OpenAI używając hosta",
|
||||
"description": ""
|
||||
},
|
||||
"OpenAIComp_api_request_failed": {
|
||||
"message": "Zapytanie do API kompatybilnego z OpenAI nie powiodło się",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OpenAIComp_ChatName": {
|
||||
"message": "Nazwa czatu",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OpenAIComp_ChatName_Info": {
|
||||
"message": "To jest nazwa, która będzie używana w czacie AI.",
|
||||
"description": ""
|
||||
},
|
||||
"StorageSpace": {
|
||||
"message": "Całkowita zajęta przestrzeń dyskowa",
|
||||
"description": ""
|
||||
},
|
||||
"SearchPrompt": {
|
||||
"message": "Szukaj poleceń",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_dynamic_menu_force_enter": {
|
||||
"message": "Menu: natychmiastowe wysyłanie polecenia",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_dynamic_menu_force_enter_info": {
|
||||
"message": "Jeśli zaznaczone, użycie skrótu klawiszowego CTRL+ALT+A automatycznie wyśle zaznaczone polecenie z menu. W przeciwnym razie nazwa polecenia zostanie wyświetlona użytkownikowi, wymagając kolejnego naciśnięcia klawisza Enter, aby je wysłać.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_dynamic_menu_order_alphabet": {
|
||||
"message": "Menu: sortuj alfabetycznie",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_dynamic_menu_order_alphabet_info": {
|
||||
"message": "Jeśli zaznaczone, polecenia w menu będą uporządkowane alfabetycznie.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_win_dims_info": {
|
||||
"message": "Ustaw na 0, jeśli nie chcesz określać rozmiaru okna.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OpenAIComp_API_Key": {
|
||||
"message": "Klucz API kompatybilny z OpenAI",
|
||||
"description": ""
|
||||
},
|
||||
"Optional": {
|
||||
"message": "Opcjonalne",
|
||||
"description": ""
|
||||
},
|
||||
"OpenChatGPTTab": {
|
||||
"message": "Otwórz kartę ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"OpenChatGPTTab_Info": {
|
||||
"message": "W przypadku problemów z logowaniem w oknie ThunderAI, otwórz ChatGPT w nowej karcie używając przycisku po prawej stronie, zaloguj się, następnie zamknij kartę i kontynuuj korzystanie z ThunderAI.",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_text_body": {
|
||||
"message": "Treść wiadomości",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_html_body": {
|
||||
"message": "Treść wiadomości HTML",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_mail_subject": {
|
||||
"message": "Temat wiadomości",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_selected_text": {
|
||||
"message": "Zaznaczony tekst",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_additional_text": {
|
||||
"message": "Dodatkowy tekst",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_junk_score": {
|
||||
"message": "Wynik spam",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_recipients": {
|
||||
"message": "Odbiorcy",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_cc_list": {
|
||||
"message": "Lista DW",
|
||||
"description": ""
|
||||
},
|
||||
"placeholder_author": {
|
||||
"message": "Autor",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value": {
|
||||
"message": "Symbole zastępcze: użyj wartości domyślnej",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_placeholders_use_default_value_info": {
|
||||
"message": "Jeśli zaznaczone, symbole zastępcze zostaną wypełnione wartościami domyślnymi, gdy nie podano wartości. W przeciwnym razie symbole zastępcze pozostaną na miejscu.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length": {
|
||||
"message": "Maksymalna długość polecenia",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_max_prompt_length_Info": {
|
||||
"message": "To jest maksymalna liczba znaków, która może być użyta w poleceniu. W przeciwnym razie zostanie wyświetlony komunikat o błędzie. Wartość nie jest edytowalna dla interfejsu webowego ChatGPT.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model": {
|
||||
"message": "Model interfejsu webowego ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model_info": {
|
||||
"message": "To jest model, który będzie wymuszony dla interfejsu webowego ChatGPT. Jeśli nie zostanie określony lub podano nieprawidłowy, domyślny model zostanie ustawiony przez ChatGPT na stronie.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat": {
|
||||
"message": "Tymczasowy czat w interfejsie webowym ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_tempchat_info": {
|
||||
"message": "Jeśli zaznaczone, w interfejsie webowym ChatGPT będzie używany tymczasowy czat.",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_btn_model": {
|
||||
"message": "Użyj bieżącego modelu",
|
||||
"description": ""
|
||||
},
|
||||
"SendingPrompt": {
|
||||
"message": "Wysyłanie polecenia...",
|
||||
"description": ""
|
||||
},
|
||||
"AllowedValues": {
|
||||
"message": "Dozwolone wartości",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Możesz użyć dodatkowych symboli zastępczych danych.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
"message": "Zachowaj kompatybilność z \"v1\"",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1_info": {
|
||||
"message": "Jeśli zaznaczone, segment \"v1\" w ścieżce wywołań API zostanie zachowany, np. \"http://localhost:1234/v1/chat/completions\".",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_owl_warning": {
|
||||
"message": "Wygląda na to, że przynajmniej jedno z Twoich kont używa dodatku Owl for Exchange. Istnieje znany problem między Thunderbirdem a Owl, który jest obecnie rozwiązywany. Na ten moment możesz używać ThunderAI podczas pisania e-maili, ale nie podczas ich czytania.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_chatgpt_web_model_tooltip": {
|
||||
"message": "Kliknij na wartość, aby ją ustawić.",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
|
|
@ -680,7 +680,7 @@
|
|||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_btnManagePrompts_infoline": {
|
||||
"message": "Agora você pode usar marcadores de posição adicionais!",
|
||||
"message": "Você pode usar marcadores de posição adicionais para dados.",
|
||||
"description": ""
|
||||
},
|
||||
"prefs_OptionText_openai_comp_use_v1": {
|
||||
|
|
|
|||
|
|
@ -45,13 +45,13 @@ let worker = null;
|
|||
|
||||
switch (llm) {
|
||||
case "chatgpt_api":
|
||||
worker = new Worker('model-worker-openai.js', { type: 'module' });
|
||||
worker = new Worker('../js/workers/model-worker-openai.js', { type: 'module' });
|
||||
break;
|
||||
case "ollama_api":
|
||||
worker = new Worker('model-worker-ollama.js', { type: 'module' });
|
||||
worker = new Worker('../js/workers/model-worker-ollama.js', { type: 'module' });
|
||||
break;
|
||||
case "openai_comp_api":
|
||||
worker = new Worker('model-worker-openai_comp.js', { type: 'module' });
|
||||
worker = new Worker('../js/workers/model-worker-openai_comp.js', { type: 'module' });
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
17
images/exclude-tag.svg
Normal file
17
images/exclude-tag.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<svg width="128" height="128" style="enable-background:new 0 0 128 128;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="64" x2="64" y1="18.6667" y2="124.8554">
|
||||
<stop offset="0" style="stop-color:#FF5252"/>
|
||||
<stop offset="0.324" style="stop-color:#F33B3B"/>
|
||||
<stop offset="1" style="stop-color:#D50000"/>
|
||||
</linearGradient>
|
||||
<circle cx="64" cy="64" r="60" style="fill:url(#SVGID_1_);"/>
|
||||
<g style="opacity:0.2;">
|
||||
<path d="M64,7c31.43,0,57,25.57,57,57s-25.57,57-57,57S7,95.43,7,64S32.57,7,64,7 M64,4 C30.86,4,4,30.86,4,64s26.86,60,60,60s60-26.86,60-60S97.14,4,64,4L64,4z" style="fill:#424242;"/>
|
||||
</g>
|
||||
<g style="opacity:0.2;">
|
||||
<path d="M104,56c2.21,0,4,1.79,4,4v8c0,2.21-1.79,4-4,4H24c-2.21,0-4-1.79-4-4v-8c0-2.21,1.79-4,4-4H104 M104,53H24c-3.86,0-7,3.14-7,7v8c0,3.86,3.14,7,7,7h80c3.86,0,7-3.14,7-7v-8C111,56.14,107.86,53,104,53L104,53z" style="fill:#424242;"/>
|
||||
</g>
|
||||
<path d="M104,72H24c-2.21,0-4-1.79-4-4v-8c0-2.21,1.79-4,4-4h80c2.21,0,4,1.79,4,4v8 C108,70.21,106.21,72,104,72z" style="fill:#FAFAFA;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
28
js/mzta-addatags-exclusion-list.js
Normal file
28
js/mzta-addatags-exclusion-list.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 Mic (m@micz.it)
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// These methods are also defined in the file /js/mzta-compose-script.js
|
||||
|
||||
export async function addTags_getExclusionList() {
|
||||
let prefs_excluded_tags = await browser.storage.local.get({add_tags_exclusions: []});
|
||||
return prefs_excluded_tags.add_tags_exclusions;
|
||||
}
|
||||
|
||||
export function addTags_setExclusionList(add_tags_exclusions) {
|
||||
browser.storage.local.set({add_tags_exclusions: add_tags_exclusions});
|
||||
}
|
||||
|
|
@ -61,46 +61,12 @@ switch (message.command) {
|
|||
case 'sendAlert':
|
||||
//console.log(">>>>>> message.curr_tab_type: " + JSON.stringify(message.curr_tab_type));
|
||||
if(message.curr_tab_type == 'mail'){ // workaround for Thunderbird bug not showing the alert
|
||||
// Create dialog elements
|
||||
const dialog_sendAlert = window.document.createElement('dialog');
|
||||
dialog_sendAlert.classList.add('mzta_dialog');
|
||||
|
||||
const content_sendAlert = window.document.createElement('div');
|
||||
content_sendAlert.classList.add('mzta_dialog_content');
|
||||
|
||||
// Create close button
|
||||
const closeButton_sendAlert = window.document.createElement('button');
|
||||
closeButton_sendAlert.classList.add('mzta_dialog_close');
|
||||
closeButton_sendAlert.id = 'mzta_dialog_close';
|
||||
closeButton_sendAlert.textContent = 'Close';
|
||||
|
||||
// Create message element
|
||||
const message_sendAlert = window.document.createElement('div');
|
||||
message_sendAlert.classList.add('mzta_dialog_message');
|
||||
message_sendAlert.textContent = message.message;
|
||||
|
||||
// Append elements to the dialog
|
||||
content_sendAlert.appendChild(message_sendAlert);
|
||||
content_sendAlert.appendChild(closeButton_sendAlert);
|
||||
dialog_sendAlert.appendChild(content_sendAlert);
|
||||
window.document.body.appendChild(dialog_sendAlert);
|
||||
|
||||
// Show the dialog
|
||||
dialog_sendAlert.showModal();
|
||||
|
||||
// Close dialog on button click and remove elements from the DOM
|
||||
closeButton_sendAlert.onclick = () => {
|
||||
dialog_sendAlert.close();
|
||||
dialog_sendAlert.addEventListener('close', () => {
|
||||
dialog_sendAlert.remove();
|
||||
style.remove();
|
||||
});
|
||||
};
|
||||
|
||||
// CSS styles for Thunderbird with support for light and dark themes
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.mzta_dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
|
|
@ -118,18 +84,23 @@ switch (message.command) {
|
|||
|
||||
.mzta_dialog_content {
|
||||
position: relative;
|
||||
padding: 20px;
|
||||
padding: 10px;
|
||||
overflow-y: auto;
|
||||
overflow-x: clip;
|
||||
max-height: 80vh;
|
||||
flex: 1;
|
||||
margin-bottom: 34px;
|
||||
}
|
||||
|
||||
.mzta_dialog_close {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
bottom: 2px;
|
||||
right: 2px;
|
||||
background: #007bff;
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
padding: 8px 12px;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
|
@ -140,10 +111,22 @@ switch (message.command) {
|
|||
|
||||
.mzta_dialog_message {
|
||||
margin-bottom: 40px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Theme support */
|
||||
h2.addtags{
|
||||
margin:0;
|
||||
font-size: 1.2em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.div_btns{
|
||||
width: 90%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
bottom: 4px;
|
||||
}
|
||||
|
||||
:root {
|
||||
--dialog-bg-color: #ffffff;
|
||||
--dialog-text-color: #000000;
|
||||
|
|
@ -155,29 +138,366 @@ switch (message.command) {
|
|||
--dialog-text-color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Darker overlay for the page background */
|
||||
.mzta_dialog_overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
z-index: 1000;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Create dialog elements
|
||||
const dialog_sendAlert = window.document.createElement('dialog');
|
||||
dialog_sendAlert.classList.add('mzta_dialog');
|
||||
|
||||
const title = document.createElement('h2');
|
||||
title.className = 'addtags';
|
||||
if(message.is_error){
|
||||
title.textContent = browser.i18n.getMessage("thunderai_error_title");
|
||||
}else{
|
||||
title.textContent = browser.i18n.getMessage("thunderai_warning_title");
|
||||
}
|
||||
dialog_sendAlert.appendChild(title);
|
||||
|
||||
const content_sendAlert = window.document.createElement('div');
|
||||
content_sendAlert.classList.add('mzta_dialog_content');
|
||||
|
||||
// Add a div for buttons
|
||||
const buttonsDiv = document.createElement('div');
|
||||
buttonsDiv.className = 'div_btns';
|
||||
|
||||
// Create close button
|
||||
const closeButton_sendAlert = window.document.createElement('button');
|
||||
closeButton_sendAlert.classList.add('mzta_dialog_close');
|
||||
closeButton_sendAlert.id = 'mzta_dialog_close';
|
||||
closeButton_sendAlert.textContent = 'Close';
|
||||
buttonsDiv.appendChild(closeButton_sendAlert);
|
||||
|
||||
// Create message element
|
||||
const message_sendAlert = window.document.createElement('div');
|
||||
message_sendAlert.classList.add('mzta_dialog_message');
|
||||
message_sendAlert.textContent = message.message;
|
||||
|
||||
// Append elements to the dialog
|
||||
content_sendAlert.appendChild(message_sendAlert);
|
||||
dialog_sendAlert.appendChild(content_sendAlert);
|
||||
dialog_sendAlert.appendChild(buttonsDiv);
|
||||
window.document.body.appendChild(dialog_sendAlert);
|
||||
|
||||
// Show the dialog
|
||||
dialog_sendAlert.showModal();
|
||||
|
||||
// Close dialog on button click and remove elements from the DOM
|
||||
closeButton_sendAlert.onclick = () => {
|
||||
dialog_sendAlert.close();
|
||||
dialog_sendAlert.addEventListener('close', () => {
|
||||
dialog_sendAlert.remove();
|
||||
style.remove();
|
||||
});
|
||||
};
|
||||
|
||||
const iframeHeight = window.innerHeight;
|
||||
const iframeWidth = window.innerWidth;
|
||||
|
||||
const dialogRect = dialog_sendAlert.getBoundingClientRect();
|
||||
|
||||
const top = Math.max(0, (iframeHeight - dialogRect.height) / 2);
|
||||
const left = Math.max(0, (iframeWidth - dialogRect.width) / 2);
|
||||
|
||||
dialog_sendAlert.style.top = `${top}px`;
|
||||
dialog_sendAlert.style.left = `${left}px`;
|
||||
dialog_sendAlert.style.maxHeight = `${iframeHeight - 40}px`;
|
||||
|
||||
dialog_sendAlert.style.transform = 'translate(0, 0)';
|
||||
|
||||
}else{
|
||||
alert(message.message);
|
||||
}
|
||||
return Promise.resolve(true);
|
||||
break;
|
||||
|
||||
case "getTags":
|
||||
console.log(">>>>>>>>>>>>>> getTags: " + JSON.stringify(message.tags));
|
||||
|
||||
// ===== These methods are also defined in the file /js/mzta-addatags-exclusion-list.js
|
||||
async function addTags_getExclusionList() {
|
||||
let prefs_excluded_tags = await browser.storage.local.get({add_tags_exclusions: []});
|
||||
console.log(">>>>>>>>>>>>>>> addTags_getExclusionList prefs_excluded_tags: " + JSON.stringify(prefs_excluded_tags));
|
||||
return prefs_excluded_tags.add_tags_exclusions;
|
||||
}
|
||||
|
||||
function addTags_setExclusionList(add_tags_exclusions) {
|
||||
browser.storage.local.set({add_tags_exclusions: add_tags_exclusions});
|
||||
}
|
||||
// ===================================================================================
|
||||
|
||||
// Create and append the styles
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.mzta_dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
width: 300px;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
padding: 0.5em;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
background-color: var(--dialog-bg-color, #fff);
|
||||
color: var(--dialog-text-color, #000);
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.mzta_dialog_content {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
max-height: 80vh;
|
||||
flex: 1;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mzta_dialog_btn {
|
||||
background: #007bff;
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mzta_dialog_btn_margin{
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.mzta_dialog_btn:hover {
|
||||
background: #0056b3;
|
||||
}
|
||||
|
||||
.mzta_dialog_message {
|
||||
margin-bottom: 40px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mzta_dialog_message2{
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.div_btns{
|
||||
width: 90%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
bottom: 4px;
|
||||
}
|
||||
|
||||
.tag_excluded{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
h2.addtags{
|
||||
margin:0;
|
||||
font-size: 1.2em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img.exclude-tag-icon{
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 2px;
|
||||
margin-left: 2px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--dialog-bg-color: #2e2e2e;
|
||||
--dialog-text-color: #ffffff;
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
async function createDialog(inputString, onSubmit) {
|
||||
// Create the dialog
|
||||
const tags_dialog = document.createElement('dialog');
|
||||
tags_dialog.className = 'mzta_dialog';
|
||||
|
||||
const title = document.createElement('h2');
|
||||
title.className = 'addtags';
|
||||
title.textContent = browser.i18n.getMessage("addtags_dialog_title");
|
||||
tags_dialog.appendChild(title);
|
||||
|
||||
// Create the content
|
||||
const content = document.createElement('div');
|
||||
content.className = 'mzta_dialog_content';
|
||||
|
||||
let no_submit = false;
|
||||
|
||||
// Parse the input string into labels
|
||||
const words = inputString.split(',').map(word => word.trim()).filter(word => word !== '');
|
||||
|
||||
console.log(">>>>>>>>>>>>> words: " + JSON.stringify(words));
|
||||
|
||||
if(words.length == 0){
|
||||
const message = document.createElement('div');
|
||||
message.className = 'mzta_dialog_message2';
|
||||
message.textContent = browser.i18n.getMessage("addtags_no_tags_received");
|
||||
content.appendChild(message);
|
||||
no_submit = true;
|
||||
}
|
||||
|
||||
let prefs_tags = await browser.storage.sync.get({add_tags_hide_exclusions: false});
|
||||
let add_tags_exclusions_list = await addTags_getExclusionList();
|
||||
|
||||
console.log(">>>>>>>>>>>>> add_tags_exclusions_list: " + JSON.stringify(add_tags_exclusions_list));
|
||||
|
||||
const words_final = words
|
||||
.filter(word => word !== '')
|
||||
.map(word => {
|
||||
const isExcluded = add_tags_exclusions_list.some(exclusion =>
|
||||
word.toLowerCase().includes(exclusion.toLowerCase())
|
||||
);
|
||||
|
||||
return {
|
||||
tag: word,
|
||||
excluded: isExcluded ? 1 : 0
|
||||
};
|
||||
});
|
||||
|
||||
console.log(">>>>>>>>>>>>> words_final: " + JSON.stringify(words_final));
|
||||
|
||||
// Create the form
|
||||
const form = document.createElement('form');
|
||||
|
||||
let tags_shown = 0;
|
||||
|
||||
words_final.forEach(word => {
|
||||
const label = document.createElement('label');
|
||||
label.style.display = 'block';
|
||||
const checkbox = document.createElement('input');
|
||||
checkbox.type = 'checkbox';
|
||||
checkbox.checked = true; // Checked by default
|
||||
checkbox.value = word.tag;
|
||||
// Add an image to the checkbox label
|
||||
const img = document.createElement('img');
|
||||
img.src = browser.runtime.getURL("/images/exclude-tag.svg");
|
||||
img.alt = browser.i18n.getMessage("addtags_exclude_tag");
|
||||
img.title = browser.i18n.getMessage("addtags_exclude_tag");
|
||||
img.className = 'exclude-tag-icon';
|
||||
img.addEventListener('click', () => {
|
||||
if (!label.classList.contains('tag_excluded')) {
|
||||
label.classList.add('tag_excluded');
|
||||
if (!add_tags_exclusions_list.includes(word.tag)) {
|
||||
add_tags_exclusions_list.push(word.tag);
|
||||
addTags_setExclusionList(add_tags_exclusions_list);
|
||||
}
|
||||
} else {
|
||||
label.classList.remove('tag_excluded');
|
||||
const idx = add_tags_exclusions_list.indexOf(word.tag);
|
||||
if (idx > -1) {
|
||||
add_tags_exclusions_list.splice(idx, 1);
|
||||
addTags_setExclusionList(add_tags_exclusions_list);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
label.appendChild(checkbox);
|
||||
label.appendChild(img);
|
||||
label.appendChild(document.createTextNode(` ${word.tag}`));
|
||||
if(!word.excluded || (word.excluded && !prefs_tags.add_tags_hide_exclusions)){
|
||||
tags_shown++;
|
||||
form.appendChild(label);
|
||||
}
|
||||
if(word.excluded){
|
||||
label.className = 'tag_excluded';
|
||||
checkbox.checked = false;
|
||||
}
|
||||
});
|
||||
|
||||
if((!no_submit) && (tags_shown == 0)){
|
||||
const message = document.createElement('div');
|
||||
message.className = 'mzta_dialog_message2';
|
||||
message.textContent = browser.i18n.getMessage("addtags_no_valid_tags");
|
||||
content.appendChild(message);
|
||||
no_submit = true;
|
||||
}
|
||||
|
||||
// Add a div for buttons
|
||||
const buttonsDiv = document.createElement('div');
|
||||
buttonsDiv.className = 'div_btns';
|
||||
|
||||
// Add the close button
|
||||
const closeButton = document.createElement('button');
|
||||
closeButton.type = 'button';
|
||||
closeButton.id = 'mzta_dialog_close';
|
||||
closeButton.textContent = 'Close';
|
||||
closeButton.className = 'mzta_dialog_btn mzta_dialog_btn_margin';
|
||||
closeButton.addEventListener('click', closeDialog);
|
||||
buttonsDiv.appendChild(closeButton);
|
||||
|
||||
if(!no_submit){
|
||||
// Add the submit button
|
||||
const submitButton = document.createElement('button');
|
||||
submitButton.type = 'button';
|
||||
submitButton.id = 'mzta_dialog_submit';
|
||||
submitButton.textContent = 'Submit';
|
||||
submitButton.className = 'mzta_dialog_btn';
|
||||
submitButton.addEventListener('click', () => {
|
||||
const selected = Array.from(form.querySelectorAll('input[type=checkbox]:checked')).map(cb => cb.value);
|
||||
onSubmit(selected);
|
||||
closeDialog();
|
||||
});
|
||||
buttonsDiv.appendChild(submitButton);
|
||||
}
|
||||
|
||||
content.appendChild(form);
|
||||
tags_dialog.appendChild(content);
|
||||
tags_dialog.appendChild(buttonsDiv);
|
||||
document.body.appendChild(tags_dialog);
|
||||
|
||||
function closeDialog() {
|
||||
tags_dialog.close();
|
||||
tags_dialog.addEventListener('close', () => {
|
||||
tags_dialog.remove();
|
||||
style.remove();
|
||||
});
|
||||
}
|
||||
|
||||
tags_dialog.showModal();
|
||||
|
||||
const iframeHeight = window.innerHeight;
|
||||
const iframeWidth = window.innerWidth;
|
||||
|
||||
const dialogRect = tags_dialog.getBoundingClientRect();
|
||||
|
||||
const top = Math.max(0, (iframeHeight - dialogRect.height) / 2);
|
||||
const left = Math.max(0, (iframeWidth - dialogRect.width) / 2);
|
||||
|
||||
tags_dialog.style.top = `${top}px`;
|
||||
tags_dialog.style.left = `${left}px`;
|
||||
tags_dialog.style.maxHeight = `${iframeHeight - 40}px`;
|
||||
|
||||
tags_dialog.style.transform = 'translate(0, 0)';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return createDialog(message.tags, (selected) => {
|
||||
console.log('>>>>>>>>>>>> Selected tags:', selected);
|
||||
browser.runtime.sendMessage({ command: "assign_tags", tags: selected, messageId: message.messageId });
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// do nothing
|
||||
return Promise.resolve(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -19,9 +19,10 @@
|
|||
// Some original methods are derived from https://github.com/ali-raheem/Aify/blob/cfadf52f576b7be3720b5b73af7c8d3129c054da/plugin/html/actions.js
|
||||
|
||||
import { getPrompts } from './mzta-prompts.js';
|
||||
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject } from './mzta-utils.js'
|
||||
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject, getTagsList, transformTagsLabels } from './mzta-utils.js'
|
||||
import { taLogger } from './mzta-logger.js';
|
||||
import { placeholdersUtils } from './mzta-placeholders.js';
|
||||
import { mzta_specialCommand_AddTags } from './special_commands/mzta-add-tags.js';
|
||||
|
||||
export class mzta_Menus {
|
||||
|
||||
|
|
@ -50,29 +51,30 @@ export class mzta_Menus {
|
|||
}
|
||||
|
||||
|
||||
async initialize() {
|
||||
async initialize(also_special = false) {
|
||||
this.allPrompts = [];
|
||||
this.rootMenu = [];
|
||||
this.shortcutMenu = [];
|
||||
this.menu_listeners = {};
|
||||
this.allPrompts = await getPrompts(true);
|
||||
this.allPrompts = await getPrompts(true,also_special);
|
||||
this.allPrompts.sort((a, b) => a.name.localeCompare(b.name));
|
||||
this.allPrompts.forEach((prompt) => {
|
||||
this.addAction(prompt)
|
||||
});
|
||||
}
|
||||
|
||||
async reload(){
|
||||
async reload(also_special = false) {
|
||||
await browser.menus.removeAll().catch(error => {
|
||||
console.error("[ThunderAI] ERROR removing the menus: ", error);
|
||||
});
|
||||
this.removeClickListener();
|
||||
this.loadMenus();
|
||||
this.loadMenus(also_special);
|
||||
}
|
||||
|
||||
addAction = (curr_prompt) => {
|
||||
|
||||
let curr_menu_entry = {id: curr_prompt.id, is_default: curr_prompt.is_default, name: curr_prompt.name};
|
||||
let curr_message = null;
|
||||
|
||||
const getMailBody = async (tabs) => {
|
||||
//const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
|
|
@ -92,7 +94,7 @@ export class mzta_Menus {
|
|||
//A selection is needed, but nothing is selected!
|
||||
//alert(browser.i18n.getMessage('prompt_selection_needed'));
|
||||
browser.tabs.sendMessage(tabs[0].id, { command: "sendAlert", curr_tab_type: tabs[0].type, message : browser.i18n.getMessage('prompt_selection_needed') });
|
||||
return;
|
||||
return {ok:'0'};
|
||||
}
|
||||
|
||||
let body_text = '';
|
||||
|
|
@ -114,6 +116,7 @@ export class mzta_Menus {
|
|||
}
|
||||
|
||||
let fullPrompt = '';
|
||||
let full_tags_list = await getTagsList();
|
||||
if(!placeholdersUtils.hasPlaceholder(curr_prompt.text)){
|
||||
// no placeholders, do as usual
|
||||
fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await this.getDefaultSignature():"") + " " + chatgpt_lang + " \"" + (selection_text=='' ? body_text : selection_text) + "\" ";
|
||||
|
|
@ -122,8 +125,21 @@ export class mzta_Menus {
|
|||
let currPHs = await placeholdersUtils.extractPlaceholders(curr_prompt.text);
|
||||
// console.log(">>>>>>>>>> currPHs: " + JSON.stringify(currPHs));
|
||||
let finalSubs = {};
|
||||
let curr_messages = await browser.mailTabs.getSelectedMessages();
|
||||
let curr_message = curr_messages.messages[0];
|
||||
let curr_messages = null;
|
||||
switch(tabs[0].type){
|
||||
case 'mail':
|
||||
curr_messages = await browser.mailTabs.getSelectedMessages();
|
||||
curr_message = curr_messages.messages[0];
|
||||
break;
|
||||
case 'messageDisplay':
|
||||
curr_messages = await messenger.messageDisplay.getDisplayedMessage(tabs[0].id);
|
||||
curr_message = curr_messages;
|
||||
break;
|
||||
case 'messageCompose':
|
||||
curr_messages = await browser.compose.getComposeDetails(tabs[0].id);
|
||||
curr_message = curr_messages;
|
||||
break;
|
||||
}
|
||||
for(let currPH of currPHs){
|
||||
switch(currPH.id){
|
||||
case 'mail_text_body':
|
||||
|
|
@ -151,6 +167,13 @@ export class mzta_Menus {
|
|||
case 'junk_score':
|
||||
finalSubs['junk_score'] = curr_message.junkScore;
|
||||
break;
|
||||
case 'mail_tags':
|
||||
let mail_tags_array = await transformTagsLabels(curr_message.tags, full_tags_list[1]);
|
||||
finalSubs['mail_tags'] = mail_tags_array.join(", ");
|
||||
break;
|
||||
case 'full_tags_list':
|
||||
finalSubs['full_tags_list'] = full_tags_list[0];
|
||||
break;
|
||||
default: // TODO Manage custom placeholders https://github.com/micz/ThunderAI/issues/156
|
||||
break;
|
||||
}
|
||||
|
|
@ -179,7 +202,46 @@ export class mzta_Menus {
|
|||
// const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
// add custom text if needed
|
||||
//browser.runtime.sendMessage({command: "chatgpt_open", prompt: fullPrompt, action: curr_prompt.action, tabId: tabs[0].id});
|
||||
this.openChatGPT(fullPrompt, curr_prompt.action, tabs[0].id, curr_prompt.name, curr_prompt.need_custom_text);
|
||||
if(curr_prompt.is_special == '1'){ // Special prompts
|
||||
switch(curr_prompt.id){
|
||||
case 'prompt_add_tags': // Add tags to the email
|
||||
let mail_tags = '';
|
||||
let prefs_at = await browser.storage.sync.get({add_tags_maxnum: 3, connection_type: ''});
|
||||
if((prefs_at.connection_type === '')||(prefs_at.connection_type === null)||(prefs_at.connection_type === undefined)||(prefs_at.connection_type === 'chatgpt_web')){
|
||||
console.error("[ThunderAI | AddTags] Invalid connection type: " + prefs_at.connection_type);
|
||||
return {ok:'0'};
|
||||
}
|
||||
let add_tags_maxnum = prefs_at.add_tags_maxnum;
|
||||
if(add_tags_maxnum > 0){
|
||||
fullPrompt += " " + browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + add_tags_maxnum +".";
|
||||
}
|
||||
this.logger.log("fullPrompt: " + fullPrompt);
|
||||
// TODO: use the current API, abort if using chatgpt web
|
||||
// COMMENTED TO DO TESTS
|
||||
mail_tags = "recipients, TEST, home, work, CAR, light";
|
||||
// let cmd_addTags = new mzta_specialCommand_AddTags(fullPrompt,prefs_at.connection_type,true);
|
||||
// await cmd_addTags.initWorker();
|
||||
// try{
|
||||
// mail_tags = await cmd_addTags.sendPrompt();
|
||||
// // console.log(">>>>>>>>>>> mail_tags: " + mail_tags);
|
||||
// }catch(err){
|
||||
// console.error("[ThunderAI] Error getting tags: ", err);
|
||||
// browser.tabs.sendMessage(tabs[0].id, { command: "sendAlert", curr_tab_type: tabs[0].type, message: "Error getting tags: " + err });
|
||||
// return {ok:'0'};
|
||||
// }
|
||||
this.logger.log("mail_tags: " + mail_tags);
|
||||
console.log(">>>>>>>>>>>> full_tags_list: " + JSON.stringify(full_tags_list));
|
||||
browser.tabs.sendMessage(tabs[0].id, {command: "getTags", tags: mail_tags, messageId: curr_message.id});
|
||||
return {ok:'1'};
|
||||
break;
|
||||
default:
|
||||
console.error("[ThunderAI] Unknown special prompt id: " + curr_prompt.id);
|
||||
break;
|
||||
}
|
||||
}else{ // Classic prompts for the API webchat
|
||||
this.openChatGPT(fullPrompt, curr_prompt.action, tabs[0].id, curr_prompt.name, curr_prompt.need_custom_text);
|
||||
return {ok:'1'};
|
||||
}
|
||||
};
|
||||
this.rootMenu.push(curr_menu_entry);
|
||||
};
|
||||
|
|
@ -205,8 +267,8 @@ export class mzta_Menus {
|
|||
this.shortcutMenu.push(curr_menu_entry);
|
||||
}
|
||||
|
||||
async loadMenus() {
|
||||
await this.initialize();
|
||||
async loadMenus(also_special = false) {
|
||||
await this.initialize(also_special);
|
||||
await this.addMenu(this.rootMenu);
|
||||
this.addClickListener();
|
||||
this.loadShortcutMenu();
|
||||
|
|
@ -296,7 +358,7 @@ export class mzta_Menus {
|
|||
if (action) {
|
||||
try {
|
||||
// Execute the action callback
|
||||
await action();
|
||||
return await action();
|
||||
} catch (error) {
|
||||
// Log any errors that occur during execution
|
||||
console.error(`Error executing action for menu item ${id}:`, error);
|
||||
|
|
@ -305,6 +367,7 @@ export class mzta_Menus {
|
|||
// Warn if no action is found for the provided ID
|
||||
console.warn(`No action found for menu item ID: ${id}`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
135
js/mzta-placeholders-autocomplete.js
Normal file
135
js/mzta-placeholders-autocomplete.js
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 Mic (m@micz.it)
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export function textareaAutocomplete(textarea, suggestions, type_value = -1) {
|
||||
const container = textarea.closest('.autocomplete-container');
|
||||
const autocompleteList = container.querySelector('.autocomplete-list');
|
||||
let activeIndex = -1;
|
||||
|
||||
textarea.addEventListener('input', () => {
|
||||
const cursorPosition = textarea.selectionStart;
|
||||
const text = textarea.value.substring(0, cursorPosition);
|
||||
const match = text.match(/{%[^\s]*$/);
|
||||
|
||||
if (match) {
|
||||
const lastWord = match[0];
|
||||
let type = type_value;
|
||||
if(type_value === -1) {
|
||||
const tr = textarea.parentNode.parentNode.parentNode;
|
||||
type = tr.querySelector('.type_output').value
|
||||
}
|
||||
// console.log(">>>>>>>>> type: " + type);
|
||||
// console.log(">>>>>>>>> suggestions: " + JSON.stringify(suggestions));
|
||||
// console.log(">>>>>>>>> lastWord: " + lastWord);
|
||||
const matches = suggestions.filter(s => s.command.startsWith(lastWord) && (String(s.type) == String(type) || String(s.type) == '0' )).map(s => s.command);
|
||||
// console.log(">>>>>>>>> matches: " + JSON.stringify(matches));
|
||||
showSuggestions(matches, autocompleteList);
|
||||
} else {
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
});
|
||||
|
||||
textarea.addEventListener('keydown', (e) => {
|
||||
if (autocompleteList.classList.contains('hidden')) {
|
||||
return;
|
||||
}
|
||||
const items = autocompleteList.querySelectorAll('li');
|
||||
if (items.length > 0) {
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
activeIndex = (activeIndex + 1) % items.length;
|
||||
updateActiveSuggestion(items, activeIndex);
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
activeIndex = (activeIndex - 1 + items.length) % items.length;
|
||||
updateActiveSuggestion(items, activeIndex);
|
||||
} else if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
if(activeIndex === -1) activeIndex = 0;
|
||||
if (activeIndex >= 0 && activeIndex < items.length) {
|
||||
insertAutocomplete(items[activeIndex].textContent, textarea);
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
} else if (e.key === 'Escape') {
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function showSuggestions(matches, autocompleteList) {
|
||||
autocompleteList.innerHTML = '';
|
||||
activeIndex = -1;
|
||||
if (matches.length === 0) {
|
||||
hideSuggestions(autocompleteList);
|
||||
return;
|
||||
}
|
||||
matches.forEach(match => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = match;
|
||||
li.addEventListener('click', () => {
|
||||
insertAutocomplete(match, textarea);
|
||||
hideSuggestions(autocompleteList);
|
||||
});
|
||||
autocompleteList.appendChild(li);
|
||||
});
|
||||
autocompleteList.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function hideSuggestions(autocompleteList) {
|
||||
autocompleteList.classList.add('hidden');
|
||||
activeIndex = -1;
|
||||
}
|
||||
|
||||
function updateActiveSuggestion(items, activeIndex) {
|
||||
items.forEach((item, index) => {
|
||||
item.classList.remove('active');
|
||||
if (index === activeIndex) {
|
||||
item.classList.add('active');
|
||||
item.scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insertAutocomplete(suggestion, textarea) {
|
||||
const cursorPosition = textarea.selectionStart;
|
||||
const textBefore = textarea.value.substring(0, cursorPosition);
|
||||
const textAfter = textarea.value.substring(cursorPosition);
|
||||
const match = textBefore.match(/{%[^\s]*$/);
|
||||
if (match) {
|
||||
const lastWord = match[0];
|
||||
const completion = suggestion.substring(lastWord.length);
|
||||
const newText = textBefore + completion + textAfter;
|
||||
textarea.value = newText;
|
||||
const newCursorPosition = cursorPosition + completion.length;
|
||||
textarea.setSelectionRange(newCursorPosition, newCursorPosition);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
// Check if the click was outside the textarea or suggestion list
|
||||
const isClickInsideTextarea = e.target.closest('.editor');
|
||||
const isClickInsideAutocompleteList = e.target.closest('.autocomplete-list');
|
||||
|
||||
if (!isClickInsideTextarea && !isClickInsideAutocompleteList) {
|
||||
const container = textarea.closest('.autocomplete-container');
|
||||
const autocompleteList = container.querySelector('.autocomplete-list');
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -96,6 +96,20 @@ const defaultPlaceholders = [
|
|||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'mail_tags',
|
||||
name: "__MSG_placeholder_mail_tags__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'full_tags_list',
|
||||
name: "__MSG_placeholder_full_tags_list__",
|
||||
default_value: "",
|
||||
type: 0,
|
||||
is_default: "1",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ const defaultPrompts = [
|
|||
need_custom_text: "0",
|
||||
define_response_lang: "1",
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_reply_advanced',
|
||||
|
|
@ -85,6 +86,7 @@ const defaultPrompts = [
|
|||
need_custom_text: "0",
|
||||
define_response_lang: "1",
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_rewrite_polite',
|
||||
|
|
@ -97,6 +99,7 @@ const defaultPrompts = [
|
|||
need_custom_text: "0",
|
||||
define_response_lang: "1",
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_rewrite_formal',
|
||||
|
|
@ -109,6 +112,7 @@ const defaultPrompts = [
|
|||
need_custom_text: "0",
|
||||
define_response_lang: "1",
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_classify',
|
||||
|
|
@ -121,6 +125,7 @@ const defaultPrompts = [
|
|||
need_custom_text: "0",
|
||||
define_response_lang: "1",
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_summarize_this',
|
||||
|
|
@ -133,6 +138,7 @@ const defaultPrompts = [
|
|||
need_custom_text: "0",
|
||||
define_response_lang: "1",
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_translate_this',
|
||||
|
|
@ -145,6 +151,7 @@ const defaultPrompts = [
|
|||
need_custom_text: "0",
|
||||
define_response_lang: "0",
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
{
|
||||
id: 'prompt_this',
|
||||
|
|
@ -157,16 +164,37 @@ const defaultPrompts = [
|
|||
need_custom_text: "0",
|
||||
define_response_lang: "0",
|
||||
is_default: "1",
|
||||
is_special: "0",
|
||||
},
|
||||
];
|
||||
|
||||
const specialPrompts = [
|
||||
{
|
||||
id: 'prompt_add_tags',
|
||||
name: "__MSG_prompt_add_tags__",
|
||||
text: "prompt_add_tags_full_text",
|
||||
type: "1",
|
||||
action: "0",
|
||||
need_selected: "0",
|
||||
need_signature: "0",
|
||||
need_custom_text: "0",
|
||||
define_response_lang: "0",
|
||||
is_default: "1",
|
||||
is_special: "1",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
export async function getPrompts(onlyEnabled = false){
|
||||
export async function getPrompts(onlyEnabled = false, includeSpecial = false){
|
||||
const _defaultPrompts = await getDefaultPrompts_withProps();
|
||||
// console.log('>>>>>>>>>>>> getPrompts _defaultPrompts: ' + JSON.stringify(_defaultPrompts));
|
||||
const customPrompts = await getCustomPrompts();
|
||||
// console.log('>>>>>>>>>>>> getPrompts customPrompts: ' + JSON.stringify(customPrompts));
|
||||
let output = _defaultPrompts.concat(customPrompts);
|
||||
const specialPrompts = await getSpecialPrompts();
|
||||
let output = specialPrompts.concat(_defaultPrompts).concat(customPrompts);
|
||||
if(!includeSpecial){
|
||||
output = output.filter(obj => obj.is_special != 1); // we do not want special prompts
|
||||
}
|
||||
if(onlyEnabled){
|
||||
output = output.filter(obj => obj.enabled != 0);
|
||||
}else{ // order only if we are not filtering, the filtering is for the menus and we are ordering there after i18n
|
||||
|
|
@ -270,7 +298,20 @@ export async function setDefaultPromptsProperties(prompts) {
|
|||
await browser.storage.local.set({_default_prompts_properties: default_prompts_properties});
|
||||
}
|
||||
|
||||
|
||||
export async function setCustomPrompts(prompts) {
|
||||
await browser.storage.local.set({_custom_prompt: prompts});
|
||||
}
|
||||
|
||||
export async function getSpecialPrompts(){
|
||||
let prefs = await browser.storage.local.get({_special_prompts: null});
|
||||
if(prefs._special_prompts === null){
|
||||
return specialPrompts;
|
||||
} else {
|
||||
return prefs._special_prompts;
|
||||
}
|
||||
}
|
||||
|
||||
export async function setSpecialPrompts(prompts) {
|
||||
// console.log(">>>>>>>>>>>> setSpecialPrompts prompts: " + JSON.stringify(prompts));
|
||||
await browser.storage.local.set({_special_prompts: prompts});
|
||||
}
|
||||
|
|
@ -176,6 +176,72 @@ export function generateCallID(length = 10) {
|
|||
return result;
|
||||
}
|
||||
|
||||
export async function getTagsList(){
|
||||
let messageTags = {};
|
||||
if(await isThunderbird128OrGreater()) {
|
||||
messageTags = await browser.messages.tags.list();
|
||||
} else {
|
||||
messageTags = await browser.messages.listTags();
|
||||
}
|
||||
const output = messageTags.map(tag => tag.tag).join(', ');
|
||||
|
||||
const output2 = messageTags.reduce((acc, messageTag) => {
|
||||
acc[messageTag.key] = {
|
||||
tag: messageTag.tag,
|
||||
color: messageTag.color,
|
||||
key: messageTag.key,
|
||||
ordinal: messageTag.ordinal,
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return [output, output2]; // Return the list of tags and the list of tags objects as an array
|
||||
}
|
||||
|
||||
export async function createTag(tag) {
|
||||
let prefs_tag = await browser.storage.sync.get({add_tags_first_uppercase: true});
|
||||
if(prefs_tag.add_tags_first_uppercase) tag = tag.toLowerCase().charAt(0).toUpperCase() + tag.toLowerCase().slice(1);
|
||||
try {
|
||||
if(await isThunderbird128OrGreater()) {
|
||||
return browser.messages.tags.create('ta-'+tag.toLowerCase(), tag, generateHexColorForTag());
|
||||
}else{
|
||||
return browser.messages.createTag('ta-'+tag.toLowerCase(), tag, generateHexColorForTag());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[ThunderAI] Error creating tag:', error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function assignTagsToMessage(messageId, tags) {
|
||||
tags = tags.map(tag => `ta-${tag.toLowerCase()}`);
|
||||
let msg_prop = await browser.messages.get(messageId);
|
||||
tags = tags.concat(msg_prop.tags || []);
|
||||
try {
|
||||
return browser.messages.update(messageId, {tags: tags});
|
||||
} catch (error) {
|
||||
console.error('[ThunderAI] Error assigning tag [messageId: ', messageId, ' - tag: ', tag, ']:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function generateHexColorForTag() {
|
||||
const red = Math.floor(Math.random() * 256);
|
||||
const green = Math.floor(Math.random() * 256);
|
||||
const blue = Math.floor(Math.random() * 256);
|
||||
|
||||
const hexColor = `#${red.toString(16).padStart(2, '0')}${green.toString(16).padStart(2, '0')}${blue.toString(16).padStart(2, '0')}`;
|
||||
|
||||
return hexColor;
|
||||
}
|
||||
|
||||
export async function transformTagsLabels(labels, tags_list) {
|
||||
console.log(">>>>>>>>> transformTagsLabels labels: " + labels);
|
||||
console.log(">>>>>>>>> transformTagsLabels tags_list: " + tags_list);
|
||||
let output = [];
|
||||
for(let label of labels) {
|
||||
output.push(tags_list[label].tag);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
// The following methods are a modified version derived from https://github.com/ali-raheem/Aify/blob/13ff87583bc520fb80f555ab90a90c5c9df797a7/plugin/content_scripts/compose.js
|
||||
|
|
|
|||
114
js/special_commands/mzta-add-tags.js
Normal file
114
js/special_commands/mzta-add-tags.js
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 Mic (m@micz.it)
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Call the API to get the tags
|
||||
|
||||
import { taLogger } from '../mzta-logger.js';
|
||||
|
||||
|
||||
export class mzta_specialCommand_AddTags {
|
||||
|
||||
prompt = "";
|
||||
worker = null;
|
||||
llm = "";
|
||||
full_message = "";
|
||||
logger = null;
|
||||
do_debug = false;
|
||||
|
||||
constructor(prompt, llm, do_debug = false) {
|
||||
this.prompt = prompt;
|
||||
this.llm = llm;
|
||||
this.logger = new taLogger('mzta_specialCommand_AddTags', do_debug);
|
||||
this.do_debug = do_debug;
|
||||
switch (this.llm) {
|
||||
case "chatgpt_api":
|
||||
this.worker = new Worker(new URL('../workers/model-worker-openai.js', import.meta.url), { type: 'module' });
|
||||
break;
|
||||
case "ollama_api":
|
||||
this.worker = new Worker(new URL('../workers/model-worker-ollama.js', import.meta.url), { type: 'module' });
|
||||
break;
|
||||
case "openai_comp_api":
|
||||
this.worker = new Worker(new URL('../workers/model-worker-openai_comp.js', import.meta.url), { type: 'module' });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async initWorker() {
|
||||
switch (this.llm) {
|
||||
case "chatgpt_api":
|
||||
let prefs_api = await browser.storage.sync.get({chatgpt_api_key: '', chatgpt_model: ''});
|
||||
this.worker.postMessage({ type: 'init', chatgpt_api_key: prefs_api.chatgpt_api_key, chatgpt_model: prefs_api.chatgpt_model, do_debug: this.do_debug, i18nStrings: ''});
|
||||
break;
|
||||
case "ollama_api": {
|
||||
let prefs_api = await browser.storage.sync.get({ollama_host: '', ollama_model: ''});
|
||||
this.worker.postMessage({ type: 'init', ollama_host: prefs_api.ollama_host, ollama_model: prefs_api.ollama_model, do_debug: this.do_debug, i18nStrings: ''});
|
||||
break;
|
||||
}
|
||||
case "openai_comp_api": {
|
||||
let prefs_api = await browser.storage.sync.get({openai_comp_host: '', openai_comp_model: '', openai_comp_api_key: '', openai_comp_use_v1: true, openai_comp_chat_name: '', do_debug: false});
|
||||
console.log(">>>>>>>>>>>> [ThunderAI] prefs_api: " + JSON.stringify(prefs_api));
|
||||
this.worker.postMessage({ type: 'init', openai_comp_host: prefs_api.openai_comp_host, openai_comp_model: prefs_api.openai_comp_model, openai_comp_api_key: prefs_api.openai_comp_api_key, openai_comp_use_v1: prefs_api.openai_comp_use_v1, do_debug: this.do_debug, i18nStrings: ''});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendPrompt(){
|
||||
return new Promise((resolve, reject) => {
|
||||
// Event listeners for worker messages
|
||||
this.worker.onmessage = (event) => {
|
||||
const { type, payload } = event.data;
|
||||
// console.log(`>>>>>>>>>>>> [Worker Message Received] type: ${type}`, payload);
|
||||
switch (type) {
|
||||
case 'messageSent':
|
||||
break;
|
||||
case 'newToken':
|
||||
this.full_message += payload.token;
|
||||
break;
|
||||
case 'tokensDone':
|
||||
console.log(">>>>>>>>>>>> [ThunderAI] tokensDone: " + this.full_message);
|
||||
resolve(this.full_message); // Resolve the promise with the full message
|
||||
break;
|
||||
case 'error':
|
||||
console.error('[ThunderAI] Error from API worker:', payload);
|
||||
reject(new Error(`[ThunderAI] Error from API worker: ${payload}`)); // Use a single error object
|
||||
break;
|
||||
default:
|
||||
console.error('[ThunderAI] Unknown event type from API worker:', type);
|
||||
}
|
||||
};
|
||||
|
||||
this.worker.onerror = (error) => {
|
||||
console.error('[ThunderAI] Worker Error Details:');
|
||||
console.error('Message:', error.message);
|
||||
console.error('Filename:', error.filename);
|
||||
console.error('Line Number:', error.lineno);
|
||||
console.error('Column Number:', error.colno);
|
||||
console.error('Event:', error);
|
||||
reject(error);
|
||||
};
|
||||
|
||||
try {
|
||||
// console.log('[ThunderAI] Sending prompt to worker:', this.prompt);
|
||||
this.worker.postMessage({ type: 'chatMessage', message: this.prompt });
|
||||
} catch (error) {
|
||||
console.error('[ThunderAI] Failed to send message to worker:', error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -20,8 +20,8 @@
|
|||
* The original code has been released under the Apache License, Version 2.0.
|
||||
*/
|
||||
|
||||
import { Ollama } from '../js/api/ollama.js';
|
||||
import { taLogger } from '../js/mzta-logger.js';
|
||||
import { Ollama } from '../api/ollama.js';
|
||||
import { taLogger } from '../mzta-logger.js';
|
||||
|
||||
let ollama_host = null;
|
||||
let ollama_model = '';
|
||||
|
|
@ -20,8 +20,8 @@
|
|||
* The original code has been released under the Apache License, Version 2.0.
|
||||
*/
|
||||
|
||||
import { OpenAI } from '../js/api/openai.js';
|
||||
import { taLogger } from '../js/mzta-logger.js';
|
||||
import { OpenAI } from '../api/openai.js';
|
||||
import { taLogger } from '../mzta-logger.js';
|
||||
|
||||
let chatgpt_api_key = null;
|
||||
let chatgpt_model = '';
|
||||
|
|
@ -20,8 +20,8 @@
|
|||
* The original code has been released under the Apache License, Version 2.0.
|
||||
*/
|
||||
|
||||
import { OpenAIComp } from '../js/api/openai_comp.js';
|
||||
import { taLogger } from '../js/mzta-logger.js';
|
||||
import { OpenAIComp } from '../api/openai_comp.js';
|
||||
import { taLogger } from '../mzta-logger.js';
|
||||
|
||||
let openai_comp_host = null;
|
||||
let openai_comp_model = '';
|
||||
|
|
@ -31,6 +31,9 @@
|
|||
"activeTab",
|
||||
"accountsRead",
|
||||
"downloads",
|
||||
"messagesTagsList",
|
||||
"messagesTags",
|
||||
"messagesUpdate",
|
||||
"https://*.chatgpt.com/*"
|
||||
],
|
||||
"background": {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { mzta_script } from './js/mzta-chatgpt.js';
|
|||
import { prefs_default } from './options/mzta-options-default.js';
|
||||
import { mzta_Menus } from './js/mzta-menus.js';
|
||||
import { taLogger } from './js/mzta-logger.js';
|
||||
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString } from './js/mzta-utils.js';
|
||||
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage } from './js/mzta-utils.js';
|
||||
|
||||
await migrateCustomPromptsStorage();
|
||||
await migrateDefaultPromptsPropStorage();
|
||||
|
|
@ -28,8 +28,8 @@ await migrateDefaultPromptsPropStorage();
|
|||
var original_html = '';
|
||||
var modified_html = '';
|
||||
|
||||
let prefs_debug = await browser.storage.sync.get({do_debug: false});
|
||||
let taLog = new taLogger("mzta-background",prefs_debug.do_debug);
|
||||
let prefs_init = await browser.storage.sync.get({do_debug: false, add_tags: false, connection_type: 'chatgpt_web'});
|
||||
let taLog = new taLogger("mzta-background",prefs_init.do_debug);
|
||||
|
||||
browser.composeScripts.register({
|
||||
js: [{file: "/js/mzta-compose-script.js"}]
|
||||
|
|
@ -210,14 +210,16 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
return _reloadBody(message.tabId);
|
||||
break;
|
||||
case 'reload_menus':
|
||||
menus.reload();
|
||||
taLog.log("Reloading menus");
|
||||
return Promise.resolve(true);
|
||||
async function _reload_menus() {
|
||||
menus.reload(prefs_init.add_tags && (prefs_init.connection_type !== "chatgpt_web"));
|
||||
taLog.log("Reloading menus");
|
||||
return true;
|
||||
}
|
||||
return _reload_menus();
|
||||
break;
|
||||
case 'shortcut_do_prompt':
|
||||
taLog.log("Executing shortcut, promptId: " + message.promptId);
|
||||
menus.executeMenuAction(message.promptId);
|
||||
return Promise.resolve(true);
|
||||
return menus.executeMenuAction(message.promptId);
|
||||
break;
|
||||
case 'popup_menu_ready':
|
||||
async function _popup_menu_ready() {
|
||||
|
|
@ -230,6 +232,26 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
}
|
||||
return _popup_menu_ready();
|
||||
break;
|
||||
case 'assign_tags':
|
||||
async function _assign_tags() {
|
||||
let all_tags_list = await getTagsList();
|
||||
all_tags_list = all_tags_list[1];
|
||||
console.log(">>>>>>>>>>>>>>> all_tags_list: " + JSON.stringify(all_tags_list));
|
||||
taLog.log("assign_tags data: " + JSON.stringify(message));
|
||||
let new_tags = [];
|
||||
for (const tag of message.tags) {
|
||||
console.log(">>>>>>>>>>>>>>> tag: " + tag);
|
||||
if (!all_tags_list.hasOwnProperty("ta-" + tag.toLowerCase())) {
|
||||
taLog.log("Creating tag: " + tag);
|
||||
await createTag(tag);
|
||||
}
|
||||
new_tags.push(tag);
|
||||
}
|
||||
await assignTagsToMessage(message.messageId, new_tags);
|
||||
taLog.log("Assigned tags: " + JSON.stringify(new_tags));
|
||||
}
|
||||
return _assign_tags();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -384,7 +406,7 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
|
||||
let rand_call_id3 = '_ollama_' + generateCallID();
|
||||
|
||||
const listener3 = async (message, sender, sendResponse) => {
|
||||
const listener3 = (message, sender, sendResponse) => {
|
||||
|
||||
function handleOllamaApi(createdTab3) {
|
||||
taLog.log("Ollama API window ready.");
|
||||
|
|
@ -440,7 +462,7 @@ async function openChatGPT(promptText, action, curr_tabId, prompt_name = '', do_
|
|||
let rand_call_id4 = '_openai_comp_api_' + generateCallID();
|
||||
|
||||
|
||||
const listener4 = async (message, sender, sendResponse) => {
|
||||
const listener4 = (message, sender, sendResponse) => {
|
||||
|
||||
function handleOpenAICompApi(createdTab) {
|
||||
let mailMessageId4 = -1;
|
||||
|
|
@ -497,6 +519,22 @@ function checkScreenDimensions(prefs){
|
|||
return prefs;
|
||||
}
|
||||
|
||||
// Register the listener for storage changes
|
||||
browser.storage.onChanged.addListener((changes, areaName) => {
|
||||
// Check if the change happened in the 'sync' storage area
|
||||
if (areaName === 'sync') {
|
||||
// Check if 'add_tags' has changed
|
||||
if (changes.add_tags) {
|
||||
menus.reload(changes.add_tags.newValue && (prefs_init.connection_type !== "chatgpt_web"));
|
||||
}
|
||||
|
||||
// Check if 'connection_type' has changed
|
||||
if (changes.connection_type) {
|
||||
menus.reload(prefs_init.add_tags && (changes.connection_type.newValue !== "chatgpt_web"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Menus handling
|
||||
const menus = new mzta_Menus(openChatGPT, prefs_debug.do_debug);
|
||||
menus.loadMenus();
|
||||
const menus = new mzta_Menus(openChatGPT, prefs_init.do_debug);
|
||||
menus.loadMenus(prefs_init.add_tags && (prefs_init.connection_type !== "chatgpt_web"));
|
||||
|
|
@ -37,4 +37,8 @@ export const prefs_default = {
|
|||
dynamic_menu_order_alphabet: true,
|
||||
placeholders_use_default_value: false,
|
||||
max_prompt_length: 30000, // max string length for prompt
|
||||
add_tags: false,
|
||||
add_tags_maxnum: 3,
|
||||
add_tags_hide_exclusions: false,
|
||||
add_tags_first_uppercase: true,
|
||||
}
|
||||
|
|
@ -166,10 +166,31 @@ input.option-input[type="text"]{
|
|||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#mzta_top_msg div{
|
||||
color: white;
|
||||
font-style: italic;
|
||||
background-color: rgb(3, 0, 180);
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#mzta_top_msg div a{
|
||||
background-color: white;
|
||||
padding:0px 3px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.conntype_chatgpt_web_option{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn_small{
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: rgb(35, 34, 43);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
<div id="miczRelNotes"><a href="mzta-release-notes.html">__MSG_prefs_OptionText_release_notes__</a></div>
|
||||
<div id="miczStatusPage" class="conntype_chatgpt_web"><a href="https://micz.it/thunderbird-addon-thunderai/status/">__MSG_prefs_status_page__</a></div>
|
||||
<table id="miczPrefs">
|
||||
<tr id="mzta_top_msg">
|
||||
<td colspan="2"><div>__MSG_prefs_SurveyLinkText__<br><a href="https://forms.gle/1qK2wcbuhaRzhwyt9">__MSG_prefs_SurveyLinkText2__</a></div></td>
|
||||
</tr>
|
||||
<tr id="owl_warning">
|
||||
<td colspan="2"><div>__MSG_prefs_OptionText_owl_warning__ <a href="https://micz.it/thunderbird-addon-thunderai/owl/">__MSG_customPrompts_managePrompts_help__</a></div></td>
|
||||
</tr>
|
||||
|
|
@ -266,6 +269,16 @@
|
|||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="add_tags_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags__</span>
|
||||
<br><button id="btnManageTagsInfo" class="btn_small">__MSG_prefs_OptionText_btnManageTagsInfo__</button></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="add_tags" name="add_tags" class="option-input" />
|
||||
__MSG_prefs_OptionText_add_tags_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:20em"><label>
|
||||
<span>__MSG_Debug__</span>
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ async function restoreOptions() {
|
|||
|
||||
function showConnectionOptions() {
|
||||
disable_MaxPromptLength();
|
||||
disable_AddTags();
|
||||
let chatgpt_web_display = 'table-row';
|
||||
let chatgpt_api_display = 'none';
|
||||
let ollama_api_display = 'none';
|
||||
|
|
@ -212,6 +213,14 @@ function disable_MaxPromptLength(){
|
|||
maxPromptLength_tr.style.display = (maxPromptLength.disabled) ? 'none' : 'table-row';
|
||||
}
|
||||
|
||||
function disable_AddTags(){
|
||||
let add_tags = document.getElementById('add_tags');
|
||||
let add_tags_tr_elements = document.querySelectorAll('.add_tags_tr');
|
||||
add_tags_tr_elements.forEach(add_tags_tr => {
|
||||
add_tags_tr.style.display = (add_tags.disabled) ? 'none' : 'table-row';
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
await restoreOptions();
|
||||
|
||||
|
|
@ -233,16 +242,36 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
el.dispatchEvent(new Event('change'), { bubbles: true });
|
||||
});
|
||||
});
|
||||
|
||||
let addtags_el = document.getElementById('add_tags');
|
||||
let addtags_info_btn = document.getElementById('btnManageTagsInfo');
|
||||
addtags_el.addEventListener('click', (event) => {
|
||||
addtags_info_btn.disabled = event.target.checked ? '' : 'disabled';
|
||||
});
|
||||
addtags_info_btn.disabled = addtags_el.checked ? '' : 'disabled';
|
||||
|
||||
document.getElementById('btnManagePrompts').addEventListener('click', () => {
|
||||
// check if the tab is already there
|
||||
browser.tabs.query({url: browser.runtime.getURL('../customprompts/mzta-custom-prompts.html')}).then((tabs) => {
|
||||
browser.tabs.query({url: browser.runtime.getURL('../pages/customprompts/mzta-custom-prompts.html')}).then((tabs) => {
|
||||
if (tabs.length > 0) {
|
||||
// if the tab is already there, focus it
|
||||
browser.tabs.update(tabs[0].id, {active: true});
|
||||
} else {
|
||||
// if the tab is not there, create it
|
||||
browser.tabs.create({url: browser.runtime.getURL('../customprompts/mzta-custom-prompts.html')});
|
||||
browser.tabs.create({url: browser.runtime.getURL('../pages/customprompts/mzta-custom-prompts.html')});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
document.getElementById('btnManageTagsInfo').addEventListener('click', () => {
|
||||
// check if the tab is already there
|
||||
browser.tabs.query({url: browser.runtime.getURL('../pages/addtags/mzta-add-tags.html')}).then((tabs) => {
|
||||
if (tabs.length > 0) {
|
||||
// if the tab is already there, focus it
|
||||
browser.tabs.update(tabs[0].id, {active: true});
|
||||
} else {
|
||||
// if the tab is not there, create it
|
||||
browser.tabs.create({url: browser.runtime.getURL('../pages/addtags/mzta-add-tags.html')});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
@ -401,6 +430,7 @@ select_openai_comp_model.addEventListener("change", warn_OpenAIComp_HostEmpty);
|
|||
warn_Ollama_HostEmpty();
|
||||
warn_OpenAIComp_HostEmpty();
|
||||
disable_MaxPromptLength();
|
||||
disable_AddTags();
|
||||
|
||||
const passwordField_chatgpt_api_key = document.getElementById('chatgpt_api_key');
|
||||
const toggleIcon_chatgpt_api_key = document.getElementById('toggle_chatgpt_api_key');
|
||||
|
|
|
|||
|
|
@ -10,6 +10,13 @@
|
|||
<h2>Version 2.4.0 - ??/??/2024</h2>
|
||||
<ul>
|
||||
<li>Default prompts text has been translated [<a href="https://github.com/micz/ThunderAI/issues/185">#185</a>].</li>
|
||||
<li>Data placeholder for the full available tags list added [<a href="https://github.com/micz/ThunderAI/issues/197">#197</a>].</li>
|
||||
<li>Data placeholder for the single mail tags list added [<a href="https://github.com/micz/ThunderAI/issues/198">#198</a>].</li>
|
||||
<li>User <a href="https://forms.gle/1qK2wcbuhaRzhwyt9">survey link</a> added [<a href="https://github.com/micz/ThunderAI/issues/202">#202</a>].</li>
|
||||
<li>Polish (pl) translation added, thanks to <a href="https://github.com/neexpl">neexpl</a>.</li>
|
||||
<li>The Custom Prompts tab has now an icon.</li>
|
||||
<li>The red border in the Custom Prompts configuration page that highlights a needed prompt configuration that is not selected is now removed when the corresponding placeholder is removed [<a href="https://github.com/micz/ThunderAI/issues/201">#201</a>].</li>
|
||||
<li>Minor bugs fixed.</li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
<h2>Version 2.3.4 - 06/12/2024</h2>
|
||||
|
|
|
|||
132
pages/addtags/mzta-add-tags.css
Normal file
132
pages/addtags/mzta-add-tags.css
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
#addtags_prompt_container{
|
||||
width: 90%;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
#addtags_prompt_text{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.infoline{
|
||||
font-size: 0.8em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#addtags_excl_list_container{
|
||||
width: 90%;
|
||||
margin: 40px auto;
|
||||
}
|
||||
|
||||
#addtags_excl_list{
|
||||
width: 30em;
|
||||
}
|
||||
|
||||
.btn_div{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#addtags_info_limit_num{
|
||||
display: none;
|
||||
}
|
||||
|
||||
table#miczPrefs {
|
||||
padding: 10px;
|
||||
border-spacing: 0px;
|
||||
width: 90%;
|
||||
margin: 0px auto 40px auto;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.addtags_table_title{
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.section_title{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table#miczPrefs td{
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
vertical-align: top;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
table#miczPrefs tr:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
table#miczPrefs tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.autocomplete-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.autocomplete-list {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
z-index: 1000;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.autocomplete-list li {
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.autocomplete-list li:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.autocomplete-list li.active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.unsaved{
|
||||
color: red;
|
||||
}
|
||||
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #1C1B22;
|
||||
color: rgb(251, 251, 254);
|
||||
}
|
||||
|
||||
a:link { color: #409EFF; }
|
||||
a:visited { color: #409EFF; }
|
||||
a:hover { color: #66B1FF; }
|
||||
a:active { color: #66B1FF; }
|
||||
a:active { color: #66B1FF; }
|
||||
|
||||
.autocomplete-list {
|
||||
background-color: #2E2F36;
|
||||
border: 1px solid #2E2F36;
|
||||
}
|
||||
|
||||
.autocomplete-list li:hover {
|
||||
background-color: #4c4e58;
|
||||
}
|
||||
|
||||
.autocomplete-list li.active {
|
||||
background-color: #4c4e58;
|
||||
}
|
||||
}
|
||||
66
pages/addtags/mzta-add-tags.html
Normal file
66
pages/addtags/mzta-add-tags.html
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ThunderAI - __MSG_AddTags_PageTitle__</title>
|
||||
<link rel="stylesheet" href="mzta-add-tags.css">
|
||||
<link rel="icon" href="../../images/icon-16px.png">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1 class="page_title">__MSG_AddTags_PageTitle__</h1>
|
||||
<p>__MSG_AddTags_info_default__</p>
|
||||
</div>
|
||||
<div class="addtags_table_title section_title">__MSG_AddTags_prompt_prefs_title__</div>
|
||||
<table id="miczPrefs">
|
||||
<tr class="add_tags_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags_maxnum__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="number" id="add_tags_maxnum" name="add_tags_maxnum" class="option-input" />
|
||||
<br>__MSG_prefs_OptionText_add_tags_maxnum_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="add_tags_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags_hide_exclusions__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="add_tags_hide_exclusions" name="add_tags_hide_exclusions" class="option-input" />
|
||||
__MSG_prefs_OptionText_add_tags_hide_exclusions_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="add_tags_tr">
|
||||
<td><span>__MSG_prefs_OptionText_add_tags_first_uppercase__</span></td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox" id="add_tags_first_uppercase" name="add_tags_first_uppercase" class="option-input" />
|
||||
__MSG_prefs_OptionText_add_tags_first_uppercase_Info__
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="addtags_prompt_container">
|
||||
<span class="section_title">__MSG_AddTags_prompt_text_title__</span><span id="addtags_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<br><span class="infoline">__MSG_prefs_OptionText_btnManagePrompts_infoline__ <a href="https://micz.it/thunderbird-addon-thunderai/data-placeholders/">__MSG_customPrompts_managePrompts_help__</a>
|
||||
<br><b>__MSG_prefs_OptionText_btnManagePrompts_infoline2__</b></span>
|
||||
<br>
|
||||
<div class="autocomplete-container">
|
||||
<textarea id="addtags_prompt_text" rows="15"></textarea>
|
||||
<ul class="autocomplete-list hidden"></ul>
|
||||
</div>
|
||||
<div id="addtags_info_limit_num"></div>
|
||||
<div class="btn_div"><button id="btn_reset_prompt" disabled>__MSG_reset_default__</button><button id="btn_save_prompt" disabled>__MSG_save__</button></div>
|
||||
</div>
|
||||
<div id="addtags_excl_list_container">
|
||||
<span class="section_title">__MSG_AddTags_excl_list_title__</span><span id="excl_list_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>
|
||||
<br><span class="infoline">__MSG_AddTags_excl_list_infoline__
|
||||
<br>__MSG_AddTags_excl_list_infoline2__</span>
|
||||
<br><textarea id="addtags_excl_list" rows="15"></textarea>
|
||||
<div class="btn_div"><button id="btn_save_excl_list" disabled>__MSG_save__</button></div>
|
||||
</div>
|
||||
<script src="mzta-add-tags.js" type="module"></script>
|
||||
<script src="../../js/mzta-i18n.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
192
pages/addtags/mzta-add-tags.js
Normal file
192
pages/addtags/mzta-add-tags.js
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
||||
* Copyright (C) 2024 Mic (m@micz.it)
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { prefs_default } from '../../options/mzta-options-default.js';
|
||||
import { taLogger } from '../../js/mzta-logger.js';
|
||||
import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js";
|
||||
import { getPlaceholders } from "../../js/mzta-placeholders.js";
|
||||
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
|
||||
import { addTags_getExclusionList, addTags_setExclusionList } from "../../js/mzta-addatags-exclusion-list.js";
|
||||
|
||||
|
||||
let autocompleteSuggestions = [];
|
||||
let taLog = new taLogger("mzta-addtags-page",true);
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
i18n.updateDocument();
|
||||
await restoreOptions();
|
||||
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
element.addEventListener("change", saveOptions);
|
||||
});
|
||||
|
||||
let addtags_textarea = document.getElementById('addtags_prompt_text');
|
||||
let addtags_save_btn = document.getElementById('btn_save_prompt');
|
||||
let addtags_reset_btn = document.getElementById('btn_reset_prompt');
|
||||
|
||||
let specialPrompts = await getSpecialPrompts();
|
||||
let addtags_prompt = specialPrompts.find(prompt => prompt.id === 'prompt_add_tags');
|
||||
|
||||
addtags_textarea.addEventListener('input', (event) => {
|
||||
addtags_reset_btn.disabled = (event.target.value === browser.i18n.getMessage('prompt_add_tags_full_text'));
|
||||
addtags_save_btn.disabled = (event.target.value === addtags_prompt.text);
|
||||
if(addtags_save_btn.disabled){
|
||||
document.getElementById('addtags_prompt_unsaved').classList.add('hidden');
|
||||
} else {
|
||||
document.getElementById('addtags_prompt_unsaved').classList.remove('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
addtags_reset_btn.addEventListener('click', () => {
|
||||
addtags_textarea.value = browser.i18n.getMessage('prompt_add_tags_full_text');
|
||||
addtags_reset_btn.disabled = true;
|
||||
let event = new Event('input', { bubbles: true, cancelable: true });
|
||||
addtags_textarea.dispatchEvent(event);
|
||||
});
|
||||
|
||||
addtags_save_btn.addEventListener('click', () => {
|
||||
specialPrompts.find(prompt => prompt.id === 'prompt_add_tags').text = addtags_textarea.value;
|
||||
setSpecialPrompts(specialPrompts);
|
||||
addtags_save_btn.disabled = true;
|
||||
document.getElementById('addtags_prompt_unsaved').classList.add('hidden');
|
||||
browser.runtime.sendMessage({command: "reload_menus"});
|
||||
});
|
||||
|
||||
if(addtags_prompt.text === 'prompt_add_tags_full_text'){
|
||||
addtags_prompt.text = browser.i18n.getMessage(addtags_prompt.text);
|
||||
}
|
||||
addtags_textarea.value = addtags_prompt.text;
|
||||
addtags_reset_btn.disabled = (addtags_textarea.value === browser.i18n.getMessage('prompt_add_tags_full_text'));
|
||||
|
||||
document.getElementById('add_tags_maxnum').addEventListener('change', updateMaxTagsNumDesc);
|
||||
|
||||
updateMaxTagsNumDesc();
|
||||
|
||||
autocompleteSuggestions = (await getPlaceholders(true)).filter(p => !(p.id === 'selected_text' || p.id === 'additional_text')).map(p => ({command: '{%'+p.id+'%}', type: p.type}));
|
||||
textareaAutocomplete(addtags_textarea, autocompleteSuggestions, 1); // type_value = 1, only when reading an email
|
||||
|
||||
let excl_list_textarea = document.getElementById('addtags_excl_list');
|
||||
let excl_list_save_btn = document.getElementById('btn_save_excl_list');
|
||||
|
||||
let excl_list_value = await addTags_getExclusionList();
|
||||
let excl_list_string = excl_list_value.join('\n');
|
||||
|
||||
excl_list_textarea.value = excl_list_string;
|
||||
|
||||
excl_list_textarea.addEventListener('input', (event) => {
|
||||
excl_list_save_btn.disabled = (event.target.value === excl_list_string);
|
||||
if(excl_list_save_btn.disabled){
|
||||
document.getElementById('excl_list_unsaved').classList.add('hidden');
|
||||
} else {
|
||||
document.getElementById('excl_list_unsaved').classList.remove('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
excl_list_save_btn.addEventListener('click', () => {
|
||||
let excl_array_new = excl_list_textarea.value.split(/[\n,]+/);
|
||||
excl_array_new = Array.from(new Set(excl_array_new.map(item => item.trim().toLowerCase()))).sort();
|
||||
addTags_setExclusionList(excl_array_new);
|
||||
excl_list_save_btn.disabled = true;
|
||||
excl_list_textarea.value = excl_array_new.join('\n');
|
||||
document.getElementById('excl_list_unsaved').classList.add('hidden');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
async function updateMaxTagsNumDesc(){
|
||||
let prefs_maxt = await browser.storage.sync.get({add_tags_maxnum: 3});
|
||||
let el_tag_limit = document.getElementById('addtags_info_limit_num');
|
||||
if(prefs_maxt.add_tags_maxnum > 0){
|
||||
el_tag_limit.textContent = browser.i18n.getMessage("addtags_info_limit_num") + " \"" + browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + prefs_maxt.add_tags_maxnum +"\".";
|
||||
el_tag_limit.style.display = 'block';
|
||||
}else{
|
||||
el_tag_limit.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Methods to manage options, derived from: /options/mzta-options.js
|
||||
|
||||
function saveOptions(e) {
|
||||
e.preventDefault();
|
||||
let options = {};
|
||||
let element = e.target;
|
||||
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
options[element.id] = element.checked;
|
||||
break;
|
||||
case 'number':
|
||||
options[element.id] = element.valueAsNumber;
|
||||
break;
|
||||
case 'text':
|
||||
case 'password':
|
||||
options[element.id] = element.value.trim();
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
options[element.id] = element.value;
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
}
|
||||
|
||||
browser.storage.sync.set(options);
|
||||
}
|
||||
|
||||
async function restoreOptions() {
|
||||
function setCurrentChoice(result) {
|
||||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
taLog.log("Options restoring " + element.id + " = " + (element.id=="chatgpt_api_key" || element.id=="openai_comp_api_key" ? "****************" : result[element.id]));
|
||||
switch (element.type) {
|
||||
case 'checkbox':
|
||||
element.checked = result[element.id] || false;
|
||||
break;
|
||||
case 'number':
|
||||
let default_number_value = 0;
|
||||
if(element.id == 'chatgpt_win_height') default_number_value = prefs_default.chatgpt_win_height;
|
||||
if(element.id == 'chatgpt_win_width') default_number_value = prefs_default.chatgpt_win_width;
|
||||
element.value = result[element.id] ?? default_number_value;
|
||||
break;
|
||||
case 'text':
|
||||
case 'password':
|
||||
let default_text_value = '';
|
||||
if(element.id == 'default_chatgpt_lang') default_text_value = prefs_default.default_chatgpt_lang;
|
||||
element.value = result[element.id] || default_text_value;
|
||||
break;
|
||||
default:
|
||||
if (element.tagName === 'SELECT') {
|
||||
let default_select_value = '';
|
||||
if(element.id == 'reply_type') default_select_value = 'reply_all';
|
||||
if(element.id == 'connection_type') default_select_value = 'chatgpt_web';
|
||||
element.value = result[element.id] || default_select_value;
|
||||
if (element.value === '') {
|
||||
element.selectedIndex = -1;
|
||||
}
|
||||
}else{
|
||||
console.error("[ThunderAI] Unhandled input type:", element.type);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let getting = await browser.storage.sync.get(prefs_default);
|
||||
setCurrentChoice(getting);
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<title>ThunderAI - __MSG_customPrompts_managePrompts__</title>
|
||||
<link rel="stylesheet" href="mzta-custom-prompts.css">
|
||||
<link rel="icon" href="../../images/icon-16px.png">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
|
@ -98,6 +99,6 @@
|
|||
<div class="storage_space">__MSG_StorageSpace__: <span id="storage_space"></span></div>
|
||||
<script src="list.js"></script>
|
||||
<script src="mzta-custom-prompts.js" type="module"></script>
|
||||
<script src="../js/mzta-i18n.js"></script>
|
||||
<script src="../../js/mzta-i18n.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -16,10 +16,11 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { getPrompts, setDefaultPromptsProperties, setCustomPrompts, preparePromptsForExport, preparePromptsForImport } from "../js/mzta-prompts.js";
|
||||
import { isThunderbird128OrGreater, getCustomPromptsUsedSpace, sanitizeHtml } from "../js/mzta-utils.js";
|
||||
import { taLogger } from "../js/mzta-logger.js";
|
||||
import { getPlaceholders } from "../js/mzta-placeholders.js";
|
||||
import { getPrompts, setDefaultPromptsProperties, setCustomPrompts, preparePromptsForExport, preparePromptsForImport } from "../../js/mzta-prompts.js";
|
||||
import { isThunderbird128OrGreater, getCustomPromptsUsedSpace, sanitizeHtml } from "../../js/mzta-utils.js";
|
||||
import { taLogger } from "../../js/mzta-logger.js";
|
||||
import { getPlaceholders } from "../../js/mzta-placeholders.js";
|
||||
import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js";
|
||||
|
||||
var promptsList = null;
|
||||
var somethingChanged = false;
|
||||
|
|
@ -118,7 +119,15 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
|
||||
// console.log('>>>>>>>>>>> suggestions: ' + JSON.stringify(suggestions));
|
||||
|
||||
textareas.forEach(textarea => textareaAutocomplete(textarea, autocompleteSuggestions));
|
||||
textareas.forEach(textarea => {
|
||||
textareaAutocomplete(textarea, autocompleteSuggestions);
|
||||
textareas.forEach(textarea => {
|
||||
textarea.addEventListener('input', (e) => {
|
||||
checkPromptsConfigForPlaceholders(e.target);
|
||||
});
|
||||
textareaAutocomplete(textarea, autocompleteSuggestions);
|
||||
});
|
||||
});
|
||||
|
||||
// document.addEventListener('click', (e) => {
|
||||
// // Check if the click was outside the textarea or suggestion list
|
||||
|
|
@ -680,141 +689,29 @@ if(await isThunderbird128OrGreater()){
|
|||
});
|
||||
}
|
||||
|
||||
function textareaAutocomplete(textarea, suggestions) {
|
||||
const container = textarea.closest('.autocomplete-container');
|
||||
const autocompleteList = container.querySelector('.autocomplete-list');
|
||||
let activeIndex = -1;
|
||||
|
||||
textarea.addEventListener('input', () => {
|
||||
const cursorPosition = textarea.selectionStart;
|
||||
const text = textarea.value.substring(0, cursorPosition);
|
||||
const match = text.match(/{%[^\s]*$/);
|
||||
|
||||
checkPromptsConfigForPlaceholders(textarea);
|
||||
|
||||
if (match) {
|
||||
const lastWord = match[0];
|
||||
const tr = textarea.parentNode.parentNode.parentNode;
|
||||
let type = tr.querySelector('.type_output').value
|
||||
// console.log(">>>>>>>>> type: " + type);
|
||||
// console.log(">>>>>>>>> suggestions: " + JSON.stringify(suggestions));
|
||||
// console.log(">>>>>>>>> lastWord: " + lastWord);
|
||||
const matches = suggestions.filter(s => s.command.startsWith(lastWord) && (String(s.type) == String(type) || String(s.type) == '0' )).map(s => s.command);
|
||||
// console.log(">>>>>>>>> matches: " + JSON.stringify(matches));
|
||||
showSuggestions(matches, autocompleteList);
|
||||
} else {
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
});
|
||||
|
||||
textarea.addEventListener('keydown', (e) => {
|
||||
if (autocompleteList.classList.contains('hidden')) {
|
||||
return;
|
||||
}
|
||||
const items = autocompleteList.querySelectorAll('li');
|
||||
if (items.length > 0) {
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
activeIndex = (activeIndex + 1) % items.length;
|
||||
updateActiveSuggestion(items, activeIndex);
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
activeIndex = (activeIndex - 1 + items.length) % items.length;
|
||||
updateActiveSuggestion(items, activeIndex);
|
||||
} else if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
if(activeIndex === -1) activeIndex = 0;
|
||||
if (activeIndex >= 0 && activeIndex < items.length) {
|
||||
insertAutocomplete(items[activeIndex].textContent, textarea);
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
} else if (e.key === 'Escape') {
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function showSuggestions(matches, autocompleteList) {
|
||||
autocompleteList.innerHTML = '';
|
||||
activeIndex = -1;
|
||||
if (matches.length === 0) {
|
||||
hideSuggestions(autocompleteList);
|
||||
return;
|
||||
}
|
||||
matches.forEach(match => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = match;
|
||||
li.addEventListener('click', () => {
|
||||
insertAutocomplete(match, textarea);
|
||||
hideSuggestions(autocompleteList);
|
||||
});
|
||||
autocompleteList.appendChild(li);
|
||||
});
|
||||
autocompleteList.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function hideSuggestions(autocompleteList) {
|
||||
autocompleteList.classList.add('hidden');
|
||||
activeIndex = -1;
|
||||
}
|
||||
|
||||
function updateActiveSuggestion(items, activeIndex) {
|
||||
items.forEach((item, index) => {
|
||||
item.classList.remove('active');
|
||||
if (index === activeIndex) {
|
||||
item.classList.add('active');
|
||||
item.scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insertAutocomplete(suggestion, textarea) {
|
||||
const cursorPosition = textarea.selectionStart;
|
||||
const textBefore = textarea.value.substring(0, cursorPosition);
|
||||
const textAfter = textarea.value.substring(cursorPosition);
|
||||
const match = textBefore.match(/{%[^\s]*$/);
|
||||
if (match) {
|
||||
const lastWord = match[0];
|
||||
const completion = suggestion.substring(lastWord.length);
|
||||
const newText = textBefore + completion + textAfter;
|
||||
textarea.value = newText;
|
||||
const newCursorPosition = cursorPosition + completion.length;
|
||||
textarea.setSelectionRange(newCursorPosition, newCursorPosition);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
// Check if the click was outside the textarea or suggestion list
|
||||
const isClickInsideTextarea = e.target.closest('.editor');
|
||||
const isClickInsideAutocompleteList = e.target.closest('.autocomplete-list');
|
||||
|
||||
if (!isClickInsideTextarea && !isClickInsideAutocompleteList) {
|
||||
const container = textarea.closest('.autocomplete-container');
|
||||
const autocompleteList = container.querySelector('.autocomplete-list');
|
||||
hideSuggestions(autocompleteList);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function checkPromptsConfigForPlaceholders(textarea){
|
||||
// check additional_text and selected_text placeholders presence and the corrispondent checkboxes
|
||||
let tr_ancestor = textarea.closest('tr');
|
||||
let need_custom_text_element = tr_ancestor.querySelector('.need_custom_text') || tr_ancestor.querySelector('.need_custom_text_new');
|
||||
if(String(textarea.value).indexOf('{%additional_text%}') != -1){
|
||||
let tr_ancestor = textarea.closest('tr');
|
||||
let need_custom_text_element = tr_ancestor.querySelector('.need_custom_text') || tr_ancestor.querySelector('.need_custom_text_new');
|
||||
if(!need_custom_text_element.checked){
|
||||
need_custom_text_element.closest('.need_custom_text_span').style.border = '2px solid red';
|
||||
}else{
|
||||
need_custom_text_element.closest('.need_custom_text_span').style.border = '';
|
||||
}
|
||||
}else{
|
||||
need_custom_text_element.closest('.need_custom_text_span').style.border = '';
|
||||
}
|
||||
|
||||
let tr_ancestor2 = textarea.closest('tr');
|
||||
let selected_text_element = tr_ancestor2.querySelector('.need_selected') || tr_ancestor2.querySelector('.need_selected_new');
|
||||
if(String(textarea.value).indexOf('{%selected_text%}') != -1){
|
||||
let tr_ancestor = textarea.closest('tr');
|
||||
let selected_text_element = tr_ancestor.querySelector('.need_selected') || tr_ancestor.querySelector('.need_selected_new');
|
||||
if(!selected_text_element.checked){
|
||||
selected_text_element.closest('.need_selected_span').style.border = '2px solid red';
|
||||
}else{
|
||||
selected_text_element.closest('.need_selected_span').style.border = '';
|
||||
}
|
||||
}else{
|
||||
selected_text_element.closest('.need_selected_span').style.border = '';
|
||||
}
|
||||
}
|
||||
|
|
@ -62,6 +62,10 @@ body {
|
|||
.mzta_autocomplete-item-active {
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
|
||||
.prompt_add_tags{
|
||||
background-color: #cfe9ff;
|
||||
}
|
||||
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
|
@ -96,4 +100,8 @@ body {
|
|||
.mzta_autocomplete-item-active {
|
||||
background-color: #444444;
|
||||
}
|
||||
|
||||
.prompt_add_tags{
|
||||
background-color: #353542;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,26 +16,30 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { taStore } from "../js/mzta-store.js";
|
||||
import { taLogger } from "../js/mzta-logger.js";
|
||||
|
||||
let menuSendImmediately = false;
|
||||
let taLog = console;
|
||||
let connection_type = 'chatgpt_web';
|
||||
let add_tags = false;
|
||||
let tabType;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
let prefs = await browser.storage.sync.get({do_debug: false, dynamic_menu_force_enter: false});
|
||||
let prefs = await browser.storage.sync.get({do_debug: false, dynamic_menu_force_enter: false, add_tags: false, connection_type: 'chatgpt_web'});
|
||||
taLog = new taLogger("mzta-popup",prefs.do_debug);
|
||||
i18n.updateDocument();
|
||||
let reponse = await browser.runtime.sendMessage({command: "popup_menu_ready"});
|
||||
taLog.log("Preparing data to load the popup menu: " + JSON.stringify(reponse));
|
||||
let tabId = reponse.lastShortcutTabId;
|
||||
let tabType = reponse.lastShortcutTabType;
|
||||
tabType = reponse.lastShortcutTabType;
|
||||
let filtering = reponse.lastShortcutFiltering;
|
||||
let _prompts_data = reponse.lastShortcutPromptsData;
|
||||
taLog.log("_prompts_data: " + JSON.stringify(_prompts_data));
|
||||
let active_prompts = filterPromptsForTab(_prompts_data, filtering);
|
||||
taLog.log("active_prompts: " + JSON.stringify(active_prompts));
|
||||
menuSendImmediately = prefs.dynamic_menu_force_enter;
|
||||
connection_type = prefs.connection_type;
|
||||
add_tags = prefs.add_tags;
|
||||
searchPrompt(active_prompts, tabId, tabType);
|
||||
i18n.updateDocument();
|
||||
}, { once: true });
|
||||
|
|
@ -78,7 +82,7 @@ async function searchPrompt(allPrompts, tabId, tabType){
|
|||
*/
|
||||
|
||||
// Filter data based on the query
|
||||
const filteredData = allPrompts.filter(item =>
|
||||
let filteredData = allPrompts.filter(item =>
|
||||
item.label.toLowerCase().includes(query)
|
||||
);
|
||||
taLog.log("filteredData: " + JSON.stringify(filteredData));
|
||||
|
|
@ -89,9 +93,20 @@ async function searchPrompt(allPrompts, tabId, tabType){
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// Prepend numbers to the first 10 items
|
||||
Array.from(filteredData).slice(0, 10).forEach((item, index) => {
|
||||
const number = (index < 9) ? (index + 1).toString() : '0';
|
||||
// If add_tags is true and connection_type is not 'chatgpt_web' reserve 0 position for prompt_add_tags
|
||||
let max_num_el = 10
|
||||
let first_num_el = 0;
|
||||
if(checkDoAddTags()){
|
||||
max_num_el = 9;
|
||||
first_num_el = 1;
|
||||
filteredData = ensurePromptAddTagsFirst(filteredData);
|
||||
filteredData[0].numberPrepended = 'true';
|
||||
filteredData[0].label = '0. ' + filteredData[0].label;
|
||||
}
|
||||
Array.from(filteredData).slice(first_num_el, max_num_el).forEach((item, index) => {
|
||||
let number = (index < 9) ? (index + 1).toString() : '0';
|
||||
// Check if the number is already prepended to avoid duplication
|
||||
if (!item.numberPrepended) {
|
||||
item.label = `${number}. ${item.label}`;
|
||||
|
|
@ -101,12 +116,22 @@ async function searchPrompt(allPrompts, tabId, tabType){
|
|||
|
||||
// console.log(">>>>>>>>>>>>> filteredData: " + JSON.stringify(filteredData));
|
||||
|
||||
// add the prompt_add_tags if add_tags is true and connection_type is not 'chatgpt_web'
|
||||
// if(checkDoAddTags()){
|
||||
// let number = '0';
|
||||
// let item = {label: `${number}. ${browser.i18n.getMessage('prompt_add_tags')}`, id: 'prompt_add_tags', numberPrepended: 'true'};
|
||||
// filteredData.unshift(item);
|
||||
// }
|
||||
|
||||
// Create a div for each filtered result
|
||||
filteredData.forEach(item => {
|
||||
const itemDiv = document.createElement('div');
|
||||
itemDiv.classList.add('mzta_autocomplete-item');
|
||||
itemDiv.textContent = item.label;
|
||||
itemDiv.setAttribute('data-id', item.id);
|
||||
if(item.id === 'prompt_add_tags'){
|
||||
itemDiv.className += ' prompt_add_tags';
|
||||
}
|
||||
|
||||
// Add a mousedown event to select the item
|
||||
itemDiv.addEventListener('mousedown', function(e) { // Use mousedown instead of click
|
||||
|
|
@ -141,8 +166,8 @@ async function searchPrompt(allPrompts, tabId, tabType){
|
|||
});
|
||||
|
||||
// Add a keydown event listener to handle arrow navigation and selection
|
||||
input.addEventListener('keydown', function (e) {
|
||||
|
||||
input.addEventListener('keydown', async function (e) {
|
||||
|
||||
const items = autocompleteList.getElementsByClassName('mzta_autocomplete-item');
|
||||
if ((autocompleteList.style.display === 'none' || items.length === 0)
|
||||
&& (e.key !== 'Enter')
|
||||
|
|
@ -154,7 +179,11 @@ async function searchPrompt(allPrompts, tabId, tabType){
|
|||
// Handle number key presses (1-9,0) to select the corresponding item directly
|
||||
if (['1','2','3','4','5','6','7','8','9','0'].includes(e.key)) {
|
||||
// Map '1' to index 0, '2' to 1, ..., '9' to 8, '0' to 9
|
||||
const numIndex = (e.key === '0') ? 9 : parseInt(e.key, 10) - 1;
|
||||
let numIndex = (e.key === '0') ? 9 : parseInt(e.key, 10) - 1;
|
||||
if(checkDoAddTags()){
|
||||
numIndex = parseInt(e.key, 10);
|
||||
}
|
||||
|
||||
if (items[numIndex]) {
|
||||
e.preventDefault(); // Prevent any default behavior
|
||||
// Dispatch a select_prompt event to simulate a click/select action
|
||||
|
|
@ -226,11 +255,15 @@ document.body.insertBefore(banner, document.body.firstChild);
|
|||
}
|
||||
|
||||
|
||||
function sendPrompt(prompt_id, tabId){
|
||||
async function sendPrompt(prompt_id, tabId){
|
||||
taLog.log("sendPrompt: " + prompt_id);
|
||||
document.getElementById('mzta_search_input').style.display = 'none';
|
||||
document.getElementById('mzta_sending_prompt').style.display = 'block';
|
||||
browser.runtime.sendMessage({command: "shortcut_do_prompt", tabId: tabId, promptId: prompt_id});
|
||||
let response = await browser.runtime.sendMessage({command: "shortcut_do_prompt", tabId: tabId, promptId: prompt_id});
|
||||
console.log(">>>>>>>>>>>>>>>>> response: " + JSON.stringify(response));
|
||||
if(response.ok == '1'){
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
|
||||
function filterPromptsForTab(prompts_data, filtering){
|
||||
|
|
@ -252,4 +285,23 @@ function filterPromptsForTab(prompts_data, filtering){
|
|||
|
||||
// Filter the array based on the allowed types
|
||||
return prompts_data.filter(prompt => allowedTypes.includes(prompt.type));
|
||||
}
|
||||
|
||||
function checkDoAddTags(){
|
||||
return add_tags && (connection_type !== "chatgpt_web" && tabType !== 'messageCompose');
|
||||
}
|
||||
|
||||
function ensurePromptAddTagsFirst(arr) {
|
||||
// Find the index of the object with id "prompt_add_tags"
|
||||
const index = arr.findIndex(item => item.id === "prompt_add_tags");
|
||||
|
||||
// If found and not already the first element
|
||||
if (index !== -1 && index !== 0) {
|
||||
// Remove it from its current position
|
||||
const [promptAddTags] = arr.splice(index, 1);
|
||||
// Add it to the beginning of the array
|
||||
arr.unshift(promptAddTags);
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
Loading…
Reference in a new issue