Skip to content

Commit

Permalink
#252: Add filter reset button and adjust styling
Browse files Browse the repository at this point in the history
  • Loading branch information
mtkennerly committed Oct 19, 2024
1 parent e0869f9 commit 49a494c
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 95 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ to better preserve the files' executable permissions.
* GUI: On the custom games screen,
when you use the button to preview a custom game,
the window will switch to the backup screen and show you the results for that game.
* GUI: There is now a button to quickly reset the game list filters,
while still leaving the filter options open.
* Fixed:
* Files on Windows network shares were not backed up correctly.
For example, a file identified as `\\localhost\share\test.txt`
Expand All @@ -41,6 +43,7 @@ to better preserve the files' executable permissions.
* GUI: The backup format and retention settings are now on the "other" screen,
instead of being accessed via the gear icon on the backup screen.
* GUI: Some uses of "select"/"deselect" have been changed to "enable"/"disable".
* GUI: The game list filters now have a different background color.
* Updated translations.
(Thanks to contributors on the [Crowdin project](https://crowdin.com/project/ludusavi))

Expand Down
18 changes: 18 additions & 0 deletions src/gui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,24 @@ impl App {
search.toggle_filter(filter, enabled);
Task::none()
}
Message::ResetSearchFilter => {
match self.screen {
Screen::Backup => {
self.backup_screen.log.search.reset();
self.text_histories.backup_search_game_name.push("");
}
Screen::Restore => {
self.restore_screen.log.search.reset();
self.text_histories.restore_search_game_name.push("");
}
Screen::CustomGames => {
self.custom_games_screen.filter.reset();
self.text_histories.custom_games_search_game_name.push("");
}
Screen::Other => {}
}
Task::none()
}
Message::EditedSearchFilterUniqueness(filter) => {
let search = if self.screen == Screen::Backup {
&mut self.backup_screen.log.search
Expand Down
8 changes: 8 additions & 0 deletions src/gui/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ pub fn filter<'a>(screen: Screen, open: bool) -> Element<'a> {
)
}

pub fn reset_filter<'a>(dirty: bool) -> Element<'a> {
template(
Icon::RemoveCircle.text(),
dirty.then_some(Message::ResetSearchFilter),
Some(style::Button::Negative),
)
}

pub fn sort<'a>(message: Message) -> Element<'a> {
template(text(TRANSLATOR.sort_button()).width(WIDTH), Some(message), None)
}
Expand Down
1 change: 1 addition & 0 deletions src/gui/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ pub enum Message {
filter: game_filter::FilterKind,
enabled: bool,
},
ResetSearchFilter,
EditedSearchFilterUniqueness(game_filter::Uniqueness),
EditedSearchFilterCompleteness(game_filter::Completeness),
EditedSearchFilterEnablement(game_filter::Enablement),
Expand Down
20 changes: 2 additions & 18 deletions src/gui/editor.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use fuzzy_matcher::FuzzyMatcher;
use iced::{
keyboard, padding,
widget::{horizontal_space, tooltip, Space},
Expand All @@ -11,14 +10,15 @@ use crate::{
button,
common::{BackupPhase, BrowseFileSubject, BrowseSubject, Message, ScrollSubject, UndoSubject},
icon::Icon,
search::CustomGamesFilter,
shortcuts::TextHistories,
style,
widget::{checkbox, pick_list, text, Column, Container, IcedParentExt, Row, Tooltip},
},
lang::TRANSLATOR,
resource::{
cache::Cache,
config::{Config, CustomGame, CustomGameKind, Integration, RedirectKind, SecondaryManifestConfigKind},
config::{Config, CustomGameKind, Integration, RedirectKind, SecondaryManifestConfigKind},
manifest::{Manifest, Store},
},
};
Expand Down Expand Up @@ -243,22 +243,6 @@ pub fn redirect<'a>(config: &Config, histories: &TextHistories, modifiers: &keyb
Container::new(wrapper)
}

#[derive(Default)]
pub struct CustomGamesFilter {
pub enabled: bool,
pub name: String,
}

impl CustomGamesFilter {
pub fn qualifies(&self, game: &CustomGame) -> bool {
!self.enabled
|| self.name.is_empty()
|| fuzzy_matcher::skim::SkimMatcherV2::default()
.fuzzy_match(&game.name, &self.name)
.is_some()
}
}

pub fn custom_games<'a>(
config: &Config,
manifest: &Manifest,
Expand Down
16 changes: 5 additions & 11 deletions src/gui/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
editor,
game_list::GameList,
icon::Icon,
search::CustomGamesFilter,
shortcuts::TextHistories,
style,
widget::{checkbox, number_input, pick_list, text, Button, Column, Container, Element, IcedParentExt, Row},
Expand Down Expand Up @@ -211,16 +212,16 @@ impl Restore {

#[derive(Default)]
pub struct CustomGames {
pub filter: editor::CustomGamesFilter,
pub filter: CustomGamesFilter,
}

impl CustomGames {
pub fn view<'a>(
&self,
&'a self,
config: &Config,
manifest: &Manifest,
operating: bool,
histories: &TextHistories,
histories: &'a TextHistories,
modifiers: &keyboard::Modifiers,
) -> Element<'a> {
let content = Column::new()
Expand All @@ -234,14 +235,7 @@ impl CustomGames {
.push(button::sort(Message::SortCustomGames))
.push(button::filter(Screen::CustomGames, self.filter.enabled)),
)
.push_maybe(self.filter.enabled.then(|| {
Row::new()
.padding(padding::left(20).right(20))
.spacing(20)
.align_y(Alignment::Center)
.push(text(TRANSLATOR.filter_label()))
.push(histories.input(UndoSubject::CustomGamesSearchGameName))
}))
.push_maybe(self.filter.view(histories))
.push(editor::custom_games(
config,
manifest,
Expand Down
208 changes: 142 additions & 66 deletions src/gui/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ use iced::{padding, Alignment};

use crate::{
gui::{
button,
common::{Message, Screen, UndoSubject},
shortcuts::TextHistories,
widget::{checkbox, pick_list, text, Column, Element, IcedParentExt, Row},
style,
widget::{checkbox, pick_list, text, Column, Container, Element, IcedParentExt, Row},
},
lang::TRANSLATOR,
resource::manifest::Manifest,
resource::{config::CustomGame, manifest::Manifest},
scan::{
game_filter::{self, FilterKind},
Duplication, ScanInfo,
Expand Down Expand Up @@ -90,6 +92,24 @@ fn template_with_label<T: 'static + Default + Clone + Eq + PartialEq + ToString>
}

impl FilterComponent {
pub fn reset(&mut self) {
self.game_name.clear();
self.uniqueness.active = false;
self.completeness.active = false;
self.enablement.active = false;
self.change.active = false;
self.manifest.active = false;
}

pub fn is_dirty(&self) -> bool {
!self.game_name.is_empty()
|| self.uniqueness.active
|| self.completeness.active
|| self.enablement.active
|| self.change.active
|| self.manifest.active
}

pub fn qualifies(
&self,
scan: &ScanInfo,
Expand Down Expand Up @@ -136,71 +156,127 @@ impl FilterComponent {
if !self.show {
return None;
}

let content = Column::new()
.padding(padding::left(5).right(5))
.spacing(15)
.push(
Row::new()
.spacing(20)
.align_y(Alignment::Center)
.push(text(TRANSLATOR.filter_label()))
.push(histories.input(match screen {
Screen::Restore => UndoSubject::RestoreSearchGameName,
_ => UndoSubject::BackupSearchGameName,
}))
.push(button::reset_filter(self.is_dirty())),
)
.push(
Row::new()
.spacing(15)
.align_y(Alignment::Center)
.push(template(
&self.uniqueness,
FilterKind::Uniqueness,
game_filter::Uniqueness::ALL,
Message::EditedSearchFilterUniqueness,
))
.push(template(
&self.completeness,
FilterKind::Completeness,
game_filter::Completeness::ALL,
Message::EditedSearchFilterCompleteness,
))
.push(template(
&self.change,
FilterKind::Change,
game_filter::Change::ALL,
Message::EditedSearchFilterChange,
))
.push_if(show_deselected_games, || {
template(
&self.enablement,
FilterKind::Enablement,
game_filter::Enablement::ALL,
Message::EditedSearchFilterEnablement,
)
})
.push_if(manifests.len() == 2, || {
template_noncopy(
&self.manifest,
FilterKind::Manifest,
manifests.clone(),
Message::EditedSearchFilterManifest,
)
})
.push_if(manifests.len() > 2, || {
template_with_label(
&self.manifest,
TRANSLATOR.source_field(),
FilterKind::Manifest,
manifests,
Message::EditedSearchFilterManifest,
)
})
.wrap(),
);

Some(
Container::new(
Container::new(content)
.class(style::Container::GameListEntry)
.padding(padding::top(5).bottom(5)),
)
.padding(padding::left(15).right(15))
.into(),
)
}
}

#[derive(Default)]
pub struct CustomGamesFilter {
pub enabled: bool,
pub name: String,
}

impl CustomGamesFilter {
pub fn reset(&mut self) {
self.name.clear();
}

pub fn is_dirty(&self) -> bool {
!self.name.is_empty()
}

pub fn qualifies(&self, game: &CustomGame) -> bool {
!self.enabled
|| self.name.is_empty()
|| fuzzy_matcher::skim::SkimMatcherV2::default()
.fuzzy_match(&game.name, &self.name)
.is_some()
}

pub fn view<'a>(&'a self, histories: &TextHistories) -> Option<Element<'a>> {
if !self.enabled {
return None;
}

let content = Row::new()
.padding(padding::left(5).right(5))
.spacing(20)
.align_y(Alignment::Center)
.push(text(TRANSLATOR.filter_label()))
.push(histories.input(UndoSubject::CustomGamesSearchGameName))
.push(button::reset_filter(self.is_dirty()));

Some(
Column::new()
.spacing(15)
.push(
Row::new()
.padding(padding::left(20).right(20))
.spacing(20)
.align_y(Alignment::Center)
.push(text(TRANSLATOR.filter_label()))
.push(histories.input(match screen {
Screen::Restore => UndoSubject::RestoreSearchGameName,
_ => UndoSubject::BackupSearchGameName,
})),
)
.push(
Row::new()
.padding(padding::left(20).right(20))
.spacing(15)
.align_y(Alignment::Center)
.push(template(
&self.uniqueness,
FilterKind::Uniqueness,
game_filter::Uniqueness::ALL,
Message::EditedSearchFilterUniqueness,
))
.push(template(
&self.completeness,
FilterKind::Completeness,
game_filter::Completeness::ALL,
Message::EditedSearchFilterCompleteness,
))
.push(template(
&self.change,
FilterKind::Change,
game_filter::Change::ALL,
Message::EditedSearchFilterChange,
))
.push_if(show_deselected_games, || {
template(
&self.enablement,
FilterKind::Enablement,
game_filter::Enablement::ALL,
Message::EditedSearchFilterEnablement,
)
})
.push_if(manifests.len() == 2, || {
template_noncopy(
&self.manifest,
FilterKind::Manifest,
manifests.clone(),
Message::EditedSearchFilterManifest,
)
})
.push_if(manifests.len() > 2, || {
template_with_label(
&self.manifest,
TRANSLATOR.source_field(),
FilterKind::Manifest,
manifests,
Message::EditedSearchFilterManifest,
)
})
.wrap(),
)
.into(),
Container::new(
Container::new(content)
.class(style::Container::GameListEntry)
.padding(padding::top(5).bottom(5)),
)
.padding(padding::left(15).right(15))
.into(),
)
}
}

0 comments on commit 49a494c

Please sign in to comment.