Skip to content

Commit fe6511d

Browse files
authored
Merge pull request #6 from ryzenpay/main
audio selector change, variable hotfixes
2 parents 4aaf6e5 + ddf8e1a commit fe6511d

8 files changed

Lines changed: 783 additions & 88 deletions

File tree

src/app.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<meta charset="utf-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1" />
66
<meta name="text-scale" content="scale" />
7+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
8+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
79
%sveltekit.head%
810
</head>
911
<body data-sveltekit-preload-data="hover">

src/lib/components/download/DownloadForm.svelte

Lines changed: 101 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import { onMount } from "svelte";
33
44
let url = $state("");
5-
let selectedProfileId = $state("");
5+
let selectedVideoProfileId = $state<string | null>(null);
6+
let selectedAudioProfileId = $state<string | null>(null);
67
let saveToLibrary = $state(false);
78
let profiles = $state<any[]>([]);
89
let loading = $state(false);
@@ -14,8 +15,8 @@
1415
let newProfileName = $state("");
1516
1617
// Basic mode stackable options
18+
let audioQuality = $state("5");
1719
let basicOptions = $state({ sponsorblock: false, subtitles: false, metadata: false });
18-
let audioQuality = $state("0");
1920
2021
// Advanced flag state
2122
let flags = $state<Record<string, { enabled: boolean; value: string }>>({});
@@ -720,6 +721,8 @@
720721
expandedCategories = next;
721722
}
722723
724+
let activeProfileId = $derived(selectedVideoProfileId ?? selectedAudioProfileId);
725+
723726
function buildBasicFlags(): string[] {
724727
const result: string[] = [];
725728
if (basicOptions.sponsorblock) {
@@ -731,13 +734,13 @@
731734
if (basicOptions.metadata) {
732735
result.push("--embed-metadata", "--embed-chapters");
733736
}
734-
const profile = profiles.find((p: any) => p.id === selectedProfileId);
737+
if (selectedVideoProfileId) {
738+
result.push("--audio-quality", audioQuality);
739+
}
740+
const profile = profiles.find((p: any) => p.id === activeProfileId);
735741
if (saveToLibrary && !(profile?.audioOnly)) {
736742
result.push("--write-thumbnail");
737743
}
738-
if (profile && !profile.audioOnly && audioQuality !== "0") {
739-
result.push("--audio-quality", audioQuality);
740-
}
741744
return result;
742745
}
743746
@@ -817,10 +820,15 @@
817820
if (profilesRes.ok) {
818821
profiles = await profilesRes.json();
819822
const defaultProfile = profiles.find((p: any) => p.isDefault);
820-
if (defaultProfile) {
821-
selectedProfileId = defaultProfile.id;
822-
loadProfileFlags(defaultProfile);
823+
if (defaultProfile && !defaultProfile.audioOnly) {
824+
selectedVideoProfileId = defaultProfile.id;
823825
}
826+
const defaultAudio = profiles.find((p: any) => p.isSystem && p.audioOnly);
827+
if (defaultAudio) {
828+
selectedAudioProfileId = defaultAudio.id;
829+
}
830+
const active = profiles.find((p: any) => p.id === activeProfileId);
831+
if (active) loadProfileFlags(active);
824832
}
825833
if (settingsRes.ok) {
826834
const settings = await settingsRes.json();
@@ -832,15 +840,15 @@
832840
e.preventDefault();
833841
error = "";
834842
835-
if (!url || !selectedProfileId) {
843+
if (!url || !activeProfileId) {
836844
error = "Please enter a URL and select a profile";
837845
return;
838846
}
839847
840848
loading = true;
841849
842850
try {
843-
const body: any = { url, profileId: selectedProfileId, saveToLibrary };
851+
const body: any = { url, profileId: activeProfileId, saveToLibrary };
844852
if (advancedMode) {
845853
const cf = buildCustomFlags();
846854
if (cf.length > 0) body.customFlags = cf;
@@ -893,7 +901,11 @@
893901
} else {
894902
profiles = [...profiles, profile];
895903
}
896-
selectedProfileId = profile.id;
904+
if (profile.audioOnly) {
905+
selectedAudioProfileId = profile.id;
906+
} else {
907+
selectedVideoProfileId = profile.id;
908+
}
897909
showSaveDialog = false;
898910
newProfileName = "";
899911
} catch (e: any) {
@@ -905,34 +917,54 @@
905917
906918
function resetToDefaults() {
907919
const sysDefault = profiles.find((p: any) => p.isDefault);
908-
if (sysDefault) {
909-
selectedProfileId = sysDefault.id;
910-
loadProfileFlags(sysDefault);
920+
if (sysDefault && !sysDefault.audioOnly) {
921+
selectedVideoProfileId = sysDefault.id;
911922
}
923+
const defaultAudio = profiles.find((p: any) => p.isSystem && p.audioOnly);
924+
if (defaultAudio) {
925+
selectedAudioProfileId = defaultAudio.id;
926+
}
927+
const active = profiles.find((p: any) => p.id === activeProfileId);
928+
if (active) loadProfileFlags(active);
912929
newProfileName = "";
913930
showSaveDialog = false;
914931
}
915932
916-
function selectProfile(id: string) {
917-
selectedProfileId = id;
933+
function selectVideoProfile(id: string) {
934+
selectedVideoProfileId = selectedVideoProfileId === id ? null : id;
935+
if (selectedVideoProfileId) selectedAudioProfileId = null;
936+
if (advancedMode) {
937+
const profile = profiles.find((p) => p.id === activeProfileId);
938+
if (profile) loadProfileFlags(profile);
939+
}
940+
}
941+
942+
function selectAudioProfile(id: string) {
943+
selectedAudioProfileId = id;
944+
selectedVideoProfileId = null;
918945
if (advancedMode) {
919946
const profile = profiles.find((p) => p.id === id);
920947
if (profile) loadProfileFlags(profile);
921948
}
949+
}
950+
951+
function selectProfile(id: string) {
952+
if (activeProfileId === id) {
953+
resetToDefaults();
954+
return;
955+
}
956+
const profile = profiles.find((p) => p.id === id);
957+
if (profile?.audioOnly) {
958+
selectAudioProfile(id);
959+
} else {
960+
selectVideoProfile(id);
961+
}
922962
if (showSaveDialog) {
923963
const custom = customProfiles.find((p) => p.id === id);
924964
newProfileName = custom ? custom.name : "";
925965
}
926966
}
927967
928-
function handleFormClick(e: MouseEvent) {
929-
if (!advancedMode) return;
930-
if (!customProfiles.some((p) => p.id === selectedProfileId)) return;
931-
const target = e.target as HTMLElement;
932-
if (target.closest(".advanced-panel, .profile-btn, .mode-toggle")) return;
933-
resetToDefaults();
934-
}
935-
936968
let videoProfiles = $derived(
937969
profiles.filter((p: any) => p.isSystem && !p.audioOnly).slice(0, 4),
938970
);
@@ -943,9 +975,7 @@
943975
</script>
944976

945977
<div class="download-form">
946-
<!-- svelte-ignore a11y_click_events_have_key_events -->
947-
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
948-
<form onsubmit={handleSubmit} onclick={handleFormClick}>
978+
<form onsubmit={handleSubmit}>
949979
<div class="form-header">
950980
<label for="url">Video URL</label>
951981
<button
@@ -955,7 +985,7 @@
955985
onclick={() => {
956986
advancedMode = !advancedMode;
957987
if (advancedMode) {
958-
const profile = profiles.find((p) => p.id === selectedProfileId);
988+
const profile = profiles.find((p) => p.id === activeProfileId);
959989
if (profile) loadProfileFlags(profile);
960990
}
961991
}}
@@ -1004,34 +1034,61 @@
10041034
<button
10051035
type="button"
10061036
class="profile-btn"
1007-
class:active={selectedProfileId === profile.id}
1008-
onclick={() => selectProfile(profile.id)}
1037+
class:active={selectedVideoProfileId === profile.id}
1038+
onclick={() => selectVideoProfile(profile.id)}
10091039
disabled={loading}
10101040
>
10111041
{profile.name}{#if profile.isDefault}
10121042
*{/if}
10131043
</button>
10141044
{/each}
10151045
</div>
1016-
<div class="audio-quality-row">
1017-
<span class="audio-quality-label">Audio Quality</span>
1018-
<select bind:value={audioQuality} disabled={loading} class="audio-quality-select">
1019-
<option value="0">High</option>
1020-
<option value="5">Medium</option>
1021-
<option value="9">Low</option>
1022-
</select>
1023-
</div>
10241046
</div>
10251047

1048+
{#if selectedVideoProfileId}
1049+
<div class="profile-group">
1050+
<span class="profile-group-label">Audio Quality</span>
1051+
<div class="profile-buttons">
1052+
<button
1053+
type="button"
1054+
class="profile-btn"
1055+
class:active={audioQuality === "0"}
1056+
onclick={() => audioQuality = "0"}
1057+
disabled={loading}
1058+
>
1059+
High
1060+
</button>
1061+
<button
1062+
type="button"
1063+
class="profile-btn"
1064+
class:active={audioQuality === "5"}
1065+
onclick={() => audioQuality = "5"}
1066+
disabled={loading}
1067+
>
1068+
Medium
1069+
</button>
1070+
<button
1071+
type="button"
1072+
class="profile-btn"
1073+
class:active={audioQuality === "9"}
1074+
onclick={() => audioQuality = "9"}
1075+
disabled={loading}
1076+
>
1077+
Low
1078+
</button>
1079+
</div>
1080+
</div>
1081+
{/if}
1082+
10261083
<div class="profile-group">
1027-
<span class="profile-group-label">Audio Only</span>
1084+
<span class="profile-group-label">Audio (only)</span>
10281085
<div class="profile-buttons">
10291086
{#each audioProfiles as profile}
10301087
<button
10311088
type="button"
10321089
class="profile-btn"
1033-
class:active={selectedProfileId === profile.id}
1034-
onclick={() => selectProfile(profile.id)}
1090+
class:active={selectedAudioProfileId === profile.id}
1091+
onclick={() => selectAudioProfile(profile.id)}
10351092
disabled={loading}
10361093
>
10371094
{profile.name}
@@ -1072,7 +1129,6 @@
10721129
</button>
10731130
</div>
10741131
</div>
1075-
10761132
</div>
10771133
{:else if customProfiles.length > 0}
10781134
<div class="profile-quick-select">
@@ -1083,7 +1139,7 @@
10831139
<button
10841140
type="button"
10851141
class="profile-btn custom"
1086-
class:active={selectedProfileId === profile.id}
1142+
class:active={activeProfileId === profile.id}
10871143
onclick={() => selectProfile(profile.id)}
10881144
disabled={loading}
10891145
>
@@ -1109,7 +1165,7 @@
11091165
class="btn-save-profile"
11101166
onclick={() => {
11111167
const custom = customProfiles.find(
1112-
(p) => p.id === selectedProfileId,
1168+
(p) => p.id === activeProfileId,
11131169
);
11141170
newProfileName = custom ? custom.name : "";
11151171
showSaveDialog = !showSaveDialog;
@@ -1497,36 +1553,6 @@
14971553
color: var(--text-primary);
14981554
}
14991555
1500-
.audio-quality-row {
1501-
display: flex;
1502-
align-items: center;
1503-
gap: var(--spacing-sm);
1504-
margin-top: var(--spacing-sm);
1505-
}
1506-
1507-
.audio-quality-label {
1508-
font-size: 0.75rem;
1509-
color: var(--text-tertiary);
1510-
font-weight: 500;
1511-
}
1512-
1513-
.audio-quality-select {
1514-
flex: 1;
1515-
padding: var(--spacing-sm) var(--spacing-md);
1516-
background: var(--bg-tertiary);
1517-
border: 1px solid var(--border);
1518-
border-radius: var(--radius-md);
1519-
color: var(--text-secondary);
1520-
font-size: 0.875rem;
1521-
cursor: pointer;
1522-
transition: all var(--transition-fast);
1523-
}
1524-
1525-
.audio-quality-select:focus {
1526-
outline: none;
1527-
border-color: var(--accent-primary);
1528-
}
1529-
15301556
.profile-btn.custom {
15311557
border-style: dashed;
15321558
border-color: var(--accent-dim);

0 commit comments

Comments
 (0)