Skip to content

Commit cb9493f

Browse files
committed
add: frontend extension work done
1 parent 9695607 commit cb9493f

File tree

5 files changed

+164
-0
lines changed

5 files changed

+164
-0
lines changed

frontend/background.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
3+
if (request.type === "TRANSLATE_CODE") {
4+
const BACKEND_URL = "https://backend.dineshsutihar123.workers.dev";
5+
6+
chrome.storage.sync.get(['targetLanguage'], (result) => {
7+
const targetLanguage = result.targetLanguage || 'Java';
8+
fetch(BACKEND_URL, {
9+
method: 'POST',
10+
headers: {
11+
'Content-Type': 'application/json',
12+
},
13+
body: JSON.stringify({
14+
code: request.code,
15+
targetLanguage: targetLanguage,
16+
}),
17+
})
18+
.then(response => {
19+
if (!response.ok) {
20+
throw new Error(`Network response was not ok: ${response.statusText}`);
21+
}
22+
return response.json();
23+
})
24+
.then(data => {
25+
26+
if (data.error) {
27+
sendResponse({ error: data.error });
28+
} else {
29+
sendResponse({ translation: data.translation });
30+
}
31+
})
32+
.catch(error => {
33+
34+
console.error("Error calling backend:", error);
35+
sendResponse({ error: `Failed to connect to the translation service: ${error.message}` });
36+
});
37+
});
38+
39+
return true;
40+
}
41+
});

frontend/content.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
let isPickerEnabled = false;
2+
let hoveredElement = null;
3+
4+
// The main listener for messages from the popup
5+
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
6+
if (message.type === "ENABLE_PICKER") {
7+
if (!isPickerEnabled) enablePicker();
8+
}
9+
});
10+
11+
function enablePicker() {
12+
isPickerEnabled = true;
13+
document.body.style.cursor = 'crosshair';
14+
document.addEventListener('mouseover', onMouseOver);
15+
document.addEventListener('mouseout', onMouseOut);
16+
document.addEventListener('click', onClick, true);
17+
}
18+
19+
function disablePicker() {
20+
isPickerEnabled = false;
21+
document.body.style.cursor = 'default';
22+
if (hoveredElement) hoveredElement.classList.remove('translator-highlight');
23+
document.removeEventListener('mouseover', onMouseOver);
24+
document.removeEventListener('mouseout', onMouseOut);
25+
document.removeEventListener('click', onClick, true);
26+
}
27+
28+
function onMouseOver(e) {
29+
hoveredElement = e.target;
30+
hoveredElement.classList.add('translator-highlight');
31+
}
32+
33+
function onMouseOut(e) {
34+
e.target.classList.remove('translator-highlight');
35+
hoveredElement = null;
36+
}
37+
38+
function onClick(e) {
39+
e.preventDefault();
40+
e.stopPropagation();
41+
42+
const clickedElement = e.target;
43+
const selectedCode = clickedElement.textContent;
44+
disablePicker();
45+
46+
const loadingDiv = document.createElement('div');
47+
loadingDiv.className = 'translator-loading';
48+
loadingDiv.textContent = 'Translating...';
49+
clickedElement.parentNode.insertBefore(loadingDiv, clickedElement.nextSibling);
50+
51+
chrome.runtime.sendMessage({ type: "TRANSLATE_CODE", code: selectedCode }, (response) => {
52+
loadingDiv.remove();
53+
54+
if (response.error) {
55+
alert(`Error: ${response.error}`);
56+
} else if (response.translation) {
57+
injectTranslatedCode(response.translation, clickedElement);
58+
}
59+
});
60+
}
61+
62+
function injectTranslatedCode(translatedCode, originalElement) {
63+
const container = document.createElement('div');
64+
container.className = 'translation-container';
65+
66+
const header = document.createElement('h4');
67+
header.textContent = 'AI-Generated Translation:';
68+
69+
const pre = document.createElement('pre');
70+
const code = document.createElement('code');
71+
code.textContent = translatedCode;
72+
pre.appendChild(code);
73+
74+
container.appendChild(header);
75+
container.appendChild(pre);
76+
77+
// Insert the container right after the original element
78+
originalElement.parentNode.insertBefore(container, originalElement.nextSibling);
79+
}

frontend/images/.gitkeep

Whitespace-only changes.

frontend/manifest.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"manifest_version": 3,
3+
"name": "CodeTranslateAI",
4+
"version": "0.1.0",
5+
"description": "Select code on a page and translate it on the fly.",
6+
"permissions": ["activeTab", "scripting", "storage"],
7+
"action": {
8+
"default_popup": "popup.html"
9+
},
10+
"content_scripts": [
11+
{
12+
"matches": ["<all_urls>"],
13+
"js": ["content.js"],
14+
"css": ["styles.css"]
15+
}
16+
],
17+
"background": {
18+
"service_worker": "background.js"
19+
}
20+
}

frontend/popup.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const enablePickerBtn = document.getElementById('enable-picker-btn');
2+
const languageSelect = document.getElementById('language-select');
3+
4+
enablePickerBtn.addEventListener('click', () => {
5+
const targetLanguage = languageSelect.value;
6+
7+
chrome.storage.sync.set({ targetLanguage: targetLanguage });
8+
9+
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
10+
const activeTab = tabs[0];
11+
chrome.tabs.sendMessage(activeTab.id, {
12+
type: "ENABLE_PICKER"
13+
});
14+
window.close();
15+
});
16+
});
17+
18+
document.addEventListener('DOMContentLoaded', () => {
19+
chrome.storage.sync.get(['targetLanguage'], (result) => {
20+
if (result.targetLanguage) {
21+
languageSelect.value = result.targetLanguage;
22+
}
23+
});
24+
});

0 commit comments

Comments
 (0)