forensa / static /script.js
Yashikaysn29's picture
Upload folder using huggingface_hub
0371b98 verified
Raw
History Blame Contribute Delete
6.62 kB
// ── Tab switching ─────────────────────────────────────────────────
const tabBtns = document.querySelectorAll('.tab-btn');
const sections = document.querySelectorAll('section');
function showTab(name) {
sections.forEach(s => s.classList.toggle('active', s.id === name));
tabBtns.forEach(b => b.classList.toggle('active', b.dataset.tab === name && !b.classList.contains('btn-launch')));
if (name === 'dashboard') refreshStats();
window.scrollTo({ top: 0, behavior: 'smooth' });
}
tabBtns.forEach(btn => {
btn.addEventListener('click', () => showTab(btn.dataset.tab));
});
// ── Upload handling ──────────────────────────────────────────────
const uploadZone = document.getElementById('uploadZone');
const fileInput = document.getElementById('fileInput');
const previewRow = document.getElementById('previewRow');
const previewThumb = document.getElementById('previewThumb');
const previewName = document.getElementById('previewName');
const previewSize = document.getElementById('previewSize');
const clearBtn = document.getElementById('clearBtn');
const scanBtn = document.getElementById('scanBtn');
const verdictCard = document.getElementById('verdictCard');
let selectedFile = null;
uploadZone.addEventListener('click', () => fileInput.click());
uploadZone.addEventListener('dragover', e => { e.preventDefault(); uploadZone.classList.add('dragover'); });
uploadZone.addEventListener('dragleave', () => uploadZone.classList.remove('dragover'));
uploadZone.addEventListener('drop', e => {
e.preventDefault();
uploadZone.classList.remove('dragover');
if (e.dataTransfer.files.length) handleFile(e.dataTransfer.files[0]);
});
fileInput.addEventListener('change', () => {
if (fileInput.files.length) handleFile(fileInput.files[0]);
});
function handleFile(file) {
selectedFile = file;
previewName.textContent = file.name;
previewSize.textContent = `${(file.size / (1024 * 1024)).toFixed(2)} MB Β· ${file.type.startsWith('video') ? 'Video' : 'Image'}`;
const url = URL.createObjectURL(file);
if (file.type.startsWith('video')) {
previewThumb.outerHTML = `<video id="previewThumb" src="${url}" muted></video>`;
} else {
if (previewThumb.tagName !== 'IMG') {
document.getElementById('previewThumb').outerHTML = `<img id="previewThumb" src="${url}" />`;
} else {
previewThumb.src = url;
}
}
previewRow.style.display = 'flex';
scanBtn.disabled = false;
verdictCard.classList.remove('show');
}
clearBtn.addEventListener('click', () => {
selectedFile = null;
fileInput.value = '';
previewRow.style.display = 'none';
scanBtn.disabled = true;
verdictCard.classList.remove('show');
});
// ── Run scan ─────────────────────────────────────────────────────
scanBtn.addEventListener('click', async () => {
if (!selectedFile) return;
scanBtn.disabled = true;
scanBtn.textContent = 'Scanning…';
const formData = new FormData();
formData.append('file', selectedFile);
formData.append('sample_rate', document.getElementById('rateSelect').value);
try {
const res = await fetch('/api/analyze', { method: 'POST', body: formData });
const data = await res.json();
if (data.error) {
alert(data.error);
} else {
renderVerdict(data);
}
} catch (err) {
alert('Something went wrong while analyzing the file.');
console.error(err);
} finally {
scanBtn.disabled = false;
scanBtn.textContent = 'Start Scan';
}
});
function renderVerdict(data) {
const isFake = data.verdict === 'FAKE';
const accent = isFake ? 'var(--red)' : 'var(--green)';
document.getElementById('verdictIcon').textContent = isFake ? '⚠' : 'βœ“';
document.getElementById('verdictIcon').style.background = isFake ? 'rgba(244,63,94,0.14)' : 'rgba(52,211,153,0.14)';
document.getElementById('verdictIcon').style.color = accent;
document.getElementById('verdictLabel').textContent = data.verdict;
document.getElementById('verdictLabel').style.color = accent;
document.getElementById('verdictConf').textContent = `${data.confidence}% confidence`;
document.getElementById('fakeVal').textContent = `${data.fake_pct}%`;
document.getElementById('realVal').textContent = `${data.real_pct}%`;
document.getElementById('fakeBar').style.width = `${data.fake_pct}%`;
document.getElementById('realBar').style.width = `${data.real_pct}%`;
document.getElementById('metaType').textContent = data.file_type === 'video' ? 'πŸŽ₯ Video' : 'πŸ–ΌοΈ Image';
document.getElementById('metaElapsed').textContent = `${data.elapsed}s`;
document.getElementById('metaFrames').textContent = data.frames;
verdictCard.classList.add('show');
verdictCard.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
// ── Dashboard ────────────────────────────────────────────────────
async function refreshStats() {
try {
const res = await fetch('/api/stats');
const data = await res.json();
document.getElementById('statTotal').textContent = data.total_scans;
document.getElementById('statFakes').textContent = data.fakes_detected;
document.getElementById('statReal').textContent = data.authentic;
document.getElementById('statAcc').textContent = `${data.model_accuracy}%`;
document.getElementById('legendReal').textContent = data.authentic;
document.getElementById('legendFake').textContent = data.fakes_detected;
document.getElementById('donutPct').textContent = `${data.fake_rate}%`;
const circumference = 2 * Math.PI * 70; // ~440
const fakeLen = (data.fake_rate / 100) * circumference;
document.getElementById('donutFake').setAttribute('stroke-dasharray', `${fakeLen} ${circumference}`);
const list = document.getElementById('historyList');
if (!data.history.length) {
list.innerHTML = '<div class="empty-state">No scans yet β€” run a detection to see results here.</div>';
} else {
list.innerHTML = data.history.map(h => `
<div class="history-row">
<span class="name">${h.name}</span>
<span class="badge ${h.verdict.toLowerCase()}">${h.verdict} Β· ${h.confidence}%</span>
</div>
`).join('');
}
} catch (err) {
console.error('Failed to load stats', err);
}
}