feat(settings): YouTube indirme ayarları ekle

Kullanıcıların YouTube indirme tercihlerini yapılandırabilmesi için ayarlar
arayüzüne yeni kontroller eklendi:

- Video çözünürlüğü seçimi (1080p, 720p, 480p, 360p, 240p, 144p)
- Sadece ses indirme seçeneği
- Ayarları kaydetme/yenileme butonları
- API ile entegrasyon için load/save fonksiyonları
This commit is contained in:
2025-12-14 21:05:10 +03:00
parent d69fb41024
commit e3d0eaf8cf

View File

@@ -13,6 +13,11 @@
let cookiesUpdatedAt = null;
let loadingCookies = false;
let savingCookies = false;
let loadingYtSettings = false;
let savingYtSettings = false;
let selectedResolution = "1080p";
let onlyAudio = false;
const resolutionOptions = ["1080p", "720p", "480p", "360p", "240p", "144p"];
let error = null;
let success = null;
@@ -64,8 +69,51 @@
}
}
async function loadYoutubeSettings() {
loadingYtSettings = true;
error = null;
try {
const resp = await apiFetch("/api/youtube/settings");
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const data = await resp.json();
if (data?.resolution) selectedResolution = data.resolution;
if (typeof data?.onlyAudio === "boolean") onlyAudio = data.onlyAudio;
} catch (err) {
error = err?.message || "YouTube ayarları alınamadı.";
} finally {
loadingYtSettings = false;
}
}
async function saveYoutubeSettings() {
if (savingYtSettings) return;
savingYtSettings = true;
error = null;
success = null;
try {
const resp = await apiFetch("/api/youtube/settings", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
resolution: selectedResolution,
onlyAudio
})
});
const data = await resp.json().catch(() => ({}));
if (!resp.ok || !data?.ok) {
throw new Error(data?.error || `HTTP ${resp.status}`);
}
success = "YouTube indirme ayarları kaydedildi.";
} catch (err) {
error = err?.message || "YouTube ayarları kaydedilemedi.";
} finally {
savingYtSettings = false;
}
}
onMount(() => {
loadCookies();
loadYoutubeSettings();
});
function formatDate(ts) {
@@ -98,6 +146,47 @@
</div>
{#if activeTab === "youtube"}
<div class="card">
<div class="card-header">
<div class="title">
<i class="fa-solid fa-circle-down"></i>
<span>YouTube Download</span>
</div>
</div>
<div class="field inline compact left-align">
<div class="inline-field">
<label for="resolution">Çözünürlük</label>
<select
id="resolution"
bind:value={selectedResolution}
disabled={loadingYtSettings || savingYtSettings}
>
{#each resolutionOptions as res}
<option value={res}>{res}</option>
{/each}
</select>
</div>
<label class="checkbox-row">
<input
type="checkbox"
bind:checked={onlyAudio}
disabled={loadingYtSettings || savingYtSettings}
/>
<span>Only Audio (sadece ses indir)</span>
</label>
</div>
<div class="actions">
<button class="btn" on:click={loadYoutubeSettings} disabled={loadingYtSettings || savingYtSettings}>
<i class="fa-solid fa-rotate"></i> Yenile
</button>
<button class="btn primary" on:click={saveYoutubeSettings} disabled={loadingYtSettings || savingYtSettings}>
<i class="fa-solid fa-floppy-disk"></i> Kaydet
</button>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="title">
@@ -238,6 +327,46 @@
font-weight: 600;
}
.field.inline {
display: flex;
align-items: center;
gap: 16px;
flex-wrap: wrap;
}
.field.inline.compact {
align-items: flex-end;
}
.field.inline.left-align {
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
gap: 10px;
}
.inline-field {
display: flex;
flex-direction: column;
gap: 6px;
}
.field select {
min-width: 180px;
max-width: 240px;
padding: 8px 10px;
border: 1px solid var(--border, #dcdcdc);
border-radius: 8px;
background: #fff;
}
.checkbox-row {
display: inline-flex;
align-items: center;
gap: 8px;
font-weight: 600;
}
.field textarea {
min-height: 180px;
padding: 10px;
@@ -258,6 +387,16 @@
justify-content: flex-end;
}
.actions.left {
justify-content: flex-start;
}
.divider {
height: 1px;
background: #eee;
margin: 6px 0;
}
.btn {
display: inline-flex;
align-items: center;