Say a photograph is downloading, and how far, instead of failing
The develop view reported a remote original on its way through the error message, so it read "Could not load image" over "Downloading…". It did so on every step along the roll, including a cached frame that was ready within a tick, so each step flashed the error. Waiting is now its own state. On the step, the grid's thumbnail of the photograph stands in at once. Only when a transfer is really on the wire does it dim under "Not on this device yet", with a line like "Downloading — 12.4 of 38.0 MB" and a progress bar. The bytes come from a new RemoteBackend::get_reporting. The Nextcloud backend overrides it to read the body chunk by chunk; the default reports once at the end. Progress is kept in the in-flight registry by path, because a step usually lands on a frame the prefetcher is already fetching. The catalog's file length stands in when the server sends no Content-Length.
This commit is contained in:
@@ -415,6 +415,31 @@ pub fn describe_bytes(bytes: u64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// TRACES: FR-NC-6a
|
||||
/// A download someone is watching, as the line under its bar and how full the
|
||||
/// bar is: `received` of `total` bytes, and a fraction in 0..1 — or below
|
||||
/// zero when there is no total, which the bar draws as indeterminate rather
|
||||
/// than as a position it would have to invent.
|
||||
pub fn describe_download(received: u64, total: Option<u64>) -> (String, f32) {
|
||||
match total.filter(|&t| t > 0) {
|
||||
// Nothing yet: the size alone says what the wait is for, where
|
||||
// "0 kB of 38.0 MB" would read as a transfer that has stalled.
|
||||
Some(t) if received == 0 => (format!("Downloading {}", describe_bytes(t)), 0.0),
|
||||
// A file that grew since the scan measured it can overrun the
|
||||
// catalog's length; the bar stops full rather than past its end.
|
||||
Some(t) => (
|
||||
format!(
|
||||
"Downloading — {} of {}",
|
||||
describe_bytes(received),
|
||||
describe_bytes(t.max(received))
|
||||
),
|
||||
(received as f64 / t as f64).min(1.0) as f32,
|
||||
),
|
||||
None if received > 0 => (format!("Downloading — {}", describe_bytes(received)), -1.0),
|
||||
None => ("Downloading…".to_string(), -1.0),
|
||||
}
|
||||
}
|
||||
|
||||
/// A running job, held by whatever is reporting on it.
|
||||
///
|
||||
/// Every method is idempotent and every one is a no-op once the job has
|
||||
@@ -498,6 +523,25 @@ impl Drop for Activity {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn a_download_reads_as_what_it_knows() {
|
||||
let mb = 1024 * 1024;
|
||||
assert_eq!(describe_download(0, None), ("Downloading…".to_string(), -1.0));
|
||||
assert_eq!(
|
||||
describe_download(0, Some(38 * mb)),
|
||||
("Downloading 38.0 MB".to_string(), 0.0)
|
||||
);
|
||||
let (text, fraction) = describe_download(19 * mb, Some(38 * mb));
|
||||
assert_eq!(text, "Downloading — 19.0 MB of 38.0 MB");
|
||||
assert_eq!(fraction, 0.5);
|
||||
let (text, fraction) = describe_download(12 * mb, None);
|
||||
assert_eq!(text, "Downloading — 12.0 MB");
|
||||
assert!(fraction < 0.0, "no total, no position");
|
||||
let (text, fraction) = describe_download(40 * mb, Some(38 * mb));
|
||||
assert_eq!(text, "Downloading — 40.0 MB of 40.0 MB");
|
||||
assert_eq!(fraction, 1.0, "an overrun stops full");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_running_job_makes_the_bar_busy() {
|
||||
let log = ActivityLog::new();
|
||||
|
||||
Reference in New Issue
Block a user