diff --git a/.gitignore b/.gitignore index ea8c4bf..68942e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +./src/snapshots diff --git a/src/app.rs b/src/app.rs index dec9374..f94b501 100644 --- a/src/app.rs +++ b/src/app.rs @@ -11,7 +11,12 @@ use std::path::PathBuf; pub enum CurrentScreen { Home, BitcoinConfig, + BitcoinStatus, P2PoolConfig, + P2PoolStatus, + LNConfig, + LNStatus, + SharesMarket, FileExplorer, Exiting, } @@ -41,6 +46,7 @@ pub struct App { pub explorer: FileExplorer, pub p2pool_config: Option, pub bitcoin_data: Vec, + pub bitcoin_status_tab: usize, } impl App { @@ -54,6 +60,7 @@ impl App { explorer: FileExplorer::new(), p2pool_config: None, bitcoin_data: Vec::new(), + bitcoin_status_tab: 0, } } @@ -62,7 +69,12 @@ impl App { match self.sidebar_index { 0 => self.current_screen = CurrentScreen::Home, 1 => self.current_screen = CurrentScreen::BitcoinConfig, - 2 => self.current_screen = CurrentScreen::P2PoolConfig, + 2 => self.current_screen = CurrentScreen::BitcoinStatus, + 3 => self.current_screen = CurrentScreen::P2PoolConfig, + 4 => self.current_screen = CurrentScreen::P2PoolStatus, + 5 => self.current_screen = CurrentScreen::LNConfig, + 6 => self.current_screen = CurrentScreen::LNStatus, + 7 => self.current_screen = CurrentScreen::SharesMarket, _ => {} } } diff --git a/src/components/bitcoin_config_view.rs b/src/components/bitcoin_config_view.rs new file mode 100644 index 0000000..c107a18 --- /dev/null +++ b/src/components/bitcoin_config_view.rs @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::App; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, List, ListItem, Paragraph}, +}; + +#[derive(Debug, Clone)] +pub struct BitcoinConfigView; + +impl BitcoinConfigView { + pub fn new() -> Self { + Self + } + + // Bitcoin Config + pub fn render(f: &mut Frame, app: &mut App, area: Rect) { + if app.bitcoin_conf_path.is_some() { + let items: Vec = app + .bitcoin_data + .iter() + .map(|entry| { + let style = if entry.enabled { + Style::default() + .fg(Color::White) + .add_modifier(Modifier::BOLD) + } else { + Style::default().fg(Color::DarkGray) + }; + + let content = Line::from(vec![ + Span::styled(format!("{} = ", entry.key), style), + Span::styled(&entry.value, style), + if !entry.enabled { + Span::styled(" (disabled)", style) + } else { + Span::raw("") + }, + ]); + + ListItem::new(content) + }) + .collect(); + + let list = List::new(items) + .block( + Block::default() + .borders(Borders::ALL) + .title(" Bitcoin Configuration "), + ) + .highlight_style(Style::default().bg(Color::Yellow)); + + f.render_widget(list, area); + } else { + let p = Paragraph::new("Press [Enter] to select a bitcoin.conf file").block( + Block::default() + .borders(Borders::ALL) + .title(" Bitcoin Config "), + ); + f.render_widget(p, area); + } + } +} + +impl Default for BitcoinConfigView { + fn default() -> Self { + Self::new() + } +} diff --git a/src/components/bitcoin_status_view.rs b/src/components/bitcoin_status_view.rs new file mode 100644 index 0000000..7c9d408 --- /dev/null +++ b/src/components/bitcoin_status_view.rs @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::App; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, Paragraph, Tabs, Wrap}, +}; + +#[derive(Debug, Clone)] +pub struct BitcoinStatusView; + +impl BitcoinStatusView { + pub fn new() -> Self { + Self + } + + pub fn render(f: &mut Frame, app: &App, area: Rect) { + let outer = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Length(4), // Tabs bar + Constraint::Min(0), // Tab content + ]) + .split(area); + + let tabs = Tabs::new(vec!["Chain Info", "System", "Logs", "Peers"]) + .block(Block::default().borders(Borders::ALL).title(" Info ")) + .select(app.bitcoin_status_tab) + .highlight_style(Style::default().bg(Color::Gray).fg(Color::Black)); + + f.render_widget(tabs, outer[0]); + + let content_area = outer[1]; + match app.bitcoin_status_tab { + // Chain Info + 0 => { + let text = "Chain Info"; + let p = Paragraph::new(text) + .block(Block::default().borders(Borders::ALL)) + .wrap(Wrap { trim: true }); + f.render_widget(p, content_area); + } + // System + 1 => { + let text = "System"; + let p = Paragraph::new(text) + .block(Block::default().borders(Borders::ALL)) + .wrap(Wrap { trim: true }); + f.render_widget(p, content_area); + } + // Logs + 2 => { + let text = "Logs"; + let p = Paragraph::new(text) + .block(Block::default().borders(Borders::ALL)) + .wrap(Wrap { trim: true }); + f.render_widget(p, content_area); + } + // Peers + 3 => { + let text = "Peers"; + let p = Paragraph::new(text) + .block(Block::default().borders(Borders::ALL)) + .wrap(Wrap { trim: true }); + f.render_widget(p, content_area); + } + _ => {} + } + } +} + +impl Default for BitcoinStatusView { + fn default() -> Self { + Self::new() + } +} diff --git a/src/components/file_explorer.rs b/src/components/file_explorer.rs index fee01b0..19efd98 100644 --- a/src/components/file_explorer.rs +++ b/src/components/file_explorer.rs @@ -2,8 +2,12 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -use crate::app::AppAction; +use crate::app::{App, AppAction}; use crossterm::event::{KeyCode, KeyEvent}; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, List, ListItem, ListState}, +}; use std::fs; use std::path::PathBuf; @@ -138,13 +142,45 @@ impl FileExplorer { _ => AppAction::None, } } + + pub fn render(f: &mut Frame, app: &mut App, area: Rect) { + let files: Vec = app + .explorer + .files + .iter() + .map(|path| { + let display_name = if path.ends_with("..") { + "πŸ“ ..".to_string() + } else { + let name = path.file_name().unwrap_or_default().to_string_lossy(); + if path.is_dir() { + format!("πŸ“ {}", name) + } else { + format!("πŸ“„ {}", name) + } + }; + ListItem::new(display_name) + }) + .collect(); + + let mut state = ListState::default(); + state.select(Some(app.explorer.selected_index)); + + let title = format!(" Select File (Current: {:?}) ", app.explorer.current_dir); + + let list = List::new(files) + .block(Block::default().borders(Borders::ALL).title(title)) + .highlight_style(Style::default().bg(Color::Blue).fg(Color::White)) + .highlight_symbol(">> "); + + f.render_stateful_widget(list, area, &mut state); + } } #[cfg(test)] mod tests { use super::*; - use std::env::temp_dir; - use std::fs::{File, create_dir}; + use std::fs::File; fn setup_temp_fs() -> PathBuf { use std::time::{SystemTime, UNIX_EPOCH}; diff --git a/src/components/home_view.rs b/src/components/home_view.rs new file mode 100644 index 0000000..0c012ba --- /dev/null +++ b/src/components/home_view.rs @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::App; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, Paragraph, Wrap}, +}; + +#[derive(Debug, Clone)] +pub struct HomeView; + +impl HomeView { + pub fn new() -> Self { + Self + } + + pub fn render(f: &mut Frame, _app: &mut App, area: Rect) { + let p = Paragraph::new("Welcome to PDM.\n\nSelect a config from the sidebar to edit.") + .block(Block::default().borders(Borders::ALL).title(" Home ")) + .wrap(Wrap { trim: true }); + f.render_widget(p, area); + } +} + +impl Default for HomeView { + fn default() -> Self { + Self::new() + } +} diff --git a/src/components/ln_config_view.rs b/src/components/ln_config_view.rs new file mode 100644 index 0000000..4093ea8 --- /dev/null +++ b/src/components/ln_config_view.rs @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::App; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, Paragraph}, +}; + +#[derive(Debug, Clone)] +pub struct LNConfigView; + +impl LNConfigView { + pub fn new() -> Self { + Self + } + + // LN Config + pub fn render(f: &mut Frame, _app: &mut App, area: Rect) { + let p = Paragraph::new("LN Config") + .block(Block::default().borders(Borders::ALL).title(" LN Config ")); + f.render_widget(p, area); + } +} + +impl Default for LNConfigView { + fn default() -> Self { + Self::new() + } +} diff --git a/src/components/ln_status_view.rs b/src/components/ln_status_view.rs new file mode 100644 index 0000000..8df3b0b --- /dev/null +++ b/src/components/ln_status_view.rs @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::App; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, Paragraph}, +}; + +#[derive(Debug, Clone)] +pub struct LNStatusView; + +impl LNStatusView { + pub fn new() -> Self { + Self + } + + // LN Status + pub fn render(f: &mut Frame, _app: &mut App, area: Rect) { + let p = Paragraph::new("LN Status") + .block(Block::default().borders(Borders::ALL).title(" LN Status ")); + f.render_widget(p, area); + } +} + +impl Default for LNStatusView { + fn default() -> Self { + Self::new() + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 6d3b562..b1fcb60 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -2,4 +2,13 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later +pub mod bitcoin_config_view; +pub mod bitcoin_status_view; pub mod file_explorer; +pub mod home_view; +pub mod ln_config_view; +pub mod ln_status_view; +pub mod p2pool_config_view; +pub mod p2pool_status_view; +pub mod shares_market_view; +pub mod status_bar; diff --git a/src/components/p2pool_config_view.rs b/src/components/p2pool_config_view.rs new file mode 100644 index 0000000..77155f2 --- /dev/null +++ b/src/components/p2pool_config_view.rs @@ -0,0 +1,117 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::App; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, List, ListItem, Paragraph}, +}; + +#[derive(Debug, Clone)] +pub struct P2PoolConfigView; + +impl P2PoolConfigView { + pub fn new() -> Self { + Self + } + + // P2Pool Config + pub fn render(f: &mut Frame, app: &mut App, area: Rect) { + if app.p2pool_conf_path.is_some() { + let mut items: Vec = Vec::new(); + + if let Some(cfg) = &app.p2pool_config { + // STRATUM + items.push(ListItem::new(Line::from(vec![ + Span::styled("[stratum] ", Style::default().fg(Color::Blue)), + Span::raw(format!("hostname = {}", cfg.stratum.hostname)), + ]))); + + items.push(ListItem::new(Line::from(vec![ + Span::styled("[stratum] ", Style::default().fg(Color::Blue)), + Span::raw(format!("port = {}", cfg.stratum.port)), + ]))); + + items.push(ListItem::new(Line::from(vec![ + Span::styled("[stratum] ", Style::default().fg(Color::Blue)), + Span::raw(format!( + "start_difficulty = {}", + cfg.stratum.start_difficulty + )), + ]))); + + items.push(ListItem::new(Line::from(vec![ + Span::styled("[stratum] ", Style::default().fg(Color::Blue)), + Span::raw(format!( + "minimum_difficulty = {}", + cfg.stratum.minimum_difficulty + )), + ]))); + + // BITCOIN RPC + items.push(ListItem::new(Line::from(vec![ + Span::styled("[bitcoinrpc] ", Style::default().fg(Color::Blue)), + Span::raw(format!("url = {}", cfg.bitcoinrpc.url)), + ]))); + + items.push(ListItem::new(Line::from(vec![ + Span::styled("[bitcoinrpc] ", Style::default().fg(Color::Blue)), + Span::raw(format!("username = {}", cfg.bitcoinrpc.username)), + ]))); + + // NETWORK + items.push(ListItem::new(Line::from(vec![ + Span::styled("[network] ", Style::default().fg(Color::Blue)), + Span::raw(format!("listen_address = {}", cfg.network.listen_address)), + ]))); + + items.push(ListItem::new(Line::from(vec![ + Span::styled("[network] ", Style::default().fg(Color::Blue)), + Span::raw(format!( + "max_established_incoming = {}", + cfg.network.max_established_incoming + )), + ]))); + + // STORE + items.push(ListItem::new(Line::from(vec![ + Span::styled("[store] ", Style::default().fg(Color::Blue)), + Span::raw(format!("path = {}", cfg.store.path)), + ]))); + + // API + items.push(ListItem::new(Line::from(vec![ + Span::styled("[api] ", Style::default().fg(Color::Blue)), + Span::raw(format!("hostname = {}", cfg.api.hostname)), + ]))); + + items.push(ListItem::new(Line::from(vec![ + Span::styled("[api] ", Style::default().fg(Color::Blue)), + Span::raw(format!("port = {}", cfg.api.port)), + ]))); + } + + let list = List::new(items).block( + Block::default() + .borders(Borders::ALL) + .title(" P2Pool Configuration "), + ); + + f.render_widget(list, area); + } else { + let p = Paragraph::new("Press [Enter] to select a p2poolv2 config file").block( + Block::default() + .borders(Borders::ALL) + .title(" P2Pool Config "), + ); + f.render_widget(p, area); + } + } +} + +impl Default for P2PoolConfigView { + fn default() -> Self { + Self::new() + } +} diff --git a/src/components/p2pool_status_view.rs b/src/components/p2pool_status_view.rs new file mode 100644 index 0000000..82d6f07 --- /dev/null +++ b/src/components/p2pool_status_view.rs @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::App; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, Paragraph}, +}; + +#[derive(Debug, Clone)] +pub struct P2PoolStatusView; + +impl P2PoolStatusView { + pub fn new() -> Self { + Self + } + + // P2Pool Status + pub fn render(f: &mut Frame, _app: &mut App, area: Rect) { + let p = Paragraph::new("P2Pool Status").block( + Block::default() + .borders(Borders::ALL) + .title(" P2Pool Status "), + ); + f.render_widget(p, area); + } +} + +impl Default for P2PoolStatusView { + fn default() -> Self { + Self::new() + } +} diff --git a/src/components/shares_market_view.rs b/src/components/shares_market_view.rs new file mode 100644 index 0000000..2fe6950 --- /dev/null +++ b/src/components/shares_market_view.rs @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::App; +use ratatui::{ + prelude::*, + widgets::{Block, Borders, Paragraph}, +}; + +#[derive(Debug, Clone)] +pub struct SharesMarketView; + +impl SharesMarketView { + pub fn new() -> Self { + Self + } + + // LN Status + pub fn render(f: &mut Frame, _app: &mut App, area: Rect) { + let p = Paragraph::new("Shares Market").block( + Block::default() + .borders(Borders::ALL) + .title(" Shares Market "), + ); + f.render_widget(p, area); + } +} + +impl Default for SharesMarketView { + fn default() -> Self { + Self::new() + } +} diff --git a/src/components/status_bar.rs b/src/components/status_bar.rs new file mode 100644 index 0000000..f615bda --- /dev/null +++ b/src/components/status_bar.rs @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2024 PDM Authors +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use crate::app::{App, CurrentScreen}; +use ratatui::{prelude::*, widgets::Paragraph}; + +#[derive(Clone, Debug)] +pub struct StatusBar; + +fn hint(key: &str, desc: &str) -> Vec> { + vec![ + Span::styled( + format!(" {key} "), + Style::default().bg(Color::DarkGray).fg(Color::White), + ), + Span::styled(format!(" {desc} "), Style::default().fg(Color::DarkGray)), + ] +} + +impl StatusBar { + pub fn new() -> Self { + Self + } + + // Status bar + pub fn render(f: &mut Frame, app: &App, area: Rect) { + let mut spans: Vec = Vec::new(); + + match app.current_screen { + CurrentScreen::FileExplorer => { + spans.extend(hint("↑↓", "Navigate")); + spans.extend(hint("Enter", "Select")); + spans.extend(hint("Esc", "Cancel")); + } + CurrentScreen::BitcoinConfig if app.bitcoin_conf_path.is_some() => { + spans.extend(hint("↑↓", "Navigate")); + spans.extend(hint("Enter", "Open file")); + spans.extend(hint("q", "Quit")); + } + CurrentScreen::P2PoolConfig if app.p2pool_conf_path.is_some() => { + spans.extend(hint("↑↓", "Navigate")); + spans.extend(hint("Enter", "Open file")); + spans.extend(hint("q", "Quit")); + } + CurrentScreen::BitcoinStatus => { + spans.extend(hint("↑↓", "Navigate sidebar")); + spans.extend(hint("←→", "Switch tab")); + spans.extend(hint("q", "Quit")); + } + _ => { + spans.extend(hint("↑↓", "Navigate sidebar")); + spans.extend(hint("Enter", "Select")); + spans.extend(hint("q", "Quit")); + } + } + + let bar = Paragraph::new(Line::from(spans)).style(Style::default().bg(Color::Black)); + f.render_widget(bar, area); + } +} + +impl Default for StatusBar { + fn default() -> Self { + Self::new() + } +} diff --git a/src/main.rs b/src/main.rs index 355f2e9..d53ce48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,6 +60,38 @@ fn run_app(terminal: &mut Terminal, app: &mut App) -> Result<()> let action = match app.current_screen { CurrentScreen::FileExplorer => app.explorer.handle_input(key), + CurrentScreen::BitcoinStatus => match key.code { + KeyCode::Left => { + if app.bitcoin_status_tab > 0 { + app.bitcoin_status_tab -= 1; + } + AppAction::None + } + KeyCode::Right => { + if app.bitcoin_status_tab < 3 { + app.bitcoin_status_tab += 1; + } + AppAction::None + } + KeyCode::Up => { + if app.sidebar_index > 0 { + app.sidebar_index -= 1; + AppAction::ToggleMenu + } else { + AppAction::None + } + } + KeyCode::Down => { + if app.sidebar_index < 3 { + app.sidebar_index += 1; + AppAction::ToggleMenu + } else { + AppAction::None + } + } + _ => AppAction::None, + }, + _ => match key.code { KeyCode::Enter => { if matches!( @@ -73,7 +105,7 @@ fn run_app(terminal: &mut Terminal, app: &mut App) -> Result<()> } KeyCode::Down => { - if app.sidebar_index < 2 { + if app.sidebar_index < 7 { app.sidebar_index += 1; AppAction::ToggleMenu } else { diff --git a/src/snapshots/pdm__tests__home_screen.snap b/src/snapshots/pdm__tests__home_screen.snap index bf9b5ea..1c88ef1 100644 --- a/src/snapshots/pdm__tests__home_screen.snap +++ b/src/snapshots/pdm__tests__home_screen.snap @@ -9,13 +9,12 @@ TestBackend { "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Home ───────────────────────────────────────────────┐", "β”‚Home β”‚β”‚Welcome to PDM. β”‚", "β”‚Bitcoin Config β”‚β”‚ β”‚", - "β”‚P2Pool Config β”‚β”‚Select a config from the sidebar to edit. β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚Select a config from the sidebar to edit. β”‚", + "β”‚P2Pool Config β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", @@ -31,11 +30,19 @@ TestBackend { "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, x: 1, y: 1, fg: Black, bg: Gray, underline: Reset, modifier: NONE, x: 24, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 24, fg: Reset, bg: Black, underline: Reset, modifier: NONE, ] }, scrollback: Buffer { diff --git a/src/snapshots/pdm__tests__menu_toggled.snap b/src/snapshots/pdm__tests__menu_toggled.snap index bc9e283..85b75d4 100644 --- a/src/snapshots/pdm__tests__menu_toggled.snap +++ b/src/snapshots/pdm__tests__menu_toggled.snap @@ -9,13 +9,12 @@ TestBackend { "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Bitcoin Config ─────────────────────────────────────┐", "β”‚Home β”‚β”‚Press [Enter] to select a bitcoin.conf file β”‚", "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", "β”‚P2Pool Config β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", @@ -31,11 +30,19 @@ TestBackend { "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, x: 1, y: 2, fg: Black, bg: Gray, underline: Reset, modifier: NONE, x: 24, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 24, fg: Reset, bg: Black, underline: Reset, modifier: NONE, ] }, scrollback: Buffer { diff --git a/src/snapshots/pdm__ui__tests__bitcoin_config_screen_render.snap b/src/snapshots/pdm__ui__tests__bitcoin_config_screen_render.snap new file mode 100644 index 0000000..7dc809c --- /dev/null +++ b/src/snapshots/pdm__ui__tests__bitcoin_config_screen_render.snap @@ -0,0 +1,55 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Bitcoin Config ─────────────────────────────────────┐", + "β”‚Home β”‚β”‚Press [Enter] to select a bitcoin.conf file β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", + "β”‚P2Pool Config β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 2, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__bitcoin_screen_render.snap b/src/snapshots/pdm__ui__tests__bitcoin_screen_render.snap.new similarity index 71% rename from src/snapshots/pdm__ui__tests__bitcoin_screen_render.snap rename to src/snapshots/pdm__ui__tests__bitcoin_screen_render.snap.new index 0223c7e..ea4c542 100644 --- a/src/snapshots/pdm__ui__tests__bitcoin_screen_render.snap +++ b/src/snapshots/pdm__ui__tests__bitcoin_screen_render.snap.new @@ -1,5 +1,6 @@ --- source: src/ui.rs +assertion_line: 409 expression: terminal.backend() --- TestBackend { @@ -9,13 +10,12 @@ TestBackend { "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Bitcoin Config ─────────────────────────────────────┐", "β”‚Home β”‚β”‚Press [Enter] to select a bitcoin.conf file β”‚", "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", "β”‚P2Pool Config β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", @@ -26,11 +26,19 @@ TestBackend { "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, x: 1, y: 2, fg: Black, bg: Gray, underline: Reset, modifier: NONE, x: 24, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 19, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 19, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 19, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 19, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 19, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 19, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 19, fg: Reset, bg: Black, underline: Reset, modifier: NONE, ] }, scrollback: Buffer { diff --git a/src/snapshots/pdm__ui__tests__bitcoin_status_screen_render.snap b/src/snapshots/pdm__ui__tests__bitcoin_status_screen_render.snap new file mode 100644 index 0000000..004c272 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__bitcoin_status_screen_render.snap @@ -0,0 +1,57 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Info ───────────────────────────────────────────────┐", + "β”‚Home β”‚β”‚ Chain Info β”‚ System β”‚ Logs β”‚ Peers β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + "β”‚P2Pool Config β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”", + "β”‚P2Pool Status β”‚β”‚Chain Info β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar ←→ Switch tab q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 27, y: 1, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 37, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 3, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 27, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 40, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 43, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 50, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__bitcoin_status_tab_logs_render.snap b/src/snapshots/pdm__ui__tests__bitcoin_status_tab_logs_render.snap new file mode 100644 index 0000000..374cd78 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__bitcoin_status_tab_logs_render.snap @@ -0,0 +1,57 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Info ───────────────────────────────────────────────┐", + "β”‚Home β”‚β”‚ Chain Info β”‚ System β”‚ Logs β”‚ Peers β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + "β”‚P2Pool Config β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”", + "β”‚P2Pool Status β”‚β”‚Logs β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar ←→ Switch tab q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 49, y: 1, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 53, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 3, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 27, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 40, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 43, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 50, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__bitcoin_status_tab_peers_render.snap b/src/snapshots/pdm__ui__tests__bitcoin_status_tab_peers_render.snap new file mode 100644 index 0000000..72ec916 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__bitcoin_status_tab_peers_render.snap @@ -0,0 +1,57 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Info ───────────────────────────────────────────────┐", + "β”‚Home β”‚β”‚ Chain Info β”‚ System β”‚ Logs β”‚ Peers β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + "β”‚P2Pool Config β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”", + "β”‚P2Pool Status β”‚β”‚Peers β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar ←→ Switch tab q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 56, y: 1, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 61, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 3, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 27, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 40, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 43, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 50, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__bitcoin_status_tab_system_render.snap b/src/snapshots/pdm__ui__tests__bitcoin_status_tab_system_render.snap new file mode 100644 index 0000000..34e5465 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__bitcoin_status_tab_system_render.snap @@ -0,0 +1,57 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Info ───────────────────────────────────────────────┐", + "β”‚Home β”‚β”‚ Chain Info β”‚ System β”‚ Logs β”‚ Peers β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + "β”‚P2Pool Config β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”", + "β”‚P2Pool Status β”‚β”‚System β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar ←→ Switch tab q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 40, y: 1, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 46, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 3, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 27, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 40, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 43, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 50, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__home_screen_render.snap b/src/snapshots/pdm__ui__tests__home_screen_render.snap index 7e664ba..1557c37 100644 --- a/src/snapshots/pdm__ui__tests__home_screen_render.snap +++ b/src/snapshots/pdm__ui__tests__home_screen_render.snap @@ -4,14 +4,17 @@ expression: terminal.backend() --- TestBackend { buffer: Buffer { - area: Rect { x: 0, y: 0, width: 80, height: 20 }, + area: Rect { x: 0, y: 0, width: 80, height: 24 }, content: [ "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Home ───────────────────────────────────────────────┐", "β”‚Home β”‚β”‚Welcome to PDM. β”‚", "β”‚Bitcoin Config β”‚β”‚ β”‚", - "β”‚P2Pool Config β”‚β”‚Select a config from the sidebar to edit. β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚Select a config from the sidebar to edit. β”‚", + "β”‚P2Pool Config β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", @@ -26,11 +29,19 @@ TestBackend { "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, x: 1, y: 1, fg: Black, bg: Gray, underline: Reset, modifier: NONE, x: 24, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, ] }, scrollback: Buffer { diff --git a/src/snapshots/pdm__ui__tests__ln_config_screen_render.snap b/src/snapshots/pdm__ui__tests__ln_config_screen_render.snap new file mode 100644 index 0000000..d0b44a5 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__ln_config_screen_render.snap @@ -0,0 +1,55 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ LN Config ──────────────────────────────────────────┐", + "β”‚Home β”‚β”‚LN Config β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", + "β”‚P2Pool Config β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 6, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 6, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__ln_status_screen_render.snap b/src/snapshots/pdm__ui__tests__ln_status_screen_render.snap new file mode 100644 index 0000000..63c2683 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__ln_status_screen_render.snap @@ -0,0 +1,55 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ LN Status ──────────────────────────────────────────┐", + "β”‚Home β”‚β”‚LN Status β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", + "β”‚P2Pool Config β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 7, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 7, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__p2pool_screen_render.snap b/src/snapshots/pdm__ui__tests__p2pool_config_screen_render.snap similarity index 66% rename from src/snapshots/pdm__ui__tests__p2pool_screen_render.snap rename to src/snapshots/pdm__ui__tests__p2pool_config_screen_render.snap index af40537..1e183bf 100644 --- a/src/snapshots/pdm__ui__tests__p2pool_screen_render.snap +++ b/src/snapshots/pdm__ui__tests__p2pool_config_screen_render.snap @@ -4,14 +4,17 @@ expression: terminal.backend() --- TestBackend { buffer: Buffer { - area: Rect { x: 0, y: 0, width: 80, height: 20 }, + area: Rect { x: 0, y: 0, width: 80, height: 24 }, content: [ "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ P2Pool Config ──────────────────────────────────────┐", "β”‚Home β”‚β”‚Press [Enter] to select a p2poolv2 config file β”‚", "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", "β”‚P2Pool Config β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", @@ -26,11 +29,19 @@ TestBackend { "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, - x: 1, y: 3, fg: Black, bg: Gray, underline: Reset, modifier: NONE, - x: 24, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 4, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, ] }, scrollback: Buffer { diff --git a/src/snapshots/pdm__ui__tests__p2pool_screen_render.snap.new b/src/snapshots/pdm__ui__tests__p2pool_screen_render.snap.new new file mode 100644 index 0000000..cea0888 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__p2pool_screen_render.snap.new @@ -0,0 +1,54 @@ +--- +source: src/ui.rs +assertion_line: 423 +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 20 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Info ───────────────────────────────────────────────┐", + "β”‚Home β”‚β”‚ Chain Info β”‚ System β”‚ Logs β”‚ Peers β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + "β”‚P2Pool Config β”‚β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”", + "β”‚P2Pool Status β”‚β”‚Chain Info β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar ←→ Switch tab q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 27, y: 1, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 37, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 3, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 19, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 19, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 19, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 27, y: 19, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 40, y: 19, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 43, y: 19, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 50, y: 19, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__p2pool_status_screen_render.snap b/src/snapshots/pdm__ui__tests__p2pool_status_screen_render.snap new file mode 100644 index 0000000..f11c111 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__p2pool_status_screen_render.snap @@ -0,0 +1,55 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ P2Pool Status ──────────────────────────────────────┐", + "β”‚Home β”‚β”‚P2Pool Status β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", + "β”‚P2Pool Config β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 5, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 5, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/snapshots/pdm__ui__tests__shares_market_screen_render.snap b/src/snapshots/pdm__ui__tests__shares_market_screen_render.snap new file mode 100644 index 0000000..32cb5f8 --- /dev/null +++ b/src/snapshots/pdm__ui__tests__shares_market_screen_render.snap @@ -0,0 +1,55 @@ +--- +source: src/ui.rs +expression: terminal.backend() +--- +TestBackend { + buffer: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 24 }, + content: [ + "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Shares Market ──────────────────────────────────────┐", + "β”‚Home β”‚β”‚Shares Market β”‚", + "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", + "β”‚P2Pool Config β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β”‚ β”‚β”‚ β”‚", + "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 1, y: 8, fg: Black, bg: Gray, underline: Reset, modifier: NONE, + x: 24, y: 8, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 23, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 23, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 23, fg: Reset, bg: Black, underline: Reset, modifier: NONE, + ] + }, + scrollback: Buffer { + area: Rect { x: 0, y: 0, width: 80, height: 0 } + }, + cursor: false, + pos: ( + 0, + 0, + ), +} diff --git a/src/ui.rs b/src/ui.rs index c83c3ea..f7740c1 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -3,25 +3,48 @@ // SPDX-License-Identifier: AGPL-3.0-or-later use crate::app::{App, CurrentScreen}; +use crate::components::{ + bitcoin_config_view::BitcoinConfigView, bitcoin_status_view::BitcoinStatusView, + file_explorer::FileExplorer, home_view::HomeView, ln_config_view::LNConfigView, + ln_status_view::LNStatusView, p2pool_config_view::P2PoolConfigView, + p2pool_status_view::P2PoolStatusView, shares_market_view::SharesMarketView, + status_bar::StatusBar, +}; use ratatui::{ prelude::*, - widgets::{Block, Borders, List, ListItem, ListState, Paragraph, Wrap}, + widgets::{Block, Borders, List, ListItem, ListState}, }; pub fn ui(f: &mut Frame, app: &mut App) { + let outer = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Min(0), // Main area + Constraint::Length(1), // Status bar + ]) + .split(f.area()); + + let main_row = outer[0]; + let status_bar_area = outer[1]; + let chunks = Layout::default() .direction(Direction::Horizontal) .constraints([ Constraint::Length(25), // Sidebar Constraint::Min(0), // Main Content ]) - .split(f.area()); + .split(main_row); // Sidebar let items = vec![ ListItem::new("Home"), ListItem::new("Bitcoin Config"), + ListItem::new("Bitcoin Status"), ListItem::new("P2Pool Config"), + ListItem::new("P2Pool Status"), + ListItem::new("LN Config"), + ListItem::new("LN Status"), + ListItem::new("Shares Market"), ]; // Highlight the active one @@ -39,191 +62,36 @@ pub fn ui(f: &mut Frame, app: &mut App) { match app.current_screen { CurrentScreen::Home => { - let p = Paragraph::new("Welcome to PDM.\n\nSelect a config from the sidebar to edit.") - .block(Block::default().borders(Borders::ALL).title(" Home ")) - .wrap(Wrap { trim: true }); - f.render_widget(p, main_area); + HomeView::render(f, app, main_area); } CurrentScreen::BitcoinConfig => { - if app.bitcoin_conf_path.is_some() { - render_bitcoin_view(f, app, main_area); - } else { - let p = Paragraph::new("Press [Enter] to select a bitcoin.conf file").block( - Block::default() - .borders(Borders::ALL) - .title(" Bitcoin Config "), - ); - f.render_widget(p, main_area); - } + BitcoinConfigView::render(f, app, main_area); + } + CurrentScreen::BitcoinStatus => { + BitcoinStatusView::render(f, app, main_area); } - CurrentScreen::P2PoolConfig => { - if app.p2pool_conf_path.is_some() { - render_p2pool_view(f, app, main_area); - } else { - let p = Paragraph::new("Press [Enter] to select a p2poolv2 config file").block( - Block::default() - .borders(Borders::ALL) - .title(" P2Pool Config "), - ); - f.render_widget(p, main_area); - } + P2PoolConfigView::render(f, app, main_area); + } + CurrentScreen::P2PoolStatus => { + P2PoolStatusView::render(f, app, main_area); + } + CurrentScreen::LNConfig => { + LNConfigView::render(f, app, main_area); + } + CurrentScreen::LNStatus => { + LNStatusView::render(f, app, main_area); + } + CurrentScreen::SharesMarket => { + SharesMarketView::render(f, app, main_area); } CurrentScreen::FileExplorer => { - render_file_explorer(f, app, main_area); + FileExplorer::render(f, app, main_area); } _ => {} } -} - -fn render_file_explorer(f: &mut Frame, app: &mut App, area: Rect) { - let files: Vec = app - .explorer - .files - .iter() - .map(|path| { - let name = path.file_name().unwrap_or_default().to_string_lossy(); - let display_name = if path.is_dir() { - format!("πŸ“ {}", name) - } else { - format!("πŸ“„ {}", name) - }; - ListItem::new(display_name) - }) - .collect(); - - let mut state = ListState::default(); - state.select(Some(app.explorer.selected_index)); - - let title = format!(" Select File (Current: {:?}) ", app.explorer.current_dir); - - let list = List::new(files) - .block(Block::default().borders(Borders::ALL).title(title)) - .highlight_style(Style::default().bg(Color::Blue).fg(Color::White)) - .highlight_symbol(">> "); - - f.render_stateful_widget(list, area, &mut state); -} - -fn render_p2pool_view(f: &mut Frame, app: &mut App, area: Rect) { - let mut items: Vec = Vec::new(); - - if let Some(cfg) = &app.p2pool_config { - // STRATUM - items.push(ListItem::new(Line::from(vec![ - Span::styled("[stratum] ", Style::default().fg(Color::Blue)), - Span::raw(format!("hostname = {}", cfg.stratum.hostname)), - ]))); - - items.push(ListItem::new(Line::from(vec![ - Span::styled("[stratum] ", Style::default().fg(Color::Blue)), - Span::raw(format!("port = {}", cfg.stratum.port)), - ]))); - - items.push(ListItem::new(Line::from(vec![ - Span::styled("[stratum] ", Style::default().fg(Color::Blue)), - Span::raw(format!( - "start_difficulty = {}", - cfg.stratum.start_difficulty - )), - ]))); - - items.push(ListItem::new(Line::from(vec![ - Span::styled("[stratum] ", Style::default().fg(Color::Blue)), - Span::raw(format!( - "minimum_difficulty = {}", - cfg.stratum.minimum_difficulty - )), - ]))); - - // BITCOIN RPC - items.push(ListItem::new(Line::from(vec![ - Span::styled("[bitcoinrpc] ", Style::default().fg(Color::Blue)), - Span::raw(format!("url = {}", cfg.bitcoinrpc.url)), - ]))); - - items.push(ListItem::new(Line::from(vec![ - Span::styled("[bitcoinrpc] ", Style::default().fg(Color::Blue)), - Span::raw(format!("username = {}", cfg.bitcoinrpc.username)), - ]))); - - // NETWORK - items.push(ListItem::new(Line::from(vec![ - Span::styled("[network] ", Style::default().fg(Color::Blue)), - Span::raw(format!("listen_address = {}", cfg.network.listen_address)), - ]))); - - items.push(ListItem::new(Line::from(vec![ - Span::styled("[network] ", Style::default().fg(Color::Blue)), - Span::raw(format!( - "max_established_incoming = {}", - cfg.network.max_established_incoming - )), - ]))); - - // STORE - items.push(ListItem::new(Line::from(vec![ - Span::styled("[store] ", Style::default().fg(Color::Blue)), - Span::raw(format!("path = {}", cfg.store.path)), - ]))); - - // API - items.push(ListItem::new(Line::from(vec![ - Span::styled("[api] ", Style::default().fg(Color::Blue)), - Span::raw(format!("hostname = {}", cfg.api.hostname)), - ]))); - - items.push(ListItem::new(Line::from(vec![ - Span::styled("[api] ", Style::default().fg(Color::Blue)), - Span::raw(format!("port = {}", cfg.api.port)), - ]))); - } - - let list = List::new(items).block( - Block::default() - .borders(Borders::ALL) - .title(" P2Pool Configuration "), - ); - f.render_widget(list, area); -} - -fn render_bitcoin_view(f: &mut Frame, app: &mut App, area: Rect) { - let items: Vec = app - .bitcoin_data - .iter() - .map(|entry| { - let style = if entry.enabled { - Style::default() - .fg(Color::White) - .add_modifier(Modifier::BOLD) - } else { - Style::default().fg(Color::DarkGray) - }; - - let content = Line::from(vec![ - Span::styled(format!("{} = ", entry.key), style), - Span::styled(&entry.value, style), - if !entry.enabled { - Span::styled(" (disabled)", style) - } else { - Span::raw("") - }, - ]); - - ListItem::new(content) - }) - .collect(); - - let list = List::new(items) - .block( - Block::default() - .borders(Borders::ALL) - .title(" Bitcoin Configuration "), - ) - .highlight_style(Style::default().bg(Color::Yellow)); - - f.render_widget(list, area); + StatusBar::render(f, app, status_bar_area); } #[cfg(test)] @@ -233,43 +101,118 @@ mod tests { use ratatui::Terminal; use ratatui::backend::TestBackend; + fn make_terminal() -> Terminal { + Terminal::new(TestBackend::new(80, 24)).unwrap() + } + #[test] fn test_home_screen_render() { - let backend = TestBackend::new(80, 20); - let mut terminal = Terminal::new(backend).unwrap(); - + let mut terminal = make_terminal(); let mut app = App::new(); + terminal.draw(|f| ui(f, &mut app)).unwrap(); + insta::assert_debug_snapshot!(terminal.backend()); + } + #[test] + fn test_bitcoin_config_screen_render() { + let mut terminal = make_terminal(); + let mut app = App::new(); + app.sidebar_index = 1; + app.toggle_menu(); terminal.draw(|f| ui(f, &mut app)).unwrap(); + insta::assert_debug_snapshot!(terminal.backend()); + } + #[test] + fn test_bitcoin_status_screen_render() { + let mut terminal = make_terminal(); + let mut app = App::new(); + app.sidebar_index = 2; + app.toggle_menu(); + terminal.draw(|f| ui(f, &mut app)).unwrap(); insta::assert_debug_snapshot!(terminal.backend()); } #[test] - fn test_bitcoin_screen_render() { - let backend = TestBackend::new(80, 20); - let mut terminal = Terminal::new(backend).unwrap(); + fn test_bitcoin_status_tab_system_render() { + let mut terminal = make_terminal(); + let mut app = App::new(); + app.sidebar_index = 2; + app.toggle_menu(); + app.bitcoin_status_tab = 1; + terminal.draw(|f| ui(f, &mut app)).unwrap(); + insta::assert_debug_snapshot!(terminal.backend()); + } + #[test] + fn test_bitcoin_status_tab_logs_render() { + let mut terminal = make_terminal(); let mut app = App::new(); - app.sidebar_index = 1; + app.sidebar_index = 2; app.toggle_menu(); + app.bitcoin_status_tab = 2; + terminal.draw(|f| ui(f, &mut app)).unwrap(); + insta::assert_debug_snapshot!(terminal.backend()); + } + #[test] + fn test_bitcoin_status_tab_peers_render() { + let mut terminal = make_terminal(); + let mut app = App::new(); + app.sidebar_index = 2; + app.toggle_menu(); + app.bitcoin_status_tab = 3; terminal.draw(|f| ui(f, &mut app)).unwrap(); + insta::assert_debug_snapshot!(terminal.backend()); + } + #[test] + fn test_p2pool_config_screen_render() { + let mut terminal = make_terminal(); + let mut app = App::new(); + app.sidebar_index = 3; + app.toggle_menu(); + terminal.draw(|f| ui(f, &mut app)).unwrap(); insta::assert_debug_snapshot!(terminal.backend()); } #[test] - fn test_p2pool_screen_render() { - let backend = TestBackend::new(80, 20); - let mut terminal = Terminal::new(backend).unwrap(); + fn test_p2pool_status_screen_render() { + let mut terminal = make_terminal(); + let mut app = App::new(); + app.sidebar_index = 4; + app.toggle_menu(); + terminal.draw(|f| ui(f, &mut app)).unwrap(); + insta::assert_debug_snapshot!(terminal.backend()); + } + #[test] + fn test_ln_config_screen_render() { + let mut terminal = make_terminal(); let mut app = App::new(); - app.sidebar_index = 2; + app.sidebar_index = 5; app.toggle_menu(); + terminal.draw(|f| ui(f, &mut app)).unwrap(); + insta::assert_debug_snapshot!(terminal.backend()); + } + #[test] + fn test_ln_status_screen_render() { + let mut terminal = make_terminal(); + let mut app = App::new(); + app.sidebar_index = 6; + app.toggle_menu(); terminal.draw(|f| ui(f, &mut app)).unwrap(); + insta::assert_debug_snapshot!(terminal.backend()); + } + #[test] + fn test_shares_market_screen_render() { + let mut terminal = make_terminal(); + let mut app = App::new(); + app.sidebar_index = 7; + app.toggle_menu(); + terminal.draw(|f| ui(f, &mut app)).unwrap(); insta::assert_debug_snapshot!(terminal.backend()); } } diff --git a/tests/snapshots/ui_snapshots__config_screen_render.snap b/tests/snapshots/ui_snapshots__config_screen_render.snap index 32f7690..5445ad4 100644 --- a/tests/snapshots/ui_snapshots__config_screen_render.snap +++ b/tests/snapshots/ui_snapshots__config_screen_render.snap @@ -9,13 +9,12 @@ TestBackend { "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Bitcoin Config ─────────────────────────────────────┐", "β”‚Home β”‚β”‚Press [Enter] to select a bitcoin.conf file β”‚", "β”‚Bitcoin Config β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚ β”‚", "β”‚P2Pool Config β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", @@ -31,11 +30,19 @@ TestBackend { "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, x: 1, y: 2, fg: Black, bg: Gray, underline: Reset, modifier: NONE, x: 24, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 24, fg: Reset, bg: Black, underline: Reset, modifier: NONE, ] }, scrollback: Buffer { diff --git a/tests/snapshots/ui_snapshots__home_screen_render.snap b/tests/snapshots/ui_snapshots__home_screen_render.snap index df0f123..c3e52fa 100644 --- a/tests/snapshots/ui_snapshots__home_screen_render.snap +++ b/tests/snapshots/ui_snapshots__home_screen_render.snap @@ -9,13 +9,12 @@ TestBackend { "β”Œ PDM β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œ Home ───────────────────────────────────────────────┐", "β”‚Home β”‚β”‚Welcome to PDM. β”‚", "β”‚Bitcoin Config β”‚β”‚ β”‚", - "β”‚P2Pool Config β”‚β”‚Select a config from the sidebar to edit. β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", - "β”‚ β”‚β”‚ β”‚", + "β”‚Bitcoin Status β”‚β”‚Select a config from the sidebar to edit. β”‚", + "β”‚P2Pool Config β”‚β”‚ β”‚", + "β”‚P2Pool Status β”‚β”‚ β”‚", + "β”‚LN Config β”‚β”‚ β”‚", + "β”‚LN Status β”‚β”‚ β”‚", + "β”‚Shares Market β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", @@ -31,11 +30,19 @@ TestBackend { "β”‚ β”‚β”‚ β”‚", "β”‚ β”‚β”‚ β”‚", "β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜", + " ↑↓ Navigate sidebar Enter Select q Quit ", ], styles: [ x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, x: 1, y: 1, fg: Black, bg: Gray, underline: Reset, modifier: NONE, x: 24, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 0, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 4, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 23, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 30, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 39, y: 24, fg: White, bg: DarkGray, underline: Reset, modifier: NONE, + x: 42, y: 24, fg: DarkGray, bg: Black, underline: Reset, modifier: NONE, + x: 49, y: 24, fg: Reset, bg: Black, underline: Reset, modifier: NONE, ] }, scrollback: Buffer {