diff --git a/Cargo.lock b/Cargo.lock index de693647e0..f530984d3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,7 +156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3bf628a79452df9614d933012dc500f8cb6ddad8c897ff8122ea1c0b187ff7" dependencies = [ "nom", - "ratatui", + "ratatui 0.26.3", "simdutf8", "smallvec", "thiserror", @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arc-swap" @@ -225,9 +225,9 @@ checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arrayref" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -877,9 +877,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] @@ -978,9 +978,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.18" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "jobserver", "libc", @@ -1205,6 +1205,20 @@ dependencies = [ "cfg-if", "itoa", "ryu", + "static_assertions", +] + +[[package]] +name = "compact_str" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", "serde", "static_assertions", ] @@ -1454,6 +1468,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags 2.6.0", + "crossterm_winapi", + "mio 1.0.2", + "parking_lot", + "rustix", + "signal-hook", + "signal-hook-mio", + "winapi", +] + [[package]] name = "crossterm_winapi" version = "0.9.1" @@ -3401,7 +3431,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.0", "tower-service", - "webpki-roots 0.26.5", + "webpki-roots 0.26.6", ] [[package]] @@ -3438,9 +3468,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3617,6 +3647,16 @@ dependencies = [ "generic-array 0.14.7", ] +[[package]] +name = "instability" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" +dependencies = [ + "quote", + "syn 2.0.77", +] + [[package]] name = "instant" version = "0.1.13" @@ -4372,9 +4412,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] @@ -4461,6 +4501,7 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -4723,7 +4764,7 @@ dependencies = [ "clap", "color-eyre", "config", - "crossterm", + "crossterm 0.27.0", "derive_deref", "directories", "dirs-next", @@ -4737,7 +4778,7 @@ dependencies = [ "log", "pretty_assertions", "prometheus-parse", - "ratatui", + "ratatui 0.28.1", "reqwest 0.12.7", "serde", "serde_json", @@ -5226,9 +5267,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.12" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" +checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" dependencies = [ "memchr", "thiserror", @@ -5237,9 +5278,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.12" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664d22978e2815783adbdd2c588b455b1bd625299ce36b2a99881ac9627e6d8d" +checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" dependencies = [ "pest", "pest_generator", @@ -5247,9 +5288,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.12" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d5487022d5d33f4c30d91c22afa240ce2a644e87fe08caad974d4eab6badbe" +checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" dependencies = [ "pest", "pest_meta", @@ -5260,9 +5301,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.12" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0091754bbd0ea592c4deb3a122ce8ecbb0753b738aa82bc055fcc2eccc8d8174" +checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" dependencies = [ "once_cell", "pest", @@ -5506,9 +5547,9 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -6021,12 +6062,10 @@ checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef" dependencies = [ "bitflags 2.6.0", "cassowary", - "compact_str", - "crossterm", + "compact_str 0.7.1", "itertools 0.12.1", "lru", "paste", - "serde", "stability", "strum", "unicode-segmentation", @@ -6034,6 +6073,28 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "ratatui" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d" +dependencies = [ + "bitflags 2.6.0", + "cassowary", + "compact_str 0.8.0", + "crossterm 0.28.1", + "instability", + "itertools 0.13.0", + "lru", + "paste", + "serde", + "strum", + "strum_macros", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] + [[package]] name = "rayon" version = "1.10.0" @@ -6218,7 +6279,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.26.5", + "webpki-roots 0.26.6", "windows-registry", ] @@ -6897,6 +6958,7 @@ checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", "mio 0.8.11", + "mio 1.0.2", "signal-hook", ] @@ -7641,9 +7703,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" -version = "12.11.0" +version = "12.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1db5ac243c7d7f8439eb3b8f0357888b37cf3732957e91383b0ad61756374e" +checksum = "9fdf97c441f18a4f92425b896a4ec7a27e03631a0b1047ec4e34e9916a9a167e" dependencies = [ "debugid", "memmap2", @@ -7653,9 +7715,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.11.0" +version = "12.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea26e430c27d4a8a5dea4c4b81440606c7c1a415bd611451ef6af8c81416afc3" +checksum = "bc8ece6b129e97e53d1fbb3f61d33a6a9e5369b11d01228c068094d6d134eaea" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -8092,9 +8154,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" dependencies = [ "indexmap 2.5.0", "serde", @@ -8385,7 +8447,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3e785f863a3af4c800a2a669d0b64c879b538738e352607e2624d03f868dc01" dependencies = [ - "crossterm", + "crossterm 0.27.0", "unicode-width", ] @@ -8476,9 +8538,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-truncate" @@ -8493,15 +8555,15 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -8842,9 +8904,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.5" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -9271,9 +9333,9 @@ dependencies = [ [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yasna" diff --git a/node-launchpad/Cargo.toml b/node-launchpad/Cargo.toml index 8c92a39f62..bb4b90abaa 100644 --- a/node-launchpad/Cargo.toml +++ b/node-launchpad/Cargo.toml @@ -41,7 +41,7 @@ libc = "0.2.148" log = "0.4.20" pretty_assertions = "1.4.0" prometheus-parse = "0.2.5" -ratatui = { version = "0.26.0", features = ["serde", "macros", "unstable-widget-ref"] } +ratatui = { version = "0.28.1", features = ["serde", "macros", "unstable-widget-ref"] } reqwest = { version = "0.12.2", default-features = false, features = [ "rustls-tls-manual-roots", ] } diff --git a/node-launchpad/src/app.rs b/node-launchpad/src/app.rs index f456fdb6b9..e8531ab825 100644 --- a/node-launchpad/src/app.rs +++ b/node-launchpad/src/app.rs @@ -167,7 +167,9 @@ impl App { for component in self.components.iter_mut() { component.register_action_handler(action_tx.clone())?; component.register_config_handler(self.config.clone())?; - component.init(tui.size()?)?; + let size = tui.size()?; + let rect = Rect::new(0, 0, size.width, size.height); + component.init(rect)?; } loop { @@ -223,7 +225,7 @@ impl App { tui.resize(Rect::new(0, 0, w, h))?; tui.draw(|f| { for component in self.components.iter_mut() { - let r = component.draw(f, f.size()); + let r = component.draw(f, f.area()); if let Err(e) = r { action_tx .send(Action::Error(format!("Failed to draw: {:?}", e))) @@ -236,10 +238,10 @@ impl App { tui.draw(|f| { f.render_widget( Block::new().style(Style::new().bg(SPACE_CADET)), - f.size(), + f.area(), ); for component in self.components.iter_mut() { - let r = component.draw(f, f.size()); + let r = component.draw(f, f.area()); if let Err(e) = r { action_tx .send(Action::Error(format!("Failed to draw: {:?}", e))) diff --git a/node-launchpad/src/components/help.rs b/node-launchpad/src/components/help.rs index 7bb94db50d..9270616d27 100644 --- a/node-launchpad/src/components/help.rs +++ b/node-launchpad/src/components/help.rs @@ -3,8 +3,8 @@ use color_eyre::eyre::Result; use ratatui::{ layout::{Constraint, Direction, Layout, Rect}, style::{Style, Stylize}, - text::{Line, Span}, - widgets::{Block, Borders, Cell, Padding, Row, Table}, + text::Span, + widgets::{Block, Borders, Padding}, Frame, }; use tokio::sync::mpsc::UnboundedSender; @@ -14,10 +14,9 @@ use crate::{ action::Action, components::header::Header, mode::{InputMode, Scene}, - style::{COOL_GREY, GHOST_WHITE}, + style::{COOL_GREY, GHOST_WHITE, VIVID_SKY_BLUE}, widgets::hyperlink::Hyperlink, }; -use ansi_to_tui::IntoText; #[derive(Clone)] pub struct Help { @@ -56,86 +55,114 @@ impl Component for Help { // ---- Get Help & Support ---- // Links + // Create a new layout as a table, so we can render hyperlinks + let columns_layout = Layout::default() + .direction(Direction::Horizontal) + .constraints(vec![Constraint::Percentage(50), Constraint::Percentage(50)]) + .split(layout[1]); + + let padded_area_left = Rect { + x: columns_layout[0].x + 2, + y: columns_layout[0].y + 2, + width: columns_layout[0].width - 2, + height: columns_layout[0].height - 2, + }; + + let left_column = Layout::default() + .direction(Direction::Vertical) + .constraints(vec![ + Constraint::Max(1), + Constraint::Max(2), + Constraint::Max(1), + Constraint::Max(2), + ]) + .split(padded_area_left); + + let padded_area_right = Rect { + x: columns_layout[1].x + 2, + y: columns_layout[1].y + 2, + width: columns_layout[1].width - 2, + height: columns_layout[1].height - 2, + }; + let right_column = Layout::default() + .direction(Direction::Vertical) + .constraints(vec![ + Constraint::Max(1), + Constraint::Max(2), + Constraint::Max(1), + Constraint::Max(2), + ]) + .split(padded_area_right); + let quickstart_guide_link = Hyperlink::new( - "docs.autonomi.com/getstarted", + Span::styled( + "docs.autonomi.com/getstarted", + Style::default().fg(VIVID_SKY_BLUE).underlined(), + ), "https://docs.autonomi.com/getstarted", ); - let beta_rewards_link = Hyperlink::new("autonomi.com/beta", "https://autonomi.com/beta"); - let get_direct_support_link = - Hyperlink::new("autonomi.com/support", "https://autonomi.com/support"); - let download_latest_link = - Hyperlink::new("autonomi.com/downloads", "https://autonomi.com/downloads"); - - // Content - let rows_help_and_support = vec![ - Row::new(vec![ - Cell::from(Line::from(vec![Span::styled( - "See the quick start guides:", - Style::default().fg(GHOST_WHITE), - )])), - Cell::from(Line::from(vec![Span::styled( - "To join the Beta Rewards Program:", - Style::default().fg(GHOST_WHITE), - )])), - ]), - Row::new(vec![ - Cell::from( - quickstart_guide_link - .to_string() - .into_text() - .unwrap() - .clone(), - ), - Cell::from(beta_rewards_link.to_string().into_text().unwrap().clone()), - ]), - Row::new(vec![ - // Empty row for padding - Cell::from(Span::raw(" ")), - Cell::from(Span::raw(" ")), - ]), - Row::new(vec![ - Cell::from(Line::from(vec![Span::styled( - "Get Direct Support:", - Style::default().fg(GHOST_WHITE), - )])), - Cell::from(Line::from(vec![Span::styled( - "Download the latest launchpad:", - Style::default().fg(GHOST_WHITE), - )])), - ]), - Row::new(vec![ - Cell::from( - get_direct_support_link - .to_string() - .into_text() - .unwrap() - .clone(), - ), - Cell::from( - download_latest_link - .to_string() - .into_text() - .unwrap() - .clone(), - ), - ]), - ]; - - let table_help_and_support = Table::new( - rows_help_and_support, - vec![Constraint::Percentage(50), Constraint::Percentage(50)], - ) - .block( - Block::new() - .borders(Borders::ALL) - .border_style(Style::default().fg(COOL_GREY)) - .padding(Padding::uniform(1)) - .title(" Get Help & Support ") - .bold() - .title_style(Style::default().bold().fg(GHOST_WHITE)), + let beta_rewards_link = Hyperlink::new( + Span::styled( + "autonomi.com/beta", + Style::default().fg(VIVID_SKY_BLUE).underlined(), + ), + "https://autonomi.com/beta", + ); + let get_direct_support_link = Hyperlink::new( + Span::styled( + "autonomi.com/support", + Style::default().fg(VIVID_SKY_BLUE).underlined(), + ), + "https://autonomi.com/support", + ); + let download_latest_link = Hyperlink::new( + Span::styled( + "autonomi.com/downloads", + Style::default().fg(VIVID_SKY_BLUE).underlined(), + ), + "https://autonomi.com/downloads", + ); + + let block = Block::new() + .borders(Borders::ALL) + .border_style(Style::default().fg(COOL_GREY)) + .padding(Padding::uniform(1)) + .title(" Get Help & Support ") + .bold() + .title_style(Style::default().bold().fg(GHOST_WHITE)); + + // Render hyperlinks in the new area + f.render_widget( + Span::styled( + "See the quick start guides:", + Style::default().fg(GHOST_WHITE), + ), + left_column[0], + ); + f.render_widget_ref(quickstart_guide_link, left_column[1]); + f.render_widget( + Span::styled("Get Direct Support:", Style::default().fg(GHOST_WHITE)), + left_column[2], + ); + f.render_widget_ref(get_direct_support_link, left_column[3]); + f.render_widget( + Span::styled( + "To join the Beta Rewards Program:", + Style::default().fg(GHOST_WHITE), + ), + right_column[0], + ); + f.render_widget_ref(beta_rewards_link, right_column[1]); + f.render_widget( + Span::styled( + "Download the latest launchpad:", + Style::default().fg(GHOST_WHITE), + ), + right_column[2], ); + f.render_widget_ref(download_latest_link, right_column[3]); - f.render_widget(table_help_and_support, layout[1]); + f.render_widget(block, layout[1]); Ok(()) } diff --git a/node-launchpad/src/widgets/hyperlink.rs b/node-launchpad/src/widgets/hyperlink.rs index 0798811ae0..2d78ed312e 100644 --- a/node-launchpad/src/widgets/hyperlink.rs +++ b/node-launchpad/src/widgets/hyperlink.rs @@ -8,7 +8,6 @@ use itertools::Itertools; use ratatui::{prelude::*, widgets::WidgetRef}; -use std::fmt; /// A hyperlink widget that renders a hyperlink in the terminal using [OSC 8]. /// @@ -27,20 +26,6 @@ impl<'content> Hyperlink<'content> { } } -// Displays the hyperlink in the terminal using OSC 8. -// Underline solid \x1b[4m -// Foreground color 45 \x1b[38;5;45m -impl fmt::Display for Hyperlink<'_> { - //TODO: Parameterize the color, underline, bold, etc. Use ratatui::Style. - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "\x1b[4m\x1b[38;5;45m\x1B]8;;{}\x07{}\x1B]8;;\x07\x1b[0m", - self.url, self.text - ) - } -} - impl WidgetRef for Hyperlink<'_> { fn render_ref(&self, area: Rect, buffer: &mut Buffer) { self.text.render_ref(area, buffer); @@ -60,8 +45,8 @@ impl WidgetRef for Hyperlink<'_> { let text = two_chars.collect::(); let hyperlink = format!("\x1B]8;;{}\x07{}\x1B]8;;\x07", self.url, text); buffer - .get_mut(area.x + i as u16 * 2, area.y) - .set_symbol(hyperlink.as_str()); + .cell_mut(Position::new(area.x + i as u16 * 2, area.y)) + .map(|cell| cell.set_symbol(hyperlink.as_str())); } } }