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