aboutsummaryrefslogtreecommitdiff
path: root/src/screens
diff options
context:
space:
mode:
Diffstat (limited to 'src/screens')
-rw-r--r--src/screens/available_packages.rs95
-rw-r--r--src/screens/dashboard.rs31
-rw-r--r--src/screens/installed_packages.rs116
-rw-r--r--src/screens/screen.rs11
4 files changed, 143 insertions, 110 deletions
diff --git a/src/screens/available_packages.rs b/src/screens/available_packages.rs
index 1f61982..46d9f39 100644
--- a/src/screens/available_packages.rs
+++ b/src/screens/available_packages.rs
@@ -13,7 +13,7 @@ use crate::{
app::LoadingState,
gentoo::package::{Package, PackageKey, PackageVersion},
screens::screen::Screen,
- signal::Signal,
+ signal::{Event, Signal},
theme::Theme,
widgets::{package_metadata::render_package_metadata, use_flags::render_use_flags},
};
@@ -28,8 +28,12 @@ enum CurrentList {
pub struct AvailablePackagesScreen {
chosen_list: CurrentList,
+ pkg_list: Option<List<'static>>,
pkg_list_state: ListState,
+
variant_list_state: ListState,
+
+ loading_state: LoadingState,
}
fn version_to_variant(pkg_version: &PackageVersion) -> String {
@@ -41,20 +45,12 @@ fn version_to_variant(pkg_version: &PackageVersion) -> String {
impl AvailablePackagesScreen {
// TODO: this is the same as InstalledPackagesScreen, replace this with a widget function
- fn render_packages(&mut self, frame: &mut Frame, area: Rect, package_keys: Vec<String>) {
+ fn render_packages(&mut self, frame: &mut Frame, area: Rect) {
// TODO: Put this into screen, instead of rebuilding the list every frame
- let list = List::new(package_keys)
- .style(Color::White)
- .highlight_style(Theme::selected())
- .highlight_symbol("> ")
- .block(
- Block::default()
- .borders(Borders::ALL)
- .border_style(Theme::block())
- .title("Available packages"),
- );
- frame.render_stateful_widget(list, area, &mut self.pkg_list_state);
+ if let Some(list) = &self.pkg_list {
+ frame.render_stateful_widget(list, area, &mut self.pkg_list_state);
+ }
}
fn render_package_variants(
@@ -98,8 +94,10 @@ impl Default for AvailablePackagesScreen {
Self {
chosen_list: CurrentList::PackageList,
+ pkg_list: None,
pkg_list_state: list_state,
variant_list_state: variant_state,
+ loading_state: LoadingState::Idle,
}
}
}
@@ -110,9 +108,8 @@ impl Screen for AvailablePackagesScreen {
frame: &mut ratatui::Frame,
area: ratatui::prelude::Rect,
repo: &crate::gentoo::Portage,
- loading_state: &crate::app::LoadingState,
) {
- if !matches!(loading_state, LoadingState::Complete) {
+ if !matches!(self.loading_state, LoadingState::Complete) {
// TODO: Implement loading screen
frame.render_widget(Text::styled("Not implemented yet :P", Theme::text()), area);
return;
@@ -133,11 +130,7 @@ impl Screen for AvailablePackagesScreen {
None => None,
};
- self.render_packages(
- frame,
- package_list,
- packages.iter().map(|x| x.qualified_name()).collect(),
- );
+ self.render_packages(frame, package_list);
if let Some(pkg) = pkg {
self.render_package_variants(frame, package_variants, pkg.versions.iter().collect());
@@ -165,30 +158,58 @@ impl Screen for AvailablePackagesScreen {
fn update(
&mut self,
- key: ratatui::crossterm::event::KeyEvent,
- _repo: &crate::gentoo::Portage,
+ event: &Event,
+ repo: &crate::gentoo::Portage,
) -> Option<crate::signal::Signal> {
- match key.code {
- KeyCode::Char('q') => return Some(Signal::Quit),
- KeyCode::Tab => return Some(Signal::CycleTab),
+ match event {
+ Event::KeyEvent(key) => match key.code {
+ KeyCode::Char('q') => return Some(Signal::Quit),
+ KeyCode::Tab => return Some(Signal::CycleTab),
- // TODO: This should cycle, also space isnt a good key for this
- KeyCode::Char(' ') => self.cycle_list(),
+ // TODO: This should cycle, also space isnt a good key for this
+ KeyCode::Char(' ') => self.cycle_list(),
- _ => match self.chosen_list {
- CurrentList::PackageList => match key.code {
- KeyCode::Char('j') => self.pkg_list_state.select_next(),
- KeyCode::Char('k') => self.pkg_list_state.select_previous(),
+ _ => match self.chosen_list {
+ CurrentList::PackageList => match key.code {
+ KeyCode::Char('j') => self.pkg_list_state.select_next(),
+ KeyCode::Char('k') => self.pkg_list_state.select_previous(),
- _ => {}
- },
- CurrentList::VariantList => match key.code {
- KeyCode::Char('j') => self.variant_list_state.select_next(),
- KeyCode::Char('k') => self.variant_list_state.select_previous(),
+ _ => {}
+ },
+ CurrentList::VariantList => match key.code {
+ KeyCode::Char('j') => self.variant_list_state.select_next(),
+ KeyCode::Char('k') => self.variant_list_state.select_previous(),
- _ => {}
+ _ => {}
+ },
},
},
+ Event::LoadStateUpdate(loading_state) => match loading_state {
+ LoadingState::Complete => {
+ let packages: Vec<String> = repo
+ .available_packages()
+ .iter()
+ .map(|x| &x.atom)
+ .map(|x| x.qualified_name())
+ .collect();
+
+ let list = List::new(packages)
+ .style(Color::White)
+ .highlight_style(Theme::selected())
+ .highlight_symbol("> ")
+ .block(
+ Block::default()
+ .borders(Borders::ALL)
+ .border_style(Theme::block())
+ .title("Available packages"),
+ );
+
+ self.pkg_list = Some(list);
+ self.loading_state = LoadingState::Complete
+ }
+
+ loading_state => self.loading_state = *loading_state,
+ },
}
None
diff --git a/src/screens/dashboard.rs b/src/screens/dashboard.rs
index 1fcb242..e000052 100644
--- a/src/screens/dashboard.rs
+++ b/src/screens/dashboard.rs
@@ -6,12 +6,18 @@ use ratatui::{
};
use crate::{
- app::LoadingState, gentoo::Portage, screens::screen::Screen, signal::Signal, theme::Theme,
+ app::LoadingState,
+ gentoo::Portage,
+ screens::screen::Screen,
+ signal::{Event, Signal},
+ theme::Theme,
widgets::helpers::human_size,
};
#[derive(Debug, Default)]
-pub struct DashboardScreen {}
+pub struct DashboardScreen {
+ loading_state: LoadingState,
+}
fn create_stats<'a>(title: &'a str, value: &'a str) -> Paragraph<'a> {
Paragraph::new(vec![
@@ -35,7 +41,6 @@ impl Screen for DashboardScreen {
frame: &mut ratatui::Frame,
area: ratatui::prelude::Rect,
repo: &crate::gentoo::Portage,
- loading_state: &LoadingState,
) {
let logo = "
██████╗ ██╗ ██╗██╗███████╗██╗ ██╗
@@ -123,7 +128,7 @@ impl Screen for DashboardScreen {
let keys_text = "(q) to quit | (tab) to cycle tabs";
- let loading_text = match loading_state {
+ let loading_text = match self.loading_state {
LoadingState::Loading => "⟳ Loading available packages...",
LoadingState::Error => "⚠ Failed to load available packages",
LoadingState::Complete => "✓ Available packages loaded",
@@ -137,7 +142,7 @@ impl Screen for DashboardScreen {
Span::raw(" | "),
Span::styled(
loading_text,
- match loading_state {
+ match self.loading_state {
crate::app::LoadingState::Loading => Theme::muted(),
crate::app::LoadingState::Error => Theme::error(),
crate::app::LoadingState::Complete => Theme::success(),
@@ -157,12 +162,18 @@ impl Screen for DashboardScreen {
frame.render_widget(key_notes, key_hints);
}
- fn update(&mut self, key: ratatui::crossterm::event::KeyEvent, _: &Portage) -> Option<Signal> {
- match key.code {
- KeyCode::Char('q') => Some(Signal::Quit),
- KeyCode::Tab => Some(Signal::CycleTab),
+ fn update(&mut self, event: &Event, _: &Portage) -> Option<Signal> {
+ match event {
+ Event::KeyEvent(key) => match key.code {
+ KeyCode::Char('q') => Some(Signal::Quit),
+ KeyCode::Tab => Some(Signal::CycleTab),
- _ => None,
+ _ => None,
+ },
+ Event::LoadStateUpdate(loading_state) => {
+ self.loading_state = *loading_state;
+ None
+ }
}
}
}
diff --git a/src/screens/installed_packages.rs b/src/screens/installed_packages.rs
index 8f0cc5d..1b0061a 100644
--- a/src/screens/installed_packages.rs
+++ b/src/screens/installed_packages.rs
@@ -1,6 +1,6 @@
use ratatui::{
Frame,
- crossterm::event::{KeyCode, KeyEvent, KeyModifiers},
+ crossterm::event::{KeyCode, KeyModifiers},
layout::{Constraint, Layout, Rect},
style::{Color, Modifier, Style},
text::{Line, Span},
@@ -9,10 +9,9 @@ use ratatui::{
use ratatui_textarea::TextArea;
use crate::{
- app::LoadingState,
gentoo::{InstalledPackage, Portage, package::PackageKey},
screens::screen::Screen,
- signal::Signal,
+ signal::{Event, Signal},
theme::Theme,
widgets::{
helpers::search_popup_rect, package_metadata::render_package_metadata,
@@ -131,13 +130,7 @@ impl Default for InstalledPackagesScreen {
}
impl Screen for InstalledPackagesScreen {
- fn draw(
- &mut self,
- frame: &mut Frame,
- area: Rect,
- repo: &Portage,
- _loading_state: &LoadingState,
- ) {
+ fn draw(&mut self, frame: &mut Frame, area: Rect, repo: &Portage) {
let constraints = [Constraint::Fill(1), Constraint::Length(3)];
let layout = Layout::vertical(constraints);
@@ -243,66 +236,71 @@ impl Screen for InstalledPackagesScreen {
}
}
- fn update(&mut self, key: KeyEvent, repo: &Portage) -> Option<Signal> {
- if self.search_popup.visible {
- let packages = match self.filter_state {
- FilterState::Unfiltered => repo.installed_packages(),
- FilterState::WorldSet => repo.world_packages(),
- };
+ fn update(&mut self, event: &Event, repo: &Portage) -> Option<Signal> {
+ match event {
+ Event::KeyEvent(key) => {
+ if self.search_popup.visible {
+ let packages = match self.filter_state {
+ FilterState::Unfiltered => repo.installed_packages(),
+ FilterState::WorldSet => repo.world_packages(),
+ };
- match key.code {
- KeyCode::Esc => self.search_popup.toggle(),
- KeyCode::Enter => {
- let result = self.search_popup.search(packages);
- self.search_popup.toggle();
+ match key.code {
+ KeyCode::Esc => self.search_popup.toggle(),
+ KeyCode::Enter => {
+ let result = self.search_popup.search(packages);
+ self.search_popup.toggle();
- if let Some(index) = result {
- self.list_state.select(Some(index));
- }
- }
- _ => {
- self.search_popup.textarea.input_without_shortcuts(key);
- let result = self.search_popup.search(packages);
+ if let Some(index) = result {
+ self.list_state.select(Some(index));
+ }
+ }
+ _ => {
+ self.search_popup.textarea.input_without_shortcuts(*key);
+ let result = self.search_popup.search(packages);
- if let Some(index) = result {
- self.list_state.select(Some(index));
- }
- }
- }
- } else {
- match key.modifiers {
- KeyModifiers::CONTROL => match key.code {
- KeyCode::Char('d') => self
- .list_state
- .select(Some(self.list_state.selected().unwrap_or(0) + 30)),
- KeyCode::Char('u') => {
- if let Some(selected) = self.list_state.selected() {
- if selected < 30 {
- self.list_state.select(Some(0));
- } else {
- self.list_state.select(Some(selected - 30));
+ if let Some(index) = result {
+ self.list_state.select(Some(index));
}
}
}
+ } else {
+ match key.modifiers {
+ KeyModifiers::CONTROL => match key.code {
+ KeyCode::Char('d') => self
+ .list_state
+ .select(Some(self.list_state.selected().unwrap_or(0) + 30)),
+ KeyCode::Char('u') => {
+ if let Some(selected) = self.list_state.selected() {
+ if selected < 30 {
+ self.list_state.select(Some(0));
+ } else {
+ self.list_state.select(Some(selected - 30));
+ }
+ }
+ }
- _ => {}
- },
+ _ => {}
+ },
- _ => match key.code {
- KeyCode::Char('q') => return Some(Signal::Quit),
- KeyCode::Tab => return Some(Signal::CycleTab),
- KeyCode::Char('j') => self.list_state.select_next(),
- KeyCode::Char('k') => self.list_state.select_previous(),
- KeyCode::Char('/') => self.search_popup.toggle(),
+ _ => match key.code {
+ KeyCode::Char('q') => return Some(Signal::Quit),
+ KeyCode::Tab => return Some(Signal::CycleTab),
+ KeyCode::Char('j') => self.list_state.select_next(),
+ KeyCode::Char('k') => self.list_state.select_previous(),
+ KeyCode::Char('/') => self.search_popup.toggle(),
- // TODO: Reimplement searchable "spaces"
- // KeyCode::Char('n') => todo!("Next search"),
- // KeyCode::Char('N') => todo!("prev search"),
- KeyCode::Char('f') => self.cycle_filter(),
+ // TODO: Reimplement searchable "spaces"
+ // KeyCode::Char('n') => todo!("Next search"),
+ // KeyCode::Char('N') => todo!("prev search"),
+ KeyCode::Char('f') => self.cycle_filter(),
- _ => {}
- },
+ _ => {}
+ },
+ }
+ }
}
+ Event::LoadStateUpdate(_) => {}
}
None
diff --git a/src/screens/screen.rs b/src/screens/screen.rs
index 8e7449c..e1bb732 100644
--- a/src/screens/screen.rs
+++ b/src/screens/screen.rs
@@ -1,8 +1,11 @@
-use ratatui::{Frame, crossterm::event::KeyEvent, layout::Rect};
+use ratatui::{Frame, layout::Rect};
-use crate::{app::LoadingState, gentoo::Portage, signal::Signal};
+use crate::{
+ gentoo::Portage,
+ signal::{Event, Signal},
+};
pub(crate) trait Screen {
- fn draw(&mut self, frame: &mut Frame, area: Rect, repo: &Portage, loading_state: &LoadingState);
- fn update(&mut self, key: KeyEvent, repo: &Portage) -> Option<Signal>;
+ fn draw(&mut self, frame: &mut Frame, area: Rect, repo: &Portage);
+ fn update(&mut self, event: &Event, repo: &Portage) -> Option<Signal>;
}