use super::AppModel;
use crate::binding::workspace_path;
use crate::names::{self, NameError};
use crate::projects::balls::Ball;
use crate::projects::join::JoinRow;
use crate::start::{self, BallSpec, Payload, StartInputs};
use std::path::{Path, PathBuf};
impl AppModel {
fn ball_of(&self, project: &Path, id: &str) -> Option<&Ball> {
self.snap
.balls_by_project
.get(project)?
.iter()
.find(|b| b.id == id)
}
pub fn start_workspace(&self) -> PathBuf {
match self.focused_workspace() {
Some(ws) => ws,
None => workspace_path(&self.roots.yog_data, names::DEFAULT_NAME),
}
}
fn start_inputs_at(&self, workspace: PathBuf, payload: Payload) -> StartInputs {
let repo = payload
.project()
.and_then(|name| self.snap.project_path(&name).ok());
StartInputs {
conversation_names: crate::boundary::answer::names_in(&self.snap, &workspace),
workspace,
repo,
payload,
home: self.roots.home.clone(),
yog_data_root: self.roots.yog_data.clone(),
balls_state_root: self.balls_state_root(),
}
}
fn start_inputs(&self, payload: Payload) -> StartInputs {
self.start_inputs_at(self.start_workspace(), payload)
}
pub fn start_bare_inputs(&self) -> StartInputs {
self.start_inputs(Payload::Bare)
}
pub fn validate_workspace_name(&self, typed: &str) -> Result<String, NameError> {
names::validate(
typed,
&crate::binding::roots(&self.roots.yog_data, &self.roots.lernie_data),
)
}
pub fn new_workspace_inputs(&self, name: &str) -> StartInputs {
self.start_inputs_at(workspace_path(&self.roots.yog_data, name), Payload::Bare)
}
pub fn start_path_inputs(&self, dir: &Path) -> StartInputs {
self.start_inputs(Payload::Path {
dir: dir.to_path_buf(),
})
}
pub fn startable(&self) -> Vec<StartInputs> {
self.snap
.join_rows
.iter()
.filter(|r| start::is_start_eligible(r.state))
.filter_map(|row| Some(self.start_inputs(self.ball_payload(row)?)))
.collect()
}
pub fn resumable(&self) -> Vec<StartInputs> {
self.snap
.join_rows
.iter()
.filter(|r| start::is_resume_eligible(r.state))
.filter_map(|row| {
let workspace = self.snap.ws_path(row.workspace.as_deref()?).ok()?;
Some(self.start_inputs_at(workspace, self.ball_payload(row)?))
})
.collect()
}
fn ball_payload(&self, row: &JoinRow) -> Option<Payload> {
Some(Payload::Ball {
project: row.project.clone(),
ball: self.ball_spec(row)?,
})
}
pub(crate) fn ball_spec(&self, row: &JoinRow) -> Option<BallSpec> {
let project = self.snap.project_path(&row.project).ok()?;
let ball = self.ball_of(&project, &row.ball_id)?;
Some(BallSpec::Existing {
id: row.ball_id.clone(),
title: ball.title.clone(),
body: ball.body.clone(),
join: row.state,
})
}
pub fn new_ball_inputs(&self, project: &Path, title: &str, body: &str) -> StartInputs {
self.start_inputs(Payload::Ball {
project: self.snap.project_name(project),
ball: BallSpec::New {
title: title.to_owned(),
body: body.to_owned(),
},
})
}
pub fn project_paths(&self) -> Vec<PathBuf> {
let mut ps: Vec<PathBuf> = self.snap.balls_by_project.keys().cloned().collect();
ps.sort();
ps
}
}