Files
lidify/frontend/features/settings/components/sections/DownloadPreferencesSection.tsx
Your Name cc8d0f6969 Release v1.3.0: Multi-source downloads, audio analyzer resilience, mobile improvements
Major Features:
- Multi-source download system (Soulseek/Lidarr with fallback)
- Configurable enrichment speed control (1-5x)
- Mobile touch drag support for seek sliders
- iOS PWA media controls (Control Center, Lock Screen)
- Artist name alias resolution via Last.fm
- Circuit breaker pattern for audio analysis

Critical Fixes:
- Audio analyzer stability (non-ASCII, BrokenProcessPool, OOM)
- Discovery system race conditions and import failures
- Radio decade categorization using originalYear
- LastFM API response normalization
- Mood bucket infinite loop prevention

Security:
- Bull Board admin authentication
- Lidarr webhook signature verification
- JWT token expiration and refresh
- Encryption key validation on startup

Closes #2, #6, #9, #13, #21, #26, #31, #34, #35, #37, #40, #43
2026-01-06 20:07:33 -06:00

128 lines
4.7 KiB
TypeScript

"use client";
import { SettingsSection, SettingsRow, SettingsSelect } from "../ui";
import { SystemSettings } from "../../types";
interface DownloadPreferencesSectionProps {
settings: SystemSettings;
onUpdate: (updates: Partial<SystemSettings>) => void;
}
export function DownloadPreferencesSection({
settings,
onUpdate,
}: DownloadPreferencesSectionProps) {
// Service configuration detection
const isLidarrConfigured =
settings.lidarrEnabled === true &&
settings.lidarrUrl.trim() !== "" &&
settings.lidarrApiKey.trim() !== "";
const isSoulseekConfigured =
settings.soulseekUsername.trim() !== "" &&
settings.soulseekPassword.trim() !== "";
const areBothServicesConfigured = isLidarrConfigured && isSoulseekConfigured;
const isDisabled = !areBothServicesConfigured;
// Dynamic fallback options based on primary source
const getFallbackOptions = () => {
if (settings.downloadSource === "soulseek") {
return [
{ value: "none", label: "Skip track" },
{ value: "lidarr", label: "Download full album via Lidarr" },
];
} else {
return [
{ value: "none", label: "Skip album" },
{ value: "soulseek", label: "Try Soulseek for individual tracks" },
];
}
};
return (
<SettingsSection
id="download-preferences"
title="Download Preferences"
description="Configure how music is downloaded for playlists and discovery"
>
<SettingsRow
label="Primary Download Source"
description={
isDisabled
? "Requires both Soulseek and Lidarr to be configured"
: "Choose how to download music for imported playlists"
}
>
<SettingsSelect
value={settings.downloadSource || "soulseek"}
onChange={(v) =>
onUpdate({
downloadSource: v as "soulseek" | "lidarr",
primaryFailureFallback: "none"
})
}
options={[
{ value: "soulseek", label: "Soulseek (Per-track)" },
{ value: "lidarr", label: "Lidarr (Full albums)" },
]}
disabled={isDisabled}
/>
</SettingsRow>
<SettingsRow
label={
settings.downloadSource === "soulseek"
? "When Soulseek Fails"
: "When Lidarr Fails"
}
description={
isDisabled
? "Requires both Soulseek and Lidarr to be configured"
: settings.downloadSource === "soulseek"
? "What to do if a track can't be found on Soulseek"
: "What to do if an album can't be found on Lidarr"
}
>
<SettingsSelect
value={settings.primaryFailureFallback || "none"}
onChange={(v) =>
onUpdate({
primaryFailureFallback: v as "none" | "lidarr" | "soulseek",
})
}
options={getFallbackOptions()}
disabled={isDisabled}
/>
</SettingsRow>
<SettingsRow
label="Soulseek Concurrent Downloads"
description="Number of simultaneous downloads when using Soulseek (1-10)"
>
<SettingsSelect
value={settings.soulseekConcurrentDownloads?.toString() || "4"}
onChange={(v) =>
onUpdate({
soulseekConcurrentDownloads: parseInt(v),
})
}
options={[
{ value: "1", label: "1" },
{ value: "2", label: "2" },
{ value: "3", label: "3" },
{ value: "4", label: "4 (Default)" },
{ value: "5", label: "5" },
{ value: "6", label: "6" },
{ value: "7", label: "7" },
{ value: "8", label: "8" },
{ value: "9", label: "9" },
{ value: "10", label: "10" },
]}
disabled={!isSoulseekConfigured}
/>
</SettingsRow>
</SettingsSection>
);
}