Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ jobs:
rpmbuild -bs --define "_topdir $RPM_TOP" "$RPM_TOP/SPECS/hydra.spec"
ls "$RPM_TOP"/SRPMS/hydra-${VERSION}-*.src.rpm

flatpak-validate:
name: Flatpak Metadata Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install validation tools
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends appstream desktop-file-utils

- name: Validate Flatpak desktop and metainfo files
run: |
set -euo pipefail
desktop-file-validate packaging/flatpak/io.github.ja7ad.hydra.desktop
appstreamcli validate --no-net packaging/flatpak/io.github.ja7ad.hydra.metainfo.xml

fmt:
name: Code Formatting
runs-on: ubuntu-latest
Expand Down
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# make rpm Fedora/RHEL/openSUSE package -> target/dist/*.rpm
# make linux both deb and rpm
# make appimage portable, self-updating AppImage -> target/dist/*.AppImage
# make flatpak Flatpak package and metadata -> target/dist/*.flatpak
# make package the right artifact(s) for the OS make runs on
#
# make extensions browser extensions: packed .xpi + .zip (+ .crx with a
Expand All @@ -32,7 +33,7 @@ VERSION := $(shell sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)
PROFILE ?= release
CARGO ?= cargo

.PHONY: all build cli gui host app dmg deb rpm linux appimage windows package clean \
.PHONY: all build cli gui host app dmg deb rpm linux appimage flatpak windows package clean \
extensions \
require-macos require-linux ffi header header-check ffi-compat \
ffi-test ffi-dist ffi-android ffi-apple
Expand Down Expand Up @@ -147,6 +148,14 @@ linux: require-linux
appimage: require-linux
scripts/package-appimage.sh $(ARGS)

# Flatpak build, metadata validation, or bundle generation:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the header at line 10 promises target/dist/*.flatpak, but bare make flatpak builds without exporting a bundle; either say make flatpak ARGS=--bundle there or default BUNDLE=1 in the script.

#
# make flatpak ARGS=--bundle export a standalone .flatpak file
# make flatpak ARGS=--install build and install into user Flatpak repo
# make flatpak ARGS=--validate-only validate metadata only
flatpak:
scripts/package-flatpak.sh $(ARGS)

windows:
scripts/build-windows-installer.sh x64

Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,20 @@ paru -S hydra-download-manager-bin

