From 17bea12b4e5706373940cef18da06c50677928c4 Mon Sep 17 00:00:00 2001 From: Thomas Eppers Date: Tue, 7 Sep 2021 16:45:27 +0200 Subject: [PATCH] added the abiliy to go to next/previous page of tags with ctrl+(n/p) --- src/tags.rs | 28 ++++++++++++++++++++++++++-- src/ui.rs | 6 ++++++ src/widget/tag_list.rs | 30 +++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/tags.rs b/src/tags.rs index fde69da..74cca60 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -20,7 +20,9 @@ pub struct Images { #[derive(Deserialize)] pub struct Tags { + #[serde(rename(deserialize = "next"))] next_page: Option, + #[serde(rename(deserialize = "previous"))] prev_page: Option, pub results: Vec, } @@ -30,6 +32,8 @@ pub enum Error { InvalidCharacter(char), Fetching(String), Converting(String), + NoPrevPage, + NoNextPage, } impl fmt::Display for Error { @@ -38,16 +42,22 @@ impl fmt::Display for Error { Error::InvalidCharacter(c) => write!(f, "Invalid Character: {}", c), Error::Fetching(s) => write!(f, "Fetching error: {}", s), Error::Converting(s) => write!(f, "Converting error: {}", s), + Error::NoNextPage => write!(f, "No next page available"), + Error::NoPrevPage => write!(f, "No previous page available"), } } } impl Tags { + /// fetches tag information with a repository name in the form of organization/repository or library/repository in the case of official images from docker pub fn new(repo: String) -> Result { let request = format!("https://hub.docker.com/v2/repositories/{}/tags", repo); + Self::with_url(&request) + } - //get response - let res = match reqwest::blocking::get(request) { + /// fetches tag information from a url + fn with_url(url: &str) -> Result { + let res = match reqwest::blocking::get(url) { Ok(result) => result, Err(e) => return Err(Error::Fetching(format!("reqwest error: {}", e))), }; @@ -76,6 +86,20 @@ impl Tags { } Ok(name) } + + pub fn next_page(&self) -> Result { + match &self.next_page { + Some(url) => Self::with_url(url), + None => Err(Error::NoNextPage), + } + } + + pub fn prev_page(&self) -> Result { + match &self.prev_page { + Some(url) => Self::with_url(url), + None => Err(Error::NoPrevPage), + } + } } impl fmt::Display for Images { diff --git a/src/ui.rs b/src/ui.rs index 0d042d5..6e9bee3 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -89,6 +89,12 @@ impl Ui { } Ok(_) => (), }, + Ok(Key::Ctrl('r')) => { + ui.repo.confirm(); + ui.tags = tag_list::TagList::with_repo(ui.repo.get()); + } + Ok(Key::Ctrl('n')) => ui.tags.next_page(), + Ok(Key::Ctrl('p')) => ui.tags.prev_page(), Ok(Key::Char('\n')) => match ui.state { State::EditRepo => { ui.repo.confirm(); diff --git a/src/widget/tag_list.rs b/src/widget/tag_list.rs index 23313ee..07ca5bf 100644 --- a/src/widget/tag_list.rs +++ b/src/widget/tag_list.rs @@ -7,11 +7,6 @@ use tui::widgets::{Block, Borders, List, ListState}; use crate::tags; use crate::ui::State; -pub struct TagList { - typ: Type, - state: ListState, -} - #[derive(Debug)] pub enum Error { NoneSelected, @@ -33,6 +28,11 @@ pub enum Type { Repo(tags::Tags), } +pub struct TagList { + typ: Type, + state: ListState, +} + impl TagList { fn new(typ: Type) -> Self { Self { @@ -54,6 +54,26 @@ impl TagList { } } + pub fn next_page(&mut self) { + match &self.typ { + Type::Status(_) => (), + Type::Repo(tags) => match tags.next_page() { + Err(e) => self.typ = Type::Status(format!("{}", e)), + Ok(tags) => self.typ = Type::Repo(tags), + }, + } + } + + pub fn prev_page(&mut self) { + match &self.typ { + Type::Status(_) => (), + Type::Repo(tags) => match tags.prev_page() { + Err(e) => self.typ = Type::Status(format!("{}", e)), + Ok(tags) => self.typ = Type::Repo(tags), + }, + } + } + /// get a list of tag names with info fn print_lines(&self) -> Vec { match &self.typ {