291 lines
9.6 KiB
JavaScript
291 lines
9.6 KiB
JavaScript
// 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';
|
||
}
|