From 6f9d80f29ed40c3972f014759a4d1bbbc22aadfe Mon Sep 17 00:00:00 2001 From: mic Date: Wed, 17 Apr 2024 21:12:42 +0200 Subject: [PATCH] using system menus. fixes #23 --- js/mzta-compose-script.js | 4 + js/mzta-menus.js | 156 ++++++++++++++++++++++++++++++++++++++ manifest.json | 8 +- mzta-background.js | 6 +- 4 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 js/mzta-menus.js diff --git a/js/mzta-compose-script.js b/js/mzta-compose-script.js index 36def3d2..e9c75643 100644 --- a/js/mzta-compose-script.js +++ b/js/mzta-compose-script.js @@ -107,6 +107,10 @@ switch (message.command) { alert(browser.i18n.getMessage('msg_prompt_too_long')); break; + case 'sendAlert': + alert(message.message); + break; + default: // do nothing break; diff --git a/js/mzta-menus.js b/js/mzta-menus.js new file mode 100644 index 00000000..4abdb395 --- /dev/null +++ b/js/mzta-menus.js @@ -0,0 +1,156 @@ +/* + * 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 . + */ + +// 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' + +export class mzta_Menus { + + openChatGPT = null; + menu_context_compose = 'compose_action_menu'; + menu_context_display = 'message_display_action_menu'; + menu_listeners = {}; + + rootMenu = [ + //{ id: 'ItemC', act: (info, tab) => { console.log('ItemC', info, tab, info.menuItemId); alert('ItemC') } }, + ]; + + constructor(openChatGPT) { + this.openChatGPT = openChatGPT; + defaultPrompts.forEach((prompt) => { + this.addAction(prompt) + }); + //this.addMenu(this.rootMenu); + } + + addAction = (curr_prompt) => { + + let curr_menu_entry = {id: curr_prompt.id }; + + const getHighlight = async () => { + const tabs = await browser.tabs.query({ active: true, currentWindow: true }); + return {tabId: tabs[0].id, + selection: await browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedText" }), + text: await browser.tabs.sendMessage(tabs[0].id, { command: "getTextOnly" }) + }; + }; + + curr_menu_entry.act = async () => { + const msg_text = await getHighlight(); + + //check if a selection is needed + if(curr_prompt.need_selected && (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 }); + browser.tabs.sendMessage(tabs[0].id, { command: "sendAlert", message : browser.i18n.getMessage('prompt_selection_needed') }); + return; + } + + var body_text = ''; + if (msg_text.selection!=='') { + body_text = msg_text.selection.replace(/\s+/g, ' ').trim(); + } else { + body_text = msg_text.text.replace(/\s+/g, ' ').trim(); + } + //open chatgpt window + //console.log("Click menu item..."); + 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 + "\" "; + + switch(curr_prompt.id){ + case 'prompt_translate_this': + fullPrompt = curr_prompt.text + chatgpt_lang + ". \"" + body_text + "\" "; + break; + case 'prompt_reply': + fullPrompt += "Do not add the subject line to the response." + break; + default: + break; + } + + const tabs = await browser.tabs.query({ active: true, currentWindow: true }); + //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); + }; + this.rootMenu.push(curr_menu_entry); + }; + + async getDefaultSignature(){ + let prefs = await browser.storage.sync.get({default_sign_name: ''}); + if(prefs.default_sign_name===''){ + return ''; + }else{ + return "Sign the message as " + prefs.default_sign_name + "."; + } + } + + loadMenus() { + this.addMenu(this.rootMenu); + let listeners = this.menu_listeners; + browser.menus.onClicked.addListener((info, tab) => { + listeners[info.menuItemId] && listeners[info.menuItemId] (info, tab); + }); + } + + addMenu = (menu, root = null) => { + for (let item of menu) { + let {id, menu, act} = item; + + browser.menus.create({ + id: id, + title: browser.i18n.getMessage(id), + contexts: this.getContexts(id), + parentId: root + }); + + if (act) { + this.menu_listeners[id] = act; + } + + if (menu) { + this.addMenu(menu, id); + } + } + + }; + + getContexts(id){ + const curr_prompt = defaultPrompts.find(p => p.id === id); + if (!curr_prompt) { + return []; + } + switch(curr_prompt.type){ + case 0: + return [this.menu_context_compose, this.menu_context_display]; + case 1: + return [this.menu_context_display]; + case 2: + return [this.menu_context_compose]; + default: + return []; + } + + } + + +} \ No newline at end of file diff --git a/manifest.json b/manifest.json index 87bd29bf..90cb7a98 100644 --- a/manifest.json +++ b/manifest.json @@ -11,14 +11,14 @@ } }, "message_display_action": { - "default_popup": "messageMenu/mzta-msgmenu.html", "default_title": "__MSG_menu_title__", - "default_icon": "images/icon-32px.png" + "default_icon": "images/icon-32px.png", + "type": "menu" }, "compose_action": { - "default_popup": "messageMenu/mzta-msgmenu.html", "default_title": "__MSG_menu_title__", - "default_icon": "images/icon-32px.png" + "default_icon": "images/icon-32px.png", + "type":"menu" }, "permissions": [ "compose", diff --git a/mzta-background.js b/mzta-background.js index 653b15e0..b409ec32 100644 --- a/mzta-background.js +++ b/mzta-background.js @@ -18,6 +18,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'; var createdWindowID = null; @@ -41,7 +42,6 @@ for (let messageTab of messageTabs) { }) } - messenger.runtime.onMessage.addListener(async (message, sender, sendResponse) => { // Check what type of message we have received and invoke the appropriate // handler function. @@ -169,3 +169,7 @@ function checkScreenDimensions(prefs){ return prefs; } + +// Menus handling +const menus = new mzta_Menus(openChatGPT); +menus.loadMenus(); \ No newline at end of file