diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index afa3cac..e1ff60d 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -12,7 +12,7 @@ keywords = { workspace = true } categories = { workspace = true } [features] -default = ["forgejo", "github"] +default = ["forgejo", "github", "tui"] forgejo = ["git-next-forge-forgejo"] github = ["git-next-forge-github"] tui = ["ratatui"] diff --git a/crates/cli/src/server/actor/handlers/receive_valid_app_config.rs b/crates/cli/src/server/actor/handlers/receive_valid_app_config.rs index 6380c67..5eb509d 100644 --- a/crates/cli/src/server/actor/handlers/receive_valid_app_config.rs +++ b/crates/cli/src/server/actor/handlers/receive_valid_app_config.rs @@ -69,9 +69,9 @@ impl Handler for ServerActor { WebhookActor::new(socket_address, webhook_router.recipient()).start(); self.webhook_actor_addr.replace(webhook_actor_addr); let shout = app_config.shout().clone(); - self.app_config.replace(app_config); + self.app_config.replace(app_config.clone()); self.alerts.do_send(UpdateShout::new(shout)); - self.send_server_updates(); + self.send_server_updates(app_config.into()); } } diff --git a/crates/cli/src/server/actor/messages.rs b/crates/cli/src/server/actor/messages.rs index d361890..f519aea 100644 --- a/crates/cli/src/server/actor/messages.rs +++ b/crates/cli/src/server/actor/messages.rs @@ -40,6 +40,8 @@ message!(Shutdown, "Notification to shutdown the server actor"); #[derive(Clone, Debug, PartialEq, Eq, Message)] #[rtype(result = "()")] pub enum ServerUpdate { + /// List of all configured forges and aliases + ForgeRepoList { list: Vec<(ForgeAlias, RepoAlias)> }, /// Status of a repo UpdateRepoSummary { forge_alias: ForgeAlias, @@ -56,6 +58,22 @@ pub enum ServerUpdate { Ping, } +impl From for ServerUpdate { + fn from(app_config: AppConfig) -> Self { + Self::ForgeRepoList { + list: app_config + .forges() + .flat_map(|(forge_alias, forge_config)| { + forge_config + .repos() + .map(|(repo_alias, _server_repo_config)| (forge_alias.clone(), repo_alias)) + .collect::>() + }) + .collect::>(), + } + } +} + message!( SubscribeToUpdates, Recipient, diff --git a/crates/cli/src/server/actor/mod.rs b/crates/cli/src/server/actor/mod.rs index d87ebe8..5f91ccf 100644 --- a/crates/cli/src/server/actor/mod.rs +++ b/crates/cli/src/server/actor/mod.rs @@ -243,9 +243,9 @@ impl ServerActor { } } - fn send_server_updates(&self) { - self.subscribers.iter().for_each(|subscriber| { - subscriber.do_send(ServerUpdate::Ping); + fn send_server_updates(&self, server_update: ServerUpdate) { + self.subscribers.iter().for_each(move |subscriber| { + subscriber.do_send(server_update.clone()); }); } } diff --git a/crates/cli/src/tui/actor/handlers/server_update.rs b/crates/cli/src/tui/actor/handlers/server_update.rs index d5c6bad..fdcf1c6 100644 --- a/crates/cli/src/tui/actor/handlers/server_update.rs +++ b/crates/cli/src/tui/actor/handlers/server_update.rs @@ -2,7 +2,13 @@ use std::time::Instant; use actix::Handler; -use crate::{server::actor::messages::ServerUpdate, tui::Tui}; +use crate::{ + server::actor::messages::ServerUpdate, + tui::{ + actor::model::{ForgeRepoKey, RepoState, State}, + Tui, + }, +}; // impl Handler for Tui { @@ -10,16 +16,33 @@ impl Handler for Tui { fn handle(&mut self, msg: ServerUpdate, _ctx: &mut Self::Context) -> Self::Result { match msg { + ServerUpdate::ForgeRepoList { list } => { + self.state = State::new( + list.into_iter() + .map(|(forge_alias, repo_alias)| ForgeRepoKey::new(forge_alias, repo_alias)) + .map(|key| (key, RepoState::Loading)) + .collect(), + ); + } ServerUpdate::UpdateRepoSummary { forge_alias, repo_alias, branches, log, - } => todo!(), + } => { + self.state.repos().insert( + ForgeRepoKey::new(forge_alias, repo_alias), + RepoState::Loaded { branches, log }, + ); + } ServerUpdate::RemoveRepo { forge_alias, repo_alias, - } => todo!(), + } => { + self.state + .repos() + .remove(&ForgeRepoKey::new(forge_alias, repo_alias)); + } ServerUpdate::Ping => { self.last_ping = Instant::now(); } diff --git a/crates/cli/src/tui/actor/mod.rs b/crates/cli/src/tui/actor/mod.rs index b00b4a3..0133ee5 100644 --- a/crates/cli/src/tui/actor/mod.rs +++ b/crates/cli/src/tui/actor/mod.rs @@ -1,6 +1,7 @@ // mod handlers; pub mod messages; +mod model; use std::{ io::{stderr, Stderr}, @@ -10,6 +11,7 @@ use std::{ use actix::{Actor, Context}; +use model::State; use ratatui::{ crossterm::{ execute, @@ -24,6 +26,7 @@ pub struct Tui { terminal: Option>>, signal_shutdown: Sender<()>, last_ping: Instant, + state: State, } impl Actor for Tui { type Context = Context; @@ -59,6 +62,7 @@ impl Tui { terminal: None, signal_shutdown, last_ping: Instant::now(), + state: State::default(), } } } diff --git a/crates/cli/src/tui/actor/model.rs b/crates/cli/src/tui/actor/model.rs new file mode 100644 index 0000000..1823c96 --- /dev/null +++ b/crates/cli/src/tui/actor/model.rs @@ -0,0 +1,30 @@ +// +use git_next_core::{git::graph::Log, ForgeAlias, RepoAlias, RepoBranches}; + +use std::collections::BTreeMap; + +use derive_more::derive::Constructor; + +#[derive(Clone, Debug, PartialEq, Eq, Default, Constructor)] +pub struct State { + repos: ReposState, +} +impl State { + pub fn repos(&mut self) -> &mut ReposState { + &mut self.repos + } +} + +pub type ReposState = BTreeMap; + +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Constructor)] +pub struct ForgeRepoKey { + forge_alias: ForgeAlias, + repo_alias: RepoAlias, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum RepoState { + Loading, + Loaded { branches: RepoBranches, log: Log }, +}