161 lines
5.2 KiB
JavaScript
161 lines
5.2 KiB
JavaScript
const urlInput = document.getElementById('urlInput');
|
|
const startBtn = document.getElementById('startBtn');
|
|
const heroSection = document.getElementById('hero');
|
|
const loadingSection = document.getElementById('loading');
|
|
const resultSection = document.getElementById('result');
|
|
const terminalLog = document.getElementById('terminalLog');
|
|
const progressCircle = document.getElementById('progressCircle');
|
|
|
|
let clonedData = null;
|
|
|
|
startBtn.addEventListener('click', startCloning);
|
|
urlInput.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') startCloning();
|
|
});
|
|
|
|
document.getElementById('btnOpenSite').addEventListener('click', () => {
|
|
if (clonedData && clonedData.data && clonedData.data.path) {
|
|
// Construct local URL. Server serves /<folderName>/index.html
|
|
// We know server serves static files from cloned-sites directly if configured?
|
|
// Wait, server.js serves ../cloned-sites as static.
|
|
// so path is just /FolderName/index.html
|
|
const dirName = clonedData.data.path.split('\\').pop().split('/').pop();
|
|
window.open(`/${dirName}/index.html`, '_blank');
|
|
}
|
|
});
|
|
|
|
document.getElementById('btnOpenFolder').addEventListener('click', () => {
|
|
if (clonedData && clonedData.data && clonedData.data.path) {
|
|
fetch('/api/open-folder', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ path: clonedData.data.path })
|
|
});
|
|
}
|
|
});
|
|
|
|
|
|
async function startCloning() {
|
|
const url = urlInput.value.trim();
|
|
if (!url) {
|
|
showToast('Por favor, insira uma URL válida', 'error');
|
|
return;
|
|
}
|
|
|
|
// Switch UI
|
|
heroSection.classList.add('hidden');
|
|
loadingSection.classList.remove('hidden');
|
|
|
|
// Simulate Terminal Logs
|
|
log('Iniciando puppeteer...');
|
|
let progress = 0;
|
|
const progressInterval = setInterval(() => {
|
|
if (progress < 90) {
|
|
progress += Math.random() * 5;
|
|
updateProgress(progress);
|
|
}
|
|
}, 1000);
|
|
|
|
const logMessages = [
|
|
'Configurando viewport 1920x1080...',
|
|
'Interceptando requisições de rede...',
|
|
'Analisando DOM e Shadow DOM...',
|
|
'Baixando assets estáticos...',
|
|
'Processando estilos computados...',
|
|
'Otimizando imagens...',
|
|
'Verificando integridade...'
|
|
];
|
|
|
|
let msgIndex = 0;
|
|
const msgInterval = setInterval(() => {
|
|
if (msgIndex < logMessages.length) {
|
|
log(logMessages[msgIndex]);
|
|
msgIndex++;
|
|
}
|
|
}, 2500);
|
|
|
|
try {
|
|
const response = await fetch('/api/smart-clone', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ url })
|
|
});
|
|
|
|
const data = await response.json();
|
|
clonedData = data;
|
|
|
|
clearInterval(progressInterval);
|
|
clearInterval(msgInterval);
|
|
updateProgress(100);
|
|
|
|
if (data.success) {
|
|
log('Clonagem concluída com sucesso!');
|
|
setTimeout(() => {
|
|
showResult(data);
|
|
}, 1000);
|
|
} else {
|
|
throw new Error(data.error || 'Erro desconhecido');
|
|
}
|
|
|
|
} catch (error) {
|
|
clearInterval(progressInterval);
|
|
clearInterval(msgInterval);
|
|
showToast('Erro: ' + error.message, 'error');
|
|
log('❌ Erro fatal: ' + error.message);
|
|
setTimeout(() => {
|
|
heroSection.classList.remove('hidden');
|
|
loadingSection.classList.add('hidden');
|
|
}, 3000);
|
|
}
|
|
}
|
|
|
|
function updateProgress(value) {
|
|
// 283 is the circumference
|
|
const dashboard = 283;
|
|
const offset = dashboard - (value / 100) * dashboard;
|
|
progressCircle.style.strokeDashoffset = offset;
|
|
}
|
|
|
|
function log(msg) {
|
|
const div = document.createElement('div');
|
|
div.className = 'log-line';
|
|
div.innerText = `> ${msg}`;
|
|
terminalLog.appendChild(div);
|
|
terminalLog.scrollTop = terminalLog.scrollHeight;
|
|
}
|
|
|
|
function showResult(data) {
|
|
loadingSection.classList.add('hidden');
|
|
resultSection.classList.remove('hidden');
|
|
|
|
// Handle Verification Images
|
|
const verifyContainer = document.getElementById('verificationContainer');
|
|
if (data.data.verification) {
|
|
verifyContainer.style.display = 'block';
|
|
|
|
// Paths are relative to site dir.
|
|
// We need to construct URL to fetch them.
|
|
const dirName = data.data.path.split('\\').pop().split('/').pop();
|
|
|
|
document.getElementById('imgOriginal').src = `/${dirName}/${data.data.verification.original}`;
|
|
document.getElementById('imgClone').src = `/${dirName}/${data.data.verification.clone}`;
|
|
} else {
|
|
verifyContainer.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function showToast(msg, type = 'info') {
|
|
const toast = document.createElement('div');
|
|
toast.style.position = 'fixed';
|
|
toast.style.bottom = '20px';
|
|
toast.style.right = '20px';
|
|
toast.style.background = type === 'error' ? '#ef4444' : '#10b981';
|
|
toast.style.color = 'white';
|
|
toast.style.padding = '1rem 2rem';
|
|
toast.style.borderRadius = '8px';
|
|
toast.style.zIndex = '1000';
|
|
toast.innerText = msg;
|
|
document.body.appendChild(toast);
|
|
setTimeout(() => toast.remove(), 3000);
|
|
}
|