AriaFlow is a SwiftPM macOS 14+ executable using SwiftUI and AppKit.
SwiftUI views
│
▼
AppStore ──────► Dock / notifications / local persistence
│
▼
Aria2Client ───► local JSON-RPC
│
▼
EngineManager ─► bundled aria2-next or system aria2
AppStore is the application state owner. Views mutate it directly or start short Task blocks for RPC operations.
| Module | Responsibility |
|---|---|
AriaFlowApp.swift |
Scene declarations, commands, settings and menu bar entry points |
AppDelegate.swift |
Application lifecycle, file/URL opening and status-item events |
AppPresentation.swift |
Activation policy and main/settings window visibility |
MainWindowViews.swift |
Main window chrome, sidebar, content shell |
TaskListViews.swift |
Task/history lists, rows, connection empty states, status bar |
AddTaskSheet.swift / FileSelectionSheet.swift / DeleteConfirmationSheet.swift |
Modal flows |
SettingsViews.swift |
Settings tabs and about |
MenuBarViews.swift |
Menu bar label, menu actions and startup bootstrap |
Persistence.swift |
Application Support paths, JSON and RPC secret storage |
TaskModels.swift |
Task/filter/status models and history items |
AppSettings.swift |
Persisted preferences |
AppStore.swift |
Application orchestration and RPC/engine state |
Aria2Client.swift |
Typed JSON-RPC request and response layer |
EngineManager.swift |
Engine discovery, process launch, logs and peer blocklist validation |
DockService.swift |
Dock badge and aggregate progress |
NotificationService.swift |
Download state notifications |
LoginItemService.swift |
Main-app login-item registration, status and legacy cleanup |
Localization.swift / Resources/*.lproj |
System-language selection, interpolation-safe lookup and English resources |
SmokeDownloadRunner.swift |
Headless packaged-app download verification |
Application data lives under ~/Library/Application Support/AriaFlow unless ARIAFLOW_APP_SUPPORT_DIR overrides it.
| File | Contents |
|---|---|
settings.json |
AppSettings, excluding the RPC secret |
rpc-secret.txt |
Local RPC secret (app storage) |
engine-runtime.conf |
Mode 0600 conf passed via --conf-path (includes rpc-secret=…) |
history.json |
Completed and removed task history |
download.session |
aria2 session state |
aria2-next.log |
Engine log with bounded rotation |
AppSettings uses backward-compatible decodeIfPresent defaults. New persisted fields must do the same.
Settings and history JSON writes are debounced (400ms) in AppStore and flushed on app termination.
AriaFlowMenuBarLabelconfiguresAppDelegateand starts automatic connection.AppStore.retryEngineConnection()connects to the configured RPC port or starts an engine.EngineManagersearches bundled resources first, then known system paths.- The bundled engine receives RPC, download, session, logging and optional peer-blocklist arguments.
AppStorepolls global stats and task lists while connected.- Shutdown saves the session when possible and terminates the managed process.
Bundled executable names:
motrix-next-engine-aarch64-apple-darwinmotrix-next-engine-x86_64-apple-darwin
System fallback paths are defined in EngineManager.findSystemExecutable().
AddTaskSheet → AppStore.addURLTask() → aria2.addUri → task refresh.
Magnet tasks start paused until metadata and file selection are available.
Torrent file bytes → Base64 → aria2.addTorrent with pause=true → file selection → aria2.changeOption(select-file) → unpause.
- Runtime-compatible limits use
aria2.changeGlobalOption. - RPC port and secret changes restart the engine.
- Peer blocklists are fetched from a configured URL into a local cache, validated, loaded at bundled-engine startup and reloaded with
aria2.changeGlobalOption.
L10n selects Chinese for any preferred language beginning with zh; all
other languages use the English table. Chinese source strings are the stable
translation keys, including interpolation placeholders. verify_localizations.py
rejects missing translations and placeholder mismatches.
- Main scene: sidebar filters, task/history content and status bar.
- Sheets: add task, torrent file selection and delete confirmation.
- Settings scene: general, downloads, engine and about tabs.
- Menu bar extra: window access, queue actions, speeds and quit.
- SoftwareUpdater: monitors network availability, checks stable GitHub releases, falls back to the jsDelivr-hosted update manifest, validates the matching archive, then replaces and relaunches the app.
Window activation and Dock visibility must remain centralized in AppPresentation. When hideDockIconInMenuBarMode is enabled, the app stays .accessory even if main or settings windows are visible.
Polling uses a 2s interval while downloads are active and 5s when idle. Transient RPC errors are tolerated for a few cycles before disconnecting. Waiting/stopped lists are paginated (100 per page, max 20 pages). Notifications fire only on complete/fail.
| Script | Purpose |
|---|---|
install_sidecar.sh |
Install one architecture's verified engine binary |
package_app.sh |
Build, bundle, sign and archive Universal or per-architecture apps |
verify_release.sh |
Run the complete automated release gate |
smoke_sidecar_download.sh |
Verify engine RPC, peer blocklist and download behavior |
smoke_app_download.sh |
Verify packaged-app engine startup and download behavior |
- Add RPC methods in
Aria2Client; keep transport details out of views. - Add persisted preferences to
AppSettingswith decode defaults. - Put engine arguments and executable discovery in
EngineManager. - Keep application orchestration in
AppStore; views should only bind state and trigger actions. - Update
THIRD_PARTY_NOTICES.mdand both checksums when replacing sidecars. - Add one focused test or smoke assertion for non-trivial parsing, state or RPC behavior.
Use Xcode 26 or a Swift 6.2-compatible toolchain.
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcrun swift test
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer scripts/verify_release.shverify_release.sh builds the Universal app, validates architecture and signing, verifies the ZIP checksum, and runs sidecar and packaged-app smoke tests.