vergen-git2 reads git metadata at build time, but the crates.io source
tarball ships no .git, so the published 1.1.0 fails on `cargo install`.
crates.io versions are immutable (no overwrite) and Chocolatey's
moderation queue blocks a fast re-push, so a clean 1.1.1 without vergen
is the only fix.
Queued transfers stored only the destination directory as the target
path. Downstream upload logic treats the queued destination as the full
file path and passes it straight to create_file, so transfers failed
with a Failure error when the remote target resolved to a directory.
Append each entry's file name to the destination directory at enqueue
time in both enqueue_file and enqueue_all, matching the single-file
transfer path which already builds the full target path.
keyring v4 is no longer a library crate; the API moved to keyring-core
plus per-platform credential store crates. Replace the keyring dependency
with keyring-core and the native store crates, and register the default
store at runtime (lazily, once) since v4 no longer selects it at compile
time via Cargo features.
Migrate to the new RustCrypto cipher 0.5 traits (aes 0.9, cbc 0.2),
rand 0.10 and vergen-git2 10, whose APIs changed:
- vergen-git2: builders renamed (BuildBuilder -> Build, etc.) and the
all_* constructors no longer return a Result
- aes/cbc: BlockDecryptMut -> BlockModeDecrypt and
decrypt_padded_vec_mut -> decrypt_padded_vec
- rand: sample API moved
An empty copy destination resolved to the source file's own path, so
std::fs::copy truncated the original file to 0 bytes.
- localhost::copy now refuses to copy a file onto itself, returning an
error instead of truncating it (root cause).
- action_copy treats an empty/whitespace destination as a cancel.
Closes#421
Resolve the config directory through a single per-platform config_dir()
function instead of relying on dirs::config_dir everywhere:
- macOS: ~/.config/termscp (was ~/Library/Application Support/termscp)
- Windows: %USERPROFILE%\.termscp (was roaming %APPDATA%\termscp)
- Linux/other: /termscp (unchanged)
Existing users are migrated automatically on first run: when the new
directory is absent and the legacy location exists, the whole config
directory is moved to the new path. The cache directory stays at the
platform-native location.
Closes#431
The bottom (partial) bar carried a block title (the current filename),
which forces a 1-row top inset in ratatui's `Block::inner` even though
its top border is dropped to join the seam with the full bar. That left
the partial bar with one inner row while the full bar kept two, so the
two gauges rendered at unequal heights.
- Move the filename from the partial bar's title into its gauge label.
- Skip setting an empty title so no phantom top-positioned title triggers
the inset.
- Put the panel title on the top (full) bar for multi-file transfers.
- Bump the two-bar popup height to fit the joined panel.
Also bump Cargo.lock and adapt the embedded terminal to the new vt100
`screen_mut()` API.
Migrate the transfer progress UI to tuirealm 4, where the stdlib
`ProgressBar` widget was dropped, by rebuilding the dual-bar panel on
top of `Gauge`.
- Restore the unified two-bar look: the full bar (top) and partial bar
(bottom) draw joined borders so they read as a single panel; a single
file shows one fully-bordered bar.
- Redraw on every file boundary in the send/recv queue loops so the
full bar's (N/total) counter advances even for small files that finish
within one in-loop redraw interval.
- Track progress with a single `TransferProgress` (exact file count from
the pre-scan, lazy partial/full computation) and consolidate the theme
progress-bar fields.
Some non-compliant FTP servers (e.g. LiteSpeed) include a self-reference
to the listed directory in the LIST response, causing the current folder
to appear as a duplicate entry in the explorer.
Closes#410
Upgrade tuirealm (3.x -> 4.0.0), tui-realm-stdlib (3 -> 4), tui-term
(0.2 -> 0.3). Apply all breaking changes from the 4.0 migration guide
across the termscp UI.
Key changes:
- Root-level re-exports removed; imports moved to module-qualified
paths (`tuirealm::application`, `::component`, `::event`, `::props`,
`::state`, `::subscription`, `::listener`, `::ratatui`). Same for
stdlib component types (`tui_realm_stdlib::components::*`).
- `MockComponent` trait renamed to `Component`; old `Component` trait
renamed to `AppComponent`. `#[derive(MockComponent)]` is now
`#[derive(Component)]`. `Component::on` now takes `&Event<_>`.
- `TextSpan` replaced with `SpanStatic`/`LineStatic`/`TextStatic`
(ratatui-based); tuple `(String, Alignment)` titles replaced with
the new `Title` builder; `Alignment` split into
`HorizontalAlignment`/`VerticalAlignment`; stdlib components use
`.alignment_horizontal` instead of `.alignment`.
- `State::One`/`PropPayload::One` -> `Single`. `CmdResult::None`
-> `NoChange`. `Props::get_or` removed; `Props::get` now returns a
borrowed `Option<&AttrValue>` (call sites switched to
`.and_then(AttrValue::as_*)`). `Component::query` returns
`Option<QueryResult<'a>>`.
- `Attribute::HighlightedColor` -> `HighlightStyle` (a full `Style`).
`.highlighted_*` helpers renamed to `.highlight_*`.
- `PollStrategy::UpTo(n)` now requires a `Duration`; tick timeout moved
from `EventListenerCfg::poll_timeout` into `PollStrategy`.
- `TerminalBridge` removed; `Context` now holds
`CrosstermTerminalAdapter` directly and enables raw mode + alternate
screen explicitly. The `TerminalAdapter` trait is imported where its
methods are used.
- `Update` trait removed; activity `update` methods are plain inherent
functions.
- `ProgressBar` replaced by stdlib `Gauge`. Paragraph `.wrap` renamed
to `.wrap_trim`; `.text` now takes an `Into<Text>`. Stdlib `List` row
items are now individual lines (`Vec<Span>` per row) rather than a
`Table` of spans; custom `FileList`/`Log` convert between the two
models.
- Radio builders drop `.foreground(color)` so unselected items render
with the terminal default foreground, and set
`highlight_style(Style::default().fg(color).add_modifier(REVERSED))`
so the selected entry is visibly highlighted only with the theme
color.
- Custom `FileList` keeps the selected row highlighted with the full
highlight style when focused and falls back to a foreground-only
style when unfocused.
- Theme loading is now backwards compatible: `Theme` uses a custom
`Deserialize` through an intermediate `ThemeFile` with optional
fields, so missing keys, unknown values or legacy aliases
(`transfer_progress_bar_full`/`_partial`) fall back to defaults on a
per-field basis instead of failing the whole load.
The old 1% progress threshold caused the UI to appear frozen on large
files (e.g. 1GB) because many read/write iterations passed between
redraws. Switching to a 100ms time-based interval ensures consistent
UI responsiveness regardless of file size.
Remove production panic and unwrap paths from core modules.
Propagate bookmark encryption failures, harden file watcher and temp mapped file handling, and clean up dead code in shared utilities.
The `Exec` arm of `Command::from_str` only captured the first
whitespace-delimited token, silently dropping all arguments.
Now passes the entire input string so e.g. `ls -la /tmp` works.
`absolutize` now lexically normalizes paths so `cd ..` navigates to the
parent directory instead of appending `..` literally. Also guard against
`file_name()` returning `None` in `fmt_path_elide_ex`, which caused a
panic on paths containing unresolved `..` components.
Closes#402
* fix: replace recursive byte-counting with entry-based transfer progress
Replace the expensive recursive `get_total_transfer_size` pre-calculation
with a lightweight entry-based counter (`TransferProgress`) for the
overall progress bar. This avoids deep `list_dir` traversals before
transfers begin, which could cause FTP idle-timeout disconnections on
large directory trees.
The per-file byte-level progress bar (`ProgressStates`) remains
unchanged. Bytes are still tracked via `TransferStates::add_bytes` for
notification threshold logic.
Closes#384
magic-crypt has known vulnerabilities. Replace it with aes-gcm for new
encryption (authenticated, with random nonces) while keeping a legacy
AES-128-CBC decryption path to transparently handle existing bookmarks.