feat: remember and normalize downloaded subfolder paths for reuse in download targets

This commit is contained in:
Dariusz L
2026-06-24 22:12:06 +02:00
parent 5445dd4ac0
commit 46b1e155b6
2 changed files with 85 additions and 0 deletions
@@ -492,6 +492,18 @@ export const resolveDownloadMethods = {
if (progress.filename) info.filename = progress.filename;
},
rememberDownloadSubfolderAfterCompletion(info = {}, progress = {}) {
const category = info?.category || progress?.category || '';
const subfolder = info?.subfolder || progress?.subfolder || '';
if (!category || !subfolder) return;
this.rememberDownloadedSubfolder?.(
category,
subfolder,
info?.baseDirectory || progress?.base_directory || progress?.baseDirectory || ''
);
},
renderDownloadStatusMessage(message, type, progress = {}, info = {}) {
const contextMenuModel = this.getDownloadFolderContext(progress, info);
return this.renderStatusMessage(message, type, {
@@ -742,6 +754,7 @@ export const resolveDownloadMethods = {
const snapshot = this.rememberDownloadSnapshotForMissing(info.missing, {
downloadId,
category: info.category || '',
subfolder: info.subfolder || '',
filename: progress.filename || info.filename || '',
downloadPath: progress.path || info.downloadPath || '',
downloadDirectory: progress.directory || info.downloadDirectory || '',
@@ -1261,6 +1274,7 @@ export const resolveDownloadMethods = {
this.rememberDownloadSnapshotForMissing(missing, {
downloadId: null,
category,
subfolder,
filename,
downloadPath: '',
downloadDirectory: '',
@@ -1340,6 +1354,7 @@ export const resolveDownloadMethods = {
progressDiv,
downloadBtn,
category,
subfolder,
filename,
downloadPath: data.path || '',
downloadDirectory: data.directory || '',
@@ -1450,6 +1465,7 @@ export const resolveDownloadMethods = {
isActive: false
});
this.renderDownloadSnapshot(downloadId, completedSnapshot, { progressDiv, downloadBtn });
this.rememberDownloadSubfolderAfterCompletion(info, progress);
this.rememberCompletedDownloadHistory?.(downloadId, info, progress);
delete this.activeDownloads[downloadId];
this.updateDownloadAllButtonState();
@@ -2515,6 +2531,7 @@ export const resolveDownloadMethods = {
this.rememberDownloadSnapshotForMissing(missing, {
downloadId: null,
category: targetSelection.category,
subfolder: targetSelection.subfolder,
filename,
downloadPath: '',
downloadDirectory: '',
@@ -2589,6 +2606,7 @@ export const resolveDownloadMethods = {
progressDiv,
downloadBtn: btn,
category: targetSelection.category,
subfolder: targetSelection.subfolder,
filename,
downloadPath: data.path || '',
downloadDirectory: data.directory || '',
@@ -503,6 +503,73 @@ export const downloadTargetMethods = {
return this.downloadSubfolders.get(this.normalizeDownloadCategory(category)) || [];
},
normalizeDownloadSubfolderPath(value = '') {
return String(value || '')
.replace(/\//g, '\\')
.split('\\')
.map(part => part.trim())
.filter(part => part && part !== '.' && part !== '..')
.join('\\');
},
getDownloadSubfolderPrefixes(value = '') {
const parts = this.normalizeDownloadSubfolderPath(value).split('\\').filter(Boolean);
const prefixes = [];
let current = '';
parts.forEach(part => {
current = current ? `${current}\\${part}` : part;
prefixes.push(current);
});
return prefixes;
},
rememberDownloadedSubfolder(category = '', subfolder = '', baseDirectory = '') {
const key = this.normalizeDownloadCategory(category);
if (!key || key === 'unknown') return;
const prefixes = this.getDownloadSubfolderPrefixes(subfolder);
if (!prefixes.length) return;
const cached = this.downloadSubfolders.get(key);
if (!Array.isArray(cached)) {
this.downloadSubfolders.delete(key);
return;
}
const targetBaseDirectory = String(baseDirectory || this.getDownloadTargetBaseDirectory(key) || '');
const normalizeBase = (value = '') => String(value || '')
.replace(/[\\/]+/g, '/')
.replace(/\/+$/g, '')
.toLowerCase();
const normalizeValue = (value = '') => this.normalizeDownloadSubfolderPath(value).toLowerCase();
const makeIdentity = (value = '', base = '') => `${normalizeValue(value)}::${normalizeBase(base)}`;
const known = new Set(cached.map(option => makeIdentity(
this.getSubfolderOptionValue(option),
this.getSubfolderOptionBaseDirectory(option)
)));
const next = [...cached];
prefixes.forEach(prefix => {
const identity = makeIdentity(prefix, targetBaseDirectory);
if (known.has(identity)) return;
known.add(identity);
next.push({
value: prefix,
label: prefix,
base_directory: targetBaseDirectory
});
});
next.sort((a, b) => {
const valueCompare = this.getSubfolderOptionValue(a)
.localeCompare(this.getSubfolderOptionValue(b), undefined, { sensitivity: 'base' });
if (valueCompare !== 0) return valueCompare;
return this.getSubfolderOptionBaseDirectory(a)
.localeCompare(this.getSubfolderOptionBaseDirectory(b), undefined, { sensitivity: 'base' });
});
this.downloadSubfolders.set(key, next);
},
getSubfolderOptionValue(option) {
return String(
option && typeof option === 'object'