- Make favorite title optional in both the DTO (drop binding:"required")
and the add-favorite modal (no validator). Server falls back to the
URL when the title is empty so the list entry always has a label.
- Auto-fill the title via the existing GET /api/url/title scraper when
the user leaves the URL field, unless they already typed their own
title. Failures are swallowed (server fallback still applies).
- Reorder the modal so URL is on top and Title below, matching the
actual data-flow: users paste a URL first and the title follows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Go Core now broadcasts a "download-create" SSE event after
POST /api/downloads succeeds, carrying the new task ids and count.
The renderer's events.ts listens for it and calls useDownloadStore's
increase() imperatively, so the sidebar badge updates regardless of
which WebContents issued the request — the source-extract overlay
dialog has its own Zustand instance and can no longer silently swallow
the increment.
- Remove the now-redundant local increase() calls in download-form and
browser-view-panel so the counter is incremented exactly once per task
from a single source of truth.
- Favorite.Create returns 409 Conflict with a translated
MsgURLAlreadyExists message when the URL already exists, instead of
500 with the raw "url_already_exists" string.
- http.ts response interceptor now surfaces the server's translated
message on 4xx/5xx instead of Axios's generic
"Request failed with status code XXX".
- Simplify getFavIcon: drop the 1s <img> probe that dropped most URLs
and return the canonical /favicon.ico; <Avatar> already falls back to
a link icon when the image fails to load.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bilibili returns an error page ("出错了") when requests lack a proper
User-Agent. Add browser User-Agent and Referer headers to both
GetPageTitle (service/helpers.go) and fetchTitle (handler/util.go).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Refactor video player API from filesystem scanning to database-backed:
- Video list queries downloads with status="success" + file existence check
- Add GET /api/v1/videos/:id endpoint for playing specific video by task ID
- Add playerUrl to /api/env response (computed from request host)
- Whitelist player/video paths in auth middleware
- Fix video URL generation to preserve folder structure (relative path)
- Fix player-ui Vite base path and video URL resolution under /player/
- Add openUrl implementation to web platform stubs
- Player-UI supports ?id= query param to auto-play specific video
- Play button now passes task.id instead of filename
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously the frontend hashed passwords with MD5 + a hardcoded salt
before sending to the backend. This exposed the salt in client-side JS
and used an insecure hash algorithm.
Backend changes:
- Setup: accepts plain password, bcrypt hashes it, generates UUID apiKey
- Signin: accepts plain password, bcrypt verifies, returns stored apiKey
- Status: checks passwordHash instead of apiKey
- AppStore: new passwordHash field
- Middleware: add X-API-Key header support (was only reading Authorization)
- CORS: allow X-API-Key header
Frontend changes:
- Signin page: send plain password, receive apiKey from response
- Remove md5/crypto-js dependency and APIKEY_SALT_KEY constant
- api/download-task: auto-inject localPath/deleteSegments from store
(was lost during go-adapter migration, caused EOF errors)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move ffmpeg execution from Electron to Go Core so conversion works in
both Electron and web server modes.
Go Core backend:
- Add -ffmpeg-bin CLI flag to pass ffmpeg binary path
- Enhance Conversion DB model with status, outputPath, outputFormat,
quality, progress, and error fields
- Create converter executor (service/converter.go) that spawns ffmpeg,
builds args per format/quality, and parses stderr for progress
- Add StartConversion/StopConversion to service with SSE events for
real-time progress (conversion-start/progress/success/failed/stop)
- Add POST /api/conversions/:id/start and /:id/stop endpoints
Supported formats:
- Video: MP4 (H.264), MKV (H.264), WebM (VP9) with CRF quality
- Audio: MP3, AAC, FLAC, WAV with bitrate quality presets
- Quality presets: high/medium/low mapping to CRF and bitrate values
Frontend (converter-page):
- Add format selector (Video/Audio groups) and quality dropdown
- Show per-item status badge, progress bar during conversion
- Action buttons: Start/Stop/Open Folder/Delete based on status
- "Convert All" batch button for pending items
- SWR auto-refresh during active conversions
Integration:
- Pass -ffmpeg-bin from Electron and core:dev to Go Core
- Remove old broken Electron-only convertToAudio code
- Add startConversion/stopConversion to core-sdk and GoApi
- Add i18n keys for new UI elements (en/zh)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Converted all Chinese-language comments across 47 source files to
English, covering Go backend (apps/core, apps/player), TypeScript
scripts, Electron main process, UI components, and shared packages.
Only comment text was modified — code, string literals, log messages,
and i18n translation values were left untouched.
Also fix pre-existing lint errors in scripts/release.ts and
scripts/utils.ts (node: protocol prefix, unused imports, bare catch).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. Sync Go Core config to Zustand on app startup so settings persist
across restarts (Go Core is the single source of truth).
2. Go Core Create handler now respects startDownload param — downloads
start immediately when "Download Now" is clicked.
3. Player integration fixes:
- Electron: graceful skip when player binary is not built
- Server: start player service alongside Go Core, expose playerUrl
- Web adapter: derive playerUrl from current host instead of empty string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>