Skip to content

Releases: FernandoHN99/flux-downloader

Flux Downloader v1.2.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 05:26
5e23188

Install

macOS and Linux (Node.js 18 or newer, plus FFmpeg):

tar xzf flux-downloader-portable.tar.gz
cd flux-downloader-portable
./install.sh

Windows: run FluxDownloader-Setup-win-x64.exe.

Then load the extension: open chrome://extensions, turn on Developer mode, choose Load unpacked, and pick the folder the installer prints. The install guide has the details and troubleshooting.

Every file is listed in SHA256SUMS.txt.

What changed

Everything since 1.1.1, which was never tagged. This is the first release with a macOS and Linux install, and the first one built and published by CI.

Install and release (macOS, Linux, Windows)

  • Added scripts/install.sh for macOS and Linux: no root, no build. It installs the companion app in the user's data folder, registers it with every Chromium-based browser it finds (Chrome, Chromium, Brave, Edge, Vivaldi; previously only Chrome and Edge), checks for FFmpeg and yt-dlp, fetches yt-dlp on request with its published checksum, and uninstalls with --uninstall.
  • Added a portable archive, flux-downloader-portable.tar.gz: the built extension, the companion app as a single file with no dependencies, and the installer. The release workflow now builds it next to the Windows installer and only publishes when both succeed.
  • Added CI: tests on Linux, macOS and Windows, shellcheck, and an end-to-end install test that unpacks the archive, installs it, starts the host over native messaging, reinstalls and uninstalls.
  • npm run version:set -- X.Y.Z writes one version everywhere; a test fails if the files disagree. The CoApp's reported version used to be a hard-coded string.
  • register-dev-host.sh now calls install.sh. FLUX_HOST_LOG writes the host's log to a file.
  • Added docs/install.md, and rewrote docs/releasing.md for the new pipeline.

Popup and history

  • Select several videos with Shift-click (a range) or Ctrl/Cmd-click, and file them into a new or existing folder, or delete them, from a selection bar. Holding Shift previews the range. The new-folder form is in the fixed header, so it is visible when the list is scrolled.
  • Lessons clicked through quickly are no longer lost: a manifest that finishes loading after the page changed is now recorded in the history instead of dropped. A video shows as soon as its playlist is read; its length follows.
  • The history and the downloaded/failed markers are no longer capped (the history stopped at 50 rows), and the extension asks for unlimitedStorage.
  • Rows that a player titles alike (a course name on every lesson) take the name their own page URL gives them.
  • Restyled the popup on shared tokens (palette, type scale, spacing), removed duplicated CSS, monospace and all-caps labels, and made it 500px wide and as tall as its content. "Clear All" is now Select all, then Delete.

Refactor baseline 2026-09-03

This section describes commits after the v1.1.1 tag on the refactor line.

Download acceleration

  • Added eight-fragment yt-dlp downloads through --concurrent-fragments 8.
  • Replaced the single-stream direct downloader with validated parallel byte ranges: up to eight connections, 4 MiB minimum parts, per-range resume/retry, object validators, exact-length checks, cancellation, and automatic sequential fallback.
  • Forwarded Referer and Origin to every direct HTTP/range request and stopped treating a partial ECONNRESET response as a complete file.
  • Changed batch execution from sequential to a four-worker pool while retaining one synchronously acquired user-run lease.
  • Made batch cancellation cover every active native ID plus IDs that arrive late, and preallocated case-insensitively unique names before parallel starts.
  • Keyed FFmpeg/yt-dlp progress by logical download, made process IDs collision-safe within the worker, and added per-row plus aggregate parallel progress in the popup.
  • Added a compatibility path for old three-argument convertOutput callbacks and preserved the old callback prefix for older extensions.
  • Documented the complete tuning and fallback model in docs/performance.md.

Rename to Flux Downloader

  • Renamed the project to Flux Downloader everywhere: manifest, UI, npm packages, install directories, log prefix, page-world globals, and release artifacts.
  • Breaking: the native messaging host id changed from com.mediagrabber.coapp to com.fluxdownloader.coapp, and install paths moved from MediaGrabber/MEDIAGRABBER_* to FluxDownloader/FLUX_*. The host must be re-registered with node dist/native-autoinstall-cli.js register <extension-id>; the previous registration and install directory are orphaned and can be deleted by hand.
  • The github.com/miroshArtem/MediaGrabber URLs and the repository directory keep the old name for now, since they are live external references.

Source layout

  • Grouped extension source by domain: entrypoints/, detection/, catalog/, download/, shared/, replacing the 30-file lib/ drawer and the content/ folder.
  • Added a per-domain AGENTS.md to each folder plus a root CLAUDE.md pointer, and trimmed the root AGENTS.md to cross-cutting material.
  • Moved history persistence and the downloaded/failed markers out of background.ts into catalog/history-store.ts, which owns its own write queue; callers no longer chain onto a shared promise. 14 new tests; background.ts dropped from 1,554 to 1,410 lines.
  • Added Vitest to the CoApp workspace with a first suite over RpcProtocol, which exposed and fixed a pending-reply leak when the transport throws.
  • Dropped the 3.9MB promo video from git tracking.

Product and list model

  • Rebranded the user-facing extension and popup to Flux while retaining MediaGrabber internal/release compatibility names. (Superseded by the full rename above.)
  • Replaced separate current/history presentations with one global list.
  • Current media from every open tab is pinned and visibly marked.
  • Added optional persisted history and Only current mode. (The 50-entry cap was removed afterwards.)
  • Added search, rename, stable drag reorder, bulk/selective delete, downloaded/failed markers, and expired-link checks.
  • Added Flat list and By site modes with collapsible/downloadable site groups.
  • Added sequential Best/Worst batch downloads in one Flux_<timestamp> folder.
  • Added unique output names using _1, _2, etc. instead of overwriting.
  • Current and busy rows are structurally excluded from reorder zones.

Popup component refactor

  • Added Vitest + happy-dom before restructuring the UI.
  • Extracted VideoRow and QualityPanel.
  • Extracted VideoList, VideoGroup, ListHeader, and ProgressPanel.
  • Replaced the 1,519-line global popup.ts with popup/index.ts, an App shell, typed Messenger, selectors, and a Store.
  • Split state into background-owned RemoteState and popup-owned UiState so detections/progress cannot erase selection, rename, search, or expansion.
  • Added component-owned DOM; components no longer coordinate by global document queries.
  • Added focus/caret/range preservation through stable data-focus-id across component redraws.
  • Split the approximately 1,600-line popup stylesheet into concern/component files bundled by styles/index.css.
  • Kept the settings page intentionally small/static rather than forcing it into the component layer.

Refresh and source attribution

  • Added one always-visible Refresh tabs button and removed the ineffective split empty-state refresh behavior.
  • Centralized refresh in refreshOpenTabs():
    1. re-record live in-memory media to restore deleted current rows;
    2. send RESCAN to all open HTTP(S) tabs;
    3. replay cached detections, rescan DOM, resend metadata;
    4. await history writes and return fresh current/history lists.
  • A cold service worker now requests a rescan when GET_MEDIA finds no tab media state.
  • Defined VideoInfo.pageUrl as the exact top-level source page and VideoInfo.url as the media/CDN URL.
  • History merge now preserves/repairs page URL/title and treats ownership changes as meaningful.
  • Fixed Rocketseat media being grouped/linking as vz-*.b-cdn.net instead of the exact app.rocketseat.com.br/jornada/.../aula/... page.

Background state

  • Consolidated scattered tab-lifetime maps into one TabStateStore.
  • Made page generations monotonic for the worker lifetime.
  • Made page reset/close cleanup atomic for all tab-owned state.
  • Fixed pageGenerationByTab growing when tabs closed.
  • Prevented stale async parser/yt-dlp results from repopulating a reused tab ID.
  • Kept downloads, batch, popup ports, settings cache, and history-write queue outside tab state because they have different lifetimes.

Pure boundaries and protocols

  • Reduced content.ts from 595 to 261 lines by extracting page metadata, URL classification, MSE projection/reduction, and normalized DOM subtree collection.
  • Removed the content script's dead private M3U8 parser and made content/background share media-url.ts.
  • Added typed, validated popup/background and content/background protocols.
  • Extracted video catalog, source ownership, history mutations, HTTP context, download planning, yt-dlp normalization, manifest quality projection, HLS relay rewriting, and relay codec inference.
  • Preserved known pageUrl values across partial detections instead of letting a CDN-only update erase ownership.
  • Hardened relay inference to require a one-to-one character mapping.

Download lifecycle and native client

  • Added DownloadTracker for active IDs, early outcomes, multiple waiters, cancellation tombstones, and late-callback suppression.
  • Added BatchRun for deterministic queue transitions; cancellation no longer marks the current video failed.
  • Fixed cancellation arriving before startDownload() returns its native ID.
  • Reserved a batch before its first await so...
Read more