From 3906541bf9958054264cfc9392f5c34ba581889d Mon Sep 17 00:00:00 2001 From: Yatika Kain Date: Tue, 5 Nov 2024 18:50:22 +0530 Subject: [PATCH 1/2] Added Context Menu Feature --- extension/public/background.js | 100 +++++++++++++++++++ extension/public/contentScript.js | 13 +++ extension/public/manifest.json | 13 ++- extension/src/pages/answer/Answer.jsx | 16 ++- extension/src/pages/text_input/TextInput.jsx | 61 ++++++----- 5 files changed, 175 insertions(+), 28 deletions(-) create mode 100644 extension/public/background.js create mode 100644 extension/public/contentScript.js diff --git a/extension/public/background.js b/extension/public/background.js new file mode 100644 index 0000000..170b491 --- /dev/null +++ b/extension/public/background.js @@ -0,0 +1,100 @@ +// Create context menu on installation +chrome.runtime.onInstalled.addListener(() => { + chrome.contextMenus.create({ + id: "askExtension", + title: "Generate Quiz with Selected Text", + contexts: ["selection"] + }); + }); + + // Handle context menu clicks + chrome.contextMenus.onClicked.addListener(async (info, tab) => { + if (info.menuItemId === "askExtension" && info.selectionText) { + try { + // Store the selected text first + await chrome.storage.local.set({ + selectedText: info.selectionText + }); + + // Inject content script if needed + await chrome.scripting.executeScript({ + target: { tabId: tab.id }, + files: ["contentScript.js"] + }); + + // Send message to content script + await chrome.tabs.sendMessage(tab.id, { + selectedText: info.selectionText + }); + + // Open the popup + // Note: Chrome extensions can't programmatically open the popup, + // but we can show the user where to click + chrome.action.setPopup({ + popup: "src/popup/popup.html" + }); + + // Show a badge to indicate text was captured + chrome.action.setBadgeText({ + text: "!" + }); + chrome.action.setBadgeBackgroundColor({ + color: "#FF005C" + }); + + // Clear the badge after 2 seconds + setTimeout(() => { + chrome.action.setBadgeText({ text: "" }); + }, 2000); + + } catch (error) { + console.error("Error in context menu handler:", error); + } + } + }); + + // Listen for messages from content script + chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.type === "TEXT_SELECTED") { + chrome.storage.local.set({ + selectedText: request.text + }, () => { + console.log("Text saved to storage:", request.text); + sendResponse({ status: "success" }); + }); + return true; // Required for async sendResponse + } + }); + + //Clear badge when popup is opened + chrome.action.onClicked.addListener(() => { + chrome.action.setBadgeText({ text: "" }); + }); + +chrome.storage.onChanged.addListener((changes, namespace) => { + for (let [key, { oldValue, newValue }] of Object.entries(changes)) { + console.log( + `Storage key "${key}" in namespace "${namespace}" changed.`, + `Old value was "${oldValue}", new value is "${newValue}".` + ); + + // Store the key-value pair in local storage + chrome.storage.local.set({ [key]: newValue }, () => { + if (chrome.runtime.lastError) { + console.error("Error storing data:", chrome.runtime.lastError); + } else { + console.log(`Stored key-value pair: { ${key}: ${newValue} }`); + } + }); + } +}); + + + // Optional: Handle extension install/update + chrome.runtime.onInstalled.addListener((details) => { + if (details.reason === "install") { + console.log("Extension installed"); + } else if (details.reason === "update") { + console.log("Extension updated"); + } + }); \ No newline at end of file diff --git a/extension/public/contentScript.js b/extension/public/contentScript.js new file mode 100644 index 0000000..163f465 --- /dev/null +++ b/extension/public/contentScript.js @@ -0,0 +1,13 @@ +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.selectedText) { + generateQuestions(request.selectedText); + } + }); + + function generateQuestions(text) { + console.log("Generating questions for:", text); + chrome.storage.local.set({ "selectedText": text }, () => { + console.log('Questions stored in local storage:', text); + }); + } + \ No newline at end of file diff --git a/extension/public/manifest.json b/extension/public/manifest.json index 42e11f2..bf43333 100644 --- a/extension/public/manifest.json +++ b/extension/public/manifest.json @@ -3,7 +3,10 @@ "name": "EduAid: AI Quiz Generator", "version": "1.0", "description": "Generate quizzes with AI-powered questions.", - "permissions": ["activeTab", "storage","sidePanel", "contextMenus"], + "permissions": ["activeTab", "storage", "sidePanel", "contextMenus", "scripting"], + "background": { + "service_worker": "background.js" + }, "side_panel": { "default_path":"/src/pages/question/sidePanel.html" }, @@ -26,5 +29,11 @@ "resources": ["static/js/*", "static/css/*", "src/assets/*"], "matches": [""] } + ], + "content_scripts": [ + { + "matches": [""], + "js": ["contentScript.js"] + } ] -} \ No newline at end of file +} diff --git a/extension/src/pages/answer/Answer.jsx b/extension/src/pages/answer/Answer.jsx index 1f3501b..1625471 100644 --- a/extension/src/pages/answer/Answer.jsx +++ b/extension/src/pages/answer/Answer.jsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import ReactDOM from "react-dom"; import "../../index.css"; import logo from "../../assets/aossie_logo.webp"; @@ -15,7 +15,16 @@ const Answer = () => { const [isToggleOn, setIsToggleOn] = useState(1); const [mode, setMode] = useState("ask_question"); // Dropdown state - + + useEffect(() => { + chrome.storage.local.get(["selectedText"], (result) => { + if (result.selectedText) { + console.log("extension", result.selectedText); + setContext(result.selectedText); + localStorage.setItem("textContent", result.selectedText); + } + }); + },[]) // const toggleSwitch = () => { // window.location.href = "/src/pages/home/home.html"; @@ -112,6 +121,9 @@ const Answer = () => { console.error("Error:", error); } finally { setLoading(false); + chrome.storage.local.remove(["selectedText"], () => { + console.log("Chrome storage cleared"); + }); } }; diff --git a/extension/src/pages/text_input/TextInput.jsx b/extension/src/pages/text_input/TextInput.jsx index c583ad7..e2928ef 100644 --- a/extension/src/pages/text_input/TextInput.jsx +++ b/extension/src/pages/text_input/TextInput.jsx @@ -1,4 +1,4 @@ -import React, { useState, useRef } from "react"; +import React, { useState, useRef, useEffect } from "react"; import ReactDOM from "react-dom"; import "../../index.css"; import logo from "../../assets/aossie_logo.webp"; @@ -18,8 +18,19 @@ function Second() { const [docUrl, setDocUrl] = useState(''); const [isToggleOn, setIsToggleOn] = useState(0); + useEffect(() => { + chrome.storage.local.get(["selectedText"], (result) => { + if (result.selectedText) { + console.log("extension", result.selectedText); + setText(result.selectedText); + localStorage.setItem("textContent", result.selectedText); + } + }); + }, []) + + const toggleSwitch = () => { - setIsToggleOn((isToggleOn+1)%2); + setIsToggleOn((isToggleOn + 1) % 2); }; const handleFileUpload = async (event) => { @@ -52,7 +63,7 @@ function Second() { const handleSaveToLocalStorage = async () => { setLoading(true); - + // Check if a Google Doc URL is provided if (docUrl) { try { @@ -63,7 +74,7 @@ function Second() { }, body: JSON.stringify({ document_url: docUrl }) }); - + if (response.ok) { const data = await response.json(); setDocUrl("") @@ -77,13 +88,16 @@ function Second() { setText('Error retrieving Google Doc content'); } finally { setLoading(false); + chrome.storage.local.remove(["selectedText"], () => { + console.log("Chrome storage cleared"); + }); } } else if (text) { // Proceed with existing functionality for local storage localStorage.setItem("textContent", text); localStorage.setItem("difficulty", difficulty); localStorage.setItem("numQuestions", numQuestions); - + await sendToBackend( text, difficulty, @@ -121,7 +135,7 @@ function Second() { const formData = JSON.stringify({ input_text: data, max_questions: numQuestions, - use_mediawiki : isToggleOn + use_mediawiki: isToggleOn }); const response = await fetch(`http://localhost:5000/${endpoint}`, { method: "POST", @@ -130,26 +144,26 @@ function Second() { "Content-Type": "application/json", }, }); - + if (response.ok) { const responseData = await response.json(); localStorage.setItem("qaPairs", JSON.stringify(responseData)); - + // Save quiz details to local storage const quizDetails = { difficulty, numQuestions, date: new Date().toLocaleDateString(), - qaPair:responseData + qaPair: responseData }; - + let last5Quizzes = JSON.parse(localStorage.getItem('last5Quizzes')) || []; last5Quizzes.push(quizDetails); if (last5Quizzes.length > 5) { last5Quizzes.shift(); // Keep only the last 5 quizzes } localStorage.setItem('last5Quizzes', JSON.stringify(last5Quizzes)); - + window.location.href = "/src/pages/question/question.html"; } else { console.error("Backend request failed."); @@ -160,7 +174,7 @@ function Second() { setLoading(false); } }; - + return (
@@ -170,9 +184,8 @@ function Second() {
)}
logo @@ -285,15 +298,15 @@ function Second() {
- -
+ +
From d282af9a10ba5e2bd89c443f35c30547f1ebb909 Mon Sep 17 00:00:00 2001 From: Yatika Kain Date: Tue, 5 Nov 2024 19:26:06 +0530 Subject: [PATCH 2/2] Added relevant logs --- extension/src/pages/answer/Answer.jsx | 2 +- extension/src/pages/text_input/TextInput.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extension/src/pages/answer/Answer.jsx b/extension/src/pages/answer/Answer.jsx index 1625471..f3de730 100644 --- a/extension/src/pages/answer/Answer.jsx +++ b/extension/src/pages/answer/Answer.jsx @@ -19,7 +19,7 @@ const Answer = () => { useEffect(() => { chrome.storage.local.get(["selectedText"], (result) => { if (result.selectedText) { - console.log("extension", result.selectedText); + console.log("Selected Text: ", result.selectedText); setContext(result.selectedText); localStorage.setItem("textContent", result.selectedText); } diff --git a/extension/src/pages/text_input/TextInput.jsx b/extension/src/pages/text_input/TextInput.jsx index e2928ef..1f3b3c3 100644 --- a/extension/src/pages/text_input/TextInput.jsx +++ b/extension/src/pages/text_input/TextInput.jsx @@ -21,7 +21,7 @@ function Second() { useEffect(() => { chrome.storage.local.get(["selectedText"], (result) => { if (result.selectedText) { - console.log("extension", result.selectedText); + console.log("Selected Text: ", result.selectedText); setText(result.selectedText); localStorage.setItem("textContent", result.selectedText); }