commit
3a4fffdc93
21 changed files with 3487 additions and 86 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -1,6 +1,17 @@
|
|||
#  ThunderAI Release Notes
|
||||
|
||||
|
||||
<h2>Version 1.1.0 - ??/??/2024</h2>
|
||||
<ul>
|
||||
<li>A prompt can be configured to request additional text from the user.</li>
|
||||
<li>Added custom prompts. See more info <a href="https://micz.it/thunderdbird-addon-thunderai/custom-prompts/">here</a>.</li>
|
||||
<li>Dark mode added.</li>
|
||||
</ul>
|
||||
<h2>Version 1.0.6 - 08/05/2024</h2>
|
||||
<ul>
|
||||
<li>Correctly handling a change in the ChatGPT web interface. See issue <a href="https://github.com/micz/ThunderAI/issues/43">#43</a></li>
|
||||
<li>Added a button to force the completion to display the 'Use last answer' button if ChatGPT has finished its work but the button has not appeared.</li>
|
||||
</ul>
|
||||
<h2>Version 1.0.5 - 03/05/2024</h2>
|
||||
<ul>
|
||||
<li>Fixed the handling of ChatGPT-4 in a large window. See issue <a href="https://github.com/micz/ThunderAI/issues/38">#38</a></li>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,186 @@
|
|||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_managePrompts": {
|
||||
"message": "Manage Prompts",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_start_saving": {
|
||||
"message": "Saving prompts...",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_reindexing_list": {
|
||||
"message": "Reindexing list...",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_filtering_prompts": {
|
||||
"message": "Filtering prompts...",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_saving_default_prompts": {
|
||||
"message": "Saving default prompts...",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_saving_custom_prompts": {
|
||||
"message": "Saving custom prompts...",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_reloading_menus": {
|
||||
"message": "Reloading menus...",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_saved": {
|
||||
"message": "Prompts saved!",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_managePrompts_statement": {
|
||||
"message": "Manage your custom prompts.",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_ID": {
|
||||
"message": "ID",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_ID_rules": {
|
||||
"message": "Must be unique, lowercase and without spaces",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_Name": {
|
||||
"message": "Name",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_Text": {
|
||||
"message": "Prompt Text",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_Action": {
|
||||
"message": "Action",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_need_selected": {
|
||||
"message": "Text selection needed",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_need_signature": {
|
||||
"message": "Always add the signature",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_need_custom_text": {
|
||||
"message": "Ask for additional text",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_label_enabled": {
|
||||
"message": "Enabled",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_form_required_fields": {
|
||||
"message": "Required fields",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_btnEdit": {
|
||||
"message": "Edit",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_btnCancel": {
|
||||
"message": "Cancel",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_btnOK": {
|
||||
"message": "OK",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_btnDelete": {
|
||||
"message": "Delete",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_btnDelete_confirmText": {
|
||||
"message": "Are you sure you want to delete this item?",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_unsaved_changes": {
|
||||
"message": "There are unsaved changes!",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_btnSaveAll": {
|
||||
"message": "Save All",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_save_button": {
|
||||
"message": "Save",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_btnNew": {
|
||||
"message": "Add New",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
"message": "Add the Prompt",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_add_to_menu": {
|
||||
"message": "Add to menu",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_add_to_menu_always": {
|
||||
"message": "Always",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_add_to_menu_reading": {
|
||||
"message": "Reading an email",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_add_to_menu_composing": {
|
||||
"message": "Composing an email",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_close_button": {
|
||||
"message": "Close button",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_do_reply": {
|
||||
"message": "Do reply",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_substitute_text": {
|
||||
"message": "Substitute text",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_win_working": {
|
||||
"message": "Work in progress...",
|
||||
"description": ""
|
||||
|
|
@ -99,6 +279,16 @@
|
|||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_force_completion": {
|
||||
"message": "force completion",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_force_completion_title": {
|
||||
"message": "Click here to display the 'Use last answer' button if ChatGPT has finished its work but the button has not appeared.",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"msg_prompt_too_long": {
|
||||
"message": "The text you provided is too long. You need to reduce it to use ChatGPT.",
|
||||
"description": ""
|
||||
|
|
@ -164,6 +354,11 @@
|
|||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_btnManagePrompts": {
|
||||
"message": "Manage your prompts",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefsInfoTitle": {
|
||||
"message": "Important Information",
|
||||
"description": ""
|
||||
|
|
|
|||
|
|
@ -1,201 +1,318 @@
|
|||
{
|
||||
"extensionDescription": {
|
||||
"message": "Usa ChatGPT per migliorare le tue email!",
|
||||
"description": "Descrizione dell'estensione."
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
|
||||
"menu_title": {
|
||||
"message": "IA",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_lang": {
|
||||
"message": "Rispondi in ",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_reply": {
|
||||
"message": "Rispondi",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_rewrite_polite": {
|
||||
"message": "Riscrivi cortese",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_rewrite_formal": {
|
||||
"message": "Riscrivi formale",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_classify": {
|
||||
"message": "Classifica",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_summarize_this": {
|
||||
"message": "Riassumi",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_translate_this": {
|
||||
"message": "Traduci",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_this": {
|
||||
"message": "Chedi a ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prompt_selection_needed": {
|
||||
"message": "Per procedere è necessario che selezioni del testo!",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"customPrompts_managePrompts": {
|
||||
"message": "Gestisci i prompt",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_start_saving": {
|
||||
"message": "Salvataggio prompt in corso...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_reindexing_list": {
|
||||
"message": "Indicizzazione lista...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_filtering_prompts": {
|
||||
"message": "Applicazione filtro in corso...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_saving_default_prompts": {
|
||||
"message": "Salvataggio prompt di base...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_saving_custom_prompts": {
|
||||
"message": "Salvataggio prompt personalizzati...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_reloading_menus": {
|
||||
"message": "Caricamento menu aggiornati...",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_saved": {
|
||||
"message": "Prompt salvati!",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_managePrompts_statement": {
|
||||
"message": "Gestisci i tuoi prompt personalizzati.",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_ID": {
|
||||
"message": "ID",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_ID_rules": {
|
||||
"message": "Deve essere univoco, minuscolo e senza spazi.",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_Name": {
|
||||
"message": "Nome",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_Text": {
|
||||
"message": "Testo del prompt",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_Action": {
|
||||
"message": "Azione",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_need_selected": {
|
||||
"message": "Necessaria la selezione di testo",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_need_signature": {
|
||||
"message": "Aggiungi sempre la firma",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_need_custom_text": {
|
||||
"message": "Chiedi un testo aggiuntivo",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_label_enabled": {
|
||||
"message": "Attivo",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_form_required_fields": {
|
||||
"message": "Campi obbligatori",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnEdit": {
|
||||
"message": "Modifica",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnCancel": {
|
||||
"message": "Annulla",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnOK": {
|
||||
"message": "OK",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnDelete": {
|
||||
"message": "Cancella",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnDelete_confirmText": {
|
||||
"message": "Sei sicuro di voler cancellare questo elemento?",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_unsaved_changes": {
|
||||
"message": "Ci sono modifiche non salvate!",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnSaveAll": {
|
||||
"message": "Salva Tutto",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_save_button": {
|
||||
"message": "Salva",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnNew": {
|
||||
"message": "Aggiungi Nuovo",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_btnAddNewCommit": {
|
||||
"message": "Aggiungi il Prompt",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_add_to_menu": {
|
||||
"message": "Aggiungi al menu",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_add_to_menu_always": {
|
||||
"message": "Sempre",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_add_to_menu_reading": {
|
||||
"message": "In lettura di una mail",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_add_to_menu_composing": {
|
||||
"message": "In composizione di una mail",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_close_button": {
|
||||
"message": "Pulsante chiudi",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_do_reply": {
|
||||
"message": "Rispondi",
|
||||
"description": ""
|
||||
},
|
||||
"customPrompts_substitute_text": {
|
||||
"message": "Sostituisci il testo",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_win_working": {
|
||||
"message": "Elaborazione in corso...",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_win_job_completed": {
|
||||
"message": "Completato!",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_win_get_answer": {
|
||||
"message": "Usa l'ultima risposta",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_win_close": {
|
||||
"message": "Chiudi",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_user_not_logged_in": {
|
||||
"message": "Non sei connesso a ChatGPT. Effettua l'accesso con le tue credenziali, chiudi la finestra di ChatGPT e poi ripeti l'azione che avevi tentato. Rimarrai connesso in seguito.",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_win_model_warning": {
|
||||
"message": "Hai impostato l'opzione per utilizzare ChatGPT-4, ma sembra che non si stia caricando. Hai selezionato correttamente il modello in alto?",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_win_custom_text": {
|
||||
"message": "Inserisci qui il testo aggiuntivo per il prompt.",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_win_send": {
|
||||
"message": "Invia",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_use_gpt35": {
|
||||
"message": "Usa GPT3.5",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"chatgpt_force_completion": {
|
||||
"message": "forza il completamento",
|
||||
"description": ""
|
||||
},
|
||||
"chatgpt_force_completion_title": {
|
||||
"message": "Fai clic qui per visualizzare il pulsante 'Usa l'ultima risposta' se ChatGPT ha terminato il suo lavoro ma il pulsante non è apparso.",
|
||||
"description": ""
|
||||
},
|
||||
"msg_prompt_too_long": {
|
||||
"message": "Il testo che vuoi inviare a ChatGPT è troppo lungo. Devi ridurlo per poter procedere.",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_release_notes": {
|
||||
"message": "Note di rilascio",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_status_page": {
|
||||
"message": "stato del servizio",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_chatgpt_win_text": {
|
||||
"message": "Dimensioni della finestra di ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_chatgpt_win_height": {
|
||||
"message": "Altezza",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_chatgpt_win_width": {
|
||||
"message": "Larghezza",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_default_sign_name": {
|
||||
"message": "Nome da utilizzare per la firma",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_default_chatgpt_lang": {
|
||||
"message": "Lingua predefinita per le risposte di ChatGPT",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_reply_all": {
|
||||
"message": "Rispondi a tutti",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_reply_sender": {
|
||||
"message": "Rispondi al mittente",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_reply_type": {
|
||||
"message": "Modalità di risposta",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_chatpgt_use_gpt4": {
|
||||
"message": "Usa il modello ChatGPT-4",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_chatpgt_use_gpt4_info": {
|
||||
"message": "Dopo aver modificato questa opzione, devi scegliere il modello corretto la prima volta che lo usi.",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefs_OptionText_btnManagePrompts": {
|
||||
"message": "Gestisci i tuoi prompts",
|
||||
"description": ""
|
||||
},
|
||||
"prefsInfoTitle": {
|
||||
"message": "Informazioni Importanti",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefsInfoDesc_1": {
|
||||
"message": "Non è più possibile disabilitare la cronologia delle chat di ChatGPT. Pertanto, non c'è modo di impedire che le richieste effettuate tramite questo componente aggiuntivo appaiano nella cronologia delle chat di ChatGPT.",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefsInfoDesc_2": {
|
||||
"message": "Se all'apertura della finestra di ChatGPT, viene mostrata una pagina bianca, significa che c'è un problema di caricamento della pagina di ChatGPT, non relativo all'utilizzo di questo componente aggiuntivo.",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefsInfoDesc_3": {
|
||||
"message": " ",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefsDonation_1": {
|
||||
"message": "Ti piace questo componente aggiuntivo?",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"prefsDonation_2": {
|
||||
"message": "Considera di fare una donazione!",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"backToOptionsText": {
|
||||
"message": "Opzioni",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
2020
customprompts/list.js
Normal file
2020
customprompts/list.js
Normal file
File diff suppressed because it is too large
Load diff
1
customprompts/list.js.map
Normal file
1
customprompts/list.js.map
Normal file
File diff suppressed because one or more lines are too long
172
customprompts/mzta-custom-prompts.css
Normal file
172
customprompts/mzta-custom-prompts.css
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
@media (prefers-color-scheme: light) {
|
||||
table th {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#command_palette{
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
table.prompts_list tr:nth-child(even) {
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
|
||||
table.prompts_list tr:nth-child(odd) {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #1C1B22;
|
||||
color: rgb(251, 251, 254);
|
||||
}
|
||||
|
||||
a:link { color: #409EFF; }
|
||||
a:visited { color: #409EFF; }
|
||||
a:hover { color: #66B1FF; }
|
||||
a:active { color: #66B1FF; }
|
||||
|
||||
table {
|
||||
background-color: #1C1B22;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
table.prompts_list th {
|
||||
background-color: #4c4e58;
|
||||
border: 1px solid rgb(251, 251, 254);
|
||||
color: rgb(194, 194, 194);
|
||||
}
|
||||
|
||||
#command_palette{
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
table.prompts_list tr:nth-child(even) {
|
||||
background-color: #2E2F36;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
thead {
|
||||
position: sticky;
|
||||
top: 26px;
|
||||
}
|
||||
|
||||
#command_palette{
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding-top: 1px;
|
||||
height: 26px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#btnNew{
|
||||
float: right;
|
||||
}
|
||||
|
||||
#btnSaveAll{
|
||||
float: left;
|
||||
}
|
||||
|
||||
#msgDisplay{
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
table tr {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
table.prompts_list th {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
table td.w08{
|
||||
width: 8vw;
|
||||
}
|
||||
|
||||
table td.w17{
|
||||
width: 17vw;
|
||||
}
|
||||
|
||||
table td.w19{
|
||||
width: 19vw;
|
||||
}
|
||||
|
||||
table td.w25{
|
||||
width: 25vw;
|
||||
}
|
||||
|
||||
table td.w40{
|
||||
width: 40vw;
|
||||
}
|
||||
|
||||
table.prompts_list td.properties{
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
table .sort {
|
||||
background-image: url(../images/listjs-arrow-sort-inactive.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
padding-right: 14px;
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
}
|
||||
|
||||
table .sort.asc {
|
||||
background-image: url(../images/listjs-arrow-sort-active-down.png);
|
||||
}
|
||||
|
||||
table .sort.desc {
|
||||
background-image: url(../images/listjs-arrow-sort-active-up.png);
|
||||
}
|
||||
|
||||
.hiddendata{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#formNew{
|
||||
display: none;
|
||||
width: 100%;
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
.text_output{
|
||||
width: 98%;
|
||||
height: 9em;
|
||||
}
|
||||
|
||||
.go_right_float{
|
||||
float: right;
|
||||
}
|
||||
|
||||
.go_right{
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.width_all{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.small_label{
|
||||
font-size: small;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#txtIdNew, .id_output{
|
||||
text-transform: lowercase;
|
||||
}
|
||||
91
customprompts/mzta-custom-prompts.html
Normal file
91
customprompts/mzta-custom-prompts.html
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ThunderAI - __MSG_customPrompts_managePrompts__</title>
|
||||
<link rel="stylesheet" href="mzta-custom-prompts.css">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>__MSG_customPrompts_managePrompts__</h1>
|
||||
<p>__MSG_customPrompts_managePrompts_statement__</p>
|
||||
</div>
|
||||
<div id="command_palette">
|
||||
<button id="btnSaveAll" disabled>__MSG_customPrompts_btnSaveAll__</button>
|
||||
<span id="msgDisplay"></span>
|
||||
<button id="btnNew">__MSG_customPrompts_btnNew__</button>
|
||||
</div>
|
||||
<div id="formNew">
|
||||
<table class="width_all">
|
||||
<tr>
|
||||
<td class="w19">
|
||||
<label for="txtIdNew">*__MSG_customPrompts_form_label_ID__:</label>
|
||||
<br>
|
||||
<input type="text" id="txtIdNew" name="id" class="input_new">
|
||||
<br><span class="small_label">[__MSG_customPrompts_form_label_ID_rules__]</span>
|
||||
</td>
|
||||
<td rowspan="2" class="w25">
|
||||
<label for="txtTextNew">*__MSG_customPrompts_form_label_Text__:</label>
|
||||
<br>
|
||||
<textarea id="txtTextNew" name="text" class="input_new text_output"></textarea>
|
||||
</td>
|
||||
<td class="w19">
|
||||
<label for="selectTypeNew">__MSG_customPrompts_add_to_menu__:</label>
|
||||
<br>
|
||||
<select id="selectTypeNew" name="type">
|
||||
<option value="0">__MSG_customPrompts_add_to_menu_always__</option>
|
||||
<option value="1">__MSG_customPrompts_add_to_menu_reading__</option>
|
||||
<option value="2">__MSG_customPrompts_add_to_menu_composing__</option>
|
||||
</select>
|
||||
</td>
|
||||
<td rowspan="2" class="w19">
|
||||
<input type="checkbox" id="checkboxNeedSelectedNew" name="need_selected" value="1"> <label for="checkboxNeedSelectedNew">__MSG_customPrompts_form_label_need_selected__</label>
|
||||
<br>
|
||||
<input type="checkbox" id="checkboxNeedSignatureNew" name="need_signature" value="1"> <label for="checkboxNeedSignatureNew">__MSG_customPrompts_form_label_need_signature__</label>
|
||||
<br>
|
||||
<input type="checkbox" id="checkboxNeedCustomTextNew" name="need_custom_text" value="1"> <label for="checkboxNeedCustomTextNew">__MSG_customPrompts_form_label_need_custom_text__</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="w19">
|
||||
<label for="txtNameNew">*__MSG_customPrompts_form_label_Name__:</label>
|
||||
<br>
|
||||
<input type="text" id="txtNameNew" name="name" class="input_new">
|
||||
</td>
|
||||
<td class="w19">
|
||||
<label for="selectActionNew">__MSG_customPrompts_form_label_Action__:</label>
|
||||
<br>
|
||||
<select id="selectActionNew" name="action">
|
||||
<option value="0">__MSG_customPrompts_close_button__</option>
|
||||
<option value="1">__MSG_customPrompts_do_reply__</option>
|
||||
<option value="2">__MSG_customPrompts_substitute_text__</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="go_right_float">* __MSG_customPrompts_form_required_fields__</div>
|
||||
<br>
|
||||
<div class="go_right"><button id="btnAddNew" disabled>__MSG_customPrompts_btnAddNewCommit__</button></div>
|
||||
</div>
|
||||
<div id="all_prompts">
|
||||
<table class="prompts_list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort" data-sort="id">__MSG_customPrompts_form_label_ID__</th>
|
||||
<th class="sort" data-sort="name">__MSG_customPrompts_form_label_Name__</th>
|
||||
<th class="sort" data-sort="text">__MSG_customPrompts_form_label_Text__</th>
|
||||
<th class="sort" data-sort="type">__MSG_customPrompts_add_to_menu__</th>
|
||||
<th>Properties</th>
|
||||
<th>__MSG_customPrompts_form_label_Action__</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<script src="list.js"></script>
|
||||
<script src="mzta-custom-prompts.js" type="module"></script>
|
||||
<script src="../js/mzta-i18n.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
525
customprompts/mzta-custom-prompts.js
Normal file
525
customprompts/mzta-custom-prompts.js
Normal file
|
|
@ -0,0 +1,525 @@
|
|||
/*
|
||||
* ThunderAI [https://micz.it/thunderdbird-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 { getPrompts, setDefaultPromptsProperties, setCustomPrompts } from "../js/mzta-prompts.js";
|
||||
|
||||
var promptsList = null;
|
||||
var somethingChanged = false;
|
||||
var positionMax_compose = 0;
|
||||
var positionMax_display = 0;
|
||||
var idnumMax = 0;
|
||||
var msgTimeout = null;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
let options = {
|
||||
valueNames: [ { data: ['idnum'] }, 'is_default', 'id', 'name', 'text', 'type', 'action', 'position_compose', 'position_display', { name: 'need_selected', attr: 'checked_val'}, { name: 'need_signature', attr: 'checked_val'}, { name: 'need_custom_text', attr: 'checked_val'}, { name: 'enabled', attr: 'checked_val'} ],
|
||||
item: function(values) {
|
||||
let type_output = '';
|
||||
switch(String(values.type)){
|
||||
case "0":
|
||||
type_output = `__MSG_customPrompts_add_to_menu_always__`;
|
||||
break;
|
||||
case "1":
|
||||
type_output = `__MSG_customPrompts_add_to_menu_reading__`;
|
||||
break;
|
||||
case "2":
|
||||
type_output = `__MSG_customPrompts_add_to_menu_composing__`;
|
||||
break;
|
||||
}
|
||||
|
||||
let action_output = '';
|
||||
switch(String(values.action)){
|
||||
case "0":
|
||||
action_output = `__MSG_customPrompts_close_button__`;
|
||||
break;
|
||||
case "1":
|
||||
action_output = `__MSG_customPrompts_do_reply__`;
|
||||
break;
|
||||
case "2":
|
||||
action_output = `__MSG_customPrompts_substitute_text__`;
|
||||
break;
|
||||
}
|
||||
//console.log('>>>>>>>>>>>>> action_output: ' + JSON.stringify(action_output));
|
||||
|
||||
let output = `<tr ` + ((values.is_default == 1) ? 'class="is_default"':'') + `>
|
||||
<td class="w08"><span class="id id_show"></span><input type="text" class="hiddendata id_output" value="` + values.id + `" /></td>
|
||||
<td class="w08"><span class="name name_show"></span><input type="text" class="hiddendata name_output" value="` + values.name + `" /></td>
|
||||
<td class="w40"><span class="text text_show"></span><textarea class="hiddendata text_output">` + values.text + `</textarea></td>
|
||||
<td><span class="type_show">` + type_output + `</span>
|
||||
<select class="type_output hiddendata">
|
||||
<option value="0"` + ((values.type == "0") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_always__</option>
|
||||
<option value="1"` + ((values.type == "1") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_reading__</option>
|
||||
<option value="2"` + ((values.type == "2") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_composing__</option>
|
||||
</select>` +
|
||||
`<span class="type hiddendata"></span>
|
||||
</td>
|
||||
<td class="w17">
|
||||
Action: <span class="action_show">` + action_output + `</span>
|
||||
<select class="action_output hiddendata">
|
||||
<option value="0"` + ((values.action == "0") ? ' selected':'') + `>__MSG_customPrompts_close_button__</option>
|
||||
<option value="1"` + ((values.action == "1") ? ' selected':'') + `>__MSG_customPrompts_do_reply__</option>
|
||||
<option value="2"` + ((values.action == "2") ? ' selected':'') + `>__MSG_customPrompts_substitute_text__</option>
|
||||
</select>` +
|
||||
`<span class="action hiddendata"></span>
|
||||
<br>
|
||||
<input type="checkbox" class="need_selected" disabled> __MSG_customPrompts_form_label_need_selected__
|
||||
<br>
|
||||
<input type="checkbox" class="need_signature" disabled> __MSG_customPrompts_form_label_need_signature__
|
||||
<br>
|
||||
<input type="checkbox" class="need_custom_text" disabled> __MSG_customPrompts_form_label_need_custom_text__
|
||||
<br>
|
||||
<input type="checkbox" class="enabled input_mod"> __MSG_customPrompts_form_label_enabled__
|
||||
<span class="is_default hiddendata"></span>
|
||||
<span class="position_compose hiddendata"></span>
|
||||
<span class="position_display hiddendata"></span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btnEditItem"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnEdit__</button>
|
||||
<button class="btnCancelItem hiddendata"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnCancel__</button>
|
||||
<br><br>
|
||||
<button class="btnConfirmItem hiddendata"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnOK__</button>
|
||||
<button class="btnDeleteItem"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnDelete__</button>
|
||||
</td>
|
||||
</tr>`;
|
||||
//console.log('>>>>>>>> values.name: ' + JSON.stringify(values.name));
|
||||
positionMax_compose = Math.max(positionMax_compose, values.position_compose);
|
||||
positionMax_display = Math.max(positionMax_display, values.position_display);
|
||||
idnumMax = Math.max(idnumMax, values.idnum);
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
let values = await getPrompts();
|
||||
|
||||
console.log('>>>>>>>>>>>>>>>> values: ' + JSON.stringify(values));
|
||||
|
||||
promptsList = new List('all_prompts', options, values);
|
||||
|
||||
checkSelectedBoxes();
|
||||
|
||||
const btnSaveAll = document.getElementById('btnSaveAll');
|
||||
btnSaveAll.disabled = true;
|
||||
|
||||
// Disable save button and handle save actions
|
||||
function handleSaveAllClick(e) {
|
||||
e.preventDefault();
|
||||
saveAll();
|
||||
clearFields();
|
||||
}
|
||||
btnSaveAll.addEventListener('click', handleSaveAllClick);
|
||||
|
||||
const btnNew = document.getElementById('btnNew');
|
||||
|
||||
// Show the new item form
|
||||
function handleNewClick(e) {
|
||||
e.preventDefault();
|
||||
e.target.disabled = true;
|
||||
document.getElementById('formNew').style.display = 'block';
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
btnNew.addEventListener('click', handleNewClick);
|
||||
|
||||
// Enable save button on input change
|
||||
function handleInputChange(e) {
|
||||
e.preventDefault();
|
||||
setSomethingChanged();
|
||||
}
|
||||
document.querySelectorAll('.input_mod').forEach(element => {
|
||||
element.addEventListener('change', handleInputChange);
|
||||
});
|
||||
|
||||
// Display selected value next to select input
|
||||
// function handleSelectChange(e) {
|
||||
// e.preventDefault();
|
||||
// const spanElement = e.target.nextElementSibling;
|
||||
// spanElement.textContent = e.target.value;
|
||||
// }
|
||||
// document.querySelectorAll('select.input_mod').forEach(element => {
|
||||
// element.addEventListener('change', handleSelectChange);
|
||||
// });
|
||||
|
||||
// Log data ID number from item row and prepare for edit action
|
||||
function handleEditClick(e) {
|
||||
e.preventDefault();
|
||||
const tr = e.target.parentNode.parentNode;
|
||||
//console.log('>>>>>>>> tr: ' + tr.getAttribute('data-idnum'));
|
||||
e.target.style.display = 'none'; // Edit btn
|
||||
tr.querySelector('.btnConfirmItem').style.display = 'inline'; // Save btn
|
||||
tr.querySelector('.btnCancelItem').style.display = 'inline'; // Cancel btn
|
||||
// tr.querySelector('.btnEditItem').style.display = 'none'; // Edit btn
|
||||
tr.querySelector('.btnDeleteItem').style.display = 'none'; // Delete btn
|
||||
showItemRowEditor(tr);
|
||||
}
|
||||
let btnEditItem_elements = document.querySelectorAll(".btnEditItem");
|
||||
btnEditItem_elements.forEach(element => {
|
||||
element.addEventListener('click', handleEditClick);
|
||||
});
|
||||
|
||||
function showItemRowEditor(tr) {
|
||||
tr.querySelector('.id_output').style.display = 'inline';
|
||||
tr.querySelector('.id_show').style.display = 'none';
|
||||
tr.querySelector('.name_output').style.display = 'inline';
|
||||
tr.querySelector('.name_show').style.display = 'none';
|
||||
tr.querySelector('.text_output').style.display = 'inline';
|
||||
tr.querySelector('.text_show').style.display = 'none';
|
||||
tr.querySelector('.type_output').style.display = 'inline';
|
||||
tr.querySelector('.type_show').style.display = 'none';
|
||||
tr.querySelector('.action_output').style.display = 'inline';
|
||||
tr.querySelector('.action_show').style.display = 'none';
|
||||
tr.querySelector('input.need_selected').disabled = false;
|
||||
tr.querySelector('input.need_signature').disabled = false;
|
||||
tr.querySelector('input.need_custom_text').disabled = false;
|
||||
}
|
||||
|
||||
function hideItemRowEditor(tr) {
|
||||
tr.querySelector('.id_output').style.display = 'none';
|
||||
tr.querySelector('.id_show').style.display = 'inline';
|
||||
tr.querySelector('.name_output').style.display = 'none';
|
||||
tr.querySelector('.name_show').style.display = 'inline';
|
||||
tr.querySelector('.text_output').style.display = 'none';
|
||||
tr.querySelector('.text_show').style.display = 'inline';
|
||||
tr.querySelector('.type_output').style.display = 'none';
|
||||
tr.querySelector('.type_show').style.display = 'inline';
|
||||
tr.querySelector('.action_output').style.display = 'none';
|
||||
tr.querySelector('.action_show').style.display = 'inline';
|
||||
tr.querySelector('input.need_selected').disabled = true;
|
||||
tr.querySelector('input.need_signature').disabled = true;
|
||||
tr.querySelector('input.need_custom_text').disabled = true;
|
||||
}
|
||||
|
||||
|
||||
// Confirm and log deletion action
|
||||
function handleDeleteClick(e) {
|
||||
e.preventDefault();
|
||||
const checkConfirm = window.confirm(browser.i18n.getMessage("customPrompts_btnDelete_confirmText"));
|
||||
if (!checkConfirm) {
|
||||
return;
|
||||
}
|
||||
const tr = e.target.parentNode.parentNode;
|
||||
//console.log('>>>>>>>> tr: ' + tr.getAttribute('data-idnum'));
|
||||
promptsList.remove("id", tr.querySelector('span.id').innerText);
|
||||
setSomethingChanged();
|
||||
}
|
||||
let btnDeleteItem_elements = document.querySelectorAll(".btnDeleteItem");
|
||||
btnDeleteItem_elements.forEach(element => {
|
||||
element.addEventListener('click', handleDeleteClick);
|
||||
});
|
||||
|
||||
function handleCancelClick(e) {
|
||||
e.preventDefault();
|
||||
const tr = e.target.parentNode.parentNode;
|
||||
e.target.style.display = 'none'; // Cancel btn
|
||||
tr.querySelector('.btnConfirmItem').style.display = 'none'; // Save btn
|
||||
// tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn
|
||||
tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn
|
||||
tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn
|
||||
hideItemRowEditor(tr);
|
||||
}
|
||||
let btnCancelItem_elements = document.querySelectorAll(".btnCancelItem");
|
||||
btnCancelItem_elements.forEach(element => {
|
||||
element.addEventListener('click', handleCancelClick);
|
||||
});
|
||||
|
||||
function handleConfirmClick(e) {
|
||||
e.preventDefault();
|
||||
const tr = e.target.parentNode.parentNode;
|
||||
e.target.style.display = 'none'; // Ok btn
|
||||
// tr.querySelector('.btnConfirmItem').style.display = 'none'; // Ok btn
|
||||
tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn
|
||||
tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn
|
||||
tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn
|
||||
// Update item data
|
||||
tr.querySelector('.id_show').innerText = String(tr.querySelector('.id_output').value).toLocaleLowerCase();
|
||||
tr.querySelector('.name_show').innerText = tr.querySelector('.name_output').value;
|
||||
tr.querySelector('.text_show').innerText = tr.querySelector('.text_output').value;
|
||||
tr.querySelector('.type').innerText = tr.querySelector('.type_output').value;
|
||||
tr.querySelector('.type_show').innerText = tr.querySelector('.type_output').selectedOptions[0].text;
|
||||
tr.querySelector('.action').innerText = tr.querySelector('.action_output').value;
|
||||
tr.querySelector('.action_show').innerText = tr.querySelector('.action_output').selectedOptions[0].text;
|
||||
// the checkboxes update is handled directly by themselves
|
||||
hideItemRowEditor(tr);
|
||||
setSomethingChanged();
|
||||
}
|
||||
let btnConfirmItem_elements = document.querySelectorAll(".btnConfirmItem");
|
||||
btnConfirmItem_elements.forEach(element => {
|
||||
element.addEventListener('click', handleConfirmClick);
|
||||
});
|
||||
|
||||
// Handle checkbox changes and log new state
|
||||
function handleCheckboxChange(e) {
|
||||
e.preventDefault();
|
||||
e.target.setAttribute('checked_val', e.target.checked ? '1' : '0');
|
||||
//console.log('>>>>>>>> checked_val: ' + e.target.getAttribute('checked_val'));
|
||||
}
|
||||
let checkbox_elements = document.querySelectorAll("input[type='checkbox']");
|
||||
checkbox_elements.forEach(element => {
|
||||
element.addEventListener('change', handleCheckboxChange);
|
||||
});
|
||||
|
||||
// Handle "type" select changes and log new state
|
||||
// function handleTypeSelectChange(e) {
|
||||
// e.preventDefault();
|
||||
// const spanElement = e.target.nextElementSibling;
|
||||
// spanElement.textContent = e.target.value;
|
||||
// }
|
||||
// let type_select_elements = document.querySelectorAll("select.type_output");
|
||||
// type_select_elements.forEach(element => {
|
||||
// element.addEventListener('change', handleTypeSelectChange);
|
||||
// });
|
||||
|
||||
// Handle "action" select changes and log new state
|
||||
// function handleActionSelectChange(e) {
|
||||
// e.preventDefault();
|
||||
// const spanElement = e.target.nextElementSibling;
|
||||
// spanElement.textContent = e.target.value;
|
||||
// }
|
||||
// let action_select_elements = document.querySelectorAll("select.action_output");
|
||||
// action_select_elements.forEach(element => {
|
||||
// element.addEventListener('change', handleActionSelectChange);
|
||||
// });
|
||||
|
||||
// for the new prompt form
|
||||
let btnNew_elements = document.querySelectorAll(".input_new");
|
||||
if(btnNew_elements) {
|
||||
btnNew_elements.forEach(element => {
|
||||
element.addEventListener('change', (e) => {
|
||||
e.preventDefault();
|
||||
checkFields();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
i18n.updateDocument();
|
||||
|
||||
//To add a new item
|
||||
var txtIdNew = document.getElementById('txtIdNew');
|
||||
var txtNameNew = document.getElementById('txtNameNew');
|
||||
var txtTextNew = document.getElementById('txtTextNew');
|
||||
var selectTypeNew = document.getElementById('selectTypeNew');
|
||||
var selectActionNew = document.getElementById('selectActionNew');
|
||||
var checkboxNeedSelectedNew = document.getElementById('checkboxNeedSelectedNew');
|
||||
var checkboxNeedSignatureNew = document.getElementById('checkboxNeedSignatureNew');
|
||||
var checkboxNeedCustomTextNew = document.getElementById('checkboxNeedCustomTextNew');
|
||||
|
||||
const btnAddNew = document.getElementById('btnAddNew');
|
||||
btnAddNew.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
if(!checkFields()) {
|
||||
return;
|
||||
}
|
||||
let newItem = promptsList.add({
|
||||
id: String(txtIdNew.value.trim()).toLocaleLowerCase(),
|
||||
name: txtNameNew.value.trim(),
|
||||
text: txtTextNew.value.trim(),
|
||||
type: selectTypeNew.value,
|
||||
action: selectActionNew.value,
|
||||
need_selected: (checkboxNeedSelectedNew.checked) ? 1 : 0,
|
||||
need_signature: (checkboxNeedSignatureNew.checked) ? 1 : 0,
|
||||
need_custom_text: (checkboxNeedCustomTextNew.checked) ? 1 : 0,
|
||||
enabled: 1,
|
||||
position_compose: positionMax_compose + 1,
|
||||
position_display: positionMax_display + 1,
|
||||
is_default: 0,
|
||||
idnum: idnumMax + 1,
|
||||
});
|
||||
idnumMax++;
|
||||
let curr_idnum = newItem[0].values().idnum;
|
||||
let checkboxes = document.querySelectorAll(`tr[data-idnum="${curr_idnum}"] input[type="checkbox"]`);
|
||||
checkSelectedBoxes(checkboxes);
|
||||
let editBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnEditItem`);
|
||||
//console.log(`>>>>>>>>>>>> tr[data-idnum="${curr_idnum}"] button.btnEditItem`);
|
||||
editBtn.addEventListener('click', handleEditClick);
|
||||
//console.log('>>>>>>>>>>>>> editBtn: ' + JSON.stringify(editBtn));
|
||||
let deleteBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnDeleteItem`);
|
||||
//console.log(`>>>>>>>>>>>> tr[data-idnum="${curr_idnum}"] button.btnDeleteItem`);
|
||||
deleteBtn.addEventListener('click', handleDeleteClick);
|
||||
let okBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnConfirmItem`);
|
||||
okBtn.addEventListener('click', handleConfirmClick);
|
||||
let cancelBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnCancelItem`);
|
||||
cancelBtn.addEventListener('click', handleCancelClick);
|
||||
// console.log('>>>>>>>>>>>>> deleteBtn: ' + JSON.stringify(deleteBtn));
|
||||
// console.log('>>>>>>>>>>>>> newItem: ' + JSON.stringify(newItem));
|
||||
document.getElementById('btnNew').disabled = false;
|
||||
clearFields();
|
||||
setSomethingChanged();
|
||||
i18n.updateDocument();
|
||||
window.scrollTo({
|
||||
top: document.body.scrollHeight,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
});
|
||||
|
||||
}, { once: true });
|
||||
|
||||
|
||||
function checkFields() {
|
||||
//console.log('>>>>>>>>>>>>> typeof promptsList: ' + typeof promptsList);
|
||||
//console.log('>>>>>>>>>>>>> Array.isArray(promptsList): ' + Array.isArray(promptsList));
|
||||
// the id must be unique and without spaces
|
||||
let is_error = false;
|
||||
let id_value = document.getElementById('txtIdNew').value.trim();
|
||||
if ((id_value == '')||
|
||||
(/\s/.test(id_value))) {
|
||||
inputSetError('txtIdNew');
|
||||
is_error = true;
|
||||
} else {
|
||||
let exists = promptsList.get("id", id_value);
|
||||
//console.log('>>>>>>>>>>>>> exists: ' + JSON.stringify(exists));
|
||||
if(exists && exists.length > 0) {
|
||||
inputSetError('txtIdNew');
|
||||
is_error = true;
|
||||
} else {
|
||||
inputClearError('txtIdNew');
|
||||
}
|
||||
}
|
||||
if (document.getElementById('txtNameNew').value.trim() == '') {
|
||||
inputSetError('txtNameNew');
|
||||
is_error = true;
|
||||
} else {
|
||||
inputClearError('txtNameNew');
|
||||
}
|
||||
if (document.getElementById('txtTextNew').value.trim() == '') {
|
||||
inputSetError('txtTextNew');
|
||||
is_error = true;
|
||||
} else {
|
||||
inputClearError('txtTextNew');
|
||||
}
|
||||
document.getElementById('btnAddNew').disabled = is_error;
|
||||
return !is_error;
|
||||
}
|
||||
|
||||
|
||||
function clearFields() {
|
||||
document.getElementById('txtIdNew').value = '';
|
||||
document.getElementById('txtNameNew').value = '';
|
||||
document.getElementById('txtTextNew').value = '';
|
||||
document.getElementById('selectTypeNew').value = '0';
|
||||
document.getElementById('selectActionNew').value = '0';
|
||||
document.getElementById('checkboxNeedSelectedNew').value = '0';
|
||||
document.getElementById('checkboxNeedSignatureNew').value = '0';
|
||||
document.getElementById('checkboxNeedCustomTextNew').value = '0';
|
||||
document.getElementById('formNew').style.display = 'none';
|
||||
}
|
||||
|
||||
function inputSetError(input) {
|
||||
document.getElementById(input).style.borderColor = 'red';
|
||||
}
|
||||
|
||||
function inputClearError(input) {
|
||||
document.getElementById(input).style.borderColor = 'green';
|
||||
}
|
||||
|
||||
function setSomethingChanged(){
|
||||
clearTimeout(msgTimeout);
|
||||
somethingChanged = true;
|
||||
document.getElementById('btnSaveAll').disabled = false;
|
||||
let msgDisplay = document.getElementById('msgDisplay');
|
||||
msgDisplay.innerHTML = browser.i18n.getMessage('customPrompts_unsaved_changes');
|
||||
msgDisplay.style.display = 'inline';
|
||||
msgDisplay.style.color = 'red';
|
||||
}
|
||||
|
||||
function setNothingChanged(){
|
||||
somethingChanged = false;
|
||||
document.getElementById('btnSaveAll').disabled = true;
|
||||
let msgDisplay = document.getElementById('msgDisplay');
|
||||
msgDisplay.disabled = true;
|
||||
msgDisplay.innerHTML = ''
|
||||
msgDisplay.style.display = 'none';
|
||||
msgDisplay.style.color = '';
|
||||
}
|
||||
|
||||
function checkSelectedBoxes(checkboxes = null) {
|
||||
if(checkboxes == null){
|
||||
checkboxes = [
|
||||
...document.querySelectorAll('.need_selected[type="checkbox"]'),
|
||||
...document.querySelectorAll('.need_signature[type="checkbox"]'),
|
||||
...document.querySelectorAll('.need_custom_text[type="checkbox"]'),
|
||||
...document.querySelectorAll('.enabled[type="checkbox"]'),
|
||||
];
|
||||
}
|
||||
|
||||
// Iterate through the checkboxes
|
||||
checkboxes.forEach(checkbox => {
|
||||
// Check if the 'checked' attribute is "0"
|
||||
if (checkbox.getAttribute('checked_val') == "0") {
|
||||
// Uncheck the checkbox
|
||||
checkbox.checked = false;
|
||||
} else {
|
||||
checkbox.checked = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//Save all prompts
|
||||
async function saveAll() {
|
||||
setMessage(browser.i18n.getMessage('customPrompts_start_saving'));
|
||||
setNothingChanged();
|
||||
if(promptsList != null) {
|
||||
setMessage(browser.i18n.getMessage('customPrompts_reindexing_list'));
|
||||
promptsList.reIndex();
|
||||
let newPrompts = promptsList.items.map(item => {
|
||||
// For each item in the array, return only the '_values' part
|
||||
return item.values();
|
||||
});
|
||||
// newPrompts.forEach(prompt => {
|
||||
// console.log('>>>>>>>>>>>>> id: ' + JSON.stringify(prompt));
|
||||
// });
|
||||
//console.log('>>>>>>>>>>>>> saveAll: ' + JSON.stringify(newPrompts));
|
||||
setMessage(browser.i18n.getMessage('customPrompts_filtering_prompts'));
|
||||
let newDefaultPrompts = newPrompts.filter(item => item.is_default == 1);
|
||||
//console.log('>>>>>>>>>>>>> newDefaultPrompts: ' + JSON.stringify(newDefaultPrompts));
|
||||
let newCustomPrompts = newPrompts.filter(item => item.is_default == 0);
|
||||
setMessage(browser.i18n.getMessage('customPrompts_saving_default_prompts'));
|
||||
await setDefaultPromptsProperties(newDefaultPrompts);
|
||||
setMessage(browser.i18n.getMessage('customPrompts_saving_custom_prompts'));
|
||||
await setCustomPrompts(newCustomPrompts);
|
||||
setMessage(browser.i18n.getMessage('customPrompts_reloading_menus'));
|
||||
browser.runtime.sendMessage({command: "reload_menus"});
|
||||
setMessage(browser.i18n.getMessage('customPrompts_saved'),'green');
|
||||
msgTimeout = setTimeout(() => {
|
||||
clearMessage();
|
||||
}, 10000)
|
||||
}
|
||||
}
|
||||
|
||||
function setMessage(msg, color = '') {
|
||||
clearTimeout(msgTimeout);
|
||||
let msgDisplay = document.getElementById('msgDisplay');
|
||||
msgDisplay.innerHTML = msg;
|
||||
msgDisplay.style.display = 'inline';
|
||||
msgDisplay.style.color = color;
|
||||
}
|
||||
|
||||
function clearMessage() {
|
||||
let msgDisplay = document.getElementById('msgDisplay');
|
||||
msgDisplay.innerHTML = '';
|
||||
msgDisplay.style.display = 'none';
|
||||
msgDisplay.style.color = '';
|
||||
}
|
||||
|
||||
|
||||
// window.addEventListener('beforeunload', function (event) {
|
||||
// // Check if any changes have been made
|
||||
// if (somethingChanged) {
|
||||
// event.preventDefault();
|
||||
// }
|
||||
// });
|
||||
BIN
images/listjs-arrow-sort-active-down.png
Normal file
BIN
images/listjs-arrow-sort-active-down.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 515 B |
BIN
images/listjs-arrow-sort-active-up.png
Normal file
BIN
images/listjs-arrow-sort-active-up.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 560 B |
BIN
images/listjs-arrow-sort-inactive.png
Normal file
BIN
images/listjs-arrow-sort-inactive.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 629 B |
|
|
@ -47,7 +47,7 @@ async function chatgpt_isIdle() {
|
|||
|
||||
function chatgpt_getRegenerateButton() {
|
||||
for (const mainSVG of document.querySelectorAll('main svg')) {
|
||||
if (mainSVG.querySelector('path[d*="M4.5 2.5C5.05228"]')) // regen icon found
|
||||
if (mainSVG.querySelector('path[d*="M3.07 10.876C3.623"]')) // regen icon found
|
||||
return mainSVG.parentNode.parentNode;
|
||||
}
|
||||
}
|
||||
|
|
@ -120,7 +120,8 @@ function addCustomDiv(prompt_action,tabId) {
|
|||
style.innerHTML += "#mzta-model_warn{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);max-height:100%px;min-width:30%;max-width:50%;padding:3px;border-radius:5px;text-align:center;background-color:#FFBABA;border:1px solid;font-size:13px;color:#D8000C;display:none;}";
|
||||
style.innerHTML += "#mzta-btn_gpt35 {background-color: #007bff;border: none;color: white;padding: 2px 4px;text-align: center;text-decoration: none;display: none;font-size: 13px;margin-left: 4px;transition-duration: 0.4s;cursor: pointer;border-radius: 2px;}";
|
||||
style.innerHTML += "#mzta-status-page{position:fixed;bottom:0;left:0;padding-left:5px;font-size:13px;font-style:italic;text-decoration:underline;color:#919191;}";
|
||||
style.innerHTML += "#mzta-status-page:hover{color:#007bff;}";
|
||||
style.innerHTML += "#mzta-force-completion{cursor:pointer;position:fixed;bottom:0;right:0;padding-right:5px;font-size:13px;font-style:italic;text-decoration:underline;color:#919191;}";
|
||||
style.innerHTML += "#mzta-status-page:hover, #mzta-force-completion:hover{color:#007bff;}";
|
||||
style.innerHTML += "#mzta-custom_text{padding:10px;width:auto;max-width:80%;height:auto;max-height:80%;border-radius:5px;overflow:auto;position:fixed;top:50%;left:50%;display:none;transform:translate(-50%,-50%);text-align:center;background:#333;color:white;border:3px solid white;}";
|
||||
style.innerHTML += "#mzta-custom_loading{height:50px;display:none;}";
|
||||
style.innerHTML += "#mzta-custom_textarea{color:black;padding:1px;font-size:15px;width:100%;}";
|
||||
|
|
@ -155,6 +156,16 @@ function addCustomDiv(prompt_action,tabId) {
|
|||
status_page_div.innerHTML = '<a href="https://micz.it/thunderdbird-addon-thunderai/status/">'+ mztaStatusPageDesc +'</a>';
|
||||
fixedDiv.appendChild(status_page_div);
|
||||
|
||||
//force completion
|
||||
var force_completion_div = document.createElement('div');
|
||||
force_completion_div.id = 'mzta-force-completion';
|
||||
force_completion_div.innerHTML = mztaForceCompletionDesc;
|
||||
force_completion_div.title = mztaForceCompletionTitle;
|
||||
force_completion_div.addEventListener('click', function() {
|
||||
operation_done();
|
||||
});
|
||||
fixedDiv.appendChild(force_completion_div);
|
||||
|
||||
// span for the text
|
||||
var curr_msg = document.createElement('span');
|
||||
curr_msg.id='mzta-curr_msg';
|
||||
|
|
@ -275,6 +286,7 @@ function operation_done(){
|
|||
document.getElementById('mzta-curr_msg').innerHTML = browser.i18n.getMessage("chatgpt_win_job_completed")+"<br>";
|
||||
document.getElementById('mzta-btn_ok').style.display = 'inline';
|
||||
document.getElementById('mzta-loading').style.display = 'none';
|
||||
document.getElementById('mzta-force-completion').style.display = 'none';
|
||||
chatpgt_scrollToBottom();
|
||||
}
|
||||
|
||||
|
|
|
|||
103
js/mzta-menus.js
103
js/mzta-menus.js
|
|
@ -18,14 +18,15 @@
|
|||
|
||||
// Some original methods are derived from https://github.com/ali-raheem/Aify/blob/cfadf52f576b7be3720b5b73af7c8d3129c054da/plugin/html/actions.js
|
||||
|
||||
import { defaultPrompts } from './mzta-prompts.js';
|
||||
import { getLanguageDisplayName } from './mzta-utils.js'
|
||||
import { getPrompts } from './mzta-prompts.js';
|
||||
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay } from './mzta-utils.js'
|
||||
|
||||
export class mzta_Menus {
|
||||
|
||||
allPrompts = [];
|
||||
openChatGPT = null;
|
||||
menu_context_compose = 'compose_action_menu';
|
||||
menu_context_display = 'message_display_action_menu';
|
||||
menu_context_compose = null;
|
||||
menu_context_display = null;
|
||||
menu_listeners = {};
|
||||
|
||||
rootMenu = [
|
||||
|
|
@ -33,16 +34,35 @@ export class mzta_Menus {
|
|||
];
|
||||
|
||||
constructor(openChatGPT) {
|
||||
this.menu_context_compose = getMenuContextCompose();
|
||||
this.menu_context_display = getMenuContextDisplay();
|
||||
this.openChatGPT = openChatGPT;
|
||||
defaultPrompts.forEach((prompt) => {
|
||||
this.allPrompts = [];
|
||||
this.listener = this.listener.bind(this);
|
||||
}
|
||||
|
||||
|
||||
async initialize() {
|
||||
this.allPrompts = [];
|
||||
this.rootMenu = [];
|
||||
this.menu_listeners = {};
|
||||
this.allPrompts = await getPrompts(true);
|
||||
this.allPrompts.forEach((prompt) => {
|
||||
this.addAction(prompt)
|
||||
});
|
||||
//this.addMenu(this.rootMenu);
|
||||
}
|
||||
|
||||
async reload(){
|
||||
await browser.menus.removeAll().catch(error => {
|
||||
console.error(">>>>>>>> ERROR removing the menus: ", error);
|
||||
});
|
||||
this.removeClickListener();
|
||||
this.loadMenus();
|
||||
}
|
||||
|
||||
addAction = (curr_prompt) => {
|
||||
|
||||
let curr_menu_entry = {id: curr_prompt.id };
|
||||
let curr_menu_entry = {id: curr_prompt.id, is_default: curr_prompt.is_default, name: curr_prompt.name};
|
||||
|
||||
const getHighlight = async () => {
|
||||
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
|
|
@ -56,7 +76,7 @@ export class mzta_Menus {
|
|||
const msg_text = await getHighlight();
|
||||
|
||||
//check if a selection is needed
|
||||
if(curr_prompt.need_selected && (msg_text.selection==='')){
|
||||
if(String(curr_prompt.need_selected) == "1" && (msg_text.selection==='')){
|
||||
//A selection is needed, but nothing is selected!
|
||||
//alert(browser.i18n.getMessage('prompt_selection_needed'));
|
||||
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
|
|
@ -75,7 +95,7 @@ export class mzta_Menus {
|
|||
let prefs = await browser.storage.sync.get({default_chatgpt_lang: getLanguageDisplayName(browser.i18n.getUILanguage())});
|
||||
let chatgpt_lang = prefs.default_chatgpt_lang;
|
||||
|
||||
var fullPrompt = curr_prompt.text + (curr_prompt.need_signature ? " " + await this.getDefaultSignature():"") + " " + browser.i18n.getMessage("prompt_lang") + chatgpt_lang + ". \"" + body_text + "\" ";
|
||||
var fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await this.getDefaultSignature():"") + " " + browser.i18n.getMessage("prompt_lang") + chatgpt_lang + ". \"" + body_text + "\" ";
|
||||
|
||||
switch(curr_prompt.id){
|
||||
case 'prompt_translate_this':
|
||||
|
|
@ -105,47 +125,66 @@ export class mzta_Menus {
|
|||
}
|
||||
}
|
||||
|
||||
loadMenus() {
|
||||
this.addMenu(this.rootMenu);
|
||||
let listeners = this.menu_listeners;
|
||||
browser.menus.onClicked.addListener((info, tab) => {
|
||||
listeners[info.menuItemId] && listeners[info.menuItemId] (info, tab);
|
||||
});
|
||||
async loadMenus() {
|
||||
await this.initialize();
|
||||
await this.addMenu(this.rootMenu);
|
||||
this.addClickListener();
|
||||
}
|
||||
|
||||
addMenu = (menu, root = null) => {
|
||||
for (let item of menu) {
|
||||
let {id, menu, act} = item;
|
||||
listener(info, tab) {
|
||||
let listeners = this.menu_listeners;
|
||||
if (listeners[info.menuItemId]) {
|
||||
listeners[info.menuItemId](info, tab);
|
||||
}
|
||||
}
|
||||
|
||||
browser.menus.create({
|
||||
id: id,
|
||||
title: this.getCustomTextAttribute(id) + browser.i18n.getMessage(id),
|
||||
contexts: this.getContexts(id),
|
||||
parentId: root
|
||||
});
|
||||
addClickListener() {
|
||||
browser.menus.onClicked.addListener(this.listener);
|
||||
}
|
||||
|
||||
removeClickListener() {
|
||||
browser.menus.onClicked.removeListener(this.listener);
|
||||
}
|
||||
|
||||
addMenu = async (menu, root = null) => {
|
||||
for (let item of menu) {
|
||||
let {id, is_default, name, menu, act} = item;
|
||||
|
||||
await new Promise(resolve =>
|
||||
browser.menus.create({
|
||||
id: id,
|
||||
title: this.getCustomTextAttribute(id) + is_default == 1 ? (browser.i18n.getMessage(id) || name) : name,
|
||||
contexts: this.getContexts(id),
|
||||
parentId: root
|
||||
},
|
||||
resolve
|
||||
)
|
||||
);
|
||||
|
||||
if (act) {
|
||||
this.menu_listeners[id] = act;
|
||||
}
|
||||
|
||||
if (menu) {
|
||||
this.addMenu(menu, id);
|
||||
await this.addMenu(menu, id);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
getContexts(id){
|
||||
const curr_prompt = defaultPrompts.find(p => p.id === id);
|
||||
//console.log(">>>>>>>>> id: " + id);
|
||||
const curr_prompt = this.allPrompts.find(p => p.id === id);
|
||||
//console.log(">>>>>>>>>> curr_prompt: " + JSON.stringify(curr_prompt));
|
||||
if (!curr_prompt) {
|
||||
return [];
|
||||
}
|
||||
switch(curr_prompt.type){
|
||||
case 0:
|
||||
switch(String(curr_prompt.type)){
|
||||
case "0":
|
||||
return [this.menu_context_compose, this.menu_context_display];
|
||||
case 1:
|
||||
case "1":
|
||||
return [this.menu_context_display];
|
||||
case 2:
|
||||
case "2":
|
||||
return [this.menu_context_compose];
|
||||
default:
|
||||
return [];
|
||||
|
|
@ -154,11 +193,11 @@ export class mzta_Menus {
|
|||
}
|
||||
|
||||
getCustomTextAttribute(id){
|
||||
const curr_prompt = defaultPrompts.find(p => p.id === id);
|
||||
const curr_prompt = this.allPrompts.find(p => p.id === id);
|
||||
if (!curr_prompt) {
|
||||
return "";
|
||||
}
|
||||
if(curr_prompt.need_custom_text === 1){
|
||||
if(String(curr_prompt.need_custom_text) === "1"){
|
||||
return "*";
|
||||
}else{
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -16,9 +16,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Modified version derived from https://github.com/ali-raheem/Aify/blob/13ff87583bc520fb80f555ab90a90c5c9df797a7/plugin/html/globals.js
|
||||
// Modified prompts text derived from https://github.com/ali-raheem/Aify/blob/13ff87583bc520fb80f555ab90a90c5c9df797a7/plugin/html/globals.js
|
||||
|
||||
/* Types (type attribute):
|
||||
/* ================= PROMPTS PROPERTIES ========================================
|
||||
|
||||
================ BASE PROPERTIES
|
||||
|
||||
Types (type attribute):
|
||||
0: always show (when composing a part of the text must be selected if need_selected = 1)
|
||||
1: show when reading an email
|
||||
2: show when composing a mail (a part of the text must be selected if need_selected = 1)
|
||||
|
|
@ -39,14 +43,166 @@
|
|||
Custom Text (need_custom_text attribute):
|
||||
0: No custom text needed
|
||||
1: Custom text needed
|
||||
|
||||
================ USER PROPERTIES
|
||||
Enabled (enabled attribute):
|
||||
0: Disabled
|
||||
1: Enabled
|
||||
|
||||
Position Display Message (position_display attribute):
|
||||
<num>: position number
|
||||
|
||||
Position Compose Message (position_compose attribute):
|
||||
<num>: position number
|
||||
|
||||
*/
|
||||
|
||||
export const defaultPrompts = [
|
||||
{ id: 'prompt_reply', name: "__MSG_prompt_reply__", text: "Reply to the following email.", type: 1, action: 1, need_selected: 0, need_signature: 1, need_custom_text: 1 }, // need_custom_text set to 1 only for testing
|
||||
{ id: 'prompt_rewrite_polite', name: "__MSG_prompt_rewrite_polite__", text: "Rewrite the following text to be more polite. Reply with only the re-written text and with no extra comments or other text.", type: 2, action: 2, need_selected: 1, need_signature: 0, need_custom_text: 0 },
|
||||
{ id: 'prompt_rewrite_formal', name: "__MSG_prompt_rewrite_formal__", text: "Rewrite the following text to be more formal. Reply with only the re-written text and with no extra comments or other text.", type: 2, action: 2, need_selected: 1, need_signature: 0, need_custom_text: 0 },
|
||||
{ id: 'prompt_classify', name: "__MSG_prompt_classify__", text: "Classify the following text in terms of Politeness, Warmth, Formality, Assertiveness, Offensiveness giving a percentage for each category. Reply with only the category and score with no extra comments or other text.", type: 0, action: 0, need_selected: 0, need_signature: 0, need_custom_text: 0 },
|
||||
{ id: 'prompt_summarize_this', name: "__MSG_prompt_summarize_this__", text: "Summarize the following email into a bullet point list.", type: 0, action: 0, need_selected: 0, need_signature: 0, need_custom_text: 0 },
|
||||
{ id: 'prompt_translate_this', name: "__MSG_prompt_translate_this__", text: "Translate the following email in ", type: 0, action: 0, need_selected: 0, need_signature: 0, need_custom_text: 0 },
|
||||
{ id: 'prompt_this', name: "__MSG_prompt_this__", text: "Reply with only the needed text and with no extra comments or other text.", type: 2, action: 2, need_selected: 1, need_signature: 0, need_custom_text: 0 },
|
||||
const defaultPrompts = [
|
||||
{
|
||||
id: 'prompt_reply',
|
||||
name: "__MSG_prompt_reply__",
|
||||
text: "Reply to the following email.",
|
||||
type: "1",
|
||||
action: "1",
|
||||
need_selected: "0",
|
||||
need_signature: "1",
|
||||
need_custom_text: "0",
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'prompt_rewrite_polite',
|
||||
name: "__MSG_prompt_rewrite_polite__",
|
||||
text: "Rewrite the following text to be more polite. Reply with only the re-written text and with no extra comments or other text.",
|
||||
type: "2",
|
||||
action: "2",
|
||||
need_selected: "1",
|
||||
need_signature: "0",
|
||||
need_custom_text: "0",
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'prompt_rewrite_formal',
|
||||
name: "__MSG_prompt_rewrite_formal__",
|
||||
text: "Rewrite the following text to be more formal. Reply with only the re-written text and with no extra comments or other text.",
|
||||
type: "2",
|
||||
action: "2",
|
||||
need_selected: "1",
|
||||
need_signature: "0",
|
||||
need_custom_text: "0",
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'prompt_classify',
|
||||
name: "__MSG_prompt_classify__",
|
||||
text: "Classify the following text in terms of Politeness, Warmth, Formality, Assertiveness, Offensiveness giving a percentage for each category. Reply with only the category and score with no extra comments or other text.",
|
||||
type: "0",
|
||||
action: "0",
|
||||
need_selected: "0",
|
||||
need_signature: "0",
|
||||
need_custom_text: "0",
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'prompt_summarize_this',
|
||||
name: "__MSG_prompt_summarize_this__",
|
||||
text: "Summarize the following email into a bullet point list.",
|
||||
type: "0",
|
||||
action: "0",
|
||||
need_selected: "0",
|
||||
need_signature: "0",
|
||||
need_custom_text: "0",
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'prompt_translate_this',
|
||||
name: "__MSG_prompt_translate_this__",
|
||||
text: "Translate the following email in ",
|
||||
type: "0",
|
||||
action: "0",
|
||||
need_selected: "0",
|
||||
need_signature: "0",
|
||||
need_custom_text: "0",
|
||||
is_default: "1",
|
||||
},
|
||||
{
|
||||
id: 'prompt_this',
|
||||
name: "__MSG_prompt_this__",
|
||||
text: "Reply with only the needed text and with no extra comments or other text.",
|
||||
type: "2",
|
||||
action: "2",
|
||||
need_selected: "1",
|
||||
need_signature: "0",
|
||||
need_custom_text: "0",
|
||||
is_default: "1",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
export async function getPrompts(filterDisabled = false){
|
||||
const defaultPrompts = await getDefaultPrompts_withProps();
|
||||
const customPrompts = await getCustomPrompts();
|
||||
let output = defaultPrompts.concat(customPrompts);
|
||||
if(filterDisabled){
|
||||
output = output.filter(obj => obj.enabled != 0);
|
||||
}
|
||||
output.sort((a, b) => a.id.localeCompare(b.id));
|
||||
for(let i=1; i<=output.length; i++){
|
||||
output[i-1].idnum = i;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
async function getDefaultPrompts_withProps() {
|
||||
let prefs = await browser.storage.sync.get({_default_prompts_properties: null}); //production
|
||||
let defaultPrompts_prop = [...defaultPrompts];
|
||||
if(prefs._default_prompts_properties === null){ // no default prompts properties saved
|
||||
let pos = 1;
|
||||
defaultPrompts_prop.forEach((prompt) => {
|
||||
prompt.position_display = pos;
|
||||
prompt.position_compose = pos;
|
||||
prompt.enabled = 1;
|
||||
pos++;
|
||||
})
|
||||
} else { // we have saved default prompts properties
|
||||
let pos = 1000;
|
||||
defaultPrompts_prop.forEach((prompt) => {
|
||||
if(prefs._default_prompts_properties?.[prompt.id]){
|
||||
prompt.position_compose = prefs._default_prompts_properties[prompt.id].position_compose;
|
||||
prompt.position_display = prefs._default_prompts_properties[prompt.id].position_display;
|
||||
prompt.enabled = prefs._default_prompts_properties[prompt.id].enabled;
|
||||
}else{
|
||||
prompt.position_display = pos;
|
||||
prompt.position_compose = pos;
|
||||
prompt.enabled = 1;
|
||||
pos++;
|
||||
}
|
||||
})
|
||||
}
|
||||
return defaultPrompts_prop;
|
||||
}
|
||||
|
||||
|
||||
async function getCustomPrompts() {
|
||||
let prefs = await browser.storage.sync.get({_custom_prompt: null});
|
||||
if(prefs._custom_prompt === null){
|
||||
return [];
|
||||
} else {
|
||||
return prefs._custom_prompt;
|
||||
}
|
||||
}
|
||||
|
||||
export async function setDefaultPromptsProperties(prompts) {
|
||||
let default_prompts_properties = {};
|
||||
prompts.forEach((prompt) => {
|
||||
default_prompts_properties[prompt.id] = {position_compose: prompt.position_compose, position_display: prompt.position_display, enabled: prompt.enabled};
|
||||
});
|
||||
console.log('>>>>>>>>>>>>>> default_prompts_properties: ' + JSON.stringify(default_prompts_properties));
|
||||
await browser.storage.sync.set({_default_prompts_properties: default_prompts_properties});
|
||||
}
|
||||
|
||||
|
||||
export async function setCustomPrompts(prompts) {
|
||||
await browser.storage.sync.set({_custom_prompt: prompts});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export const getMenuContextCompose = () => 'compose_action_menu';
|
||||
export const getMenuContextDisplay = () => 'message_display_action_menu';
|
||||
|
||||
|
||||
export function getLanguageDisplayName(languageCode) {
|
||||
const languageDisplay = new Intl.DisplayNames([languageCode], {type: 'language'});
|
||||
|
|
|
|||
|
|
@ -113,6 +113,10 @@ messenger.runtime.onMessage.addListener(async (message, sender, sendResponse) =>
|
|||
await setBody(message.tabId, original_html);
|
||||
await setBody(message.tabId, modified_html);
|
||||
break;
|
||||
case 'reload_menus':
|
||||
await menus.reload();
|
||||
console.log('>>>>>>>>>>>>>>>>> Reloaded menus');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -162,6 +166,8 @@ async function openChatGPT(promptText, action, curr_tabId, do_custom_text = 0) {
|
|||
});
|
||||
|
||||
let pre_script = `let mztaStatusPageDesc="`+ browser.i18n.getMessage("prefs_status_page") +`";
|
||||
let mztaForceCompletionDesc="`+ browser.i18n.getMessage("chatgpt_force_completion") +`";
|
||||
let mztaForceCompletionTitle="`+ browser.i18n.getMessage("chatgpt_force_completion_title") +`";
|
||||
let mztaDoCustomText=`+ do_custom_text +`;
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,16 @@
|
|||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: rgb(35, 34, 43);
|
||||
color: rgb(251, 251, 254);
|
||||
}
|
||||
|
||||
a:link { color: #409EFF; }
|
||||
a:visited { color: #409EFF; }
|
||||
a:hover { color: #66B1FF; }
|
||||
a:active { color: #66B1FF; }
|
||||
|
||||
}
|
||||
|
||||
div#miczDescription{
|
||||
padding:0px 15px 0px 15px;
|
||||
font-size: 13px;
|
||||
|
|
@ -71,4 +84,10 @@ input#chatgpt_win_height{
|
|||
span.dims_label{
|
||||
width: 75px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#btn_custom_prompts{
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
|
@ -71,6 +71,9 @@
|
|||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="btn_custom_prompts">
|
||||
<button id="btnManagePrompts">__MSG_prefs_OptionText_btnManagePrompts__</button>
|
||||
</div>
|
||||
<div id="miczDescription">
|
||||
<h1>__MSG_prefsInfoTitle__</h1>
|
||||
<p>__MSG_prefsInfoDesc_1__<br/>
|
||||
|
|
|
|||
|
|
@ -93,4 +93,16 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
document.querySelectorAll(".option-input").forEach(element => {
|
||||
element.addEventListener("change", saveOptions);
|
||||
});
|
||||
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) => {
|
||||
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')});
|
||||
}
|
||||
})
|
||||
});
|
||||
}, { once: true });
|
||||
|
|
|
|||
|
|
@ -1,3 +1,16 @@
|
|||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: rgb(35, 34, 43);
|
||||
color: rgb(251, 251, 254);
|
||||
}
|
||||
|
||||
a:link { color: #409EFF; }
|
||||
a:visited { color: #409EFF; }
|
||||
a:hover { color: #66B1FF; }
|
||||
a:active { color: #66B1FF; }
|
||||
|
||||
}
|
||||
|
||||
div#miczRelNotes{
|
||||
padding: 10px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,13 @@
|
|||
<h2>Version 1.1.0 - ??/??/2024</h2>
|
||||
<ul>
|
||||
<li>A prompt can be configured to request additional text from the user.</li>
|
||||
<li>...</li>
|
||||
<li>Added custom prompts. See more info <a href="https://micz.it/thunderdbird-addon-thunderai/custom-prompts/">here</a>.</li>
|
||||
<li>Dark mode added.</li>
|
||||
</ul>
|
||||
<h2>Version 1.0.6 - 08/05/2024</h2>
|
||||
<ul>
|
||||
<li>Correctly handling a change in the ChatGPT web interface. See issue <a href="https://github.com/micz/ThunderAI/issues/43">#43</a></li>
|
||||
<li>Added a button to force the completion to display the 'Use last answer' button if ChatGPT has finished its work but the button has not appeared.</li>
|
||||
</ul>
|
||||
<h2>Version 1.0.5 - 03/05/2024</h2>
|
||||
<ul>
|
||||
|
|
|
|||
Loading…
Reference in a new issue