diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4665973..e3a87a08 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,8 @@
[OpenAI Comp API] Added a new integration method to use a local LLM via an API compatible with OpenAI's API specifications [#126].
Custom Prompts storage space incremented to 5MB, using storage.local. Added also the total occupied space at the bottom of the Custom Prompts page [#129].
[ChatGPT Web] Updated the information in the option page.
+ A new dynamic menu for selecting prompts has been added. In addition to clicking the ThunderAI button, you can now use the CTRL+ALT+A keyboard shortcut [#130].
+ Added an option to order alphabetically the prompts in the menu.
...
Version 2.1.4 - 11/09/2024
diff --git a/README.md b/README.md
index fea84788..6e6d1440 100644
--- a/README.md
+++ b/README.md
@@ -56,5 +56,6 @@ Are you using this addon in your Thunderbird?
The specific references are described in the corresponding source files.
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 6d2347ee..d5d5f2b2 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -327,6 +327,14 @@
"message": "To use this integration, you need to set up a local server compatible with the OpenAI API, like LM Studio. Once the server is running, enter its address in the designated field within the application. To ensure proper communication between ThunderAI and the local server remember to set the CORS settings correctly.",
"description": ""
},
+ "prefsInfoDesc_5": {
+ "message": "Remember that you can open the ThunderAI menu using the keyboard shortcut CTRL+ALT+A.",
+ "description": ""
+ },
+ "prefsInfoDesc_6": {
+ "message": "You can change the shortcut clicking on the cogwheel icon at the top right of this page and choosing \"Manage Extension Shortcut\".",
+ "description": ""
+ },
"prefsDonation_1": {
"message": "Do you like this addon?",
"description": ""
@@ -542,5 +550,25 @@
"StorageSpace": {
"message": "Total storage space occupied",
"description": ""
+ },
+ "SearchPrompt": {
+ "message": "Search prompts",
+ "description": ""
+ },
+ "prefs_OptionText_dynamic_menu_force_enter": {
+ "message": "Menu: immediate prompt send",
+ "description": ""
+ },
+ "prefs_OptionText_dynamic_menu_force_enter_info": {
+ "message": "If checked, using the keyboard shortcut CTRL+ALT+A will automatically send the hightlighted prompt from the menu. Otherwise, the prompt name will be displayed to the user, requiring another press of the Enter key to send it.",
+ "description": ""
+ },
+ "prefs_OptionText_dynamic_menu_order_alphabet": {
+ "message": "Menu: order alphabetically",
+ "description": ""
+ },
+ "prefs_OptionText_dynamic_menu_order_alphabet_info": {
+ "message": "If checked, the prompts in the menu will be ordered alphabetically.",
+ "description": ""
}
}
\ No newline at end of file
diff --git a/js/mzta-menus.js b/js/mzta-menus.js
index 9b709e19..a6c8fd96 100644
--- a/js/mzta-menus.js
+++ b/js/mzta-menus.js
@@ -19,7 +19,7 @@
// Some original methods are derived from https://github.com/ali-raheem/Aify/blob/cfadf52f576b7be3720b5b73af7c8d3129c054da/plugin/html/actions.js
import { getPrompts } from './mzta-prompts.js';
-import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay } from './mzta-utils.js'
+import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet } from './mzta-utils.js'
export class mzta_Menus {
@@ -33,6 +33,10 @@ export class mzta_Menus {
//{ id: 'ItemC', act: (info, tab) => { console.log('ItemC', info, tab, info.menuItemId); alert('ItemC') } },
];
+ shortcutMenu = [
+ //{ id: 'ItemD', label: 'LabelD' },
+ ];
+
constructor(openChatGPT) {
this.menu_context_compose = getMenuContextCompose();
this.menu_context_display = getMenuContextDisplay();
@@ -45,6 +49,7 @@ export class mzta_Menus {
async initialize() {
this.allPrompts = [];
this.rootMenu = [];
+ this.shortcutMenu = [];
this.menu_listeners = {};
this.allPrompts = await getPrompts(true);
this.allPrompts.sort((a, b) => a.name.localeCompare(b.name));
@@ -55,7 +60,7 @@ export class mzta_Menus {
async reload(){
await browser.menus.removeAll().catch(error => {
- console.error("[ThunderAI] ERROR removing the menus: ", error);
+ console.error("[ThunderAI] ERROR removing the menus: ", error);
});
this.removeClickListener();
this.loadMenus();
@@ -140,10 +145,23 @@ export class mzta_Menus {
}
}
+ loadShortcutMenu() {
+ this.shortcutMenu = [];
+ this.allPrompts.forEach((prompt) => {
+ this.addShortcutMenu(prompt);
+ });
+ }
+
+ addShortcutMenu(prompt) {
+ let curr_menu_entry = {id: prompt.id, label: i18nConditionalGet(prompt.name), type: prompt.type};
+ this.shortcutMenu.push(curr_menu_entry);
+ }
+
async loadMenus() {
await this.initialize();
await this.addMenu(this.rootMenu);
this.addClickListener();
+ this.loadShortcutMenu();
}
listener(info, tab) {
@@ -219,4 +237,23 @@ export class mzta_Menus {
}
}
+
+ async executeMenuAction(id) {
+ // Retrieve the action callback from the menu listeners using the provided ID
+ const action = this.menu_listeners[id];
+
+ if (action) {
+ try {
+ // Execute the action callback
+ await action();
+ } catch (error) {
+ // Log any errors that occur during execution
+ console.error(`Error executing action for menu item ${id}:`, error);
+ }
+ } else {
+ // Warn if no action is found for the provided ID
+ console.warn(`No action found for menu item ID: ${id}`);
+ }
+ }
+
}
\ No newline at end of file
diff --git a/js/mzta-store.js b/js/mzta-store.js
new file mode 100644
index 00000000..1a12b15a
--- /dev/null
+++ b/js/mzta-store.js
@@ -0,0 +1,32 @@
+/*
+ * 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 .
+ */
+
+
+export const taStore = {
+
+ async setSessionData (key, value) {
+ let obj = {};
+ obj[key] = value;
+ await browser.storage.session.set(obj);
+ },
+
+ async getSessionData (key) {
+ let output = await browser.storage.session.get(key);
+ return output[key];
+ },
+};
\ No newline at end of file
diff --git a/js/tb115_segmenter/tb115_loader.js b/js/tb115_segmenter/tb115_loader.js
new file mode 100644
index 00000000..f5bbf28d
--- /dev/null
+++ b/js/tb115_segmenter/tb115_loader.js
@@ -0,0 +1,65 @@
+/*
+ * 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 .
+ */
+// Firefox 115 and, consequently, Thunderbird 115 are not compatible with Intl.Segmenter.
+// ChatGPT is using Intl.Segmenter, so we have to do something about it or it won't work...
+
+console.log("[ThunderAI] Intl.Segmenter: " + Intl.Segmenter);
+
+(function() {
+ if('Segmenter' in Intl){
+ console.log('[ThunderAI] TB128+ detected. Intl.Segmenter is already supported.');
+ return;
+ }
+ // Creates a
+
+