Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 10 additions & 16 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::config::Config;
use crate::diff_image_loader::DiffImageLoader;
use crate::settings::Settings;
use crate::state::{AppState, AppStateRef, PageRef, SystemCommand, ViewerSystemCommand};
use crate::{DiffSource, bar, home, viewer};
use eframe::egui::{Context, Key, Modifiers};
use crate::{config::Config, state::View};
use eframe::egui::{Context, Modifiers};
use eframe::{Frame, Storage, egui};
use egui_extras::install_image_loaders;
use egui_inbox::UiInbox;
Expand Down Expand Up @@ -172,21 +172,15 @@ impl App {
state.send(ViewerSystemCommand::SelectSnapshot(new_index));
}

let handle_key = |key: Key, toggle: &mut bool| {
if ctx.input_mut(|i| i.key_pressed(key)) {
*toggle = true;
let mut new_view = vs.state.view;
for view in View::ALL {
if ctx.input_mut(|i| i.consume_key(Default::default(), view.key())) {
new_view = view;
}
if ctx.input_mut(|i| i.key_released(key)) {
*toggle = false;
}
};

let mut view_filter = vs.state.view_filter;
handle_key(Key::Num1, &mut view_filter.show_old);
handle_key(Key::Num2, &mut view_filter.show_new);
handle_key(Key::Num3, &mut view_filter.show_diff);
if view_filter != vs.state.view_filter {
state.send(ViewerSystemCommand::SetViewFilter(view_filter));
}

if new_view != vs.state.view {
state.send(ViewerSystemCommand::SetView(new_view));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub enum Commands {
Files { directory: Option<String> },
/// Compare images between current branch and default branch
Git { repo_path: Option<String> },
/// Compare images between PR branches from GitHub PR URL (needs to be run from within the repo)
/// Compare images between PR branches from GitHub PR URL
Pr { url: String },
/// Load and compare snapshot files from a zip archive (URL or local file)
Archive { source: String },
Expand Down
30 changes: 15 additions & 15 deletions src/snapshot.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::diff_image_loader;
use crate::diff_image_loader::DiffOptions;
use crate::state::{AppStateRef, PageRef};
use crate::{diff_image_loader, state::View};
use eframe::egui;
use eframe::egui::{Color32, ImageSource};
use std::path::PathBuf;
Expand Down Expand Up @@ -88,14 +88,14 @@ impl Snapshot {
state: &AppStateRef<'a>,
uri: String,
opacity: f32,
show_all: bool,
blend_all: bool,
) -> eframe::egui::Image<'a> {
let mut image = eframe::egui::Image::new(uri)
.texture_options(eframe::egui::TextureOptions {
magnification: state.settings.texture_magnification,
..eframe::egui::TextureOptions::default()
})
.tint(Color32::from_white_alpha(if show_all {
.tint(Color32::from_white_alpha(if blend_all {
(255.0 * opacity) as u8
} else {
u8::MAX
Expand All @@ -114,37 +114,37 @@ impl Snapshot {
let PageRef::DiffViewer(vs) = &state.page else {
return None;
};
let show_all = vs.view_filter.all();
let show_old = vs.view_filter.show_old;
(show_all || show_old)
let blend_all = vs.view == View::BlendAll;
let show_old = vs.view == View::Old;
(blend_all || show_old)
.then(|| self.old_uri())
.flatten()
.map(|uri| Self::make_image(state, uri, 1.0, show_all))
.map(|uri| Self::make_image(state, uri, 1.0, blend_all))
}

pub fn new_image<'a>(&self, state: &AppStateRef<'a>) -> Option<eframe::egui::Image<'a>> {
let PageRef::DiffViewer(vs) = &state.page else {
return None;
};
let show_all = vs.view_filter.all();
let show_new = vs.view_filter.show_new;
(show_all || show_new)
let blend_all = vs.view == View::BlendAll;
let show_new = vs.view == View::New;
(blend_all || show_new)
.then(|| self.new_uri())
.flatten()
.map(|new_uri| Self::make_image(state, new_uri, state.settings.new_opacity, show_all))
.map(|new_uri| Self::make_image(state, new_uri, state.settings.new_opacity, blend_all))
}

pub fn diff_image<'a>(&self, state: &AppStateRef<'a>) -> Option<eframe::egui::Image<'a>> {
let PageRef::DiffViewer(vs) = &state.page else {
return None;
};
let show_all = vs.view_filter.all();
let show_diff = vs.view_filter.show_diff;
(show_all || show_diff)
let blend_all = vs.view == View::BlendAll;
let show_diff = vs.view == View::Diff;
(blend_all || show_diff)
.then(|| self.diff_uri(state.settings.use_original_diff, state.settings.options))
.flatten()
.map(|diff_uri| {
Self::make_image(state, diff_uri, state.settings.diff_opacity, show_all)
Self::make_image(state, diff_uri, state.settings.diff_opacity, blend_all)
})
}
}
58 changes: 41 additions & 17 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::github::pr::GithubPr;
use crate::loaders::SnapshotLoader;
use crate::settings::Settings;
use crate::snapshot::Snapshot;
use eframe::egui::Context;
use eframe::egui::{self, Context};
use egui_inbox::UiInboxSender;
use octocrab::Octocrab;
use std::ops::Deref;
Expand All @@ -31,7 +31,7 @@ pub struct ViewerState {
/// If true, this item will scroll into view.
pub index_just_selected: bool,
pub filter: String,
pub view_filter: ViewFilter,
pub view: View,
}

impl ViewerState {
Expand All @@ -52,19 +52,43 @@ impl ViewerState {
}
}

/// If any is true, only show those, but at full opacity
///
/// If all are false, show all at their set opacities
#[derive(Default, Copy, Clone, PartialEq, Eq)]
pub struct ViewFilter {
pub show_old: bool,
pub show_new: bool,
pub show_diff: bool,
#[derive(Copy, Clone, Default, PartialEq, Eq)]
pub enum View {
/// View all stacked on each other, with opacity settings.
#[default]
BlendAll,

/// View old image
Old,

/// View new image
New,

/// View diff
Diff,
}

impl ViewFilter {
pub fn all(&self) -> bool {
!self.show_old && !self.show_new && !self.show_diff
impl std::fmt::Display for View {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::BlendAll => write!(f, "Blend all"),
Self::Old => write!(f, "Old"),
Self::New => write!(f, "New"),
Self::Diff => write!(f, "Diff"),
}
}
}

impl View {
pub const ALL: [Self; 4] = [Self::BlendAll, Self::Old, Self::New, Self::Diff];

pub fn key(self) -> egui::Key {
match self {
Self::BlendAll => egui::Key::Num1,
Self::Old => egui::Key::Num2,
Self::New => egui::Key::Num3,
Self::Diff => egui::Key::Num4,
}
}
}

Expand Down Expand Up @@ -198,7 +222,7 @@ pub enum SystemCommand {
pub enum ViewerSystemCommand {
SetFilter(String),
SelectSnapshot(usize),
SetViewFilter(ViewFilter),
SetView(View),
}

impl From<ViewerSystemCommand> for SystemCommand {
Expand All @@ -217,7 +241,7 @@ impl AppState {
index: 0,
index_just_selected: true,
loader,
view_filter: ViewFilter::default(),
view: View::default(),
});
}
SystemCommand::GithubAuth(auth) => {
Expand Down Expand Up @@ -270,8 +294,8 @@ impl ViewerState {
self.index_just_selected = true;
}
}
ViewerSystemCommand::SetViewFilter(view_filter) => {
self.view_filter = view_filter;
ViewerSystemCommand::SetView(view_filter) => {
self.view = view_filter;
}
}
}
Expand Down
41 changes: 25 additions & 16 deletions src/viewer/viewer_options.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
use crate::settings::ImageMode;
use crate::state::{SystemCommand, ViewerAppStateRef, ViewerSystemCommand};
use eframe::egui::{Checkbox, Slider, TextureFilter, Ui};
use crate::{settings::ImageMode, state::View};
use eframe::egui::{self, Slider, TextureFilter, Ui};

pub fn viewer_options(ui: &mut Ui, state: &ViewerAppStateRef<'_>) {
let mut settings = state.app.settings.clone();

ui.group(|ui| {
ui.strong("View only");
let mut view_filter = state.view_filter;
ui.add_enabled(
false,
Checkbox::new(&mut state.view_filter.all(), "All with opacity"),
);
ui.checkbox(&mut view_filter.show_old, "Old (1)");
ui.checkbox(&mut view_filter.show_new, "New (2)");
ui.checkbox(&mut view_filter.show_diff, "Diff (3)");
if view_filter != state.view_filter {
state
.app
.send(ViewerSystemCommand::SetViewFilter(view_filter));
ui.strong("View");
let mut new_view = state.view;

for view in View::ALL {
ui.radio_value(
&mut new_view,
view,
format!("{view} ({})", view.key().name()),
);
}

ui.label("Toggle old/new with SPACE");
ui.input(|i| {
if i.key_pressed(egui::Key::Space) {
new_view = View::New;
} else if i.key_released(egui::Key::Space) {
new_view = View::Old;
}
});

if new_view != state.view {
state.app.send(ViewerSystemCommand::SetView(new_view));
}
});

ui.add_enabled_ui(state.view_filter.all(), |ui| {
ui.add_enabled_ui(state.view == View::BlendAll, |ui| {
ui.add(Slider::new(&mut settings.new_opacity, 0.0..=1.0).text("New Opacity"));
ui.add(Slider::new(&mut settings.diff_opacity, 0.0..=1.0).text("Diff Opacity"));
});
Expand Down
Loading