Skip to content

Commit

Permalink
feat(term): add feeds requirement filter
Browse files Browse the repository at this point in the history
  • Loading branch information
ymgyt committed Apr 15, 2024
1 parent 6788ea3 commit 7d4b3e5
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 25 deletions.
3 changes: 2 additions & 1 deletion crates/synd_term/src/application/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,8 @@ impl Application {
}
Command::MoveFilterRequirement(direction) => {
let filter = self.components.filter.move_requirement(direction);
self.components.entries.update_filter(filter);
self.components.entries.update_filter(filter.clone());
self.components.subscription.update_filter(filter);
self.should_render = true;
}
Command::HandleError {
Expand Down
19 changes: 9 additions & 10 deletions crates/synd_term/src/types/requirement_ext.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
use ratatui::{
style::{Color, Style},
text::Span,
};
use ratatui::{style::Style, text::Span};
use synd_feed::types::Requirement;

use crate::ui::theme::RequirementLabelTheme;

pub trait RequirementExt {
fn label(&self, color: Color) -> [Span<'static>; 3];
fn label(&self, theme: &RequirementLabelTheme) -> [Span<'static>; 3];
}

impl RequirementExt for Requirement {
fn label(&self, fg: Color) -> [Span<'static>; 3] {
fn label(&self, theme: &RequirementLabelTheme) -> [Span<'static>; 3] {
let (label, color) = match self {
Requirement::Must => ("MST", Color::Rgb(154, 4, 4)),
Requirement::Should => ("SHD", Color::Rgb(243, 201, 105)),
Requirement::May => ("MAY", Color::Rgb(35, 57, 91)),
Requirement::Must => ("MST", theme.must),
Requirement::Should => ("SHD", theme.should),
Requirement::May => ("MAY", theme.may),
};
[
Span::styled("", Style::default().fg(color)),
Span::styled(label, Style::default().bg(color).fg(fg)),
Span::styled(label, Style::default().bg(color).fg(theme.fg)),
Span::styled("", Style::default().fg(color)),
]
}
Expand Down
2 changes: 1 addition & 1 deletion crates/synd_term/src/ui/components/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl Entries {
.unwrap_or_else(|| ui::default_icon());

let feed_title = entry.feed_title.as_deref().unwrap_or(ui::UNKNOWN_SYMBOL);
let requirement = entry.requirement().label(cx.theme.requiment_fg).to_vec();
let requirement = entry.requirement().label(&cx.theme.requirement).to_vec();

Row::new([
Cell::from(Span::from(published)),
Expand Down
5 changes: 3 additions & 2 deletions crates/synd_term/src/ui/components/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub enum FilterResult {
Discard,
}

#[derive(Clone)]
pub struct FeedFilter {
requirement: Requirement,
}
Expand Down Expand Up @@ -176,9 +177,9 @@ impl Filter {
Span::from(" "),
Span::from("Requirement ").dim(),
];
spans.extend(self.requirement.label(cx.theme.requiment_fg));
spans.extend(self.requirement.label(&cx.theme.requirement));

spans.extend([Span::from(" "), Span::from(" Category").dim()]);
spans.extend([Span::from(" "), Span::from(" Categories").dim()]);

for c in &self.categories {
let state = self
Expand Down
53 changes: 44 additions & 9 deletions crates/synd_term/src/ui/components/subscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,27 @@ use crate::{
application::{Direction, IndexOutOfRange, ListAction},
client::query::subscription::SubscriptionOutput,
types::{self, EntryMeta, Feed, RequirementExt, TimeExt},
ui::{self, Context},
ui::{
self,
components::filter::{FeedFilter, FilterResult},
Context,
},
};

pub struct Subscription {
selected_feed_index: usize,
feeds: Vec<types::Feed>,
effective_feeds: Vec<usize>,
filter: FeedFilter,
}

impl Subscription {
pub fn new() -> Self {
Self {
selected_feed_index: 0,
feeds: Vec::new(),
effective_feeds: Vec::new(),
filter: FeedFilter::default(),
}
}

Expand All @@ -42,7 +50,9 @@ impl Subscription {
}

pub fn selected_feed(&self) -> Option<&types::Feed> {
self.feeds.get(self.selected_feed_index)
self.effective_feeds
.get(self.selected_feed_index)
.map(|&idx| self.feeds.get(idx).unwrap())
}

pub fn update_subscription(&mut self, action: ListAction, subscription: SubscriptionOutput) {
Expand All @@ -51,24 +61,42 @@ impl Subscription {
ListAction::Append => self.feeds.extend(feed_metas),
ListAction::Replace => self.feeds = feed_metas.collect(),
}
self.apply_filter();
}

pub fn update_filter(&mut self, filter: FeedFilter) {
self.filter = filter;
self.apply_filter();
}

fn apply_filter(&mut self) {
self.effective_feeds = self
.feeds
.iter()
.enumerate()
.filter(|(_idx, feed)| self.filter.feed(feed) == FilterResult::Use)
.map(|(idx, _)| idx)
.collect();
}

pub fn upsert_subscribed_feed(&mut self, feed: types::Feed) {
match self.feeds.iter_mut().find(|x| x.url == feed.url) {
Some(x) => *x = feed,
None => self.feeds.insert(0, feed),
}
self.apply_filter();
}

pub fn remove_unsubscribed_feed(&mut self, url: &str) {
self.feeds.retain(|feed_meta| feed_meta.url != url);
self.apply_filter();
self.move_selection(&Direction::Up);
}

pub fn move_selection(&mut self, direction: &Direction) {
self.selected_feed_index = direction.apply(
self.selected_feed_index,
self.feeds.len(),
self.effective_feeds.len(),
IndexOutOfRange::Wrapping,
);
}
Expand All @@ -79,7 +107,7 @@ impl Subscription {

pub fn move_last(&mut self) {
if !self.feeds.is_empty() {
self.selected_feed_index = self.feeds.len() - 1;
self.selected_feed_index = self.effective_feeds.len() - 1;
}
}
}
Expand Down Expand Up @@ -183,14 +211,15 @@ impl Subscription {
let desc = feed_meta.description.as_deref().unwrap_or("");
let requirement = feed_meta
.requirement()
.label(cx.theme.requiment_fg)
.label(&cx.theme.requirement)
.to_vec();
let category = feed_meta.category();
// TODO: fallback icon
let icon = cx.categories.icon(category).unwrap();
let icon = cx
.categories
.icon(category)
.unwrap_or_else(|| ui::default_icon());

Row::new([
// Cell::from(Span::from(title)),
Cell::from(Line::from(vec![
Span::from(icon.symbol()).fg(icon.color().unwrap_or(cx.theme.default_icon_fg)),
Span::from(" "),
Expand All @@ -203,7 +232,13 @@ impl Subscription {
])
};

(header, constraints, self.feeds.iter().map(row))
(
header,
constraints,
self.effective_feeds
.iter()
.map(move |&idx| row(self.feeds.get(idx).unwrap())),
)
}

#[allow(clippy::too_many_lines)]
Expand Down
17 changes: 15 additions & 2 deletions crates/synd_term/src/ui/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub struct Theme {
pub entries: EntriesTheme,
pub error: ErrorTheme,
pub default_icon_fg: Color,
pub requiment_fg: Color,
pub requirement: RequirementLabelTheme,
}

#[derive(Clone)]
Expand Down Expand Up @@ -50,6 +50,14 @@ pub struct EntriesTheme {
pub selected_entry: Style,
}

#[derive(Clone)]
pub struct RequirementLabelTheme {
pub must: Color,
pub should: Color,
pub may: Color,
pub fg: Color,
}

impl Theme {
pub fn with_palette(p: &Palette) -> Self {
let gray = tailwind::ZINC;
Expand Down Expand Up @@ -87,7 +95,12 @@ impl Theme {
message: Style::new().fg(err).bg(bg),
},
default_icon_fg: fg,
requiment_fg: bg,
requirement: RequirementLabelTheme {
must: Color::Rgb(154, 4, 4),
should: Color::Rgb(243, 201, 105),
may: Color::Rgb(35, 57, 91),
fg: bg,
},
}
}
pub fn new() -> Self {
Expand Down

0 comments on commit 7d4b3e5

Please sign in to comment.