mod helpers;
mod mapper;
#[cfg(test)]
mod mapper_tests;
use crate::components::ComponentManager;
use crate::commands::{
Command, CommandResult,
};
use crate::errors::ApplicationError;
use super::{event_loop, AppState, Action};
use crate::services::GitService;
use crate::async_result::AsyncResult;
use crossterm::event::EventStream;
use notify::RecommendedWatcher;
use ratatui::backend::CrosstermBackend;
use ratatui::Terminal;
use std::sync::Arc;
use tokio::sync::{mpsc, watch};
pub struct Application {
pub(crate) state: AppState,
pub(crate) component_manager: ComponentManager,
pub(crate) git_service: Arc<GitService>,
pub(crate) event_stream: EventStream,
pub(crate) cancel_rx: watch::Receiver<bool>,
pub(crate) async_tx: mpsc::UnboundedSender<AsyncResult>,
pub(crate) async_rx: mpsc::UnboundedReceiver<AsyncResult>,
pub(crate) _watcher: Option<RecommendedWatcher>, }
impl Application {
pub fn new(
state: AppState,
component_manager: ComponentManager,
git_service: Arc<GitService>,
cancel_rx: watch::Receiver<bool>,
async_tx: mpsc::UnboundedSender<AsyncResult>,
async_rx: mpsc::UnboundedReceiver<AsyncResult>,
watcher: Option<RecommendedWatcher>,
) -> Result<Self, ApplicationError> {
let event_stream = EventStream::new();
Ok(Self {
state,
component_manager,
git_service,
event_stream,
cancel_rx,
async_tx,
async_rx,
_watcher: watcher,
})
}
pub async fn run(&mut self, terminal: &mut Terminal<CrosstermBackend<std::io::Stdout>>) -> Result<(), ApplicationError> {
event_loop::run(self, terminal).await
}
pub(crate) fn action_to_command(&self, action: &Action) -> Option<Box<dyn Command>> {
mapper::action_to_command(&self.state, action)
}
pub(crate) fn apply_command_result(&mut self, result: CommandResult) -> Result<(), ApplicationError> {
match result {
CommandResult::StateUpdate(new_state) => {
self.state = new_state;
}
CommandResult::AsyncTask(_) => {
}
CommandResult::NoOp => {}
}
Ok(())
}
pub(crate) fn handle_async_result(&mut self, result: AsyncResult) -> Result<(), ApplicationError> {
match result {
AsyncResult::TaskComplete { message, should_refresh, .. } => {
self.state.feedback_message = Some(message);
if should_refresh {
}
}
AsyncResult::FileChanged => {
}
AsyncResult::CommitDetailLoaded(detail) => {
self.state.commit_detail = Some(detail);
}
AsyncResult::CommitDetailError(err) => {
self.state.feedback_message = Some(format!("Error: {}", err));
}
}
Ok(())
}
}