constant 250ms tick rate
This commit is contained in:
parent
3d9dbc56c7
commit
7605dcf3b6
55
src/ui.rs
55
src/ui.rs
@ -9,7 +9,7 @@ pub mod title;
|
|||||||
use std::{
|
use std::{
|
||||||
io::Stdout,
|
io::Stdout,
|
||||||
sync::mpsc::{channel, Receiver, Sender},
|
sync::mpsc::{channel, Receiver, Sender},
|
||||||
thread,
|
thread, time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -136,23 +136,54 @@ fn draw(app_state: &AppState, terminal: &mut Terminal<CrosstermBackend<Stdout>>)
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Event {
|
||||||
|
UserInput(crossterm::event::Event),
|
||||||
|
ReloadState,
|
||||||
|
Tick,
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_events(state: &mut AppState, ctx: &TrsEnv) -> Result<()> {
|
fn handle_events(state: &mut AppState, ctx: &TrsEnv) -> Result<()> {
|
||||||
let recv_action = state.receiver.try_recv();
|
let event = get_event(state)?;
|
||||||
|
match event {
|
||||||
|
Event::UserInput(event) => {
|
||||||
|
handle_user_input(state, event)?;
|
||||||
|
}
|
||||||
|
Event::ReloadState => {
|
||||||
|
let channels = commands::list_channels(&ctx, &ListChannelArgs { limit: None })?;
|
||||||
|
state.channels = channels;
|
||||||
|
}
|
||||||
|
Event::Tick => {}
|
||||||
|
};
|
||||||
|
|
||||||
if let Ok(_) = recv_action {
|
Ok(())
|
||||||
let channels = commands::list_channels(&ctx, &ListChannelArgs { limit: None })?;
|
}
|
||||||
state.channels = channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
let raw_event = event::read().map_err(|e| TrsError::TuiError(e))?;
|
fn handle_user_input(state: &mut AppState, event: event::Event) -> Result<()> {
|
||||||
if state.show_add_channel_ui {
|
if state.show_add_channel_ui {
|
||||||
let event = controls::parse_popup_ui_action(raw_event);
|
let popup_ui_action = controls::parse_popup_ui_action(event);
|
||||||
return actions::handle_popup_action(state, event);
|
actions::handle_popup_action(state, popup_ui_action)?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let event = controls::parse_ui_action(raw_event);
|
let ui_action = controls::parse_ui_action(event);
|
||||||
state.last_action = Some(event.clone());
|
state.last_action = Some(ui_action.clone());
|
||||||
actions::handle_action(state, event)
|
actions::handle_action(state, ui_action)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event(state: &mut AppState) -> Result<Event> {
|
||||||
|
let recv_action = state.receiver.try_recv();
|
||||||
|
if let Ok(_) = recv_action {
|
||||||
|
return Ok(Event::ReloadState);
|
||||||
|
}
|
||||||
|
|
||||||
|
let raw_event = event::poll(Duration::from_millis(250)).map_err(|e| TrsError::TuiError(e))?;
|
||||||
|
if raw_event == false {
|
||||||
|
return Ok(Event::Tick);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's guaranteed that an event is available now
|
||||||
|
Ok(Event::UserInput(event::read().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AppStateWidget<'a> {
|
struct AppStateWidget<'a> {
|
||||||
|
|||||||
@ -60,13 +60,12 @@ pub fn handle_action(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
UiAction::ToggleReadStatus => {
|
UiAction::ToggleReadStatus => {
|
||||||
let article = get_highlighted_article_mut(app_state);
|
let article = get_highlighted_article(app_state);
|
||||||
let mut article_id = None;
|
let mut article_id = None;
|
||||||
let mut unread = None;
|
let mut unread = None;
|
||||||
if let Some(article) = article {
|
if let Some(article) = article {
|
||||||
article.unread = !article.unread;
|
unread = Some(!article.unread);
|
||||||
article_id = Some(article.id);
|
article_id = Some(article.id);
|
||||||
unread = Some(article.unread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(article_id) = article_id {
|
if let Some(article_id) = article_id {
|
||||||
@ -143,16 +142,10 @@ fn get_highlighted_channel<'a>(app_state: &'a AppState) -> Option<&'a RssChannel
|
|||||||
.and_then(|idx| app_state.channels.get(idx).or_else(|| None))
|
.and_then(|idx| app_state.channels.get(idx).or_else(|| None))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_highlighted_channel_mut<'a>(app_state: &'a mut AppState) -> Option<&'a mut RssChannelD> {
|
fn get_highlighted_article<'a>(app_state: &'a AppState) -> Option<&'a RssArticleD> {
|
||||||
app_state
|
|
||||||
.highlighted_channel
|
|
||||||
.and_then(|idx| app_state.channels.get_mut(idx).or_else(|| None))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_highlighted_article_mut<'a>(app_state: &'a mut AppState) -> Option<&'a mut RssArticleD> {
|
|
||||||
let hi_article = app_state.highlighted_article?;
|
let hi_article = app_state.highlighted_article?;
|
||||||
let channel = get_highlighted_channel_mut(app_state)?;
|
let channel = get_highlighted_channel(app_state)?;
|
||||||
channel.articles.get_mut(hi_article)
|
channel.articles.get(hi_article)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_entry_up(app_state: &mut AppState) {
|
fn focus_entry_up(app_state: &mut AppState) {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ pub struct TitleWidget;
|
|||||||
|
|
||||||
impl Widget for TitleWidget {
|
impl Widget for TitleWidget {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
let title = "Terminal RSS Reader";
|
let title = "Terminal RSS Manager";
|
||||||
let areas = Layout::default()
|
let areas = Layout::default()
|
||||||
.constraints(Constraint::from_ratios([(1, 3), (1, 3), (1, 3)]))
|
.constraints(Constraint::from_ratios([(1, 3), (1, 3), (1, 3)]))
|
||||||
.split(area)
|
.split(area)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user