Add Retry Scan button with auto-close, Next button click detection, and filter out page metadata from questions
This commit is contained in:
+50
-3
@@ -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
@@ -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>
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user