settings.html
⎇
Raw
1{{define "settings"}}
2<div class="page-header">
3 <h2>Settings</h2>
4</div>
5
6<div class="settings-layout">
7 <article>
8 <h3>Global Settings</h3>
9 <form method="post" action="/settings">
10 <label for="refresh_interval">Auto-refresh Interval (seconds)</label>
11 <input type="number" id="refresh_interval" name="refresh_interval" min="1" max="300"
12 value="{{.Data.Settings.RefreshInterval}}">
13
14 <label>
15 <input type="checkbox" name="auto_refresh_library" value="1"
16 {{if .Data.Settings.AutoRefreshLibrary}}checked{{end}}>
17 Auto-refresh Library page
18 </label>
19
20 <label>
21 <input type="checkbox" name="auto_refresh_downloads" value="1"
22 {{if .Data.Settings.AutoRefreshDownloads}}checked{{end}}>
23 Auto-refresh Queue page
24 </label>
25
26 <label for="cookies">Cookies (cookies.txt format)</label>
27 <textarea id="cookies" name="cookies" rows="6" placeholder="Paste cookies.txt content here...">{{.Data.Settings.Cookies}}</textarea>
28 <small>Paste the contents of a cookies.txt file. Will be passed to yt-dlp via --cookies.</small>
29
30 <div class="form-actions">
31 <button type="submit" class="primary">Save Settings</button>
32 </div>
33 </form>
34 </article>
35
36 <article>
37 <h3>Theme</h3>
38 <div class="theme-selector">
39 <form method="post" action="/theme" class="inline">
40 <input type="hidden" name="theme" value="light">
41 <button type="submit" class="secondary {{if eq .Theme "light"}}active{{end}}">Light</button>
42 </form>
43 <form method="post" action="/theme" class="inline">
44 <input type="hidden" name="theme" value="dark">
45 <button type="submit" class="secondary {{if eq .Theme "dark"}}active{{end}}">Dark</button>
46 </form>
47 <form method="post" action="/theme" class="inline">
48 <input type="hidden" name="theme" value="auto">
49 <button type="submit" class="secondary {{if eq .Theme "auto"}}active{{end}}">Auto</button>
50 </form>
51 </div>
52 </article>
53
54 <article>
55 <h3>Presets</h3>
56
57 <div class="presets-list">
58 {{range .Data.Presets}}
59 <article>
60 <div class="preset-header">
61 <h4>{{.Name}} {{if .IsDefault}}<span class="badge">default</span>{{end}}</h4>
62 <details class="delete-overlay">
63 <summary role="button" class="small danger">Delete</summary>
64 <div class="overlay-panel">
65 <p>Are you sure you want to delete preset <strong>{{.Name}}</strong>?</p>
66 <form method="post" action="/settings/presets/{{.ID}}/delete" class="form-actions">
67 <button type="submit" class="danger">Yes, Delete</button>
68 </form>
69 </div>
70 </details>
71 </div>
72
73 {{if .Description}}
74 <p class="preset-description">{{.Description}}</p>
75 {{end}}
76
77 <div class="preset-flags">
78 <strong>Effective flags:</strong>
79 <pre>{{presetFlags .}}</pre>
80 </div>
81
82 <div class="preset-actions">
83 <details>
84 <summary role="button" class="small"><span class="edit-text">Edit</span><span class="cancel-text">Cancel</span></summary>
85 <form method="post" action="/settings/presets/{{.ID}}" class="edit-form">
86 {{template "preset_form" .}}
87 <div class="form-actions">
88 <button type="submit" class="primary">Update Preset</button>
89 </div>
90 </form>
91 </details>
92 </div>
93 </article>
94 {{else}}
95 <p>No presets yet. Create one below.</p>
96 {{end}}
97 </div>
98
99 <article>
100 <h4>Create Preset</h4>
101 <form method="post" action="/settings/presets">
102 {{template "preset_form_create" .}}
103
104 <div class="form-actions">
105 <button type="submit" class="primary">Create Preset</button>
106 </div>
107 </form>
108 </article>
109 </article>
110</div>
111{{end}}
112
113{{define "preset_form"}}
114 <div class="form-group">
115 <label for="name">Name *</label>
116 <input type="text" name="name" required
117 value="{{if .}}{{.Name}}{{end}}">
118 </div>
119
120 <div class="form-group">
121 <label for="description">Description</label>
122 <input type="text" name="description"
123 value="{{if .}}{{.Description}}{{end}}">
124 </div>
125
126 <div class="form-group">
127 <label>
128 <input type="checkbox" name="is_default" value="1"
129 {{if .}}{{if .IsDefault}}checked{{end}}{{end}}>
130 Set as default preset
131 </label>
132 </div>
133
134 <div class="conditional-section">
135 <label>Format Selection</label>
136 <div class="radio-group format-mode">
137 <label>
138 <input type="radio" name="format_mode" value="default" class="conditional-trigger"
139 {{if .}}{{if or (eq .FormatMode "default") (eq .FormatMode "")}}checked{{end}}{{else}}checked{{end}}>
140 yt-dlp default
141 </label>
142 <label>
143 <input type="radio" name="format_mode" value="preset" class="conditional-trigger"
144 {{if .}}{{if eq .FormatMode "preset"}}checked{{end}}{{end}}>
145 Preset format
146 </label>
147 <label>
148 <input type="radio" name="format_mode" value="custom" class="conditional-trigger"
149 {{if .}}{{if eq .FormatMode "custom"}}checked{{end}}{{end}}>
150 Custom format
151 </label>
152 </div>
153
154 <div class="conditional-content format-preset">
155 <div class="form-row">
156 <div class="form-group">
157 <label for="format">Format</label>
158 <select name="format">
159 <option value="best" {{if .}}{{if eq .Format "best"}}selected{{end}}{{end}}>best</option>
160 <option value="worst" {{if .}}{{if eq .Format "worst"}}selected{{end}}{{end}}>worst</option>
161 <option value="bestvideo+bestaudio" {{if .}}{{if eq .Format "bestvideo+bestaudio"}}selected{{end}}{{end}}>bestvideo+bestaudio</option>
162 <option value="bestvideo" {{if .}}{{if eq .Format "bestvideo"}}selected{{end}}{{end}}>bestvideo</option>
163 <option value="bestaudio" {{if .}}{{if eq .Format "bestaudio"}}selected{{end}}{{end}}>bestaudio</option>
164 </select>
165 </div>
166
167 <div class="form-group">
168 <label for="quality">Max Quality</label>
169 <select name="quality">
170 <option value="" {{if .}}{{if eq .Quality ""}}selected{{end}}{{end}}>No limit</option>
171 <option value="720" {{if .}}{{if eq .Quality "720"}}selected{{end}}{{end}}>720p</option>
172 <option value="1080" {{if .}}{{if eq .Quality "1080"}}selected{{end}}{{end}}>1080p</option>
173 <option value="1440" {{if .}}{{if eq .Quality "1440"}}selected{{end}}{{end}}>1440p</option>
174 <option value="2160" {{if .}}{{if eq .Quality "2160"}}selected{{end}}{{end}}>4K (2160p)</option>
175 </select>
176 </div>
177 </div>
178 </div>
179
180 <div class="conditional-content format-custom">
181 <div class="form-group">
182 <label for="custom_format">Custom Format</label>
183 <input type="text" name="custom_format" placeholder="e.g., bestvideo+bestaudio/best or format ID like 22"
184 value="{{if .}}{{.CustomFormat}}{{end}}">
185 <small>Overrides the format selection. Use yt-dlp format syntax.</small>
186 </div>
187 </div>
188 </div>
189
190 <div class="conditional-section">
191 <div class="form-group">
192 <label>
193 <input type="checkbox" name="extract_audio" value="1" class="conditional-trigger"
194 {{if .}}{{if .ExtractAudio}}checked{{end}}{{end}}>
195 Extract audio only
196 </label>
197 </div>
198 <div class="conditional-content">
199 <div class="form-group">
200 <label>Audio Format</label>
201 <div class="radio-group">
202 <label><input type="radio" name="audio_format" value="mp3" {{if .}}{{if eq .AudioFormat "mp3"}}checked{{end}}{{end}}> MP3</label>
203 <label><input type="radio" name="audio_format" value="flac" {{if .}}{{if eq .AudioFormat "flac"}}checked{{end}}{{end}}> FLAC</label>
204 <label><input type="radio" name="audio_format" value="wav" {{if .}}{{if eq .AudioFormat "wav"}}checked{{end}}{{end}}> WAV</label>
205 <label><input type="radio" name="audio_format" value="opus" {{if .}}{{if eq .AudioFormat "opus"}}checked{{end}}{{end}}> Opus</label>
206 <label><input type="radio" name="audio_format" value="aac" {{if .}}{{if eq .AudioFormat "aac"}}checked{{end}}{{end}}> AAC</label>
207 <label><input type="radio" name="audio_format" value="" {{if .}}{{if eq .AudioFormat ""}}checked{{end}}{{else}}checked{{end}}> Default (no conversion)</label>
208 </div>
209 </div>
210 </div>
211 </div>
212
213 <div class="conditional-section">
214 <div class="form-group">
215 <label>
216 <input type="checkbox" name="embed_subs" value="1" class="conditional-trigger"
217 {{if .}}{{if .EmbedSubs}}checked{{end}}{{end}}>
218 Embed subtitles
219 </label>
220 </div>
221 <div class="conditional-content">
222 <div class="form-group">
223 <label for="sub_langs">Subtitle Languages</label>
224 <input type="text" name="sub_langs" placeholder="e.g., en,de,fr or all"
225 value="{{if .}}{{.SubLangs}}{{else}}en{{end}}">
226 <small>Comma-separated language codes or "all"</small>
227 </div>
228 </div>
229 </div>
230
231 <div class="form-group">
232 <label>
233 <input type="checkbox" name="embed_thumbnail" value="1"
234 {{if .}}{{if .EmbedThumbnail}}checked{{end}}{{else}}checked{{end}}>
235 Embed thumbnail
236 </label>
237 </div>
238
239 <div class="form-group">
240 <label>
241 <input type="checkbox" name="embed_metadata" value="1"
242 {{if .}}{{if .EmbedMetadata}}checked{{end}}{{else}}checked{{end}}>
243 Embed metadata
244 </label>
245 </div>
246
247 <div class="form-group">
248 <label>
249 <input type="checkbox" name="write_info_json" value="1"
250 {{if .}}{{if .WriteInfoJSON}}checked{{end}}{{else}}checked{{end}}>
251 Write info JSON
252 </label>
253 </div>
254
255 <div class="form-group">
256 <label for="custom_flags">Custom Flags</label>
257 <textarea name="custom_flags" rows="2" placeholder="Any additional yt-dlp flags...">{{if .}}{{.CustomFlags}}{{end}}</textarea>
258 </div>
259{{end}}
260
261{{define "preset_form_create"}}
262 <div class="form-group">
263 <label for="name">Name *</label>
264 <input type="text" name="name" required>
265 </div>
266
267 <div class="form-group">
268 <label for="description">Description</label>
269 <input type="text" name="description">
270 </div>
271
272 <div class="form-group">
273 <label>
274 <input type="checkbox" name="is_default" value="1">
275 Set as default preset
276 </label>
277 </div>
278
279 <div class="conditional-section">
280 <label>Format Selection</label>
281 <div class="radio-group format-mode">
282 <label>
283 <input type="radio" name="format_mode" value="default" class="conditional-trigger" checked>
284 yt-dlp default
285 </label>
286 <label>
287 <input type="radio" name="format_mode" value="preset" class="conditional-trigger">
288 Preset format
289 </label>
290 <label>
291 <input type="radio" name="format_mode" value="custom" class="conditional-trigger">
292 Custom format
293 </label>
294 </div>
295
296 <div class="conditional-content format-preset">
297 <div class="form-row">
298 <div class="form-group">
299 <label for="format">Format</label>
300 <select name="format">
301 <option value="best" selected>best</option>
302 <option value="worst">worst</option>
303 <option value="bestvideo+bestaudio">bestvideo+bestaudio</option>
304 <option value="bestvideo">bestvideo</option>
305 <option value="bestaudio">bestaudio</option>
306 </select>
307 </div>
308
309 <div class="form-group">
310 <label for="quality">Max Quality</label>
311 <select name="quality">
312 <option value="" selected>No limit</option>
313 <option value="720">720p</option>
314 <option value="1080">1080p</option>
315 <option value="1440">1440p</option>
316 <option value="2160">4K (2160p)</option>
317 </select>
318 </div>
319 </div>
320 </div>
321
322 <div class="conditional-content format-custom">
323 <div class="form-group">
324 <label for="custom_format">Custom Format</label>
325 <input type="text" name="custom_format" placeholder="e.g., bestvideo+bestaudio/best or format ID like 22">
326 <small>Overrides the format selection. Use yt-dlp format syntax.</small>
327 </div>
328 </div>
329 </div>
330
331 <div class="conditional-section">
332 <div class="form-group">
333 <label>
334 <input type="checkbox" name="extract_audio" value="1" class="conditional-trigger">
335 Extract audio only
336 </label>
337 </div>
338 <div class="conditional-content">
339 <div class="form-group">
340 <label>Audio Format</label>
341 <div class="radio-group">
342 <label><input type="radio" name="audio_format" value="mp3"> MP3</label>
343 <label><input type="radio" name="audio_format" value="flac"> FLAC</label>
344 <label><input type="radio" name="audio_format" value="wav"> WAV</label>
345 <label><input type="radio" name="audio_format" value="opus"> Opus</label>
346 <label><input type="radio" name="audio_format" value="aac"> AAC</label>
347 <label><input type="radio" name="audio_format" value="" checked> Default (no conversion)</label>
348 </div>
349 </div>
350 </div>
351 </div>
352
353 <div class="conditional-section">
354 <div class="form-group">
355 <label>
356 <input type="checkbox" name="embed_subs" value="1" class="conditional-trigger">
357 Embed subtitles
358 </label>
359 </div>
360 <div class="conditional-content">
361 <div class="form-group">
362 <label for="sub_langs">Subtitle Languages</label>
363 <input type="text" name="sub_langs" placeholder="e.g., en,de,fr or all" value="en">
364 <small>Comma-separated language codes or "all"</small>
365 </div>
366 </div>
367 </div>
368
369 <div class="form-group">
370 <label>
371 <input type="checkbox" name="embed_thumbnail" value="1" checked>
372 Embed thumbnail
373 </label>
374 </div>
375
376 <div class="form-group">
377 <label>
378 <input type="checkbox" name="embed_metadata" value="1" checked>
379 Embed metadata
380 </label>
381 </div>
382
383 <div class="form-group">
384 <label>
385 <input type="checkbox" name="write_info_json" value="1" checked>
386 Write info JSON
387 </label>
388 </div>
389
390 <div class="form-group">
391 <label for="custom_flags">Custom Flags</label>
392 <textarea name="custom_flags" rows="2" placeholder="Any additional yt-dlp flags..."></textarea>
393 </div>
394{{end}}
395