diff --git a/CODE-AUDIT.md b/CODE-AUDIT.md index 63aaa71..e737ce0 100644 --- a/CODE-AUDIT.md +++ b/CODE-AUDIT.md @@ -420,18 +420,18 @@ token system + shared primitives (UI/SIMP — high value, larger effort) · i18n - [ ] **L21 — Inconsistent in-component error handling.** SettingsView funnels the app-update not-ok result into a dedicated `appUpdError` slot but keeps not-ok duals for version/update/export/import — two patterns in one file. -- [ ] **L22 — DownloadOptionsForm shows both audio + video controls** regardless of the chosen +- [x] **L22 — DownloadOptionsForm shows both audio + video controls** regardless of the chosen kind in the per-download override panel (audio format shown for a video download, etc.). - [x] **L23 — Diagnostics shows first 20 errors** with no "showing 20 of N" hint (the copied report includes all). -- [ ] **L24 — `window.open(htmlUrl, '_blank')`** in SettingsView is the only `window.open` in the +- [x] **L24 — `window.open(htmlUrl, '_blank')`** in SettingsView is the only `window.open` in the app (relies on the window-open handler); elsewhere external opens go through IPC/`shell`. - [x] **L25 — Taskbar effect over-fires.** `App.tsx` subscribes to the whole downloads store and recomputes `summarizeQueue` + sends the taskbar IPC on *every* store change (each progress tick); throttle or dedupe by computed value. - [ ] **L26 — Third URL-sniffing path.** DownloadBar's drag-drop `firstUrl` is a separate "first http(s) line" extractor alongside `useClipboardLink.looksLikeUrl` and deeplink's scan. -- [ ] **L27 — DownloadBar Enter probes, not downloads.** Enter in the URL field triggers +- [x] **L27 — DownloadBar Enter probes, not downloads.** Enter in the URL field triggers `fetchFormats`; there's no keyboard path to actually start the download (LibraryView's Enter runs its primary action). Inconsistent. - [ ] **L28 — Default kind/quality applied once.** DownloadBar seeds from settings via a one-shot diff --git a/src/main/index.ts b/src/main/index.ts index 73e2708..89bfe03 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -325,6 +325,14 @@ function registerIpcHandlers(): void { }) ipcMain.handle(IpcChannels.openPath, (_e, p: string) => safeOpenPath(p)) + ipcMain.handle(IpcChannels.openUrl, (_e, url: string) => { + try { + const { protocol } = new URL(url) + if (protocol === 'http:' || protocol === 'https:') void shell.openExternal(url) + } catch { + // Ignore malformed URLs. + } + }) ipcMain.handle(IpcChannels.showInFolder, (_e, p: string) => safeShowInFolder(p)) ipcMain.handle(IpcChannels.clipboardRead, () => clipboard.readText()) diff --git a/src/preload/index.ts b/src/preload/index.ts index 7655631..4ed7209 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -77,6 +77,8 @@ const api = { openPath: (path: string): Promise => ipcRenderer.invoke(IpcChannels.openPath, path), + openUrl: (url: string): Promise => ipcRenderer.invoke(IpcChannels.openUrl, url), + showInFolder: (path: string): Promise => ipcRenderer.invoke(IpcChannels.showInFolder, path), readClipboard: (): Promise => ipcRenderer.invoke(IpcChannels.clipboardRead), diff --git a/src/renderer/src/components/DownloadBar.tsx b/src/renderer/src/components/DownloadBar.tsx index edb0a64..a5a2b47 100644 --- a/src/renderer/src/components/DownloadBar.tsx +++ b/src/renderer/src/components/DownloadBar.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react' +import { useState, useEffect, useRef } from 'react' import { Input, Textarea, @@ -254,7 +254,7 @@ const useStyles = makeStyles({ }) // Format a Date as the `YYYY-MM-DDTHH:mm` value a datetime-local input expects, -// in LOCAL time — used as the picker's `min` so a past time can't be chosen and +// in LOCAL time -- used as the picker's `min` so a past time can't be chosen and // then silently download immediately (L156/L57). function toLocalDatetimeValue(d: Date): string { const pad = (n: number): string => String(n).padStart(2, '0') @@ -302,7 +302,7 @@ export function DownloadBar(): React.JSX.Element { onUrlChange(fromText) return } - // A dropped Windows .url Internet Shortcut — read its URL= line. + // A dropped Windows .url Internet Shortcut -- read its URL= line. const file = Array.from(dt.files).find((f) => f.name.toLowerCase().endsWith('.url')) if (file) { file @@ -342,7 +342,7 @@ export function DownloadBar(): React.JSX.Element { // Clipboard auto-detect and links handed to AeroFetch from outside (the // aerofetch:// protocol or a "Send to" .url file) share one suggestion banner, // driven by the same hook the library's add-source field uses. An external link - // always takes priority over a clipboard guess — it's a direct request. + // always takes priority over a clipboard guess -- it's a direct request. const { suggestion, source: suggestionSource, @@ -376,7 +376,7 @@ export function DownloadBar(): React.JSX.Element { function onUrlChange(next: string): void { setUrl(next) - // Any probed info — or a duplicate warning — is stale once the URL changes. + // Any probed info -- or a duplicate warning -- is stale once the URL changes. if (info || probeError || playlist) clearProbe() if (dup) setDup(null) confirmDup.current = false @@ -418,7 +418,7 @@ export function DownloadBar(): React.JSX.Element { const text = await navigator.clipboard.readText() if (text) onUrlChange(text.trim()) } catch { - /* clipboard blocked — ignore in preview */ + /* clipboard blocked -- ignore in preview */ } } @@ -457,7 +457,7 @@ export function DownloadBar(): React.JSX.Element { // Duplicate guard: if this URL is already in the queue (and the user hasn't // confirmed via "Download anyway"), warn instead of silently enqueuing a copy. - // Canceled/failed items don't count — re-adding those is a legitimate retry. + // Canceled/failed items don't count -- re-adding those is a legitimate retry. if (!confirmDup.current) { const existing = useDownloads .getState() @@ -551,7 +551,11 @@ export function DownloadBar(): React.JSX.Element { input={{ id: 'aerofetch-url', 'aria-label': 'Video or playlist URL' }} value={url} onChange={(_, d) => onUrlChange(d.value)} - onKeyDown={(e) => e.key === 'Enter' && fetchFormats()} + onKeyDown={(e) => { + if (e.key !== 'Enter') return + if (info || probeError || playlist) download() + else void fetchFormats() + }} placeholder="Paste a video or playlist URL, then fetch…" size="large" contentBefore={} @@ -598,7 +602,7 @@ export function DownloadBar(): React.JSX.Element { {dup && (
- Already in your queue: “{dup}”. + Already in your queue: "{dup}". @@ -622,7 +626,7 @@ export function DownloadBar(): React.JSX.Element { {probeError && (
- {probeError} — you can still download with the presets below. + {probeError} -- you can still download with the presets below.
)} @@ -697,8 +701,8 @@ export function DownloadBar(): React.JSX.Element {