use std::path::Path;
use super::state::App;
use crate::infra::fs::FsClient;
pub(super) const TASKS_ROADMAP_PATH: &str = "docs/plan/roadmap.md";
#[derive(Clone, Debug, Eq, PartialEq)]
pub(super) enum ActiveProjectRoadmap {
Loaded(String),
LoadError(String),
}
impl App {
pub fn active_project_has_tasks_tab(&self) -> bool {
self.active_project_has_tasks_tab
}
pub fn task_roadmap_scroll_offset(&self) -> u16 {
self.task_roadmap_scroll_offset
}
pub fn scroll_task_roadmap_down(&mut self) {
self.task_roadmap_scroll_offset = self.task_roadmap_scroll_offset.saturating_add(1);
}
pub fn scroll_task_roadmap_up(&mut self) {
self.task_roadmap_scroll_offset = self.task_roadmap_scroll_offset.saturating_sub(1);
}
pub fn reset_task_roadmap_scroll(&mut self) {
self.task_roadmap_scroll_offset = 0;
}
pub(super) async fn refresh_active_project_roadmap(&mut self) {
self.active_project_roadmap = Self::load_project_roadmap(
self.services.fs_client().as_ref(),
self.projects.working_dir(),
)
.await;
self.active_project_has_tasks_tab = self.active_project_roadmap.is_some();
self.task_roadmap_scroll_offset = 0;
}
pub(super) async fn refresh_active_project_roadmap_and_tabs(&mut self) {
self.refresh_active_project_roadmap().await;
self.tabs.normalize(self.active_project_has_tasks_tab());
}
pub(super) async fn load_project_roadmap(
fs_client: &dyn FsClient,
working_dir: &Path,
) -> Option<ActiveProjectRoadmap> {
let roadmap_path = working_dir.join(TASKS_ROADMAP_PATH);
if !fs_client.is_file(roadmap_path.clone()) {
return None;
}
match fs_client.read_file(roadmap_path).await {
Ok(contents) => Some(ActiveProjectRoadmap::Loaded(
String::from_utf8_lossy(&contents).into_owned(),
)),
Err(error) => Some(ActiveProjectRoadmap::LoadError(format!(
"Failed to load `{TASKS_ROADMAP_PATH}`: {error}"
))),
}
}
}