settings.html
⎇
Raw
1{{define "settings"}}
2<div class="page-header">
3 <h2>Settings</h2>
4</div>
5
6<div class="settings-layout">
7 <section class="settings-section">
8 <h3>Global Settings</h3>
9 <form method="post" action="/settings">
10 <div class="form-group">
11 <label for="refresh_interval">Auto-refresh Interval (seconds)</label>
12 <input type="number" id="refresh_interval" name="refresh_interval" min="1" max="300"
13 value="{{.Data.Settings.RefreshInterval}}">
14 </div>
15
16 <div class="form-group checkbox">
17 <label>
18 <input type="checkbox" name="auto_refresh_library" value="1"
19 {{if .Data.Settings.AutoRefreshLibrary}}checked{{end}}>
20 Auto-refresh Library page
21 </label>
22 </div>
23
24 <div class="form-group checkbox">
25 <label>
26 <input type="checkbox" name="auto_refresh_downloads" value="1"
27 {{if .Data.Settings.AutoRefreshDownloads}}checked{{end}}>
28 Auto-refresh Queue page
29 </label>
30 </div>
31
32 <div class="form-actions">
33 <button type="submit" class="primary">Save Settings</button>
34 </div>
35 </form>
36 </section>
37
38 <section class="settings-section">
39 <h3>Theme</h3>
40 <div class="theme-selector">
41 <form method="post" action="/theme" class="inline">
42 <input type="hidden" name="theme" value="light">
43 <button type="submit" class="secondary {{if eq .Theme "light"}}active{{end}}">Light</button>
44 </form>
45 <form method="post" action="/theme" class="inline">
46 <input type="hidden" name="theme" value="dark">
47 <button type="submit" class="secondary {{if eq .Theme "dark"}}active{{end}}">Dark</button>
48 </form>
49 <form method="post" action="/theme" class="inline">
50 <input type="hidden" name="theme" value="auto">
51 <button type="submit" class="secondary {{if eq .Theme "auto"}}active{{end}}">Auto</button>
52 </form>
53 </div>
54 </section>
55
56 <section class="settings-section">
57 <h3>Presets</h3>
58
59 <div class="presets-list">
60 {{range .Data.Presets}}
61 <div class="preset-card">
62 <div class="preset-header">
63 <h4>{{.Name}} {{if .IsDefault}}<span class="badge">default</span>{{end}}</h4>
64 <details class="delete-overlay">
65 <summary class="button small danger">Delete</summary>
66 <div class="overlay-panel">
67 <p>Are you sure you want to delete preset <strong>{{.Name}}</strong>?</p>
68 <form method="post" action="/settings/presets/{{.ID}}/delete" class="form-actions">
69 <button type="submit" class="danger">Yes, Delete</button>
70 </form>
71 </div>
72 </details>
73 </div>
74
75 {{if .Description}}
76 <p class="preset-description">{{.Description}}</p>
77 {{end}}
78
79 <div class="preset-flags">
80 <strong>Effective flags:</strong>
81 <pre>{{presetFlags .}}</pre>
82 </div>
83
84 <div class="preset-actions">
85 <details>
86 <summary class="button small"><span class="edit-text">Edit</span><span class="cancel-text">Cancel</span></summary>
87 <form method="post" action="/settings/presets/{{.ID}}" class="edit-form">
88 {{template "preset_form" .}}
89 <div class="form-actions">
90 <button type="submit" class="primary">Update Preset</button>
91 </div>
92 </form>
93 </details>
94 </div>
95 </div>
96 {{else}}
97 <p>No presets yet. Create one below.</p>
98 {{end}}
99 </div>
100
101 <h4>Create Preset</h4>
102 <form method="post" action="/settings/presets" class="form-card">
103 {{template "preset_form_create" .}}
104
105 <div class="form-actions">
106 <button type="submit" class="primary">Create Preset</button>
107 </div>
108 </form>
109 </section>
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 checkbox">
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 checkbox">
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="m4a" {{if .}}{{if eq .AudioFormat "m4a"}}checked{{end}}{{end}}> M4A</label>
204 <label><input type="radio" name="audio_format" value="ogg" {{if .}}{{if eq .AudioFormat "ogg"}}checked{{end}}{{end}}> OGG</label>
205 <label><input type="radio" name="audio_format" value="flac" {{if .}}{{if eq .AudioFormat "flac"}}checked{{end}}{{end}}> FLAC</label>
206 <label><input type="radio" name="audio_format" value="wav" {{if .}}{{if eq .AudioFormat "wav"}}checked{{end}}{{end}}> WAV</label>
207 <label><input type="radio" name="audio_format" value="opus" {{if .}}{{if eq .AudioFormat "opus"}}checked{{end}}{{end}}> Opus</label>
208 <label><input type="radio" name="audio_format" value="aac" {{if .}}{{if eq .AudioFormat "aac"}}checked{{end}}{{end}}> AAC</label>
209 <label><input type="radio" name="audio_format" value="" {{if .}}{{if eq .AudioFormat ""}}checked{{end}}{{else}}checked{{end}}> Default (no conversion)</label>
210 </div>
211 </div>
212 </div>
213 </div>
214
215 <div class="conditional-section">
216 <div class="form-group checkbox">
217 <label>
218 <input type="checkbox" name="embed_subs" value="1" class="conditional-trigger"
219 {{if .}}{{if .EmbedSubs}}checked{{end}}{{end}}>
220 Embed subtitles
221 </label>
222 </div>
223 <div class="conditional-content">
224 <div class="form-group">
225 <label for="sub_langs">Subtitle Languages</label>
226 <input type="text" name="sub_langs" placeholder="e.g., en,de,fr or all"
227 value="{{if .}}{{.SubLangs}}{{else}}en{{end}}">
228 <small>Comma-separated language codes or "all"</small>
229 </div>
230 </div>
231 </div>
232
233 <div class="form-group checkbox">
234 <label>
235 <input type="checkbox" name="embed_thumbnail" value="1"
236 {{if .}}{{if .EmbedThumbnail}}checked{{end}}{{else}}checked{{end}}>
237 Embed thumbnail
238 </label>
239 </div>
240
241 <div class="form-group checkbox">
242 <label>
243 <input type="checkbox" name="embed_metadata" value="1"
244 {{if .}}{{if .EmbedMetadata}}checked{{end}}{{else}}checked{{end}}>
245 Embed metadata
246 </label>
247 </div>
248
249 <div class="form-group checkbox">
250 <label>
251 <input type="checkbox" name="write_info_json" value="1"
252 {{if .}}{{if .WriteInfoJSON}}checked{{end}}{{else}}checked{{end}}>
253 Write info JSON
254 </label>
255 </div>
256
257 <div class="form-group">
258 <label for="output_template">Output Template</label>
259 <input type="text" name="output_template"
260 value="{{if .}}{{.OutputTemplate}}{{else}}%(title)s [%(id)s].%(ext)s{{end}}">
261 <small>Use / for subfolders. Example: %(playlist_title)s/%(title)s.%(ext)s</small>
262 </div>
263
264 <div class="form-group">
265 <label for="custom_flags">Custom Flags</label>
266 <textarea name="custom_flags" rows="2" placeholder="Any additional yt-dlp flags...">{{if .}}{{.CustomFlags}}{{end}}</textarea>
267 </div>
268{{end}}
269
270{{define "preset_form_create"}}
271 <div class="form-group">
272 <label for="name">Name *</label>
273 <input type="text" name="name" required>
274 </div>
275
276 <div class="form-group">
277 <label for="description">Description</label>
278 <input type="text" name="description">
279 </div>
280
281 <div class="form-group checkbox">
282 <label>
283 <input type="checkbox" name="is_default" value="1">
284 Set as default preset
285 </label>
286 </div>
287
288 <div class="conditional-section">
289 <label>Format Selection</label>
290 <div class="radio-group format-mode">
291 <label>
292 <input type="radio" name="format_mode" value="default" class="conditional-trigger" checked>
293 yt-dlp default
294 </label>
295 <label>
296 <input type="radio" name="format_mode" value="preset" class="conditional-trigger">
297 Preset format
298 </label>
299 <label>
300 <input type="radio" name="format_mode" value="custom" class="conditional-trigger">
301 Custom format
302 </label>
303 </div>
304
305 <div class="conditional-content format-preset">
306 <div class="form-row">
307 <div class="form-group">
308 <label for="format">Format</label>
309 <select name="format">
310 <option value="best" selected>best</option>
311 <option value="worst">worst</option>
312 <option value="bestvideo+bestaudio">bestvideo+bestaudio</option>
313 <option value="bestvideo">bestvideo</option>
314 <option value="bestaudio">bestaudio</option>
315 </select>
316 </div>
317
318 <div class="form-group">
319 <label for="quality">Max Quality</label>
320 <select name="quality">
321 <option value="" selected>No limit</option>
322 <option value="720">720p</option>
323 <option value="1080">1080p</option>
324 <option value="1440">1440p</option>
325 <option value="2160">4K (2160p)</option>
326 </select>
327 </div>
328 </div>
329 </div>
330
331 <div class="conditional-content format-custom">
332 <div class="form-group">
333 <label for="custom_format">Custom Format</label>
334 <input type="text" name="custom_format" placeholder="e.g., bestvideo+bestaudio/best or format ID like 22">
335 <small>Overrides the format selection. Use yt-dlp format syntax.</small>
336 </div>
337 </div>
338 </div>
339
340 <div class="conditional-section">
341 <div class="form-group checkbox">
342 <label>
343 <input type="checkbox" name="extract_audio" value="1" class="conditional-trigger">
344 Extract audio only
345 </label>
346 </div>
347 <div class="conditional-content">
348 <div class="form-group">
349 <label>Audio Format</label>
350 <div class="radio-group">
351 <label><input type="radio" name="audio_format" value="mp3"> MP3</label>
352 <label><input type="radio" name="audio_format" value="m4a"> M4A</label>
353 <label><input type="radio" name="audio_format" value="ogg"> OGG</label>
354 <label><input type="radio" name="audio_format" value="flac"> FLAC</label>
355 <label><input type="radio" name="audio_format" value="wav"> WAV</label>
356 <label><input type="radio" name="audio_format" value="opus"> Opus</label>
357 <label><input type="radio" name="audio_format" value="aac"> AAC</label>
358 <label><input type="radio" name="audio_format" value="" checked> Default (no conversion)</label>
359 </div>
360 </div>
361 </div>
362 </div>
363
364 <div class="conditional-section">
365 <div class="form-group checkbox">
366 <label>
367 <input type="checkbox" name="embed_subs" value="1" class="conditional-trigger">
368 Embed subtitles
369 </label>
370 </div>
371 <div class="conditional-content">
372 <div class="form-group">
373 <label for="sub_langs">Subtitle Languages</label>
374 <input type="text" name="sub_langs" placeholder="e.g., en,de,fr or all" value="en">
375 <small>Comma-separated language codes or "all"</small>
376 </div>
377 </div>
378 </div>
379
380 <div class="form-group checkbox">
381 <label>
382 <input type="checkbox" name="embed_thumbnail" value="1" checked>
383 Embed thumbnail
384 </label>
385 </div>
386
387 <div class="form-group checkbox">
388 <label>
389 <input type="checkbox" name="embed_metadata" value="1" checked>
390 Embed metadata
391 </label>
392 </div>
393
394 <div class="form-group checkbox">
395 <label>
396 <input type="checkbox" name="write_info_json" value="1" checked>
397 Write info JSON
398 </label>
399 </div>
400
401 <div class="form-group">
402 <label for="output_template">Output Template</label>
403 <input type="text" name="output_template" value="%(title)s [%(id)s].%(ext)s">
404 <small>Use / for subfolders. Example: %(playlist_title)s/%(title)s.%(ext)s</small>
405 </div>
406
407 <div class="form-group">
408 <label for="custom_flags">Custom Flags</label>
409 <textarea name="custom_flags" rows="2" placeholder="Any additional yt-dlp flags..."></textarea>
410 </div>
411{{end}}
412