basic ui
This commit is contained in:
parent
7a59d51311
commit
c15745b156
@ -5,16 +5,25 @@ use crate::{
|
||||
persistence::Db,
|
||||
};
|
||||
|
||||
pub fn execute(mut db: Db, args: &TrsArgs) -> Result<(), TrsError> {
|
||||
let sub_command = &args.sub_command;
|
||||
match sub_command {
|
||||
TrsSubCommand::AddChannel(add_args) => add_channel(&mut db, add_args),
|
||||
TrsSubCommand::ListChannels(list_args) => list_channels(&mut db, list_args),
|
||||
TrsSubCommand::RemoveChannel(delete_args) => delete_channel(&mut db, delete_args),
|
||||
pub struct RssChannelD {
|
||||
pub id: i64,
|
||||
pub title: String,
|
||||
pub link: String,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
impl RssChannelD {
|
||||
fn new(id: i64, title: String, link: String, description: String) -> Self {
|
||||
RssChannelD {
|
||||
id,
|
||||
title,
|
||||
link,
|
||||
description,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_channel(db: &mut Db, args: &AddChannelArgs) -> Result<(), TrsError> {
|
||||
pub fn add_channel(db: &mut Db, args: &AddChannelArgs) -> Result<(), TrsError> {
|
||||
let client = reqwest::blocking::Client::new();
|
||||
let rss = client.get(&args.link).send().map_err(|e| {
|
||||
TrsError::ReqwestError(
|
||||
@ -39,7 +48,7 @@ fn add_channel(db: &mut Db, args: &AddChannelArgs) -> Result<(), TrsError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list_channels(conn: &mut Db, args: &ListChannelArgs) -> Result<(), TrsError> {
|
||||
pub fn list_channels(conn: &mut Db, args: &ListChannelArgs) -> Result<Vec<RssChannelD>, TrsError> {
|
||||
let channels_iter =
|
||||
conn.list_channels
|
||||
.query_map([args.limit.unwrap_or_else(|| 999)], |row| {
|
||||
@ -51,18 +60,18 @@ fn list_channels(conn: &mut Db, args: &ListChannelArgs) -> Result<(), TrsError>
|
||||
))
|
||||
})?;
|
||||
|
||||
let mut channels = Vec::new();
|
||||
|
||||
for row in channels_iter {
|
||||
let (id, name, link, description) = row?;
|
||||
println!(
|
||||
"ID: {}, Name: {}, Link: {}, Description: {}",
|
||||
id, name, link, description
|
||||
);
|
||||
let channel = RssChannelD::new(id, name, link, description);
|
||||
channels.push(channel);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(channels)
|
||||
}
|
||||
|
||||
fn delete_channel(db: &mut Db, args: &RemoveChannelArgs) -> Result<(), TrsError> {
|
||||
pub fn remove_channel(db: &mut Db, args: &RemoveChannelArgs) -> Result<(), TrsError> {
|
||||
let rows_affected = db
|
||||
.remove_channel
|
||||
.execute([args.id])
|
||||
|
24
src/main.rs
24
src/main.rs
@ -1,4 +1,4 @@
|
||||
use args::TrsArgs;
|
||||
use args::{TrsArgs, TrsSubCommand};
|
||||
use error::Result;
|
||||
pub mod args;
|
||||
pub mod commands;
|
||||
@ -10,16 +10,26 @@ pub mod ui;
|
||||
fn main() -> Result<()> {
|
||||
if std::env::args().len() < 2 {
|
||||
let terminal = ratatui::init();
|
||||
ui::ui(terminal)?;
|
||||
let conn = persistence::init_connection()?;
|
||||
let db = persistence::init_db(&conn)?;
|
||||
ui::ui(db, terminal)?;
|
||||
ratatui::restore();
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let args = argh::from_env::<TrsArgs>();
|
||||
let conn = persistence::init_connection()?;
|
||||
let db = persistence::init_db(&conn)?;
|
||||
commands::execute(db, &args).map_err(|e| {
|
||||
eprintln!("Error executing command: {}", e);
|
||||
e
|
||||
})
|
||||
let mut db = persistence::init_db(&conn)?;
|
||||
match args.sub_command {
|
||||
TrsSubCommand::AddChannel(args) => commands::add_channel(&mut db, &args),
|
||||
TrsSubCommand::ListChannels(args) => {
|
||||
let channels = commands::list_channels(&mut db, &args)?;
|
||||
for channel in channels {
|
||||
println!("{}: {} ({})", channel.id, channel.title, channel.link);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
TrsSubCommand::RemoveChannel(args) => commands::remove_channel(&mut db, &args),
|
||||
}
|
||||
}
|
||||
|
95
src/ui.rs
95
src/ui.rs
@ -1,29 +1,110 @@
|
||||
use std::io::Stdout;
|
||||
|
||||
use crate::error::{Result, TrsError};
|
||||
use crate::{
|
||||
args::ListChannelArgs,
|
||||
commands::{self, RssChannelD},
|
||||
error::{Result, TrsError},
|
||||
persistence::Db,
|
||||
};
|
||||
use crossterm::event::{self, Event, KeyEventKind};
|
||||
use ratatui::{prelude::CrosstermBackend, Terminal};
|
||||
use ratatui::{
|
||||
prelude::*,
|
||||
widgets::{Block, Borders, Paragraph},
|
||||
};
|
||||
|
||||
struct ChannelsWidget<'a> {
|
||||
channels: &'a Vec<RssChannelD>,
|
||||
}
|
||||
|
||||
impl<'a> Widget for ChannelsWidget<'a> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let columns = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints(vec![
|
||||
Constraint::Length(5),
|
||||
Constraint::Length(50),
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(5),
|
||||
])
|
||||
.split(area);
|
||||
|
||||
let rows = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(vec![
|
||||
Constraint::Length(3),
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(5),
|
||||
])
|
||||
.split(columns[1]);
|
||||
|
||||
let channel_rows = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(vec![Constraint::Length(1); 10])
|
||||
.split(rows[1])
|
||||
.to_vec();
|
||||
|
||||
Block::default()
|
||||
.borders(Borders::RIGHT)
|
||||
.render(rows[1], buf);
|
||||
|
||||
for (row, channel) in channel_rows.into_iter().zip(self.channels) {
|
||||
let id = Span::styled(
|
||||
format!("{}. ", channel.id),
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
);
|
||||
let title = Span::styled(
|
||||
channel.title.clone(),
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
);
|
||||
let line = Line::from(vec![id, title]);
|
||||
let para = Paragraph::new(line).block(Block::default());
|
||||
para.render(row, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AppState {
|
||||
exit: bool,
|
||||
channels: Vec<RssChannelD>,
|
||||
}
|
||||
|
||||
pub fn ui(mut terminal: Terminal<CrosstermBackend<Stdout>>) -> Result<()> {
|
||||
let mut app_state = AppState { exit: false };
|
||||
pub fn ui(mut db: Db, mut terminal: Terminal<CrosstermBackend<Stdout>>) -> Result<()> {
|
||||
let mut app_state = AppState {
|
||||
channels: Vec::new(),
|
||||
exit: false,
|
||||
};
|
||||
|
||||
let channels = commands::list_channels(&mut db, &ListChannelArgs { limit: None })?;
|
||||
app_state.channels = channels;
|
||||
|
||||
loop {
|
||||
draw(&app_state, &mut terminal)?;
|
||||
|
||||
handle_events(&mut app_state)?;
|
||||
|
||||
if app_state.exit {
|
||||
break;
|
||||
}
|
||||
|
||||
draw(&app_state, &mut terminal)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw(app_state: &AppState, terminal: &mut Terminal<CrosstermBackend<Stdout>>) -> Result<()> {
|
||||
todo!()
|
||||
terminal
|
||||
.draw(|f| {
|
||||
let channel_widget = ChannelsWidget {
|
||||
channels: &app_state.channels,
|
||||
};
|
||||
|
||||
f.render_widget(channel_widget, f.area());
|
||||
})
|
||||
.map_err(|e| TrsError::TuiError(e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_events(state: &mut AppState) -> Result<()> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user