> AUR Packages: [hydra-download-manager](https://aur.archlinux.org/packages/hydra-download-manager) | [hydra-download-manager-bin](https://aur.archlinux.org/packages/hydra-download-manager-bin)

### Flatpak (Flathub)

Install from Flathub:

```bash
flatpak install flathub io.github.ja7ad.hydra
```

Run Hydra:

```bash
flatpak run io.github.ja7ad.hydra
```

### AppImage (portable, self-updating)

One file, no installation, no root. Download it from the
Expand Down
2 changes: 1 addition & 1 deletion crates/hydra-gui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1786,7 +1786,7 @@ impl App {
// hydra.desktop (scripts/package-linux.sh, install.sh).

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comment "Must stay equal to the basename of hydra.desktop (scripts/package-linux.sh, install.sh)" is now only half true; add the Flatpak entry to the list it names.

#[cfg(target_os = "linux")]
let platform_specific = window::settings::PlatformSpecific {
application_id: "hydra".to_string(),
application_id: std::env::var("FLATPAK_ID").unwrap_or_else(|_| "hydra".to_string()),
..Default::default()
};
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
Expand Down
19 changes: 15 additions & 4 deletions crates/hydra-gui/src/autostart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ fn entry_path() -> Option<PathBuf> {

#[cfg(all(unix, not(target_os = "macos")))]
fn entry_path() -> Option<PathBuf> {
Some(dirs::home_dir()?.join(".config/autostart/hydra.desktop"))
if let Ok(id) = std::env::var("FLATPAK_ID") {
Some(dirs::home_dir()?.join(format!(".config/autostart/{id}.desktop")))
} else {
Some(dirs::home_dir()?.join(".config/autostart/hydra.desktop"))
}
}

/// Sync the login item with the settings. Safe to call every save.
Expand Down Expand Up @@ -193,9 +197,16 @@ pub fn apply(enabled: bool, minimized: bool) {
}
#[cfg(all(unix, not(target_os = "macos")))]
{
content = format!(
"[Desktop Entry]\nType=Application\nName=Hydra Download Manager\nExec=\"{exe}\" {arg}\nX-GNOME-Autostart-enabled=true\n"
);
if let Ok(id) = std::env::var("FLATPAK_ID") {
let space_arg = if minimized { " --minimized" } else { "" };
content = format!(
"[Desktop Entry]\nType=Application\nName=Hydra Download Manager\nExec=flatpak run {id}{space_arg}\nIcon={id}\nX-GNOME-Autostart-enabled=true\n"
);
} else {
content = format!(
"[Desktop Entry]\nType=Application\nName=Hydra Download Manager\nExec=\"{exe}\" {arg}\nIcon=hydra\nX-GNOME-Autostart-enabled=true\n"
);
}
}
// Already correct: leave it alone (a rewrite would only bump the
// Background Task Management generation on macOS for no change).
Expand Down
17 changes: 11 additions & 6 deletions crates/hydra-updater/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,18 +479,23 @@ pub fn update_method(dir: &Path) -> UpdateMethod {
}
}

/// True when running inside a Flatpak sandbox (`FLATPAK_ID` set or `/.flatpak-info` exists).
pub fn is_flatpak() -> bool {
std::env::var_os("FLATPAK_ID").is_some() || Path::new("/.flatpak-info").exists()
}

/// Whether a package manager owns the install in `dir`.
///
/// Linux: the deb and rpm both install into `/usr/bin` (scripts/package-linux.sh),
/// while `/usr/local` is by convention exactly the part of the filesystem no
/// package manager touches. macOS: the `.pkg` records a receipt per package
/// identifier and lands in `/Applications`; a dragged `.dmg` leaves no
/// receipt, which is what separates the two installs that otherwise look
/// identical. Windows: the setup installer owns whatever it wrote, and there
/// Flatpak runs from an immutable `/app` mount, while `/usr/local` is by convention
/// exactly the part of the filesystem no package manager touches. macOS: the `.pkg`
/// records a receipt per package identifier and lands in `/Applications`; a dragged
/// `.dmg` leaves no receipt, which is what separates the two installs that otherwise
/// look identical. Windows: the setup installer owns whatever it wrote, and there
/// is no unprivileged way to rewrite `Program Files`.
fn package_managed(dir: &Path) -> bool {
if cfg!(target_os = "linux") {
dir.starts_with("/usr") && !dir.starts_with("/usr/local")
is_flatpak() || (dir.starts_with("/usr") && !dir.starts_with("/usr/local"))
} else if cfg!(target_os = "macos") {
dir.starts_with("/Applications")
&& Path::new("/var/db/receipts/io.github.ja7ad.hydra.plist").exists()
Expand Down
67 changes: 67 additions & 0 deletions packaging/flatpak/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Flatpak Packaging for Hydra

This directory contains the Flatpak package definition and AppStream metadata for **Hydra Download Manager** (`io.github.ja7ad.hydra`).

## Files

- `io.github.ja7ad.hydra.yml`: Flatpak manifest for building with `flatpak-builder`.
- `io.github.ja7ad.hydra.metainfo.xml`: AppStream 1.0+ metadata for Flathub, GNOME Software, and KDE Discover.
- `io.github.ja7ad.hydra.desktop`: XDG Desktop entry for Flatpak environments.

## Building Locally

### Prerequisites

Install Flatpak, `flatpak-builder`, and the Freedesktop 24.08 runtime and SDK:

```bash
flatpak install flathub org.freedesktop.Platform//24.08 org.freedesktop.Sdk//24.08 org.freedesktop.Sdk.Extension.rust-stable//24.08
```

### Build and Install

To build and install the Flatpak into your user installation:

```bash
flatpak-builder --user --install --force-clean build-dir packaging/flatpak/io.github.ja7ad.hydra.yml
```

### Run

```bash
flatpak run io.github.ja7ad.hydra
```

Or run via CLI:

```bash
flatpak run --command=hydra io.github.ja7ad.hydra --help
```

## Creating a Standalone Bundle (.flatpak)

To build a standalone `.flatpak` single-file installer:

```bash
# Build into local repo
flatpak-builder --repo=repo --force-clean build-dir packaging/flatpak/io.github.ja7ad.hydra.yml

# Export single-file bundle
flatpak build-bundle repo Hydra-0.4.2-x86_64.flatpak io.github.ja7ad.hydra
```

Or use the helper script:

```bash
scripts/package-flatpak.sh --bundle
```

## Flathub Submission & Maintenance

1. Fork the [Flathub repository](https://github.com/flathub/flathub).
2. Generate `cargo-sources.json` for offline cargo dependencies:
```bash
flatpak-cargo-generator Cargo.lock -o packaging/flatpak/cargo-sources.json
```
3. Update the `sources` in `io.github.ja7ad.hydra.yml` to reference the release git tag and `cargo-sources.json`.
4. Submit a pull request to `flathub/flathub` with the `io.github.ja7ad.hydra` branch/directory.
12 changes: 12 additions & 0 deletions packaging/flatpak/io.github.ja7ad.hydra.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Desktop Entry]
Type=Application
Name=Hydra Download Manager
GenericName=Download Manager
Comment=Multi-connection download accelerator and manager
Exec=hydra-gui @@u %u @@

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either drop both lines (Exec=hydra-gui, no MimeType), matching packaging/debian/hydra.desktop, or teach main.rs to consume a positional URL. As written the entry claims the hydra: scheme and throws the argument away.

Icon=io.github.ja7ad.hydra
Terminal=false
Categories=Network;FileTransfer;
Keywords=download;manager;accelerator;torrent;http;metalink;hls;dash;
StartupWMClass=hydra

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StartupWMClass=io.github.ja7ad.hydra, to match the app id app.rs:1789 now sets.

MimeType=x-scheme-handler/hydra;
71 changes: 71 additions & 0 deletions packaging/flatpak/io.github.ja7ad.hydra.metainfo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>io.github.ja7ad.hydra</id>
<name>Hydra Download Manager</name>
<summary>Multi-connection download accelerator and manager</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<developer id="io.github.ja7ad">
<name>Javad Rajabzadeh</name>
</developer>
<description>
<p>
Hydra is an advanced, high-performance download accelerator and manager written in Rust.
It splits downloads across multiple parallel HTTP/HTTPS connections with dynamic chunk sizing,
automatic resume capability, and end-to-end cryptographic checksum verification (SHA-256, BLAKE3, MD5, SHA-1).
</p>
<p>Key features include:</p>
<ul>
<li>High-speed multi-connection HTTP/HTTPS and streaming download engine</li>
<li>Adaptive stream assembly for HLS and MPEG-DASH audio/video streams</li>
<li>Metalink 3.0 and 4.0 XML parser and mirror failover handling</li>
<li>Remote zip preview and selective single-file extraction without full archive download</li>
<li>Reed-Solomon forward error correction (PAR2 parity) verification and repair</li>
<li>Full-featured graphical user interface, lightweight CLI (hydra / hya), and browser native messaging host</li>
<li>Browser integration for Firefox, Chrome, Edge, and Chromium derivatives</li>
<li>System tray integration (StatusNotifierItem) and dark/light system theme support</li>
</ul>
</description>
<launchable type="desktop-id">io.github.ja7ad.hydra.desktop</launchable>
<url type="homepage">https://github.com/ja7ad/hydra</url>
<url type="bugtracker">https://github.com/ja7ad/hydra/issues</url>
<url type="vcs-browser">https://github.com/ja7ad/hydra</url>
<url type="help">https://github.com/ja7ad/hydra/blob/main/README.md</url>
<screenshots>
<screenshot type="default">
<image>https://raw.githubusercontent.com/ja7ad/hydra/main/docs/img/screenshot1.jpg</image>
<caption>Hydra Download Manager main window</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/ja7ad/hydra/main/docs/img/screenshot2.png</image>
<caption>Queue scheduling and download progress</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/ja7ad/hydra/main/docs/img/screenshot3.png</image>
<caption>Stream sniffer and media stream capture</caption>
</screenshot>
<screenshot>
<image>https://raw.githubusercontent.com/ja7ad/hydra/main/docs/img/screenshot4.png</image>
<caption>Zip directory preview and selective archive download</caption>
</screenshot>
</screenshots>
<provides>
<binary>hydra</binary>
<binary>hya</binary>
<binary>hydra-gui</binary>
<binary>hydra-host</binary>
</provides>
<releases>
<release version="0.4.2" date="2026-09-01">

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

date="2026-09-05" per CHANGELOG.md:8, and move the "Flatpak packaging" bullet (:65) to whichever release actually ships it.

<description>
<p>Features and improvements in release 0.4.2:</p>
<ul>
<li>Enhanced streaming parser and parallel segment fetcher</li>
<li>Optimized memory consumption and UI responsiveness</li>
<li>Flatpak packaging and Flathub distribution support</li>
</ul>
</description>
</release>
</releases>
<content_rating type="oars-1.1"/>
</component>
84 changes: 84 additions & 0 deletions packaging/flatpak/io.github.ja7ad.hydra.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
app-id: io.github.ja7ad.hydra
runtime: org.freedesktop.Platform
runtime-version: '24.08'
sdk: org.freedesktop.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.rust-stable
command: hydra-gui

finish-args:
# Display & Windowing
- --share=ipc
- --socket=fallback-x11
- --socket=wayland
# Network & Hardware
- --share=network
- --socket=pulseaudio
- --device=dri
# Filesystem permissions for download directories
- --filesystem=xdg-download
- --filesystem=home
# StatusNotifierItem system tray integration
- --talk-name=org.kde.StatusNotifierWatcher
- --own-name=org.kde.StatusNotifierItem-*

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete the line. --own-name=org.kde.StatusNotifierItem-* isn't a valid bus name (flatpak only strips a trailing .*), so build-finish errors out. ksni registers with the watcher under its unique name, so line 22's --talk-name=org.kde.StatusNotifierWatcher is all that's needed.

# Desktop notifications
- --talk-name=org.freedesktop.Notifications
# XDG Portals (File dialogs, settings, dark theme detection, URI open)
- --talk-name=org.freedesktop.portal.Desktop
- --talk-name=org.freedesktop.portal.FileChooser
- --talk-name=org.freedesktop.portal.OpenURI
- --talk-name=org.freedesktop.portal.Settings
- --talk-name=org.freedesktop.portal.Background
- --talk-name=org.freedesktop.portal.FdoStyle
- --system-talk-name=org.freedesktop.login1

build-options:
append-path: /usr/lib/sdk/rust-stable/bin
env:
CARGO_HOME: /run/build/hydra/cargo
Comment on lines +35 to +38

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build has no network and no offline sources. For the local make flatpak path add the build-arg; for the Flathub submission generate cargo-sources.json instead (never both — Flathub rejects --share=network):

build-options:
  append-path: /usr/lib/sdk/rust-stable/bin
  build-args:
    - --share=network
  env:
    CARGO_HOME: /run/build/hydra/cargo


modules:
- name: hydra
buildsystem: simple
build-commands:
# Build GUI, CLI, and Native Host
- cargo build --release --locked -p hya-cli -p hya-gui -p hya-host
# Binaries
- install -Dm755 target/release/hydra-gui /app/bin/hydra-gui
- install -Dm755 target/release/hydra /app/bin/hydra
- install -Dm755 target/release/hydra-host /app/bin/hydra-host
- ln -sf hydra /app/bin/hya
# Desktop launcher & AppStream metadata
- install -Dm644 packaging/flatpak/io.github.ja7ad.hydra.desktop /app/share/applications/io.github.ja7ad.hydra.desktop
- install -Dm644 packaging/flatpak/io.github.ja7ad.hydra.metainfo.xml /app/share/metainfo/io.github.ja7ad.hydra.metainfo.xml
# Application icons (docs/logo.png -> hicolor)
- install -Dm644 docs/logo.png /app/share/icons/hicolor/512x512/apps/io.github.ja7ad.hydra.png
- |
for s in 16 32 48 64 128 256; do
if command -v magick >/dev/null 2>&1; then
install -d "/app/share/icons/hicolor/${s}x${s}/apps"
magick docs/logo.png -resize "${s}x${s}" "/app/share/icons/hicolor/${s}x${s}/apps/io.github.ja7ad.hydra.png"
elif command -v convert >/dev/null 2>&1; then
install -d "/app/share/icons/hicolor/${s}x${s}/apps"
convert docs/logo.png -resize "${s}x${s}" "/app/share/icons/hicolor/${s}x${s}/apps/io.github.ja7ad.hydra.png"
fi
done
# Shell completions
- install -d /app/share/bash-completion/completions /app/share/zsh/site-functions /app/share/fish/vendor_completions.d
- target/release/hydra completions bash > /app/share/bash-completion/completions/hydra
- target/release/hydra completions zsh > /app/share/zsh/site-functions/_hydra
- target/release/hydra completions fish > /app/share/fish/vendor_completions.d/hydra.fish
- target/release/hydra completions bash --bin-name hya > /app/share/bash-completion/completions/hya
- target/release/hydra completions zsh --bin-name hya > /app/share/zsh/site-functions/_hya
- target/release/hydra completions fish --bin-name hya > /app/share/fish/vendor_completions.d/hya.fish
# Man pages
- install -d /app/share/man/man1
- for page in docs/man/*.1; do install -Dm644 "$page" "/app/share/man/man1/$(basename "$page")"; done
# Documentation & Licenses
- install -Dm644 LICENSE /app/share/licenses/io.github.ja7ad.hydra/LICENSE
- install -Dm644 LICENSING.md /app/share/licenses/io.github.ja7ad.hydra/LICENSING.md
- install -Dm644 README.md /app/share/doc/io.github.ja7ad.hydra/README.md
- install -Dm644 CHANGELOG.md /app/share/doc/io.github.ja7ad.hydra/CHANGELOG.md
sources:
- type: dir

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add skip: [target, .git, build-dir, repo] under the type: dir source.

path: ../..
Loading
Loading