import { useEffect, useState } from 'react'; import { Gauge, Save, Zap } from 'lucide-react'; import { useSettingsStore } from '../store/useSettingsStore'; import { WindowDragRegion } from './WindowDragRegion'; import { useToast } from '../contexts/ToastContext'; type SpeedUnit = 'KB/s' | 'MB/s'; function parseLimit(limit: string, fallback: number): { value: number; unit: SpeedUnit } { const match = limit.trim().match(/^(\d+(?:\.\d+)?)\s*([km]?)b?(?:\/s)?$/i); const valueKiB = match ? Math.max(1, Math.round(Number(match[1]) * (match[2].toLowerCase() === 'm' ? 1024 : 1))) : fallback; return valueKiB >= 1024 && valueKiB % 1024 === 0 ? { value: valueKiB / 1024, unit: 'MB/s' } : { value: valueKiB, unit: 'KB/s' }; } export default function SpeedLimiterView() { const globalSpeedLimit = useSettingsStore(state => state.globalSpeedLimit); const lastCustomSpeedLimitKiB = useSettingsStore(state => state.lastCustomSpeedLimitKiB); const setGlobalSpeedLimit = useSettingsStore(state => state.setGlobalSpeedLimit); const setLastCustomSpeedLimitKiB = useSettingsStore(state => state.setLastCustomSpeedLimitKiB); const initial = parseLimit(globalSpeedLimit, lastCustomSpeedLimitKiB); const [enabled, setEnabled] = useState(Boolean(globalSpeedLimit)); const [value, setValue] = useState(initial.value); const [unit, setUnit] = useState(initial.unit); const { addToast } = useToast(); useEffect(() => { const parsed = parseLimit(globalSpeedLimit, lastCustomSpeedLimitKiB); setEnabled(Boolean(globalSpeedLimit)); setValue(parsed.value); setUnit(parsed.unit); }, [globalSpeedLimit, lastCustomSpeedLimitKiB]); const save = () => { const numericValue = Math.max(1, Math.min(Number(value) || 1, unit === 'MB/s' ? 10240 : 10_485_760)); const valueKiB = Math.min(10_485_760, Math.round(unit === 'MB/s' ? numericValue * 1024 : numericValue)); setLastCustomSpeedLimitKiB(valueKiB); setGlobalSpeedLimit(enabled ? `${valueKiB}K` : ''); addToast({ message: enabled ? `Global limit saved at ${numericValue} ${unit}` : 'Global speed limit disabled', variant: 'success' }); }; const preset = (presetValue: number) => { setEnabled(true); setValue(presetValue); setUnit('MB/s'); }; return (
Speed Limiter
{enabled ? `${value} ${unit}` : 'Unlimited'}
Global Speed Limit

This cap is shared by transfers running through the core downloader. A lower per-download limit still takes precedence. Saving updates the core downloader immediately; media extraction keeps its existing per-download options.

setValue(Math.max(1, Number(event.target.value) || 1))} className="app-control w-28 px-3 py-2 text-right font-mono" />
{(['KB/s', 'MB/s'] as SpeedUnit[]).map(option => ( ))}
Quick Presets
{[1, 5, 10].map(presetValue => ( ))}
); }