use super::AppModel;
use crate::projects::join;
use std::path::Path;
impl AppModel {
pub fn ws_balls(&self, ws: &Path) -> Vec<crate::nav::BoundBall> {
self.snap
.join_rows
.iter()
.filter(|r| r.workspace.as_deref() == Some(ws) && !r.ball_id.is_empty())
.map(|r| crate::nav::BoundBall {
id: r.ball_id.clone(),
badge: join::badge(r.state, r.claimant.as_deref()),
project: r.project.clone(),
owner: join::owner_name(r),
state: r.state,
})
.collect()
}
pub fn roster_ball_rows(&self, ws: &Path) -> Vec<crate::nav::BoundBall> {
self.ws_balls(ws)
.into_iter()
.filter(|b| !crate::start::is_resume_eligible(b.state))
.collect()
}
pub fn bound_ball(&self, ws: &Path, id: &str) -> Option<crate::nav::BoundBall> {
self.ws_balls(ws).into_iter().find(|b| b.id == id)
}
pub fn conversation_groups(
&self,
now_unix: i64,
expanded: &std::collections::HashSet<String>,
) -> Vec<crate::nav::convs::group::ConvGroup> {
crate::nav::convs::group::group_by_ball(self.visible_conversations(now_unix, expanded))
}
pub fn conversation_ball(&self, root_id: &str) -> Option<crate::nav::convs::ConvBall> {
let ws = self.focus.ws.as_deref()?;
let tree = self.snap.trees.get(ws)?;
let id = tree
.agents
.iter()
.find(|a| a.agent_id == root_id)?
.goal_ball
.as_deref()?;
Some(self.resolve_conv_ball(id))
}
pub(crate) fn resolve_conv_ball(&self, id: &str) -> crate::nav::convs::ConvBall {
crate::boundary::answer::conv_ball(&self.snap, id)
}
}