为什么我的Firefox扩展程序只能在一个聊天页面上添加上传文件按钮?

我正在尝试为基于FireFox/Gecko的浏览器开发一个扩展程序,以便在chat.openai.com上添加一个上传文件的按钮。当我添加我的扩展程序时,它只会在刷新一个聊天页面时添加按钮。如果我转到过去的聊天,它就不会添加按钮。(顺便说一下,我在ChatGPT的帮助下编写了这段代码,哈哈)。

manifest.json:

{    "manifest_version": 3,    "name": "ChatGPT File Upload",    "version": "1.0",    "description": "Adds a button to upload files into ChatGPT. (NOT for images, videos, Word Documents, or other non-raw-text files. Please use .txt, .js, .py, .html, .css, .json, and .csv.",    "permissions": [      "scripting",      "https://chat.openai.com/*"    ],    "action": {      "default_icon": {        "128": "icon128.png",        "256": "icon128.png"      }    },    "icons": {      "128": "icon128.png",      "256": "icon256.png"    },    "content_scripts": [      {        "matches": ["https://chat.openai.com/*"],        "js": ["content.js"]      }    ],    "background": {      "scripts": ["background.js"],      "service_worker": "background.js"    }  }  

background.js:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {    if (changeInfo.url && changeInfo.url.startsWith('https://chat.openai.com/')) {      chrome.scripting.executeScript({        target: { tabId: tabId },        files: ['content.js']      });    }  });  

content.js:

console.log("Content script loaded.");// This script will be injected into chat.openai.com pages// You can add your desired functionality here// Create the buttonconst button = document.createElement('button');button.innerText = '📂 Submit File';button.style.backgroundColor = '#35393d';button.style.color = 'white';button.style.padding = '5px';button.style.border = '1px solid #6b6458';button.style.borderRadius = '5px';button.style.margin = '5px';button.style.width = '180px';// Create a container div for centeringconst containerDiv = document.createElement('div');containerDiv.style.display = 'flex';containerDiv.style.justifyContent = 'center';// Append the button to the container divcontainerDiv.appendChild(button);// Find the target elementconst targetElement = document.querySelector("div.relative.flex.h-full.max-w-full.flex-1.overflow-hidden > div > main > div.absolute.bottom-0 > form > div > div:nth-child(1)");// Insert the container div before the target elementtargetElement.parentNode.insertBefore(containerDiv, targetElement);// Add click event listener to the buttonbutton.addEventListener('click', async () => {  // Create the file input element  const fileInput = document.createElement('input');  fileInput.type = 'file';  fileInput.accept = '.txt, .js, .py, .html, .css, .json, .csv';  // Handle file selection  fileInput.addEventListener('change', async (event) => {    const file = event.target.files[0];    if (file) {      const reader = new FileReader();      reader.onload = async (e) => {        const fileContent = e.target.result;        const chunkSize = 15000;        const chunks = [];        // Split file content into chunks        for (let i = 0; i < fileContent.length; i += chunkSize) {          const chunk = fileContent.slice(i, i + chunkSize);          chunks.push(chunk);        }        // Submit each chunk to the conversation        for (let i = 0; i < chunks.length; i++) {          const chunk = chunks[i];          const part = i + 1;          const filename = file.name;          await submitConversation(chunk, part, filename);        }      };      reader.readAsText(file);    }  });  // Trigger file input click event  fileInput.click();});// Submit conversation functionasync function submitConversation(text, part, filename) {  const textarea = document.querySelector("textarea[tabindex='0']");  const enterKeyEvent = new KeyboardEvent('keydown', {    bubbles: true,    cancelable: true,    keyCode: 13,  });  textarea.value = `Part ${part} of ${filename}:\n\n${text}`;  textarea.dispatchEvent(enterKeyEvent);}

我在网上查看了不同的background.js文件,但似乎没有一个能解决我的问题。我对开发非常新手,所以在这类事情上我基本上是迷失的。


回答:

在这里扩展我的评论。

导航可以分为两种类型

  1. 完整页面刷新
  2. 基于JavaScript的页面加载

在第一种情况下,扩展程序会执行其任务并加载按钮,但在第二种情况下,如果Web应用程序用新元素加载整个页面,那么你的“编辑”元素将被新元素替换。

据我所知,你可以通过两种方式解决这个问题

  1. 监听导航变化
  2. 使用Mutation Observer

监听导航事件

如果Web应用程序更改了地址栏中的地址,那么你可以监听该事件,并在按钮不存在时添加按钮。https://developer.mozilla.org/en-US/docs/Web/API/Navigation/navigate_event

navigation.addEventListener("navigate", (event) => {  checkAndInjectButton()})

Mutation Observer

如果由于某些原因你无法检测到Web应用程序中的导航变化,那么你可以监听DOM中的变化,并根据事件做出反应。

Mutation Observer会跟踪属性、子节点和子树,因此如果对目标元素进行了任何更改,你的脚本将获得回调。

// Select the node that will be observed for mutationsconst targetElement = document.querySelector("div.relative.flex.h-full.max-w-full.flex-1.overflow-hidden > div > main > div.absolute.bottom-0 > form > div > div:nth-child(1)");// Options for the observer (which mutations to observe)const config = { attributes: true, childList: true, subtree: true };// Callback function to execute when mutations are observedconst callback = (mutationList, observer) => {  checkAndInjectButton();};// Create an observer instance linked to the callback functionconst observer = new MutationObserver(callback);// Start observing the target node for configured mutationsobserver.observe(targetElement, config);// If you need to stop observingobserver.disconnect();

这两种解决方案都将应用到你的content.js

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注