project_panel: Fix crash when adding a new file or directory to the first folded directory (#23217)

tims created

Closes #23216

This crash happens in the `update_visible_entries` function, where we
calculate `ancestors` and `current_ancestor_depth`. `ancestors` is map
storing information about folded ancestors and `current_ancestor_depth`
is basically selected ancestor index in reverse order of visibility.

For example, before adding a new file or directory in `a/b/c`, the
`ancestors` might look like:

```jsonc
{
    "entry_id_of_c": {
            "current_ancestor_depth": 2,  // "a" is selected
            "ancestors": ["entry_id_of_a", "entry_id_of_b", "entry_id_of_c"]
    }
}
```

When new file or directory is added to`a`, ancestors length is reduced,
as `a` now is not part of folded dir due to having multiple children.

But depth still remains the same as while calculating it, we use depth
from `old_ancestors` to preserve selection across renders. This causes
panic.

```jsonc
{
    "entry_id_of_c": {
            "current_ancestor_depth": 2,  // wrong: use of old depth here causes panic
            "ancestors": ["entry_id_of_b", "entry_id_of_c"]  // correct: notice "a" is missing, as "a" now has multiple children
    }
}
```

This PR fixes it by capping depth so it don't exceed `ancestors` array.
This preserves existing depth as well as handles our edge case.

Release Notes:

- Fixed crash when adding a new file or directory to the first folded
directory

Change summary

crates/project_panel/src/project_panel.rs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

Detailed changes

crates/project_panel/src/project_panel.rs 🔗

@@ -2368,7 +2368,8 @@ impl ProjectPanel {
                     let depth = old_ancestors
                         .get(&entry.id)
                         .map(|ancestor| ancestor.current_ancestor_depth)
-                        .unwrap_or_default();
+                        .unwrap_or_default()
+                        .min(auto_folded_ancestors.len());
                     if let Some(edit_state) = &mut self.edit_state {
                         if edit_state.entry_id == entry.id {
                             edit_state.depth = depth;