Skip to content

packaging: AppImage/Flatpak/macOS/Windows + first-run launcher prompt - #510

Merged
mrjimenez merged 3 commits into
amule-project:masterfrom
got3nks:pr3-appimage-integration
May 2, 2026
Merged

packaging: AppImage/Flatpak/macOS/Windows + first-run launcher prompt#510
mrjimenez merged 3 commits into
amule-project:masterfrom
got3nks:pr3-appimage-integration

Conversation

@got3nks

@got3nks got3nks commented May 2, 2026

Copy link
Copy Markdown
Contributor

Summary

aMule today ships as source. Distros build their own packages on their own schedule (some with patches, some pinned to 2.3.3 from years ago); macOS users either use MacPorts or build from source with whatever Homebrew layout breaks today; Windows users are on the auld eMule-style installers from third-party sites. There's no upstream-blessed "click here, get aMule" path on any platform.

This PR lays that path. Single workflow_dispatch produces:

  • Linux: AppImage (x86_64, aarch64) — single-file, runs on any glibc-2.17+ distro, validated cross-distro on each build. Bundles the full toolset (amule, amuled, amulegui, amulecmd, amuleweb, ed2k); a custom AppRun dispatches based on argv[0], so ln -s aMule.AppImage amuled && ./amuled runs the daemon, … amulecmd runs the EC client, etc. Same idiom Krita / GIMP use to ship multiple tools in one image.
  • Linux: Flatpak (x86_64, aarch64) — Flathub-shaped manifest, GNOME Platform 49 runtime, built-from-source AyatanaIndicators stack for SNI tray. Bundles the full toolset; flatpak run org.amule.aMule launches the GUI by default, flatpak run --command=amuled org.amule.aMule (or --command=amulecmd, --command=amuleweb, --command=ed2k) invokes the other binaries.
  • macOS: Universal2 .dmg (arm64 + x86_64 lipo-merged) — drag-to-Applications layout, dylibs bundled. CLI binaries (amuled, amulecmd, amuleweb, ed2k) ship inside aMule.app/Contents/MacOS/ next to the GUI entry point, runnable from terminal as aMule.app/Contents/MacOS/amuled ….
  • Windows: portable .zip (x64 MINGW64, arm64 CLANGARM64) — self-contained MSYS2 runtime, CA bundle for libcurl HTTPS. bin/ contains every executable (amule.exe, amuled.exe, amulegui.exe, amulecmd.exe, ed2k.exe); run any directly.

A second small commit then teaches the AppImage to integrate itself with the user's desktop on first launch (one-shot prompt; declinable for life via a prefs flag).


Commit 1 — packaging recipes

Tree layout

packaging/
  linux/
    build.sh                    dispatcher: appimage | flatpak | validate
    appimage/                   AppRun, Dockerfile, build.sh
    flatpak/                    org.amule.aMule.yaml.in template, build.sh
    versions.env                pinned tarball URLs + SHA256s
  macos/
    build.sh                    cmake → bundle .app → dylibbundler → .dmg
  windows/
    build.sh                    cmake -G Ninja → install --prefix → zip
.github/workflows/packaging.yml two triggers (push-to-master + dispatch), matrix per platform

Workflow design

