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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user