fix(gui,cli): count what a folder's first scan has checked (#46)

The first pass over a synced folder has no baseline to estimate from, so
its scan showed only "checking for changes…" in the app and "scanning…"
in `pdfs sync list`. For a large folder that scan reads every item on
Proton Drive before anything downloads, which takes many minutes and
looked stuck. Both now show how many items the scan has checked so far.
This commit is contained in:
nvrl committed 2026-10-26 22:28:46 +01:00
1 parent a5acae41b3
commit 0e7ffe1261
12 files changed
+833 -687

No files matched your search

+8 -1
View File
@@ -1143,7 +1143,14 @@ fn cmd_sync(action: SyncCmd) -> Result<()> {
// A pass in flight says what it is doing, indented under it.
if let Some(p) = &f.progress {
match p.phase {
SyncPhase::Scanning if p.total == 0 => println!(" scanning…"),
SyncPhase::Scanning if p.total == 0 && p.done == 0 => {
println!(" scanning…")
}
// A first pass has no estimate yet; the count alone
// shows a long first scan is moving.
SyncPhase::Scanning if p.total == 0 => {
println!(" scanning: {} checked", p.done)
}
SyncPhase::Scanning => {
println!(
" scanning: {} of {}",
+42 -3
View File
@@ -629,9 +629,17 @@ pub(crate) fn sync_state_label(state: &str) -> String {
/// — so both read "12 of 40" rather than a percentage that could go backwards.
pub(crate) fn sync_progress_label(p: &SyncProgress) -> String {
match p.phase {
// Before the first pass finishes there is no estimate, so the count would
// be "checked 12 of 12" — worse than saying nothing.
SyncPhase::Scanning if p.total == 0 => gettext("checking for changes…"),
SyncPhase::Scanning if p.total == 0 && p.done == 0 => gettext("checking for changes…"),
// Before the first pass finishes there is no estimate, so "12 of 12" would
// say nothing. The count alone still shows a first scan of a large folder
// moving, which can take many minutes before anything downloads.
// Translators: {n} counts the folders and files checked so far.
SyncPhase::Scanning if p.total == 0 => ngettext_f(
"checking for changes — {n} item checked",
"checking for changes — {n} items checked",
p.done as u64,
&[],
),
// Translators: {done} and {total} count folders and files checked so far.
SyncPhase::Scanning => gettext_f(
"checking for changes — {done} of {total}",
@@ -1296,6 +1304,37 @@ mod tests {
);
}
fn scanning(done: usize, total: usize) -> SyncProgress {
SyncProgress {
phase: SyncPhase::Scanning,
done,
total,
current: String::new(),
}
}
#[test]
fn a_first_scan_counts_what_it_checked() {
// A first sync of a large folder scans for many minutes before anything
// downloads; without a count it reads as stuck (#46).
assert_eq!(
sync_progress_label(&scanning(0, 0)),
"checking for changes…"
);
assert_eq!(
sync_progress_label(&scanning(1, 0)),
"checking for changes — 1 item checked"
);
assert_eq!(
sync_progress_label(&scanning(1234, 0)),
"checking for changes — 1234 items checked"
);
assert_eq!(
sync_progress_label(&scanning(12, 40)),
"checking for changes — 12 of 40"
);
}
#[test]
fn the_restore_picker_names_the_computer_it_restores_from() {
assert!(restore_picker_body(Some("laptop")).contains("“laptop”"));