Files
VibeDownloader/src/renderer.js
T

291 lines
9.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// DOM Elements
const dependencyOverlay = document.getElementById('dependency-overlay');
const depTitle = document.getElementById('dep-title');
const depMsg = document.getElementById('dep-msg');
const depProgress = document.getElementById('dep-progress');
const depPercent = document.getElementById('dep-percent');
const urlInput = document.getElementById('url-input');
const analyzeBtn = document.getElementById('analyze-btn');
const outputPath = document.getElementById('output-path');
const changeFolderBtn = document.getElementById('change-folder-btn');
const errorCard = document.getElementById('error-card');
const errorMessage = document.getElementById('error-message');
const step1 = document.getElementById('step-1');
const step2 = document.getElementById('step-2');
const backBtn = document.getElementById('back-btn');
const trackList = document.getElementById('track-list');
const formatMp3Btn = document.getElementById('format-mp3-btn');
const formatMp4Btn = document.getElementById('format-mp4-btn');
const qualityPillsContainer = document.getElementById('quality-pills');
const downloadBtn = document.getElementById('download-btn');
const downloadProgressPanel = document.getElementById('download-progress-panel');
const downloadStatus = document.getElementById('download-status');
const downloadPercent = document.getElementById('download-percent');
const downloadProgressBar = document.getElementById('download-progress-bar');
const downloadSubtext = document.getElementById('download-subtext');
// State Variables
let analyzedUrl = '';
let currentFormat = 'mp3'; // 'mp3' or 'mp4'
let currentQuality = '320'; // Selected quality value
let currentVideoData = null;
// Quality Configuration Data
const qualityConfigs = {
mp3: [
{ label: '320 kbps (En Yüksek)', value: '320' },
{ label: '256 kbps', value: '256' },
{ label: '192 kbps', value: '192' }
],
mp4: [
{ label: '1080p (Full HD)', value: '1080' },
{ label: '720p (HD)', value: '720' },
{ label: '480p (Standart)', value: '480' }
]
};
// 1. Initial Load & Dependency Verification
window.addEventListener('DOMContentLoaded', async () => {
// Setup Custom Titlebar Controls
document.getElementById('titlebar-minimize').addEventListener('click', () => {
window.api.minimizeWindow();
});
document.getElementById('titlebar-close').addEventListener('click', () => {
window.api.closeWindow();
});
// Get and display default downloads folder path
const defaultPath = await window.api.getDownloadsFolder();
outputPath.textContent = defaultPath;
// Listen to dependency checking progress
window.api.onDependencyStatus(({ message, progress }) => {
depMsg.textContent = message;
depProgress.style.width = `${progress}%`;
depPercent.textContent = `${progress}%`;
});
try {
const result = await window.api.checkDependencies();
if (result.success) {
// Transition out the loading overlay
dependencyOverlay.style.opacity = '0';
setTimeout(() => {
dependencyOverlay.classList.remove('active');
}, 400);
} else {
depTitle.textContent = 'Hata Oluştu';
depMsg.textContent = `Bileşenler yüklenemedi: ${result.error}`;
depPercent.textContent = 'Hata';
}
} catch (err) {
depTitle.textContent = 'Hata Oluştu';
depMsg.textContent = err.message;
}
// Render initial quality pills
renderQualityPills();
});
// 2. Output Path Folder Changer
changeFolderBtn.addEventListener('click', async () => {
const newPath = await window.api.selectDirectory();
outputPath.textContent = newPath;
});
// 3. Format Toggle Event Listeners
formatMp3Btn.addEventListener('click', () => {
if (currentFormat === 'mp3') return;
currentFormat = 'mp3';
formatMp3Btn.classList.add('active');
formatMp4Btn.classList.remove('active');
currentQuality = '320'; // Reset to default best quality for MP3
renderQualityPills();
});
formatMp4Btn.addEventListener('click', () => {
if (currentFormat === 'mp4') return;
currentFormat = 'mp4';
formatMp4Btn.classList.add('active');
formatMp3Btn.classList.remove('active');
currentQuality = '1080'; // Reset to default best quality for MP4
renderQualityPills();
});
// 4. Quality Pills Renderer
function renderQualityPills() {
qualityPillsContainer.innerHTML = '';
const options = qualityConfigs[currentFormat];
options.forEach(opt => {
const pill = document.createElement('button');
pill.className = 'quality-pill';
if (opt.value === currentQuality) {
pill.classList.add('active');
}
pill.textContent = opt.label;
pill.dataset.value = opt.value;
pill.addEventListener('click', () => {
document.querySelectorAll('.quality-pill').forEach(p => p.classList.remove('active'));
pill.classList.add('active');
currentQuality = opt.value;
});
qualityPillsContainer.appendChild(pill);
});
}
// 5. Back Button (Step 2 to Step 1 Transition)
backBtn.addEventListener('click', () => {
// Reset any error card
errorCard.style.display = 'none';
// Fade out Step 2 and show Step 1
step2.classList.remove('active');
step1.classList.add('active');
urlInput.focus();
});
// 6. Link Analysis Handler
analyzeBtn.addEventListener('click', async () => {
const url = urlInput.value.trim();
if (!url) return;
// Reset error displays
errorCard.style.display = 'none';
// Toggle button loading states
analyzeBtn.disabled = true;
const analyzeSpan = analyzeBtn.querySelector('span');
const analyzeIcon = analyzeBtn.querySelector('.btn-icon');
analyzeSpan.textContent = 'Analiz ediliyor...';
analyzeIcon.style.display = 'inline-block';
try {
const result = await window.api.getVideoInfo(url);
if (result.success) {
analyzedUrl = url;
currentVideoData = result.info;
// Render the fetched video details inside the scrollable list container
renderTrackList(result.info);
// Wizard transition: Step 1 -> Step 2
step1.classList.remove('active');
step2.classList.add('active');
} else {
showError(result.error);
}
} catch (err) {
showError(err.message);
} finally {
analyzeBtn.disabled = false;
analyzeSpan.textContent = 'Analiz Et';
analyzeIcon.style.display = 'none';
}
});
// 7. Render Track List Function
function renderTrackList(info) {
trackList.innerHTML = `
<div class="track-item">
<div class="track-thumb">
<img src="${info.thumbnail}" alt="Thumbnail">
</div>
<div class="track-details">
<h4>${info.title}</h4>
<p class="track-uploader">${info.uploader}</p>
<span class="track-duration">Süre: ${info.duration}</span>
</div>
<div class="track-status">
<span id="track-status-badge" class="status-badge ready">Hazır</span>
</div>
</div>
`;
}
// 8. Media Download Executor
downloadBtn.addEventListener('click', async () => {
if (!analyzedUrl) return;
// Setup download progress panel UI states
downloadProgressPanel.style.display = 'block';
downloadBtn.disabled = true;
backBtn.disabled = true;
downloadStatus.textContent = 'Bağlantı kuruluyor...';
downloadPercent.textContent = '0%';
downloadProgressBar.style.width = '0%';
downloadSubtext.textContent = currentFormat === 'mp3' ? 'Ses akışı alınıyor...' : 'Video akışı alınıyor...';
// Set track status badge as downloading
const statusBadge = document.getElementById('track-status-badge');
if (statusBadge) {
statusBadge.textContent = 'İndiriliyor';
statusBadge.className = 'status-badge downloading';
}
// Subscribe to progress events from the main process
window.api.onDownloadProgress(({ percent, status }) => {
downloadStatus.textContent = status;
downloadPercent.textContent = `${percent}%`;
downloadProgressBar.style.width = `${percent}%`;
if (percent > 90) {
downloadSubtext.textContent = currentFormat === 'mp3'
? 'Dönüştürme işlemi yapılıyor (Yüksek Kaliteli MP3)...'
: 'Video ve ses dosyaları birleştiriliyor...';
} else {
downloadSubtext.textContent = 'İndirme hızı ve dosya boyutuna göre işlem süresi değişebilir.';
}
});
try {
const result = await window.api.downloadMedia(analyzedUrl, currentFormat, currentQuality);
if (result.success) {
downloadStatus.textContent = 'Tamamlandı!';
downloadPercent.textContent = '100%';
downloadProgressBar.style.width = '100%';
downloadSubtext.textContent = 'Dosyanız başarıyla kaydedildi!';
if (statusBadge) {
statusBadge.textContent = 'Tamamlandı';
statusBadge.className = 'status-badge ready';
statusBadge.style.borderColor = 'rgba(0, 255, 135, 0.3)';
statusBadge.style.color = '#00ff87';
statusBadge.style.background = 'rgba(0, 255, 135, 0.1)';
}
// Success gradient transitions
downloadProgressBar.style.background = 'linear-gradient(90deg, #00ff87 0%, #60efff 100%)';
downloadProgressBar.style.boxShadow = '0 0 15px rgba(0, 255, 135, 0.6)';
} else {
showError(result.error);
downloadProgressPanel.style.display = 'none';
if (statusBadge) {
statusBadge.textContent = 'Hata';
statusBadge.className = 'status-badge ready';
statusBadge.style.borderColor = 'rgba(255, 77, 77, 0.3)';
statusBadge.style.color = '#ff4d4d';
statusBadge.style.background = 'rgba(255, 77, 77, 0.1)';
}
}
} catch (err) {
showError(err.message);
downloadProgressPanel.style.display = 'none';
} finally {
downloadBtn.disabled = false;
backBtn.disabled = false;
}
});
// Helper: Show Error Alert inside Step 1
function showError(msg) {
errorMessage.textContent = `Hata: ${msg}`;
errorCard.style.display = 'flex';
}