webui: category default download location in add modal

The add-torrent save path now shows the selected category's default
location (its own save path, else the global default), greyed and
read-only. Clicking makes it editable; an overridden path then stays
put when the category changes. Resolves the "category default location
does nothing" issue by feeding the category's save path into the add.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ookami125 2026-06-23 00:33:35 -04:00
parent d55fc35c72
commit d8c4a96e88
2 changed files with 35 additions and 1 deletions

View file

@ -496,6 +496,14 @@ async function confirmDelete(hashes) {
}
/* ---------- add torrent modal ---------- */
// Default download location for a category: its own save path if set,
// otherwise the global default.
function categoryDefaultPath(catName) {
const c = state.meta.categories.find((x) => x.name === catName);
if (c && c.savePath) return c.savePath;
return state.meta.preferences.save_path || '/data/downloads';
}
function openAddModal() {
const cats = '<option value="" selected>Uncategorized</option>' +
state.meta.categories.filter((c) => c.name).map((c) => `<option value="${f.esc(c.name)}">${f.esc(c.name)}</option>`).join('');
@ -519,7 +527,9 @@ function openAddModal() {
</div>
</div></div>
<div class="field"><label>Save path</label>
<input type="text" id="addPath" value="${f.esc(state.meta.preferences.save_path || '/data/downloads')}" /></div>
<input type="text" id="addPath" class="path-default" readonly title="Click to change"
value="${f.esc(categoryDefaultPath(''))}" />
<div class="dim" id="addPathHint" style="font-size:12px;margin-top:4px">Category default click to change.</div></div>
<div class="checks">
<label><input type="checkbox" id="addPaused"> Add paused</label>
<label><input type="checkbox" id="addSeq"> Sequential download</label>
@ -606,6 +616,26 @@ function openAddModal() {
document.getElementById('addTagAdd').addEventListener('click', addTag);
input.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); addTag(); } });
})();
// save path: greyed default that tracks the category until the user edits it
(() => {
const path = document.getElementById('addPath');
const cat = document.getElementById('addCat');
const hint = document.getElementById('addPathHint');
let manual = false;
const enable = () => {
if (manual) return;
manual = true;
path.readOnly = false;
path.classList.remove('path-default');
hint.textContent = "Custom location — won't change with the category.";
path.focus();
path.select();
};
path.addEventListener('mousedown', (e) => { if (!manual) { e.preventDefault(); enable(); } });
cat.addEventListener('change', () => {
if (!manual) path.value = categoryDefaultPath(cat.value);
});
})();
// live readout of the chosen file(s)
document.getElementById('addFile').addEventListener('change', async (e) => {
const info = document.getElementById('addFileInfo');