refacotring and pain
This commit is contained in:
12
src/tui/component.rs
Normal file
12
src/tui/component.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
use ratatui::{layout::Rect, Frame};
|
||||||
|
|
||||||
|
pub trait Component {
|
||||||
|
/// The enum that represents what can happen in THIS component
|
||||||
|
type Msg;
|
||||||
|
|
||||||
|
/// Update the state based on a message
|
||||||
|
fn update(&mut self, msg: Self::Msg);
|
||||||
|
|
||||||
|
/// Render the component to the screen
|
||||||
|
fn view(&self, frame: &mut Frame);
|
||||||
|
}
|
||||||
21
src/tui/dashboard.rs
Normal file
21
src/tui/dashboard.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
use crate::component::Component;
|
||||||
|
use crossterm::event::Event;
|
||||||
|
use ratatui::{layout::Rect, text::Text, Frame};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MenuMsg {
|
||||||
|
MoveUp,
|
||||||
|
MoveDown,
|
||||||
|
Select,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
pub struct Menu;
|
||||||
|
impl Component for Menu {
|
||||||
|
type Msg = MenuMsg;
|
||||||
|
fn update(&mut self, msg: MenuMsg) {}
|
||||||
|
fn view(&self, f: &mut Frame) {
|
||||||
|
let text = Text::raw("meow");
|
||||||
|
f.render_widget(text, f.area());
|
||||||
|
}
|
||||||
|
}
|
||||||
110
src/tui/main.rs
110
src/tui/main.rs
@@ -5,92 +5,52 @@ use data::{ArchivedData, Data};
|
|||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{self, Constraint, Flex, Layout, Rect},
|
layout::{self, Constraint, Flex, Layout, Rect},
|
||||||
prelude::Stylize,
|
prelude::Stylize,
|
||||||
|
style::Style,
|
||||||
text::Text,
|
text::Text,
|
||||||
widgets::{Block, BorderType, Borders},
|
widgets::{Block, BorderType, Borders, Paragraph},
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
use rkyv::{deserialize, rancor};
|
use rkyv::{deserialize, rancor};
|
||||||
mod data_graph;
|
|
||||||
|
use crate::{
|
||||||
|
component::Component,
|
||||||
|
dashboard::{Menu, MenuMsg},
|
||||||
|
};
|
||||||
|
|
||||||
|
mod component;
|
||||||
|
mod dashboard;
|
||||||
|
|
||||||
|
// -- GLOBAL APP MESSAGE --
|
||||||
|
enum AppMsg {
|
||||||
|
Menu(MenuMsg), // Wraps the Menu's specific enum
|
||||||
|
GlobalQuit,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
struct Root {
|
struct App {
|
||||||
counter: i32,
|
menu: Menu,
|
||||||
running_state: RunningState,
|
should_quit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq)]
|
impl App {
|
||||||
enum RunningState {
|
// The "Update" part of TEA
|
||||||
#[default]
|
fn update(&mut self, msg: AppMsg) {
|
||||||
Running,
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
enum Message {
|
|
||||||
Increment,
|
|
||||||
Decrement,
|
|
||||||
Reset,
|
|
||||||
Quit,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Root {
|
|
||||||
fn view(&self, f: &mut Frame) {
|
|
||||||
let text = Text::raw("Meow");
|
|
||||||
let block = Block::new().borders(Borders::ALL).title("Meow");
|
|
||||||
let vertical_layout = Layout::vertical([Constraint::Max(50)])
|
|
||||||
.flex(Flex::Center)
|
|
||||||
.split(f.area());
|
|
||||||
|
|
||||||
let area = Layout::horizontal([Constraint::Max(50)])
|
|
||||||
.flex(Flex::Center)
|
|
||||||
.split(vertical_layout[0])[0];
|
|
||||||
f.render_widget(block, area);
|
|
||||||
}
|
|
||||||
fn handle_events() -> Result<Option<Message>, Box<dyn Error>> {
|
|
||||||
if event::poll(Duration::from_millis(250))? {
|
|
||||||
if let Ok(Event::Key(key)) = event::read() {
|
|
||||||
return Ok(Self::handle_key(key));
|
|
||||||
}
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
fn handle_key(key: event::KeyEvent) -> Option<Message> {
|
|
||||||
match key.code {
|
|
||||||
KeyCode::Up => Some(Message::Increment),
|
|
||||||
KeyCode::Down => Some(Message::Decrement),
|
|
||||||
KeyCode::Esc => Some(Message::Quit),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn update(&mut self) -> Result<(), Box<dyn Error>> {
|
|
||||||
if let Ok(msg) = Self::handle_events() {
|
|
||||||
if let Some(msg) = msg {
|
|
||||||
match msg {
|
match msg {
|
||||||
Message::Increment => self.counter += 1,
|
AppMsg::Menu(child_msg) => self.menu.update(child_msg),
|
||||||
Message::Decrement => self.counter -= 1,
|
AppMsg::GlobalQuit => self.should_quit = true,
|
||||||
Message::Reset => unimplemented!(),
|
|
||||||
Message::Quit => self.running_state = RunningState::Done,
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
} else {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("Failed to process event");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
// The "View" part of TEA
|
||||||
let mut app = Root::default();
|
fn view(&self, f: &mut Frame) {
|
||||||
ratatui::run(|terminal| {
|
// Centering logic we discussed earlier!
|
||||||
while app.running_state == RunningState::Running {
|
self.menu.view(f);
|
||||||
terminal.draw(|frame| {
|
|
||||||
app.view(frame);
|
|
||||||
})?;
|
|
||||||
app.update()?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
}
|
||||||
})
|
|
||||||
|
fn main() {
|
||||||
|
let app: App = App::default();
|
||||||
|
ratatui::run(|terminal| loop {
|
||||||
|
terminal.draw(|f| app.view(f));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user