project_panel: Add Alt/Opt+Click to expand/collapse a directory and all its contents (#22896)

Closes #15966 

This PR adds `Alt/Opt+Click` to expand or collapse a directory and all
its contents.

Context:

The current `expand_entry` scans immediate child subdirectories if they
aren’t loaded, while `expand_all_for_entry` scans the entire subtree.
The latter takes longer, so we wait for it to complete to ensure
accurate results.

For full directory scan, instead of using
`refresh_entries_for_paths(vec![path])`, which requires specifying all
explicit paths to refresh, we use `add_path_prefix_to_scan`, which
eliminates the need to list every path. Both methods internally call
`reload_entries_for_paths`, which invokes `should_scan_directory`. This
determines whether to scan deeper based on a path prefix match between
the given directory and its subdirectories, returning `true` for
`add_path_prefix_to_scan`.

The existing code handles scanning, removing path prefixes after scans
complete, and managing ignored directories.

How it works (Expand):
1. Alt clicking on non-ignored closed directory, expands it and all its
subdirectories, except ignored subdirectories. This helps while working
on mono repos, where you might not want to expand dirs like
`node_modules`, `dist`, etc or git submodules, when you expand any root
dir.

In example, `draft` and `posts` dir are ignored dir.


[expand-1.webm](https://github.com/user-attachments/assets/07d3f724-0757-408f-b349-5beb4ee8440e)

2. Alt clicking on ignored closed directory, expands it and all its
subdirectories. This is when you explicitly want to do it, on dirs like
`node_modules`, `dist`, etc.

In example, `dist` dir is ignored dir.


[expand-2.webm](https://github.com/user-attachments/assets/99e55883-ab1a-4a9c-a0f0-48026991a922)

3. In case of auto folded subdirectories, expand all action will take
precedence over it. That is, it will unfold all the subdirectories
inside clicked dir. This is intentional, as user explicitly wants to
reveal as much content as possible. (This is my personal opinion on how
it should work).


[expand-3.webm](https://github.com/user-attachments/assets/f20b0311-e92a-4e34-b640-1469b0d6fa16)

How it works (Collapse):
1. Alt clicking any opened directory will collapse it and all its
children, whether ignored or not. This is when you want to start from a
fresh state.

2. When auto fold is enabled in settings, collapse action will also fold
all subdirectories that it can fold. This is to bring it back to its
fresh state as mentioned above.


[collapse-1-2.webm](https://github.com/user-attachments/assets/74db6cee-0afa-406b-a9a2-7421083a2c2a)


Future:
- Using keybinding to expand/collapse all for selected entry
- Handle expand/collapse all for folded entry

Todos:
- [x] Expand entries logic
- [x] Handle remote worktree for expand
- [x] Figure out scan complete status
- [x] Move expansion logic to status update event
- [x] Collapse entries logic
- [x] Handle fold/unfold subdirs interaction
- [x] Do not expand git ignored sub-dirs
- [x] Tests
- [x] Test Remote

Release Notes:

- Added Alt/Opt+Click functionality to expand or collapse a directory
and all its contents.
This commit is contained in:
tims 2025-01-28 14:07:56 +05:30 committed by GitHub
parent 793873bdc9
commit 5c650cdcb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 640 additions and 13 deletions

View file

@ -73,7 +73,8 @@ message Envelope {
ProjectEntryResponse project_entry_response = 50;
ExpandProjectEntry expand_project_entry = 51;
ExpandProjectEntryResponse expand_project_entry_response = 52;
ExpandAllForProjectEntry expand_all_for_project_entry = 291;
ExpandAllForProjectEntryResponse expand_all_for_project_entry_response = 292;
UpdateDiagnosticSummary update_diagnostic_summary = 53;
StartLanguageServer start_language_server = 54;
UpdateLanguageServer update_language_server = 55;
@ -630,6 +631,15 @@ message ExpandProjectEntryResponse {
uint64 worktree_scan_id = 1;
}
message ExpandAllForProjectEntry {
uint64 project_id = 1;
uint64 entry_id = 2;
}
message ExpandAllForProjectEntryResponse {
uint64 worktree_scan_id = 1;
}
message ProjectEntryResponse {
optional Entry entry = 1;
uint64 worktree_scan_id = 2;

View file

@ -174,6 +174,8 @@ messages!(
(Error, Foreground),
(ExpandProjectEntry, Foreground),
(ExpandProjectEntryResponse, Foreground),
(ExpandAllForProjectEntry, Foreground),
(ExpandAllForProjectEntryResponse, Foreground),
(Follow, Foreground),
(FollowResponse, Foreground),
(FormatBuffers, Foreground),
@ -394,6 +396,7 @@ request_messages!(
(DeleteChannel, Ack),
(DeleteProjectEntry, ProjectEntryResponse),
(ExpandProjectEntry, ExpandProjectEntryResponse),
(ExpandAllForProjectEntry, ExpandAllForProjectEntryResponse),
(Follow, FollowResponse),
(FormatBuffers, FormatBuffersResponse),
(FuzzySearchUsers, UsersResponse),
@ -518,6 +521,7 @@ entity_messages!(
CreateProjectEntry,
DeleteProjectEntry,
ExpandProjectEntry,
ExpandAllForProjectEntry,
FindSearchCandidates,
FormatBuffers,
GetCodeActions,