[3.7.7] - 2026-05-10
Benchmark Trash Purge, AeroFile UX Polish, and Windows Update No-Trace
A consolidation release. The original benchmark trash-purge work (still detailed below) ships alongside a sweep of file-browser UX papercuts surfaced in #178, the no-trace portable update and per-user file associations on Windows (#176), and a handful of provider polish items.
Added
- Dedicated MIME-style icons for AeroFTP file types so
.aerovault,.aeroftpand.aeroftp-keystorerender with their own document icons in the file list and in the host file manager. - App version in the window title and Help menu, so users can see at a glance which build they are running.
- Folder drill-in spinner (#178 #2): both Remote and Local panels now show a soft overlay spinner while a directory listing is in flight. Debounced via a
fadeInDelayedkeyframe (opacity 0 for the first ~250 ms of a 450 ms animation) so fast listings never reveal the spinner. Honoursprefers-reduced-motion. - Per-panel Up button (#178 #3): Up has moved from the global toolbar into each panel's path bar (next to the existing refresh icon) so the affordance is unambiguously bound to the panel it operates on. Works in both AeroFile mode and dual-pane.
Changed
- Parent folder row navigates on single click (#178 bonus): the legacy
..row required a double-click, inheriting the FileZilla / WinSCP convention. Selecting a Parent row was always a no-op (you cannot download, delete or rename a parent entry) so single-click is strictly better. - Self-extracting auto-update artifacts stage outside
~/Downloads/(#176): portable.zipand.AppImagenow stage into a private cache directory ($XDG_CACHE_HOME/aeroftp/updates/on Linux,~/Library/Caches/aeroftp/updates/on macOS,%LOCALAPPDATA%\aeroftp\updates\on Windows). Installer formats (msi/exe/deb/rpm/dmg) keep~/Downloads/because they ARE the artifact, useful to re-run, copy to USB, hand to a colleague. The Windows portable cmd helper also wipes the staged ZIP, the sigstore sidecar and the temp extraction dir after the swap so the "portable" no-trace contract is honoured. The Linux AppImage install drops the staged source archive after copying it into the running install location. - WebDAV setup example shows the full URL with
https://scheme (#175 follow-up): the previous example "Example: cloud.example.com/remote.php/dav/files/user/" omitted the scheme the server field actually requires, so users would copy-paste a URL the backend then rejected. The placeholder is now hardcoded as a technical example; only the surrounding "Example:" label stays translated.
Fixed
- WebDAV reads tolerate a missing TLS
close_notifyafter the full body has been received: some WebDAV servers do not sendclose_notifyafter the last byte and the previous behaviour aborted the read mid-stream once Content-Length had been satisfied. - Trash purge fixes for MEGA, Internxt and pCloud after live tests: final live-test corrections on top of the benchmark trash-purge work below.
- Filen S3 and WebDAV wrapper triage: connections through Filen's S3 and WebDAV bridges work again after a wrapper-layer regression.
- Filen email placeholder key + Tab.digital
tabdigital.cloudshard recognition: the email field now displays the correct hint, and the Tab.digital connection screen recognisestabdigital.cloudas a Tab.digital shard for proper routing. - 2FA detection ordered before the failure log on the saved-server connect path (#128 follow-up): the saved-server flow logged
Connection to <server> failed. Check credentials.before checking for the TOTP challenge, so the activity log misled users into thinking the password was wrong when the server was just asking for a 2FA code. The order now mirrors the QuickConnect path: 2FA detection first, log entry becomesauth.enter2FAHintinstead ofCheck credentials. - Portable AeroFTP no longer overwrites the installed app's vault keyring entry: portable builds now use a separate
vault-passphrase-portableslot under the sameKEYRING_SERVICE, so a portable instance launched alongside an installed AeroFTP cannot lock the installed vault on first init. - Windows file associations register under HKCU for per-user installs: the previous HKLM writes were being silently dropped by Windows registry virtualisation on non-elevated Tauri NSIS installs, which is why the doc-style MIME icons were never honoured. Explorer's icon cache is also flushed post-install so the icons appear immediately rather than after a logout.
- Windows auto-update no longer flashes a
cmd.execonsole window: droppingDETACHED_PROCESSwhile keepingCREATE_NO_WINDOWand pinning the child stdio to null eliminates the console-allocation race that briefly drew the window before destroying it. - Stale
protocol.tabdigital*andwebdavLocalScheme*translation keys: 5 keys had been carrying[NEEDS TRANSLATION]placeholders in 45 locales since their introduction.npm run i18n:validateis now warning-free.
Benchmark Cleanup: Trash Purge for Consumer Cloud Providers
A targeted cleanup release that stops the CLI benchmark from silently filling up provider trash bins. Reported by a user after a v3.7.5 community benchmark sweep left ~1 GB of test artefacts in Google Drive's trash, with similar leaks expected on Dropbox, OneDrive, Box, MEGA, FileLu, Internxt, kDrive, Zoho WorkDrive, pCloud, OpenDrive and Backblaze B2 over long runs.
Added
StorageProvider::delete_permanenttrait method: a hard-delete path that bypasses the recycle bin. The default returnsOk(false)(no-op), which is correct for protocols without a trash concept (FTP, FTPS, SFTP, plain S3, plain WebDAV) and for any unmigrated provider. Trash-aware providers override it to perform the actual purge.- CLI benchmark trash purge:
aeroftp-cli speedandaeroftp-cli benchmarknow calldelete_permanentafter the standard cleanup. ThespeedJSON / CSV / Markdown reports gain atrash_purgedcolumn and atrash_purge_errorfield. Thebenchmarkcommand logs the purge of the test root and surfaces any failure in the run errors.
Fixed
- Google Drive trash leak: benchmark and speed cleanup now resolves the just-trashed file by basename via
name='X' and trashed=trueand calls the existing inherentpermanent_delete(file_id), leaving the trash empty after the run. - Dropbox trash leak:
delete_permanentwraps the inherentpermanent_delete(path). The OAuth scope set was bumped to includefiles.permanent_deleteso newly issued tokens can perform the call. Existing tokens issued before this release will need a one-time disconnect and reconnect to refresh permissions: a clear hint is now surfaced when the API returns the missing-scope error. - MEGA cmd trash leak:
delete_permanentreconstructs the rubbish path as//bin/<full-relative-path>and invokesmega-rm -r -f. The original inherent helper assumed the trash item was at top level (basename only), which is correct for items the user trashed via the GUI but wrong for items just moved by ourdelete()becausemega-mv ... //bin/preserves the original folder hierarchy under//bin/. NotFound is now treated as Ok(false) so concurrent purges do not propagate as errors. - MEGA native trash leak:
delete_permanentstrips the input to basename before calling the inherentpermanent_delete_from_trash(name). The native SDK'sdelete()moves only the file node (not its parents) to the trash root, so the trashed item is keyed by basename. Passing the original full path was the bug behind the previous "X not found in trash" failures. NotFound is treated as Ok(false). - Box, OpenDrive, kDrive, Zoho WorkDrive trash leak: each provider's
delete_permanentresolves the basename in its trash listing, recovers the item id (and item type / dir flag where required) from the listing metadata, then dispatches to the existing inherentpermanent_delete*helper. - pCloud trash leak (folder case):
delete_permanentresolves the basename in the trash listing and dispatches totrash_clear?folderid=X, which is documented and works. The single-file path (trash_clear?fileid=X) falls back to Ok(false) because the pCloud API silently ignores the unknownfileidquery parameter ontrash_clearand returns a generic "Log in required" error: there is no documented single-file purge endpoint, so trashed plain files rely on pCloud's 30-day retention to reclaim space. Benchmark cleanup is unaffected because the test root is a folder. - FileLu trash leak (single-file case): matches the basename in
files/deletedand callspermanent_delete_file(file_code). Folder-level paths fall back to the no-op default because the FileLu API has no folder permanent-delete endpoint and trashed files do not carry parent-folder identifiers. - Internxt trash leak: matches the basename in the trash listing, extracts the item UUID and type, then issues
DELETE /storage/trashwith{ items: [{ uuid, type }] }. The existinglist_trashwas also fixed: it had been issuing/storage/trash/paginated?offset=X&limit=Ywithout the requiredtypeandrootquery parameters and the gateway rejected the call with 400 Bad Request: it now pages throughtype=foldersandtype=filesseparately and tolerates both the new{ "result": [] }and legacy{ "files": [], "folders": [] }response shapes. On the gateway tested (gateway.internxt.com, 2026-05-09)DELETE /drive/files/{uuid}already removes the file hard so this override mostly returns Ok(false), but it remains wired for deployments and workspace plans that route through a recoverable trash. - Backblaze B2 version leak:
delete_permanentcalls the inherentpermanent_delete_path(path)which walks every version (including hide markers) so soft-deleted files no longer accumulate when versioning is on. - OneDrive recycle bin (Personal accounts): the override is wired to the
permanent_delete(item_id)helper but Microsoft Graph does not expose a documented endpoint for the personal recycle bin: the search now returnsOk(None)instead of erroring out so the benchmark reportstrash_purged: falsecleanly. Microsoft auto-purges the OneDrive recycle bin after 30 days.
Provider notes
- Yandex Disk and Jottacloud: explicitly NOT overridden. Their
delete()already issues a hard delete (permanently=truefor Yandex,?rm=truefor Jottacloud) so the default no-op is correct: a comment on each impl block now records this rationale.
Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage