Auto-deploy: 2026-05-17 22:45:01

This commit is contained in:
Hamza-Ayed
2026-05-17 22:45:01 +03:00
parent 8dc55c698e
commit 5fd6969ff8
5 changed files with 177 additions and 19 deletions

View File

@@ -955,6 +955,149 @@ Brief honest assessment of this opportunity for my profile`
setTimeout(() => toast.classList.remove('show'), 2500);
}
// ─── List Scanner ────────────────────────────────────────────────────────
function injectListScanner() {
if (document.getElementById('lja-scan-btn')) return;
const btn = document.createElement('button');
btn.id = 'lja-scan-btn';
btn.innerHTML = '🔍 Scan List';
btn.style.cssText = `
position: fixed;
bottom: 20px;
left: 20px;
z-index: 999999;
background: linear-gradient(135deg, #00d67e, #00a65e);
color: white;
border: none;
border-radius: 50px;
padding: 12px 24px;
font-size: 14px;
font-weight: bold;
cursor: pointer;
box-shadow: 0 4px 15px rgba(0, 214, 126, 0.4);
transition: transform 0.2s;
font-family: Arial, sans-serif;
`;
btn.onmouseover = () => btn.style.transform = 'scale(1.05)';
btn.onmouseout = () => btn.style.transform = 'scale(1)';
btn.onclick = async () => {
btn.innerHTML = '⏳ Scanning...';
try {
await scanJobList();
} catch (e) {
console.error(e);
alert('Scan failed: ' + e.message);
}
btn.innerHTML = '🔍 Scan List';
};
document.body.appendChild(btn);
}
async function scanJobList() {
const listItems = document.querySelectorAll('.jobs-search-results__list-item, .job-card-container');
if (!listItems.length) {
alert('No job items found on this page. Scroll down to load them.');
return;
}
const jobsToScan = [];
listItems.forEach((item, index) => {
const titleEl = item.querySelector('.job-card-list__title, .artdeco-entity-lockup__title');
const companyEl = item.querySelector('.job-card-container__primary-description, .artdeco-entity-lockup__subtitle');
if (titleEl && companyEl) {
jobsToScan.push({
index: index,
title: titleEl.textContent.trim().replace(/\n/g, ''),
company: companyEl.textContent.trim().replace(/\n/g, ''),
element: item
});
}
});
if (!jobsToScan.length) {
alert('Could not parse job titles.');
return;
}
document.querySelectorAll('.lja-badge').forEach(b => b.remove());
const listDataStr = JSON.stringify(jobsToScan.map(j => ({ index: j.index, title: j.title, company: j.company })));
const settings = await getSettings();
if (!settings.apiKey) {
alert('Please set your API key in the extension popup first.');
return;
}
if (typeof buildPromptV2 !== 'function') {
alert('buildPromptV2 not found. Extension error.');
return;
}
const promptStr = buildPromptV2('list_analysis', { skills: [], listData: listDataStr }, settings.userProfile, settings.language);
const response = await fetch(
\`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=\${settings.apiKey}\`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contents: [{ parts: [{ text: promptStr }] }],
generationConfig: { maxOutputTokens: 2048, temperature: 0.1 }
})
}
);
if (!response.ok) throw new Error('API Request failed');
const data = await response.json();
let resultText = data.candidates[0].content.parts[0].text;
resultText = resultText.replace(/\`\`\`json/g, '').replace(/\`\`\`/g, '').trim();
let results;
try {
results = JSON.parse(resultText);
} catch(e) {
console.error(resultText);
throw new Error('Failed to parse AI response');
}
results.forEach(res => {
const jobItem = jobsToScan.find(j => j.index === res.index);
if (jobItem) {
const badge = document.createElement('div');
badge.className = 'lja-badge';
badge.style.cssText = \`
display: inline-block;
padding: 4px 8px;
border-radius: 6px;
font-size: 11px;
font-weight: bold;
margin-top: 6px;
color: white;
width: 100%;
box-sizing: border-box;
\`;
if (res.verdict === 'YES') {
badge.style.background = 'linear-gradient(135deg, #00d67e, #00a65e)';
badge.innerHTML = \`✅ MATCH: \${res.reason}\`;
} else if (res.verdict === 'NO') {
badge.style.background = 'linear-gradient(135deg, #ff4d6d, #d90429)';
badge.innerHTML = \`❌ SKIP: \${res.reason}\`;
} else {
badge.style.background = 'linear-gradient(135deg, #ffb347, #ff9200)';
badge.innerHTML = \`⚠️ MAYBE: \${res.reason}\`;
}
const contentContainer = jobItem.element.querySelector('.artdeco-entity-lockup__content');
if (contentContainer) contentContainer.appendChild(badge);
}
});
}
// ─── SPA Navigation Observer ─────────────────────────────────────────────
let lastUrl = location.href;
@@ -970,7 +1113,7 @@ Brief honest assessment of this opportunity for my profile`
const old = document.getElementById('lja-root');
if (old) old.remove();
window.__linkedinAnalyzerLoaded = false;
setTimeout(injectOverlay, 1200);
setTimeout(() => { injectOverlay(); injectListScanner(); }, 1200);
}
// Watch for URL changes (SPA navigation + job switches)
@@ -1006,9 +1149,9 @@ Brief honest assessment of this opportunity for my profile`
function init() {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => setTimeout(injectOverlay, 1000));
document.addEventListener('DOMContentLoaded', () => setTimeout(() => { injectOverlay(); injectListScanner(); }, 1000));
} else {
setTimeout(injectOverlay, 1000);
setTimeout(() => { injectOverlay(); injectListScanner(); }, 1000);
}
}