use crate::{
config::{self, Theme},
key,
ui::{self, Orientation},
utils::filtered_items_from_query,
};
pub type UIStateGuard<'a> = parking_lot::MutexGuard<'a, UIState>;
mod page;
mod popup;
pub use page::*;
pub use popup::*;
#[derive(Default, Debug)]
#[cfg(feature = "image")]
pub struct ImageRenderInfo {
pub url: String,
pub render_area: ratatui::layout::Rect,
pub rendered: bool,
}
#[derive(Debug)]
pub struct UIState {
pub is_running: bool,
pub theme: config::Theme,
pub input_key_sequence: key::KeySequence,
pub orientation: ui::Orientation,
pub history: Vec<PageState>,
pub popup: Option<PopupState>,
pub playback_progress_bar_rect: ratatui::layout::Rect,
pub count_prefix: Option<usize>,
#[cfg(feature = "image")]
pub last_cover_image_render_info: ImageRenderInfo,
}
impl UIState {
pub fn current_page(&self) -> &PageState {
self.history.last().expect("non-empty history")
}
pub fn current_page_mut(&mut self) -> &mut PageState {
self.history.last_mut().expect("non-empty history")
}
pub fn new_search_popup(&mut self) {
self.current_page_mut().select(0);
self.popup = Some(PopupState::Search {
query: String::new(),
});
}
pub fn new_page(&mut self, page: PageState) {
self.history.push(page);
self.popup = None;
}
pub fn has_focused_popup(&self) -> bool {
match self.popup.as_ref() {
None => false,
Some(popup) => !matches!(popup, PopupState::Search { .. }),
}
}
pub fn search_filtered_items<'a, T: std::fmt::Display>(&self, items: &'a [T]) -> Vec<&'a T> {
match self.popup {
Some(PopupState::Search { ref query }) => filtered_items_from_query(query, items),
_ => items.iter().collect::<Vec<_>>(),
}
}
}
use ratatui::layout::Rect;
impl Default for UIState {
fn default() -> Self {
Self {
is_running: true,
theme: Theme::default(),
input_key_sequence: key::KeySequence { keys: vec![] },
orientation: match crossterm::terminal::size() {
Ok((columns, rows)) => ui::Orientation::from_size(columns, rows),
Err(err) => {
tracing::warn!("Unable to get terminal size, error: {err:#}");
Orientation::default()
}
},
history: vec![PageState::Library {
state: LibraryPageUIState::new(),
}],
popup: None,
playback_progress_bar_rect: Rect::default(),
count_prefix: None,
#[cfg(feature = "image")]
last_cover_image_render_info: ImageRenderInfo::default(),
}
}
}