Skip to content

Commit

Permalink
Merge PR #7 from josueBarretogit/develop_v0.2.0
Browse files Browse the repository at this point in the history
Develop v0.2.0
  • Loading branch information
josueBarretogit authored Aug 9, 2024
2 parents 1c1dce9 + 0cb91e8 commit ecd27d0
Show file tree
Hide file tree
Showing 16 changed files with 458 additions and 174 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: main

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

env:
CARGO_TERM_COLOR: always

jobs:
build_and_test:
name: Test manga tui
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: Swatinem/rust-cache@v2

- name: setup toolchain
uses: hecrj/setup-rust-action@v1
with:
rust-version: stable

- name: cargo test
run: cargo test


- name: clippy
run: cargo clippy --all --all-features --tests -- -D warnings
env:
RUST_BACKTRACE: full
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ target/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
*.db
*~
7 changes: 3 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "manga-tui"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
authors = ["Josue <[email protected]>"]
readme = "README.md"
Expand All @@ -24,7 +24,7 @@ crossterm = { version = "0.27.0", features = ["event-stream"] }
directories = "5.0.1"
image = "0.25.1"
ratatui = { version = "0.27.0", features = ["all-widgets", "palette", "unstable-widget-ref"] }
ratatui-image = {version = "1.0.2", features = [ "rustix",]}
ratatui-image = { git = "https://github.com/josueBarretogit/ratatui-image", version = "1.0.2", features = ["rustix"]}
reqwest = { version = "0.12.4", features = ["json"] }
serde = { version = "1.0.203", features = ["derive"] }
tokio = { version = "1.38.0", features = ["full"] }
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ https://github.com/user-attachments/assets/64880a98-74c8-4656-8cf8-2c1daf5375d2
```shell
cargo install manga-tui --locked
```

### AUR

You can install `manga-tui` from the [AUR](https://aur.archlinux.org/packages/manga-tui) with using an [AUR helper](https://wiki.archlinux.org/title/AUR_helpers).

```shell
paru -S manga-tui
```

## Binary release

Download a binary from the [releases page](https://github.com/josueBarretogit/manga-tui/releases/latest)
Expand Down
97 changes: 91 additions & 6 deletions src/backend/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt::Write;
use strum::{Display, EnumIter, IntoEnumIterator};

use crate::global::PREFERRED_LANGUAGE;
use crate::view::widgets::filter_widget::state::FilterListItem;
use crate::view::widgets::filter_widget::state::{FilterListItem, TagListItem, TagListItemState};

pub trait IntoParam {
fn into_param(self) -> String;
Expand Down Expand Up @@ -63,8 +63,45 @@ pub enum SortBy {
YearAscending,
}

#[derive(Clone, PartialEq, Eq)]
pub struct Tags(Vec<String>);
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TagSelection {
Included,
Excluded,
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TagData {
id: String,
state: TagSelection,
}

impl TagData {
pub fn new(id: String, state: TagSelection) -> Self {
Self { id, state }
}
}

impl From<&TagListItem> for TagData {
fn from(value: &TagListItem) -> Self {
Self {
id: value.id.clone(),
state: if value.state == TagListItemState::Included {
TagSelection::Included
} else {
TagSelection::Excluded
},
}
}
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Tags(Vec<TagData>);

impl Tags {
pub fn new(tags: Vec<TagData>) -> Self {
Self(tags)
}
}

impl IntoParam for Tags {
fn into_param(self) -> String {
Expand All @@ -74,8 +111,12 @@ impl IntoParam for Tags {
return param;
}

for id_tag in self.0 {
param.push_str(format!("&includedTags[]={}", id_tag).as_str());
for tag in self.0 {
let parameter = match tag.state {
TagSelection::Included => "&includedTags[]=",
TagSelection::Excluded => "&excludedTags[]=",
};
param.push_str(format!("{}{}", parameter, tag.id).as_str());
}

param
Expand Down Expand Up @@ -470,7 +511,7 @@ impl Filters {
pub fn set_sort_by(&mut self, sort_by: SortBy) {
self.sort_by = sort_by;
}
pub fn set_tags(&mut self, tags: Vec<String>) {
pub fn set_tags(&mut self, tags: Vec<TagData>) {
self.tags.0 = tags;
}

Expand Down Expand Up @@ -501,6 +542,7 @@ impl Filters {

#[cfg(test)]
mod test {

use super::*;

#[test]
Expand All @@ -518,4 +560,47 @@ mod test {

assert_eq!(conversion, Languages::Spanish);
}

#[test]
fn filter_by_tags_works() {
let tags = Tags::new(vec![
TagData {
id: "id_tag_included".to_string(),
state: TagSelection::Included,
},
TagData {
id: "id_tag_excluded".to_string(),
state: TagSelection::Excluded,
},
]);

assert_eq!(
"&includedTags[]=id_tag_included&excludedTags[]=id_tag_excluded",
tags.into_param()
);
}

#[test]
fn filters_combined_work() {
PREFERRED_LANGUAGE.set(Languages::default()).unwrap();
let filters = Filters::default();

assert_eq!("&availableTranslatedLanguage[]=en&contentRating[]=safe&contentRating[]=suggestive&order[latestUploadedChapter]=desc", filters.into_param());

let mut filters = Filters::default();

filters.set_tags(vec![TagData::new(
"id_1".to_string(),
TagSelection::Included,
)]);

filters.set_authors(vec![
Author::new("id_1".to_string()),
Author::new("id_2".to_string()),
]);

filters.set_languages(vec![Languages::French, Languages::Spanish]);

assert_eq!("&authors[]=id_1&authors[]=id_2&availableTranslatedLanguage[]=fr&availableTranslatedLanguage[]=es&includedTags[]=id_1&contentRating[]=safe&contentRating[]=suggestive&order[latestUploadedChapter]=desc", filters.into_param());
}
}
5 changes: 4 additions & 1 deletion src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ pub static PREFERRED_LANGUAGE: OnceCell<Languages> = OnceCell::new();
pub static INSTRUCTIONS_STYLE: Lazy<Style> =
Lazy::new(|| Style::default().bold().underlined().yellow());

pub static ERROR_STYLE : Lazy<Style> = Lazy::new(|| Style::default().bold().underlined().red().on_black());
pub static ERROR_STYLE: Lazy<Style> =
Lazy::new(|| Style::default().bold().underlined().red().on_black());

pub static CURRENT_LIST_ITEM_STYLE: Lazy<Style> = Lazy::new(|| Style::default().on_blue());
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
None => PREFERRED_LANGUAGE.set(Languages::default()).unwrap(),
}


let user_agent = format!(
"manga-tui/0.1.0 ({}/{}/{})",
"manga-tui/{} ({}/{}/{})",
env!("CARGO_PKG_VERSION"),
std::env::consts::FAMILY,
std::env::consts::OS,
std::env::consts::ARCH
Expand Down
9 changes: 9 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::backend::fetch::MangadexClient;
use crate::backend::filter::Languages;
use crate::backend::Data;
use crate::common::{Artist, Author, Manga};
use crate::view::widgets::filter_widget::state::{TagListItem, TagListItemState};
use crate::view::widgets::ImageHandler;
use crate::PICKER;
use image::io::Reader;
Expand Down Expand Up @@ -33,6 +34,14 @@ pub fn set_status_style(status: &str) -> Span<'_> {
}
}

pub fn set_filter_tags_style(tag: &TagListItem) -> Span<'_> {
match tag.state {
TagListItemState::Included => format!(" {} ", tag.name).black().on_green(),
TagListItemState::Excluded => format!(" {} ", tag.name).black().on_red(),
TagListItemState::NotSelected => Span::from(tag.name.clone()),
}
}

pub fn search_manga_cover<IM: ImageHandler>(
file_name: String,
manga_id: String,
Expand Down
41 changes: 16 additions & 25 deletions src/view/pages/manga.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ use tokio::task::JoinSet;

use self::text::ToSpan;

// Todo! Define all keybindings

#[derive(PartialEq, Eq)]
pub enum PageState {
DownloadingChapters,
Expand Down Expand Up @@ -90,6 +88,7 @@ pub struct MangaPage {
local_event_rx: UnboundedReceiver<MangaPageEvents>,
chapters: Option<ChaptersData>,
chapter_order: ChapterOrder,
chapter_language: Languages,
state: PageState,
statistics: Option<MangaStatistics>,
tasks: JoinSet<()>,
Expand Down Expand Up @@ -127,6 +126,12 @@ impl MangaPage {
local_event_tx.send(MangaPageEvents::SearchChapters).ok();
local_event_tx.send(MangaPageEvents::FethStatistics).ok();

let chapter_language = manga
.available_languages
.iter()
.find(|lang| *lang == Languages::get_preferred_lang())
.cloned();

Self {
manga,
image_state,
Expand All @@ -142,6 +147,7 @@ impl MangaPage {
tasks: JoinSet::new(),
available_languages_state: ListState::default(),
is_list_languages_open: false,
chapter_language: chapter_language.unwrap_or(Languages::default()),
}
}
fn render_cover(&mut self, area: Rect, buf: &mut Buffer) {
Expand Down Expand Up @@ -351,7 +357,10 @@ impl MangaPage {
);
} else {
Paragraph::new(Line::from(vec![
"Available languages : ".into(),
"Language: ".into(),
self.chapter_language.as_emoji().into(),
" | ".into(),
"Available languages: ".into(),
"<l>".bold().yellow(),
]))
.render(language_area, buf);
Expand All @@ -373,6 +382,7 @@ impl MangaPage {
}
KeyCode::Enter | KeyCode::Char('s') => {
self.chapters = None;
self.chapter_language = self.get_current_selected_language();
self.search_chapters();
}
KeyCode::Char('l') | KeyCode::Esc => {
Expand Down Expand Up @@ -554,28 +564,9 @@ impl MangaPage {
}

fn get_current_selected_language(&mut self) -> Languages {
let preferred_language = Languages::get_preferred_lang();
match self.available_languages_state.selected() {
Some(index) => *self
.manga
.available_languages
.get(index)
.unwrap_or(preferred_language),
None => {
let maybe_preferred_language = self
.manga
.available_languages
.iter()
.find(|lang| *lang == preferred_language);

maybe_preferred_language.cloned().unwrap_or(
self.manga
.available_languages
.first()
.cloned()
.unwrap_or(*preferred_language),
)
}
Some(index) => self.manga.available_languages[index],
None => self.chapter_language,
}
}

Expand All @@ -601,7 +592,7 @@ impl MangaPage {
self.state = PageState::SearchingChapters;
let manga_id = self.manga.id.clone();
let tx = self.local_event_tx.clone();
let language = self.get_current_selected_language();
let language = self.chapter_language;
let chapter_order = self.chapter_order;

let page = if let Some(chapters) = self.chapters.as_ref() {
Expand Down
5 changes: 3 additions & 2 deletions src/view/widgets/feed.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::backend::filter::Languages;
use crate::backend::ChapterResponse;
use crate::global::CURRENT_LIST_ITEM_STYLE;
use crate::utils::display_dates_since_publication;
use ratatui::{prelude::*, widgets::*};
use tui_widget_list::PreRender;
Expand Down Expand Up @@ -51,7 +52,7 @@ impl Widget for MangasRead {

let [title_area, recent_chapters_area] = layout.margin(1).areas(area);

Block::bordered().style(self.style).render(area, buf);
Block::bordered().border_style(self.style).render(area, buf);

Paragraph::new(self.title)
.block(Block::default().borders(Borders::RIGHT))
Expand All @@ -74,7 +75,7 @@ impl Widget for MangasRead {
impl PreRender for MangasRead {
fn pre_render(&mut self, context: &tui_widget_list::PreRenderContext) -> u16 {
if context.is_selected {
self.style = Style::default().fg(Color::Yellow);
self.style = *CURRENT_LIST_ITEM_STYLE;
}
10
}
Expand Down
Loading

0 comments on commit ecd27d0

Please sign in to comment.