Skip to content

Commit 3ccf6c9

Browse files
committed
feat: tracking the solved problems in a list for now
1 parent 771f9cf commit 3ccf6c9

File tree

5 files changed

+129
-5
lines changed

5 files changed

+129
-5
lines changed

background.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// background.js
2+
// Handles persistent messaging and storage for LeetCode Tracker
3+
4+
// Listen for messages from content scripts
5+
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
6+
if (message.type === 'PROBLEM_SOLVED' && message.slug) {
7+
// Update storage with solved status
8+
browser.storage.local.get(message.slug).then((existing) => {
9+
const data = existing[message.slug] || {};
10+
data.status = 'Solved';
11+
data.solvedAt = Date.now();
12+
browser.storage.local.set({ [message.slug]: data });
13+
});
14+
}
15+
// Optionally handle other message types here
16+
});
17+
18+
// Listen for popup requests for problem data
19+
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
20+
if (message.type === 'GET_PROBLEM_DATA' && message.slug) {
21+
browser.storage.local.get(message.slug).then((result) => {
22+
sendResponse(result[message.slug] || null);
23+
});
24+
// Return true to indicate async response
25+
return true;
26+
}
27+
});

content.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,37 @@ function getProblemData() {
4040

4141
observer.observe(document.body, { childList: true, subtree: true });
4242
}
43+
44+
function waitForSubmissionResult(slug) {
45+
const observer = new MutationObserver(() => {
46+
const resultEl = document.querySelector('span[data-e2e-locator="submission-result"]');
47+
if (resultEl && resultEl.textContent.includes("Accepted")) {
48+
console.log("✅ Accepted detected via submission result!");
49+
50+
browser.storage.local.get(slug).then((existing) => {
51+
const data = existing[slug] || {};
52+
data.status = "Solved";
53+
data.solvedAt = Date.now();
54+
browser.storage.local.set({ [slug]: data })
55+
56+
browser.runtime.sendMessage({ type: 'PROBLEM_SOLVED', slug});
57+
observer.disconnect();
58+
});
59+
}
60+
});
61+
62+
observer.observe(document.body, {childList: true, subtree: true});
63+
}
4364

4465
waitForContentAndStore();
4566

67+
const { slug } = getProblemData();
68+
waitForSubmissionResult(slug);
69+
70+
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
71+
if (message.type === 'GET_PROBLEM_DATA') {
72+
const data = getProblemData();
73+
sendResponse(data);
74+
}
75+
});
4676

manifest.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
"manifest_version" : 2,
33
"name": "LeetCode Tracker",
44
"version": "0.1.0",
5-
"descriptin": "Track your leetcode activity to improve faster",
5+
"description": "Track your leetcode activity to improve faster",
66
"permissions": ["storage", "tabs", "activeTab", "scripting"],
77
"host_permissions": ["https://leetcode.com/*"],
88
"background": {
99
"scripts": ["background.js"],
1010
"persistent": false
1111
},
12-
"action": {
13-
"default_popup": "popup.html",
12+
"browser_action": {
13+
"default_popup": "popup/popup.html",
1414
"default_icon": "placeholder.png"
1515
},
1616
"content_scripts": [

popup/popup.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@
77

88
<body>
99
<h1>LeetCode Tracker</h1>
10-
<p id="status">No data yet</p>
10+
<div id="popupContent">
11+
<p>
12+
Loading problem info...
13+
</p>
14+
</div>
15+
16+
<div id="solvedList">
17+
18+
</div>
1119
<script src="popup.js"></script>
1220
</body>
1321
</html>

popup/popup.js

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,60 @@
1-
document.getElementById("status").textContent = "Loading...";
1+
document.addEventListener("DOMContentLoaded", () => {
2+
browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
3+
const tab = tabs[0];
4+
// Get the problem slug from the URL
5+
const url = new URL(tab.url);
6+
const pathParts = url.pathname.split("/").filter(Boolean);
7+
const slug = pathParts[1] || null;
8+
if (!slug) {
9+
document.body.innerHTML = "<p>Not a leetcode problem page</p>";
10+
return;
11+
}
12+
// Ask background for the latest problem data
13+
browser.runtime.sendMessage({ type: "GET_PROBLEM_DATA", slug })
14+
.then((data) => {
15+
if (!data) {
16+
document.body.innerHTML = "<p>Not a leetcode problem page</p>";
17+
return;
18+
}
19+
const container = document.getElementById("popupContent");
20+
container.innerHTML = `
21+
<h2>${data.title}</h2>
22+
<p>Difficulty: ${data.difficulty} </p>
23+
<p id="status">${data.status || "Unsolved"}</p>
24+
`;
25+
26+
// Listen for problem solved message
27+
browser.runtime.onMessage.addListener((msg) => {
28+
if (msg.type === "PROBLEM_SOLVED" && msg.slug === data.slug) {
29+
const statusEl = document.getElementById("status");
30+
if (statusEl) statusEl.textContent = "Solved ✅";
31+
}
32+
});
33+
})
34+
.catch((err) => {
35+
document.body.innerHTML = "<p>Unable to read this page</p>";
36+
console.error(err);
37+
});
38+
});
39+
});
40+
41+
document.addEventListener("DOMContentLoaded", () => {
42+
browser.storage.local.get(null).then((allData) => {
43+
const problems = Object.values(allData).filter(p => p.status === "Solved");
44+
const list = document.getElementById("solvedList");
45+
46+
if (problems.length === 0) {
47+
list.innerHTML = "<p>No solved problems yet</p>"
48+
}
49+
50+
problems.forEach(problem => {
51+
const item = document.createElement("div");
52+
item.className = "problem-item";
53+
item.innerHTML = `
54+
<a href="${problem.url}" target="_blank">${problem.title}</a>
55+
<span class="difficulty">${problem.difficulty}</span>
56+
`;
57+
list.appendChild(item);
58+
})
59+
})
60+
})

0 commit comments

Comments
 (0)