mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-07 18:03:23 +00:00
fix: resolve P2 and P3 audit findings
This commit is contained in:
@@ -317,6 +317,7 @@ export const AddDownloadsModal = () => {
|
||||
|
||||
// Metadata parser
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
const lines = urls.split('\n').map(u => u.trim()).filter(u => u.length > 0);
|
||||
|
||||
// Immediately display items in loading state
|
||||
@@ -340,6 +341,7 @@ export const AddDownloadsModal = () => {
|
||||
let firstReadyIndex: number | null = null;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (!active) break;
|
||||
const url = lines[i];
|
||||
try {
|
||||
new URL(url);
|
||||
@@ -408,15 +410,18 @@ export const AddDownloadsModal = () => {
|
||||
console.error("Meta fetch failed", e);
|
||||
updatedItems[i] = { ...updatedItems[i], size: 'Unknown', sizeBytes: 0, status: 'Error' };
|
||||
}
|
||||
setParsedItems([...updatedItems]);
|
||||
if (active) setParsedItems([...updatedItems]);
|
||||
}
|
||||
|
||||
if (firstReadyIndex !== null) {
|
||||
if (active && firstReadyIndex !== null) {
|
||||
setSelectedItemIndex(firstReadyIndex);
|
||||
}
|
||||
}, 400);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
return () => {
|
||||
active = false;
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [urls, pendingAddFilename]);
|
||||
|
||||
if (!isAddModalOpen) return null;
|
||||
|
||||
@@ -245,6 +245,11 @@ export default function SettingsView() {
|
||||
type="number" min="1" max="16"
|
||||
value={settings.perServerConnections}
|
||||
onChange={(e) => settings.setPerServerConnections(Number(e.target.value))}
|
||||
onBlur={(e) => {
|
||||
const val = Number(e.target.value);
|
||||
if (val < 1) settings.setPerServerConnections(1);
|
||||
if (val > 16) settings.setPerServerConnections(16);
|
||||
}}
|
||||
className="app-control w-24 text-center"
|
||||
/>
|
||||
</div>
|
||||
@@ -257,6 +262,11 @@ export default function SettingsView() {
|
||||
type="number" min="1" max="12"
|
||||
value={settings.maxConcurrentDownloads}
|
||||
onChange={(e) => settings.setMaxConcurrentDownloads(Number(e.target.value))}
|
||||
onBlur={(e) => {
|
||||
const val = Number(e.target.value);
|
||||
if (val < 1) settings.setMaxConcurrentDownloads(1);
|
||||
if (val > 12) settings.setMaxConcurrentDownloads(12);
|
||||
}}
|
||||
className="app-control w-24 text-center"
|
||||
/>
|
||||
</div>
|
||||
@@ -285,6 +295,11 @@ export default function SettingsView() {
|
||||
type="number" min="0" max="10"
|
||||
value={settings.maxAutomaticRetries}
|
||||
onChange={(e) => settings.setMaxAutomaticRetries(Number(e.target.value))}
|
||||
onBlur={(e) => {
|
||||
const val = Number(e.target.value);
|
||||
if (val < 0) settings.setMaxAutomaticRetries(0);
|
||||
if (val > 10) settings.setMaxAutomaticRetries(10);
|
||||
}}
|
||||
className="app-control w-24 text-center"
|
||||
/>
|
||||
</div>
|
||||
@@ -453,9 +468,14 @@ export default function SettingsView() {
|
||||
<div className="mac-settings-row">
|
||||
<span className="text-[13px] text-text-primary pl-4">Proxy Port</span>
|
||||
<input
|
||||
type="number"
|
||||
type="number" min="1" max="65535"
|
||||
value={settings.proxyPort}
|
||||
onChange={(e) => settings.setProxyPort(Number(e.target.value))}
|
||||
onBlur={(e) => {
|
||||
const val = Number(e.target.value);
|
||||
if (val < 1) settings.setProxyPort(1);
|
||||
if (val > 65535) settings.setProxyPort(65535);
|
||||
}}
|
||||
className="app-control w-24 text-center"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useSettingsStore } from './useSettingsStore';
|
||||
export type { DownloadCategory } from '../utils/downloads';
|
||||
|
||||
const getProxyArgs = (settings: ReturnType<typeof useSettingsStore.getState>) => {
|
||||
if (settings.proxyMode === 'system') return 'system';
|
||||
if (settings.proxyMode === 'custom' && settings.proxyHost) {
|
||||
return `http://${settings.proxyHost}:${settings.proxyPort}`;
|
||||
}
|
||||
@@ -25,7 +26,8 @@ export const getSiteLogin = (url: string, settings: ReturnType<typeof useSetting
|
||||
const suffix = pattern.substring(2);
|
||||
if (host === suffix || host.endsWith('.' + suffix)) return login;
|
||||
} else if (pattern.includes('*')) {
|
||||
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
||||
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
||||
const regex = new RegExp('^' + escaped.replace(/\*/g, '.*') + '$');
|
||||
if (regex.test(host)) return login;
|
||||
} else if (host === pattern) {
|
||||
return login;
|
||||
@@ -191,9 +193,13 @@ export const useDownloadStore = create<DownloadState>((set, get) => ({
|
||||
},
|
||||
redownload: (id) => {
|
||||
let updatedItem: DownloadItem | null = null;
|
||||
let wasDownloading = false;
|
||||
set((state) => ({
|
||||
downloads: state.downloads.map(d => {
|
||||
if (d.id === id) {
|
||||
if (d.status === 'downloading') {
|
||||
wasDownloading = true;
|
||||
}
|
||||
const updated: DownloadItem = { ...d, status: 'queued', _dispatched: false, fraction: 0, speed: '-', eta: '-' };
|
||||
updatedItem = updated;
|
||||
return updated;
|
||||
@@ -201,6 +207,9 @@ export const useDownloadStore = create<DownloadState>((set, get) => ({
|
||||
return d;
|
||||
})
|
||||
}));
|
||||
if (wasDownloading) {
|
||||
invoke('pause_download', { id }).catch(console.error);
|
||||
}
|
||||
if (updatedItem) {
|
||||
const toSave = { ...(updatedItem as DownloadItem) };
|
||||
delete toSave.fraction; delete toSave.speed; delete toSave.eta;
|
||||
|
||||
@@ -11,8 +11,10 @@ const MEDIA_DOMAINS = [
|
||||
'instagram.com',
|
||||
'tiktok.com',
|
||||
'reddit.com',
|
||||
'v.redd.it',
|
||||
'soundcloud.com',
|
||||
'facebook.com'
|
||||
'facebook.com',
|
||||
'fb.watch'
|
||||
];
|
||||
|
||||
export const categoryForFileName = (fileName: string): DownloadCategory => {
|
||||
|
||||
Reference in New Issue
Block a user