Skip to content

Commit

Permalink
trying to fetch features for each crate part 3
Browse files Browse the repository at this point in the history
  • Loading branch information
josueBarretogit committed May 30, 2024
1 parent 9778fc7 commit 38c823e
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 102 deletions.
85 changes: 77 additions & 8 deletions src/tui/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ use ratatui::{backend::CrosstermBackend, Terminal};
use tokio::sync::mpsc::{self, UnboundedSender};

use crate::content_parser::content_parser::JsonContentParser;
use crate::view::widgets::{CategoriesTabs, CrateItemList};
use crate::{dependency_builder::DependenciesBuilder, view::ui::AppView};

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Action {
FetchFeatures(CategoriesTabs),
UpdateFeatures(CategoriesTabs, Vec<CrateItemList>),
Tick,
FetchFeatures,
UpdateFeatures(Vec<String>, usize),
ToggleShowFeatures,
ShowLoadingAddingDeps,
AddingDeps,
Expand All @@ -30,10 +31,6 @@ pub enum Action {

pub fn update(app: &mut AppView, action: Action) {
match action {
Action::UpdateFeatures(features, index) => {
app.update_features_crates(features, index);

}
Action::ToggleShowFeatures => {
app.toggle_show_features();
}
Expand Down Expand Up @@ -96,9 +93,73 @@ pub fn update(app: &mut AppView, action: Action) {
}
});
}
Action::FetchFeatures(category) => {
let client = crates_io_api::AsyncClient::new(
"josuebarretogit (josuebarretogit@gmail.com)",
Duration::from_millis(500),
)
.unwrap();
match category {
CategoriesTabs::General => {
let mut general_crates = app.general_crates.clone();
let tx = app.action_tx.clone();
tokio::spawn(async move {
for crateitem in general_crates.iter_mut() {
let crate_name = crateitem.name.as_str();
let response = client.get_crate(crate_name).await;

if let Ok(information) = response {
let features: Vec<String> = match information.versions.first() {
Some(latest) => latest.features.clone().into_keys().collect(),
None => vec!["This crate has no features".to_string()],
};

crateitem.features = Some(features);
};
}
tx.send(Action::UpdateFeatures(
CategoriesTabs::General,
general_crates,
))
.unwrap();
});
}
CategoriesTabs::Common => {
let mut common_crates = app.common_crates.clone();
let tx = app.action_tx.clone();
tokio::spawn(async move {
for crateitem in common_crates.iter_mut() {
let crate_name = crateitem.name.as_str();
let response = client.get_crate(crate_name).await;

if let Ok(information) = response {
let features: Vec<String> = match information.versions.first() {
Some(latest) => latest.features.clone().into_keys().collect(),
None => vec!["This crate has no features".to_string()],
};

crateitem.features = Some(features);
};
}
tx.send(Action::UpdateFeatures(
CategoriesTabs::Common,
common_crates,
))
.unwrap();
});
}
_ => {}
}

}

Action::UpdateFeatures(category, items) => match category {
CategoriesTabs::General => app.general_crates = items,
CategoriesTabs::Common => app.common_crates = items,
_ => {}
},

Action::Quit => app.exit(),
_ => {}
}
}
pub fn handle_event(tx: UnboundedSender<Action>) -> tokio::task::JoinHandle<()> {
Expand All @@ -123,7 +184,6 @@ pub fn handle_event(tx: UnboundedSender<Action>) -> tokio::task::JoinHandle<()>
KeyCode::Char('d') => Action::CheckDocs,
KeyCode::Char('c') => Action::CheckCratesIo,
KeyCode::Char('f') => Action::ToggleShowFeatures,

_ => Action::Tick,
}
} else {
Expand Down Expand Up @@ -152,6 +212,15 @@ pub async fn run() -> Result<(), Box<dyn Error>> {

let mut app = AppView::setup(action_tx.clone(), &json_parser);

std::thread::spawn(move || {
action_tx
.send(Action::FetchFeatures(CategoriesTabs::General))
.unwrap();
action_tx
.send(Action::FetchFeatures(CategoriesTabs::Common))
.unwrap();
});

let task = handle_event(app.action_tx.clone());

loop {
Expand Down
137 changes: 49 additions & 88 deletions src/view/ui.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(clippy::too_many_lines)]
use std::{time::Duration, usize};
use std::{thread::spawn, time::Duration, usize};
use throbber_widgets_tui::ThrobberState;
use tokio::sync::mpsc::UnboundedSender;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};

use ratatui::{
prelude::*,
Expand Down Expand Up @@ -40,19 +40,17 @@ pub struct AppView {
pub exit: bool,
pub is_showing_features: bool,

fetch_once: bool,

categories_list_state: ListState,
general_crates: Vec<CrateItemList>,
math_crates: Vec<CrateItemList>,
ffi_crates: Vec<CrateItemList>,
cryptography_crates: Vec<CrateItemList>,
common_crates: Vec<CrateItemList>,
concurrency_crates: Vec<CrateItemList>,
networking_crates: Vec<CrateItemList>,
database_crates: Vec<CrateItemList>,
clis_crates: Vec<CrateItemList>,
graphics_crates: Vec<CrateItemList>,
pub categories_list_state: ListState,
pub general_crates: Vec<CrateItemList>,
pub math_crates: Vec<CrateItemList>,
pub ffi_crates: Vec<CrateItemList>,
pub cryptography_crates: Vec<CrateItemList>,
pub common_crates: Vec<CrateItemList>,
pub concurrency_crates: Vec<CrateItemList>,
pub networking_crates: Vec<CrateItemList>,
pub database_crates: Vec<CrateItemList>,
pub clis_crates: Vec<CrateItemList>,
pub graphics_crates: Vec<CrateItemList>,
}

#[derive(Default)]
Expand Down Expand Up @@ -157,22 +155,31 @@ impl AppView {
list_state.select(Some(0));
feature_list_state.select(Some(0));

let general_crates = page_contents.get_general_crates();

let math_crates = page_contents.get_crates(&Categories::Math);
let ffi_crates = page_contents.get_crates(&Categories::FFI);
let cryptography_crates = page_contents.get_crates(&Categories::Cryptography);

let common_crates = page_contents.get_crates_with_sub(&CategoriesWithSubCategories::Common);
let concurrency_crates =
page_contents.get_crates_with_sub(&CategoriesWithSubCategories::Concurrency);
let networking_crates =
page_contents.get_crates_with_sub(&CategoriesWithSubCategories::Networking);
let database_crates =
page_contents.get_crates_with_sub(&CategoriesWithSubCategories::Databases);
let clis_crates = page_contents.get_crates_with_sub(&CategoriesWithSubCategories::Clis);
let graphics_crates =
page_contents.get_crates_with_sub(&CategoriesWithSubCategories::Graphics);
let general_crates: Vec<CrateItemList> = page_contents.get_general_crates().into();

let math_crates: Vec<CrateItemList> = page_contents.get_crates(&Categories::Math).into();
let ffi_crates: Vec<CrateItemList> = page_contents.get_crates(&Categories::FFI).into();
let cryptography_crates: Vec<CrateItemList> =
page_contents.get_crates(&Categories::Cryptography).into();

let common_crates: Vec<CrateItemList> = page_contents
.get_crates_with_sub(&CategoriesWithSubCategories::Common)
.into();
let concurrency_crates: Vec<CrateItemList> = page_contents
.get_crates_with_sub(&CategoriesWithSubCategories::Concurrency)
.into();
let networking_crates: Vec<CrateItemList> = page_contents
.get_crates_with_sub(&CategoriesWithSubCategories::Networking)
.into();
let database_crates: Vec<CrateItemList> = page_contents
.get_crates_with_sub(&CategoriesWithSubCategories::Databases)
.into();
let clis_crates: Vec<CrateItemList> = page_contents
.get_crates_with_sub(&CategoriesWithSubCategories::Clis)
.into();
let graphics_crates: Vec<CrateItemList> = page_contents
.get_crates_with_sub(&CategoriesWithSubCategories::Graphics)
.into();

Self {
action_tx,
Expand All @@ -182,19 +189,17 @@ impl AppView {
is_adding_dependencies: false,
loader_state: ThrobberState::default(),

general_crates: general_crates.into(),

math_crates: math_crates.into(),
ffi_crates: ffi_crates.into(),
general_crates,

cryptography_crates: cryptography_crates.into(),

common_crates: common_crates.into(),
concurrency_crates: concurrency_crates.into(),
networking_crates: networking_crates.into(),
database_crates: database_crates.into(),
clis_crates: clis_crates.into(),
graphics_crates: graphics_crates.into(),
math_crates,
ffi_crates,
cryptography_crates,
common_crates,
concurrency_crates,
networking_crates,
database_crates,
clis_crates,
graphics_crates,

categories_list_state: list_state,

Expand All @@ -203,7 +208,6 @@ impl AppView {

popup_widget: Popup::default(),
features: Features::default(),
fetch_once: true,
}
}

Expand Down Expand Up @@ -282,6 +286,7 @@ impl AppView {
fn render_crates_list(&mut self, area: Rect, buf: &mut Buffer) {
match self.category_tabs {
CategoriesTabs::General => {

self.crates_list.crates_widget_list = CratesListWidget::new(&self.general_crates);

StatefulWidget::render(
Expand All @@ -290,43 +295,6 @@ impl AppView {
buf,
&mut self.crates_list.state,
);

if self.fetch_once {
self.fetch_once = false;
for (index, item) in self.general_crates.iter().cloned().enumerate() {
let tx = self.action_tx.clone();

let client = crates_io_api::AsyncClient::new(
"josuebarretogit (josuebarretogit@gmail.com)",
Duration::from_millis(500),
)
.unwrap();

tokio::spawn(async move {
let crate_name = item.name.as_str();
let response = client.get_crate(crate_name).await;
match response {
Ok(information) => {
let features: Vec<String> = match information.versions.first() {
Some(latest) => {
latest.features.clone().into_keys().collect()
}
None => vec!["This crate has no features".to_string()],
};

tx.send(Action::UpdateFeatures(features, index)).unwrap();
}
Err(_) => {
tx.send(Action::UpdateFeatures(
vec!["This crate has no features".to_string()],
index,
))
.unwrap();
}
};
});
}
}
}
CategoriesTabs::Graphics => {
self.crates_list.crates_widget_list = CratesListWidget::new(&self.graphics_crates);
Expand Down Expand Up @@ -711,11 +679,4 @@ impl AppView {
self.is_showing_features = !self.is_showing_features;
}
}

pub fn update_features_crates(&mut self, features: Vec<String>, index: usize) {
match self.category_tabs {
CategoriesTabs::General => self.general_crates[index].features = Some(features),
_ => {}
}
}
}
14 changes: 8 additions & 6 deletions src/view/widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,23 @@ impl FeaturesWidgetList {
impl StatefulWidget for FeaturesWidgetList {
type State = ListState;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
Block::bordered().title("").render(area, buf);

Block::bordered().title("Features").render(area, buf);

let inner_area = area.inner(&Margin {
vertical: 1,
horizontal: 1,
});

let features = if self.features.is_some() {
self.features.unwrap()
} else {
vec![FeatureItemList::new("Fetching features".to_string())]
vec![FeatureItemList::new("Fetching features, please wait a moment".to_string())]
};

let features_list = List::new(features)
.highlight_style(Style::default().blue())
.highlight_symbol("* ")
.highlight_symbol(">> ")
.direction(ListDirection::TopToBottom);

StatefulWidget::render(features_list, inner_area, buf, state);
Expand Down Expand Up @@ -118,7 +120,7 @@ impl StatefulWidget for Popup {
}
}

#[derive(Default, Clone)]
#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct CrateItemList {
pub name: String,
pub description: String,
Expand Down Expand Up @@ -205,7 +207,7 @@ impl From<CrateItemList> for ListItem<'_> {
impl StatefulWidget for CratesListWidget {
type State = ListState;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
let block = Block::bordered().padding(Padding::uniform(1));
let block = Block::default().padding(Padding::uniform(1));

let list = List::new(self.crates)
.block(block)
Expand All @@ -226,7 +228,7 @@ impl CratesListWidget {
}
}

#[derive(Default, Clone, Copy, Display, FromRepr, EnumIter)]
#[derive(Default, Clone, Copy, Display, FromRepr, EnumIter, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum CategoriesTabs {
#[strum(to_string = "General")]
#[default]
Expand Down

0 comments on commit 38c823e

Please sign in to comment.