feat: run the tui
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
pub use error_stack::{Report, ResultExt};
|
||||
// Removed unused imports Report and ResultExt
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("An error occurred")]
|
||||
pub struct Error;
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
pub mod errors;
|
||||
use errors::*;
|
||||
mod api;
|
||||
@@ -2,10 +2,10 @@ mod api;
|
||||
mod cli;
|
||||
mod errors;
|
||||
mod tui;
|
||||
use errors::*;
|
||||
|
||||
use crate::api::SonarrClient;
|
||||
pub fn main() -> Result<()> {
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// let args = <cli::Cli as clap::Parser>::parse();
|
||||
// match args.cmd {
|
||||
// cli::SubCommand::Add(add) => {
|
||||
@@ -23,6 +23,6 @@ pub fn main() -> Result<()> {
|
||||
"https://sonarr.tsuba.darksailor.dev".into(),
|
||||
"1a47401731bf44ae9787dfcd4bab402f".into(),
|
||||
);
|
||||
tui::run_app(client);
|
||||
tui::run_app(client).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
84
src/tui.rs
84
src/tui.rs
@@ -7,10 +7,10 @@ use ratatui::{
|
||||
backend::{Backend, CrosstermBackend},
|
||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||
style::{Color, Modifier, Style},
|
||||
text::{Line, Span, Text},
|
||||
text::{Line, Span},
|
||||
widgets::{
|
||||
Block, Borders, Cell, Clear, Gauge, List, ListItem, ListState, Paragraph, Row, Table,
|
||||
TableState, Tabs, Wrap,
|
||||
Block, Borders, Cell, Clear, List, ListItem, ListState, Paragraph, Row, Table, TableState,
|
||||
Tabs, Wrap,
|
||||
},
|
||||
Frame, Terminal,
|
||||
};
|
||||
@@ -649,8 +649,8 @@ async fn handle_input(
|
||||
}
|
||||
}
|
||||
|
||||
fn ui<B: Backend>(f: &mut Frame<B>, app: &App) {
|
||||
let size = f.size();
|
||||
fn ui(f: &mut Frame, app: &App) {
|
||||
let size = f.area();
|
||||
|
||||
// Create main layout
|
||||
let chunks = Layout::default()
|
||||
@@ -684,7 +684,7 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &App) {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_header<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_header(f: &mut Frame, area: Rect, app: &App) {
|
||||
let tabs = Tabs::new(TabIndex::titles())
|
||||
.block(
|
||||
Block::default()
|
||||
@@ -702,7 +702,7 @@ fn render_header<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
f.render_widget(tabs, area);
|
||||
}
|
||||
|
||||
fn render_series_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_series_tab(f: &mut Frame, area: Rect, app: &App) {
|
||||
if app.series.is_empty() {
|
||||
let loading_text = if app.loading {
|
||||
"Loading series..."
|
||||
@@ -745,7 +745,7 @@ fn render_series_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
f.render_stateful_widget(list, area, &mut app.series_list_state.clone());
|
||||
}
|
||||
|
||||
fn render_calendar_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_calendar_tab(f: &mut Frame, area: Rect, app: &App) {
|
||||
if app.calendar.is_empty() {
|
||||
let loading_text = if app.loading {
|
||||
"Loading calendar..."
|
||||
@@ -801,7 +801,7 @@ fn render_calendar_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
f.render_stateful_widget(list, area, &mut app.episodes_list_state.clone());
|
||||
}
|
||||
|
||||
fn render_queue_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_queue_tab(f: &mut Frame, area: Rect, app: &App) {
|
||||
if app.queue.is_empty() {
|
||||
let loading_text = if app.loading {
|
||||
"Loading queue..."
|
||||
@@ -838,7 +838,7 @@ fn render_queue_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
|
||||
Row::new(vec![
|
||||
Cell::from(title),
|
||||
Cell::from(status),
|
||||
Cell::from(status.as_str()),
|
||||
Cell::from(progress),
|
||||
Cell::from(quality),
|
||||
Cell::from(size),
|
||||
@@ -846,30 +846,32 @@ fn render_queue_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let table = Table::new(rows)
|
||||
.header(header.style(Style::default().fg(Color::Yellow)))
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.title("Download Queue"),
|
||||
)
|
||||
.widths(&[
|
||||
let table = Table::new(
|
||||
rows,
|
||||
&[
|
||||
Constraint::Percentage(40),
|
||||
Constraint::Percentage(15),
|
||||
Constraint::Percentage(15),
|
||||
Constraint::Percentage(15),
|
||||
Constraint::Percentage(15),
|
||||
])
|
||||
.highlight_style(
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
);
|
||||
],
|
||||
)
|
||||
.header(header.style(Style::default().fg(Color::Yellow)))
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.title("Download Queue"),
|
||||
)
|
||||
.highlight_style(
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
);
|
||||
|
||||
f.render_stateful_widget(table, area, &mut app.queue_table_state.clone());
|
||||
}
|
||||
|
||||
fn render_history_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_history_tab(f: &mut Frame, area: Rect, app: &App) {
|
||||
if app.history.is_empty() {
|
||||
let loading_text = if app.loading {
|
||||
"Loading history..."
|
||||
@@ -910,32 +912,34 @@ fn render_history_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
Cell::from(date),
|
||||
Cell::from(series),
|
||||
Cell::from(episode),
|
||||
Cell::from(event),
|
||||
Cell::from(event.as_str()),
|
||||
Cell::from(quality),
|
||||
])
|
||||
})
|
||||
.collect();
|
||||
|
||||
let table = Table::new(rows)
|
||||
.header(header.style(Style::default().fg(Color::Yellow)))
|
||||
.block(Block::default().borders(Borders::ALL).title("History"))
|
||||
.widths(&[
|
||||
let table = Table::new(
|
||||
rows,
|
||||
&[
|
||||
Constraint::Percentage(20),
|
||||
Constraint::Percentage(30),
|
||||
Constraint::Percentage(15),
|
||||
Constraint::Percentage(20),
|
||||
Constraint::Percentage(15),
|
||||
])
|
||||
.highlight_style(
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
);
|
||||
],
|
||||
)
|
||||
.header(header.style(Style::default().fg(Color::Yellow)))
|
||||
.block(Block::default().borders(Borders::ALL).title("History"))
|
||||
.highlight_style(
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
);
|
||||
|
||||
f.render_stateful_widget(table, area, &mut app.history_table_state.clone());
|
||||
}
|
||||
|
||||
fn render_health_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_health_tab(f: &mut Frame, area: Rect, app: &App) {
|
||||
if app.health.is_empty() {
|
||||
let loading_text = if app.loading {
|
||||
"Loading health status..."
|
||||
@@ -990,7 +994,7 @@ fn render_health_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
f.render_stateful_widget(list, area, &mut app.health_list_state.clone());
|
||||
}
|
||||
|
||||
fn render_search_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_search_tab(f: &mut Frame, area: Rect, app: &App) {
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Length(3), Constraint::Min(0)])
|
||||
@@ -1068,7 +1072,7 @@ fn render_search_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_footer<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_footer(f: &mut Frame, area: Rect, app: &App) {
|
||||
let help_text = if app.input_mode {
|
||||
"ESC: Cancel | Enter: Search | Type to enter search term"
|
||||
} else {
|
||||
@@ -1100,7 +1104,7 @@ fn render_footer<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
f.render_widget(paragraph, area);
|
||||
}
|
||||
|
||||
fn render_error_popup<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
|
||||
fn render_error_popup(f: &mut Frame, area: Rect, app: &App) {
|
||||
if let Some(error) = &app.error_message {
|
||||
let popup_area = centered_rect(60, 20, area);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user