[4.0.4] - 2026-06-07
Reversible Restricted-Filename Encoding, CLI Polish and Stability
A focused follow-up to v4.0.3. Filenames that a provider would otherwise reject now round-trip transparently on Box, Dropbox, Jottacloud and OpenDrive; the interactive CLI absorbs the next wave of the community wishlist (#270); and three stability bugs are fixed, including a long-standing tray crash on suspend/resume, a zero-size main window on macOS Tahoe (#290), and an OAuth reconnect that re-ran the full browser flow every time (#270).
Added
- Reversible restricted-filename encoding (#272, #266): Box, Dropbox, Jottacloud and OpenDrive now transparently encode filename characters the provider rejects (control characters plus each provider's reserved set) using the rclone-compatible reversible scheme (fullwidth and control-picture mappings, a quote-collision escape, and position-dependent space and dot rules), then decode them back on listing. A name like
a:bround-trips intact instead of failing silently. The encode/decode runs once at the provider boundary, so it covers the GUI, every CLIcmd_*handler, CLIsync/benchmark, the transfer engine and the session manager at once, and is property-testeddecode(encode(s)) == sover tens of thousands of cases per provider. Providers whose only restriction is control characters keep the clear localized error from v4.0.3. (@EhudKirsh, #272/#266) - CLI interactive shell polish (#270): the
profiles -iuser-switch now accepts the compactu3/3utokens (it was the only action that still required the spacedu <N|name>form), and a# <selector> <N>reorder reprints the table with a visual diff: a red struck-through ghost at the old slot, the live row at the new slot joined by a left-gutter arrow, andold -> newmarkers on every row whose index shifted. (@EhudKirsh, #270) - Lightweight CI checks job: a fast workflow runs
cargo fmt --check,cargo audit(RustSec advisory scan) and the vitest React suite on every PR and push, outside the heavy Tauri build/release matrix, closing three gaps in CI coverage.
Changed
- Discover health-check toggle is now an icon-only button: the Activity icon is lit when health checks are on and dimmed when off, replacing the sliding switch for the same on/off affordance (
role=switchandaria-checkedkept). The manual Check button is unchanged. - My Servers filters: My Servers gains a "Local bridge" filter chip. The free/paid and HQ-country signals stay on the Discover page, where they help before you sign up, and were dropped from My Servers, where an already-saved server makes them redundant.
- PixelUnion catalog corrected to 16 GB free storage with a free API, regenerating the CLI catalog, README and docs/PROVIDERS.md from the single source of truth.
Fixed
- macOS Tahoe zero-size window (#290): the main window could come up at a
0x0content size on macOS 26 Tahoe, leaving only a Dock icon. Two causes are addressed. First, a window-state file poisoned by the pre-v4.0.3 borderless builds saved a0x0size, so even after the v4.0.3 overlay title-bar fix the window was restored at zero size; the app now self-heals any restored inner size below the minimum (or zero) by resetting it to the computed initial size and re-centering, repairing already-poisoned state files without the user deleting anything (idempotent on healthy windows, cross-platform). Second, the reporter confirmed the WebKit content can still collapse to0x0atshow()time even with a completely fresh config, so the size is now also re-asserted after the window is on screen (the documented WebKit workaround) and re-checked on a short delay, with timestamped[diag #290]lines added at four points to pinpoint exactly when a collapse lands. (@alexhorner, #290) - Default account skipped welcome after tray Quit (#270): with more than one passphrase-free account the boot picker reappeared on every relaunch instead of entering the starred default, because a persisted password-free active user reported as already unlocked and bypassed the default-account fast path. The boot policy is now a pure, unit-tested decision that honors the default account on boot (the default wins over the last-active user); protected accounts still show their prompt and an explicit "switch account" still forces the picker. (@EhudKirsh, #270)
- OAuth reconnect re-authorized every time (#270): reconnecting an OAuth profile re-ran the full browser authorization instead of reusing the saved per-profile token, because a snake_case
profile_idargument never bound through Tauri v2's camelCase mapping and the check fell back to the legacy singleton key. PassingprofileIdso it binds restores token reuse on reconnect. (@EhudKirsh, #270) - Tray heap corruption on suspend/resume: tray badge updates mutated the StatusNotifierItem (over GDBus on Linux) directly from caller threads, including the background sync worker on a tokio worker thread, racing the GLib main loop and corrupting the GLib heap (the recurring
malloc(): unaligned fastbin chunk detectedabort). The RGBA icon is now generated off-thread and every tray mutation is marshalled onto the GTK main thread viarun_on_main_thread. - CLI bootstrap hardening + rclone FTPS export:
--help,--version,agent-info,profiles,catalogandcompletionsno longer depend prematurely on config / data-root / AIMD, the pre-clap parser no longer mistakes valued global options for subcommands, and a missing or unreadable default AIMD config no longer blocks metadata commands. rclone export now emits onlyexplicit_tls = truefor FTPS profiles; the previoustls = truemeant implicit FTPS to rclone and produced an unusable remote.
Maintenance
cargo fmtsweep acrosssrc-tauri(no semantic change, only re-wrapping and trailing-newline fixes) to bring the tree tocargo fmt --checkcompliance after several wishlist contributions, now enforced by the new CI checks job.
Contributors
Thanks to the people who shaped this release:
Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage