-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support of auto folded directories #7674
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work @ABckh . Thanks for adding tests and that demo video. I left some suggestions on the implementation.
@@ -120,6 +122,8 @@ actions!( | |||
Open, | |||
ToggleFocus, | |||
NewSearchInDirectory, | |||
UnfoldTheChildren, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's call these commands "Fold/Unfold Directory" instead of "Fold/Unfold The Children".
@@ -45,6 +45,8 @@ pub struct ProjectPanel { | |||
visible_entries: Vec<(WorktreeId, Vec<Entry>)>, | |||
last_worktree_root_id: Option<ProjectEntryId>, | |||
expanded_dir_ids: HashMap<WorktreeId, Vec<ProjectEntryId>>, | |||
collapsed_dir_paths: HashMap<ProjectEntryId, String>, | |||
excluded_collapsed_dir_paths: HashMap<ProjectEntryId, String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should only add a single piece of state here: unfolded_dir_ids
- which are the set of directories that have been explicitly unfolded. It could be structured similarly to expanded_dir_ids
(in a hash map keyed by WorktreeId
, or perhaps a simple HashSet<ProjectEntryId>
.
I think we can remove the String
(for the folded paths). I'll explain more below.
while let Some(entry) = entry_iter.entry() { | ||
visible_worktree_entries.push(entry.clone()); | ||
if auto_collapse_dirs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than storing the folded paths explicitly as strings, I think we could use the existing path
field that's on an Entry, and if we noticed that the entrie's descendant directories should be folded, we can render multiple components of the path (instead of just the filename).
So in this loop, could we simply omit entries for directories that are folded, so that the visible_worktree_entries
vector would look like this:
[
Entry {
path: "src",
// ...
},
// The entries for the singleton directories `dir1` and `dir2` are omitted,
// because we decided to fold those single-child directories.
Entry {
path: "src/dir1/dir2/TheFile.java",
// ...
},
]
Then, when processing these entries in for_each_visible_entry
, we could notice that the entry for TheFile.java
has some folded descendants, because its path differs from its predecessor's path by more than one path component. When we detect that, we could render all of the additional path components (dir1/dir2/TheFile.java
), not just the filename (TheFile.java
).
With this approach, we don't need to store as much redundant state. Does that make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does, this approach looks better. I will try to implement it, thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than storing the folded paths explicitly as strings, I think we could use the existing
path
field that's on an Entry, and if we noticed that the entrie's descendant directories should be folded, we can render multiple components of the path (instead of just the filename).So in this loop, could we simply omit entries for directories that are folded, so that the
visible_worktree_entries
vector would look like this:[ Entry { path: "src", // ... }, // The entries for the singleton directories `dir1` and `dir2` are omitted, // because we decided to fold those single-child directories. Entry { path: "src/dir1/dir2/TheFile.java", // ... }, ]Then, when processing these entries in
for_each_visible_entry
, we could notice that the entry forTheFile.java
has some folded descendants, because its path differs from its predecessor's path by more than one path component. When we detect that, we could render all of the additional path components (dir1/dir2/TheFile.java
), not just the filename (TheFile.java
).With this approach, we don't need to store as much redundant state. Does that make sense?
Hi @maxbrunsfeld ,
I've returned to work on the PR and I have a question about the implementation. I've managed to achieve this structure for visible_worktree_entries
:
[
Entry {
path: "src",
// ...
},
// The entries for the singleton directories `dir1` and `dir2` are omitted,
// because we decided to fold those single-child directories.
Entry {
path: "src/dir1/dir2/TheFile.java",
// ...
},
]
However, I didn't fully understand how you want them to be rendered properly. So what I did is I took the parent entry from visible_worktree_entries
and calculated the difference, then I changed the filename and depth of a child based on that difference. From what I understood, this might not be the way you want it to be rendered. Could you please clarify?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that sounds good to me. I just didn't think we need to maintain additional state for the paths of collapsed directories. It looks like there is still that state on the branch. Are you talking about changes that you haven't pushed up yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I have not pushed it yet, still facing issues with some corner cases. Thank you for clarification!
A few notes related to the UX, based on a real Java project (https://github.com/vaadin/flow/) ![]() Here, ![]() Here
![]() it does close the new unfolded directories, and I have to make an extra click to open the back: ![]() that does not seem right to me, as the original, folded view did show those directories as "open". |
How does this interact with paths that only have an empty directory at the end? Particularly if you have say, |
I don't really have experience with such functionality so no good references. Not folding seems reasonable there. And I assume |
Yep, it does not matter if the last dir has children or not |
do you consider a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for making that refactoring @ABckh. Looks good.
Reverts #7674 @ABckh: reverting this as it introduced a significant performance slowdown, most likely caused by iterating through all the snapshot entries to determine whether a directory is foldable/unfoldable/omitted. It would be great if you could open a new PR that reverts this revert and addresses the performance issues. Thank you! /cc: @maxbrunsfeld Release notes: - N/A
Fixed auto folded dirs which caused significant performance issues #8476 (#7674) Moved from iterating over snapshot entries to use `child_entries` function from `worktree.rs` by making it public @maxbrunsfeld Release Notes: - Fixed a bug where project panel settings changes would not be applied immediately. - Added a `project_panel.auto_fold_dirs` setting which collapses the nesting in the project panel when there is a chain of folders containing a single folder. <img width="288" alt="Screenshot 2024-04-12 at 11 10 58 AM" src="https://github.com/zed-industries/zed/assets/2280405/efd61e75-026c-464d-ba4d-90db5f68bad3"> --------- Co-authored-by: Mikayla <mikayla@zed.dev>
Added support of auto collapsed directories, for example when directory has only one directory inside we should display it as dir1/dir2 (#6935 ). Please feel free to propose better solutions, as I am new in Rust
Demo:
https://streamable.com/seo3n9
Release Notes: