mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-22 18:22:26 +00:00
Merge PR #1101
This commit is contained in:
commit
99e9f25796
2 files changed
+50
-4
No files matched your search
@@ -798,7 +798,7 @@ fn local_rows(app: &mut LightcraftApp, ui: &mut egui::Ui, now: &LocalNow) {
|
|||||||
for (i, (name, path)) in local.places.iter().enumerate() {
|
for (i, (name, path)) in local.places.iter().enumerate() {
|
||||||
let transient = local.browse_root.as_deref() == Some(path.as_str());
|
let transient = local.browse_root.as_deref() == Some(path.as_str());
|
||||||
let reveal = local.owner == Some(i);
|
let reveal = local.owner == Some(i);
|
||||||
folder_tree(app, ui, name, path, 0.0, current, reveal, transient);
|
folder_tree(app, ui, path, name, path, 0.0, current, reveal, transient);
|
||||||
}
|
}
|
||||||
if app.services.pick_folder.is_some() && row(app, ui, "local:browse", Icon::Plus, crate::i18n::tr("Browse Folder…"), None, false, 0.0).clicked()
|
if app.services.pick_folder.is_some() && row(app, ui, "local:browse", Icon::Plus, crate::i18n::tr("Browse Folder…"), None, false, 0.0).clicked()
|
||||||
{
|
{
|
||||||
@@ -990,10 +990,14 @@ pub(crate) fn fs_cached<T: Clone + Send + 'static>(ui: &egui::Ui, kind: &'static
|
|||||||
/// subfolders. In the tree that holds the folder being browsed (`reveal`), the folders on the
|
/// subfolders. In the tree that holds the folder being browsed (`reveal`), the folders on the
|
||||||
/// way down to it open whenever the browsed folder changes, so it shows highlighted in place.
|
/// way down to it open whenever the browsed folder changes, so it shows highlighted in place.
|
||||||
/// `transient`: a top-level row listed for this session only (it offers Keep in Local).
|
/// `transient`: a top-level row listed for this session only (it offers Keep in Local).
|
||||||
|
/// `place`: the top-level folder this tree hangs from. A folder can be listed in more than one
|
||||||
|
/// tree (Pictures on its own and inside Home): each row opens and closes by itself, and their
|
||||||
|
/// triangles have ids of their own, else the copy drawn last takes the other's clicks (#1093).
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn folder_tree(
|
fn folder_tree(
|
||||||
app: &mut LightcraftApp,
|
app: &mut LightcraftApp,
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
|
place: &str,
|
||||||
name: &str,
|
name: &str,
|
||||||
path: &str,
|
path: &str,
|
||||||
indent: f32,
|
indent: f32,
|
||||||
@@ -1001,13 +1005,13 @@ fn folder_tree(
|
|||||||
reveal: bool,
|
reveal: bool,
|
||||||
transient: bool,
|
transient: bool,
|
||||||
) {
|
) {
|
||||||
let open_id = egui::Id::new(("folder-open", path.to_string()));
|
let open_id = egui::Id::new(("folder-open", place.to_string(), path.to_string()));
|
||||||
let sel = current.is_some_and(|c| same_folder(c, path));
|
let sel = current.is_some_and(|c| same_folder(c, path));
|
||||||
let on_the_way = !sel && current.is_some_and(|c| lightcraft_catalog::query::folder_within(c, path));
|
let on_the_way = !sel && current.is_some_and(|c| lightcraft_catalog::query::folder_within(c, path));
|
||||||
let mut open = tree_open(ui, open_id, false);
|
let mut open = tree_open(ui, open_id, false);
|
||||||
if reveal && on_the_way {
|
if reveal && on_the_way {
|
||||||
// opened once per browsed folder: collapsing it again afterwards sticks
|
// opened once per browsed folder: collapsing it again afterwards sticks
|
||||||
let revealed_id = egui::Id::new(("folder-revealed", path.to_string()));
|
let revealed_id = egui::Id::new(("folder-revealed", place.to_string(), path.to_string()));
|
||||||
let target = current.map(str::to_string);
|
let target = current.map(str::to_string);
|
||||||
if ui.data(|d| d.get_temp::<Option<String>>(revealed_id)) != Some(target.clone()) {
|
if ui.data(|d| d.get_temp::<Option<String>>(revealed_id)) != Some(target.clone()) {
|
||||||
open = true;
|
open = true;
|
||||||
@@ -1070,7 +1074,7 @@ fn folder_tree(
|
|||||||
});
|
});
|
||||||
if open && indent < 12.0 * 8.0 {
|
if open && indent < 12.0 * 8.0 {
|
||||||
for (n, p) in subfolders(ui, path) {
|
for (n, p) in subfolders(ui, path) {
|
||||||
folder_tree(app, ui, &n, &p, indent + 12.0, current, reveal, false);
|
folder_tree(app, ui, place, &n, &p, indent + 12.0, current, reveal, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -896,6 +896,48 @@ fn local_folder_tree_expands_and_browses() {
|
|||||||
h.settle(SETTLE);
|
h.settle(SETTLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A folder listed twice in Local (Pictures as a place of its own and again inside Home) opens
|
||||||
|
/// and closes on each row by itself: both copies of its triangle used to share one egui id, so
|
||||||
|
/// the copy drawn later took the clicks of the one drawn first (issue #1093).
|
||||||
|
#[test]
|
||||||
|
fn local_folder_listed_twice_opens_and_closes_each_row() {
|
||||||
|
let base = std::env::temp_dir().join(format!("lc-ui-twice-{}", std::process::id()));
|
||||||
|
let _ = std::fs::remove_dir_all(&base);
|
||||||
|
let inner = base.join("Inner");
|
||||||
|
std::fs::create_dir_all(inner.join("Sub")).unwrap();
|
||||||
|
let mut h = detail("panel.edit");
|
||||||
|
exec(&mut h, "view.leftPanel", json!({"show": true}));
|
||||||
|
h.hide_home_above(&base);
|
||||||
|
let (base_s, inner_s) = (base.to_string_lossy().to_string(), inner.to_string_lossy().to_string());
|
||||||
|
let sub = inner.join("Sub").to_string_lossy().to_string();
|
||||||
|
exec(&mut h, "local.addRoot", json!({"path": base_s}));
|
||||||
|
exec(&mut h, "local.addRoot", json!({"path": inner_s}));
|
||||||
|
h.settle(SETTLE);
|
||||||
|
let r = h.request("ui.clickWidget", json!({"id": format!("folderToggle:{base_s}")}), T);
|
||||||
|
assert_eq!(r["ok"], true, "{r}");
|
||||||
|
let toggle = format!("folderToggle:{inner_s}");
|
||||||
|
h.step_until(SETTLE, |h| h.app.widgets.iter().filter(|(w, _)| *w == toggle).count() == 2);
|
||||||
|
let rows = |h: &Headless, id: &str| h.app.widgets.iter().filter(|(w, _)| w == id).count();
|
||||||
|
assert_eq!(rows(&h, &toggle), 2, "Inner is listed inside the base folder and as a place of its own");
|
||||||
|
let sub_row = format!("source:local:{sub}");
|
||||||
|
assert_eq!(rows(&h, &sub_row), 0);
|
||||||
|
// each copy's triangle opens that copy only, and closes it again
|
||||||
|
for copy in 0..2 {
|
||||||
|
let at = h.app.widgets.iter().filter(|(w, _)| *w == toggle).nth(copy).map(|(_, r)| r.center()).unwrap();
|
||||||
|
let r = h.request("ui.click", json!({"x": at.x, "y": at.y}), T);
|
||||||
|
assert_eq!(r["ok"], true, "{r}");
|
||||||
|
h.step_until(SETTLE, |h| h.app.widgets.iter().any(|(w, _)| *w == sub_row));
|
||||||
|
assert_eq!(rows(&h, &sub_row), 1, "copy {copy} opens, the other stays closed");
|
||||||
|
let at = h.app.widgets.iter().filter(|(w, _)| *w == toggle).nth(copy).map(|(_, r)| r.center()).unwrap();
|
||||||
|
let r = h.request("ui.click", json!({"x": at.x, "y": at.y}), T);
|
||||||
|
assert_eq!(r["ok"], true, "{r}");
|
||||||
|
h.settle(SETTLE);
|
||||||
|
assert_eq!(rows(&h, &sub_row), 0, "copy {copy} closes again");
|
||||||
|
}
|
||||||
|
let _ = std::fs::remove_dir_all(&base);
|
||||||
|
h.settle(SETTLE);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn slideshow_advances_pauses_and_ends() {
|
fn slideshow_advances_pauses_and_ends() {
|
||||||
let mut h = detail("panel.edit");
|
let mut h = detail("panel.edit");
|
||||||
|
|||||||
Reference in new issue
Block a user