Show active transfer count, add SFTP retry resilience, and fix config tab refresh

- Use rclone transferring array to show only active transfers instead of
  cumulative count; zero out speed when no transfers are active
- Add SFTP retry/timeout flags to rclone mount for flaky Tailscale tunnels
- Skip auto-refresh on config tab to prevent editor resets

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
grabbit 2026-02-19 00:21:22 +08:00
parent 16d11aa4ef
commit 15f915fbee
4 changed files with 34 additions and 3 deletions

View File

@ -70,6 +70,16 @@ pub fn build_mount_args(config: &Config, share: &ShareConfig, rc_port: u16) -> V
args.push("--transfers".into());
args.push(config.writeback.transfers.to_string());
// SFTP connection resilience: increase retries for flaky tunnels (Tailscale/WireGuard)
args.push("--retries".into());
args.push("10".into());
args.push("--low-level-retries".into());
args.push("20".into());
args.push("--retries-sleep".into());
args.push("1s".into());
args.push("--contimeout".into());
args.push("30s".into());
// Bandwidth limits (only add flag if at least one direction is limited)
let bw = format_bwlimit(&config.bandwidth.limit_up, &config.bandwidth.limit_down);
if bw != "0" {

View File

@ -16,6 +16,9 @@ pub struct CoreStats {
pub errors: u64,
#[serde(rename = "totalBytes")]
pub total_bytes: Option<u64>,
/// Currently active transfers (present only when transfers are running).
#[serde(default)]
pub transferring: Vec<serde_json::Value>,
}
/// Response from `vfs/stats`.
@ -233,5 +236,22 @@ mod tests {
assert_eq!(stats.bytes, u64::MAX);
assert_eq!(stats.transfers, 1000000);
assert_eq!(stats.errors, 999);
assert!(stats.transferring.is_empty());
}
#[test]
fn test_core_stats_with_active_transferring() {
let json = r#"{
"bytes": 1048576,
"speed": 524288.0,
"transfers": 5,
"errors": 0,
"transferring": [
{"name": "file1.jpg", "size": 1024, "bytes": 512},
{"name": "file2.jpg", "size": 2048, "bytes": 1024}
]
}"#;
let stats: CoreStats = serde_json::from_str(json).unwrap();
assert_eq!(stats.transferring.len(), 2);
}
}

View File

@ -732,8 +732,9 @@ fn update_status(
// Fetch core stats (speed, transfers)
if let Ok(core) = rc::core_stats(mc.rc_port) {
ss.speed = core.speed;
ss.transfers = core.transfers;
let active = core.transferring.len() as u64;
ss.speed = if active > 0 { core.speed } else { 0.0 };
ss.transfers = active;
ss.errors = core.errors;
}
}

View File

@ -25,7 +25,7 @@
if (this._timer) { clearInterval(this._timer); this._timer = null; }
},
refreshTab() {
if (this.activeTab === 'dashboard' || this.activeTab === 'logs') return;
if (this.activeTab === 'dashboard' || this.activeTab === 'logs' || this.activeTab === 'config') return;
let url = '/tabs/' + this.activeTab;
if (this.activeTab === 'shares') {
const el = document.querySelector('#tab-content [x-data]');