Add Retry Scan button with auto-close, Next button click detection, and filter out page metadata from questions

This commit is contained in:
justin committed 2026-01-08 11:15:16 -07:00
1 parent f79629e1b6
commit 75ebd38060
3 files changed
+108 -3

No files matched your search

+50 -3
View File
@@ -66,6 +66,12 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
openaiApiKey = request.apiKey; openaiApiKey = request.apiKey;
console.log('✓ OpenAI API key updated'); console.log('✓ OpenAI API key updated');
processedQuestions.clear(); processedQuestions.clear();
} else if (request.action === 'retryScan') {
console.log('🔄 Manual retry initiated from popup');
processedQuestions.clear();
isProcessing = false;
removeHighlights();
waitForContentAndScan();
} }
}); });
@@ -168,7 +174,7 @@ function getFullQuestionContext(questionElement) {
return questionText; return questionText;
} }
// Enhanced question finding for Microsoft Learn // Enhanced question finding for Microsoft Learn - Groups multi-line questions
function findQuestions() { function findQuestions() {
const questions = []; const questions = [];
const seenTexts = new Set(); const seenTexts = new Set();
@@ -216,6 +222,8 @@ function findQuestions() {
if (questionText.length < 15 || seenTexts.has(questionText)) return; if (questionText.length < 15 || seenTexts.has(questionText)) return;
if (/^(next|previous|submit|skip)$/i.test(questionText)) return; if (/^(next|previous|submit|skip)$/i.test(questionText)) return;
// Skip page metadata, scripts, and non-question content
if (/var\s+\w+\s*=\s*\{|function\s*\(|microsoft learn|practice assessment/i.test(questionText)) return;
seenTexts.add(questionText); seenTexts.add(questionText);
questions.push({ questions.push({
@@ -718,7 +726,7 @@ async function scanAndHighlight() {
} }
} }
// Mutation observer for dynamic content // Mutation observer for dynamic content - ignores self-triggered changes
let mutationTimeout; let mutationTimeout;
const observer = new MutationObserver((mutations) => { const observer = new MutationObserver((mutations) => {
if (!extensionEnabled || isProcessing) return; if (!extensionEnabled || isProcessing) return;
@@ -726,7 +734,10 @@ const observer = new MutationObserver((mutations) => {
const hasNewContent = mutations.some(mutation => { const hasNewContent = mutations.some(mutation => {
return mutation.addedNodes.length > 0 && return mutation.addedNodes.length > 0 &&
Array.from(mutation.addedNodes).some(node => Array.from(mutation.addedNodes).some(node =>
node.nodeType === 1 && node.textContent.length > 50 node.nodeType === 1 &&
node.textContent.length > 50 &&
!node.classList?.contains('quiz-helper-correct') &&
!node.hasAttribute?.('data-quiz-helper-highlight')
); );
}); });
@@ -743,3 +754,39 @@ observer.observe(document.body, {
childList: true, childList: true,
subtree: true subtree: true
}); });
// Listen for page navigation (Next button clicks)
let lastUrl = location.href;
const urlObserver = new MutationObserver(() => {
if (location.href !== lastUrl) {
lastUrl = location.href;
console.log('🔄 Page navigation detected, resetting and rescanning...');
processedQuestions.clear();
isProcessing = false;
setTimeout(() => waitForContentAndScan(), 1000);
}
});
urlObserver.observe(document.body, { childList: true, subtree: true });
// Also listen for popstate (browser back/forward)
window.addEventListener('popstate', () => {
console.log('🔄 Browser navigation detected, resetting and rescanning...');
processedQuestions.clear();
isProcessing = false;
setTimeout(() => waitForContentAndScan(), 1000);
});
// Listen for Next button clicks
document.addEventListener('click', (e) => {
const target = e.target;
if (target.tagName === 'SPAN' && target.textContent.trim() === 'Next') {
console.log('🔄 Next button clicked, scanning in 1 second...');
setTimeout(() => {
processedQuestions.clear();
isProcessing = false;
removeHighlights();
waitForContentAndScan();
}, 1000);
}
});
+17
View File
@@ -127,6 +127,22 @@
display: block; display: block;
margin-bottom: 5px; margin-bottom: 5px;
} }
.retry-btn {
padding: 6px 12px;
font-size: 11px;
background: #28a745;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.retry-btn:hover {
background: #218838;
}
.retry-btn:disabled {
background: #ccc;
cursor: not-allowed;
}
</style> </style>
</head> </head>
<body> <body>
@@ -154,6 +170,7 @@
<span class="slider"></span> <span class="slider"></span>
</label> </label>
<span id="toggleLabel">Off</span> <span id="toggleLabel">Off</span>
<button id="retryBtn" class="retry-btn">Retry Scan</button>
</div> </div>
<div id="status"></div> <div id="status"></div>
+41
View File
@@ -60,6 +60,47 @@ document.getElementById('toggleSwitch').addEventListener('change', function(e) {
}, 2000); }, 2000);
}); });
// Handle Retry button click
document.getElementById('retryBtn').addEventListener('click', function() {
const btn = document.getElementById('retryBtn');
btn.disabled = true;
btn.textContent = 'Scanning...';
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if (tabs[0]) {
const url = tabs[0].url;
if (url.startsWith('chrome://') || url.startsWith('chrome-extension://') || url.startsWith('edge://')) {
document.getElementById('status').textContent = 'Extension cannot run on this page';
document.getElementById('status').style.color = '#d13438';
btn.disabled = false;
btn.textContent = 'Retry Scan';
setTimeout(() => {
document.getElementById('status').textContent = '';
document.getElementById('status').style.color = '';
}, 3000);
return;
}
chrome.tabs.sendMessage(tabs[0].id, {
action: 'retryScan'
}).then(() => {
window.close();
}).catch(error => {
console.log('Could not send retry message:', error);
document.getElementById('status').textContent = 'Could not initiate scan - refresh the page';
document.getElementById('status').style.color = '#d13438';
btn.disabled = false;
btn.textContent = 'Retry Scan';
setTimeout(() => {
document.getElementById('status').textContent = '';
document.getElementById('status').style.color = '';
}, 3000);
});
}
});
});
// Handle API key save // Handle API key save
document.getElementById('saveApiKey').addEventListener('click', function() { document.getElementById('saveApiKey').addEventListener('click', function() {
const apiKey = document.getElementById('apiKey').value.trim(); const apiKey = document.getElementById('apiKey').value.trim();