Two triggers, both path-filtered so doc-only commits don't burn CI:

  • Push to master (or any packaging** branch) — fires when src/**, cmake/**, CMakeLists.txt, packaging/**, or .github/workflows/packaging.yml change. Keeps master always-shippable; in practice this fires on every PR merge (since merge is a push to master). Open PRs do not trigger the workflow — that avoids the wasteful "fires on PR open AND on merge" double-cost.
  • Manual workflow_dispatch — with an only=appimage,flatpak,macos,windows input for iterating on a single track without paying for the green ones. Reviewers who want to inspect a PR's artifacts before merging can dispatch this against the PR branch from the Actions UI.

Each platform runs on its native GHA runner (no QEMU emulation), or its closest equivalent:

Platform Runner Notes
AppImage x86_64 ubuntu-22.04 glibc 2.35 baseline — old enough for compatibility, new enough for libstdc++23
AppImage aarch64 ubuntu-22.04-arm Native ARM, no QEMU
Flatpak x86_64 ubuntu-22.04 flatpak-builder + GNOME 49 runtime
Flatpak aarch64 ubuntu-22.04-arm Native
macOS arm64 macos-15 Native Apple Silicon
macOS x86_64 macos-15 (Rosetta) macos-13 was deprecated; Rosetta-emulated build via parallel /usr/local Homebrew
macOS Universal2 .dmg macos-15 lipo merge of both arm64 + x86_64 .app trees
Windows x64 windows-latest (MSYS2 MINGW64)
Windows arm64 windows-latest (MSYS2 CLANGARM64)

AppImage cross-distro validation

Every AppImage build runs the produced binary inside a Docker matrix — Ubuntu 22/24/25, Fedora 41, Debian 12, Arch latest — and asserts --version works. This catches glibc / libstdc++ / openssl skew before users do.

Flatpak details

The org.amule.aMule.yaml.in manifest is a template; packaging/linux/versions.env provides pinned tarball URLs + SHA256s, rendered into the manifest by build.sh. Notable choices:

  • --filesystem=home: aMule is a P2P client where users mark arbitrary folders as shared and pick arbitrary destinations for Incoming/Temp dirs. Restricting to xdg-download makes the most common configs ("share my Music folder, save to ~/Movies") silently fail. This matches qBittorrent and Transmission on Flathub for the same reason. Side benefit: aMule's config dir lives at the standard ~/.aMule/ on the host, so state survives without --persist, and a Flatpak install shares config with any non-Flatpak install side by side.

  • AyatanaIndicators stack from source: GNOME Platform 49 doesn't ship libayatana-appindicator (or its dependencies — intltool, libdbusmenu, ayatana-ido, libayatana-indicator). Building them in-manifest is the price of admission for the SNI tray-icon backend on Flatpak. Each module has tight cleanup: rules so build-only deps don't end up in the runtime layer.

  • libdbusmenu source: only on launchpad.net. Debian/Ubuntu ship the .1 point release with a different sha256, snapshot.debian.org doesn't carry the source package at this version, and old-releases / ports paths 404. No working mirror exists at the pinned upstream sha — relying on launchpad-only with a documented fallback hint (switch to AyatanaIndicators/libayatana-dbusmenu, the GitHub-hosted ABI-compatible fork) for if launchpad reliability becomes ongoing trouble.

macOS x86_64 via Rosetta

GitHub deprecated macos-13 (Intel) — it's been flaky for months and is being retired. Migrating: x86_64 builds on macos-15 (Apple Silicon) with Rosetta. A parallel Homebrew install at /usr/local supplies x86_64 dep bottles, and every command that produces x86_64 output is wrapped in arch -x86_64. CMake honours MACOS_ARCHITECTURES=x86_64 from the env (handled in packaging/macos/build.sh's existing arch logic) so clang emits the right slice. End result is identical to a native Intel build, and the runner is now reliable.

Universal2 .dmg merge

Both arm64 and x86_64 builds upload their .app trees as artifacts. A third job downloads both, walks the arm64 layout, lipo-merges every Mach-O against its x86_64 sibling, and re-wraps the merged .app into a single .dmg.

After lipo-merge, two post-processing steps are mandatory:

  1. chmod +x every merged Mach-O. lipo -create -output <file> writes the result with the runner's process umask (default 022 → rw-r--r--), discarding the source's executable bit. Without restoring it, macOS launchd refuses to spawn the bundle with errno 13 (EACCES on access(X_OK)) — the .app appears intact but won't open.
  2. codesign --force --deep --sign - ad-hoc the whole bundle. clang on Apple Silicon emits ad-hoc-signed Mach-O by default; lipo invalidates per-slice signatures on merge, and Apple Silicon's amfid then refuses to load the resulting fat binary. The re-sign produces valid ad-hoc sigs across every nested executable so the binaries pass amfid even before any notarization step.

macOS first-launch UX (unsigned + non-notarized)

Without an Apple Developer ID + notarization stamp, the produced .dmg ships with only ad-hoc signatures. End users on macOS 11–14 used to bypass Gatekeeper via right-click → Open → "Open Anyway". macOS 15 (Sequoia) removed that path entirely — the only way for end users to launch an unsigned .app now is via System Settings:

  1. Double-click the .app — macOS shows a generic "cannot open" dialog (no usable Open button).
  2. System Settings → Privacy & Security → scroll to bottom → "aMule was blocked because it is not from an identified developer" → click Open Anyway → enter admin password.
  3. Re-launch the .app — second time it launches normally.

Or via terminal one-liner (faster for power users):

xattr -cr /Applications/aMule.app
open /Applications/aMule.app

Until the project has Apple Developer credentials wired up (see follow-ups), this is the user experience. The macOS install hint should be documented in the .dmg's README and on the project download page so first-time users aren't surprised. Notarization is the highest-impact post-merge follow-up — the only thing that makes the .dmg "just work" without these steps.

Windows .zip

cmake --install lays out a portable tree under ~/amule-portable/: bin/*.exe plus all bundled MSYS2 runtime DLLs (via file(GET_RUNTIME_DEPENDENCIES)) and a bin/ca-bundle.crt for libcurl HTTPS. Self-contained — copies cleanly to a non-MSYS2 host.


Commit 2 — AppImage first-run launcher prompt

Why this is in the same PR as packaging

Without a launcher entry, the AppImage produced by Commit 1 is just a file in ~/Downloads. Wayland's app_id binding (PR #508) only kicks in when there's a .desktop to bind against. So the AppImage launches, GNOME shows a generic icon, and the user has no way to "find aMule in the menu" short of running chmod +x from a terminal every time.

Splitting these into two PRs would mean shipping a half-finished UX from day one. Bundling them keeps the artifact testable end-to-end.

Behaviour

When aMule starts inside an AppImage (getenv("APPIMAGE") set by AppRun) AND no user-level ~/.local/share/applications/org.amule.aMule.desktop exists yet AND the user hasn't opted out:

  • Show a wxRichMessageDialog after the main frame is realized:
    • Title: Add aMule to your application menu?
    • Body explains what'll be copied where, notes the action is reversible.
    • Buttons: Install (default) / Not now.
    • Checkbox: Don't ask again.
  • On Install:
    • Copy org.amule.aMule.desktop from $APPDIR/usr/share/applications/ into $XDG_DATA_HOME/applications/ (default ~/.local/share/applications/), rewriting Exec= to point at the current $APPIMAGE path so the launcher invokes the AppImage at its real on-disk location.
    • Copy hicolor icons (org.amule.aMule.png per size) into $XDG_DATA_HOME/icons/hicolor/<size>/apps/.
    • Best-effort update-desktop-database + gtk-update-icon-cache.
    • Confirm with a follow-up dialog offering an immediate Restart now so the running window's dock-icon binding can pick up the new launcher entry. Restart is implemented via a detached sh that polls the current PID and execs $APPIMAGE once aMule has fully exited (gives the normal shutdown path time to save partfiles, release the EC port, etc.).
  • On Not now: skip this run; prompt fires again next launch.
  • On Don't ask again (checkbox checked, regardless of which button was clicked): persist [General] AppImageIntegrationDeclined=true to aMule prefs and call Save() immediately so a crash before normal shutdown still remembers the user's choice.

Source-code touch points

  • src/AppImageIntegration.{h,cpp} — new module (~270 LOC): env detection, file copies, cache-refresh, the prompt + restart flow.
  • src/Preferences.{h,cpp} — adds s_appimageIntegrationDeclined static + IsAppImageIntegrationDeclined() / SetAppImageIntegrationDeclined() accessors. Persisted via the existing s_MiscList for cfg items not tied to a UI dialog control.
  • src/amule-gui.cpp::CamuleGuiApp::OnInit — call site, gated on __WXGTK__. Uses CallAfter() to defer the dialog until the event loop is fully running so it doesn't block OnInit's return path.
  • cmake/source-vars.cmake — adds the new .cpp to GUI_SOURCES.

The whole module is gated on __WXGTK__ — Windows / macOS builds skip both the include and the call entirely (verified by CI on those platforms).

Why only AppImage (not also Flatpak / distro / cmake-install)

Scenario What's the integration state? Should we prompt?
Distro install (apt install amule) /usr/share/applications/*.desktop already there No — package owns it
Local cmake --install to /usr/local /usr/local/share/applications/*.desktop already there No — same
Running from build tree No .desktop, but it's a dev workflow No — annoying for contributors
Flatpak Flatpak machinery owns its own .desktop No — Flatpak handles it
AppImage No system entry, single-file binary Yes — only place a prompt makes sense

$APPIMAGE env var is the affirmative signal that the user is in a self-contained, no-install-script context. Every other case is either already handled by a package manager or a dev workflow.


Verification

CI green on all 9 jobs across 4 platforms (linked to the passing workflow run at PR-open time).

Manual end-to-end tests:

  • Arch Linux (vanilla GNOME 50.1 with gnome-shell-extension-appindicator): AppImage launcher prompt fires on first run, Install populates ~/.local/share/applications/ and ~/.local/share/icons/hicolor/<sizes>/apps/, Restart now cleanly cycles the binary, post-restart aMule appears in the application menu with the correct mule icon, dock icon binds via Wayland app_id (PR desktop integration: Wayland app_id, SNI tray, macOS dock-restore + tray opt-in (closes #410) #508).
  • openSUSE Tumbleweed (GNOME with AppIndicator extension): Flatpak install via flatpak install --user *.flatpak, flatpak run org.amule.aMule launches, server.met persists across flatpak kill + relaunch (--filesystem=home resolves the sandbox-overlay write loss), tray icon renders, Incoming dir set to ~/Movies/ works (no sandbox write block).
  • macOS arm64 + x86_64 Universal2 (M-series Mac): drag .app to /Applications, double-click launches, banner shows correct rev, dock-click after HideOnClose restores window (PR desktop integration: Wayland app_id, SNI tray, macOS dock-restore + tray opt-in (closes #410) #508).
  • Windows ARM64 VM (UTM/Win11): unzip portable, bin/amule.exe launches, banner correct.

Future follow-ups (out of scope here)

  • release.yml: tag-triggered workflow that runs the same builds and uploads artifacts to GitHub Releases (permanent public URLs, anonymous download). The packaging.yml here is a "PR sanity gate"; the release workflow is the user-facing distribution channel.
  • Flathub submission: once the manifest has a few merged-revision soak weeks, submit to Flathub for flatpak install flathub org.amule.aMule discoverability + auto-updates.
  • macOS code signing + notarization: packaging/macos/sign.sh is stubbed; wire up Apple Developer credentials when the project has an account, otherwise users get the "unidentified developer" Gatekeeper warning.
  • libdbusmenu → AyatanaIndicators/libayatana-dbusmenu if launchpad reliability remains a recurring outage (manifest currently has a comment pointing at the GitHub-hosted fork as the migration target).

Test plan

  • Packaging CI green on all 9 jobs (AppImage x86_64 + aarch64, Flatpak x86_64 + aarch64, macOS arm64 + x86_64 + Universal2, Windows x64 + arm64)
  • AppImage first-run prompt fires once, Install copies files + rewrites Exec=, Don't ask again persists across launches
  • Flatpak persists ~/.aMule state across reboots (home access)
  • Tray icon visible on GNOME with AppIndicator extension; on Flatpak; on Windows; on macOS
  • Wayland app_id binds the dock icon to the launcher entry post-Install + restart
  • Distro / cmake-install / dev-build aMule does NOT trigger the prompt ($APPIMAGE unset)

got3nks added 2 commits May 2, 2026 13:46
Adds reproducible packaging recipes for the four end-user distribution
formats and a GitHub Actions workflow_dispatch that builds + uploads
artifacts on demand.

Tree:
  packaging/
    linux/
      build.sh                    dispatcher: appimage | flatpak
      appimage/                   AppRun, Dockerfile, build.sh
      flatpak/                    org.amule.aMule.yaml.in (template,
                                  rendered via versions.env), build.sh
      versions.env                pinned tarball URLs + SHA256s
    macos/                        cmake -> bundle .app -> dylibbundler -> .dmg
    windows/                      cmake -G Ninja -> install --prefix -> zip
  .github/workflows/packaging.yml workflow_dispatch matrix per platform

Linux jobs run native on ubuntu-latest (x86_64) and ubuntu-24.04-arm
(aarch64). AppImages are validated cross-distro inside a Docker matrix
(Ubuntu 22/24/25, Fedora 41, Debian 12, Arch latest) so glibc/libstdc++
skew is caught before users hit it.

Flatpak manifest sets --persist=.aMule so $HOME/.aMule writes inside
the sandbox (server.met, amule.conf, known.met, partfile metadata,
client credits) are redirected to ~/.var/app/org.amule.aMule/.aMule on
the host. Without it, Flatpak's sandbox overlay swallowed those writes
and the server list reset on every reboot. A long-term follow-up could
teach aMule's config-path resolution to prefer XDG_DATA_HOME/aMule
inside a sandbox (detected via FLATPAK_ID / /.flatpak-info), making
the --persist hint redundant — out of scope for this PR.
When aMule starts inside an AppImage and no user-level launcher entry
exists yet, show a one-shot dialog ("Install / Not now" + "Don't ask
again" checkbox) offering to copy the bundled .desktop and hicolor
icons into ~/.local/share. The .desktop's Exec= is rewritten to point
at $APPIMAGE so the menu entry invokes the image at its real on-disk
path. update-desktop-database and gtk-update-icon-cache are run
best-effort.

The whole module is gated on __WXGTK__ — Windows / macOS skip the
include and call. Detection is via the APPIMAGE / APPDIR env vars
exported by AppImage's AppRun, so distro-installed and dev builds
never trigger the prompt.

A new persistent flag /GUI/AppImageIntegrationDeclined records the
"Don't ask again" choice so a user who declines once is never asked
again on subsequent AppImage launches.
Reviewers landing in packaging/ get hit with five subdirectories and
no entry point that explains how they fit together. Add packaging/
README.md as a single orientation doc:

* Tree layout with one-line descriptions of each subdir.
* Per-platform pointer table linking to the existing platform-specific
  README.md files (AppImage / Flatpak / macOS / Windows).
* 'Building one platform locally' — the four shell-script entrypoints
  in one place, so contributors don't have to read four docs to find
  the right invocation.
* 'Building all four via GitHub Actions' — runner matrix, trigger
  policy (push-to-master + manual dispatch only, deliberately no
  pull_request trigger), and the macOS Rosetta migration note.
* Versions and dependency pins — what versions.env files exist and
  how the Flatpak template gets rendered.
* 'What this repo does NOT ship' — explicit scope: distro packaging,
  signing secrets, and the future release.yml are intentionally not
  in scope. Reduces 'why doesn't this also do X' questions in
  review.

The per-platform README.md files under each subdir continue to own
their platform-specific details — this top-level doc references them
rather than duplicating their content.
got3nks added a commit to got3nks/amule that referenced this pull request May 2, 2026
…3nks

mrjimenez flagged on PR amule-project#514 review that these three contributors
were missing from the roster:

* Werner Mahr / Vollstrecker — has merge access on amule-project/amule
  and merges incoming PRs (e.g. amule-project#430, amule-project#385, amule-project#319, amule-project#330, amule-project#286). Goes
  under Maintainers based on that role.
* Pablo Barciela / Sc0w — recent contributor, e.g. wxWidgets 3.2.6
  build fixes, GTK version-check cleanup, dropping gtk1/gtk2 support,
  Chinese translation work. Goes under Developers.
* got3nks — Wayland app_id binding + SNI tray (amule-project#508), macOS UX
  (amule-project#508), libmaxminddb CI fix (amule-project#507), ip2country/upnp/nls/boost
  hard-fail series (amule-project#509/amule-project#511/amule-project#512/amule-project#513), packaging (amule-project#510),
  docs modernize (this PR). Goes under Developers.

Other recent folks may be missing too — those can be added in
follow-up commits as they're identified. mrjimenez explicitly noted
this is the priority subset to not block the rename PR.
mrjimenez pushed a commit that referenced this pull request May 2, 2026
…3nks

mrjimenez flagged on PR #514 review that these three contributors
were missing from the roster:

* Werner Mahr / Vollstrecker — has merge access on amule-project/amule
  and merges incoming PRs (e.g. #430, #385, #319, #330, #286). Goes
  under Maintainers based on that role.
* Pablo Barciela / Sc0w — recent contributor, e.g. wxWidgets 3.2.6
  build fixes, GTK version-check cleanup, dropping gtk1/gtk2 support,
  Chinese translation work. Goes under Developers.
* got3nks — Wayland app_id binding + SNI tray (#508), macOS UX
  (#508), libmaxminddb CI fix (#507), ip2country/upnp/nls/boost
  hard-fail series (#509/#511/#512/#513), packaging (#510),
  docs modernize (this PR). Goes under Developers.

Other recent folks may be missing too — those can be added in
follow-up commits as they're identified. mrjimenez explicitly noted
this is the priority subset to not block the rename PR.
@mrjimenez
mrjimenez merged commit 635745a into amule-project:master May 2, 2026
12 checks passed
@got3nks
got3nks deleted the pr3-appimage-integration branch May 2, 2026 14:31
mrjimenez pushed a commit that referenced this pull request May 2, 2026
…lity

The libupnp 1.18.4 cmake build hard-codes lib64 as the install
directory on both x86_64 and aarch64 — its CMakeLists doesn't go
through GNUInstallDirs the usual biarch-aware way. As a result
libupnp.pc + libupnp.so end up at /app/lib64/, but Flatpak's
downstream PKG_CONFIG_PATH only searches /app/lib/pkgconfig/.

aMule's cmake/upnp.cmake then can't find libupnp via
pkg_check_modules and (since #511 made ENABLE_UPNP=YES a hard
requirement) errors out. Before #511 this silently produced a
Flatpak with no UPnP support — symptom went unnoticed because the
existing test plan didn't cover UPnP port forwarding from inside
the sandbox.

Fix: pass -DCMAKE_INSTALL_LIBDIR=lib to libupnp's config-opts.
Same pattern already applied to the ayatana-* libs further down in
the manifest for the identical reason. libupnp.pc now lands at
/app/lib/pkgconfig/libupnp.pc, pkg-config finds it, ENABLE_UPNP
resolves true, the build completes.

Affected runs: the first amule-project/amule:master Packaging run
after #510-#514 merged (https://github.com/amule-project/amule/actions/runs/25253858400)
where Flatpak (aarch64) failed at the amule cmake step with the
new #511 FATAL_ERROR. Verified locally that the same regression
existed on x86_64 too.
mrjimenez pushed a commit that referenced this pull request May 3, 2026
PR #510 (AppImage first-run launcher prompt) added 14 user-facing
strings in src/AppImageIntegration.cpp wrapped with _() / wxTRANSLATE
for translation. The file itself was never added to po/POTFILES.in,
so xgettext skips it during the periodic 'Automated translation
update' run — the strings are extractable in source but invisible to
the translation pipeline. Result: the new dialog stays English-only
in every locale, even after translators sync their .po files.

Add src/AppImageIntegration.cpp to po/POTFILES.in (alphabetised under
src/A*). The next automated translation update will then regenerate
po/aMule.pot with the new entries, propagating them to translators
through the existing workflow.
got3nks added a commit to got3nks/amule that referenced this pull request May 3, 2026
Re-run scripts/update-po.sh to refresh po/amule.pot and merge into all
po/*.po files. The previous update-po run did not pick up the new
strings introduced in src/AppImageIntegration.cpp (PR amule-project#510), because
src/AppImageIntegration.cpp had not yet been added to po/POTFILES.in
when xgettext ran. This commit propagates the missing 14 user-facing
strings into amule.pot and into every locale's .po file (as untranslated
or fuzzy-matched entries, per msgmerge).

Also fix scripts/update-po.sh to pass package metadata flags to xgettext
(--copyright-holder, --package-name, --package-version,
--msgid-bugs-address). Without these, each regen reset the pot header
back to the xgettext placeholder values (PACKAGE VERSION,
THE PACKAGE'S COPYRIGHT HOLDER), losing the aMule-specific package
references that translators rely on.
got3nks added a commit to got3nks/amule that referenced this pull request May 3, 2026
Re-run scripts/update-po.sh to refresh po/amule.pot and merge into all
po/*.po files. The previous update-po run did not pick up the new
strings introduced in src/AppImageIntegration.cpp (PR amule-project#510), because
src/AppImageIntegration.cpp had not yet been added to po/POTFILES.in
when xgettext ran. This commit propagates the missing 14 user-facing
strings into amule.pot and into every locale's .po file (as untranslated
or fuzzy-matched entries, per msgmerge).

Also fix scripts/update-po.sh to preserve aMule package metadata in the
regenerated pot:

- Pass --copyright-holder, --package-name, --package-version, and
  --msgid-bugs-address to xgettext so the pot header retains
  'Project-Id-Version: aMule SVN' and the upstream bug address.
- Substitute the current year for xgettext's 'Copyright (C) YEAR'
  placeholder using sed.

Without these, every regen reset the pot header to xgettext placeholders
(PACKAGE VERSION, THE PACKAGE'S COPYRIGHT HOLDER, YEAR), erasing the
aMule-specific package references.
mrjimenez pushed a commit that referenced this pull request May 3, 2026
Re-run scripts/update-po.sh to refresh po/amule.pot and merge into all
po/*.po files. The previous update-po run did not pick up the new
strings introduced in src/AppImageIntegration.cpp (PR #510), because
src/AppImageIntegration.cpp had not yet been added to po/POTFILES.in
when xgettext ran. This commit propagates the missing 14 user-facing
strings into amule.pot and into every locale's .po file (as untranslated
or fuzzy-matched entries, per msgmerge).

Also fix scripts/update-po.sh to preserve aMule package metadata in the
regenerated pot:

- Pass --copyright-holder, --package-name, --package-version, and
  --msgid-bugs-address to xgettext so the pot header retains
  'Project-Id-Version: aMule SVN' and the upstream bug address.
- Substitute the current year for xgettext's 'Copyright (C) YEAR'
  placeholder using sed.

Without these, every regen reset the pot header to xgettext placeholders
(PACKAGE VERSION, THE PACKAGE'S COPYRIGHT HOLDER, YEAR), erasing the
aMule-specific package references.
got3nks added a commit to got3nks/amule that referenced this pull request Jul 17, 2026
…ty (amule-project#510)

PR amule-project#508 added an "aMuleGUI Log" tab to the remote GUI's log notebook by
inserting it at index 1. CamuleDlg tracked the network-conditional log tabs
(Server Info / ED2K Info / Kad Info) by position in a fixed m_logpages[4]
array, so the extra tab shifted everything: the GetPageCount() == 4 assert
fired in debug builds, the capture loop wrote past the array end (corrupting
the adjacent m_networkpages), and DoNetworkRearrange re-added the wrong pages
-- dropping the Kad Info tab, as reported on amule-project#508.

Track the network-conditional tabs by identity instead of index: capture each
page via the control it hosts (ID_SERVERINFO / ID_ED2KINFO / ID_KADINFO) and
add/remove those specific pages with FindPage(). This is index- and
build-independent -- the always-on tabs (aMule Log, and aMuleGUI Log in the
remote GUI) are simply left in place -- so the monolithic and amulegui layouts
share one code path and it won't break again if a tab is added or reordered.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants