constant 250ms tick rate

This commit is contained in:
cool-mist 2025-08-31 22:16:21 +05:30
parent 3d9dbc56c7
commit 7605dcf3b6
3 changed files with 49 additions and 25 deletions

View File

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

View File

@ -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) {

View File

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