Let the top level be chosen as the library root
Confirming "/" in the folder picker set an empty root, which the launch model read as no root at all: "Open library" stayed disabled after the question had plainly been answered, and a folder library — whose folder is the whole library — could never be opened without first descending into a subfolder of it. The empty string was carrying two meanings. Record the choice as its own fact on the account (`root_chosen`, defaulted so existing configuration loads unchanged), treat a folder endpoint as chosen by definition, and let the launch screen say so: a folder is shown as a LIBRARY rather than an ACCOUNT, the second question becomes an optional "scan only a subfolder", and the library header names the folder instead of calling it "· whole account".
This commit is contained in:
@@ -984,14 +984,7 @@ pub fn open(
|
||||
window.set_library_status("Starting…".into());
|
||||
// Always visible: two folders one letter apart are easy to confuse, and a
|
||||
// scan of the wrong one is indistinguishable from a broken scan.
|
||||
window.set_library_root_label(
|
||||
if conn.account.root.is_empty() {
|
||||
format!("{} · whole account", conn.account.user_id)
|
||||
} else {
|
||||
format!("{}/{}", conn.account.user_id, conn.account.root)
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
window.set_library_root_label(library_root_label(&conn.account).into());
|
||||
|
||||
// An empty filter would walk the whole tree and match nothing, which looks
|
||||
// exactly like a broken scan. Say so instead.
|
||||
@@ -7158,10 +7151,49 @@ fn stop(slot: &RefCell<Option<slint::Timer>>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// The line in the library header that says what is being catalogued.
|
||||
///
|
||||
/// For an account with a user, the user and the chosen subtree, or the
|
||||
/// whole account when none was chosen. For a folder there is no user and
|
||||
/// the endpoint is the library, so the folder's own name: `library`, or
|
||||
/// `library/2026` when narrowed — never " · whole account", which is a
|
||||
/// sentence about a server said of a directory.
|
||||
fn library_root_label(account: &Account) -> String {
|
||||
if account.login.is_empty() {
|
||||
let folder = std::path::Path::new(&account.endpoint)
|
||||
.file_name()
|
||||
.map(|n| n.to_string_lossy().into_owned())
|
||||
.unwrap_or_else(|| account.endpoint.clone());
|
||||
if account.root.is_empty() {
|
||||
folder
|
||||
} else {
|
||||
format!("{folder}/{}", account.root)
|
||||
}
|
||||
} else if account.root.is_empty() {
|
||||
format!("{} · whole account", account.user_id)
|
||||
} else {
|
||||
format!("{}/{}", account.user_id, account.root)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn the_header_names_a_folder_library_by_its_folder() {
|
||||
let mut folder = Account::new("folder", "/var/tmp/dr-demo/library");
|
||||
assert_eq!(library_root_label(&folder), "library");
|
||||
folder.root = "2026".into();
|
||||
assert_eq!(library_root_label(&folder), "library/2026");
|
||||
|
||||
let mut cloud =
|
||||
Account::new("nextcloud", "https://cloud.example").with_login("duncan", "duncan");
|
||||
assert_eq!(library_root_label(&cloud), "duncan · whole account");
|
||||
cloud.root = "PhotosRaw".into();
|
||||
assert_eq!(library_root_label(&cloud), "duncan/PhotosRaw");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_scrub_fraction_interpolates_within_the_span() {
|
||||
// The point of going fractional: a slow drag must advance
|
||||
|
||||
Reference in New Issue
Block a user