feat: run the tui

This commit is contained in:
uttarayan21
2025-10-08 14:58:33 +05:30
parent 3cb82612be
commit c18e92ff01
4 changed files with 49 additions and 48 deletions

View File

@@ -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;

View File

@@ -1,3 +0,0 @@
pub mod errors;
use errors::*;
mod api;

View File

@@ -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(())
}

View File

@@ -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,20 +846,22 @@ fn render_queue_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
})
.collect();
let table = Table::new(rows)
let table = Table::new(
rows,
&[
Constraint::Percentage(40),
Constraint::Percentage(15),
Constraint::Percentage(15),
Constraint::Percentage(15),
Constraint::Percentage(15),
],
)
.header(header.style(Style::default().fg(Color::Yellow)))
.block(
Block::default()
.borders(Borders::ALL)
.title("Download Queue"),
)
.widths(&[
Constraint::Percentage(40),
Constraint::Percentage(15),
Constraint::Percentage(15),
Constraint::Percentage(15),
Constraint::Percentage(15),
])
.highlight_style(
Style::default()
.fg(Color::Yellow)
@@ -869,7 +871,7 @@ fn render_queue_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
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,22 +912,24 @@ 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),
])
],
)
.header(header.style(Style::default().fg(Color::Yellow)))
.block(Block::default().borders(Borders::ALL).title("History"))
.highlight_style(
Style::default()
.fg(Color::Yellow)
@@ -935,7 +939,7 @@ fn render_history_tab<B: Backend>(f: &mut Frame<B>, area: Rect, app: &App) {
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);