forked from kemitix/git-next
feat(tui): hightlight status message in colour
This commit is contained in:
parent
4555b3ae09
commit
f9e305afa4
7 changed files with 135 additions and 30 deletions
64
Cargo.lock
generated
64
Cargo.lock
generated
|
@ -320,6 +320,28 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bon"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3b71187ef9d11cfa48c023d574a00ec5e4850dcb145ef51619d99cc119486cb"
|
||||
dependencies = [
|
||||
"bon-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bon-macros"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f8407447d440da7b3de982f286d15e30e7646bef4ebca994eebebaa1690fd9c"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.76",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.10.0"
|
||||
|
@ -592,6 +614,41 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.76",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.76",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "6.0.1"
|
||||
|
@ -1041,6 +1098,7 @@ dependencies = [
|
|||
"actix-rt",
|
||||
"anyhow",
|
||||
"assert2",
|
||||
"bon",
|
||||
"bytes",
|
||||
"clap",
|
||||
"color-eyre",
|
||||
|
@ -2350,6 +2408,12 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
|
|
|
@ -79,6 +79,7 @@ time = "0.3"
|
|||
standardwebhooks = "1.0"
|
||||
|
||||
# boilerplate
|
||||
bon = "2.0"
|
||||
derive_more = { version = "1.0.0-beta", features = [
|
||||
"as_ref",
|
||||
"constructor",
|
||||
|
|
|
@ -52,6 +52,7 @@ actix = { workspace = true }
|
|||
actix-rt = { workspace = true }
|
||||
|
||||
# boilerplate
|
||||
bon = { workspace = true }
|
||||
derive_more = { workspace = true }
|
||||
derive-with = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
//
|
||||
use actix::Handler;
|
||||
use ratatui::style::Color;
|
||||
|
||||
use crate::{
|
||||
server::actor::messages::{RepoUpdate, ServerUpdate},
|
||||
tui::{actor::ServerState, Tui},
|
||||
};
|
||||
|
||||
static OKAY: Color = Color::Green;
|
||||
static PREP: Color = Color::Gray;
|
||||
static ACTING: Color = Color::Yellow;
|
||||
static WARN: Color = Color::LightYellow;
|
||||
|
||||
impl Handler<ServerUpdate> for Tui {
|
||||
type Result = ();
|
||||
|
||||
|
@ -35,50 +41,53 @@ impl Handler<ServerUpdate> for Tui {
|
|||
RepoUpdate::Log { log } => {
|
||||
repo_state.update_log(log);
|
||||
}
|
||||
RepoUpdate::ValidateRepo => repo_state.update_message("polling..."),
|
||||
RepoUpdate::ValidateRepo => repo_state.update_message("polling...", ACTING),
|
||||
RepoUpdate::Okay { main, next, dev } => {
|
||||
repo_state.clear_alert();
|
||||
repo_state.update_message("okay");
|
||||
repo_state.update_message("okay", OKAY);
|
||||
*repo_state = repo_state.clone().ready(main, next, dev);
|
||||
}
|
||||
RepoUpdate::Alert { alert } => {
|
||||
repo_state.alert(alert);
|
||||
}
|
||||
RepoUpdate::CheckingCI => {
|
||||
repo_state.update_message("Checking CI status");
|
||||
repo_state.update_message("Checking CI status", ACTING);
|
||||
}
|
||||
RepoUpdate::AdvancingNext { commit, force: _ } => {
|
||||
repo_state.update_message(format!("advancing next to {commit}"));
|
||||
repo_state
|
||||
.update_message(format!("advancing next to {commit}"), ACTING);
|
||||
}
|
||||
RepoUpdate::AdvancingMain { commit } => {
|
||||
repo_state.update_message(format!("advancing main to {commit}"));
|
||||
repo_state
|
||||
.update_message(format!("advancing main to {commit}"), ACTING);
|
||||
}
|
||||
RepoUpdate::Opening => {
|
||||
repo_state.update_message("opening...");
|
||||
repo_state.update_message("opening...", PREP);
|
||||
}
|
||||
RepoUpdate::Opened => {
|
||||
repo_state.update_message("opened");
|
||||
repo_state.update_message("opened", PREP);
|
||||
}
|
||||
RepoUpdate::LoadingConfigFromRepo => {
|
||||
repo_state.update_message("loading config from repo...");
|
||||
repo_state.update_message("loading config from repo...", PREP);
|
||||
}
|
||||
RepoUpdate::ReceiveCIStatus { status } => {
|
||||
repo_state.update_message(format!("ci status: {status:?}"));
|
||||
repo_state.update_message(format!("ci status: {status:?}"), WARN);
|
||||
}
|
||||
RepoUpdate::ReceiveRepoConfig { repo_config: _ } => {
|
||||
repo_state.update_message("loaded config from repo");
|
||||
repo_state.update_message("loaded config from repo", PREP);
|
||||
}
|
||||
RepoUpdate::RegisteringWebhook => {
|
||||
repo_state.update_message("registering webhook...");
|
||||
repo_state.update_message("registering webhook...", PREP);
|
||||
}
|
||||
RepoUpdate::UnregisteringWebhook => {
|
||||
repo_state.update_message("unregistering webhook...");
|
||||
repo_state.update_message("unregistering webhook...", PREP);
|
||||
}
|
||||
RepoUpdate::WebhookReceived { branch, push: _ } => {
|
||||
repo_state.update_message(format!("webhook update: {branch:?}"));
|
||||
repo_state
|
||||
.update_message(format!("webhook update: {branch:?}"), ACTING);
|
||||
}
|
||||
RepoUpdate::RegisteredWebhook => {
|
||||
repo_state.update_message("registered webhook");
|
||||
repo_state.update_message("registered webhook", PREP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
use ratatui::{
|
||||
layout::Alignment,
|
||||
prelude::{Buffer, Rect},
|
||||
style::Stylize as _,
|
||||
style::{Color, Style, Stylize as _},
|
||||
symbols::border,
|
||||
text::Line,
|
||||
text::{Line, Span},
|
||||
widgets::{block::Title, Block, Paragraph, StatefulWidget, Widget},
|
||||
};
|
||||
|
||||
|
@ -127,7 +127,10 @@ impl From<ValidAppConfig> for ServerState {
|
|||
repo_alias.clone(),
|
||||
RepoState::Configured {
|
||||
repo_alias,
|
||||
message: "configured".into(),
|
||||
message: RepoMessage::builder()
|
||||
.text("configured".into())
|
||||
.style(Style::default().fg(Color::LightGreen))
|
||||
.build(),
|
||||
alert: None,
|
||||
branches: rc.branches().clone(),
|
||||
log: git::graph::Log::default(),
|
||||
|
@ -137,7 +140,10 @@ impl From<ValidAppConfig> for ServerState {
|
|||
repo_alias.clone(),
|
||||
RepoState::Identified {
|
||||
repo_alias,
|
||||
message: "identified".into(),
|
||||
message: RepoMessage::builder()
|
||||
.text("identified".into())
|
||||
.style(Style::default().fg(Color::Gray))
|
||||
.build(),
|
||||
alert: None,
|
||||
},
|
||||
),
|
||||
|
@ -182,23 +188,37 @@ pub struct ForgeState {
|
|||
pub repos: BTreeMap<RepoAlias, RepoState>,
|
||||
}
|
||||
|
||||
#[bon::builder]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RepoMessage {
|
||||
text: String,
|
||||
style: Style,
|
||||
}
|
||||
impl From<&RepoMessage> for Span<'_> {
|
||||
fn from(value: &RepoMessage) -> Self {
|
||||
Self::default()
|
||||
.content(value.text.clone())
|
||||
.style(value.style)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum RepoState {
|
||||
Identified {
|
||||
repo_alias: RepoAlias,
|
||||
message: String,
|
||||
message: RepoMessage,
|
||||
alert: Option<String>,
|
||||
},
|
||||
Configured {
|
||||
repo_alias: RepoAlias,
|
||||
message: String,
|
||||
message: RepoMessage,
|
||||
alert: Option<String>,
|
||||
branches: RepoBranches,
|
||||
log: Log,
|
||||
},
|
||||
Ready {
|
||||
repo_alias: RepoAlias,
|
||||
message: String,
|
||||
message: RepoMessage,
|
||||
alert: Option<String>,
|
||||
branches: RepoBranches,
|
||||
view_state: ViewState,
|
||||
|
@ -241,14 +261,16 @@ impl RepoState {
|
|||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub fn update_message(&mut self, msg: impl Into<String> + std::fmt::Debug) {
|
||||
let msg: String = msg.into();
|
||||
pub fn update_message(&mut self, msg: impl Into<String> + std::fmt::Debug, colour: Color) {
|
||||
match self {
|
||||
Self::Identified { message, .. }
|
||||
| Self::Configured { message, .. }
|
||||
| Self::Ready { message, .. } => {
|
||||
info!(?msg, "updating ui");
|
||||
*message = msg;
|
||||
*message = RepoMessage::builder()
|
||||
.text(msg.into())
|
||||
.style(Style::default().fg(colour))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +287,7 @@ impl RepoState {
|
|||
pub fn alert(&mut self, msg: impl Into<String> + std::fmt::Debug) {
|
||||
let msg: String = msg.into();
|
||||
tracing::info!(%msg, "new tui alert");
|
||||
self.update_message("ALERT");
|
||||
self.update_message("ALERT", Color::Red);
|
||||
match self {
|
||||
Self::Identified { alert, .. }
|
||||
| Self::Configured { alert, .. }
|
||||
|
|
|
@ -8,11 +8,13 @@ use ratatui::{
|
|||
widgets::block::Title,
|
||||
};
|
||||
|
||||
use crate::tui::actor::RepoMessage;
|
||||
|
||||
pub struct Identity<'a> {
|
||||
pub label: &'a str,
|
||||
pub repo_alias: &'a RepoAlias,
|
||||
pub alert: Option<&'a str>,
|
||||
pub message: &'a str,
|
||||
pub message: &'a RepoMessage,
|
||||
pub repo_branches: Option<&'a RepoBranches>,
|
||||
}
|
||||
impl<'a> Identity<'a> {
|
||||
|
@ -20,7 +22,7 @@ impl<'a> Identity<'a> {
|
|||
label: &'a str,
|
||||
repo_alias: &'a RepoAlias,
|
||||
alert: Option<&'a str>,
|
||||
message: &'a str,
|
||||
message: &'a RepoMessage,
|
||||
repo_branches: Option<&'a RepoBranches>,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -56,7 +58,10 @@ impl<'a> Identity<'a> {
|
|||
vec![
|
||||
Span::from(format!(" {repo_alias} ({label}) ")),
|
||||
alert,
|
||||
Span::from(format!("({main}/{next}/{dev}) [{message}] ")),
|
||||
Span::from(format!("({main}/{next}/{dev}) [")),
|
||||
message.into(),
|
||||
// Span::from(message.},
|
||||
Span::from("] "),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ use git_next_core::{RepoAlias, RepoBranches};
|
|||
|
||||
use crate::{
|
||||
git,
|
||||
tui::{actor::RepoState, components::CommitLog},
|
||||
tui::{
|
||||
actor::{RepoMessage, RepoState},
|
||||
components::CommitLog,
|
||||
},
|
||||
};
|
||||
|
||||
use identity::Identity;
|
||||
|
@ -97,7 +100,7 @@ impl<'a> Widget for RepoWidget<'a> {
|
|||
struct InnerRepoWidget<'a> {
|
||||
pub label: &'a str,
|
||||
pub repo_alias: &'a RepoAlias,
|
||||
pub message: &'a str,
|
||||
pub message: &'a RepoMessage,
|
||||
pub alert: Option<&'a str>,
|
||||
pub branches: Option<&'a RepoBranches>,
|
||||
pub log: Option<&'a git::graph::Log>,
|
||||
|
|
Loading…
Reference in a new issue