feat(settings): modernize download location settings

- Replace split 'Default Download Path' and 'All Categories Base' with a canonical baseDownloadFolder and categorySubfolders model
- Retain absolute category overrides only where required
- Update Add window to accurately reflect intended destination:
  - Single URL: specific category path
  - Multiple URLs: base folder with explanatory text
  - Manual Browse override: selected folder
- Centralize path resolution logic shared by Rust backend and UI
This commit is contained in:
NimBold
2026-06-20 19:22:20 +03:30
parent 79b579790d
commit 038f31b988
17 changed files with 1103 additions and 380 deletions
+65
View File
@@ -0,0 +1,65 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
vi.mock('@tauri-apps/api/path', () => ({
join: vi.fn(async (...parts: string[]) =>
parts
.map((part, index) => index === 0 ? part.replace(/[\\/]+$/, '') : part.replace(/^[\\/]+|[\\/]+$/g, ''))
.join('/')
)
}));
import {
DEFAULT_CATEGORY_SUBFOLDERS,
normalizeCategorySubfolder,
normalizeDownloadLocationSettings,
resolveCategoryDestination
} from './downloadLocations';
describe('download locations', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('migrates legacy derived directories without creating overrides', () => {
const settings = normalizeDownloadLocationSettings({
defaultDownloadPath: '/Users/test/Downloads',
downloadDirectories: {
Movies: '/Users/test/Downloads/Movies',
Documents: '/Users/test/Downloads/Documents'
}
});
expect(settings.baseDownloadFolder).toBe('/Users/test/Downloads');
expect(settings.categorySubfolders).toEqual(DEFAULT_CATEGORY_SUBFOLDERS);
expect(settings.categoryDirectoryOverrides).toEqual({});
});
it('preserves legacy custom category directories as overrides', () => {
const settings = normalizeDownloadLocationSettings({
defaultDownloadPath: '/Users/test/Downloads',
downloadDirectories: {
Video: '/Volumes/Media/Movies'
}
});
expect(settings.categoryDirectoryOverrides.Movies).toBe('/Volumes/Media/Movies');
});
it('resolves automatic and overridden category destinations', async () => {
const automatic = normalizeDownloadLocationSettings({
baseDownloadFolder: '/Users/test/Downloads',
categorySubfolders: { Movies: 'Video Files' }
});
expect(await resolveCategoryDestination(automatic, 'Movies'))
.toBe('/Users/test/Downloads/Video Files');
automatic.categoryDirectoryOverrides.Movies = '/Volumes/Media';
expect(await resolveCategoryDestination(automatic, 'Movies')).toBe('/Volumes/Media');
});
it('keeps category subfolders relative and permits nested folders', () => {
expect(normalizeCategorySubfolder('../Media/./Movies', 'Movies')).toBe('Media/Movies');
expect(normalizeCategorySubfolder('C:\\Media\\Movies', 'Movies')).toBe('Media/Movies');
expect(normalizeCategorySubfolder('../../', 'Movies')).toBe('Movies');
});
});