use std::path::Path;
use super::App;
use super::types::VisibleRow;
use crate::project::AbsolutePath;
use crate::project::ProjectFields;
use crate::project::Visibility::Dismissed;
use crate::tui::types::PaneId;
#[derive(Clone, Debug)]
pub enum DismissTarget {
Toast(u64),
DeletedProject(AbsolutePath),
}
impl App {
pub(in super::super) fn dismiss_target_for_row_inner(
&self,
row: VisibleRow,
) -> Option<DismissTarget> {
let dismiss_path = match row {
VisibleRow::Root { node_index } | VisibleRow::GroupHeader { node_index, .. } => self
.projects
.get(node_index)
.map(|item| item.path().clone()),
VisibleRow::Member { node_index, .. }
| VisibleRow::Vendored { node_index, .. }
| VisibleRow::Submodule { node_index, .. } => self
.projects
.get(node_index)
.map(|item| item.path().clone()),
VisibleRow::WorktreeEntry {
node_index,
worktree_index,
}
| VisibleRow::WorktreeGroupHeader {
node_index,
worktree_index,
..
}
| VisibleRow::WorktreeMember {
node_index,
worktree_index,
..
}
| VisibleRow::WorktreeVendored {
node_index,
worktree_index,
..
} => match self.projects.get(node_index)? {
crate::project::RootItem::Worktrees(
crate::project::WorktreeGroup::Workspaces {
primary, linked, ..
},
) => {
if worktree_index == 0 {
Some(primary.path().clone())
} else {
linked.get(worktree_index - 1).map(|ws| ws.path().clone())
}
},
crate::project::RootItem::Worktrees(crate::project::WorktreeGroup::Packages {
primary,
linked,
..
}) => {
if worktree_index == 0 {
Some(primary.path().clone())
} else {
linked.get(worktree_index - 1).map(|pkg| pkg.path().clone())
}
},
_ => None,
},
}?;
if self.is_deleted(&dismiss_path) {
Some(DismissTarget::DeletedProject(dismiss_path))
} else {
None
}
}
pub(in super::super) fn focused_dismiss_target(&self) -> Option<DismissTarget> {
match self.focused_pane {
PaneId::Toasts => self.focused_toast_id().map(DismissTarget::Toast),
PaneId::ProjectList => self
.selected_row()
.and_then(|row| self.dismiss_target_for_row_inner(row)),
_ => None,
}
}
pub(in super::super) fn dismiss(&mut self, target: DismissTarget) {
match target {
DismissTarget::Toast(id) => self.dismiss_toast(id),
DismissTarget::DeletedProject(path) => {
let parent_node_index = self.worktree_parent_node_index(&path);
if let Some(project) = self.projects.at_path_mut(&path) {
project.visibility = Dismissed;
}
self.dirty.rows.mark_dirty();
self.dirty.disk_cache.mark_dirty();
self.dirty.fit_widths.mark_dirty();
self.ensure_visible_rows_cached();
if let Some(ni) = parent_node_index {
self.select_root_row(ni);
} else {
let count = self.row_count();
let selected = self.pane_manager.pane(PaneId::ProjectList).pos();
if selected >= count {
self.pane_manager
.pane_mut(PaneId::ProjectList)
.set_pos(count.saturating_sub(1));
}
}
},
}
}
fn worktree_parent_node_index(&self, path: &Path) -> Option<usize> {
self.projects
.iter()
.enumerate()
.find_map(|(ni, item)| match item {
crate::project::RootItem::Worktrees(
crate::project::WorktreeGroup::Workspaces {
primary, linked, ..
},
) => {
let has_match =
primary.path() == path || linked.iter().any(|l| l.path() == path);
has_match.then_some(ni)
},
crate::project::RootItem::Worktrees(crate::project::WorktreeGroup::Packages {
primary,
linked,
..
}) => {
let has_match =
primary.path() == path || linked.iter().any(|l| l.path() == path);
has_match.then_some(ni)
},
_ => None,
})
}
fn select_root_row(&mut self, node_index: usize) {
let rows = self.visible_rows();
if let Some(pos) = rows
.iter()
.position(|row| matches!(row, VisibleRow::Root { node_index: ni } if *ni == node_index))
{
self.pane_manager.pane_mut(PaneId::ProjectList).set_pos(pos);
}
}
}