Fix L23/L78/L79: diagnostics hint, empty-state copy, SponsorBlock defaults

L23: Diagnostics error list now shows "Showing 20 of N errors." when there
     are more than 20 logged errors.
L78: DownloadsView empty-state copy updated from "Paste a URL above to get
     started" to "Paste a URL above, then click Download" -- matches the UI.
L79: SponsorBlock default categories expanded from ['sponsor'] to
     ['sponsor', 'selfpromo', 'interaction'] -- sponsor-only was silently
     covering almost nothing; the three new defaults are universally unwanted.
     Existing SB tests updated to pass explicit categories instead of using defaults.

typecheck + 242 tests + eslint + prettier green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 13:57:53 -04:00
parent 3086ac469f
commit 94c5723246
5 changed files with 18 additions and 7 deletions
+3 -3
View File
@@ -422,7 +422,7 @@ token system + shared primitives (UI/SIMP — high value, larger effort) · i18n
version/update/export/import — two patterns in one file.
- [ ] **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.).
- [ ] **L23 — Diagnostics shows first 20 errors** with no "showing 20 of N" hint (the copied
- [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
app (relies on the window-open handler); elsewhere external opens go through IPC/`shell`.
@@ -522,9 +522,9 @@ token system + shared primitives (UI/SIMP — high value, larger effort) · i18n
`titleFromUrl` placeholder before metadata resolves ('YouTube video (id)').
- [x] **L77 — ffmpeg/ffprobe versions have no re-check affordance** (load once; "not found" sticks
with no retry) unlike the yt-dlp "Check version" button.
- [ ] **L78 — `DownloadsView` empty-state copy** ("Paste a URL above to get started") doesn't match
- [x] **L78 — `DownloadsView` empty-state copy** ("Paste a URL above to get started") doesn't match
the actual two-step Fetch→Download affordance.
- [ ] **L79 — SponsorBlock default categories = `['sponsor']` only** — enabling SB silently covers
- [x] **L79 — SponsorBlock default categories = `['sponsor']` only** — enabling SB silently covers
just sponsors until the user expands categories (expectation gap).
*Round 4 (2026-06-29) — doc/code drift, build artifacts, edge cases:*
@@ -133,7 +133,7 @@ export function DownloadsView(): React.JSX.Element {
{items.length === 0 ? (
<div className={styles.empty}>
<ArrowDownloadRegular fontSize={40} />
<Body1>Nothing queued yet. Paste a URL above to get started.</Body1>
<Body1>Nothing queued yet. Paste a URL above, then click Download.</Body1>
</div>
) : (
<VirtualList
@@ -1008,6 +1008,11 @@ export function SettingsView(): React.JSX.Element {
<Caption1 className={errText.errorPre}>{e.error}</Caption1>
</div>
))}
{errorEntries.length > 20 && (
<Caption1 className={styles.hint}>
Showing 20 of {errorEntries.length} errors.
</Caption1>
)}
</div>
)}
</Card>
+1 -1
View File
@@ -217,7 +217,7 @@ export const DEFAULT_DOWNLOAD_OPTIONS: DownloadOptions = {
autoSubtitles: false,
sponsorBlock: false,
sponsorBlockMode: 'remove',
sponsorBlockCategories: ['sponsor'],
sponsorBlockCategories: ['sponsor', 'selfpromo', 'interaction'],
embedChapters: false,
splitChapters: false,
embedMetadata: true,
+8 -2
View File
@@ -220,13 +220,19 @@ describe('embedSubtitles', () => {
describe('sponsorBlock', () => {
it('remove → --sponsorblock-remove <cats> --force-keyframes-at-cuts', () => {
const argv = build(opts(), dlo({ sponsorBlock: true, sponsorBlockMode: 'remove' }))
const argv = build(
opts(),
dlo({ sponsorBlock: true, sponsorBlockMode: 'remove', sponsorBlockCategories: ['sponsor'] })
)
expect(hasSeq(argv, '--sponsorblock-remove', 'sponsor', '--force-keyframes-at-cuts')).toBe(true)
expect(argv).not.toContain('--sponsorblock-mark')
})
it('mark → --sponsorblock-mark <cats>, no keyframe forcing', () => {
const argv = build(opts(), dlo({ sponsorBlock: true, sponsorBlockMode: 'mark' }))
const argv = build(
opts(),
dlo({ sponsorBlock: true, sponsorBlockMode: 'mark', sponsorBlockCategories: ['sponsor'] })
)
expect(hasSeq(argv, '--sponsorblock-mark', 'sponsor')).toBe(true)
expect(argv).not.toContain('--sponsorblock-remove')
expect(argv).not.toContain('--force-keyframes-at-cuts')